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))); }
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); }
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()); } }
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); } } } } } }
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))); } }
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); } }
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())); } }