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