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;
namespace Tango.DBObservablesGenerator.CLI
{
/// <summary>
/// Generates observable entities code files.
/// </summary>
public class ObservablesGenerator
{
/// <summary>
/// Generates C# code files.
/// </summary>
/// <param name="targetPath">The target path.</param>
public void GenerateCSharp(String targetPath)
{
List<DbDescription> dbDescriptions = new List<DbDescription>();
//Get column descriptions...
using (RemoteDB db = new RemoteDB(SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource))
{
db.Configuration.LazyLoadingEnabled = false;
db.Database.Connection.Open();
dbDescriptions = Core.Components.DataBaseDescriptionsHelper.GetDescriptions(db.Database.Connection);
}
//Generate Entities...
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)
{
table_description = db_des.TableDescription;
}
EntityCodeFile codeFile = new EntityCodeFile(DalNameToStandardName(table.Name).SingularizeMVC())
{
EntityName = table.Name.SingularizeMVC(),
TableName = table.Name,
Description = table_description,
};
List<String> foreignKeys = 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", "")).ToList();
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)
{
codeField.DbDescription = column_description.ToLines().Select(x => "/// " + x).Join(Environment.NewLine);
}
if (field.PropertyType.IsGenericType)
{
if (field.PropertyType == typeof(Nullable<DateTime>))
{
codeField.Type = String.Format("Nullable<{0}>", "DateTime");
}
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.SingleOrDefault(x => x.Contains(codeField.Name));
if (fk != null)
{
codeField.Name = fk;
}
codeField.Complex = true;
}
else
{
codeField.Type = field.PropertyType.Name;
if (codeField.Name.EndsWith("Guid"))
{
codeField.IsForeignKey = true;
codeField.ForeignKeyName = codeField.Name.Replace("Guid", "");
}
}
}
codeFile.Fields.Add(codeField);
}
String code = codeFile.GenerateCode();
String entitiesPath = Path.Combine(targetPath, "Entities");
Directory.CreateDirectory(entitiesPath);
File.WriteAllText(Path.Combine(entitiesPath, codeFile.Name + ".cs"), code);
}
//Generate Entities...
//Generate Enumerations...
using (RemoteDB db = new RemoteDB(SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource))
{
foreach (var tableProp in db.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType.IsGenericType))
{
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).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 + ".cs"), code);
}
}
catch { }
}
}
//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)))
{
adapterFile.Properties.Add(new Property()
{
Name = DalNameToStandardName(table.Name),
Type = String.Format("ObservableCollection<{0}>", DalNameToStandardName(table.PropertyType.GenericTypeArguments.Single().Name).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)))
{
collectionsFile.Properties.Add(new Property()
{
Name = DalNameToStandardName(table.Name),
Type = String.Format("ObservableCollection<{0}>", DalNameToStandardName(table.PropertyType.GenericTypeArguments.Single().Name).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)))
{
contextFile.Properties.Add(new Property()
{
Name = DalNameToStandardName(table.Name),
Type = String.Format("DbSet<{0}>", DalNameToStandardName(table.PropertyType.GenericTypeArguments.Single().Name).SingularizeMVC()),
});
}
String contextCode = contextFile.GenerateCode();
File.WriteAllText(Path.Combine(targetPath, "ObservablesContext.cs"), contextCode);
//Generate Observables Context
}
/// <summary>
/// Generates Java code files.
/// </summary>
/// <param name="targetPath">The target path.</param>
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.IsGenericType)
{
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<CoreSettings>().DataSource))
{
foreach (var tableProp in db.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType.IsGenericType))
{
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...
}
/// <summary>
/// Lower case the first character of a string.
/// </summary>
/// <param name="str">The string.</param>
/// <returns></returns>
private static string FirstCharacterToLower(string str)
{
if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
return str;
return Char.ToLowerInvariant(str[0]) + str.Substring(1);
}
/// <summary>
/// Converts the specified database conventional name to the observables conventional name.
/// </summary>
/// <param name="dalName">DAL name.</param>
/// <returns></returns>
private static String DalNameToStandardName(String dalName)
{
return String.Join("", dalName.Split('_').Select(x => ToTitleCase(x)));
}
/// <summary>
/// Converts the specified text to title case.
/// </summary>
/// <param name="text">The text.</param>
/// <returns></returns>
private static string ToTitleCase(string text)
{
return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(text.ToLower());
}
}
}