コード例 #1
0
        public override bool CanResolve(Entity owner, string key, bool fallback = false)
        {
            if (!owner.HasValue <IType>() ||
                key == EntityKeys.TemplateKey)
            {
                return(false);
            }

            IType type = owner.Value <IType>();

            metaDataTemplate metaDataTemplate = templateRepository.FieldTemplates
                                                .FirstOrDefault(t => t.name.Plural().Equals(key,
                                                                                            StringComparison
                                                                                            .OrdinalIgnoreCase));

            Templates.Type.metaDataTemplate typeMetaDataTemplate = templateRepository.TypeTemplates
                                                                   .FirstOrDefault(t => t.name.Equals(key, StringComparison.OrdinalIgnoreCase));

            templateRelationship[] relationships = owner.HasTemplate() ? owner.Template().Relationship : null;
            templateRelationship   relationship  =
                relationships?.FirstOrDefault(r => r.name.Equals(key, StringComparison.OrdinalIgnoreCase))
                ?? relationships?.FirstOrDefault(
                    r => r.name.Equals(key.Singular(), StringComparison.OrdinalIgnoreCase));

            return(key is EntityKeys.PathKey or EntityKeys.FieldsKey or EntityKeys.BaseTypeKey or EntityKeys.FileKey ||
                   type.HasPropertyValueEntity(key) ||
                   metaDataTemplate != null ||
                   typeMetaDataTemplate != null ||
                   relationship != null &&
                   type.Attributes.Any(a => a.Name.Equals(relationship.name,
                                                          StringComparison.OrdinalIgnoreCase)));
        }
コード例 #2
0
        private bool TryResolveRelationship(Entity owner, string key, IType type, out Entity result)
        {
            templateRelationship[] relationships = owner.Template().Relationship;
            templateRelationship   relationship  =
                relationships?.FirstOrDefault(r => r.name.Equals(key, StringComparison.OrdinalIgnoreCase))
                ?? relationships?.FirstOrDefault(
                    r => r.name.Equals(key.Singular(), StringComparison.OrdinalIgnoreCase));
            TemplateDescription relationshipDescription =
                relationship != null?templateRepository.Template(relationship.type) : null;

            if (relationshipDescription != null)
            {
                IEnumerable <string> names = type.Attributes
                                             .Where(a => a.Name.Equals(relationship.name,
                                                                       StringComparison.OrdinalIgnoreCase))
                                             .SelectMany(a => a.Values);
                result = relationship.GetRelationship(relationshipDescription, owner, names.ToArray());
                return(true);
            }

            result = null;
            return(false);
        }
コード例 #3
0
        public static Entity GetRelationship(this templateRelationship relationship,
                                             TemplateDescription relationshipDescription, Entity owner,
                                             params string[] relationshipNames)
        {
            if (relationshipDescription.isRoot)
            {
                return(owner.Root);
            }

            ICodeModel codeModel = owner.Root.Value <ICodeModel>();

            IType[] availableTypes = codeModel?.Types.Keys
                                     .Where(t => t.HasAttributeWithoutValue(relationshipDescription.name))
                                     .ToArray() ?? Array.Empty <IType>();
            Entity[] availableEntities = owner.EntityHierarchy()
                                         .Where(e => e.Type.Equals(relationshipDescription.name,
                                                                   StringComparison.OrdinalIgnoreCase))
                                         .Where(e => e.HasValue <IType>() || e.HasValue <CommandDefinition>())
                                         .ToArray();
            if (relationship.multiplicity == multiplicity.One)
            {
                if (relationshipNames.Length != 1)
                {
                    throw new RelationshipMultiplicityMismatchException(relationship.name, owner.Name);
                }
                string name = relationshipNames[0];
                return(CreateRelationshipEntity(name));
            }
            else
            {
                return(owner.Create(relationship.name.Plural(), relationshipNames.Select(CreateRelationshipEntity)));
            }

            Entity CreateRelationshipEntity(string name)
            {
                IType exactType = availableTypes.FirstOrDefault(t => t.FullName.Equals(name, StringComparison.OrdinalIgnoreCase));

                IType[] relationshipTypes = exactType != null
                                                ? new[] { exactType }
                                                : availableTypes.Where(t => t.FullName.Contains(name, StringComparison.OrdinalIgnoreCase))
                .ToArray();
                Entity[] relationshipEntities = availableEntities.Where(e => e.Name?.Equals(name,
                                                                                            StringComparison.OrdinalIgnoreCase)
                                                                        == true)
                                                .ToArray();
                if (relationshipTypes.Length > 1)
                {
                    throw new AmbiguousRelationshipTypeException(relationship.name, name, relationshipTypes);
                }

                if (relationshipTypes.Length == 0 && !relationshipEntities.Any())
                {
                    throw new RelationshipTypeNotFoundException(relationship.name, name, availableTypes);
                }

                IType relationshipType = relationshipTypes.SingleOrDefault();

                if (relationshipType != null)
                {
                    return(availableEntities.FirstOrDefault(e => e.HasValue <IType>() &&
                                                            e.Value <IType>() == relationshipType)
                           ?? owner.Create(relationship.name, relationshipType.Name, relationshipType));
                }

                if (relationshipEntities.Length > 1)
                {
                    throw new AmbiguousRelationshipTypeException(relationship.name, name, relationshipEntities);
                }

                return(relationshipEntities.Single());
            }
        }
コード例 #4
0
        public async Task <IEnumerable <VirtualFile> > InitalizeTemplate(Entity dataModel, ChangeObservable observable)
        {
            bool forced = dataModel.Value <CommandDefinition>()
                          .Argument <BoolArgument>(TemplateCommandBuilder.ForcedArgumentName)
                          .Value;
            TemplateDescription template = dataModel.Template();

            List <VirtualFile> generatedFiles = new List <VirtualFile>(await InitializeFiles().ConfigureAwait(false));

            generatedFiles.AddRange(await InitializeSubTemplates().ConfigureAwait(false));

            Exception e = dataModel.GetCodeExceptions();

            if (e != null)
            {
                e.CompleteCodeExceptions(fileSystem.GetDirectory(dataModel.Root.Path));
                throw e;
            }

            return(generatedFiles);

            async Task <IEnumerable <VirtualFile> > InitializeFiles()
            {
                string basePath             = dataModel.Root.Path;
                HashSet <VirtualFile> files = new HashSet <VirtualFile>();

                foreach (templateFile file in template.File)
                {
                    (string content, Encoding encoding) = await GetResolvedTemplateContent(dataModel, file, template).ConfigureAwait(false);

                    VirtualFile destination = await GetFile(dataModel, file, forced, basePath, template).ConfigureAwait(false);

                    observable.OnNext(new Change(() => destination.Restore(),
                                                 $"Create file {Path.GetFileName(destination.Name)} for template " +
                                                 $"{template.name} in {destination.Parent.FullName}."));

                    using (Stream fileStream = destination.OpenWrite())
                        using (StreamWriter writer = new StreamWriter(fileStream, encoding))
                        {
                            fileStream.SetLength(0);
                            await writer.WriteAsync(content).ConfigureAwait(false);
                        }

                    files.Add(destination);
                }

                return(files);
            }

            async Task <IEnumerable <VirtualFile> > InitializeSubTemplates()
            {
                List <VirtualFile> files = new List <VirtualFile>();

                foreach (templateReference reference in SortByRelationship(template.AddTemplate ?? Enumerable.Empty <templateReference>()))
                {
                    if (repository.Template(reference.template) == null)
                    {
                        throw new TemplateReferenceNotDefinedException(reference.template);
                    }

                    CommandDefinitionBuilder pseudoDefinition = CommandDefinitionBuilder.Create()
                                                                .SetName(reference.template);
                    foreach (templateArgumentInstance argumentInstance in reference.Arguments)
                    {
                        AddArgument(argumentInstance, pseudoDefinition);
                    }

                    IEnumerable <IGrouping <string, templateRelationshipInstance> > grouped = (reference.Relationship ?? Enumerable.Empty <templateRelationshipInstance>()).GroupBy(r => r.name);
                    foreach (IGrouping <string, templateRelationshipInstance> relationshipInstances in grouped)
                    {
                        AddRelationships(relationshipInstances, pseudoDefinition, reference);
                    }

                    pseudoDefinition.CreateArgument()
                    .SetName(TemplateCommandBuilder.ForcedArgumentName)
                    .SetValue(forced)
                    .Build();
                    Entity referencedTemplateEntity = dataModel.Create(reference.template, pseudoDefinition.Build());
                    dataModel.AddEntity(referencedTemplateEntity);
                    files.AddRange(await InitalizeTemplate(referencedTemplateEntity, observable).ConfigureAwait(false));
                }

                return(files);

                void AddArgument(templateArgumentInstance templateArgumentInstance, CommandDefinitionBuilder commandDefinitionBuilder)
                {
                    string templateArgumentValue = resolver.Resolve(templateArgumentInstance.value, dataModel);
                    bool   argumentHasNoValue    = bool.TryParse(templateArgumentValue, out bool boolValue);

                    string[] argumentSplit   = templateArgumentValue.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                    bool     isMultiArgument = argumentSplit.Length > 1;

                    if (argumentHasNoValue)
                    {
                        commandDefinitionBuilder.CreateArgument()
                        .SetName(templateArgumentInstance.name)
                        .SetValue(boolValue)
                        .Build();
                    }
                    else if (isMultiArgument)
                    {
                        commandDefinitionBuilder.CreateArgument()
                        .SetName(templateArgumentInstance.name)
                        .SetValue(argumentSplit)
                        .Build();
                    }
                    else
                    {
                        commandDefinitionBuilder.CreateArgument()
                        .SetName(templateArgumentInstance.name)
                        .SetValue(templateArgumentValue)
                        .Build();
                    }
                }

                void AddRelationships(IGrouping <string, templateRelationshipInstance> relationshipInstances,
                                      CommandDefinitionBuilder commandDefinitionBuilder, templateReference reference)
                {
                    templateRelationship relationshipDefinition = repository.Template(reference.template).Relationship
                                                                  ?.FirstOrDefault(r => r.name ==
                                                                                   relationshipInstances.Key);

                    if (relationshipDefinition == null)
                    {
                        throw new TemplateRelationshipNotFoundException(reference.template, relationshipInstances.Key);
                    }

                    bool multipleValues = relationshipDefinition.multiplicity == multiplicity.OneOrMore;

                    if (multipleValues)
                    {
                        string[] relationships = relationshipInstances.Select(r => resolver.Resolve(r.value, dataModel))
                                                 .ToArray();
                        commandDefinitionBuilder.CreateArgument()
                        .SetName(relationshipInstances.Key)
                        .SetValue(relationships)
                        .Build();
                    }
                    else
                    {
                        if (relationshipInstances.Count() != 1)
                        {
                            throw new RelationshipMultiplicityMismatchException(relationshipInstances.Key, reference.template);
                        }
                        commandDefinitionBuilder.CreateArgument()
                        .SetName(relationshipInstances.Key)
                        .SetValue(resolver.Resolve(relationshipInstances.Single().value, dataModel))
                        .Build();
                    }
                }

                IEnumerable <templateReference> SortByRelationship(IEnumerable <templateReference> references)
                {
                    List <templateReference> unsorted = references.ToList();
                    List <templateReference> sorted   = new List <templateReference>();

                    while (unsorted.Any())
                    {
                        Insert(unsorted[0]);
                    }

                    return(sorted);

                    void Insert(templateReference current, CycleChecker <templateReference> cycleChecker = null)
                    {
                        using (cycleChecker = cycleChecker?.SpawnChild() ?? new CycleChecker <templateReference>(
                                   ExceptionTexts.TemplateRelationshipCycle,
                                   () => cycleChecker = null))
                        {
                            cycleChecker.AddItem(current);
                            List <templateReference> dependent = new List <templateReference>();
                            foreach (templateRelationshipInstance relationshipInstance in current.Relationship ??
                                     Enumerable
                                     .Empty <
                                         templateRelationshipInstance
                                         >())
                            {
                                templateReference reference =
                                    unsorted.FirstOrDefault(r => HasRelationship(r, relationshipInstance));
                                if (reference != null)
                                {
                                    Insert(reference, cycleChecker);
                                }
                                else
                                {
                                    reference = sorted.FirstOrDefault(r => HasRelationship(r, relationshipInstance));
                                }

                                if (reference != null)
                                {
                                    dependent.Add(reference);
                                }
                            }

                            int skipping = dependent.Any() ? dependent.Select(d => sorted.IndexOf(d)).Max() : -1;
                            int index    = skipping + 1;
                            sorted.Insert(index, current);
                            unsorted.Remove(current);

                            bool HasRelationship(templateReference currentReference,
                                                 templateRelationshipInstance relationshipInstance)
                            {
                                templateArgumentInstance instance = currentReference.Arguments
                                                                    .FirstOrDefault(a => a.name
                                                                                    .Equals(
                                                                                        EntityKeys
                                                                                        .NameKey,
                                                                                        StringComparison
                                                                                        .OrdinalIgnoreCase));

                                return(instance?.value?.Equals(relationshipInstance.value,
                                                               StringComparison.OrdinalIgnoreCase) == true);
                            }
                        }
                    }
                }
            }
        }
コード例 #5
0
        public override bool CanResolve(Entity owner, string key, bool fallback = false)
        {
            return(owner.HasValue <ICodeModel>() &&
                   (key == EntityKeys.NamespaceKey ||
                    key == EntityKeys.PortStructsKey ||
                    key == EntityKeys.PortEnumsKey) ||
                   owner.HasValue <IType>() && CanResolveType() ||
                   owner.HasValue <IField>() && CanResolveField() ||
                   owner.HasValue <IDataType>() && CanResolveDataType() ||
                   owner.HasValue <ISymbol>() && CanResolveSymbol() ||
                   key == EntityKeys.FieldArpDataTypeKey && owner.Type == EntityKeys.FormatKey ||
                   key == EntityKeys.TypeMetaDataFormatKey && owner.Type == EntityKeys.FormatKey ||
                   key == EntityKeys.ExpandHiddenTypesFormatKey && owner.All(e => e.HasValue <IField>()) ||
                   key == EntityKeys.FilterHiddenTypesFormatKey && owner.All(e => e.HasValue <IType>()) ||
                   key == EntityKeys.IsFieldKey ||
                   key == EntityKeys.IsTypeKey ||
                   key == EntityKeys.BaseDirectoryKey && HasBaseDirectory(owner, out _) ||
                   key == EntityKeys.BigDataProjectKey ||
                   key == EntityKeys.NormalProjectKey);

            bool CanResolveSymbol()
            {
                return(owner.Value <ISymbol>().HasPropertyValueEntity(key));
            }

            bool CanResolveDataType()
            {
                return(key == EntityKeys.NameKey ||
                       key == EntityKeys.FullNameKey);
            }

            bool CanResolveField()
            {
                metaDataTemplate metaDataTemplate = templateRepository.FieldTemplates
                                                    .FirstOrDefault(t => t.name.Equals(key,
                                                                                       StringComparison.OrdinalIgnoreCase));

                return(key == EntityKeys.FieldNameKey ||
                       key == EntityKeys.DataTypeKey ||
                       key == EntityKeys.MultiplicityKey ||
                       key == EntityKeys.ResolvedTypeKey ||
                       metaDataTemplate != null);
            }

            bool CanResolveType()
            {
                if (key == EntityKeys.TemplateKey)
                {
                    return(false);
                }
                IType type = owner.Value <IType>();

                metaDataTemplate metaDataTemplate = templateRepository.FieldTemplates
                                                    .FirstOrDefault(t => t.name.Plural().Equals(key,
                                                                                                StringComparison
                                                                                                .OrdinalIgnoreCase));

                Templates.Type.metaDataTemplate typeMetaDataTemplate = templateRepository.TypeTemplates
                                                                       .FirstOrDefault(t => t.name.Equals(key, StringComparison.OrdinalIgnoreCase));

                templateRelationship[] relationships = owner.HasTemplate() ? owner.Template().Relationship : null;
                templateRelationship   relationship  = relationships?.FirstOrDefault(r => r.name.Equals(key, StringComparison.OrdinalIgnoreCase))
                                                       ?? relationships?.FirstOrDefault(r => r.name.Equals(key.Singular(), StringComparison.OrdinalIgnoreCase));

                return(key == EntityKeys.PathKey ||
                       key == EntityKeys.FieldsKey ||
                       key == EntityKeys.BaseTypeKey ||
                       key == EntityKeys.FileKey ||
                       type.HasPropertyValueEntity(key) ||
                       metaDataTemplate != null ||
                       typeMetaDataTemplate != null ||
                       relationship != null && type.Attributes.Any(a => a.Name.Equals(relationship.name,
                                                                                      StringComparison.OrdinalIgnoreCase)));
            }
        }
コード例 #6
0
        public override Entity Resolve(Entity owner, string key, bool fallback = false)
        {
            TemplateEntity ownerTemplateEntity = TemplateEntity.Decorate(owner);

            if (key == EntityKeys.FieldArpDataTypeKey && owner.Type == EntityKeys.FormatKey)
            {
                return(ResolveArpDataType());
            }
            if (key == EntityKeys.TypeMetaDataFormatKey && owner.Type == EntityKeys.FormatKey)
            {
                return(ResolveTypeMetaDataFormat());
            }
            if (key == EntityKeys.ExpandHiddenTypesFormatKey)
            {
                return(ExpandHiddenTypes());
            }
            if (key == EntityKeys.FilterHiddenTypesFormatKey)
            {
                return(FilterHiddenTypes());
            }
            if (key == EntityKeys.IsFieldKey)
            {
                return(owner.Create(key, CodeEntity.Decorate(owner).AsField != null));
            }
            if (key == EntityKeys.IsTypeKey)
            {
                return(owner.Create(key, CodeEntity.Decorate(owner).AsType != null));
            }
            if (key == EntityKeys.BigDataProjectKey)
            {
                return(GetBigDataProjectEntity());
            }
            if (key == EntityKeys.NormalProjectKey)
            {
                return(GetNormalProjectEntity());
            }


            ISymbol symbol = owner.Value <ISymbol>();

            if (symbol != null)
            {
                Entity result = owner.PropertyValueEntity(key, symbol);
                if (result != null)
                {
                    return(result);
                }

                throw new ContentProviderException(key, owner);
            }

            if (key == EntityKeys.BaseDirectoryKey && HasBaseDirectory(owner, out string baseDirectory))
            {
                return(owner.Create(key, baseDirectory));
            }

            IType type = owner.Value <IType>();

            if (type != null)
            {
                return(ResolveType());
            }

            IField field = owner.Value <IField>();

            if (field != null)
            {
                return(ResolveField());
            }

            IDataType dataType = owner.Value <IDataType>();

            if (dataType != null)
            {
                return(ResolveDataType());
            }

            ICodeModel codeModel = owner.Value <ICodeModel>();

            if (codeModel != null)
            {
                return(ResolveCodeModel());
            }
            throw new ContentProviderException(key, owner);

            IEnumerable <CodeEntity> GetPortEnums()
            {
                return(GetAllPorts().Concat(GetPortStructures().SelectMany(p => p.Fields))
                       .Select(f => f.ResolvedType)
                       .Where(t => t.AsEnum != null)
                       .Distinct());
            }

            IEnumerable <CodeEntity> GetAllPorts()
            {
                bool IsPort(CodeEntity fieldEntity)
                {
                    return(fieldEntity.AsField != null &&
                           fieldEntity.AsField.HasAttributeWithoutValue(EntityKeys.PortAttributeKey));
                }

                return(TemplateEntity.Decorate(owner).EntityHierarchy
                       .Select(CodeEntity.Decorate)
                       .SelectMany(c => c.Fields)
                       .Where(IsPort));
            }

            IEnumerable <CodeEntity> GetPortStructures()
            {
                HashSet <CodeEntity> structures = new HashSet <CodeEntity>(GetAllPorts()
                                                                           .Select(f => f.ResolvedType)
                                                                           .Where(t => t.AsType != null &&
                                                                                  t.AsEnum == null),
                                                                           new FullNameCodeEntityComparer());

                HashSet <CodeEntity> visited = new HashSet <CodeEntity>(new FullNameCodeEntityComparer());

                while (structures.Except(visited).Any())
                {
                    foreach (CodeEntity structure in structures.Except(visited).ToArray())
                    {
                        foreach (CodeEntity structureField in structure.Fields)
                        {
                            CodeEntity structureDataType = structureField.ResolvedType;
                            if (structureDataType.AsType != null && structureDataType.AsEnum == null)
                            {
                                structures.Add(structureDataType);
                            }
                        }

                        visited.Add(structure);
                    }
                }

                return(structures);
            }

            Entity FilterHiddenTypes()
            {
                IEnumerable <IType> types = owner.Select(CodeEntity.Decorate)
                                            .Where(c => !c.IsHidden())
                                            .Select(c => c.AsType)
                                            .ToArray();
                string name = owner.FirstOrDefault()?.Name ?? string.Empty;

                return(owner.Create(key, types.Select(t => owner.Create(name, t.FullName, t))));
            }

            Entity ExpandHiddenTypes()
            {
                IEnumerable <CodeEntity> dataSourceFields = owner.Select(CodeEntity.Decorate);

                dataSourceFields = ExpandHiddenStructureFields(dataSourceFields);
                string name = owner.FirstOrDefault()?.Name ?? string.Empty;

                return(owner.Create(key, dataSourceFields.Select(e => e.AsField)
                                    .Select(f => owner.Create(name, f.Name, f))));

                IEnumerable <CodeEntity> ExpandHiddenStructureFields(IEnumerable <CodeEntity> fields)
                {
                    foreach (CodeEntity hiddenField in fields)
                    {
                        CodeEntity hiddenType = hiddenField.ResolvedType;
                        if (hiddenType == null || !hiddenType.IsHidden())
                        {
                            yield return(hiddenField);

                            continue;
                        }

                        foreach (CodeEntity hiddenTypeField in ExpandHiddenStructureFields(hiddenType.Fields))
                        {
                            yield return(hiddenTypeField);
                        }
                    }
                }
            }

            T ChooseMetaDataTemplate <T>(IEnumerable <(T template, string name, string context)> templates)
            {
                return(templates.OrderByDescending(t => ContextComplexity(t.context ?? string.Empty))
                       .FirstOrDefault(Matches)
                       .template);

                bool Matches((T template, string name, string context) template)
                {
                    if (!key.Equals(template.name, StringComparison.OrdinalIgnoreCase))
                    {
                        return(false);
                    }

                    if (string.IsNullOrEmpty(template.context))
                    {
                        return(true);
                    }
                    string[] contextPath = template.context.Split(new [] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries)
                                           .Reverse().ToArray();
                    Entity current = owner;

                    foreach (string part in contextPath)
                    {
                        current = current?.Owner;
                        if (current?[$"is{part}"].Value <bool>() != true)
                        {
                            return(false);
                        }
                    }

                    return(true);
                }

                int ContextComplexity(string context)
                {
                    return(context.Count(c => c == '/' || c == '\\'));
                }
            }

            Entity ResolveType()
            {
                switch (key)
                {
                case EntityKeys.PathKey:
                {
                    return(owner.Create(key, type.GetFile(owner).Parent.FullName));
                }

                case EntityKeys.FieldsKey:
                {
                    return(owner.Create(key, type.Fields.Select(f => owner.Create(key.Singular(), f.Name, f))));
                }

                case EntityKeys.FileKey:
                {
                    VirtualFile file = owner.Root.Value <ICodeModel>()
                                       .Types[type];
                    return(owner.Create(key, file.Name, file));
                }

                case EntityKeys.BaseTypeKey:
                {
                    IDataType baseType = type.BaseTypes.FirstOrDefault();
                    return(owner.Create(key, baseType));
                }

                default:
                {
                    if (TryResolveTypeTemplate(out Entity result))
                    {
                        return(result);
                    }

                    if (TryResolveProperty(out result))
                    {
                        return(result);
                    }

                    if (TryResolveFields(out result))
                    {
                        return(result);
                    }

                    if (TryResolveRelationship(out result))
                    {
                        return(result);
                    }

                    throw new ContentProviderException(key, owner);
                }
                }

                bool TryResolveTypeTemplate(out Entity result)
                {
                    Templates.Type.metaDataTemplate typeMetaDataTemplate = ChooseMetaDataTemplate(templateRepository.TypeTemplates
                                                                                                  .Select(t => (t, t.name, t.context)));
                    if (typeMetaDataTemplate != null)
                    {
                        result = GetTypeTemplateEntity(typeMetaDataTemplate);
                        return(true);
                    }

                    result = null;
                    return(false);

                    Entity GetTypeTemplateEntity(Templates.Type.metaDataTemplate metaDataTemplate)
                    {
                        if (!metaDataTemplate.hasvalue)
                        {
                            bool hasAttribute = type.HasAttributeWithoutValue(metaDataTemplate.name);
                            return(owner.Create(key, new Func <string>(hasAttribute.ToString), hasAttribute));
                        }
                        (string[] values, CodePosition position) = GetTypeTemplateValue();
                        IEnumerable <string> formattedValues = VerifyValues().ToArray();

                        return(metaDataTemplate.multiplicity == Templates.Type.multiplicity.OneOrMore
                                   ? owner.Create(key, formattedValues.Select(v => owner.Create(key.Singular(), v)))
                                   : owner.Create(key, formattedValues.First()));

                        IEnumerable <string> VerifyValues()
                        {
                            return(values.Select(VerifyValue));

                            string VerifyValue(string arg)
                            {
                                (bool success, string message, string newValue) = metaDataTemplate.ValueRestriction.Verify(arg);
                                if (!success)
                                {
                                    owner.AddCodeException(new FieldAttributeRestrictionException(metaDataTemplate.name, arg, message, position, type.GetFile(owner)));
                                }

                                return(newValue);
                            }
                        }

                        (string[], CodePosition) GetTypeTemplateValue()
                        {
                            IAttribute attribute = type.Attributes.LastOrDefault(a => a.Name.Equals(metaDataTemplate.name,
                                                                                                    StringComparison.OrdinalIgnoreCase));
                            string value = attribute?.Values.FirstOrDefault() ??
                                           resolver.Resolve(metaDataTemplate.defaultvalue, owner);

                            return(metaDataTemplate.multiplicity == Templates.Type.multiplicity.OneOrMore
                                        ? value.Split(new[] { metaDataTemplate.split }, StringSplitOptions.RemoveEmptyEntries)
                                        : new[] { value },
                                   attribute?.Position ?? new CodePosition(0, 0));
                        }
                    }
                }

                bool TryResolveProperty(out Entity result)
                {
                    result = owner.PropertyValueEntity(key, type);
                    return(result != null);
                }

                bool TryResolveFields(out Entity result)
                {
                    metaDataTemplate metaDataTemplate = templateRepository.FieldTemplates
                                                        .FirstOrDefault(t => t.name.Plural().Equals(key,
                                                                                                    StringComparison
                                                                                                    .OrdinalIgnoreCase));

                    if (metaDataTemplate != null)
                    {
                        IEnumerable <IField> fields = type.Fields
                                                      .Where(f => f.Attributes
                                                             .Any(a => a.Name
                                                                  .Equals(metaDataTemplate.name,
                                                                          StringComparison.OrdinalIgnoreCase)));
                        result = owner.Create(key, fields.Select(f => owner.Create(metaDataTemplate.name, f.Name, f)));
                        return(true);
                    }

                    result = null;
                    return(false);
                }

                bool TryResolveRelationship(out Entity result)
                {
                    templateRelationship[] relationships = owner.Template().Relationship;
                    templateRelationship   relationship  = relationships?.FirstOrDefault(r => r.name.Equals(key, StringComparison.OrdinalIgnoreCase))
                                                           ?? relationships?.FirstOrDefault(r => r.name.Equals(key.Singular(), StringComparison.OrdinalIgnoreCase));
                    TemplateDescription relationshipDescription = relationship != null?templateRepository.Template(relationship.type) : null;

                    if (relationshipDescription != null)
                    {
                        IEnumerable <string> names = type.Attributes
                                                     .Where(a => a.Name.Equals(relationship.name,
                                                                               StringComparison.OrdinalIgnoreCase))
                                                     .SelectMany(a => a.Values);
                        result = relationship.GetRelationship(relationshipDescription, owner, names.ToArray());
                        return(true);
                    }

                    result = null;
                    return(false);
                }
            }

            Entity ResolveField()
            {
                switch (key)
                {
                case EntityKeys.FieldNameKey:
                {
                    return(owner.Create(key, field.Name));
                }

                case EntityKeys.DataTypeKey:
                {
                    IDataType fieldDataType = GetRealFieldDataType();
                    return(owner.Create(key, fieldDataType.Name, fieldDataType));
                }

                case EntityKeys.ResolvedTypeKey:
                {
                    ICodeModel model         = owner.Root.Value <ICodeModel>();
                    IDataType  fieldDataType = field.DataType;
                    IType      realType      = fieldDataType.PotentialFullNames
                                               .Select(model.Type)
                                               .FirstOrDefault(t => t != null);
                    return(owner.Create(key, realType?.Name, realType));
                }

                case EntityKeys.MultiplicityKey:
                {
                    return(owner.Create(key, field.Multiplicity.Select(m => owner.Create(key, new Func <string>(m.ToString), m))));
                }

                default:
                {
                    metaDataTemplate metaDataTemplate = templateRepository.FieldTemplates
                                                        .FirstOrDefault(t => t.name.Equals(key,
                                                                                           StringComparison.OrdinalIgnoreCase));
                    if (metaDataTemplate != null)
                    {
                        return(GetFieldTemplateEntity(metaDataTemplate));
                    }
                    throw new ContentProviderException(key, owner);
                }
                }

                IDataType GetRealFieldDataType()
                {
                    ICodeModel rootCodeModel = owner.Root.Value <ICodeModel>();
                    IEnum      @enum         = field.DataType.PotentialFullNames.Select(n => rootCodeModel.GetEnum(n)).FirstOrDefault(e => e != null);

                    if (@enum != null)
                    {
                        (IDataType enumBaseType, _) = GetEnumBaseType(@enum);
                        return(enumBaseType);
                    }

                    return(field.DataType);
                }

                Entity GetFieldTemplateEntity(metaDataTemplate metaDataTemplate)
                {
                    if (!metaDataTemplate.hasvalue)
                    {
                        bool hasAttribute = field.HasAttributeWithoutValue(metaDataTemplate.name);
                        return(owner.Create(key, new Func <string>(hasAttribute.ToString), hasAttribute));
                    }
                    (string[] values, CodePosition position) = GetFieldTemplateValue();
                    IEnumerable <string> formattedValues = VerifyValues().ToArray();

                    return(metaDataTemplate.multiplicity == multiplicity.OneOrMore
                               ? owner.Create(key, formattedValues.Select(v => owner.Create(key.Singular(), v)))
                               : owner.Create(key, formattedValues.First()));

                    IEnumerable <string> VerifyValues()
                    {
                        return(values.Select(VerifyValue));

                        string VerifyValue(string arg)
                        {
                            (bool success, string message, string newValue) = metaDataTemplate.ValueRestriction.Verify(arg);
                            if (!success)
                            {
                                owner.AddCodeException(new FieldAttributeRestrictionException(metaDataTemplate.name, arg, message, position, field.GetFile(owner)));
                            }

                            return(newValue);
                        }
                    }

                    (string[], CodePosition) GetFieldTemplateValue()
                    {
                        IAttribute attribute = field.Attributes.LastOrDefault(a => a.Name.Equals(metaDataTemplate.name,
                                                                                                 StringComparison.OrdinalIgnoreCase));
                        string value = string.IsNullOrEmpty(attribute?.Values.FirstOrDefault())
                                           ? resolver.Resolve(metaDataTemplate.defaultvalue, owner)
                                           : attribute.Values.First();

                        return(metaDataTemplate.multiplicity == multiplicity.OneOrMore
                                    ? value.Split(new[] { metaDataTemplate.split }, StringSplitOptions.RemoveEmptyEntries)
                                    : new[] { value },
                               attribute?.Position ?? new CodePosition(0, 0));
                    }
                }
            }

            Entity ResolveCodeModel()
            {
                switch (key)
                {
                case EntityKeys.PortStructsKey:
                {
                    return(owner.Create(key, GetPortStructures().Select(c => c.Base)));
                }

                case EntityKeys.PortEnumsKey:
                {
                    return(owner.Create(key, GetPortEnums().Select(c => c.Base)));
                }

                case EntityKeys.NamespaceKey:
                {
                    bool prior206Target = CheckProjectTargets();
                    IEnumerable <string> relevantTypes = TemplateEntity.Decorate(owner).EntityHierarchy
                                                         .Select(CodeEntity.Decorate)
                                                         .Where(c => !c.IsRoot())
                                                         .Select(c => c.FullName);
                    string ns = prior206Target
                                        ? codeModel.RootNamespaceForOldTarget(
                        relevantTypes.ToArray(), GetPortStructures().Concat(GetPortEnums())
                        .Select(c => c.FullName)
                        .ToArray())
                                        : codeModel.RootNamespace(relevantTypes.ToArray());
                    if (string.IsNullOrEmpty(ns))
                    {
                        ns = owner.Name;
                    }

                    return(owner.Create(key, ns));
                }

                default:
                    throw new ContentProviderException(key, owner);
                }

                bool CheckProjectTargets()
                {
                    IEnumerable <TargetEntity> targets = ProjectEntity.Decorate(owner).Targets.Select(t => TargetEntity.Decorate(t));

                    return(targets.Any(t => t.Version < new Version(20, 6)));
                }
            }

            Entity ResolveDataType()
            {
                switch (key)
                {
                case EntityKeys.NameKey:
                    return(owner.Create(key, dataType.Name));

                case EntityKeys.FullNameKey:
                    string fullName = GetDataTypeFullName();
                    return(owner.Create(key, fullName));

                default:
                    throw new ContentProviderException(key, owner);
                }

                string GetDataTypeFullName()
                {
                    ICodeModel rootCodeModel = owner.Root.Value <ICodeModel>();

                    return(dataType.PotentialFullNames.FirstOrDefault(fn => rootCodeModel.Type(fn) != null)
                           ?? dataType.Name);
                }
            }

            Entity ResolveTypeMetaDataFormat()
            {
                IEntityBase dataSource         = ownerTemplateEntity.FormatOrigin;
                IDataType   dataSourceDataType = dataSource.HasValue <IDataType>()
                                                   ? dataSource.Value <IDataType>()
                                                   : dataSource.Value <IField>().DataType;

                ICodeModel rootCodeModel = dataSource.Root.Value <ICodeModel>();
                string     dataTypeName  = string.Empty;

                if (dataSourceDataType != null)
                {
                    dataTypeName = dataSourceDataType.PotentialFullNames
                                   .Select(n => rootCodeModel.Type(n))
                                   .FirstOrDefault(t => t != null)
                                   ?.Name
                                   ?? datatypeConversion.Convert(dataSourceDataType);
                }

                return(owner.Create(key, dataTypeName));
            }

            Entity ResolveArpDataType()
            {
                IEntityBase dataSource      = ownerTemplateEntity.FormatOrigin;
                IField      dataSourceField = dataSource.Value <IField>();

                if (dataSourceField == null)
                {
                    throw new FormatTargetMismatchException("arpDataType", "field|port", dataSource.Type);
                }

                ICodeModel rootCodeModel = dataSource.Root.Value <ICodeModel>();
                bool       isStruct      = dataSourceField.DataType.PotentialFullNames.Any(n => rootCodeModel.GetClass(n) != null || rootCodeModel.GetStructure(n) != null);
                IEnum      @enum         = dataSourceField.DataType.PotentialFullNames.Select(n => rootCodeModel.GetEnum(n)).FirstOrDefault(e => e != null);
                bool       isArray       = dataSourceField.Multiplicity.Any();
                string     arpName       = "DataType::" + GetArpDataType(dataSourceField.DataType.Name);

                return(owner.Create(key, arpName));

                string GetArpDataType(string dataTypeName)
                {
                    string postfix = isArray ? " | DataType::Array" : string.Empty;

                    if (isStruct)
                    {
                        return("Struct" + postfix);
                    }

                    if (@enum != null)
                    {
                        (IDataType enumBaseType, string formattedBaseType) = GetEnumBaseType(@enum);

                        return($"Enum | DataType::{formattedBaseType}" + postfix);
                    }

                    (bool success, string value) = FormatDataType(dataTypeName);

                    if (!success)
                    {
                        throw new UnknownDataTypeException(value);
                    }

                    return(value + postfix);
                }
            }

            (bool success, string value) FormatDataType(string unformattedValue)
            {
                if (unformattedValue.Contains('<'))
                {
                    unformattedValue = unformattedValue.Substring(0, unformattedValue.IndexOf('<'));
                }

                string result      = owner.Create("temporaryCtnFormatContainer", unformattedValue).Format()["knownDataTypes"].Value <string>();
                Match  unkownMatch = UnkownDataTypeRegex.Match(result);

                if (unkownMatch.Success)
                {
                    return(false, unkownMatch.Groups["dataType"].Value);
                }

                return(true, result);
            }

            (IDataType, string) GetEnumBaseType(IEnum @enum)
            {
                IDataType enumDataType = @enum.BaseTypes.FirstOrDefault();
                string    enumBaseType = enumDataType?.Name;

                if (string.IsNullOrEmpty(enumBaseType))
                {
                    throw new MissingEnumDataTypeException(@enum);
                }

                (bool formatted, string formattedBaseType) = FormatDataType(enumBaseType);
                if (!formatted)
                {
                    throw new UnkownEnumDataTypeException(formattedBaseType, @enum);
                }

                return(enumDataType, formattedBaseType);
            }

            Entity GetBigDataProjectEntity()
            {
                if (HasMoreThan1000Fields())
                {
                    return(owner.Create(key, "true", true));
                }
                return(owner.Create(key, "false", false));
            }

            Entity GetNormalProjectEntity()
            {
                if (HasMoreThan1000Fields())
                {
                    return(owner.Create(key, "false", false));
                }
                return(owner.Create(key, "true", true));
            }

            bool HasMoreThan1000Fields()
            {
                ICodeModel model = owner.Value <ICodeModel>();

                if (model == null ||
                    GetAllPorts().Concat(GetPortStructures().SelectMany(s => s.Fields)).Count() <= 1000)
                {
                    return(false);
                }
                return(true);
            }
        }
コード例 #7
0
        public override Entity Resolve(Entity owner, string key, bool fallback = false)
        {
            templateRelationship[] relationships = owner.HasTemplate() ? owner.Template().Relationship : null;
            templateRelationship   relationship  = relationships?.FirstOrDefault(r => r.name.Equals(key, StringComparison.OrdinalIgnoreCase))
                                                   ?? relationships?.FirstOrDefault(r => r.name.Equals(key.Singular(), StringComparison.OrdinalIgnoreCase));
            TemplateDescription relationshipDescription = relationship != null?templateRepository.Template(relationship.type) : null;

            if (relationshipDescription != null)
            {
                return(GetRelationship());
            }
            if (key == EntityKeys.PathKey)
            {
                return(GetCommandPath());
            }
            if (key == EntityKeys.FullNameKey)
            {
                return(GetFullName());
            }

            return(GetArgument());

            Entity GetFullName()
            {
                SingleValueArgument nameArgument = owner.Value <CommandDefinition>()
                                                   .Argument <SingleValueArgument>(EntityKeys.NameKey);
                SingleValueArgument namespaceArgument = owner.Value <CommandDefinition>()
                                                        .Argument <SingleValueArgument>(EntityKeys.NamespaceKey);
                string fullName = codeLanguage.CombineNamespace(Value(namespaceArgument, EntityKeys.NamespaceKey),
                                                                Value(nameArgument, EntityKeys.NameKey));

                return(owner.Create(key, fullName, nameArgument, namespaceArgument));
            }

            Entity GetCommandPath()
            {
                SingleValueArgument singleValueArgument = owner.Value <CommandDefinition>()
                                                          .Argument <SingleValueArgument>(EntityKeys.OutputKey);
                string basePath = owner.IsRoot() ? string.Empty : owner.Root.Path;
                string path     = fileSystem.GetDirectory(Value(singleValueArgument), basePath, false).FullName;

                return(owner.Create(key, path, singleValueArgument));
            }

            string Value(Argument arg, string argumentName = null)
            {
                if (string.IsNullOrEmpty(argumentName))
                {
                    argumentName = key;
                }
                if (arg != null && arg is BoolArgument boolArgument)
                {
                    return(boolArgument.Value.ToString(CultureInfo.InvariantCulture));
                }

                SingleValueArgument singleValueArgument = (SingleValueArgument)arg;

                if (singleValueArgument?.Value != null)
                {
                    return(ResolveValue(singleValueArgument.Value));
                }

                if ((arg != null && arg.Name != argumentName && TryGetTemplateDefault(arg.Name, out string result)) ||
                    TryGetTemplateDefault(argumentName, out result))
                {
                    return(result);
                }

                return(string.Empty);
            }

            string ResolveValue(string value)
            {
                string result = templateResolver.Resolve(value, owner);

                if (TryGetTemplateFormat(out string format) &&
                    !string.IsNullOrEmpty(format))
                {
                    Entity temporary = owner.Create(key, result);
                    result = temporary.Format()[format].Value <string>();
                }
                return(result);

                bool TryGetTemplateFormat(out string formattedValue)
                {
                    TemplateDescription description = owner.HasTemplate() ? owner.Template() : null;

                    if (description != null)
                    {
                        templateArgumentDefinition templateArgument = description.Arguments.FirstOrDefault(a => a.name == key);
                        if (templateArgument != null)
                        {
                            formattedValue = templateArgument.format;
                            return(true);
                        }
                    }

                    formattedValue = null;
                    return(false);
                }
            }

            bool TryGetTemplateDefault(string argumentName, out string value)
            {
                TemplateDescription description = owner.HasTemplate() ? owner.Template() : null;

                if (description != null)
                {
                    templateArgumentDefinition templateArgument = description.Arguments.FirstOrDefault(a => a.name == argumentName);
                    if (templateArgument != null)
                    {
                        value = ResolveValue(templateArgument.@default);
                        return(true);
                    }
                }

                value = null;
                return(false);
            }

            Entity GetArgument()
            {
                Argument argument = owner.Value <CommandDefinition>().Argument <Argument>(key);

                if (argument == null)
                {
                    if (TryGetTemplateDefault(key, out string value))
                    {
                        return(owner.Create(key, value));
                    }
                    throw new ContentProviderException(key, owner);
                }

                switch (argument)
                {
                case BoolArgument boolArgument:
                    return(owner.Create(key, Value(argument), boolArgument));

                case SingleValueArgument singleValueArgument:
                    return(owner.Create(key, Value(argument), singleValueArgument));

                case MultipleValueArgument multipleValueArgument:
                    IEnumerable <Entity> values = Values(multipleValueArgument);
                    return(owner.Create(key, values));

                default:
                    throw new InvalidOperationException($"Unkown argument type {argument.GetType()}");
                }

                IEnumerable <Entity> Values(MultipleValueArgument multipleValueArgument)
                {
                    if (multipleValueArgument.Values != null)
                    {
                        return(multipleValueArgument.Values
                               .Select(s => owner.Create(key,
                                                         ResolveValue(s),
                                                         multipleValueArgument)));
                    }

                    if (TryGetTemplateDefault(key, out string result))
                    {
                        return(new[] { owner.Create(key, result, multipleValueArgument) });
                    }

                    throw new ContentProviderException(key, owner);
                }
            }

            Entity GetRelationship()
            {
                if (relationshipDescription.isRoot)
                {
                    return(owner.Root);
                }

                if (relationship.multiplicity == multiplicity.One)
                {
                    string name = owner.Value <CommandDefinition>()
                                  .Argument <SingleValueArgument>(relationship.name)
                                  .Value;
                    return(relationship.GetRelationship(relationshipDescription, owner, name));
                }

                IEnumerable <string> names = owner.Value <CommandDefinition>()
                                             .Argument <MultipleValueArgument>(relationship.name)
                                             .Values;

                return(relationship.GetRelationship(relationshipDescription, owner, names.ToArray()));
            }
        }