using System;
using System.Collections;
using System.Text;
using System.Data;
using SubSonic.Utilities;
using System.Diagnostics;
namespace SubSonic
{
public class CodeGeneration
{
private static string tableList = "*";
//private const string PROPERTY_TEMPLATE = "propTemplate";
//private const string CLASS_TEMPLATE = "classTemplate";
//private const string COLLECTION_TEMPLATE = "collectionTemplate";
//private const string ODS_INSERT = "odsInsert";
//private const string ODS_UPDATE = "odsUpdate";
//private const string DEFAULT_NAMESPACE = "";
#region Public Methods
public static void EnsureProviderLoad()
{
DataService.LoadProviders();
}
#region Usings
public static string GetUsingStatements(LanguageType languageType)
{
if (languageType == LanguageType.CSharp)
{
return ResourceHelper.GetString(TemplateName.CLASS_USINGS) + Environment.NewLine + Environment.NewLine;
}
else if (languageType == LanguageType.VB)
{
return ResourceHelper.GetString(TemplateName.CLASS_USINGS_VB) + Environment.NewLine + Environment.NewLine;
}
return String.Empty;
}
#endregion
#region Scaffolds
public static string GenerateScaffold(string table, LanguageType languageType, DataProvider provider)
{
string template = String.Empty;
if (languageType == LanguageType.CSharp)
{
template = ResourceHelper.GetString(TemplateName.SCAFFOLD);
}
else if (languageType == LanguageType.VB)
{
template = ResourceHelper.GetString(TemplateName.SCAFFOLD_VB);
}
string result = template.Replace(TemplateVariable.TABLE_NAME, table);
result = result.Replace(TemplateVariable.PROVIDER, provider.Name);
return result;
}
public static string GenerateScaffold(string table, string masterPageFile, LanguageType languageType, DataProvider provider)
{
string template = String.Empty;
if (languageType == LanguageType.CSharp)
{
template = ResourceHelper.GetString(TemplateName.SCAFFOLD_MASTER_PAGE);
}
else if (languageType == LanguageType.VB)
{
template = ResourceHelper.GetString(TemplateName.SCAFFOLD_MASTER_PAGE_VB);
}
string result = template.Replace(TemplateVariable.TABLE_NAME, table).Replace(TemplateVariable.MASTER_PAGE, masterPageFile);
result = result.Replace(TemplateVariable.PROVIDER, provider.Name);
return result;
}
#endregion
#region Classes
public static string GenerateClass(string tableName, StringBuilder generatedTableList, LanguageType languageType, DataProvider provider)
{
tableList = generatedTableList.ToString();
CodeGenerationArgs args = new CodeGenerationArgs();
args.TableName = tableName;
args.Namespace = GetNameSpace(provider);
args.Language = languageType;
return GetClass(args, provider) + Environment.NewLine;
}
public static string GenerateClasses(DataProvider provider, string tables, LanguageType languageType)
{
tableList = tables;
//make sure everything's loaded properly
DataService.LoadProviders();
//set the provider for this class
//to the provider that was passed in
//set the SubSonicConfig.ProviderName - this will ensure that we get schema from the proper DB
StringBuilder sOut = new StringBuilder();
string[] tbls = DataService.GetTableNames(provider.Name);
foreach(string tbl in tbls)
{
if(isInList(tbl))
{
CodeGenerationArgs args = new CodeGenerationArgs();
args.TableName = tbl;
args.Namespace = GetNameSpace(provider);
args.Language = languageType;
sOut.AppendLine(GetClass(args, provider));
}
}
string result = sOut.ToString();
return result;
}
public static string GenerateClasses(string tables, LanguageType languageType, DataProvider provider)
{
tableList = tables;
//make sure everything's loaded properly
DataService.LoadProviders();
string result = GenerateClasses(provider, tableList, languageType);
return result;
}
public static string GenerateClass(string table, LanguageType languageType, DataProvider provider)
{
return GenerateClasses(table, languageType, provider);
}
//TODO: Why are there two similar GenerateClass methods?
// One should be an override of the other if necessary.
public static string GenerateClass(string table, string nameSpace, LanguageType languageType, DataProvider provider)
{
tableList = table;
CodeGenerationArgs args = new CodeGenerationArgs();
args.TableName = table;
args.Namespace = nameSpace;
args.Language = languageType;
return GetClass(args, provider) + Environment.NewLine;
}
/// <summary>
/// this method can't be used with the build provider nor class generators since it would cause a doubling of using statements
/// </summary>
public static string GenerateClass(string table, string className, string nameSpace, LanguageType languageType, DataProvider provider)
{
tableList = table;
string usings = GetUsingStatements(languageType);
CodeGenerationArgs args = new CodeGenerationArgs();
args.TableName = table;
args.Namespace = nameSpace;
args.Language = languageType;
args.ClassName = className;
string classCode = GetClass(args, provider);
string result = usings + Environment.NewLine + Environment.NewLine + classCode;
return result;
}
#endregion
#region Enums
public static string GenerateEnums(LanguageType languageType)
{
string enums = String.Empty;//GetEnums();//GetEnums_VB();
return enums;
}
#endregion
#region SPs
public static string GenerateSPs(LanguageType languageType, string nameSpace, DataProvider provider)
{
return GenerateSPs(languageType, nameSpace, true, provider);
}
public static string GenerateSPs(LanguageType languageType, DataProvider provider)
{
return GenerateSPs(languageType, true, provider);
}
public static string GenerateSPs(LanguageType languageType, bool useConfig, DataProvider provider)
{
return GenerateSPs(languageType, provider.GeneratedNamespace, useConfig, provider);
}
public static string GenerateSPs(LanguageType languageType, string nameSpace, bool useConfig, DataProvider provider)
{
string find = provider.SPStartsWith;
string replaceWith = provider.AppendWith;
string spClassName = provider.SPClassName.Replace(" ", String.Empty).Trim();
if (String.IsNullOrEmpty(spClassName))
{
spClassName = ClassName.STORED_PROCEDURES;
}
StringBuilder sOut = new StringBuilder();
// If useConfig is false, we don't use the configuration
// setting and always generate the code. Used for
// dynamic code generation that doesn't rely on web.config
if (!useConfig || provider.UseSPs)
{
if (languageType == LanguageType.CSharp)
{
if (!String.IsNullOrEmpty(nameSpace))
{
sOut.AppendLine();
sOut.AppendLine("namespace " + nameSpace);
sOut.AppendLine("{");
sOut.AppendLine();
sOut.AppendLine();
}
sOut.AppendLine("public class " + spClassName);
sOut.AppendLine("{");
sOut.AppendLine(GetSPs(find, replaceWith, languageType, provider));
sOut.AppendLine("}");
if (!String.IsNullOrEmpty(nameSpace))
{
sOut.AppendLine();
sOut.Append("}");
}
}
else if (languageType == LanguageType.VB)
{
if (!String.IsNullOrEmpty(nameSpace))
{
sOut.AppendLine();
sOut.AppendLine("Namespace " + nameSpace);
sOut.AppendLine();
sOut.AppendLine();
}
sOut.AppendLine("Public Class " + spClassName);
sOut.AppendLine();
sOut.Append(GetSPs(find, replaceWith, languageType, provider));
sOut.AppendLine("End Class");
if (!String.IsNullOrEmpty(nameSpace))
{
sOut.AppendLine();
sOut.AppendLine("End Namespace");
}
}
}
return sOut.ToString();
}
#endregion
#region Views
/// <summary>
/// Returns the Views as ReadOnly classes
/// </summary>
/// <returns></returns>
public static string GenerateViews(LanguageType languageType, DataProvider provider)
{
string sOut = String.Empty;
string[] views = DataService.GetViewNames(provider.Name);
foreach (string view in views)
{
if (Utility.StartsWith(view, provider.ViewStartsWith))
{
CodeGenerationArgs args = new CodeGenerationArgs();
args.TableName = view;
args.Namespace = GetNameSpace(provider);
args.Language = languageType;
args.IsReadOnly = true;
sOut += GetView(args, provider) + Environment.NewLine;
}
}
return sOut;
}
public static string GenerateView(string viewName, LanguageType languageType, DataProvider provider)
{
return GenerateView(GetNameSpace(provider), viewName, languageType, provider);
}
public static string GenerateView(string nameSpace, string viewName, LanguageType languageType, DataProvider provider)
{
CodeGenerationArgs args = new CodeGenerationArgs();
args.TableName = viewName;
args.Namespace = nameSpace;
args.Language = languageType;
return GetView(args, provider) + Environment.NewLine;
}
#endregion
#region Structs
public static string GenerateTableStruct(LanguageType languageType, DataProvider provider)
{
return GenerateTableStruct(languageType, provider.GeneratedNamespace, provider);
}
public static string GenerateTableStruct(LanguageType languageType, string nameSpace, DataProvider provider)
{
string[] tables = DataService.GetTableNames(provider.Name);
return BuildTablesStruct(tables, nameSpace, languageType, provider);
}
public static string GenerateViewStruct(LanguageType languageType, DataProvider provider)
{
return GenerateViewStruct(languageType, provider.GeneratedNamespace, provider);
}
public static string GenerateViewStruct(LanguageType languageType, string nameSpace, DataProvider provider)
{
string[] views = DataService.GetViewNames(provider.Name);
//check for multiple providers
string sOut = BuildViewsStruct(views, nameSpace, languageType, provider);
return sOut;
}
#endregion
#endregion
#region Private Methods
#region Namespace
static string GetNameSpace(DataProvider provider)
{
string result = null;
try
{
result = provider.GeneratedNamespace;
}
catch (Exception)
{
//TODO: We shouldn't swallow all exceptions!
//Isn't it best to fail if we can't do this?
//What exceptions can be throw here? P.H. -- 2007.02.16
}
if (String.IsNullOrEmpty(result))
{
result = "Subsonic.Generated";
}
return result;
}
#endregion
#region Bools
public static bool IsManyToMany(TableSchema.Table schema)
{
int keyCount = 0;
bool bOut = false;
foreach (TableSchema.TableColumn col in schema.Columns)
{
if (col.IsPrimaryKey)
keyCount++;
}
if (keyCount > 1)
{
bOut = true;
}
return bOut;
}
private static bool isInList(string tableName)
{
if (tableList.Trim() == "*")
{
return true;
}
else
{
//thanks chegan!
return (Environment.NewLine + tableList.ToLower() + Environment.NewLine).Contains(Environment.NewLine + tableName.ToLower() + Environment.NewLine);
}
}
private static string ReplaceTemplateValues(string template, string summary, string methodName, string methodType, string methodBody)
{
template = template.Replace(TemplateVariable.SUMMARY, summary);
template = template.Replace(TemplateVariable.METHOD_NAME, methodName);
template = template.Replace(TemplateVariable.METHOD_BODY, methodBody);
template = template.Replace(TemplateVariable.METHOD_TYPE, methodType) + Environment.NewLine;
return template;
}
#endregion
#region SPs
private static string GetSPs(string find, string replaceWith, LanguageType languageType, DataProvider provider)
{
//get the SP list from the DB
string[] SPs = DataService.GetSPList(provider.Name);
StringBuilder spList = new StringBuilder();
string spTemplate = String.Empty;
if (languageType == LanguageType.CSharp)
{
spTemplate = ResourceHelper.GetString(TemplateName.STORED_PROCEDURE);
}
else if (languageType == LanguageType.VB)
{
spTemplate = ResourceHelper.GetString(TemplateName.STORED_PROCEDURE_VB);
}
foreach (string sp in SPs)
{
if (!sp.StartsWith("dt_") && Utility.StartsWith(sp, provider.SPStartsWith))
{
string methodName;
Convention convention = new Convention(provider);
if (string.IsNullOrEmpty(find))
{
methodName = convention.SPName(sp, replaceWith);
}
else
{
methodName = convention.SPName(sp, find, replaceWith);
}
StringBuilder paramList = new StringBuilder();
StringBuilder argList = new StringBuilder();
//grab the parameters
IDataReader paramReader = DataService.GetSPParams(sp, provider.Name);
bool firstPass = true;
while (paramReader.Read())
{
//loop the params, pulling out the names and dataTypes
DbType dbType = DataService.GetDbType(paramReader[SqlSchemaVariable.DATA_TYPE].ToString(), provider.Name);
string Type = Utility.GetVariableType(dbType, languageType);
string paramName = paramReader[SqlSchemaVariable.NAME].ToString();
string arg = convention.ParameterName(paramName);
string dbTypeName = Enum.GetName(typeof(DbType), dbType);
string sMode = paramReader[SqlSchemaVariable.MODE].ToString();
//append to the arg list
if (!firstPass)
{
argList.Append(", ");
}
if (languageType == LanguageType.CSharp)
{
argList.Append(Type + " " + arg);
if (sMode == SqlSchemaVariable.MODE_INOUT)
{
//thanks to dmcgiv for this!
paramList.AppendLine("\tsp.Command.AddOutputParameter(\"" + paramName + "\",DbType." + dbTypeName + ");");
}
else
{
paramList.AppendLine("\tsp.Command.AddParameter(\"" + paramName + "\"," + arg + ", DbType." + dbTypeName + ");");
}
}
else if (languageType == LanguageType.VB)
{
argList.Append("ByVal " + arg + " As " + Type);
if (sMode == SqlSchemaVariable.MODE_INOUT)
{
paramList.AppendLine("\tsp.Command.AddOutputParameter(\"" + paramName + "\", DbType." + dbTypeName + ")");
}
else
{
paramList.AppendLine("\tsp.Command.AddParameter(\"" + paramName + "\"," + arg + ", DbType." + dbTypeName + ")");
}
}
firstPass = false;
}
paramReader.Close();
//put it all together
string spMethod;
spMethod = spTemplate.Replace(TemplateVariable.STORED_PROCEDURE_NAME, sp);
spMethod = spMethod.Replace(TemplateVariable.METHOD_NAME, methodName);
spMethod = spMethod.Replace(TemplateVariable.PARAMETERS, paramList.ToString());
spMethod = spMethod.Replace(TemplateVariable.ARGUMENT_LIST, argList.ToString());
spMethod = spMethod.Replace(TemplateVariable.PROVIDER, provider.Name);
spList.AppendLine(spMethod);
spList.AppendLine();
}
}
return spList.ToString();
}
#endregion
#region Views
private static string GetView(CodeGenerationArgs args, DataProvider provider)//string nameSpace, string viewName, LanguageType languageType, DataProvider provider)
{
//this is here for reverse-compat
return GetClass(args, provider);
}
#endregion
#region Classes
//an override for className
private static string GetClass(CodeGenerationArgs args, DataProvider provider)
{
string namespaceStart = String.Empty;
string namespaceEnd = String.Empty;
string classTemplate = String.Empty;
if (args.Language == LanguageType.CSharp)
{
namespaceStart = Environment.NewLine + "namespace " + args.Namespace + Environment.NewLine + "{" + Environment.NewLine;
namespaceEnd = Environment.NewLine + "}" + Environment.NewLine + Environment.NewLine;
if (args.IsReadOnly)
{
classTemplate = ResourceHelper.GetString(TemplateName.READ_ONLY_CLASS);
}
else
{
classTemplate = ResourceHelper.GetString(TemplateName.CLASS);
}
}
if (args.Language == LanguageType.VB)
{
if (args.IsReadOnly)
{
classTemplate = ResourceHelper.GetString(TemplateName.READ_ONLY_CLASS_VB);
}
else
{
classTemplate = ResourceHelper.GetString(TemplateName.CLASS_VB);
}
namespaceStart = Environment.NewLine + "Namespace " + args.Namespace + Environment.NewLine + Environment.NewLine;
namespaceEnd = "End Namespace" + Environment.NewLine + Environment.NewLine;
}
string sOut = String.Empty;
TableSchema.Table tbl = DataService.GetTableSchema(args.TableName, provider.Name);
string className = tbl.ClassName;
//Debug.Assert(!tbl.ClassName.Contains(" "), args.TableName);
bool isReadOnly = args.IsReadOnly;
LanguageType languageType = args.Language;
if (!String.IsNullOrEmpty(args.Namespace))
{
sOut += namespaceStart;
}
//create the collection
string collectionClass = GenerateCollection(className, isReadOnly, languageType);
//load the properties
string propList = GenerateProperties(tbl, languageType);
//add the collection first
string classOut = collectionClass + Environment.NewLine + Environment.NewLine;
classOut += classTemplate.Replace(TemplateVariable.CLASS_NAME, className).Replace(TemplateVariable.PROPERTY_LIST, propList);
classOut = classOut.Replace(TemplateVariable.TABLE_NAME, tbl.Name);
//place holder for now - don't know what this does...
//foreign key lookups
string methodList = GenerateForeignKeyMethods(className, tbl, languageType);
methodList += GeneratePKMethods(tbl, languageType);
classOut = classOut.Replace(TemplateVariable.METHOD_LIST, methodList);
//column struct
string columnStruct = GenerateColumnsStruct(tbl, languageType);
classOut = classOut.Replace(TemplateVariable.COLUMNS_STRUCT, columnStruct);
if (!isReadOnly)
{
string odsInsertMethod = GenerateODSInsertMethod(className, tbl, languageType);
string odsUpdateMethod = GenerateODSUpdateMethod(className, tbl, languageType);
classOut = classOut.Replace(TemplateVariable.INSERT, odsInsertMethod);
classOut = classOut.Replace(TemplateVariable.UPDATE, odsUpdateMethod);
}
string schema = GenerateSchema(tbl, languageType);
classOut = classOut.Replace(TemplateVariable.TABLE_SCHEMA, schema);
//Many To Many
string manyMethodList = GenerateManyToManyMethods(className, tbl, languageType);
sOut += classOut.Replace(TemplateVariable.MANY_METHODS, manyMethodList);
if (!String.IsNullOrEmpty(args.Namespace))
{
sOut += namespaceEnd;
}
return sOut;
}
#endregion
#region Generators
/// <summary>
/// Generates the schema in the class itself, so we don't need to hit the DB at runtime
/// </summary>
/// <param name="tbl"></param>
/// <param name="languageType"></param>
/// <returns></returns>
private static string GenerateSchema(TableSchema.Table tbl, LanguageType languageType)
{
string eol = ";";
if (languageType == LanguageType.VB)
{
eol = String.Empty;
}
StringBuilder sb = new StringBuilder();
sb.AppendLine("BaseSchema = new TableSchema.Table(\"" + tbl.Name + "\", DataService.GetInstance(\"" + tbl.Provider.Name + "\"))" + eol);
if (languageType == LanguageType.VB)
{
//sb.AppendLine("If Schema Is Nothing");
sb.AppendLine("\t\t" + "Dim columns As TableSchema.TableColumnCollection = New TableSchema.TableColumnCollection()");
}
else
{
//sb.AppendLine("if(Schema == null)");
//sb.AppendLine("\t\t{");
//sb.AppendLine("BaseSchema = new TableSchema.Table()" + eol);
sb.AppendLine("\t\t" + "TableSchema.TableColumnCollection columns = new TableSchema.TableColumnCollection()" + eol);
}
sb.AppendLine("\t\t" + "BaseSchema.Name = \"" + tbl.Name + "\"" + eol);
//sb.AppendLine("\t\t" + "BaseSchema.ProviderName = \"" + tbl.Provider.Name + "\"" + eol);
sb.AppendLine("\t\t" + "BaseSchema.SchemaName = \"" + tbl.SchemaName + "\"" + eol);
sb.AppendLine(String.Empty);
foreach (TableSchema.TableColumn column in tbl.Columns)
{
string varName = "col" + column.ArgumentName;
if (languageType == LanguageType.VB)
{
sb.AppendLine("\t\t" + "Dim " + varName + " As TableSchema.TableColumn = New TableSchema.TableColumn(BaseSchema)");
}
else
{
sb.AppendLine("\t\t" + "TableSchema.TableColumn " + varName + " = new TableSchema.TableColumn(BaseSchema);");
}
sb.AppendLine("\t\t" + varName + ".ColumnName = \"" + column.ColumnName + "\"" + eol);
sb.AppendLine("\t\t" + varName + ".DataType = DbType." + column.DataType + eol);
sb.AppendLine("\t\t" + varName + ".MaxLength = " + column.MaxLength + eol);
//sb.AppendLine("\t\t" + varName + ".PropertyName = \"" + column.PropertyName + "\"" + eol);
//sb.AppendLine("\t\t" + varName + ".DisplayName = \"" + Utility.ParseCamelToProper(column.PropertyName) + "\"" + eol);
//sb.AppendLine("\t\t" + varName + ".ParameterName = \"" + column.ParameterName + "\"" + eol);
//sb.AppendLine("\t\t" + varName + ".ArgumentName = \"" + column.ArgumentName + "\"" + eol);
if (languageType == LanguageType.VB)
{
sb.AppendLine("\t\t" + varName + ".AutoIncrement = " + column.AutoIncrement + eol);
sb.AppendLine("\t\t" + varName + ".IsNullable = " + column.IsNullable + eol);
sb.AppendLine("\t\t" + varName + ".IsPrimaryKey = " + column.IsPrimaryKey + eol);
sb.AppendLine("\t\t" + varName + ".IsForeignKey = " + column.IsForeignKey + eol);
sb.AppendLine("\t\t" + varName + ".IsReadOnly = " + column.IsReadOnly + eol);
}
else
{
sb.AppendLine("\t\t" + varName + ".AutoIncrement = " + column.AutoIncrement.ToString().ToLower() + eol);
sb.AppendLine("\t\t" + varName + ".IsNullable = " + column.IsNullable.ToString().ToLower() + eol);
sb.AppendLine("\t\t" + varName + ".IsPrimaryKey = " + column.IsPrimaryKey.ToString().ToLower() + eol);
sb.AppendLine("\t\t" + varName + ".IsForeignKey = " + column.IsForeignKey.ToString().ToLower() + eol);
sb.AppendLine("\t\t" + varName + ".IsReadOnly = " + column.IsReadOnly.ToString().ToLower() + eol);
}
sb.AppendLine("\t\t" + "columns.Add(" + varName + ")" + eol);
sb.AppendLine(String.Empty);
}
sb.AppendLine("\t\t" + "BaseSchema.Columns = columns" + eol);
if (languageType == LanguageType.VB)
{
//sb.AppendLine("\t\t" + "End If" + eol);
//sb.AppendLine("\t\t" + "Return Schema" + eol);
}
else
{
//sb.AppendLine("\t\t" + "}" + eol);
//sb.AppendLine("\t\t" + "return Schema" + eol);
}
return sb.ToString();
}
private static string GetNamespaceStart(string nameSpace, LanguageType langType)
{
if (!String.IsNullOrEmpty(nameSpace))
{
if (langType == LanguageType.VB)
{
return Environment.NewLine + "Namespace " + nameSpace + Environment.NewLine + Environment.NewLine;
}
return Environment.NewLine + "namespace " + nameSpace + Environment.NewLine + "{" + Environment.NewLine;
}
return String.Empty;
}
private static string GetNamespaceEnd(string nameSpace, LanguageType langType)
{
if (!String.IsNullOrEmpty(nameSpace))
{
if (langType == LanguageType.VB)
{
return Environment.NewLine + "End Namespace" + Environment.NewLine + Environment.NewLine;
}
return Environment.NewLine + "}" + Environment.NewLine + Environment.NewLine;
}
return String.Empty;
}
private static string WrapCodeInNamespace(string code, string nameSpace, LanguageType langType)
{
return GetNamespaceStart(nameSpace, langType) + code + GetNamespaceEnd(nameSpace, langType);
}
private static string ReplaceStructVariables(string code, string declareList, string assignList, LanguageType langType)
{
if (langType == LanguageType.VB)
{
code = code.Replace(TemplateVariable.STRUCT_LIST, declareList);
code = code.Replace(TemplateVariable.STRUCT_ASSIGNMENTS, assignList);
}
else
{
code = code.Replace(TemplateVariable.STRUCT_LIST, assignList);
}
return code;
}
static string BuildViewsStruct(string[] views, string nameSpace, LanguageType languageType, DataProvider provider)
{
string sOut;
//pull the template
if (languageType == LanguageType.VB)
{
sOut = ResourceHelper.GetString(TemplateName.VIEW_LIST_VB);
}
else
{
sOut = ResourceHelper.GetString(TemplateName.VIEW_LIST);
}
//create the table list
StringBuilder assignList = new StringBuilder();
StringBuilder declareList = new StringBuilder();
foreach (string view in views)
{
string alteredName = DataService.GetTableSchema(view, provider.Name).ClassName;
if (languageType == LanguageType.VB)
{
assignList.AppendLine(alteredName + " = @\"" + view + "\"");
declareList.AppendLine("\t\tPublic Shared " + alteredName + " As String");
}
else
{
assignList.AppendLine("\t\tpublic static string " + alteredName + " = @\"" + view + "\";");
}
}
sOut = ReplaceStructVariables(sOut, declareList.ToString(), assignList.ToString(), languageType);
return WrapCodeInNamespace(sOut, nameSpace, languageType);
}
static string BuildTablesStruct(string[] tables, string nameSpace, LanguageType languageType, DataProvider provider)
{
string sOut;
//pull the template
if (languageType == LanguageType.VB)
{
sOut = ResourceHelper.GetString(TemplateName.TABLE_LIST_VB);
}
else
{
sOut = ResourceHelper.GetString(TemplateName.TABLE_LIST);
}
//create the table list
StringBuilder assignList = new StringBuilder();
StringBuilder declareList = new StringBuilder();
foreach (string table in tables)
{
string alteredName = DataService.GetTableSchema(table, provider.Name).ClassName;
if (languageType == LanguageType.VB)
{
assignList.AppendLine(alteredName + " = @\"" + table + "\"");
declareList.AppendLine("\t\tPublic Shared " + alteredName + " As String");
}
else
{
assignList.AppendLine("\t\tpublic static string " + alteredName + " = @\"" + table + "\";");
}
}
sOut = ReplaceStructVariables(sOut, declareList.ToString(), assignList.ToString(), languageType);
return WrapCodeInNamespace(sOut, nameSpace, languageType);
}
static string GenerateColumnsStruct(TableSchema.Table table, LanguageType languageType)
{
string sOut;
if (languageType == LanguageType.VB)
{
sOut = ResourceHelper.GetString(TemplateName.COLUMN_STRUCT_VB);
}
else
{
sOut = ResourceHelper.GetString(TemplateName.COLUMN_STRUCT);
}
StringBuilder assignList = new StringBuilder();
StringBuilder declareList = new StringBuilder();
foreach (TableSchema.TableColumn col in table.Columns)
{
string alteredName = col.PropertyName;
if (languageType == LanguageType.VB)
{
assignList.AppendLine("\t\t" + alteredName + " = \"" + col.ColumnName + "\"");
declareList.AppendLine("\t\tPublic Shared " + alteredName + " As String");
}
else
{
assignList.AppendLine("\t\tpublic static string " + alteredName + " = @\"" + col.ColumnName + "\";");
}
}
sOut = ReplaceStructVariables(sOut, declareList.ToString(), assignList.ToString(), languageType);
return sOut;
}
static string GenerateCollection(string className, bool isReadOnly, LanguageType languageType)
{
//pull the template
string sOut;
if (languageType == LanguageType.VB)
{
if (isReadOnly)
{
sOut = ResourceHelper.GetString(TemplateName.READ_ONLY_COLLECTION_VB);
}
else
{
sOut = ResourceHelper.GetString(TemplateName.COLLECTION_VB);
}
}
else
{
if (isReadOnly)
{
sOut = ResourceHelper.GetString(TemplateName.READ_ONLY_COLLECTION);
}
else
{
sOut = ResourceHelper.GetString(TemplateName.COLLECTION);
}
}
sOut = sOut.Replace(TemplateVariable.CLASS_NAME, className);
return sOut;
}
static string GenerateODSUpdateMethod(string className, TableSchema.Table tbl, LanguageType languageType)
{
string updateMethod;
string updateSetList = String.Empty;
string updateArgList = String.Empty;
foreach (TableSchema.TableColumn col in tbl.Columns)
{
string varType = Utility.GetVariableType(col.DataType, col.IsNullable, languageType);
string propertyName = col.PropertyName;
string argName = col.ArgumentName;
if (!Utility.IsAuditField(col.ColumnName))
{
updateSetList += updateSetList.Length == 0 ? String.Empty : (Environment.NewLine + "\t\t");
if (languageType == LanguageType.CSharp)
{
string argument = varType + " " + argName;
updateSetList += "item." + propertyName + " = " + argName + ";";
updateArgList += updateArgList.Length == 0 ? argument : (", " + argument);
}
else if (languageType == LanguageType.VB)
{
string argument = "ByVal " + argName + " As " + varType;
updateSetList += "item." + propertyName + " = " + argName;
updateArgList += updateArgList.Length == 0 ? argument : (", " + argument);
}
}
}
string updateTemplate;
if (languageType == LanguageType.CSharp)
{
updateTemplate = ResourceHelper.GetString(TemplateName.ODS_UPDATE);
}
else
{
updateTemplate = ResourceHelper.GetString(TemplateName.ODS_UPDATE_VB);
}
updateMethod = updateTemplate.Replace(TemplateVariable.ARGUMENT_LIST, updateArgList);
updateMethod = updateMethod.Replace(TemplateVariable.CLASS_NAME, className);
updateMethod = updateMethod.Replace(TemplateVariable.SET_LIST, updateSetList);
return updateMethod;
}
static string GenerateODSInsertMethod(string className, TableSchema.Table tbl, LanguageType languageType)
{
string insertSetList = String.Empty;
string insertArgList = String.Empty;
string insertMethod;
foreach (TableSchema.TableColumn col in tbl.Columns)
{
string varType = Utility.GetVariableType(col.DataType, col.IsNullable, languageType);
string propertyName = col.PropertyName;
string argName = col.ArgumentName;
if (!Utility.IsAuditField(col.ColumnName))
{
insertSetList += insertSetList.Length == 0 ? String.Empty : (Environment.NewLine + "\t\t");
if (languageType == LanguageType.CSharp)
{
string argument = varType + " " + argName;
if (!col.AutoIncrement)
{
insertArgList += insertArgList.Length == 0 ? argument : (", " + argument);
insertSetList += "item." + propertyName + " = " + argName + ";";
}
}
else if (languageType == LanguageType.VB)
{
string argument = "ByVal " + argName + " As " + varType;
if (!col.AutoIncrement)
{
insertArgList += insertArgList.Length == 0 ? argument : (", " + argument);
insertSetList += "item." + propertyName + " = " + argName;
}
}
}
}
string insertTemplate;
if (languageType == LanguageType.CSharp)
{
insertTemplate = ResourceHelper.GetString(TemplateName.ODS_INSERT);
}
else
{
insertTemplate = ResourceHelper.GetString(TemplateName.ODS_INSERT_VB);
}
insertMethod = insertTemplate.Replace(TemplateVariable.ARGUMENT_LIST, insertArgList);
insertMethod = insertMethod.Replace(TemplateVariable.CLASS_NAME, className);
insertMethod = insertMethod.Replace(TemplateVariable.SET_LIST, insertSetList);
return insertMethod;
}
static string GeneratePKMethods(TableSchema.Table tbl, LanguageType languageType)
{
StringBuilder methodList = new StringBuilder();
ArrayList usedMethodNames = new ArrayList();
foreach (TableSchema.TableColumn col in tbl.Columns)
{
if (col.IsPrimaryKey)
{
string propFKTable = GetPrimaryKeyTableSetter(tbl, col, usedMethodNames, languageType);
if (!string.IsNullOrEmpty(propFKTable))
{
methodList.AppendLine(propFKTable);
}
}
}
return methodList.ToString();
}
static string GenerateForeignKeyMethods(string className, TableSchema.Table tbl, LanguageType languageType)
{
//string methodList = string.Empty;
StringBuilder methodList = new StringBuilder();
//StringBuilder output = new StringBuilder();
//if (languageType == LanguageType.VB) {
// output.AppendLine("Public Property " + propertyName + "() As " + fkTableNameSingular);
// output.AppendLine("\tGet" + Environment.NewLine + "\t\t return " + fkTableNameSingular + ".FetchByID(" + pkPropertyName + ")" + Environment.NewLine + "\tEnd Get");
// output.AppendLine("\tSet" + Environment.NewLine + "\t\t MarkDirty()" + Environment.NewLine + "\t\tSetColumnValue(\"" + pkPropertyName + "\", Value." + Convention.PropertyName(tblFK.PrimaryKey.ColumnName, table.Name) + ")" + Environment.NewLine + "\tEnd Set" + Environment.NewLine + "End Property");
//} else {
// output.AppendLine("public " + fkTableNameSingular + " " + propertyName + Environment.NewLine + "{");
// output.AppendLine("\tget { return " + fkTableNameSingular + ".FetchByID(" + pkPropertyName + "); }");
// output.Append("\tset" + Environment.NewLine + "\t{" + Environment.NewLine + "\t\tMarkDirty();" + Environment.NewLine + "\t\tSetColumnValue(\"" + pkPropertyName + "\", value." + Convention.PropertyName(tblFK.PrimaryKey.ColumnName, table.Name) + ");" + Environment.NewLine + "\t}" + Environment.NewLine + "}");
//}
//return output.ToString();
ArrayList usedPropertyNames = new ArrayList();
foreach (TableSchema.TableColumn col in tbl.Columns)
{
if (col.IsForeignKey)
{
string propFKTable = GetForeignKeyTableSetter(tbl, col, className, usedPropertyNames, languageType);
if (!string.IsNullOrEmpty(propFKTable))
{
methodList.AppendLine(propFKTable);
}
}
}
return methodList.ToString();
}
static string GenerateManyToManyMethods(string className, TableSchema.Table tbl, LanguageType languageType)
{
string manyMethods = String.Empty;
StringBuilder manyMethodList = new StringBuilder();
string[] manyList = DataService.GetManyToMany(tbl.Provider.Name, tbl.Name);
foreach (string mapTable in manyList)
{
if (mapTable.EndsWith(tbl.Provider.ManyToManySuffix))
{
string template;
if (languageType == LanguageType.CSharp)
{
template = ResourceHelper.GetString(TemplateName.MANY_TO_MANY_METHODS);
}
else
{
template = ResourceHelper.GetString(TemplateName.MANY_TO_MANY_METHODS_VB);
}
string foreignPK = String.Empty;
//pull map table
TableSchema.Table mtbl = DataService.GetTableSchema(mapTable, tbl.Provider.Name);
//there should be two keys on this table - ignore the one that's for
//this class
foreach (TableSchema.TableColumn col in mtbl.Columns)
{
if (col.IsPrimaryKey && !Utility.IsMatch(col.ColumnName, tbl.PrimaryKey.ColumnName))
{
foreignPK = col.ColumnName;
break;
}
}
if (!String.IsNullOrEmpty(foreignPK))
{
//now, get foreign table
try
{
string fTableName = DataService.GetForeignKeyTableName(foreignPK, tbl.Name, tbl.Provider.Name);
if(isInList(fTableName))
{
TableSchema.Table ftbl = DataService.GetTableSchema(fTableName, tbl.Provider.Name);
string fClassName = ftbl.ClassName;
string pkPropertyName = tbl.PrimaryKey.DisplayName;
//now that we have the schema, we can set the template
manyMethods = template.Replace(TemplateVariable.CLASS_NAME, className);
manyMethods = manyMethods.Replace(TemplateVariable.PK_PROP, pkPropertyName);
manyMethods = manyMethods.Replace(TemplateVariable.PK, tbl.PrimaryKey.ColumnName);
//manyMethods = manyMethods.Replace(TemplateVariable.PK_VAR, tbl.PrimaryKey.ColumnName.ToLower());
manyMethods = manyMethods.Replace(TemplateVariable.PK_VAR, tbl.PrimaryKey.ColumnName);
manyMethods = manyMethods.Replace(TemplateVariable.MAP_TABLE, mtbl.Name);
manyMethods = manyMethods.Replace(TemplateVariable.FOREIGN_PK, ftbl.PrimaryKey.ColumnName);
//manyMethods = manyMethods.Replace(TemplateVariable.FK_VAR, ftbl.PrimaryKey.ColumnName.ToLower());
manyMethods = manyMethods.Replace(TemplateVariable.FK_VAR, ftbl.PrimaryKey.ColumnName);
manyMethods = manyMethods.Replace(TemplateVariable.FOREIGN_TABLE, ftbl.Name);
manyMethods = manyMethods.Replace(TemplateVariable.FOREIGN_CLASS, fClassName);
}
}
catch
{
manyMethods = "";
}
}
}
else
{
}
manyMethodList.AppendLine(manyMethods);
}
return manyMethods;
}
static string GenerateProperties(TableSchema.Table tbl, LanguageType languageType)
{
StringBuilder sOut = new StringBuilder();
string propTemplate;
if (languageType == LanguageType.CSharp)
{
propTemplate = ResourceHelper.GetString(TemplateName.PROPERTY);
}
else
{
propTemplate = ResourceHelper.GetString(TemplateName.PROPERTY_VB);
}
foreach (TableSchema.TableColumn col in tbl.Columns)
{
string varType = Utility.GetVariableType(col.DataType, col.IsNullable, languageType);
string propertyName = col.PropertyName;
string getLine = GetPropertyGetter(col, languageType);
string setLine = GetPropertySetter(col, languageType);
sOut.AppendLine(propTemplate.Replace(TemplateVariable.PROPERTY_NAME, propertyName)
.Replace(TemplateVariable.GETTER, getLine)
.Replace(TemplateVariable.SETTER, setLine)
.Replace(TemplateVariable.PROPERTY_TYPE, varType));
}
return sOut.ToString();
}
#endregion
#region Props
private static string GetPrimaryKeyTableSetter(TableSchema.Table table, TableSchema.TableColumn column, ArrayList usedMethodNames, LanguageType languageType)
{
StringBuilder allMethods = new StringBuilder();
TableSchema.Table[] pkTables = DataService.GetPrimaryKeyTables(table.Name, table.Provider.Name);
if (pkTables != null)
{
foreach(TableSchema.Table pkTable in pkTables)
{
if(isInList(pkTable.Name) && (pkTable.PrimaryKey != null))
{
string methodFKTableTemplate;
if(languageType == LanguageType.VB)
{
methodFKTableTemplate = ResourceHelper.GetString(TemplateName.METHOD_VB);
}
else
{
methodFKTableTemplate = ResourceHelper.GetString(TemplateName.METHOD);
}
//if (String.IsNullOrEmpty(pkTable[0]) || String.IsNullOrEmpty(pkTable[1]))
//{
// return String.Empty;
//}
string tblNameFK = pkTable.ClassName;
string tblNameFKPlural = pkTable.ClassNamePlural;
string tblNameFKCollection = tblNameFK + "Collection";
string structNameFK = pkTable.PrimaryKey.PropertyName;
string propertyName = column.PropertyName;
string methodBody;
if(languageType == LanguageType.VB)
{
methodBody = "\t\tReturn New " + tblNameFKCollection + "().Where(" + tblNameFK + ".Columns." +
structNameFK + ", " + propertyName + ").Load()";
}
else
{
methodBody = "\t\treturn new " + tblNameFKCollection + "().Where(" + tblNameFK + ".Columns." +
structNameFK + ", " + propertyName + ").Load();";
}
string methodName = table.Provider.RelatedTableLoadPrefix + tblNameFKPlural;
string summary = "One to Many - Returns " + tblNameFKPlural;
if(Utility.IsMatch(tblNameFK, tblNameFKPlural))
{
methodName = methodName + "Records";
}
if(tblNameFK == table.Name)
{
methodName = "Child" + methodName;
}
if(usedMethodNames.Contains(methodName))
{
methodName += "From" + propertyName;
}
if(!usedMethodNames.Contains(methodName))
{
usedMethodNames.Add(methodName);
methodFKTableTemplate = ReplaceTemplateValues(methodFKTableTemplate, summary, methodName, tblNameFKCollection, methodBody);
allMethods.Append(methodFKTableTemplate);
}
}
}
}
return allMethods.ToString();
}
private static string GetForeignKeyTableSetter(TableSchema.Table table, TableSchema.TableColumn column, string className, ArrayList usedPropertyNames, LanguageType languageType)
{
TableSchema.Table fkTable = DataService.GetForeignKeyTable(column, table);
if (fkTable == null || !isInList(fkTable.Name))
{
return String.Empty;
}
//TableSchema.Table tblFK = null;
//try
//{
// tblFK = DataService.GetTableSchema(fkTableName, SubSonicConfig.ProviderName);//Query.BuildTableSchema(fkTableName,SubSonicConfig.ProviderName);
//}
//catch
//{
// Debug.WriteLine("Failed for " + fkTableName);
// return null;
//}
bool isManyToMany = IsManyToMany(fkTable);
string methodType = fkTable.ClassName;
string methodTypeCollection = methodType + "Collection";
string fkTableNameSingular = fkTable.ClassName;
string pkStructName = fkTable.PrimaryKey.PropertyName;
string pkPropertyName = column.PropertyName;
if (String.IsNullOrEmpty(pkStructName))
{
if (fkTable.Columns.Count > 0)
{
pkStructName = fkTable.Columns[0].ColumnName;
}
}
if (!isManyToMany)
{
if (!IsManyToMany(table))
{
string propertyName = table.Provider.RelatedTableLoadPrefix + fkTableNameSingular;
if (fkTable.Name == table.Name)
{
propertyName = "Parent" + propertyName;
}
if (usedPropertyNames.Contains(propertyName))
{
propertyName += "From" + pkPropertyName;
}
usedPropertyNames.Add(propertyName);
StringBuilder output = new StringBuilder();
if (languageType == LanguageType.VB)
{
output.AppendLine("Public Property " + propertyName + "() As " + fkTableNameSingular);
output.AppendLine("\tGet" + Environment.NewLine + "\t\t return " + fkTableNameSingular + ".FetchByID(" + pkPropertyName + ")" + Environment.NewLine + "\tEnd Get");
output.AppendLine("\tSet" + Environment.NewLine + "\t\t MarkDirty()" + Environment.NewLine + "\t\tSetColumnValue(\"" + pkPropertyName + "\", Value." + fkTable.PrimaryKey.PropertyName + ")" + Environment.NewLine + "\tEnd Set" + Environment.NewLine + "End Property");
}
else
{
output.AppendLine("public " + fkTableNameSingular + " " + propertyName + Environment.NewLine + "{");
output.AppendLine("\tget { return " + fkTableNameSingular + ".FetchByID(" + pkPropertyName + "); }");
output.Append("\tset" + Environment.NewLine + "\t{" + Environment.NewLine + "\t\tMarkDirty();" + Environment.NewLine + "\t\tSetColumnValue(\"" + pkPropertyName + "\", value." + fkTable.PrimaryKey.PropertyName + ");" + Environment.NewLine + "\t}" + Environment.NewLine + "}");
}
return output.ToString();
}
else
{
string methodFKTableTemplate;
string methodBody;
if (languageType == LanguageType.VB)
{
methodFKTableTemplate = ResourceHelper.GetString(TemplateName.METHOD_VB);
methodBody = "\t\tReturn New " + fkTableNameSingular + "Collection().Where(" + fkTableNameSingular + ".Columns." + pkStructName + ", " + pkPropertyName + ").Load()";
}
else
{
methodFKTableTemplate = ResourceHelper.GetString(TemplateName.METHOD);
methodBody = "\t\treturn new " + fkTableNameSingular + "Collection().Where(" + fkTableNameSingular + ".Columns." + pkStructName + ", " + pkPropertyName + ").Load();";
}
string methodName = table.Provider.RelatedTableLoadPrefix + table.ClassNamePlural;
if (usedPropertyNames.Contains(methodName) || Utility.IsMatch(methodName, className))
{
methodName += "From" + pkPropertyName;
}
if (!usedPropertyNames.Contains(methodName))
{
string summary = "Returns " + fkTableNameSingular;
string methodFKTable = ReplaceTemplateValues(methodFKTableTemplate, summary, methodName, methodTypeCollection, methodBody);
usedPropertyNames.Add(methodName);
return methodFKTable;
}
}
}
return String.Empty;
}
private static string GetPropertyGetter(TableSchema.TableColumn column, LanguageType languageType)
{
StringBuilder sb = new StringBuilder();
string varType = Utility.GetVariableType(column.DataType, column.IsNullable, languageType);
if (languageType == LanguageType.VB)
{
sb.AppendFormat("\t\t\tReturn GetColumnValue(Of {0})(\"{1}\")", varType, column.ColumnName);
}
else
{
sb.AppendFormat("\t\t\treturn GetColumnValue<{0}>(\"{1}\");", varType, column.ColumnName);
}
return sb.ToString();
}
private static string GetPropertySetter(TableSchema.TableColumn column, LanguageType languageType)
{
StringBuilder sb = new StringBuilder();
if (languageType == LanguageType.VB)
{
sb.AppendLine("\t\t\tMarkDirty()");
sb.AppendLine("\t\t\tSetColumnValue(\"" + column.ColumnName + "\", Value)");
}
else
{
sb.AppendLine("\t\t\tMarkDirty();");
sb.AppendLine("\t\t\tSetColumnValue(\"" + column.ColumnName + "\", value);");
}
return sb.ToString();
}
#endregion
#endregion
}
/// <summary>
/// Helper class to hold arguments for passing to methods
/// </summary>
class CodeGenerationArgs
{
public string Template = string.Empty;
public TableSchema TableSchema = null;
public LanguageType Language = LanguageType.CSharp;
public string[] TableNames = null;
public bool IsReadOnly = false;
public string ClassName = string.Empty;
public string TableName = string.Empty;
public string SPName = string.Empty;
public string Namespace = string.Empty;
}
}