using System; using System.Collections; using System.Collections.Generic; using System.Data.Entity; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Tango.CodeGeneration; using Tango.DAL.Remote.DB; using Tango.Settings; using Humanizer; using System.Globalization; using Tango.Core; using System.Data; using System.Diagnostics; using static Tango.Core.Components.DataBaseDescriptionsHelper; using System.Threading; using Newtonsoft.Json; namespace Tango.DBObservablesGenerator.CLI { /// /// Generates observable entities code files. /// public class ObservablesGenerator { /// /// Generates C# code files. /// /// The target path. public void GenerateCSharp(String targetPath) { List dbDescriptions = new List(); List foreign_keys = new List(); //Get column descriptions... using (RemoteDB db = new RemoteDB(SettingsManager.Default.GetOrCreate().DataSource)) { db.Configuration.LazyLoadingEnabled = false; db.Database.Connection.Open(); dbDescriptions = Core.Components.DataBaseDescriptionsHelper.GetDescriptions(db.Database.Connection); foreign_keys = Core.Components.DataBaseDescriptionsHelper.GetForeignKeys(db.Database.Connection); } //Generate Entities and DTOs... foreach (var table in typeof(RemoteDB).GetProperties().Where(x => typeof(IEnumerable).IsAssignableFrom(x.PropertyType))) { Console.WriteLine("Generating table '" + table + "'..."); String table_description = null; var db_des = dbDescriptions.FirstOrDefault(x => x.TableName == table.Name); if (db_des != null && !String.IsNullOrWhiteSpace(db_des.TableDescription)) { table_description = db_des.TableDescription; } EntityCodeFile codeFile = new EntityCodeFile((table.Name == "TECH_VALVES" ? "TechValve" : DalNameToStandardName(table.Name).SingularizeMVC()) + "Base") { EntityName = table.Name.SingularizeMVC(), TableName = table.Name, Description = table_description, }; EntityDTOCodeFile dtoCodeBase = new EntityDTOCodeFile(); dtoCodeBase.Name = codeFile.Name.Replace("Base", "DTOBase"); dtoCodeBase.Description = codeFile.Description; dtoCodeBase.ObservableType = codeFile.Name.Replace("Base", ""); dtoCodeBase.InheritedType = dtoCodeBase.Name.Replace("Base", ""); List guessed_keys = table.PropertyType.GenericTypeArguments.First().GetProperties().Skip(3).Where(x => x.PropertyType == typeof(String)).Where(x => x.Name.ToLower().Contains("guid")).Select(x => DalNameToStandardName(x.Name).SingularizeMVC().Replace("Guid", "")).OrderBy(x => x).ToList(); List foreignKeys = foreign_keys.Where(x => x.TableName == table.Name).Select(x => DalNameToStandardName(x.ColumnName).SingularizeMVC().Replace("Guid", "")).OrderBy(x => x).ToList(); String t_name = table.Name; if (guessed_keys.Count != foreignKeys.Count) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"Suspicious entry at {table.Name}."); for (int i = 0; i < Math.Max(guessed_keys.Count, foreignKeys.Count); i++) { if (i < guessed_keys.Count) { Console.Write(guessed_keys[i]); } Console.Write(" <=> "); if (i < foreignKeys.Count) { Console.Write(foreignKeys[i]); } Console.WriteLine(); } Console.ForegroundColor = ConsoleColor.Gray; //Thread.Sleep(2000); } foreach (var field in table.PropertyType.GenericTypeArguments.First().GetProperties().Skip(3)) { EntityCodeFileField codeField = new EntityCodeFileField(); codeField.FieldName = field.Name; codeField.Name = DalNameToStandardName(field.Name); codeField.Description = field.Name.Replace("_", " ").ToLower(); String column_description = null; var column_des = dbDescriptions.FirstOrDefault(x => x.TableName == table.Name && x.ColumnName == field.Name); if (column_des != null) { column_description = column_des.ColumnDescription; } if (column_description != null) { DbPropertyExtensionModel dbPropertyExtensionModel = null; try { dbPropertyExtensionModel = JsonConvert.DeserializeObject(column_description, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, MissingMemberHandling = MissingMemberHandling.Ignore, }); } catch { } if (dbPropertyExtensionModel != null) { codeField.PropertyExtension = dbPropertyExtensionModel; if (dbPropertyExtensionModel.Description != null) { codeField.DbDescription = dbPropertyExtensionModel.Description.ToLines().Select(x => "/// " + x).Join(Environment.NewLine); } } else { codeField.DbDescription = column_description.ToLines().Select(x => "/// " + x).Join(Environment.NewLine); } } if (field.PropertyType.IsGenericType) { if (field.PropertyType == typeof(Nullable)) { codeField.Type = String.Format("Nullable<{0}>", "DateTime"); } else if (field.PropertyType == typeof(Nullable)) { codeField.Type = String.Format("Nullable<{0}>", "Int32"); } else if (field.PropertyType == typeof(Nullable)) { codeField.Type = String.Format("Nullable<{0}>", "Double"); } else { codeField.Type = String.Format("SynchronizedObservableCollection<{0}>", DalNameToStandardName(field.PropertyType.GenericTypeArguments.Single().Name).SingularizeMVC()); codeField.Construct = true; } } else { if (field.PropertyType.IsClass && field.PropertyType != typeof(String) && field.PropertyType != typeof(byte[])) { codeField.Type = DalNameToStandardName(field.PropertyType.Name).SingularizeMVC(); codeField.Name = codeField.Type; codeField.XmlIgnore = true; var fk = foreignKeys.FirstOrDefault(x => x.Contains(codeField.Name)); if (fk != null) { codeField.Name = fk; foreignKeys.Remove(fk); } codeField.Complex = true; } else { codeField.Type = field.PropertyType.Name; if (foreignKeys.Contains(codeField.Name.Replace("Guid", ""))) { codeField.IsForeignKey = true; codeField.ForeignKeyName = codeField.Name.Replace("Guid", ""); } } } codeFile.Fields.Add(codeField); if (field.PropertyType.IsPrimitive || field.PropertyType.IsValueType || field.PropertyType == typeof(String) || field.PropertyType == typeof(byte[])) { dtoCodeBase.Properties.Add(new Property() { Type = codeField.Type, Name = codeField.Name, Description = codeField.Description, }); } } String code = codeFile.GenerateCode(); String entitiesPath = Path.Combine(targetPath, "Entities"); Directory.CreateDirectory(entitiesPath); File.WriteAllText(Path.Combine(entitiesPath, codeFile.Name + ".cs"), code); if (!File.Exists(Path.Combine(entitiesPath, codeFile.Name + ".cs"))) { EntityInheritedCodeFile inherited = new EntityInheritedCodeFile(codeFile.Name.Replace("Base", ""), codeFile.Name); String inheritedCode = inherited.GenerateCode(); File.WriteAllText(Path.Combine(entitiesPath, inherited.Name + ".cs"), inheritedCode); } if (dtoCodeBase.Name != "SysdiagramDTOBase") { String dtoCode = dtoCodeBase.GenerateCode(); String dtoPath = Path.Combine(targetPath, "DTO"); Directory.CreateDirectory(dtoPath); File.WriteAllText(Path.Combine(dtoPath, dtoCodeBase.Name + ".cs"), dtoCode); String inheritedName = dtoCodeBase.Name.Replace("Base", ""); if (!File.Exists(Path.Combine(dtoPath, inheritedName + ".cs"))) { EntityInheritedDTOCodeFile inherited = new EntityInheritedDTOCodeFile(inheritedName, dtoCodeBase.Name); String inheritedCode = inherited.GenerateCode(); File.WriteAllText(Path.Combine(dtoPath, inherited.Name + ".cs"), inheritedCode); } } } //Generate Entities... //Generate Enumerations... using (RemoteDB db = new RemoteDB(SettingsManager.Default.GetOrCreate().DataSource)) { foreach (var tableProp in db.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType.IsGenericTypeAndNotNullable())) { try { var a = tableProp.PropertyType.GenericTypeArguments.FirstOrDefault(); var codeProp = tableProp.PropertyType.GenericTypeArguments.First().GetProperty("CODE"); var nameProp = tableProp.PropertyType.GenericTypeArguments.First().GetProperty("NAME"); var descriptionProp = tableProp.PropertyType.GenericTypeArguments.First().GetProperty("DESCRIPTION"); if (codeProp != null && nameProp != null) { EnumerationFile enumFile = new EnumerationFile(); enumFile.Name = DalNameToStandardName(tableProp.Name); Console.WriteLine("Generating enumeration '" + enumFile.Name + "'..."); foreach (var row in tableProp.GetValue(db) as IEnumerable) { EnumerationField field = new EnumerationField(); field.Name = nameProp.GetValue(row).ToString().Replace(" ", ""); field.Value = (int)codeProp.GetValue(row); if (descriptionProp != null) { field.Description = descriptionProp.GetValue(row).ToStringSafe(); } else { field.Description = nameProp.GetValue(row).ToString(); } enumFile.Fields.Add(field); } String enumerationsPath = Path.Combine(targetPath, "Enumerations"); Directory.CreateDirectory(enumerationsPath); String code = enumFile.GenerateCode(); File.WriteAllText(Path.Combine(enumerationsPath, enumFile.Name + ".cs"), code); } } catch (Exception ex) { } } } //Generate Enumerations... //Generate Observables Adapter Extensions... Console.WriteLine("Generating Observables Adapter..."); ObservablesAdapterFile adapterFile = new ObservablesAdapterFile(); adapterFile.Name = "ObservablesEntitiesAdapter"; foreach (var table in typeof(RemoteDB).GetProperties().Where(x => typeof(IEnumerable).IsAssignableFrom(x.PropertyType))) { String tName = table.PropertyType.GenericTypeArguments.Single().Name; adapterFile.Properties.Add(new Property() { Name = DalNameToStandardName(table.Name), Type = String.Format("ObservableCollection<{0}>", tName == "TECH_VALVES" ? "TechValve" : DalNameToStandardName(tName).SingularizeMVC()), }); } String adapterCode = adapterFile.GenerateCode(); File.WriteAllText(Path.Combine(targetPath, "ObservablesEntitiesAdapterExtension.cs"), adapterCode); //Generate Observables Adapter Extensions... //Generate Observables Static Collections... Console.WriteLine("Generating Observables Static Collections..."); ObservablesStaticCollectionsFile collectionsFile = new ObservablesStaticCollectionsFile(); collectionsFile.Name = "ObservablesStaticCollections"; foreach (var table in typeof(RemoteDB).GetProperties().Where(x => typeof(IEnumerable).IsAssignableFrom(x.PropertyType))) { String tName = table.PropertyType.GenericTypeArguments.Single().Name; collectionsFile.Properties.Add(new Property() { Name = DalNameToStandardName(table.Name), Type = String.Format("ObservableCollection<{0}>", tName == "TECH_VALVES" ? "TechValve" : DalNameToStandardName(tName).SingularizeMVC()), }); } String collectionsCode = collectionsFile.GenerateCode(); File.WriteAllText(Path.Combine(targetPath, "ObservablesStaticCollectionsExtension.cs"), collectionsCode); //Generate Observables Static Collections... //Generate Observables Context Console.WriteLine("Generating Observables DB Context..."); ObservablesContextCodeFile contextFile = new ObservablesContextCodeFile(); contextFile.Name = "ObservablesContext"; foreach (var table in typeof(RemoteDB).GetProperties().Where(x => typeof(IEnumerable).IsAssignableFrom(x.PropertyType))) { String tName = table.PropertyType.GenericTypeArguments.Single().Name; contextFile.Properties.Add(new Property() { Name = DalNameToStandardName(table.Name), Type = String.Format("DbSet<{0}>", tName == "TECH_VALVES" ? "TechValve" : DalNameToStandardName(tName).SingularizeMVC()), }); } String contextCode = contextFile.GenerateCode(); File.WriteAllText(Path.Combine(targetPath, "ObservablesContext.cs"), contextCode); //Generate Observables Context } /// /// Generates Java code files. /// /// The target path. public void GenerateJava(String targetPath) { //Generate Entities... foreach (var table in typeof(RemoteDB).GetProperties().Where(x => typeof(IEnumerable).IsAssignableFrom(x.PropertyType))) { EntityCodeFileJava codeFile = new EntityCodeFileJava(DalNameToStandardName(table.Name).Singularize(false) + "Base") { EntityName = table.Name.Singularize(false), TableName = table.Name, }; EntityCodeFileJavaExtension extensionCodeFile = new EntityCodeFileJavaExtension(DalNameToStandardName(table.Name).Singularize(false), codeFile.Name) { TableName = table.Name }; foreach (var field in table.PropertyType.GenericTypeArguments.First().GetProperties().Skip(3).Where(x => !x.Name.Contains("GUID"))) { String name = field.Name; if (name.ToLower().StartsWith("set_")) { name = name.Remove(0, 4); } EntityCodeFileField codeField = new EntityCodeFileField(); codeField.FieldName = field.Name; codeField.Name = DalNameToStandardName(name); codeField.Description = FirstCharacterToLower(DalNameToStandardName(name)); if (field.PropertyType.IsGenericTypeAndNotNullable()) { continue; } else { if (field.PropertyType.IsClass && field.PropertyType != typeof(String) && field.PropertyType != typeof(Byte[])) { codeField.Type = DalNameToStandardName(field.PropertyType.Name).Singularize(false); codeField.Construct = true; codeField.FieldName = codeField.FieldName.Singularize(false).ToUpper(); codeField.Description = codeField.Description.Singularize(false); codeField.Name = codeField.Type; } else if (field.PropertyType == typeof(Byte[]) || field.PropertyType == typeof(Boolean) || field.PropertyType == typeof(Double)) { codeField.Type = field.PropertyType.Name.ToLower(); } else { codeField.Type = field.PropertyType.Name == "Int32" ? "int" : field.PropertyType.Name; } } codeFile.Fields.Add(codeField); } codeFile.IndentResult = false; extensionCodeFile.IndentResult = false; String code = codeFile.GenerateCode(); String extensionCode = extensionCodeFile.GenerateCode(); String entitiesPath = Path.Combine(targetPath, "entities"); Directory.CreateDirectory(entitiesPath); File.WriteAllText(Path.Combine(entitiesPath, codeFile.Name + ".java"), code); String extensionCodeFilePath = Path.Combine(entitiesPath, extensionCodeFile.Name + ".java"); if (!File.Exists(extensionCodeFilePath)) { File.WriteAllText(extensionCodeFilePath, extensionCode); } } //Generate Entities... //Generate Enumerations... using (RemoteDB db = new RemoteDB(SettingsManager.Default.GetOrCreate().DataSource)) { foreach (var tableProp in db.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType.IsGenericTypeAndNotNullable())) { try { var a = tableProp.PropertyType.GenericTypeArguments.FirstOrDefault(); var codeProp = tableProp.PropertyType.GenericTypeArguments.First().GetProperty("CODE"); var nameProp = tableProp.PropertyType.GenericTypeArguments.First().GetProperty("NAME"); var descriptionProp = tableProp.PropertyType.GenericTypeArguments.First().GetProperty("DESCRIPTION"); if (codeProp != null && nameProp != null) { EnumerationFileJava enumFile = new EnumerationFileJava(); enumFile.Name = DalNameToStandardName(tableProp.Name); foreach (var row in tableProp.GetValue(db) as IEnumerable) { EnumerationField field = new EnumerationField(); field.Name = nameProp.GetValue(row).ToString().Replace(" ", ""); field.Value = (int)codeProp.GetValue(row); if (descriptionProp != null) { field.Description = descriptionProp.GetValue(row).ToString(); } else { field.Description = nameProp.GetValue(row).ToString(); } enumFile.Fields.Add(field); } String enumerationsPath = Path.Combine(targetPath, "enumerations"); Directory.CreateDirectory(enumerationsPath); String code = enumFile.GenerateCode(); File.WriteAllText(Path.Combine(enumerationsPath, enumFile.Name + ".java"), code); } } catch { } } } //Generate Enumerations... //Generate DAO... TangoDAOJavaFile daoFile = new TangoDAOJavaFile(); daoFile.Name = "TangoDAO"; foreach (var table in typeof(RemoteDB).GetProperties().Where(x => typeof(IEnumerable).IsAssignableFrom(x.PropertyType))) { daoFile.Entities.Add(new TangoDAOJavaFile.TangoDAOEntity() { Name = DalNameToStandardName(table.Name).Singularize(false), TableName = DalNameToStandardName(table.Name), }); } String daoCode = daoFile.GenerateCode(); String daoFolder = Path.Combine(targetPath, "dao"); Directory.CreateDirectory(daoFolder); File.WriteAllText(Path.Combine(daoFolder, "TangoDAO.java"), daoCode); //Generate DAO... } /// /// Lower case the first character of a string. /// /// The string. /// private static string FirstCharacterToLower(string str) { if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0)) return str; return Char.ToLowerInvariant(str[0]) + str.Substring(1); } /// /// Converts the specified database conventional name to the observables conventional name. /// /// DAL name. /// private static String DalNameToStandardName(String dalName) { return String.Join("", dalName.Split('_').Select(x => ToTitleCase(x))); } /// /// Converts the specified text to title case. /// /// The text. /// private static string ToTitleCase(string text) { return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(text.ToLower()); } } }