/// <summary> Process this. </summary> /// /// <remarks> Ken, 10/5/2020. </remarks> /// /// <param name="entityObject"> The entity object. </param> /// <param name="entityPropertyItem"> The entity property item. </param> /// <param name="annotationType"></param> /// <param name="typeBuilder"> The type builder. </param> /// <param name="appHierarchyNodeObject"> The application hierarchy node object. </param> /// <param name="generatorConfiguration"> The generator configuration. </param> /// /// <returns> True if it succeeds, false if it fails. </returns> public bool Process(EntityObject entityObject, EntityPropertyItem entityPropertyItem, Type annotationType, TypeBuilder typeBuilder, AppUIHierarchyNodeObject appHierarchyNodeObject, IGeneratorConfiguration generatorConfiguration) { if (entityPropertyItem.PropertyName == "UIGroup") { foreach (var childProperty in entityPropertyItem.ChildProperties) { var annotationAtrributeType = generatorConfiguration.FindDataAnnotationType(childProperty.PropertyName + "Attribute"); var handler = generatorConfiguration.GetDataAnnotationTypeHandler(childProperty.PropertyName, annotationAtrributeType); if (handler != null) { if (!handler.Process(entityObject, childProperty, annotationAtrributeType, typeBuilder, appHierarchyNodeObject, generatorConfiguration)) { throw new Exception($"Cannot process annotation type '{ annotationAtrributeType.AsDisplayText() }' and property '{ childProperty.PropertyName }"); } } else { throw new HandlerNotFoundException($"Cannot find annotation type handler for annotation type '{ annotationAtrributeType.AsDisplayText() }' and property '{ childProperty.PropertyName }"); } } return(true); } else if (annotationType != null) { return(Process(entityObject, null, entityPropertyItem, appHierarchyNodeObject, annotationType, (c) => typeBuilder.SetCustomAttribute(c))); } else { throw new Exception($"Cannot find Attribute type or custom handler to process property '{ entityPropertyItem.PropertyName }"); } }
/// <summary> Process this. </summary> /// /// <remarks> Ken, 10/5/2020. </remarks> /// /// <param name="entityObject"> The entity object. </param> /// <param name="attributeObject"> The attribute object. </param> /// <param name="entityPropertyItem"> The entity property item. </param> /// <param name="annotationType"></param> /// <param name="propertyBuilder"> The property builder. </param> /// <param name="appHierarchyNodeObject"> The application hierarchy node object. </param> /// <param name="generatorConfiguration"> The generator configuration. </param> /// /// <returns> True if it succeeds, false if it fails. </returns> public bool Process(EntityObject entityObject, AttributeObject attributeObject, EntityPropertyItem entityPropertyItem, Type annotationType, PropertyBuilder propertyBuilder, AppUIHierarchyNodeObject appHierarchyNodeObject, IGeneratorConfiguration generatorConfiguration) { if (annotationType != null) { return(Process(entityObject, attributeObject, entityPropertyItem, appHierarchyNodeObject, annotationType, (c) => propertyBuilder.SetCustomAttribute(c))); } else { throw new Exception($"Cannot find Attribute type or custom handler to process property '{ entityPropertyItem.PropertyName }"); } }
/// <summary> Process from JSON. </summary> /// /// <remarks> Ken, 10/2/2020. </remarks> /// /// <param name="entityModelJsonFile"> The entities JSON file. </param> /// <param name="businessModelJsonFile"> The business model file. </param> /// <param name="entitiesProjectPath"> Full pathname of the entities project file. </param> public void ProcessFromJson(string entityModelJsonFile, string businessModelJsonFile, string entitiesProjectPath) { var config = this.GeneratorConfiguration; var directory = new DirectoryInfo(projectFolderRoot); var solutionFile = directory.GetFiles("*.sln", SearchOption.TopDirectoryOnly).SingleOrDefault(); var hydraJsonFile = directory.GetFiles("hydra.json", SearchOption.AllDirectories).FirstOrDefault(); ConfigObject configObject = null; IModelAugmentationHandler modelAugmentationHandler; IEntitiesModelGeneratorHandler generatorHandler; FileInfo outputFile; BusinessModel businessModel; EntityDomainModel entityDomainModel; VSProject entitiesProject; string fileName; string appName = null; string appDescription = null; string organizationName = null; AppUIHierarchyNodeObject appUIHierarchyNodeObject = null; if (hydraJsonFile != null) { configObject = ConfigObject.Load(hydraJsonFile.FullName); appName = configObject.AppName; appDescription = configObject.AppDescription; organizationName = configObject.OrganizationName; } if (solutionFile != null) { var solutionName = Path.GetFileNameWithoutExtension(solutionFile.Name); var solutionFolder = Path.GetDirectoryName(solutionFile.FullName); if (appName == null) { appName = solutionName; organizationName = solutionName; } fileName = Path.Combine(projectFolderRoot, "entities.json"); } else { if (appName != null) { fileName = Path.Combine(projectFolderRoot, "entities.json"); } else { fileName = Path.Combine(projectFolderRoot, "entities.json"); organizationName = "NoOrganization"; appName = "NoApp"; } } config.KeyValuePairs = new Dictionary <string, object>(); config.KeyValuePairs.Add("ConfigObject", configObject); config.AppName = appName; config.AppDescription = appDescription; outputFile = new FileInfo(fileName); if (config.CurrentPass == GeneratorPass.Files) { if (outputFile.Exists) { outputFile.MakeWritable(); } } WriteLine("Loading entity model from json file"); entityDomainModel = config.CreateEntityDomainModelFromJsonFile(entityModelJsonFile); WriteLine("Loading business model"); businessModel = config.CreateBusinessModelFromJson(businessModelJsonFile); modelAugmentationHandler = config.GetModelAugmentationHandler(); entitiesProject = new VSProject(entitiesProjectPath); if (modelAugmentationHandler != null) { WriteLine("Augmenting entity model for code generation"); modelAugmentationHandler.Process(entityDomainModel, businessModel, projectType, projectFolderRoot, entitiesProject, config, out appUIHierarchyNodeObject); } generatorHandler = config.GetEntitiesModelGeneratorHandler(); if (generatorHandler != null) { WriteLine("Processing entity model and generating code file"); generatorHandler.Process(entityDomainModel, businessModel, appUIHierarchyNodeObject, projectType, projectFolderRoot, entitiesProject, config); if (config.CurrentPass == GeneratorPass.Files) { WriteLine($"Generated { outputFile.FullName }"); } } else { WriteError("No handler found implementing IEntitiesModelGeneratorHandler"); throw new HandlerNotFoundException("Entities model generation"); } }
/// <summary> Process this. </summary> /// /// <remarks> Ken, 10/4/2020. </remarks> /// /// <param name="entityDomainModel"> The entity domain model. </param> /// <param name="businessModel"> The business model. </param> /// <param name="appUIHierarchyNodeObject"></param> /// <param name="appSettingsObjects"> The application settings objects. </param> /// <param name="projectType"> Type of the project. </param> /// <param name="projectFolderRoot"> The project folder root. </param> /// <param name="generatorConfiguration"> The generator configuration. </param> /// /// <returns> True if it succeeds, false if it fails. </returns> public bool Process(EntityDomainModel entityDomainModel, BusinessModel businessModel, AppUIHierarchyNodeObject appUIHierarchyNodeObject, Dictionary <AppSettingsKind, BusinessModelObject> appSettingsObjects, Guid projectType, string projectFolderRoot, IGeneratorConfiguration generatorConfiguration) { var profilePreferencesObject = appSettingsObjects[AppSettingsKind.ProfilePreferences]; var userObject = businessModel.GetDescendants().Single(o => o.Id == profilePreferencesObject.ShadowItem); var userEntity = userObject.UIHierarchyNodeObject.Entities.Single(e => e.HasIdentityEntityKind(IdentityEntityKind.User)); foreach (var attribute in userEntity.Attributes.Where(a => a.HasIdentityFieldKind(IdentityFieldKind.Client) || a.HasIdentityFieldKind(IdentityFieldKind.PasswordHash))) { attribute.Properties.Add(new EntityPropertyItem { PropertyName = "AllowUserEdit", PropertyValue = "true" }); } return(true); }
/// <summary> Process this. </summary> /// /// <remarks> Ken, 10/3/2020. </remarks> /// /// <param name="entityDomainModel"> The entity domain model. </param> /// <param name="businessModel"> The business model. </param> /// <param name="projectType"> Type of the project. </param> /// <param name="projectFolderRoot"> The project folder root. </param> /// <param name="entitiesProject"></param> /// <param name="generatorConfiguration"> The generator configuration. </param> /// <param name="appUIHierarchyNodeObject"></param> /// /// <returns> True if it succeeds, false if it fails. </returns> public bool Process(EntityDomainModel entityDomainModel, BusinessModel businessModel, Guid projectType, string projectFolderRoot, IVSProject entitiesProject, IGeneratorConfiguration generatorConfiguration, out AppUIHierarchyNodeObject appUIHierarchyNodeObject) { var appSystemObject = businessModel.GetDescendants().Single(a => a.IsApp && a.Name == generatorConfiguration.AppName); var topLevelObject = businessModel.TopLevelObject; var topHierarchyNodeObjects = new List <UIHierarchyNodeObject>(); var allHierarchyNodeObjects = new List <UIHierarchyNodeObject>(); var appSettingsObjects = new Dictionary <AppSettingsKind, BusinessModelObject>(); IMemoryModuleBuilder memoryModuleBuilder; ModuleBuilder entititesModuleBuilder; UIHierarchyNodeObject topHierarchyNodeObject = null; string debugUIHierarchy; // create the UI hierarchy appUIHierarchyNodeObject = null; topLevelObject.GetDescendantsAndSelf <BusinessModelObject, UIHierarchyNodeObject>(o => o.Children, (o, n) => { var hierarchyNodeObject = new UIHierarchyNodeObject(o); if (topHierarchyNodeObject == null) { topHierarchyNodeObject = hierarchyNodeObject; } if (n != null) { n.AddChild(hierarchyNodeObject); } return(hierarchyNodeObject); }); // prune the tree topHierarchyNodeObject.GetDescendantsAndSelf(n => n.Children, n => { if (n.Parent != null) { var parent = n.Parent; if (!parent.ShowInUI) { var newParent = parent.Parent; if (newParent == null) { n.Parent = null; if (n.ShowInUI) { topHierarchyNodeObjects.Add(n); } } else { newParent.Children.Remove(parent); newParent.AddChild(n); } } } }); foreach (var hierarchyNodeObject in topHierarchyNodeObjects) { allHierarchyNodeObjects.AddRange(hierarchyNodeObject.GetDescendantsAndSelf()); } // create the app UI Hierarchy appUIHierarchyNodeObject = allHierarchyNodeObjects.Single(n => n.Id == appSystemObject.Id).CreateCopy <AppUIHierarchyNodeObject>(); foreach (var hierarchyNodeObject in topHierarchyNodeObjects) { hierarchyNodeObject.Name = "Home"; appUIHierarchyNodeObject.TopUIHierarchyNodeObjects.Add(hierarchyNodeObject); } // attach entities foreach (var entity in entityDomainModel.Entities) { if (entity.IsInherentDataItem) { appUIHierarchyNodeObject.InherentEntities.Add(entity); } else { var hierarchyNodeObject = allHierarchyNodeObjects.Single(n => n.Id == entity.ParentDataItem); foreach (var shadowHierarchyNodeObject in allHierarchyNodeObjects.Where(n => n.ShadowItem == hierarchyNodeObject.Id)) { shadowHierarchyNodeObject.Entities.Add(entity); } hierarchyNodeObject.Entities.Add(entity); } appUIHierarchyNodeObject.AllEntities.Add(entity); } // create new entities from app settings kind foreach (var appSettingsObject in topLevelObject.GetDescendants().Where(o => o.AppSettingsKind != null)) { var appSettingsKind = EnumUtils.GetValue <AppSettingsKind>(appSettingsObject.AppSettingsKind); appSettingsObjects.Add(appSettingsKind, appSettingsObject); } foreach (var pair in appSettingsObjects) { var appSettingsKind = pair.Key; var handler = generatorConfiguration.GetAppSettingsKindHandler(appSettingsKind); if (handler != null) { handler.Process(entityDomainModel, businessModel, appUIHierarchyNodeObject, appSettingsObjects, projectType, projectFolderRoot, generatorConfiguration); } } // create new entities from many-to-many containers foreach (var entity in appUIHierarchyNodeObject.AllEntities.ToList().Where(e => e.HasRelatedEntityAttributes())) { foreach (var containsManyToManyAttribute in entity.GetRelatedEntityAttributes().Where(a => a.Properties.Single(p => p.PropertyName == "RelatedEntity").ChildProperties.Any(p2 => p2.PropertyName == "RelationshipKind" && p2.PropertyValue == "ContainsManyToMany"))) { var relatedEntityProperty = containsManyToManyAttribute.Properties.Single(p => p.PropertyName == "RelatedEntity"); var containsManyToManyProperty = relatedEntityProperty.ChildProperties.Single(p2 => p2.PropertyName == "RelationshipKind" && p2.PropertyValue == "ContainsManyToMany"); var existingEntityProperty = containsManyToManyProperty.ChildProperties.Single(p3 => p3.PropertyName == "ExistingEntity"); var existingEntityName = existingEntityProperty.PropertyValue; var existingEntity = appUIHierarchyNodeObject.AllEntities.Single(e => e.Name == existingEntityName); var containerNameProperty = containsManyToManyProperty.ChildProperties.Single(p3 => p3.PropertyName == "ContainerName"); var containerName = containerNameProperty.PropertyValue; var associateEntityObject = new EntityObject() { Name = containerName, IsInherentDataItem = true, Attributes = new List <AttributeObject>() { new AttributeObject { Name = entity.Name, AttributeType = "related entity", Properties = new List <EntityPropertyItem>() { new EntityPropertyItem() { PropertyName = "RelatedEntity", PropertyValue = "IsLookupOfManyToOne", ChildProperties = new List <EntityPropertyItem>() { new EntityPropertyItem() { PropertyName = "ExistingEntity", PropertyValue = entity.Name } } } } }, new AttributeObject { Name = existingEntityName, AttributeType = "related entity", Properties = new List <EntityPropertyItem>() { new EntityPropertyItem() { PropertyName = "RelatedEntity", PropertyValue = "IsLookupOfManyToOne", ChildProperties = new List <EntityPropertyItem>() { new EntityPropertyItem() { PropertyName = "ExistingEntity", PropertyValue = existingEntityName } } } } } } }; if (entity.HasIdentityEntityKind(IdentityEntityKind.User) && existingEntity.HasIdentityEntityKind(IdentityEntityKind.Role)) { associateEntityObject.Properties = new List <EntityPropertyItem>() { new EntityPropertyItem() { PropertyName = "IdentityEntity", ChildProperties = new List <EntityPropertyItem>() { new EntityPropertyItem() { PropertyName = "IdentityEntityKind", PropertyValue = IdentityEntityKind.UserToRole.ToString() } } } }; } appUIHierarchyNodeObject.InherentEntities.Add(associateEntityObject); appUIHierarchyNodeObject.AllEntities.Add(associateEntityObject); } } debugUIHierarchy = appUIHierarchyNodeObject.DebugPrintUIHierarchy(); // build types memoryModuleBuilder = generatorConfiguration.GetMemoryModuleBuilder(); entititesModuleBuilder = memoryModuleBuilder.CreateMemoryModuleBuilder(entitiesProject); appUIHierarchyNodeObject.EntitiesModuleBuilder = entititesModuleBuilder; foreach (var entity in appUIHierarchyNodeObject.AllEntities) { generatorConfiguration.CreateTypeForEntity(entititesModuleBuilder, entity, appUIHierarchyNodeObject); } return(true); }
/// <summary> Process this. </summary> /// /// <remarks> Ken, 10/4/2020. </remarks> /// /// <param name="entityDomainModel"> The entity domain model. </param> /// <param name="businessModel"> The business model. </param> /// <param name="appUIHierarchyNodeObject"> The application UI hierarchy node object. </param> /// <param name="appSettingsObjects"> The application settings objects. </param> /// <param name="projectType"> Type of the project. </param> /// <param name="projectFolderRoot"> The project folder root. </param> /// <param name="generatorConfiguration"> The generator configuration. </param> /// /// <returns> True if it succeeds, false if it fails. </returns> public bool Process(EntityDomainModel entityDomainModel, BusinessModel businessModel, AppUIHierarchyNodeObject appUIHierarchyNodeObject, Dictionary <AppSettingsKind, BusinessModelObject> appSettingsObjects, Guid projectType, string projectFolderRoot, IGeneratorConfiguration generatorConfiguration) { var globalSettingsObject = appSettingsObjects[AppSettingsKind.GlobalSettings]; var userPreferencesObject = appSettingsObjects[AppSettingsKind.UserPreferences]; var appSettingsEntityObject = new EntityObject() { Name = appUIHierarchyNodeObject.Name + "Settings", ParentDataItem = globalSettingsObject.Id, Attributes = new List <AttributeObject>() { new AttributeObject { Name = "Setting", AttributeType = "string", }, new AttributeObject { Name = "Setting Type", AttributeType = "string", }, new AttributeObject { Name = "Setting Value", AttributeType = "string", }, new AttributeObject { Name = "Allow User Customize", AttributeType = "bool", }, new AttributeObject { Name = "Reset Customization", AttributeType = "bool", } }, Properties = new List <EntityPropertyItem>() { new EntityPropertyItem { PropertyName = "AppSettingsKind", PropertyValue = AppSettingsKind.GlobalSettings.ToString() } } }; globalSettingsObject.UIHierarchyNodeObject.Entities.Add(appSettingsEntityObject); userPreferencesObject.UIHierarchyNodeObject.Entities.Add(appSettingsEntityObject.Shadow()); appUIHierarchyNodeObject.AllEntities.Add(appSettingsEntityObject); return(true); }