using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using TierGenerator.Common.Util.Model;
using System.IO;
using TierGenerator.Common.Util.Settings;
namespace TierGenerator.Common.Util.Generate.XmlModel
{
public class TierModelBuilder
{
#region Class Members
private TierModelBuilder parentTierModelBuilder;
private TierModel tierModel;
#endregion
public TierModelBuilder(TierGeneratorSettings _settings, string _tierXmlModelPath)
{
tierModel = new TierModel();
TierModel.Solution = _settings.Solution;
TierModel.ModelPath = _tierXmlModelPath;
TierModel.Settings = _settings;
}
private TierModelBuilder(TierModelBuilder parentTierModelBuilder, TierGeneratorSettings _settings, string _tierXmlModelPath)
: this(_settings, _tierXmlModelPath)
{
this.parentTierModelBuilder = parentTierModelBuilder;
}
#region Properties
public TierModel TierModel
{
get { return tierModel; }
set { tierModel = value; }
}
#endregion
#region Public Methods
public void Parse()
{
if (!File.Exists(TierModel.ModelPath))
{
throw new InvalidDataException(String.Format("File {0} does not exists.", TierModel.ModelPath));
}
XmlDocument doc = new XmlDocument();
doc.Load(TierModel.ModelPath);
XmlNode root = doc.DocumentElement;
this.TierModel.XmlDocument = doc;
this.TierModel.Namespace = root.Attributes["Namespace"].Value;
this.TierModel.ServiceName = root.Attributes["ServiceName"].Value;
this.ParseDeclaration();
this.ParseInfoModel();
this.ParseListItemModel();
this.ParseIncludes();
this.ParseUdf();
this.Validate();
}
#endregion
#region Helper Methods
private void ParseDeclaration()
{
XmlNode root = TierModel.XmlDocument.DocumentElement;
XmlNodeList declarationList = root.SelectNodes("/TierModel/Declare");
foreach (XmlNode declarationNode in declarationList)
{
Declaration declaration = new Declaration();
declaration.FullType = declarationNode.Attributes["Type"].Value;
if (
declaration.FullType.StartsWith(String.Concat(this.TierModel.Solution, ".Common.Data")) ||
declaration.FullType.StartsWith(String.Concat(this.TierModel.Solution, ".Common.Exception")) ||
declaration.FullType.StartsWith(String.Concat(this.TierModel.Solution, ".Common.Util"))
)
{
continue;
}
TierModel.DeclarationList.Add(declaration);
}
}
private void ParseIncludes()
{
XmlNode root = TierModel.XmlDocument.DocumentElement;
XmlNodeList includeList = root.SelectNodes("/TierModel/Include");
foreach (XmlNode includeNode in includeList)
{
string path = includeNode.Attributes["Path"].Value;
string type = includeNode.Attributes["Type"].Value;
string xmlModelPath = Path.Combine(TierModel.Settings.TierModelPath, path);
TierModelBuilder tmpTierModelBuilder = null;
if (!this.TryGetParentFromPath(xmlModelPath, out tmpTierModelBuilder))
{
tmpTierModelBuilder = new TierModelBuilder(this, TierModel.Settings, xmlModelPath);
tmpTierModelBuilder.Parse();
}
IItem item = tmpTierModelBuilder.TierModel.GetItemInfoByName(type);
if (item == null)
{
item = tmpTierModelBuilder.TierModel.GetListItemByName(type);
}
Include include = new Include(item, tmpTierModelBuilder.TierModel.Namespace, tmpTierModelBuilder.TierModel.ServiceName, path, type);
TierModel.IncludeList.Add(include);
}
}
private void ParseInfoModel()
{
XmlNode root = TierModel.XmlDocument.DocumentElement;
XmlNodeList infoModelList = root.SelectNodes("/TierModel/ItemModel");
foreach (XmlNode itemNode in infoModelList)
{
ItemInfo itemInfo = new ItemInfo();
itemInfo.ClassName = itemNode.Attributes["ClassName"].Value;
itemInfo.DbTableName = itemNode.Attributes["DbTable"].Value;
if (itemNode.Attributes["DbView"] != null)
{
itemInfo.DbViewName = itemNode.Attributes["DbView"].Value;
}
if (itemNode.Attributes["Caching"] != null)
{
itemInfo.AllowCaching = Boolean.Parse(itemNode.Attributes["Caching"].Value);
}
if (itemNode.Attributes["History"] != null)
{
itemInfo.AllowHistory = Boolean.Parse(itemNode.Attributes["History"].Value);
}
if (itemNode.Attributes["Equatable"] != null)
{
itemInfo.Equatable = Boolean.Parse(itemNode.Attributes["Equatable"].Value);
}
XmlNodeList keyNodeList = itemNode.SelectNodes("KeyProperty");
if (keyNodeList.Count != 1)
{
//throw new InvalidDataException(String.Format("{0} must have only one key property.", itemInfo.ClassName));
}
if (keyNodeList.Count > 0)
{
itemInfo.ColumnList.Add(TierModelHelper.ParseColumn(this, keyNodeList[0]));
}
XmlNodeList propertyNodeList = itemNode.SelectNodes("Property");
foreach (XmlNode propertyNode in propertyNodeList)
{
itemInfo.ColumnList.Add(TierModelHelper.ParseColumn(this, propertyNode));
}
XmlNodeList selectNodeList = itemNode.SelectNodes("SelectMethod");
XmlNodeList insertNodeList = itemNode.SelectNodes("InsertMethod");
XmlNodeList updateNodeList = itemNode.SelectNodes("UpdateMethod");
XmlNodeList deleteNodeList = itemNode.SelectNodes("DeleteMethod");
if (selectNodeList.Count != 1)
{
throw new InvalidDataException(String.Format("{0} must have only one select method declaration.", itemInfo.ClassName));
}
if (insertNodeList.Count != 1)
{
throw new InvalidDataException(String.Format("{0} must have only one insert method declaration.", itemInfo.ClassName));
}
if (updateNodeList.Count != 1)
{
throw new InvalidDataException(String.Format("{0} must have only one update method declaration.", itemInfo.ClassName));
}
if (deleteNodeList.Count != 1)
{
throw new InvalidDataException(String.Format("{0} must have only one delete method declaration.", itemInfo.ClassName));
}
#region Parse Select Method
itemInfo.SelectMethod.NeedToCreate = Convert.ToBoolean(selectNodeList[0].Attributes["NeedToCreate"].Value.ToLower());
if (selectNodeList[0].Attributes["BllAccess"] != null)
{
itemInfo.SelectMethod.BllAccess = Convert.ToBoolean(selectNodeList[0].Attributes["BllAccess"].Value.ToLower());
}
if (selectNodeList[0].Attributes["DalAccess"] != null)
{
itemInfo.SelectMethod.DalAccess = Convert.ToBoolean(selectNodeList[0].Attributes["DalAccess"].Value.ToLower());
}
#endregion Parse Select Method
#region Parse Insert Method
itemInfo.InsertMethod.NeedToCreate = Convert.ToBoolean(insertNodeList[0].Attributes["NeedToCreate"].Value.ToLower());
if (insertNodeList[0].Attributes["BllAccess"] != null)
{
itemInfo.InsertMethod.BllAccess = Convert.ToBoolean(insertNodeList[0].Attributes["BllAccess"].Value.ToLower());
}
if (insertNodeList[0].Attributes["DalAccess"] != null)
{
itemInfo.InsertMethod.DalAccess = Convert.ToBoolean(insertNodeList[0].Attributes["DalAccess"].Value.ToLower());
}
#endregion Parse Insert Method
#region Parse Update Method
itemInfo.UpdateMethod.NeedToCreate = Convert.ToBoolean(updateNodeList[0].Attributes["NeedToCreate"].Value.ToLower());
if (updateNodeList[0].Attributes["BllAccess"] != null)
{
itemInfo.UpdateMethod.BllAccess = Convert.ToBoolean(updateNodeList[0].Attributes["BllAccess"].Value.ToLower());
}
if (updateNodeList[0].Attributes["DalAccess"] != null)
{
itemInfo.UpdateMethod.DalAccess = Convert.ToBoolean(updateNodeList[0].Attributes["DalAccess"].Value.ToLower());
}
#endregion Parse Update Method
#region Parse Delete Method
itemInfo.DeleteMethod.NeedToCreate = Convert.ToBoolean(deleteNodeList[0].Attributes["NeedToCreate"].Value.ToLower());
if (deleteNodeList[0].Attributes["BllAccess"] != null)
{
itemInfo.DeleteMethod.BllAccess = Convert.ToBoolean(deleteNodeList[0].Attributes["BllAccess"].Value.ToLower());
}
if (deleteNodeList[0].Attributes["DalAccess"] != null)
{
itemInfo.DeleteMethod.DalAccess = Convert.ToBoolean(deleteNodeList[0].Attributes["DalAccess"].Value.ToLower());
}
#endregion Parse Delete Method
TierModel.ItemInfoList.Add(itemInfo);
}
}
private void ParseListItemModel()
{
XmlNode root = TierModel.XmlDocument.DocumentElement;
XmlNodeList listItemModelList = root.SelectNodes("/TierModel/ListItemModel");
foreach (XmlNode itemNode in listItemModelList)
{
ListItem listItem = new ListItem();
listItem.ClassName = itemNode.Attributes["ClassName"].Value;
listItem.DbViewName = itemNode.Attributes["DbView"].Value;
XmlNodeList keyNodeList = itemNode.SelectNodes("KeyProperty");
if (keyNodeList.Count != 1)
{
throw new InvalidDataException(String.Format("{0} must have excatly one key property.", listItem.ClassName));
}
listItem.ColumnList.Add(TierModelHelper.ParseColumn(this, keyNodeList[0]));
XmlNodeList propertyNodeList = itemNode.SelectNodes("Property");
foreach (XmlNode propertyNode in propertyNodeList)
{
listItem.ColumnList.Add(TierModelHelper.ParseColumn(this, propertyNode));
}
TierModel.ListItemList.Add(listItem);
}
}
private void ParseUdf()
{
ParseSelectMethod();
ParseUpdateMethod();
ParseDeleteMethod();
}
private void ParseSelectMethod()
{
XmlNode root = TierModel.XmlDocument.DocumentElement;
XmlNodeList selectMethodList = root.SelectNodes("/TierModel/SelectMethod");
foreach (XmlNode udfNode in selectMethodList)
{
UdfInfo udf = new UdfInfo();
udf.Name = udfNode.Attributes["Name"].Value;
if (udfNode.Attributes["BllAccess"] != null)
{
udf.BllAccess = Convert.ToBoolean(udfNode.Attributes["BllAccess"].Value);
}
if (udfNode.Attributes["DalAccess"] != null)
{
udf.DalAccess = Convert.ToBoolean(udfNode.Attributes["DalAccess"].Value);
}
udf.Comment = udfNode.SelectSingleNode("Comment").InnerText;
udf.SqlQuery = udfNode.SelectSingleNode("Sql").SelectSingleNode("Query").InnerText;
XmlNodeList propertyNodeList = udfNode.SelectNodes("Property");
foreach (XmlNode propertyNode in propertyNodeList)
{
udf.ColumnList.Add(TierModelHelper.ParseColumn(this, propertyNode));
}
XmlNode returnNode = udfNode.SelectSingleNode("Return");
udf.ReturnType = CSharpTypeHelper.GetCSharpTypeEnum(returnNode.Attributes["ReturnType"].Value);
if (!CSharpTypeHelper.IsSimpleType(udf.ReturnType))
{
if (returnNode.Attributes["Type"] != null)
{
udf.Type = returnNode.Attributes["Type"].Value;
}
else if (returnNode.Attributes["ReturnType"] != null)
{
udf.Type = returnNode.Attributes["ReturnType"].Value;
}
}
else if (udf.ReturnType == CSharpTypeEnum.ENUM)
{
udf.Type = returnNode.Attributes["ReturnType"].Value;
}
TierModel.SelectMethodList.Add(udf);
}
}
private void ParseUpdateMethod()
{
XmlNode root = TierModel.XmlDocument.DocumentElement;
XmlNodeList selectMethodList = root.SelectNodes("/TierModel/UpdateMethod");
foreach (XmlNode udfNode in selectMethodList)
{
UdfInfo udf = new UdfInfo();
udf.Name = udfNode.Attributes["Name"].Value;
if (udfNode.Attributes["BllAccess"] != null)
{
udf.BllAccess = Convert.ToBoolean(udfNode.Attributes["BllAccess"].Value);
}
if (udfNode.Attributes["DalAccess"] != null)
{
udf.DalAccess = Convert.ToBoolean(udfNode.Attributes["DalAccess"].Value);
}
udf.Comment = udfNode.SelectSingleNode("Comment").Value;
udf.SqlQuery = udfNode.SelectSingleNode("Sql").SelectSingleNode("Query").InnerText;
XmlNodeList propertyNodeList = udfNode.SelectNodes("Property");
foreach (XmlNode propertyNode in propertyNodeList)
{
udf.ColumnList.Add(TierModelHelper.ParseColumn(this, propertyNode));
}
TierModel.UpdateMethodList.Add(udf);
}
}
private void ParseDeleteMethod()
{
XmlNode root = TierModel.XmlDocument.DocumentElement;
XmlNodeList selectMethodList = root.SelectNodes("/TierModel/DeleteMethod");
foreach (XmlNode udfNode in selectMethodList)
{
UdfInfo udf = new UdfInfo();
udf.Name = udfNode.Attributes["Name"].Value;
if (udfNode.Attributes["BllAccess"] != null)
{
udf.BllAccess = Convert.ToBoolean(udfNode.Attributes["BllAccess"].Value);
}
if (udfNode.Attributes["DalAccess"] != null)
{
udf.DalAccess = Convert.ToBoolean(udfNode.Attributes["DalAccess"].Value);
}
udf.Comment = udfNode.SelectSingleNode("Comment").Value;
udf.SqlQuery = udfNode.SelectSingleNode("Sql").SelectSingleNode("Query").InnerText;
XmlNodeList propertyNodeList = udfNode.SelectNodes("Property");
foreach (XmlNode propertyNode in propertyNodeList)
{
udf.ColumnList.Add(TierModelHelper.ParseColumn(this, propertyNode));
}
TierModel.DeleteMethodList.Add(udf);
}
}
private void Validate()
{
#region Rule 1 - ListItemModel must not have blob fields
foreach (ListItem listItem in TierModel.ListItemList)
{
foreach (ColumnInfo column in listItem.ColumnList)
{
if (column.CSharpColumn.Type == CSharpTypeEnum.BLOB)
{
throw new InvalidDataException(string.Format("{0} ListItemModel must not have blob fields", listItem.ClassName));
}
}
}
#endregion Rule 1 - ListItemModel must not have blob fields
#region Rule 2 - Declarations with the same Short/Full Type is not allowed
foreach (Declaration declaration in TierModel.DeclarationList)
{
foreach (Declaration declaration2 in TierModel.DeclarationList)
{
if (ReferenceEquals(declaration, declaration2))
{
continue;
}
if (declaration.ShortType == declaration2.ShortType)
{
throw new InvalidDataException(string.Format("Declarations with the same name {0} is not allowed ListItemModel must not have blob fields", declaration.ShortType));
}
if (declaration.FullType == declaration2.FullType)
{
throw new InvalidDataException(string.Format("Declarations with the same name {0} is not allowed ListItemModel must not have blob fields", declaration.FullType));
}
}
}
#endregion Rule 2 - Declarations with the same Short Type is not allowed
#region Rule 3 - Include type is not in the Path
foreach (Include include in TierModel.IncludeList)
{
if (include.Item == null)
{
throw new InvalidDataException(string.Format("Include type {0} is not in the Path \"{1}\"", include.Type, include.Path));
}
}
#endregion Rule 3 - Include type is not in the Path
}
private bool TryGetParentFromPath(string xmlModelPath, out TierModelBuilder parentTierModelBuilder)
{
parentTierModelBuilder = null;
if (this.parentTierModelBuilder != null)
{
if (String.Compare(this.parentTierModelBuilder.TierModel.ModelPath, xmlModelPath, StringComparison.InvariantCultureIgnoreCase) == 0)
{
parentTierModelBuilder = this.parentTierModelBuilder;
return true;
}
return this.parentTierModelBuilder.TryGetParentFromPath(xmlModelPath, out parentTierModelBuilder);
}
return false;
}
#endregion
}
}