📄 classbinder.cs
字号:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Engine;
using NHibernate.Mapping;
using NHibernate.Type;
using NHibernate.Util;
namespace NHibernate.Cfg.XmlHbmBinding
{
public abstract class ClassBinder : Binder
{
protected readonly Dialect.Dialect dialect;
protected readonly XmlNamespaceManager namespaceManager;
public ClassBinder(Binder parent, XmlNamespaceManager namespaceManager, Dialect.Dialect dialect)
: base(parent)
{
this.dialect = dialect;
this.namespaceManager = namespaceManager;
}
public ClassBinder(ClassBinder parent)
: base(parent)
{
dialect = parent.dialect;
namespaceManager = parent.namespaceManager;
}
protected void PropertiesFromXML(XmlNode node, PersistentClass model)
{
Table table = model.Table;
foreach (XmlNode subnode in node.ChildNodes)
{
//I am only concerned with elements that are from the nhibernate namespace
if (subnode.NamespaceURI != Configuration.MappingSchemaXMLNS)
continue;
string name = subnode.LocalName; //.Name;
string propertyName = GetPropertyName(subnode);
IValue value = null;
CollectionBinder collectionBinder = new CollectionBinder(this);
if (collectionBinder.CanCreate(name))
{
Mapping.Collection collection = collectionBinder.Create(name, subnode, model.EntityName,
propertyName, model, model.MappedClass);
mappings.AddCollection(collection);
value = collection;
}
else if ("many-to-one".Equals(name))
{
value = new ManyToOne(table);
BindManyToOne(subnode, (ManyToOne) value, propertyName, true);
}
else if ("any".Equals(name))
{
value = new Any(table);
BindAny(subnode, (Any) value, true);
}
else if ("one-to-one".Equals(name))
{
value = new OneToOne(table, model);
BindOneToOne(subnode, (OneToOne) value);
}
else if ("property".Equals(name))
{
value = new SimpleValue(table);
BindSimpleValue(subnode, (SimpleValue) value, true, propertyName);
}
else if ("component".Equals(name) || "dynamic-component".Equals(name))
{
// NH: Modified from H2.1 to allow specifying the type explicitly using class attribute
System.Type reflectedClass = GetPropertyType(subnode, model.MappedClass, propertyName);
value = new Component(model);
BindComponent(subnode, (Component) value, reflectedClass, model.EntityName, propertyName, true);
}
else if ("join".Equals(name))
{
Join join = new Join();
join.PersistentClass = model;
BindJoin(subnode, join);
model.AddJoin(join);
}
else if ("subclass".Equals(name))
new SubclassBinder(this).HandleSubclass(model, subnode);
else if ("joined-subclass".Equals(name))
new JoinedSubclassBinder(this).HandleJoinedSubclass(model, subnode);
else if ("union-subclass".Equals(name))
new UnionSubclassBinder(this).HandleUnionSubclass(model, subnode);
else if ("filter".Equals(name))
ParseFilter(subnode, model);
if (value != null)
model.AddProperty(CreateProperty(value, propertyName, model.MappedClass, subnode));
}
}
protected void BindClass(XmlNode node, PersistentClass model)
{
string className = node.Attributes["name"] == null ? null : FullClassName(node.Attributes["name"].Value, mappings);
// CLASS
model.ClassName = ClassForFullNameChecked(className, "persistent class {0} not found").AssemblyQualifiedName;
string entityName = node.Attributes["entity-name"] == null ? null : node.Attributes["name"].Value;
if (entityName == null)
entityName = model.MappedClass.FullName;
if (entityName == null)
{
throw new MappingException("Unable to determine entity name");
}
model.EntityName = entityName;
// PROXY INTERFACE
XmlAttribute proxyNode = node.Attributes["proxy"];
XmlAttribute lazyNode = node.Attributes["lazy"];
bool lazy = lazyNode == null ? mappings.DefaultLazy : "true".Equals(lazyNode.Value);
// go ahead and set the lazy here, since pojo.proxy can override it.
model.IsLazy = lazy;
if (proxyNode != null)
{
model.ProxyInterfaceName = ClassForNameChecked(proxyNode.Value, mappings, "proxy class not found: {0}").AssemblyQualifiedName;
model.IsLazy = true;
}
else if (model.IsLazy)
model.ProxyInterfaceName = model.MappedClass.AssemblyQualifiedName;
// DISCRIMINATOR
XmlAttribute discriminatorNode = node.Attributes["discriminator-value"];
model.DiscriminatorValue = (discriminatorNode == null) ? model.EntityName : discriminatorNode.Value;
// DYNAMIC UPDATE
XmlAttribute dynamicNode = node.Attributes["dynamic-update"];
model.DynamicUpdate = (dynamicNode == null) ? false : "true".Equals(dynamicNode.Value);
// DYNAMIC INSERT
XmlAttribute insertNode = node.Attributes["dynamic-insert"];
model.DynamicInsert = (insertNode == null) ? false : "true".Equals(insertNode.Value);
// IMPORT
// we automatically want to add an import of the Assembly Qualified Name (includes version,
// culture, public-key) to the className supplied in the hbm.xml file. The most common use-case
// will have it contain the "FullClassname, AssemblyName", it might contain version, culture,
// public key, etc...) but should not assume it does.
mappings.AddImport(model.MappedClass.AssemblyQualifiedName, StringHelper.GetFullClassname(className));
// if we are supposed to auto-import the Class then add an import to get from the Classname
// to the Assembly Qualified Class Name
if (mappings.IsAutoImport)
mappings.AddImport(model.MappedClass.AssemblyQualifiedName, StringHelper.GetClassname(className));
// BATCH SIZE
XmlAttribute batchNode = node.Attributes["batch-size"];
if (batchNode != null)
model.BatchSize = int.Parse(batchNode.Value);
// SELECT BEFORE UPDATE
XmlAttribute sbuNode = node.Attributes["select-before-update"];
if (sbuNode != null)
model.SelectBeforeUpdate = "true".Equals(sbuNode.Value);
// OPTIMISTIC LOCK MODE
XmlAttribute olNode = node.Attributes["optimistic-lock"];
model.OptimisticLockMode = GetOptimisticLockMode(olNode);
// META ATTRIBUTES
model.MetaAttributes = GetMetas(node);
// PERSISTER
XmlAttribute persisterNode = node.Attributes["persister"];
if (persisterNode == null)
{
//persister = typeof( EntityPersister );
}
else
model.EntityPersisterClass =
ClassForNameChecked(persisterNode.Value, mappings, "could not instantiate persister class: {0}");
// CUSTOM SQL
HandleCustomSQL(node, model);
foreach (XmlNode syncNode in node.SelectNodes(HbmConstants.nsSynchronize, namespaceManager))
model.AddSynchronizedTable(XmlHelper.GetAttributeValue(syncNode, "table"));
bool? isAbstract = null;
XmlAttribute abstractNode = node.Attributes["abstract"];
if (abstractNode != null)
{
if ("true".Equals(abstractNode.Value) || "1".Equals(abstractNode.Value))
isAbstract = true;
else if ("false".Equals(abstractNode.Value) || "0".Equals(abstractNode.Value))
isAbstract = false;
}
model.IsAbstract = isAbstract;
}
private void BindJoin(XmlNode node, Join join)
{
PersistentClass persistentClass = join.PersistentClass;
String path = persistentClass.EntityName;
// TABLENAME
XmlAttribute schemaNode = node.Attributes["schema"];
string schema = schemaNode == null ? mappings.SchemaName : schemaNode.Value;
XmlAttribute catalogNode = node.Attributes["catalog"];
string catalog = catalogNode == null ? mappings.CatalogName : catalogNode.Value;
Table table = mappings.AddTable(schema, catalog, GetClassTableName(persistentClass, node), null, false);
join.Table = table;
XmlAttribute fetchNode = node.Attributes["fetch"];
if (fetchNode != null)
join.IsSequentialSelect = "select".Equals(fetchNode.Value);
XmlAttribute invNode = node.Attributes["inverse"];
if (invNode != null)
join.IsInverse = "true".Equals(invNode.Value);
XmlAttribute nullNode = node.Attributes["optional"];
if (nullNode != null)
join.IsOptional = "true".Equals(nullNode.Value);
log.InfoFormat("Mapping class join: {0} -> {1}", persistentClass.EntityName, join.Table.Name);
// KEY
XmlNode keyNode = node.SelectSingleNode(HbmConstants.nsKey, namespaceManager);
SimpleValue key = new DependantValue(table, persistentClass.Identifier);
join.Key = key;
if (keyNode.Attributes["on-delete"] != null)
key.IsCascadeDeleteEnabled = "cascade".Equals(keyNode.Attributes["on-delete"].Value);
BindSimpleValue(keyNode, key, false, persistentClass.EntityName);
join.CreatePrimaryKey(dialect);
join.CreateForeignKey();
// PROPERTIES
//PropertiesFromXML(node, persistentClass, mappings);
foreach (XmlNode subnode in node.ChildNodes)
{
string name = subnode.Name;
XmlAttribute nameAttribute = subnode.Attributes["name"];
string propertyName = nameAttribute == null ? null : nameAttribute.Value;
IValue value = null;
switch (name)
{
case "many-to-one":
value = new ManyToOne(table);
BindManyToOne(subnode, (ManyToOne) value, propertyName, true);
break;
case "any":
value = new Any(table);
BindAny(subnode, (Any) value, true);
break;
case "property":
value = new SimpleValue(table);
BindSimpleValue(subnode, (SimpleValue) value, true, propertyName);
break;
case "component":
case "dynamic-component":
string subpath = StringHelper.Qualify(path, propertyName);
value = new Component(join);
BindComponent(
subnode,
(Component) value,
join.PersistentClass.MappedClass,
propertyName,
subpath,
true);
break;
}
if (value != null)
{
Mapping.Property prop = CreateProperty(value, propertyName, persistentClass.MappedClass, subnode);
prop.IsOptional = join.IsOptional;
join.AddProperty(prop);
}
}
// CUSTOM SQL
HandleCustomSQL(node, join);
}
private void HandleCustomSQL(XmlNode node, PersistentClass model)
{
XmlNode element = node.SelectSingleNode(HbmConstants.nsSqlInsert, namespaceManager);
if (element != null)
{
bool callable = IsCallable(element);
model.SetCustomSQLInsert(element.InnerText.Trim(), callable, GetResultCheckStyle(element, callable));
}
element = node.SelectSingleNode(HbmConstants.nsSqlDelete, namespaceManager);
if (element != null)
{
bool callable = IsCallable(element);
model.SetCustomSQLDelete(element.InnerText.Trim(), callable, GetResultCheckStyle(element, callable));
}
element = node.SelectSingleNode(HbmConstants.nsSqlUpdate, namespaceManager);
if (element != null)
{
bool callable = IsCallable(element);
model.SetCustomSQLUpdate(element.InnerText.Trim(), callable, GetResultCheckStyle(element, callable));
}
element = node.SelectSingleNode(HbmConstants.nsLoader, namespaceManager);
if (element != null)
model.LoaderName = XmlHelper.GetAttributeValue(element, "query-ref");
}
private void HandleCustomSQL(XmlNode node, Join model)
{
XmlNode element = node.SelectSingleNode(HbmConstants.nsSqlInsert, namespaceManager);
if (element != null)
{
bool callable = IsCallable(element);
model.SetCustomSQLInsert(element.InnerText.Trim(), callable, GetResultCheckStyle(element, callable));
}
element = node.SelectSingleNode(HbmConstants.nsSqlDelete, namespaceManager);
if (element != null)
{
bool callable = IsCallable(element);
model.SetCustomSQLDelete(element.InnerText.Trim(), callable, GetResultCheckStyle(element, callable));
}
element = node.SelectSingleNode(HbmConstants.nsSqlUpdate, namespaceManager);
if (element != null)
{
bool callable = IsCallable(element);
model.SetCustomSQLUpdate(element.InnerText.Trim(), callable, GetResultCheckStyle(element, callable));
}
}
private static Versioning.OptimisticLock GetOptimisticLockMode(XmlAttribute olAtt)
{
if (olAtt == null)
return Versioning.OptimisticLock.Version;
string olMode = olAtt.Value;
if (olMode == null || "version".Equals(olMode))
return Versioning.OptimisticLock.Version;
else if ("dirty".Equals(olMode))
return Versioning.OptimisticLock.Dirty;
else if ("all".Equals(olMode))
return Versioning.OptimisticLock.All;
else if ("none".Equals(olMode))
return Versioning.OptimisticLock.None;
else
throw new MappingException("Unsupported optimistic-lock style: " + olMode);
}
protected PersistentClass GetSuperclass(XmlNode subnode)
{
XmlAttribute extendsAttr = subnode.Attributes["extends"];
if (extendsAttr == null)
throw new MappingException("'extends' attribute is not found.");
String extendsValue = FullClassName(extendsAttr.Value, mappings);
System.Type superclass = ClassForFullNameChecked(extendsValue,
"extended class not found: {0}");
PersistentClass superModel = mappings.GetClass(superclass);
if (superModel == null)
throw new MappingException("Cannot extend unmapped class: " + extendsValue);
return superModel;
}
protected string GetClassTableName(PersistentClass model, XmlNode node)
{
XmlAttribute tableNameNode = node.Attributes["table"];
if (tableNameNode == null)
return mappings.NamingStrategy.ClassToTableName(model.EntityName);
else
return mappings.NamingStrategy.TableName(tableNameNode.Value);
}
protected void MakeIdentifier(XmlNode node, SimpleValue model)
{
//GENERATOR
XmlNode subnode = node.SelectSingleNode(HbmConstants.nsGenerator, namespaceManager);
if (subnode != null)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -