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..b74945b
--- /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.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;
+ }
+ }
+ }
+ }
+
+ 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