From 68564342cefdea0e5f1f05b37fd7d95dc683e5a8 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 9 Nov 2018 17:55:34 +0200 Subject: [PATCH 1/2] Added initial Model Generation Tool with Tests. --- Gravity/Gravity.sln | 18 ++ .../GravityModelGenerationTests.cs | 26 ++ .../ModelGeneration.Tests.csproj | 75 +++++ .../Properties/AssemblyInfo.cs | 20 ++ .../ModelGeneration.Tests/packages.config | 5 + .../Attributes/XmlNodeKeyAttribute.cs | 23 ++ .../Attributes/XmlNodePathAttribute.cs | 23 ++ .../Extensions/StringExtensions.cs | 24 ++ .../Extensions/TypeExtensions.cs | 12 + .../Factories/Base/XmlFactoryBase.cs | 14 + .../External/GravityModelGenerationFactory.cs | 86 ++++++ .../Factories/Internal/GravityRdoFactory.cs | 76 +++++ .../Internal/NetModelGenerationFactory.cs | 268 ++++++++++++++++++ .../ModelGenerationTool.csproj | 103 +++++++ .../Models/File/CSharpFile.cs | 17 ++ .../Models/File/CSharpTemplates.Designer.cs | 145 ++++++++++ .../Models/File/CSharpTemplates.resx | 139 +++++++++ .../Models/GravityRdo/Constants.cs | 9 + .../Models/GravityRdo/GravityChoice.cs | 36 +++ .../Models/GravityRdo/GravityChoiceModel.cs | 50 ++++ .../Models/GravityRdo/GravityFieldModel.cs | 154 ++++++++++ .../Models/GravityRdo/GravityModel.cs | 97 +++++++ .../Models/NET/Base/INetParsableClass.cs | 7 + .../Models/NET/Base/INetParsableFlag.cs | 7 + .../Models/NET/Base/INetParsableProperty.cs | 7 + .../ModelGenerationTool/Models/NET/NetFlag.cs | 26 ++ .../Models/NET/NetItemType.cs | 10 + .../Models/NET/NetModel.cs | 83 ++++++ .../Models/NET/NetProperty.cs | 87 ++++++ .../Properties/AssemblyInfo.cs | 36 +++ .../Resources/CSharpClass.txt | 8 + .../Resources/CSharpEnum.txt | 7 + .../Resources/CSharpEnumFlag.txt | 3 + .../Resources/CSharpInterface.txt | 0 .../Resources/CSharpProperty.txt | 3 + .../Resources/CSharpStruct.txt | 0 36 files changed, 1704 insertions(+) create mode 100644 Gravity/Model Generation Tool/ModelGeneration.Tests/GravityModelGenerationTests.cs create mode 100644 Gravity/Model Generation Tool/ModelGeneration.Tests/ModelGeneration.Tests.csproj create mode 100644 Gravity/Model Generation Tool/ModelGeneration.Tests/Properties/AssemblyInfo.cs create mode 100644 Gravity/Model Generation Tool/ModelGeneration.Tests/packages.config create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Attributes/XmlNodeKeyAttribute.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Attributes/XmlNodePathAttribute.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Extensions/StringExtensions.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Extensions/TypeExtensions.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Factories/Base/XmlFactoryBase.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Factories/External/GravityModelGenerationFactory.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/GravityRdoFactory.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/NetModelGenerationFactory.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/ModelGenerationTool.csproj create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpFile.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpTemplates.Designer.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpTemplates.resx create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/Constants.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityChoice.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityChoiceModel.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityFieldModel.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityModel.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableClass.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableFlag.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableProperty.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetFlag.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetItemType.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetModel.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetProperty.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Properties/AssemblyInfo.cs create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpClass.txt create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpEnum.txt create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpEnumFlag.txt create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpInterface.txt create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpProperty.txt create mode 100644 Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpStruct.txt diff --git a/Gravity/Gravity.sln b/Gravity/Gravity.sln index 7cd8d72..c9455e2 100644 --- a/Gravity/Gravity.sln +++ b/Gravity/Gravity.sln @@ -18,6 +18,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Directory.Build.targets = Directory.Build.targets EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Model Generation Tool", "Model Generation Tool", "{3C2F531F-8DB7-42EB-BD1A-8845D297DAC6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelGenerationTool", "Model Generation Tool\ModelGenerationTool\ModelGenerationTool.csproj", "{6CFC0187-3447-4D9C-A931-FA6500B05EB2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelGeneration.Tests", "Model Generation Tool\ModelGeneration.Tests\ModelGeneration.Tests.csproj", "{07463FBC-A94F-4B8A-8A1F-341812386CCB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -40,10 +46,22 @@ Global {C0882E20-283A-4CAC-A53C-3512A71127DF}.Debug|Any CPU.Build.0 = Debug|Any CPU {C0882E20-283A-4CAC-A53C-3512A71127DF}.Release|Any CPU.ActiveCfg = Release|Any CPU {C0882E20-283A-4CAC-A53C-3512A71127DF}.Release|Any CPU.Build.0 = Release|Any CPU + {6CFC0187-3447-4D9C-A931-FA6500B05EB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CFC0187-3447-4D9C-A931-FA6500B05EB2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CFC0187-3447-4D9C-A931-FA6500B05EB2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CFC0187-3447-4D9C-A931-FA6500B05EB2}.Release|Any CPU.Build.0 = Release|Any CPU + {07463FBC-A94F-4B8A-8A1F-341812386CCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07463FBC-A94F-4B8A-8A1F-341812386CCB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07463FBC-A94F-4B8A-8A1F-341812386CCB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07463FBC-A94F-4B8A-8A1F-341812386CCB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {6CFC0187-3447-4D9C-A931-FA6500B05EB2} = {3C2F531F-8DB7-42EB-BD1A-8845D297DAC6} + {07463FBC-A94F-4B8A-8A1F-341812386CCB} = {3C2F531F-8DB7-42EB-BD1A-8845D297DAC6} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {02DBD25B-BBE4-4F36-9E32-31682E297EC9} EndGlobalSection diff --git a/Gravity/Model Generation Tool/ModelGeneration.Tests/GravityModelGenerationTests.cs b/Gravity/Model Generation Tool/ModelGeneration.Tests/GravityModelGenerationTests.cs new file mode 100644 index 0000000..06adede --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGeneration.Tests/GravityModelGenerationTests.cs @@ -0,0 +1,26 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ModelGenerationTool.Factories.External; + +namespace ModelGeneration.Tests +{ + [TestClass] + public class GravityModelGenerationTests + { + GravityModelGenerationFactory _gravityModelGenFactory; + + string _rapXmlSchemaLocation = ""; + string _modelsOutputPath = ""; + + [TestInitialize] + public void Initialize() + { + _gravityModelGenFactory = new GravityModelGenerationFactory(_rapXmlSchemaLocation); + } + + [TestMethod] + public void GenerateGravityModels() + { + _gravityModelGenFactory.GenerateGravityModels(_modelsOutputPath); + } + } +} diff --git a/Gravity/Model Generation Tool/ModelGeneration.Tests/ModelGeneration.Tests.csproj b/Gravity/Model Generation Tool/ModelGeneration.Tests/ModelGeneration.Tests.csproj new file mode 100644 index 0000000..d97904a --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGeneration.Tests/ModelGeneration.Tests.csproj @@ -0,0 +1,75 @@ + + + + + + Debug + AnyCPU + {07463FBC-A94F-4B8A-8A1F-341812386CCB} + Library + Properties + ModelGeneration.Tests + ModelGeneration.Tests + v4.6.2 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + + + ..\..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + + + + + + + + + + + + + + {6CFC0187-3447-4D9C-A931-FA6500B05EB2} + ModelGenerationTool + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGeneration.Tests/Properties/AssemblyInfo.cs b/Gravity/Model Generation Tool/ModelGeneration.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c9effc7 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGeneration.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("ModelGeneration.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ModelGeneration.Tests")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: Guid("07463fbc-a94f-4b8a-8a1f-341812386ccb")] + +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Gravity/Model Generation Tool/ModelGeneration.Tests/packages.config b/Gravity/Model Generation Tool/ModelGeneration.Tests/packages.config new file mode 100644 index 0000000..18af168 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGeneration.Tests/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Attributes/XmlNodeKeyAttribute.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Attributes/XmlNodeKeyAttribute.cs new file mode 100644 index 0000000..110f198 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Attributes/XmlNodeKeyAttribute.cs @@ -0,0 +1,23 @@ +using System; + +namespace ModelGenerationTool.Attributes +{ + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] + internal class XmlNodeKeyAttribute : Attribute + { + internal XmlNodeKeyAttribute(string xmlNodeKey) + { + XmlNodeKey = xmlNodeKey; + } + + internal XmlNodeKeyAttribute(string xmlNodeKey, string customData) + { + XmlNodeKey = xmlNodeKey; + CustomData = customData; + } + + internal string XmlNodeKey { get; set; } + + internal string CustomData { get; set; } + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Attributes/XmlNodePathAttribute.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Attributes/XmlNodePathAttribute.cs new file mode 100644 index 0000000..3402e37 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Attributes/XmlNodePathAttribute.cs @@ -0,0 +1,23 @@ +using System; + +namespace ModelGenerationTool.Attributes +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + internal class XmlNodePathAttribute : Attribute + { + internal XmlNodePathAttribute(string xmlNodePath) + { + XmlNodePath = xmlNodePath; + } + + internal XmlNodePathAttribute(string xmlNodePath, string customData) + { + XmlNodePath = xmlNodePath; + CustomData = customData; + } + + internal string XmlNodePath { get; set; } + + internal string CustomData { get; set; } + } +} diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Extensions/StringExtensions.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Extensions/StringExtensions.cs new file mode 100644 index 0000000..7d92861 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Extensions/StringExtensions.cs @@ -0,0 +1,24 @@ +using System.Text; + +namespace ModelGenerationTool.Extensions +{ + internal static class StringExtensions + { + internal static string ToDotNetNameFormat(this string input) + { + StringBuilder resultBuilder = new StringBuilder(input.Length); + char[] inputAsChars = input.ToCharArray(); + + for (int i = 0; i < input.Length; i++) + { + if ((char.IsDigit(inputAsChars[i]) && resultBuilder.Length > 0) + || char.IsLetter(inputAsChars[i])) + { + resultBuilder.Append(inputAsChars[i]); + } + } + + return resultBuilder.ToString(); + } + } +} diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Extensions/TypeExtensions.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Extensions/TypeExtensions.cs new file mode 100644 index 0000000..d87d417 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Extensions/TypeExtensions.cs @@ -0,0 +1,12 @@ +using System; +using System.Linq; +using System.Reflection; + +namespace ModelGenerationTool.Extensions +{ + internal static class TypeExtensions + { + internal static A GetPropertyAttribute(this Type type, string propertyName) + where A : Attribute => type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).First(p => p.Name == propertyName).GetCustomAttribute(); + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Base/XmlFactoryBase.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Base/XmlFactoryBase.cs new file mode 100644 index 0000000..c2594f7 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Base/XmlFactoryBase.cs @@ -0,0 +1,14 @@ +using System.Xml; + +namespace ModelGenerationTool.Factories.Base +{ + public abstract class XmlFactoryBase + { + protected XmlDocument xmlDocument; + + protected XmlFactoryBase(XmlDocument xmlDocument) + { + this.xmlDocument = xmlDocument; + } + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Factories/External/GravityModelGenerationFactory.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Factories/External/GravityModelGenerationFactory.cs new file mode 100644 index 0000000..b0ccce4 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Factories/External/GravityModelGenerationFactory.cs @@ -0,0 +1,86 @@ +using ModelGenerationTool.Factories.Base; +using ModelGenerationTool.Factories.Internal; +using ModelGenerationTool.Models.File; +using ModelGenerationTool.Models.GravityRdo; +using ModelGenerationTool.Models.NET; +using System.Collections.Generic; +using System.Linq; +using System.Xml; + +namespace ModelGenerationTool.Factories.External +{ + public class GravityModelGenerationFactory : XmlFactoryBase + { + public GravityModelGenerationFactory(XmlDocument xmlDocument) + : base(xmlDocument) { } + + public GravityModelGenerationFactory(string xmlDocumentLocation) + : base(new XmlDocument()) => xmlDocument.Load(xmlDocumentLocation); + + public void GenerateGravityModels(string outputPath) + { + // 1. Load xmlDocument by Path + GravityRdoFactory rdoFactory = new GravityRdoFactory(xmlDocument); + + // 2. Read in Platform specific Models + var rdoModels = rdoFactory.GenerateRdoModelsForXml(); + + // 3. ConvertToDotNet with NetProperties + var rdoModelsAsDotNet = ConvertRdoModelsToDotNet(rdoModels); + + NetModelGenerationFactory netFactory = new NetModelGenerationFactory(); + + foreach (var netModel in rdoModelsAsDotNet) + { + // 4. Convert NetModel with NetProperties to CSharpFile + var csFile = netFactory.GenerateCSharpFileFromModel(netModel); + + // 5. Store file in specified output path + csFile.Save(outputPath); + } + } + + public List GenerateGravityModelFiles() + { + List resultList = new List(); + + // 1. Load xmlDocument by Path + GravityRdoFactory rdoFactory = new GravityRdoFactory(xmlDocument); + + // 2. Read in Platform specific Models + var rdoModels = rdoFactory.GenerateRdoModelsForXml(); + + // 3. ConvertToDotNet with NetProperties + var rdoModelsAsDotNet = ConvertRdoModelsToDotNet(rdoModels); + + NetModelGenerationFactory netFactory = new NetModelGenerationFactory(); + + foreach (var netModel in rdoModelsAsDotNet) + { + // 4. Convert NetModel with NetProperties to CSharpFile + resultList.Add(netFactory.GenerateCSharpFileFromModel(netModel)); + } + + return resultList; + } + + // TODO: This should be moved out from factory.. + private static List ConvertRdoModelsToDotNet(List rdoModels) + { + List returnList = new List(); + + foreach (var rdoModel in rdoModels) + { + foreach (var choice in rdoModel.GravityChoices) + { + if (returnList.Select(x => x.Name).Contains(choice.Name) == false) + returnList.Add(choice.ConvertToDotNet()); + } + + returnList.Add(rdoModel.ConvertToDotNet()); + } + + return returnList; + } + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/GravityRdoFactory.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/GravityRdoFactory.cs new file mode 100644 index 0000000..de7b450 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/GravityRdoFactory.cs @@ -0,0 +1,76 @@ +using Gravity.Base; +using ModelGenerationTool.Attributes; +using ModelGenerationTool.Factories.Base; +using ModelGenerationTool.Models.GravityRdo; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Xml; + +namespace ModelGenerationTool.Factories.Internal +{ + internal class GravityRdoFactory : XmlFactoryBase + { + internal GravityRdoFactory(XmlDocument xmlDocument) + : base(xmlDocument) + { } + + internal GravityRdoFactory(string xmlDocumentLocation) + : base(new XmlDocument()) + { + xmlDocument.Load(xmlDocumentLocation); + } + + internal List GenerateRdoModelsForXml() + { + List resultList = new List(); + + string objectsXpath = typeof(GravityModel).GetCustomAttribute().XmlNodePath; + + XmlNodeList rdoObjects = xmlDocument.SelectNodes(objectsXpath); + + foreach (XmlNode rdoObject in rdoObjects) + { + resultList.Add(new GravityModel(rdoObject)); + } + + PopulateObjectFields(resultList); + PopulateChildrenFields(resultList); + + return resultList; + } + + private void PopulateObjectFields(List models) + { + foreach (var model in models) + { + var objectFields = model.GravityFields + .Where(f => f.RdoFieldType == RdoFieldType.SingleObject || f.RdoFieldType == RdoFieldType.MultipleObject); + + foreach (var objField in objectFields) + { + string descriptorObjName = models.First(m => m.DescriptorArtifactTypeId == objField.AssociativeArtifactTypeId.Value)?.Name; + var associatedObjs = model.GravityFields.Where(f => f.AssociativeArtifactTypeId == objField.AssociativeArtifactTypeId.Value); + + foreach (var associatedObj in associatedObjs) + { + associatedObj.Name = descriptorObjName; + } + } + } + } + + private void PopulateChildrenFields(List models) + { + foreach (var child in models) + { + var parent = models.FirstOrDefault(m => m.DescriptorArtifactTypeId == child.ParentArtifactTypeId); + + if (child.ParentArtifactTypeId.HasValue && parent != null) + { + parent.GravityFields.Add(new GravityFieldModel(child.Name, null, null)); + } + } + } + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/NetModelGenerationFactory.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/NetModelGenerationFactory.cs new file mode 100644 index 0000000..216f9fe --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/NetModelGenerationFactory.cs @@ -0,0 +1,268 @@ +using ModelGenerationTool.Models.File; +using ModelGenerationTool.Models.NET; +using System; +using System.Collections.Generic; +using System.Text; + +namespace ModelGenerationTool.Factories.Internal +{ + internal class NetModelGenerationFactory + { + internal CSharpFile GenerateCSharpFileFromModel(NetModel netModel) + { + CSharpFile csFile; + + switch (netModel.Type) + { + case NetItemType.Class: + csFile = CreateCSharpClassFile(netModel); + break; + + case NetItemType.Enum: + csFile = CreateCSharpEnumFile(netModel); + break; + + case NetItemType.Interface: + csFile = CreateCSharpInterfaceFile(netModel); + break; + + case NetItemType.Struct: + csFile = CreateCSharpStructFile(netModel); + break; + + // TODO: + default: + throw new NotImplementedException(); + } + + return csFile; + } + + private CSharpFile CreateCSharpClassFile(NetModel netModel) + { + StringBuilder classFileTemplate = new StringBuilder(CSharpTemplates.CSharpClass, short.MaxValue); + + classFileTemplate.Replace("%usings%", FormatUsings(netModel.Usings)); + classFileTemplate.Replace("%attributes%", FormatParamList(netModel.Attributes, "\t")); + classFileTemplate.Replace("%inherits%", FormatAncestors(netModel.Inherits)); + classFileTemplate.Replace("%namespace%", netModel.Namespace); + classFileTemplate.Replace("%access_modifier%", $"\t{netModel.AccessModifier}"); + classFileTemplate.Replace("%additional_keyword%", netModel.AdditionalKeyword); + classFileTemplate.Replace("%name%", netModel.Name); + classFileTemplate.Replace("%properties%", FormatProperties(netModel.Properties)); + + return new CSharpFile(netModel.Name, classFileTemplate.ToString()); + } + + private CSharpFile CreateCSharpEnumFile(NetModel netModel) + { + StringBuilder enumFileTemplate = new StringBuilder(CSharpTemplates.CSharpEnum, short.MaxValue); + + enumFileTemplate.Replace("%usings%", FormatUsings(netModel.Usings)); + enumFileTemplate.Replace("%attributes%", FormatParamList(netModel.Attributes)); + enumFileTemplate.Replace("%namespace%", netModel.Namespace); + enumFileTemplate.Replace("%access_modifier%", $"\t{netModel.AccessModifier}"); + enumFileTemplate.Replace("%name%", netModel.Name); + enumFileTemplate.Replace("%flags%", FormatFlags(netModel.Flags)); + + return new CSharpFile(netModel.Name, enumFileTemplate.ToString()); + } + + private CSharpFile CreateCSharpInterfaceFile(NetModel netModel) + => throw new NotImplementedException(); + + private CSharpFile CreateCSharpStructFile(NetModel netModel) + => throw new NotImplementedException(); + + + #region Format Methods + + private string FormatUsings(List usings) + { + StringBuilder paramBuilder; + + if (usings == null || usings.Count <= 0) + return string.Empty; + else + { + paramBuilder = new StringBuilder(short.MaxValue); + + for (int i = 0; i < usings.Count; i++) + { + if (i < usings.Count - 1) + paramBuilder.AppendLine(FormatUsing(usings[i])); + else + paramBuilder.Append(FormatUsing(usings[i])); + } + + return paramBuilder.ToString(); + } + } + + private string FormatUsing(string _using) + { + if (string.IsNullOrEmpty(_using)) + return null; + + StringBuilder resultBuilder = new StringBuilder(_using); + + if (_using.LastIndexOf(';') != _using.Length - 1) + resultBuilder.Append(";"); + + if (_using.ToLower().IndexOf("using") == -1 && _using.IndexOf("=") == -1) + resultBuilder.Insert(0, "using "); + + return resultBuilder.ToString(); + } + + private string FormatAncestors(List ancestors) + { + StringBuilder paramBuilder; + + if (ancestors == null || ancestors.Count <= 0) + return string.Empty; + else + { + paramBuilder = new StringBuilder(short.MaxValue); + + for (int i = 0; i < ancestors.Count; i++) + { + if (i < ancestors.Count - 1) + paramBuilder.AppendLine(FormatAncestor(ancestors[i], i)); + else + paramBuilder.Append(FormatAncestor(ancestors[i], i)); + } + + return paramBuilder.ToString(); + } + } + + private string FormatAncestor(string ancestor, int index) + { + string result = null; + + if (string.IsNullOrEmpty(ancestor)) + result = null; + else if (index == 0) + result = $" : {ancestor}"; + else + result = $", {ancestor}"; + + return result; + } + + private string FormatProperties(List properties) + { + StringBuilder propertiesBuilder; + + if (properties == null || properties.Count <= 0) + return string.Empty; + else + { + propertiesBuilder = new StringBuilder(short.MaxValue); + + foreach (var property in properties) + { + propertiesBuilder.AppendLine(FormatProperty(property)); + } + + return propertiesBuilder.ToString(); + } + } + + private string FormatProperty(NetProperty netProperty) + { + StringBuilder propertyFileTemplate = new StringBuilder(CSharpTemplates.CSharpProperty, short.MaxValue); + + // Attributes + propertyFileTemplate.Replace("%attributes%", FormatParamList(netProperty.Attributes, "\t\t")); + + // Access Modifier + propertyFileTemplate.Replace("%access_modifier%", $"\t\t{netProperty.AccessModifier}"); + + // Type + propertyFileTemplate.Replace("%type%", netProperty.Type != null ? netProperty.Type.Name : netProperty.TypeName); + + // Name + propertyFileTemplate.Replace("%name%", netProperty.Name); + + // Get & Set Modifiers + if (string.IsNullOrEmpty(netProperty.GetAccessModifier) || string.IsNullOrEmpty(netProperty.SetAccessModifier)) + { + propertyFileTemplate.Replace("%get_modifier%", ""); + propertyFileTemplate.Replace("%set_modifier%", ""); + } + else + { + string getAccessModifier = netProperty.GetAccessModifier.ToLower().Trim() == "public" ? "" : netProperty.GetAccessModifier; + string setAccessModifier = netProperty.SetAccessModifier.ToLower().Trim() == "public" ? "" : netProperty.SetAccessModifier; + + propertyFileTemplate.Replace("%get_modifier%", $"{'{'} {getAccessModifier} get; "); + propertyFileTemplate.Replace("%set_modifier%", $"{setAccessModifier} set; {'}'}"); + } + + // Value + propertyFileTemplate.Replace("%value%", string.IsNullOrEmpty(netProperty.Value) ? "" : $"= {netProperty.Value}"); + + return propertyFileTemplate.ToString(); + } + + private string FormatFlags(List flags) + { + StringBuilder flagsBuilder; + + if (flags == null || flags.Count <= 0) + return string.Empty; + else + { + flagsBuilder = new StringBuilder(short.MaxValue); + + foreach (var flag in flags) + { + flagsBuilder.AppendLine(FormatFlag(flag)); + } + + return flagsBuilder.ToString(); + } + } + + private string FormatFlag(NetFlag flag) + { + StringBuilder flagFileTemplate = new StringBuilder(CSharpTemplates.CSharpEnumFlag, short.MaxValue); + + // Attributes + flagFileTemplate.Replace("%attributes%", FormatParamList(flag.Attributes, "\t\t")); + + // Name + flagFileTemplate.Replace("%name%", $"\t\t{flag.Name}"); + + // Value + flagFileTemplate.Replace("%value%", string.IsNullOrEmpty(flag.Value) ? "" : $"= {flag.Value},"); + + return flagFileTemplate.ToString(); + } + + private string FormatParamList(List paramList, string paramPrefix = "") + { + StringBuilder paramBuilder; + + if (paramList == null || paramList.Count <= 0) + return string.Empty; + else + { + paramBuilder = new StringBuilder(short.MaxValue); + + for (int i = 0; i < paramList.Count; i++) + { + if (i < paramList.Count - 1) + paramBuilder.AppendLine($"{paramPrefix}{paramList[i]}"); + else + paramBuilder.Append($"{paramPrefix}{paramList[i]}"); + } + + return paramBuilder.ToString(); + } + } + #endregion + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/ModelGenerationTool.csproj b/Gravity/Model Generation Tool/ModelGenerationTool/ModelGenerationTool.csproj new file mode 100644 index 0000000..d292290 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/ModelGenerationTool.csproj @@ -0,0 +1,103 @@ + + + + + Debug + AnyCPU + {6CFC0187-3447-4D9C-A931-FA6500B05EB2} + Library + Properties + ModelGenerationTool + ModelGenerationTool + v4.6.2 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + CSharpTemplates.resx + True + True + + + + + + + + + + + + + + + + + + {cfa21c47-85e1-47b9-a824-7cd3989c9998} + Gravity + + + + + ResXFileCodeGenerator + CSharpTemplates.Designer.cs + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpFile.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpFile.cs new file mode 100644 index 0000000..0e7b148 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpFile.cs @@ -0,0 +1,17 @@ +namespace ModelGenerationTool.Models.File +{ + public class CSharpFile + { + private string _name; + private string _content; + + internal CSharpFile(string name, string content) + { + _name = name; + _content = content; + } + + public void Save(string location) + => System.IO.File.WriteAllText($"{location}\\{_name}.cs", _content); + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpTemplates.Designer.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpTemplates.Designer.cs new file mode 100644 index 0000000..d252b23 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpTemplates.Designer.cs @@ -0,0 +1,145 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ModelGenerationTool.Models.File { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class CSharpTemplates { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal CSharpTemplates() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModelGenerationTool.Models.File.CSharpTemplates", typeof(CSharpTemplates).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to %usings% + /// + ///namespace %namespace% + ///{ + /// %attributes% + /// %access_modifier_class% class %class_name% : %inherits% + /// { + /// %properties% + /// } + ///}. + /// + internal static string CSharpClass { + get { + return ResourceManager.GetString("CSharpClass", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to %usings% + /// + ///namespace %namespace% + ///{ + /// %access_modifier% enum %enum_name% + /// { + /// [RelativityObject("4F04381D-F3E3-4DEE-8EF9-11F27047D9B4")] + /// SingleChoice1 = 1, + /// + /// [RelativityObject("8453BF3E-D95B-4BC5-BD68-3CF4277DD731")] + /// SingleChoice2 = 2, + /// + /// [RelativityObject("960FE22C-2AA9-4017-9B7C-10D04D0C8F38")] + /// SingleChoice3 = 3 + /// } + ///} + ///. + /// + internal static string CSharpEnum { + get { + return ResourceManager.GetString("CSharpEnum", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to %attributes% + ///%name% = %value%. + /// + internal static string CSharpEnumFlag { + get { + return ResourceManager.GetString("CSharpEnumFlag", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string CSharpInterface { + get { + return ResourceManager.GetString("CSharpInterface", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to + ///%attributes% + ///%access_modifier% %type% %name% { %get_modifier% get; %set_modifier% set; }. + /// + internal static string CSharpProperty { + get { + return ResourceManager.GetString("CSharpProperty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to . + /// + internal static string CSharpStruct { + get { + return ResourceManager.GetString("CSharpStruct", resourceCulture); + } + } + } +} diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpTemplates.resx b/Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpTemplates.resx new file mode 100644 index 0000000..4fde06c --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/File/CSharpTemplates.resx @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\..\Resources\CSharpClass.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;windows-1251 + + + ..\..\Resources\CSharpEnum.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;windows-1251 + + + ..\..\Resources\CSharpEnumFlag.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;windows-1251 + + + ..\..\Resources\CSharpInterface.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;windows-1251 + + + ..\..\Resources\CSharpProperty.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;windows-1251 + + + ..\..\Resources\CSharpStruct.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;windows-1251 + + \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/Constants.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/Constants.cs new file mode 100644 index 0000000..e58e241 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/Constants.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace ModelGenerationTool.Models.GravityRdo +{ + internal static class Constants + { + internal static readonly List AllowedRelativitySystemFields = new List() { "Name" }; + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityChoice.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityChoice.cs new file mode 100644 index 0000000..1431a6b --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityChoice.cs @@ -0,0 +1,36 @@ +using ModelGenerationTool.Attributes; +using ModelGenerationTool.Models.NET; +using ModelGenerationTool.Models.NET.Base; +using System.Collections.Generic; + +namespace ModelGenerationTool.Models.GravityRdo +{ + [XmlNodePath("Codes/Code")] + internal class GravityChoice : INetParsableFlag + { + int _value; + + internal GravityChoice(string name, string guid, int value) + { + Name = name; + Guid = guid; + _value = value; + } + + [XmlNodeKey("Name")] + internal string Name { get; set; } + + [XmlNodeKey("Guid")] + internal string Guid { get; set; } + + public NetFlag ConvertToDotNet() + { + List attributes = new List() + { + $"[RelativityObject(\"{Guid}\")]" + }; + + return new NetFlag(attributes, Name, _value.ToString()); + } + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityChoiceModel.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityChoiceModel.cs new file mode 100644 index 0000000..75edf03 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityChoiceModel.cs @@ -0,0 +1,50 @@ +using ModelGenerationTool.Attributes; +using ModelGenerationTool.Extensions; +using ModelGenerationTool.Models.NET; +using ModelGenerationTool.Models.NET.Base; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Xml; + +namespace ModelGenerationTool.Models.GravityRdo +{ + internal class GravityChoiceModel : INetParsableClass + { + internal GravityChoiceModel(XmlNode choiceFieldNode) + { + string choicesPath = typeof(GravityChoice).GetCustomAttribute().XmlNodePath; + string nameKey = typeof(GravityChoiceModel).GetPropertyAttribute(nameof(Name)).XmlNodeKey; + + string choiceNameKey = typeof(GravityChoice).GetPropertyAttribute(nameof(GravityChoice.Name)).XmlNodeKey; + string choiceGuidKey = typeof(GravityChoice).GetPropertyAttribute(nameof(GravityChoice.Guid)).XmlNodeKey; + + Name = choiceFieldNode[nameKey].InnerText.ToDotNetNameFormat(); + Choices = new List(); + + XmlNodeList choicesList = choiceFieldNode.SelectNodes(choicesPath); + int counter = 0; + + foreach (XmlNode choiceNode in choicesList) + { + string name = choiceNode[choiceNameKey].InnerText.ToDotNetNameFormat(); + string guid = choiceNode[choiceGuidKey].InnerText; + + Choices.Add(new GravityChoice(name, guid, ++counter)); + } + } + + [XmlNodeKey("DisplayName")] + internal string Name { get; set; } + + internal List Choices { get; set; } + + public NetModel ConvertToDotNet() + { + List flags = new List(); + flags.AddRange(Choices.Select(c => c.ConvertToDotNet())); + + return new NetModel("ModelGenerationTool.Test", null, Name, flags, "public"); + } + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityFieldModel.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityFieldModel.cs new file mode 100644 index 0000000..812110b --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityFieldModel.cs @@ -0,0 +1,154 @@ +using Gravity.Base; +using ModelGenerationTool.Attributes; +using ModelGenerationTool.Extensions; +using ModelGenerationTool.Models.NET; +using ModelGenerationTool.Models.NET.Base; +using System; +using System.Collections.Generic; +using System.Xml; + +namespace ModelGenerationTool.Models.GravityRdo +{ + [XmlNodePath("Fields/Field", "Default")] + [XmlNodePath("SystemFields/SystemField", "System")] + internal class GravityFieldModel : INetParsableProperty + { + internal GravityFieldModel(XmlNode fieldNode, bool isSystemField = false) + { + string nameKey = typeof(GravityFieldModel).GetPropertyAttribute(nameof(Name)).XmlNodeKey; + string rdoFieldTypeKey = typeof(GravityFieldModel).GetPropertyAttribute(nameof(RdoFieldType)).XmlNodeKey; + string guidKey = typeof(GravityFieldModel).GetPropertyAttribute(nameof(Guid)).XmlNodeKey; + string associativeObjIdKey = typeof(GravityFieldModel).GetPropertyAttribute(nameof(AssociativeArtifactTypeId)).XmlNodeKey; + string maxTextLengthKey = typeof(GravityFieldModel).GetPropertyAttribute(nameof(MaxTextLength)).XmlNodeKey; + + Name = fieldNode[nameKey].InnerText.ToDotNetNameFormat(); + RdoFieldType = (RdoFieldType)Convert.ToInt32(fieldNode[rdoFieldTypeKey].InnerText); + Guid = fieldNode[guidKey].InnerText; + + int.TryParse(fieldNode[associativeObjIdKey].InnerText, out int associativeObjId); + AssociativeArtifactTypeId = associativeObjId > 0 ? associativeObjId : (int?)null; + + int.TryParse(fieldNode[maxTextLengthKey].InnerText, out int maxTextLength); + MaxTextLength = maxTextLength > 0 ? maxTextLength : (int?)null; + + IsSystemField = isSystemField; + } + + internal GravityFieldModel(string name, RdoFieldType? rdoFieldType, string guid, + int? associativeObjId = null, + int? maxTextLength = null, + bool isSystemField = false) + { + Name = name.ToDotNetNameFormat(); + RdoFieldType = rdoFieldType; + Guid = guid; + AssociativeArtifactTypeId = associativeObjId; + MaxTextLength = maxTextLength; + IsSystemField = isSystemField; + } + + [XmlNodeKey("DisplayName")] + internal string Name { get; set; } + + [XmlNodeKey("FieldTypeId")] + internal RdoFieldType? RdoFieldType { get; private set; } + + [XmlNodeKey("Guid")] + internal string Guid { get; private set; } + + [XmlNodeKey("MaxLength")] + internal int? MaxTextLength { get; set; } + + [XmlNodeKey("AssociativeArtifactTypeId")] + internal int? AssociativeArtifactTypeId { get; set; } + + internal bool IsSystemField { get; private set; } + + public NetProperty ConvertToDotNet() + { + string fieldAttr; + string typeName = typeof(object).Name; + + if (RdoFieldType.HasValue) + { + fieldAttr = $"[RelativityObjectField(\"{Guid}\", RdoFieldType.{RdoFieldType.Value.ToString()})]"; + + switch (RdoFieldType.Value) + { + case Gravity.Base.RdoFieldType.Currency: + case Gravity.Base.RdoFieldType.Decimal: + typeName = typeof(decimal).Name; + break; + + case Gravity.Base.RdoFieldType.Date: + typeName = typeof(DateTime).Name; + break; + + case Gravity.Base.RdoFieldType.File: + typeName = typeof(FileDto).Name; + break; + + case Gravity.Base.RdoFieldType.FixedLengthText: + typeName = typeof(string).Name; + + if (MaxTextLength.HasValue) + fieldAttr = $"[RelativityObjectField(\"{Guid}\", RdoFieldType.{RdoFieldType.Value.ToString()}, {MaxTextLength.Value})]"; + + break; + + case Gravity.Base.RdoFieldType.LongText: + typeName = typeof(string).Name; + break; + + case Gravity.Base.RdoFieldType.WholeNumber: + typeName = typeof(int).Name; + break; + + case Gravity.Base.RdoFieldType.User: + // TODO: Must refer to kCura.Relativity.Client.DTOs to be able to use: typeof(User).Name; + typeName = "User"; + break; + + case Gravity.Base.RdoFieldType.YesNo: + typeName = typeof(bool).Name; + break; + + case Gravity.Base.RdoFieldType.SingleChoice: + typeName = Name; + break; + + case Gravity.Base.RdoFieldType.MultipleChoice: + typeName = $"IList<{Name}>"; + break; + + case Gravity.Base.RdoFieldType.SingleObject: + typeName = Name; + + // Is parent artifact Id field.. + if (IsSystemField && AssociativeArtifactTypeId.HasValue) + { + fieldAttr = $"[RelativityObjectFieldParentArtifactId(\"{Guid}\")]"; + RdoFieldType = Gravity.Base.RdoFieldType.WholeNumber; + } + + break; + + case Gravity.Base.RdoFieldType.MultipleObject: + typeName = $"IList<{Name}>"; + break; + + case Gravity.Base.RdoFieldType.Empty: + break; + } + } + else + { + // Children List + typeName = $"IList<{Name}>"; + fieldAttr = "[RelativityObjectChildrenList()]"; + } + + return new NetProperty(new List() { fieldAttr }, Name, typeName); + } + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityModel.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityModel.cs new file mode 100644 index 0000000..3a7e418 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/GravityRdo/GravityModel.cs @@ -0,0 +1,97 @@ +using Gravity.Base; +using ModelGenerationTool.Attributes; +using ModelGenerationTool.Extensions; +using ModelGenerationTool.Models.NET; +using ModelGenerationTool.Models.NET.Base; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Xml; + +namespace ModelGenerationTool.Models.GravityRdo +{ + [XmlNodePath("/Application/Objects/Object")] + internal class GravityModel : INetParsableClass + { + internal GravityModel(XmlNode rdoObjectNode) + { + string nameKey = typeof(GravityModel).GetPropertyAttribute(nameof(Name)).XmlNodeKey; + string guidKey = typeof(GravityModel).GetPropertyAttribute(nameof(Guid)).XmlNodeKey; + string descriptorObjIdKey = typeof(GravityModel).GetPropertyAttribute(nameof(DescriptorArtifactTypeId)).XmlNodeKey; + string parentObjIdKey = typeof(GravityModel).GetPropertyAttribute(nameof(ParentArtifactTypeId)).XmlNodeKey; + + string fieldModelPath = typeof(GravityFieldModel).GetCustomAttributes().FirstOrDefault(a => a.CustomData.Equals("Default"))?.XmlNodePath; + string sysFieldModelPath = typeof(GravityFieldModel).GetCustomAttributes().FirstOrDefault(a => a.CustomData.Equals("System"))?.XmlNodePath; + + Name = rdoObjectNode[nameKey].InnerText.ToDotNetNameFormat(); + Guid = rdoObjectNode[guidKey].InnerText; + GravityFields = new List(); + GravityChoices = new List(); + + int.TryParse(rdoObjectNode[descriptorObjIdKey].InnerText, out int descriptorObjId); + DescriptorArtifactTypeId = descriptorObjId > 0 ? descriptorObjId : (int?)null; + + int.TryParse(rdoObjectNode[parentObjIdKey].InnerText, out int parentObjId); + ParentArtifactTypeId = parentObjId > 0 ? parentObjId : (int?)null; + + XmlNodeList fieldsForObject = rdoObjectNode.SelectNodes(fieldModelPath); + XmlNodeList sysFieldsForObject = rdoObjectNode.SelectNodes(sysFieldModelPath); + + GravityFieldModel fieldModel; + + foreach (XmlNode field in fieldsForObject) + { + fieldModel = new GravityFieldModel(field); + GravityFields.Add(fieldModel); + + if (fieldModel.RdoFieldType == RdoFieldType.SingleChoice + || fieldModel.RdoFieldType == RdoFieldType.MultipleChoice) + { + GravityChoices.Add(new GravityChoiceModel(field)); + } + } + + foreach (XmlNode sysField in sysFieldsForObject) + { + fieldModel = new GravityFieldModel(sysField, true); + + if (fieldModel.AssociativeArtifactTypeId.HasValue + || Constants.AllowedRelativitySystemFields.Contains(fieldModel.Name)) + { + GravityFields.Add(fieldModel); + } + } + } + + [XmlNodeKey("Name")] + internal string Name { get; private set; } + + [XmlNodeKey("Guid")] + internal string Guid { get; private set; } + + [XmlNodeKey("ParentArtifactTypeId")] + internal int? ParentArtifactTypeId { get; set; } + + [XmlNodeKey("DescriptorArtifactTypeId")] + internal int? DescriptorArtifactTypeId { get; set; } + + internal List GravityFields { get; set; } + + internal List GravityChoices { get; set; } + + public NetModel ConvertToDotNet() + { + List attributes = new List() + { + // Set Gravity Attributes.. + $"[Serializable()]", + $"[RelativityObject(\"{Guid}\")]" + }; + + List properties = new List(); + properties.AddRange(GravityFields.OrderByDescending(f => f.IsSystemField).Select(f => f.ConvertToDotNet())); + + return new NetModel("ModelGenerationTool.Test", attributes, Name, properties, "public", null, new List() { "System", "Gravity.Base", "System.Collections.Generic" }, new List() { "BaseDto" }); + } + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableClass.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableClass.cs new file mode 100644 index 0000000..1a4d034 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableClass.cs @@ -0,0 +1,7 @@ +namespace ModelGenerationTool.Models.NET.Base +{ + internal interface INetParsableClass + { + NetModel ConvertToDotNet(); + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableFlag.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableFlag.cs new file mode 100644 index 0000000..773f5fe --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableFlag.cs @@ -0,0 +1,7 @@ +namespace ModelGenerationTool.Models.NET.Base +{ + internal interface INetParsableFlag + { + NetFlag ConvertToDotNet(); + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableProperty.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableProperty.cs new file mode 100644 index 0000000..0f365c4 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/Base/INetParsableProperty.cs @@ -0,0 +1,7 @@ +namespace ModelGenerationTool.Models.NET.Base +{ + internal interface INetParsableProperty + { + NetProperty ConvertToDotNet(); + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetFlag.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetFlag.cs new file mode 100644 index 0000000..b7ed101 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetFlag.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +namespace ModelGenerationTool.Models.NET +{ + internal class NetFlag + { + /// + /// Constructor for .NET enumeration flags. + /// + /// .NET enum flag attributes. + /// .NET enum flag name. + /// .NET enum flag value. + internal NetFlag(List attributes, string name, string value) + { + Attributes = attributes; + Name = name; + Value = value; + } + + internal List Attributes { get; private set; } + + internal string Name { get; private set; } + + internal string Value { get; private set; } + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetItemType.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetItemType.cs new file mode 100644 index 0000000..89e2ae0 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetItemType.cs @@ -0,0 +1,10 @@ +namespace ModelGenerationTool.Models.NET +{ + internal enum NetItemType + { + Struct = 1, + Enum = 2, + Interface = 3, + Class = 4 + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetModel.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetModel.cs new file mode 100644 index 0000000..2bce279 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetModel.cs @@ -0,0 +1,83 @@ +using System.Collections.Generic; + +namespace ModelGenerationTool.Models.NET +{ + internal class NetModel + { + /// + /// Constructor for .NET class models. + /// + /// .NET class namespace. + /// .NET class attributes. + /// .NET class name. + /// .NET class properties. + /// .NET class additional keyword. For example - "abstract", "static", etc. + /// .NET class access modifier. For example "public". + /// .NET class usings. For example {"System", "System.Collections.Generic"} + /// .NET class parents. For example {"BaseClass", "IMyInterface"} + internal NetModel(string _namespace, List attributes, string name, List properties, + string additionalKeyword = null, + string accessModifier = null, + List usings = null, + List inherits = null) + : this(_namespace, attributes, name, additionalKeyword, accessModifier, usings, inherits) + { + Type = NetItemType.Class; + Properties = properties; + } + + /// + /// Constructor for .NET enumeration models. + /// + /// .NET enumeration namespace. + /// .NET enumeration attributes. + /// .NET enumeration name. + /// .NET enumeration flags. + /// .NET enumeration access modifier. For example "public". + /// .NET enumeration usings. For example {"System", "System.Collections.Generic"} + internal NetModel(string _namespace, List attributes, string name, List flags, + string accessModifier = null, + List usings = null) + : this(_namespace, attributes, name, null, accessModifier, usings, null) + { + Type = NetItemType.Enum; + Flags = flags; + } + + private NetModel(string _namespace, List attributes, string name, + string additionalKeyword = null, + string accessModifier = null, + List usings = null, + List inherits = null) + { + Namespace = _namespace; + Attributes = attributes; + Name = name; + + AdditionalKeyword = additionalKeyword; + AccessModifier = accessModifier; + Usings = usings; + Inherits = inherits; + } + + internal string Namespace { get; private set; } + + internal List Attributes { get; private set; } + + internal NetItemType Type { get; private set; } + + internal string Name { get; private set; } + + internal List Properties { get; private set; } + + internal List Flags { get; private set; } + + internal string AdditionalKeyword { get; private set; } + + internal List Usings { get; private set; } + + internal List Inherits { get; private set; } + + internal string AccessModifier { get; private set; } + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetProperty.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetProperty.cs new file mode 100644 index 0000000..3d94d6c --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Models/NET/NetProperty.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; + +namespace ModelGenerationTool.Models.NET +{ + internal class NetProperty + { + /// + /// Constructor for .NET class properties. + /// + /// .NET class property attributes. + /// .NET class property name. + /// .NET class property type. + /// .NET class property additional keyword. For example - "abstract", "static", etc. + /// .NET class property access modifier. For example - "public". + /// .NET class property get access modifier. For example - "private". + /// .NET class property set access modifier. For example - "private". + /// .NET class property value. For example - "new List()". + internal NetProperty(List attributes, string name, Type type, + string additionalKeyword = null, + string accessModifier = "public", + string getModifier = "public", + string setModifier = "public", + string value = null) + : this(attributes, name, additionalKeyword, accessModifier, getModifier, setModifier, value) + { + Type = type; + } + + /// + /// Constructor for .NET class properties. + /// + /// .NET class property attributes. + /// .NET class property name. + /// .NET class property type name. For example "MyCustomClass". + /// .NET class property additional keyword. For example - "abstract", "static", etc. + /// .NET class property access modifier. For example - "public". + /// .NET class property get access modifier. For example - "private". + /// .NET class property set access modifier. For example - "private". + /// .NET class property value. For example - "new List()". + internal NetProperty(List attributes, string name, string typeName, + string additionalKeyword = null, + string accessModifier = "public", + string getModifier = "public", + string setModifier = "public", + string value = null) + : this(attributes, name, additionalKeyword, accessModifier, getModifier, setModifier, value) + { + TypeName = typeName; + } + + private NetProperty(List attributes, string name, + string additionalKeyword = null, + string accessModifier = "public", + string getModifier = "public", + string setModifier = "public", + string value = null) + { + Attributes = attributes; + Name = name; + + AdditionalKeyword = additionalKeyword; + AccessModifier = accessModifier; + GetAccessModifier = getModifier; + SetAccessModifier = setModifier; + Value = value; + } + + internal List Attributes { get; private set; } + + internal string Name { get; private set; } + + internal Type Type { get; private set; } + + internal string TypeName { get; private set; } + + internal string AdditionalKeyword { get; private set; } + + internal string AccessModifier { get; private set; } + + internal string GetAccessModifier { get; private set; } + + internal string SetAccessModifier { get; private set; } + + internal string Value { get; private set; } + } +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Properties/AssemblyInfo.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b2ebdab --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ModelGenerationTool")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ModelGenerationTool")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("6cfc0187-3447-4d9c-a931-fa6500b05eb2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpClass.txt b/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpClass.txt new file mode 100644 index 0000000..349c408 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpClass.txt @@ -0,0 +1,8 @@ +%usings% + +namespace %namespace% +{ +%attributes% +%access_modifier% %additional_keyword% class %name% %inherits% + {%properties%} +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpEnum.txt b/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpEnum.txt new file mode 100644 index 0000000..d493806 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpEnum.txt @@ -0,0 +1,7 @@ +%usings% + +namespace %namespace% +{%attributes% +%access_modifier% enum %name% + {%flags%} +} \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpEnumFlag.txt b/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpEnumFlag.txt new file mode 100644 index 0000000..e1d4344 --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpEnumFlag.txt @@ -0,0 +1,3 @@ + +%attributes% +%name% %value% \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpInterface.txt b/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpInterface.txt new file mode 100644 index 0000000..e69de29 diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpProperty.txt b/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpProperty.txt new file mode 100644 index 0000000..aca47cc --- /dev/null +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpProperty.txt @@ -0,0 +1,3 @@ + +%attributes% +%access_modifier% %type% %name% %get_modifier% %set_modifier% %value% \ No newline at end of file diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpStruct.txt b/Gravity/Model Generation Tool/ModelGenerationTool/Resources/CSharpStruct.txt new file mode 100644 index 0000000..e69de29 From 4b20718ff988a1d29b06ef5438c26b0e47dce744 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 31 May 2019 13:42:53 +0300 Subject: [PATCH 2/2] Fixed a small defect where SystemObject fields were causing errors. --- .../Factories/Internal/GravityRdoFactory.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/GravityRdoFactory.cs b/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/GravityRdoFactory.cs index de7b450..b74945b 100644 --- a/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/GravityRdoFactory.cs +++ b/Gravity/Model Generation Tool/ModelGenerationTool/Factories/Internal/GravityRdoFactory.cs @@ -49,12 +49,12 @@ private void PopulateObjectFields(List models) foreach (var objField in objectFields) { - string descriptorObjName = models.First(m => m.DescriptorArtifactTypeId == objField.AssociativeArtifactTypeId.Value)?.Name; - var associatedObjs = model.GravityFields.Where(f => f.AssociativeArtifactTypeId == objField.AssociativeArtifactTypeId.Value); + string descriptorObjName = models.FirstOrDefault(m => m.DescriptorArtifactTypeId == objField.AssociativeArtifactTypeId.Value)?.Name; + var associatedObjs = model.GravityFields.Where(f => f.AssociativeArtifactTypeId == objField.AssociativeArtifactTypeId.Value).ToList(); foreach (var associatedObj in associatedObjs) { - associatedObj.Name = descriptorObjName; + associatedObj.Name = descriptorObjName ?? associatedObj.Name; } } }