/// <remarks> /// Called for all collections /// </remarks> public static void BindCollection( XmlNode node, Mapping.Collection model, string className, string path, Mappings mappings ) { //ROLENAME model.Role = StringHelper.Qualify( className, path ); XmlAttribute inverseNode = node.Attributes[ "inverse" ]; if( inverseNode != null ) { model.IsInverse = StringHelper.BooleanValue( inverseNode.Value ); } XmlAttribute orderNode = node.Attributes[ "order-by" ]; if( orderNode != null ) { model.OrderBy = orderNode.Value; } XmlAttribute whereNode = node.Attributes[ "where" ]; if( whereNode != null ) { model.Where = whereNode.Value; } XmlAttribute batchNode = node.Attributes[ "batch-size" ]; if( batchNode != null ) { model.BatchSize = Int32.Parse( batchNode.Value ); } //PERSISTER XmlAttribute persisterNode = node.Attributes[ "persister" ]; if( persisterNode == null ) { //persister = CollectionPersisterImpl.class; } else { model.CollectionPersisterClass = ClassForNameChecked( persisterNode.Value, mappings, "could not instantiate collection persister class: {0}" ); } InitOuterJoinFetchSetting( node, model ); XmlNode oneToManyNode = node.SelectSingleNode( nsOneToMany, nsmgr ); if( oneToManyNode != null ) { OneToMany oneToMany = new OneToMany( model.Owner ); model.Element = oneToMany; BindOneToMany( oneToManyNode, oneToMany, mappings ); //we have to set up the table later!! yuck } else { //TABLE XmlAttribute tableNode = node.Attributes[ "table" ]; string tableName; if( tableNode != null ) { tableName = mappings.NamingStrategy.TableName( tableNode.Value ); } else { tableName = mappings.NamingStrategy.PropertyToTableName( className, path ); } XmlAttribute schemaNode = node.Attributes[ "schema" ]; string schema = schemaNode == null ? mappings.SchemaName : schemaNode.Value; model.CollectionTable = mappings.AddTable( schema, tableName ); log.Info( "Mapping collection: " + model.Role + " -> " + model.CollectionTable.Name ); } //LAZINESS XmlAttribute lazyNode = node.Attributes[ "lazy" ]; if( lazyNode != null ) { model.IsLazy = StringHelper.BooleanValue( lazyNode.Value ); } //SORT XmlAttribute sortedAtt = node.Attributes[ "sort" ]; // unsorted, natural, comparator.class.name if( sortedAtt == null || sortedAtt.Value.Equals( "unsorted" ) ) { model.IsSorted = false; } else { model.IsSorted = true; string comparatorClassName = FullClassName( sortedAtt.Value, mappings ); if( !comparatorClassName.Equals( "natural" ) ) { try { model.Comparer = ( IComparer ) Activator.CreateInstance( ReflectHelper.ClassForName( comparatorClassName ) ); } catch { throw new MappingException( "could not instantiate comparer class: " + comparatorClassName ); } } } //ORPHAN DELETE (used for programmer error detection) XmlAttribute cascadeAtt = node.Attributes[ "cascade" ]; if( cascadeAtt != null && cascadeAtt.Value.Equals( "all-delete-orphan" ) ) { model.OrphanDelete = true; } //set up second pass if( model is List ) { mappings.AddSecondPass( new ListSecondPass( node, mappings, ( List ) model ) ); } else if( model is Map ) { mappings.AddSecondPass( new MapSecondPass( node, mappings, ( Map ) model ) ); } else if( model is Set ) { mappings.AddSecondPass( new SetSecondPass( node, mappings, ( Set ) model ) ); } else if( model is IdentifierCollection ) { mappings.AddSecondPass( new IdentifierCollectionSecondPass( node, mappings, ( IdentifierCollection ) model ) ); } else { mappings.AddSecondPass( new CollectionSecondPass( node, mappings, model ) ); } }
public static void BindJoinedSubclass( XmlNode node, Subclass model, Mappings mappings ) { BindClass( node, model, mappings ); // joined subclass if( model.ClassPersisterClass == null ) { model.RootClazz.ClassPersisterClass = typeof( NormalizedEntityPersister ); } //table + schema names XmlAttribute schemaNode = node.Attributes[ "schema" ]; string schema = schemaNode == null ? mappings.SchemaName : schemaNode.Value; Table mytable = mappings.AddTable( schema, GetClassTableName( model, node, mappings ) ); model.Table = mytable; log.Info( "Mapping joined-subclass: " + model.Name + " -> " + model.Table.Name ); XmlNode keyNode = node.SelectSingleNode( nsKey, nsmgr ); SimpleValue key = new SimpleValue( mytable ); model.Key = key; BindSimpleValue( keyNode, key, false, model.Name, mappings ); model.Key.Type = model.Identifier.Type; model.CreatePrimaryKey( dialect ); model.CreateForeignKey(); // CHECK XmlAttribute chNode = node.Attributes[ "check" ]; if( chNode != null ) { mytable.AddCheckConstraint( chNode.Value ); } // properties PropertiesFromXML( node, model, mappings ); }
public static void BindRootClass( XmlNode node, RootClass model, Mappings mappings ) { BindClass( node, model, mappings ); //TABLENAME XmlAttribute schemaNode = node.Attributes[ "schema" ]; string schema = schemaNode == null ? mappings.SchemaName : schemaNode.Value; Table table = mappings.AddTable( schema, GetClassTableName( model, node, mappings ) ); model.Table = table; log.Info( "Mapping class: " + model.Name + " -> " + model.Table.Name ); //MUTABLE XmlAttribute mutableNode = node.Attributes[ "mutable" ]; model.IsMutable = ( mutableNode == null ) || mutableNode.Value.Equals( "true" ); //WHERE XmlAttribute whereNode = node.Attributes[ "where" ]; if( whereNode != null ) { model.Where = whereNode.Value; } //CHECK XmlAttribute checkNode = node.Attributes[ "check" ]; if( checkNode != null ) { table.AddCheckConstraint( checkNode.Value ); } //POLYMORPHISM XmlAttribute polyNode = node.Attributes[ "polymorphism" ]; model.IsExplicitPolymorphism = ( polyNode != null ) && polyNode.Value.Equals( "explicit" ); foreach( XmlNode subnode in node.ChildNodes ) { string name = subnode.LocalName; //Name; string propertyName = GetPropertyName( subnode ); //I am only concerned with elements that are from the nhibernate namespace if( subnode.NamespaceURI != Configuration.MappingSchemaXMLNS ) { continue; } switch( name ) { case "id": SimpleValue id = new SimpleValue( table ); model.Identifier = id; if( propertyName == null ) { BindSimpleValue( subnode, id, false, RootClass.DefaultIdentifierColumnName, mappings ); if( id.Type == null ) { throw new MappingException( "must specify an identifier type: " + model.MappedClass.Name ); } model.IdentifierProperty = null; } else { BindSimpleValue( subnode, id, false, propertyName, mappings ); id.SetTypeByReflection( model.MappedClass, propertyName, PropertyAccess( subnode, mappings ) ); Mapping.Property prop = new Mapping.Property( id ); BindProperty( subnode, prop, mappings ); model.IdentifierProperty = prop; } if( id.Type.ReturnedClass.IsArray ) { throw new MappingException( "illegal use of an array as an identifier (arrays don't reimplement equals)" ); } MakeIdentifier( subnode, id, mappings ); break; case "composite-id": Component compId = new Component( model ); model.Identifier = compId; if( propertyName == null ) { BindComponent( subnode, compId, null, model.Name, "id", false, mappings ); model.HasEmbeddedIdentifier = compId.IsEmbedded; model.IdentifierProperty = null; } else { System.Type reflectedClass = GetPropertyType( subnode, mappings, model.MappedClass, propertyName ); BindComponent( subnode, compId, reflectedClass, model.Name, propertyName, false, mappings ); Mapping.Property prop = new Mapping.Property( compId ); BindProperty( subnode, prop, mappings ); model.IdentifierProperty = prop; } MakeIdentifier( subnode, compId, mappings ); System.Type compIdClass = compId.ComponentClass; if( !ReflectHelper.OverridesEquals( compIdClass ) ) { throw new MappingException( "composite-id class must override Equals(): " + compIdClass.FullName ); } if( !ReflectHelper.OverridesGetHashCode( compIdClass ) ) { throw new MappingException( "composite-id class must override GetHashCode(): " + compIdClass.FullName ); } // Serializability check not ported break; case "version": case "timestamp": //VERSION SimpleValue val = new SimpleValue( table ); BindSimpleValue( subnode, val, false, propertyName, mappings ); if( val.Type == null ) { val.Type = ( ( "version".Equals( name ) ) ? NHibernateUtil.Int32 : NHibernateUtil.Timestamp ); } Mapping.Property timestampProp = new Mapping.Property( val ); BindProperty( subnode, timestampProp, mappings ); MakeVersion( subnode, val ); model.Version = timestampProp; model.AddNewProperty( timestampProp ); break; case "discriminator": //DISCRIMINATOR SimpleValue discrim = new SimpleValue( table ); model.Discriminator = discrim; BindSimpleValue( subnode, discrim, false, RootClass.DefaultDiscriminatorColumnName, mappings ); if( discrim.Type == null ) { discrim.Type = NHibernateUtil.String; foreach( Column col in discrim.ColumnCollection ) { col.Type = NHibernateUtil.String; break; } } model.IsPolymorphic = true; if( subnode.Attributes[ "force" ] != null && "true".Equals( subnode.Attributes[ "force" ].Value ) ) { model.IsForceDiscriminator = true; } if( subnode.Attributes[ "insert" ] != null && "false".Equals( subnode.Attributes[ "insert" ].Value ) ) { model.IsDiscriminatorInsertable = false; } break; case "jcs-cache": case "cache": string className = model.MappedClass.FullName; ICacheConcurrencyStrategy cache = CacheFactory.CreateCache( subnode, className, model.IsMutable ); mappings.AddCache( className, cache ); model.Cache = cache; break; } } model.CreatePrimaryKey( dialect ); PropertiesFromXML( node, model, mappings ); }
/// <remarks> /// Called for all collections. <paramref name="containingType" /> parameter /// was added in NH to allow for reflection related to generic types. /// </remarks> public static void BindCollection(XmlNode node, Mapping.Collection model, string className, string path, System.Type containingType, Mappings mappings) { // ROLENAME model.Role = StringHelper.Qualify(className, path); // TODO: H3.1 has just collection.setRole(path) here - why? XmlAttribute inverseNode = node.Attributes["inverse"]; if (inverseNode != null) { model.IsInverse = StringHelper.BooleanValue(inverseNode.Value); } // TODO: H3.1 - not ported: mutable XmlAttribute olNode = node.Attributes["optimistic-lock"]; model.IsOptimisticLocked = olNode == null || "true".Equals(olNode.Value); XmlAttribute orderNode = node.Attributes["order-by"]; if (orderNode != null) { model.OrderBy = orderNode.Value; } XmlAttribute whereNode = node.Attributes["where"]; if (whereNode != null) { model.Where = whereNode.Value; } XmlAttribute batchNode = node.Attributes["batch-size"]; if (batchNode != null) { model.BatchSize = Int32.Parse(batchNode.Value); } // PERSISTER XmlAttribute persisterNode = node.Attributes["persister"]; if (persisterNode == null) { //persister = CollectionPersisterImpl.class; } else { model.CollectionPersisterClass = ClassForNameChecked( persisterNode.Value, mappings, "could not instantiate collection persister class: {0}"); } XmlAttribute typeNode = node.Attributes["collection-type"]; if (typeNode != null) { model.TypeName = typeNode.Value; } // FETCH STRATEGY InitOuterJoinFetchSetting(node, model); if ("subselect".Equals(XmlHelper.GetAttributeValue(node, "fetch"))) { model.IsSubselectLoadable = true; model.Owner.HasSubselectLoadableCollections = true; } // LAZINESS InitLaziness(node, model, mappings, "true", mappings.DefaultLazy); // TODO: H3.1 - lazy="extra" XmlNode oneToManyNode = node.SelectSingleNode(HbmConstants.nsOneToMany, nsmgr); if (oneToManyNode != null) { OneToMany oneToMany = new OneToMany(model.Owner); model.Element = oneToMany; BindOneToMany(oneToManyNode, oneToMany, mappings); //we have to set up the table later!! yuck } else { //TABLE XmlAttribute tableNode = node.Attributes["table"]; string tableName; if (tableNode != null) { tableName = mappings.NamingStrategy.TableName(tableNode.Value); } else { tableName = mappings.NamingStrategy.PropertyToTableName(className, path); } XmlAttribute schemaNode = node.Attributes["schema"]; string schema = schemaNode == null ? mappings.SchemaName : schemaNode.Value; model.CollectionTable = mappings.AddTable(schema, tableName); log.Info("Mapping collection: " + model.Role + " -> " + model.CollectionTable.Name); } //SORT XmlAttribute sortedAtt = node.Attributes["sort"]; // unsorted, natural, comparator.class.name if (sortedAtt == null || sortedAtt.Value.Equals("unsorted")) { model.IsSorted = false; } else { model.IsSorted = true; if (!sortedAtt.Value.Equals("natural")) { string comparatorClassName = FullClassName(sortedAtt.Value, mappings); try { model.Comparer = Activator.CreateInstance(ReflectHelper.ClassForName(comparatorClassName)); } catch { throw new MappingException("could not instantiate comparer class: " + comparatorClassName); } } } //ORPHAN DELETE (used for programmer error detection) XmlAttribute cascadeAtt = node.Attributes["cascade"]; if (cascadeAtt != null && cascadeAtt.Value.Equals("all-delete-orphan")) { model.OrphanDelete = true; } bool? isGeneric = null; XmlAttribute genericAtt = node.Attributes["generic"]; if (genericAtt != null) { isGeneric = bool.Parse(genericAtt.Value); } System.Type collectionType = null; if (!isGeneric.HasValue) { collectionType = GetPropertyType(node, mappings, containingType, GetPropertyName(node)); isGeneric = collectionType.IsGenericType; } model.IsGeneric = isGeneric ?? false; if (model.IsGeneric) { // Determine the generic arguments using reflection if (collectionType == null) { collectionType = GetPropertyType(node, mappings, containingType, GetPropertyName(node)); } System.Type[] genericArguments = collectionType.GetGenericArguments(); model.GenericArguments = genericArguments; } HandleCustomSQL(node, model); //set up second pass if (model is List) { mappings.AddSecondPass(new ListSecondPass(node, mappings, (List) model)); } else if (model is Map) { mappings.AddSecondPass(new MapSecondPass(node, mappings, (Map) model)); } else if (model is Set) { mappings.AddSecondPass(new SetSecondPass(node, mappings, (Set) model)); } else if (model is IdentifierCollection) { mappings.AddSecondPass(new IdentifierCollectionSecondPass(node, mappings, (IdentifierCollection) model)); } else { mappings.AddSecondPass(new CollectionSecondPass(node, mappings, model)); } foreach (XmlNode filter in node.SelectNodes(HbmConstants.nsFilter, nsmgr)) { ParseFilter(filter, model, mappings); } XmlNode loader = node.SelectSingleNode(HbmConstants.nsLoader, nsmgr); if (loader != null) { model.LoaderName = XmlHelper.GetAttributeValue(loader, "query-ref"); } }