1 package org.hibernate.cfg; 3 4 import java.io.Serializable ; 5 import java.util.ArrayList ; 6 import java.util.Comparator ; 7 import java.util.HashMap ; 8 import java.util.HashSet ; 9 import java.util.Iterator ; 10 import java.util.Properties ; 11 import java.util.StringTokenizer ; 12 13 import org.apache.commons.collections.SequencedHashMap; 14 import org.apache.commons.logging.Log; 15 import org.apache.commons.logging.LogFactory; 16 import org.dom4j.Attribute; 17 import org.dom4j.Document; 18 import org.dom4j.Element; 19 import org.hibernate.EntityMode; 20 import org.hibernate.FetchMode; 21 import org.hibernate.FlushMode; 22 import org.hibernate.LockMode; 23 import org.hibernate.MappingException; 24 import org.hibernate.engine.FilterDefinition; 25 import org.hibernate.engine.NamedQueryDefinition; 26 import org.hibernate.engine.NamedSQLQueryDefinition; 27 import org.hibernate.engine.ResultSetMappingDefinition; 28 import org.hibernate.engine.Versioning; 29 import org.hibernate.id.PersistentIdentifierGenerator; 30 import org.hibernate.loader.custom.SQLQueryCollectionReturn; 31 import org.hibernate.loader.custom.SQLQueryJoinReturn; 32 import org.hibernate.loader.custom.SQLQueryRootReturn; 33 import org.hibernate.loader.custom.SQLQueryScalarReturn; 34 import org.hibernate.mapping.Any; 35 import org.hibernate.mapping.Array; 36 import org.hibernate.mapping.Backref; 37 import org.hibernate.mapping.Bag; 38 import org.hibernate.mapping.Collection; 39 import org.hibernate.mapping.Column; 40 import org.hibernate.mapping.Component; 41 import org.hibernate.mapping.DependantValue; 42 import org.hibernate.mapping.Fetchable; 43 import org.hibernate.mapping.Filterable; 44 import org.hibernate.mapping.Formula; 45 import org.hibernate.mapping.IdentifierBag; 46 import org.hibernate.mapping.IdentifierCollection; 47 import org.hibernate.mapping.IndexBackref; 48 import org.hibernate.mapping.IndexedCollection; 49 import org.hibernate.mapping.Join; 50 import org.hibernate.mapping.JoinedSubclass; 51 import org.hibernate.mapping.KeyValue; 52 import org.hibernate.mapping.List; 53 import org.hibernate.mapping.ManyToOne; 54 import org.hibernate.mapping.Map; 55 import org.hibernate.mapping.MetaAttribute; 56 import org.hibernate.mapping.OneToMany; 57 import org.hibernate.mapping.OneToOne; 58 import org.hibernate.mapping.PersistentClass; 59 import org.hibernate.mapping.PrimitiveArray; 60 import org.hibernate.mapping.Property; 61 import org.hibernate.mapping.RootClass; 62 import org.hibernate.mapping.Selectable; 63 import org.hibernate.mapping.Set; 64 import org.hibernate.mapping.SimpleValue; 65 import org.hibernate.mapping.SingleTableSubclass; 66 import org.hibernate.mapping.Subclass; 67 import org.hibernate.mapping.Table; 68 import org.hibernate.mapping.ToOne; 69 import org.hibernate.mapping.TypeDef; 70 import org.hibernate.mapping.UnionSubclass; 71 import org.hibernate.mapping.UniqueKey; 72 import org.hibernate.mapping.Value; 73 import org.hibernate.persister.entity.JoinedSubclassEntityPersister; 74 import org.hibernate.persister.entity.SingleTableEntityPersister; 75 import org.hibernate.persister.entity.UnionSubclassEntityPersister; 76 import org.hibernate.type.DiscriminatorType; 77 import org.hibernate.type.ForeignKeyDirection; 78 import org.hibernate.type.Type; 79 import org.hibernate.type.TypeFactory; 80 import org.hibernate.util.ArrayHelper; 81 import org.hibernate.util.CollectionHelper; 82 import org.hibernate.util.JoinedIterator; 83 import org.hibernate.util.ReflectHelper; 84 import org.hibernate.util.StringHelper; 85 86 92 public final class HbmBinder { 93 94 private static final Log log = LogFactory.getLog( HbmBinder.class ); 95 96 99 private HbmBinder() { 100 } 101 102 111 public static void bindRoot(Document doc, Mappings mappings, java.util.Map inheritedMetas) 112 throws MappingException { 113 114 java.util.List names = HbmBinder.getExtendsNeeded( doc, mappings ); 115 if ( !names.isEmpty() ) { 116 for ( Iterator iter = names.iterator(); iter.hasNext(); ) { 118 String className = (String ) iter.next(); 119 mappings.addToExtendsQueue( className, doc ); 120 } 121 return; 122 } 123 124 Element hmNode = doc.getRootElement(); 125 inheritedMetas = getMetas( hmNode, inheritedMetas, true ); extractRootAttributes( hmNode, mappings ); 128 129 Iterator filterDefs = hmNode.elementIterator( "filter-def" ); 130 while ( filterDefs.hasNext() ) { 131 parseFilterDef( (Element) filterDefs.next(), mappings ); 132 } 133 134 Iterator typeDefs = hmNode.elementIterator( "typedef" ); 135 while ( typeDefs.hasNext() ) { 136 Element typeDef = (Element) typeDefs.next(); 137 String typeClass = typeDef.attributeValue( "class" ); 138 String typeName = typeDef.attributeValue( "name" ); 139 Iterator paramIter = typeDef.elementIterator( "param" ); 140 Properties parameters = new Properties (); 141 while ( paramIter.hasNext() ) { 142 Element param = (Element) paramIter.next(); 143 parameters.setProperty( param.attributeValue( "name" ), param.getTextTrim() ); 144 } 145 146 mappings.addTypeDef( typeName, typeClass, parameters ); 147 } 148 149 Iterator nodes = hmNode.elementIterator( "class" ); 150 while ( nodes.hasNext() ) { 151 Element n = (Element) nodes.next(); 152 RootClass rootclass = new RootClass(); 153 bindRootClass( n, rootclass, mappings, inheritedMetas ); 154 mappings.addClass( rootclass ); 155 } 156 157 Iterator subclassnodes = hmNode.elementIterator( "subclass" ); 158 while ( subclassnodes.hasNext() ) { 159 Element subnode = (Element) subclassnodes.next(); 160 PersistentClass superModel = getSuperclass( mappings, subnode ); 161 handleSubclass( superModel, mappings, subnode, inheritedMetas ); 162 } 163 164 Iterator joinedsubclassnodes = hmNode.elementIterator( "joined-subclass" ); 165 while ( joinedsubclassnodes.hasNext() ) { 166 Element subnode = (Element) joinedsubclassnodes.next(); 167 PersistentClass superModel = getSuperclass( mappings, subnode ); 168 handleJoinedSubclass( superModel, mappings, subnode, inheritedMetas ); 169 } 170 171 Iterator unionsubclassnodes = hmNode.elementIterator( "union-subclass" ); 172 while ( unionsubclassnodes.hasNext() ) { 173 Element subnode = (Element) unionsubclassnodes.next(); 174 PersistentClass superModel = getSuperclass( mappings, subnode ); 175 handleUnionSubclass( superModel, mappings, subnode, inheritedMetas ); 176 } 177 178 nodes = hmNode.elementIterator( "query" ); 179 while ( nodes.hasNext() ) { 180 bindNamedQuery( (Element) nodes.next(), null, mappings ); 181 } 182 183 nodes = hmNode.elementIterator( "sql-query" ); 184 while ( nodes.hasNext() ) { 185 bindNamedSQLQuery( (Element) nodes.next(), null, mappings ); 186 } 187 188 nodes = hmNode.elementIterator( "resultset" ); 189 while ( nodes.hasNext() ) { 190 bindResultSetMappingDefinition( (Element) nodes.next(), null, mappings ); 191 } 192 193 nodes = hmNode.elementIterator( "import" ); 194 while ( nodes.hasNext() ) { 195 Element n = (Element) nodes.next(); 196 String className = getClassName( n.attribute( "class" ), mappings ); 197 Attribute renameNode = n.attribute( "rename" ); 198 String rename = ( renameNode == null ) 199 ? StringHelper.unqualify( className ) 200 : renameNode.getValue(); 201 log.debug( "Import: " + rename + " -> " + className ); 202 mappings.addImport( className, rename ); 203 } 204 } 205 206 private static void extractRootAttributes(Element hmNode, Mappings mappings) { 207 Attribute schemaNode = hmNode.attribute( "schema" ); 208 mappings.setSchemaName( ( schemaNode == null ) ? null : schemaNode.getValue() ); 209 210 Attribute catalogNode = hmNode.attribute( "catalog" ); 211 mappings.setCatalogName( ( catalogNode == null ) ? null : catalogNode.getValue() ); 212 213 Attribute dcNode = hmNode.attribute( "default-cascade" ); 214 mappings.setDefaultCascade( ( dcNode == null ) ? "none" : dcNode.getValue() ); 215 216 Attribute daNode = hmNode.attribute( "default-access" ); 217 mappings.setDefaultAccess( ( daNode == null ) ? "property" : daNode.getValue() ); 218 219 Attribute dlNode = hmNode.attribute( "default-lazy" ); 220 mappings.setDefaultLazy( dlNode == null || dlNode.getValue().equals( "true" ) ); 221 222 Attribute aiNode = hmNode.attribute( "auto-import" ); 223 mappings.setAutoImport( ( aiNode == null ) ? true : "true".equals( aiNode.getValue() ) ); 224 225 Attribute packNode = hmNode.attribute( "package" ); 226 if ( packNode != null ) mappings.setDefaultPackage( packNode.getValue() ); 227 } 228 229 238 public static void bindRootClass(Element node, RootClass rootClass, Mappings mappings, 239 java.util.Map inheritedMetas) throws MappingException { 240 bindClass( node, rootClass, mappings, inheritedMetas ); 241 inheritedMetas = getMetas( node, inheritedMetas, true ); bindRootPersistentClassCommonValues( node, inheritedMetas, mappings, rootClass ); 243 } 244 245 private static void bindRootPersistentClassCommonValues(Element node, 246 java.util.Map inheritedMetas, Mappings mappings, RootClass entity) 247 throws MappingException { 248 249 251 Attribute schemaNode = node.attribute( "schema" ); 252 String schema = schemaNode == null ? mappings.getSchemaName() : schemaNode.getValue(); 253 254 Attribute catalogNode = node.attribute( "catalog" ); 255 String catalog = catalogNode == null ? mappings.getCatalogName() : catalogNode.getValue(); 256 257 Table table = mappings.addTable( 258 schema, 259 catalog, 260 getClassTableName( entity, node, mappings ), 261 getSubselect( node ), 262 entity.isAbstract() 263 ); 264 entity.setTable( table ); 265 bindComment(table, node); 266 267 log.info( "Mapping class: " 268 + entity.getEntityName() 269 + " -> " 270 + entity.getTable().getName() ); 271 272 Attribute mutableNode = node.attribute( "mutable" ); 274 entity.setMutable( ( mutableNode == null ) || mutableNode.getValue().equals( "true" ) ); 275 276 Attribute whereNode = node.attribute( "where" ); 278 if ( whereNode != null ) entity.setWhere( whereNode.getValue() ); 279 280 Attribute chNode = node.attribute( "check" ); 282 if ( chNode != null ) table.addCheckConstraint( chNode.getValue() ); 283 284 Attribute polyNode = node.attribute( "polymorphism" ); 286 entity.setExplicitPolymorphism( ( polyNode != null ) 287 && polyNode.getValue().equals( "explicit" ) ); 288 289 Attribute rowidNode = node.attribute( "rowid" ); 291 if ( rowidNode != null ) table.setRowId( rowidNode.getValue() ); 292 293 Iterator subnodes = node.elementIterator(); 294 while ( subnodes.hasNext() ) { 295 296 Element subnode = (Element) subnodes.next(); 297 String name = subnode.getName(); 298 299 if ( "id".equals( name ) ) { 300 bindSimpleId( subnode, entity, mappings, inheritedMetas ); 302 } 303 else if ( "composite-id".equals( name ) ) { 304 bindCompositeId( subnode, entity, mappings, inheritedMetas ); 306 } 307 else if ( "version".equals( name ) || "timestamp".equals( name ) ) { 308 bindVersioningProperty( table, subnode, mappings, name, entity, inheritedMetas ); 310 } 311 else if ( "discriminator".equals( name ) ) { 312 bindDiscriminatorProperty( table, entity, subnode, mappings ); 314 } 315 else if ( "cache".equals( name ) ) { 316 entity.setCacheConcurrencyStrategy( subnode.attributeValue( "usage" ) ); 317 entity.setCacheRegionName( subnode.attributeValue( "region" ) ); 318 } 319 320 } 321 322 entity.createPrimaryKey(); 324 325 createClassProperties( node, entity, mappings, inheritedMetas ); 326 } 327 328 private static void bindSimpleId(Element idNode, RootClass entity, Mappings mappings, 329 java.util.Map inheritedMetas) throws MappingException { 330 String propertyName = idNode.attributeValue( "name" ); 331 332 SimpleValue id = new SimpleValue( entity.getTable() ); 333 entity.setIdentifier( id ); 334 335 353 if ( propertyName == null ) { 354 bindSimpleValue( idNode, id, false, RootClass.DEFAULT_IDENTIFIER_COLUMN_NAME, mappings ); 355 } 356 else { 357 bindSimpleValue( idNode, id, false, propertyName, mappings ); 358 } 359 360 if ( propertyName == null || !entity.hasPojoRepresentation() ) { 361 if ( !id.isTypeSpecified() ) { 362 throw new MappingException( "must specify an identifier type: " 363 + entity.getEntityName() ); 364 } 365 } 366 else { 367 id.setTypeUsingReflection( entity.getClassName(), propertyName ); 368 } 369 370 if ( propertyName != null ) { 371 Property prop = new Property(); 372 prop.setValue( id ); 373 bindProperty( idNode, prop, mappings, inheritedMetas ); 374 entity.setIdentifierProperty( prop ); 375 } 376 377 382 makeIdentifier( idNode, id, mappings ); 383 } 384 385 private static void bindCompositeId(Element idNode, RootClass entity, Mappings mappings, 386 java.util.Map inheritedMetas) throws MappingException { 387 String propertyName = idNode.attributeValue( "name" ); 388 Component id = new Component( entity ); 389 entity.setIdentifier( id ); 390 bindCompositeId( idNode, id, entity, propertyName, mappings, inheritedMetas ); 391 if ( propertyName == null ) { 392 entity.setEmbeddedIdentifier( id.isEmbedded() ); 393 if ( id.isEmbedded() ) { 394 id.setDynamic( !entity.hasPojoRepresentation() ); 396 401 } 402 } 403 else { 404 Property prop = new Property(); 405 prop.setValue( id ); 406 bindProperty( idNode, prop, mappings, inheritedMetas ); 407 entity.setIdentifierProperty( prop ); 408 } 409 410 makeIdentifier( idNode, id, mappings ); 411 412 } 413 414 private static void bindVersioningProperty(Table table, Element subnode, Mappings mappings, 415 String name, RootClass entity, java.util.Map inheritedMetas) { 416 417 String propertyName = subnode.attributeValue( "name" ); 418 SimpleValue val = new SimpleValue( table ); 419 bindSimpleValue( subnode, val, false, propertyName, mappings ); 420 if ( !val.isTypeSpecified() ) { 421 val.setTypeName( "version".equals( name ) ? "integer" : "timestamp" ); 422 } 423 Property prop = new Property(); 424 prop.setValue( val ); 425 bindProperty( subnode, prop, mappings, inheritedMetas ); 426 makeVersion( subnode, val ); 427 entity.setVersion( prop ); 428 entity.addProperty( prop ); 429 } 430 431 private static void bindDiscriminatorProperty(Table table, RootClass entity, Element subnode, 432 Mappings mappings) { 433 SimpleValue discrim = new SimpleValue( table ); 434 entity.setDiscriminator( discrim ); 435 bindSimpleValue( 436 subnode, 437 discrim, 438 false, 439 RootClass.DEFAULT_DISCRIMINATOR_COLUMN_NAME, 440 mappings 441 ); 442 if ( !discrim.isTypeSpecified() ) { 443 discrim.setTypeName( "string" ); 444 } 446 entity.setPolymorphic( true ); 447 if ( "true".equals( subnode.attributeValue( "force" ) ) ) 448 entity.setForceDiscriminator( true ); 449 if ( "false".equals( subnode.attributeValue( "insert" ) ) ) 450 entity.setDiscriminatorInsertable( false ); 451 } 452 453 public static void bindClass(Element node, PersistentClass persistentClass, Mappings mappings, 454 java.util.Map inheritedMetas) throws MappingException { 455 Attribute lazyNode = node.attribute( "lazy" ); 458 boolean lazy = lazyNode == null ? mappings.isDefaultLazy() : "true".equals( lazyNode 459 .getValue() ); 460 persistentClass.setLazy( lazy ); 462 463 String entityName = node.attributeValue( "entity-name" ); 464 if ( entityName == null ) entityName = getClassName( node.attribute("name"), mappings ); 465 if ( entityName==null ) { 466 throw new MappingException( "Unable to determine entity name" ); 467 } 468 persistentClass.setEntityName( entityName ); 469 470 bindPojoRepresentation( node, persistentClass, mappings, inheritedMetas ); 471 bindDom4jRepresentation( node, persistentClass, mappings, inheritedMetas ); 472 bindMapRepresentation( node, persistentClass, mappings, inheritedMetas ); 473 474 bindPersistentClassCommonValues( node, persistentClass, mappings, inheritedMetas ); 475 476 } 477 478 private static void bindPojoRepresentation(Element node, PersistentClass entity, 479 Mappings mappings, java.util.Map metaTags) { 480 481 String className = getClassName( node.attribute( "name" ), mappings ); 482 String proxyName = getClassName( node.attribute( "proxy" ), mappings ); 483 484 entity.setClassName( className ); 485 486 if ( proxyName != null ) { 487 entity.setProxyInterfaceName( proxyName ); 488 entity.setLazy( true ); 489 } 490 else if ( entity.isLazy() ) { 491 entity.setProxyInterfaceName( className ); 492 } 493 494 Element tuplizer = locateTuplizerDefinition( node, EntityMode.POJO ); 495 if ( tuplizer != null ) { 496 entity.addTuplizer( EntityMode.POJO, tuplizer.attributeValue( "class" ) ); 497 } 498 } 499 500 private static void bindDom4jRepresentation(Element node, PersistentClass entity, 501 Mappings mappings, java.util.Map inheritedMetas) { 502 String nodeName = node.attributeValue( "node" ); 503 if (nodeName==null) nodeName = StringHelper.unqualify( entity.getEntityName() ); 504 entity.setNodeName(nodeName); 505 506 Element tuplizer = locateTuplizerDefinition( node, EntityMode.DOM4J ); 507 if ( tuplizer != null ) { 508 entity.addTuplizer( EntityMode.DOM4J, tuplizer.attributeValue( "class" ) ); 509 } 510 } 511 512 private static void bindMapRepresentation(Element node, PersistentClass entity, 513 Mappings mappings, java.util.Map inheritedMetas) { 514 Element tuplizer = locateTuplizerDefinition( node, EntityMode.MAP ); 515 if ( tuplizer != null ) { 516 entity.addTuplizer( EntityMode.MAP, tuplizer.attributeValue( "class" ) ); 517 } 518 } 519 520 527 private static Element locateTuplizerDefinition(Element container, EntityMode entityMode) { 528 Iterator itr = container.elements( "tuplizer" ).iterator(); 529 while( itr.hasNext() ) { 530 final Element tuplizerElem = ( Element ) itr.next(); 531 if ( entityMode.toString().equals( tuplizerElem.attributeValue( "entity-mode") ) ) { 532 return tuplizerElem; 533 } 534 } 535 return null; 536 } 537 538 private static void bindPersistentClassCommonValues(Element node, PersistentClass entity, 539 Mappings mappings, java.util.Map inheritedMetas) throws MappingException { 540 Attribute discriminatorNode = node.attribute( "discriminator-value" ); 542 entity.setDiscriminatorValue( ( discriminatorNode == null ) 543 ? entity.getEntityName() 544 : discriminatorNode.getValue() ); 545 546 Attribute dynamicNode = node.attribute( "dynamic-update" ); 548 entity.setDynamicUpdate( ( dynamicNode == null ) ? false : "true".equals( dynamicNode 549 .getValue() ) ); 550 551 Attribute insertNode = node.attribute( "dynamic-insert" ); 553 entity.setDynamicInsert( ( insertNode == null ) ? false : "true".equals( insertNode 554 .getValue() ) ); 555 556 mappings.addImport( entity.getEntityName(), entity.getEntityName() ); 558 if ( mappings.isAutoImport() && entity.getEntityName().indexOf( '.' ) > 0 ) { 559 mappings.addImport( entity.getEntityName(), StringHelper.unqualify( entity 560 .getEntityName() ) ); 561 } 562 563 Attribute batchNode = node.attribute( "batch-size" ); 565 if ( batchNode != null ) entity.setBatchSize( Integer.parseInt( batchNode.getValue() ) ); 566 567 Attribute sbuNode = node.attribute( "select-before-update" ); 569 if ( sbuNode != null ) entity.setSelectBeforeUpdate( "true".equals( sbuNode.getValue() ) ); 570 571 Attribute olNode = node.attribute( "optimistic-lock" ); 573 entity.setOptimisticLockMode( getOptimisticLockMode( olNode ) ); 574 575 entity.setMetaAttributes( getMetas( node, inheritedMetas ) ); 576 577 Attribute persisterNode = node.attribute( "persister" ); 579 if ( persisterNode == null ) { 580 } 582 else { 583 try { 584 entity.setEntityPersisterClass( ReflectHelper.classForName( persisterNode 585 .getValue() ) ); 586 } 587 catch (ClassNotFoundException cnfe) { 588 throw new MappingException( "Could not find persister class: " 589 + persisterNode.getValue() ); 590 } 591 } 592 593 handleCustomSQL( node, entity ); 595 596 Iterator tables = node.elementIterator( "synchronize" ); 597 while ( tables.hasNext() ) { 598 entity.addSynchronizedTable( ( (Element) tables.next() ).attributeValue( "table" ) ); 599 } 600 601 Attribute abstractNode = node.attribute( "abstract" ); 602 if ( abstractNode != null ) entity.setAbstract( "true".equals( abstractNode.getValue() ) ); 603 } 604 605 private static void handleCustomSQL(Element node, PersistentClass model) 606 throws MappingException { 607 Element element = node.element( "sql-insert" ); 608 if ( element != null ) { 609 boolean callable = false; 610 callable = isCallable( element ); 611 model.setCustomSQLInsert( element.getText(), callable ); 612 } 613 614 element = node.element( "sql-delete" ); 615 if ( element != null ) { 616 boolean callable = false; 617 callable = isCallable( element ); 618 model.setCustomSQLDelete( element.getText(), callable ); 619 } 620 621 element = node.element( "sql-update" ); 622 if ( element != null ) { 623 boolean callable = false; 624 callable = isCallable( element ); 625 model.setCustomSQLUpdate( element.getText(), callable ); 626 } 627 628 element = node.element( "loader" ); 629 if ( element != null ) { 630 model.setLoaderName( element.attributeValue( "query-ref" ) ); 631 } 632 } 633 634 private static void handleCustomSQL(Element node, Join model) throws MappingException { 635 Element element = node.element( "sql-insert" ); 636 if ( element != null ) { 637 boolean callable = false; 638 callable = isCallable( element ); 639 model.setCustomSQLInsert( element.getText(), callable ); 640 } 641 642 element = node.element( "sql-delete" ); 643 if ( element != null ) { 644 boolean callable = false; 645 callable = isCallable( element ); 646 model.setCustomSQLDelete( element.getText(), callable ); 647 } 648 649 element = node.element( "sql-update" ); 650 if ( element != null ) { 651 boolean callable = false; 652 callable = isCallable( element ); 653 model.setCustomSQLUpdate( element.getText(), callable ); 654 } 655 } 656 657 private static void handleCustomSQL(Element node, Collection model) throws MappingException { 658 Element element = node.element( "sql-insert" ); 659 if ( element != null ) { 660 boolean callable = false; 661 callable = isCallable( element, true ); 662 model.setCustomSQLInsert( element.getText(), callable ); 663 } 664 665 element = node.element( "sql-delete" ); 666 if ( element != null ) { 667 boolean callable = false; 668 callable = isCallable( element, true ); 669 model.setCustomSQLDelete( element.getText(), callable ); 670 } 671 672 element = node.element( "sql-update" ); 673 if ( element != null ) { 674 boolean callable = false; 675 callable = isCallable( element, true ); 676 model.setCustomSQLUpdate( element.getText(), callable ); 677 } 678 679 element = node.element( "sql-delete-all" ); 680 if ( element != null ) { 681 boolean callable = false; 682 callable = isCallable( element, true ); 683 model.setCustomSQLDeleteAll( element.getText(), callable ); 684 } 685 } 686 687 private static boolean isCallable(Element e) throws MappingException { 688 return isCallable( e, true ); 689 } 690 691 696 private static boolean isCallable(Element element, boolean supportsCallable) 697 throws MappingException { 698 Attribute attrib = element.attribute( "callable" ); 699 if ( attrib != null && "true".equals( attrib.getValue() ) ) { 700 if ( !supportsCallable ) { 701 throw new MappingException( "callable attribute not supported yet!" ); 702 } 703 return true; 704 } 705 return false; 706 } 707 708 public static void bindUnionSubclass(Element node, UnionSubclass unionSubclass, 709 Mappings mappings, java.util.Map inheritedMetas) throws MappingException { 710 711 bindClass( node, unionSubclass, mappings, inheritedMetas ); 712 inheritedMetas = getMetas( node, inheritedMetas, true ); 714 if ( unionSubclass.getEntityPersisterClass() == null ) { 715 unionSubclass.getRootClass().setEntityPersisterClass( 716 UnionSubclassEntityPersister.class ); 717 } 718 719 Attribute schemaNode = node.attribute( "schema" ); 720 String schema = schemaNode == null ? mappings.getSchemaName() : schemaNode.getValue(); 721 722 Attribute catalogNode = node.attribute( "catalog" ); 723 String catalog = catalogNode == null ? mappings.getCatalogName() : catalogNode.getValue(); 724 725 Table mytable = mappings.addDenormalizedTable( 726 schema, 727 catalog, 728 getClassTableName(unionSubclass, node, mappings ), 729 unionSubclass.isAbstract(), 730 getSubselect( node ), 731 unionSubclass.getSuperclass().getTable() ); 732 unionSubclass.setTable( mytable ); 733 734 log.info( "Mapping union-subclass: " 735 + unionSubclass.getEntityName() 736 + " -> " 737 + unionSubclass.getTable().getName() ); 738 739 createClassProperties( node, unionSubclass, mappings, inheritedMetas ); 740 741 } 742 743 public static void bindSubclass(Element node, Subclass subclass, Mappings mappings, 744 java.util.Map inheritedMetas) throws MappingException { 745 746 bindClass( node, subclass, mappings, inheritedMetas ); 747 inheritedMetas = getMetas( node, inheritedMetas, true ); 749 if ( subclass.getEntityPersisterClass() == null ) { 750 subclass.getRootClass().setEntityPersisterClass( SingleTableEntityPersister.class ); 751 } 752 753 log.info( "Mapping subclass: " 754 + subclass.getEntityName() 755 + " -> " 756 + subclass.getTable().getName() ); 757 758 createClassProperties( node, subclass, mappings, inheritedMetas ); 760 } 761 762 private static String getClassTableName(PersistentClass model, Element node, Mappings mappings) { 763 Attribute tableNameNode = node.attribute( "table" ); 764 if ( tableNameNode == null ) { 765 return mappings.getNamingStrategy().classToTableName( model.getEntityName() ); 766 } 767 else { 768 return mappings.getNamingStrategy().tableName( tableNameNode.getValue() ); 769 } 770 } 771 772 public static void bindJoinedSubclass(Element node, JoinedSubclass joinedSubclass, 773 Mappings mappings, java.util.Map inheritedMetas) throws MappingException { 774 775 bindClass( node, joinedSubclass, mappings, inheritedMetas ); 776 inheritedMetas = getMetas( node, inheritedMetas, true ); 779 if ( joinedSubclass.getEntityPersisterClass() == null ) { 781 joinedSubclass.getRootClass().setEntityPersisterClass( 782 JoinedSubclassEntityPersister.class ); 783 } 784 785 Attribute schemaNode = node.attribute( "schema" ); 786 String schema = schemaNode == null ? mappings.getSchemaName() : schemaNode.getValue(); 787 788 Attribute catalogNode = node.attribute( "catalog" ); 789 String catalog = catalogNode == null ? mappings.getCatalogName() : catalogNode.getValue(); 790 791 Table mytable = mappings.addTable( 792 schema, 793 catalog, 794 getClassTableName( joinedSubclass, node, mappings ), 795 getSubselect( node ), 796 false ); 797 joinedSubclass.setTable( mytable ); 798 bindComment(mytable, node); 799 800 log.info( "Mapping joined-subclass: " 801 + joinedSubclass.getEntityName() 802 + " -> " 803 + joinedSubclass.getTable().getName() ); 804 805 Element keyNode = node.element( "key" ); 807 SimpleValue key = new DependantValue( mytable, joinedSubclass.getIdentifier() ); 808 joinedSubclass.setKey( key ); 809 key.setCascadeDeleteEnabled( "cascade".equals( keyNode.attributeValue( "on-delete" ) ) ); 810 bindSimpleValue( keyNode, key, false, joinedSubclass.getEntityName(), mappings ); 811 812 joinedSubclass.createPrimaryKey(); 814 joinedSubclass.createForeignKey(); 815 816 Attribute chNode = node.attribute( "check" ); 818 if ( chNode != null ) mytable.addCheckConstraint( chNode.getValue() ); 819 820 createClassProperties( node, joinedSubclass, mappings, inheritedMetas ); 822 823 } 824 825 private static void bindJoin(Element node, Join join, Mappings mappings, 826 java.util.Map inheritedMetas) throws MappingException { 827 828 PersistentClass persistentClass = join.getPersistentClass(); 829 String path = persistentClass.getEntityName(); 830 831 833 Attribute schemaNode = node.attribute( "schema" ); 834 String schema = schemaNode == null ? mappings.getSchemaName() : schemaNode.getValue(); 835 836 Attribute catalogNode = node.attribute( "catalog" ); 837 String catalog = catalogNode == null ? mappings.getCatalogName() : catalogNode.getValue(); 838 839 Table table = mappings.addTable( 840 schema, 841 catalog, 842 getClassTableName( persistentClass, node, mappings ), 843 getSubselect( node ), 844 false ); 845 join.setTable( table ); 846 bindComment(table, node); 847 848 Attribute fetchNode = node.attribute( "fetch" ); 849 if ( fetchNode != null ) 850 join.setSequentialSelect( "select".equals( fetchNode.getValue() ) ); 851 852 Attribute invNode = node.attribute( "inverse" ); 853 if ( invNode != null ) join.setInverse( "true".equals( invNode.getValue() ) ); 854 855 Attribute nullNode = node.attribute( "optional" ); 856 if ( nullNode != null ) join.setOptional( "true".equals( nullNode.getValue() ) ); 857 858 log.info( "Mapping class join: " 859 + persistentClass.getEntityName() 860 + " -> " 861 + join.getTable().getName() ); 862 863 Element keyNode = node.element( "key" ); 865 SimpleValue key = new DependantValue( table, persistentClass.getIdentifier() ); 866 join.setKey( key ); 867 key.setCascadeDeleteEnabled( "cascade".equals( keyNode.attributeValue( "on-delete" ) ) ); 868 bindSimpleValue( keyNode, key, false, persistentClass.getEntityName(), mappings ); 869 870 join.createPrimaryKey(); 872 join.createForeignKey(); 873 874 Iterator iter = node.elementIterator(); 876 while ( iter.hasNext() ) { 877 Element subnode = (Element) iter.next(); 878 String name = subnode.getName(); 879 String propertyName = subnode.attributeValue( "name" ); 880 881 Value value = null; 882 if ( "many-to-one".equals( name ) ) { 883 value = new ManyToOne( table ); 884 bindManyToOne( subnode, (ManyToOne) value, propertyName, true, mappings ); 885 } 886 else if ( "any".equals( name ) ) { 887 value = new Any( table ); 888 bindAny( subnode, (Any) value, true, mappings ); 889 } 890 else if ( "property".equals( name ) ) { 891 value = new SimpleValue( table ); 892 bindSimpleValue( subnode, (SimpleValue) value, true, propertyName, mappings ); 893 } 894 else if ( "component".equals( name ) || "dynamic-component".equals( name ) ) { 895 String subpath = StringHelper.qualify( path, propertyName ); 896 value = new Component( join ); 897 bindComponent( 898 subnode, 899 (Component) value, 900 join.getPersistentClass().getClassName(), 901 propertyName, 902 subpath, 903 true, 904 false, 905 mappings, 906 inheritedMetas, 907 false 908 ); 909 } 910 911 if ( value != null ) { 912 Property prop = createProperty( value, propertyName, persistentClass 913 .getEntityName(), subnode, mappings, inheritedMetas ); 914 prop.setOptional( join.isOptional() ); 915 join.addProperty( prop ); 916 } 917 918 } 919 920 handleCustomSQL( node, join ); 922 923 } 924 925 public static void bindColumns(final Element node, final SimpleValue simpleValue, 926 final boolean isNullable, final boolean autoColumn, final String propertyPath, 927 final Mappings mappings) throws MappingException { 928 929 Table table = simpleValue.getTable(); 930 931 Attribute columnAttribute = node.attribute( "column" ); 933 if ( columnAttribute == null ) { 934 Iterator iter = node.elementIterator(); 935 int count = 0; 936 while ( iter.hasNext() ) { 937 Element columnElement = (Element) iter.next(); 938 if ( columnElement.getName().equals( "column" ) ) { 939 Column column = new Column(); 940 column.setValue( simpleValue ); 941 column.setTypeIndex( count++ ); 942 bindColumn( columnElement, column, isNullable ); 943 column.setName( mappings.getNamingStrategy().columnName( 944 columnElement.attributeValue( "name" ) ) ); 945 if ( table != null ) table.addColumn( column ); simpleValue.addColumn( column ); 948 bindIndex( columnElement.attribute( "index" ), table, column ); 950 bindIndex( node.attribute( "index" ), table, column ); 951 bindUniqueKey( columnElement.attribute( "unique-key" ), table, column ); 953 bindUniqueKey( node.attribute( "unique-key" ), table, column ); 954 } 955 else if ( columnElement.getName().equals( "formula" ) ) { 956 Formula formula = new Formula(); 957 formula.setFormula( columnElement.getText() ); 958 simpleValue.addFormula( formula ); 959 } 960 } 961 } 962 else { 963 if ( node.elementIterator( "column" ).hasNext() ) { 964 throw new MappingException( 965 "column attribute may not be used together with <column> subelement" ); 966 } 967 if ( node.elementIterator( "formula" ).hasNext() ) { 968 throw new MappingException( 969 "column attribute may not be used together with <formula> subelement" ); 970 } 971 972 Column column = new Column(); 973 column.setValue( simpleValue ); 974 bindColumn( node, column, isNullable ); 975 column.setName( mappings.getNamingStrategy().columnName( columnAttribute.getValue() ) ); 976 if ( table != null ) table.addColumn( column ); simpleValue.addColumn( column ); 979 bindIndex( node.attribute( "index" ), table, column ); 980 bindUniqueKey( node.attribute( "unique-key" ), table, column ); 981 } 982 983 if ( autoColumn && simpleValue.getColumnSpan() == 0 ) { 984 Column col = new Column(); 985 col.setValue( simpleValue ); 986 bindColumn( node, col, isNullable ); 987 col.setName( mappings.getNamingStrategy().propertyToColumnName( propertyPath ) ); 988 simpleValue.getTable().addColumn( col ); 989 simpleValue.addColumn( col ); 990 bindIndex( node.attribute( "index" ), table, col ); 991 bindUniqueKey( node.attribute( "unique-key" ), table, col ); 992 } 993 994 } 995 996 private static void bindIndex(Attribute indexAttribute, Table table, Column column) { 997 if ( indexAttribute != null && table != null ) { 998 StringTokenizer tokens = new StringTokenizer ( indexAttribute.getValue(), ", " ); 999 while ( tokens.hasMoreTokens() ) { 1000 table.getOrCreateIndex( tokens.nextToken() ).addColumn( column ); 1001 } 1002 } 1003 } 1004 1005 private static void bindUniqueKey(Attribute uniqueKeyAttribute, Table table, Column column) { 1006 if ( uniqueKeyAttribute != null && table != null ) { 1007 StringTokenizer tokens = new StringTokenizer ( uniqueKeyAttribute.getValue(), ", " ); 1008 while ( tokens.hasMoreTokens() ) { 1009 table.getOrCreateUniqueKey( tokens.nextToken() ).addColumn( column ); 1010 } 1011 } 1012 } 1013 1014 public static void bindSimpleValue(Element node, SimpleValue simpleValue, boolean isNullable, 1016 String path, Mappings mappings) throws MappingException { 1017 bindSimpleValueType( node, simpleValue, mappings ); 1018 1019 bindColumnsOrFormula( node, simpleValue, path, isNullable, mappings ); 1020 1021 Attribute fkNode = node.attribute( "foreign-key" ); 1022 if ( fkNode != null ) simpleValue.setForeignKeyName( fkNode.getValue() ); 1023 } 1024 1025 private static void bindSimpleValueType(Element node, SimpleValue simpleValue, Mappings mappings) 1026 throws MappingException { 1027 String typeName = null; 1028 1029 Properties parameters = new Properties (); 1030 1031 Attribute typeNode = node.attribute( "type" ); 1032 if ( typeNode == null ) typeNode = node.attribute( "id-type" ); if ( typeNode != null ) typeName = typeNode.getValue(); 1034 1035 Element typeChild = node.element( "type" ); 1036 if ( typeName == null && typeChild != null ) { 1037 typeName = typeChild.attribute( "name" ).getValue(); 1038 Iterator typeParameters = typeChild.elementIterator( "param" ); 1039 1040 while ( typeParameters.hasNext() ) { 1041 Element paramElement = (Element) typeParameters.next(); 1042 parameters.setProperty( paramElement.attributeValue( "name" ), paramElement 1043 .getTextTrim() ); 1044 } 1045 } 1046 1047 TypeDef typeDef = mappings.getTypeDef( typeName ); 1048 if ( typeDef != null ) { 1049 typeName = typeDef.getTypeClass(); 1050 Properties allParameters = new Properties (); 1053 allParameters.putAll( typeDef.getParameters() ); 1054 allParameters.putAll( parameters ); 1055 parameters = allParameters; 1056 } 1057 1058 if ( !parameters.isEmpty() ) simpleValue.setTypeParameters( parameters ); 1059 1060 if ( typeName != null ) simpleValue.setTypeName( typeName ); 1061 } 1062 1063 public static void bindProperty(Element node, Property property, Mappings mappings, 1064 java.util.Map inheritedMetas) throws MappingException { 1065 1066 String propName = node.attributeValue( "name" ); 1067 property.setName( propName ); 1068 String nodeName = node.attributeValue( "node" ); 1069 if (nodeName==null) nodeName = propName; 1070 property.setNodeName( nodeName ); 1071 1072 1077 Attribute accessNode = node.attribute( "access" ); 1078 if ( accessNode != null ) { 1079 property.setPropertyAccessorName( accessNode.getValue() ); 1080 } 1081 else if ( node.getName().equals( "properties" ) ) { 1082 property.setPropertyAccessorName( "embedded" ); 1083 } 1084 else { 1085 property.setPropertyAccessorName( mappings.getDefaultAccess() ); 1086 } 1087 1088 Attribute cascadeNode = node.attribute( "cascade" ); 1089 property.setCascade( cascadeNode == null ? mappings.getDefaultCascade() : cascadeNode 1090 .getValue() ); 1091 1092 Attribute updateNode = node.attribute( "update" ); 1093 property.setUpdateable( updateNode == null || "true".equals( updateNode.getValue() ) ); 1094 1095 Attribute insertNode = node.attribute( "insert" ); 1096 property.setInsertable( insertNode == null || "true".equals( insertNode.getValue() ) ); 1097 1098 Attribute lockNode = node.attribute( "optimistic-lock" ); 1099 property.setOptimisticLocked( lockNode == null || "true".equals( lockNode.getValue() ) ); 1100 1101 boolean isLazyable = "property".equals( node.getName() ) 1102 || "component".equals( node.getName() ) 1103 || "many-to-one".equals( node.getName() ) 1104 || "one-to-one".equals( node.getName() ) 1105 || "any".equals( node.getName() ); 1106 if ( isLazyable ) { 1107 Attribute lazyNode = node.attribute( "lazy" ); 1108 property.setLazy( lazyNode != null && "true".equals( lazyNode.getValue() ) ); 1109 } 1110 1111 if ( log.isDebugEnabled() ) { 1112 String msg = "Mapped property: " + property.getName(); 1113 String columns = columns( property.getValue() ); 1114 if ( columns.length() > 0 ) msg += " -> " + columns; 1115 log.debug( msg ); 1118 } 1119 1120 property.setMetaAttributes( getMetas( node, inheritedMetas ) ); 1121 1122 } 1123 1124 private static String columns(Value val) { 1125 StringBuffer columns = new StringBuffer (); 1126 Iterator iter = val.getColumnIterator(); 1127 while ( iter.hasNext() ) { 1128 columns.append( ( (Selectable) iter.next() ).getText() ); 1129 if ( iter.hasNext() ) columns.append( ", " ); 1130 } 1131 return columns.toString(); 1132 } 1133 1134 1137 public static void bindCollection(Element node, Collection collection, String className, 1138 String path, Mappings mappings) throws MappingException { 1139 1140 collection.setRole(path); 1142 1143 Attribute inverseNode = node.attribute( "inverse" ); 1144 if ( inverseNode != null ) { 1145 collection.setInverse( "true".equals( inverseNode.getValue() ) ); 1146 } 1147 1148 Attribute mutableNode = node.attribute( "mutable" ); 1149 if ( mutableNode != null ) { 1150 collection.setMutable( !"false".equals( mutableNode.getValue() ) ); 1151 } 1152 1153 Attribute olNode = node.attribute( "optimistic-lock" ); 1154 collection.setOptimisticLocked( olNode == null || "true".equals( olNode.getValue() ) ); 1155 1156 Attribute orderNode = node.attribute( "order-by" ); 1157 if ( orderNode != null ) { 1158 if ( Environment.jvmSupportsLinkedHashCollections() || ( collection instanceof Bag ) ) { 1159 collection.setOrderBy( orderNode.getValue() ); 1160 } 1161 else { 1162 log.warn( "Attribute \"order-by\" ignored in JDK1.3 or less" ); 1163 } 1164 } 1165 Attribute whereNode = node.attribute( "where" ); 1166 if ( whereNode != null ) { 1167 collection.setWhere( whereNode.getValue() ); 1168 } 1169 Attribute batchNode = node.attribute( "batch-size" ); 1170 if ( batchNode != null ) { 1171 collection.setBatchSize( Integer.parseInt( batchNode.getValue() ) ); 1172 } 1173 1174 String nodeName = node.attributeValue( "node" ); 1175 if ( nodeName == null ) nodeName = node.attributeValue( "name" ); 1176 collection.setNodeName( nodeName ); 1177 String embed = node.attributeValue( "embed-xml" ); 1178 collection.setEmbedded( embed==null || "true".equals(embed) ); 1179 1180 1181 Attribute persisterNode = node.attribute( "persister" ); 1183 if ( persisterNode != null ) { 1184 try { 1185 collection.setCollectionPersisterClass( ReflectHelper.classForName( persisterNode 1186 .getValue() ) ); 1187 } 1188 catch (ClassNotFoundException cnfe) { 1189 throw new MappingException( "Could not find collection persister class: " 1190 + persisterNode.getValue() ); 1191 } 1192 } 1193 1194 Attribute typeNode = node.attribute( "collection-type" ); 1195 if ( typeNode != null ) collection.setTypeName( typeNode.getValue() ); 1196 1197 1199 initOuterJoinFetchSetting( node, collection ); 1200 1201 if ( "subselect".equals( node.attributeValue("fetch") ) ) { 1202 collection.setSubselectLoadable(true); 1203 collection.getOwner().setSubselectLoadableCollections(true); 1204 } 1205 1206 initLaziness( node, collection, mappings, "true", mappings.isDefaultLazy() ); 1207 1208 Element oneToManyNode = node.element( "one-to-many" ); 1209 if ( oneToManyNode != null ) { 1210 OneToMany oneToMany = new OneToMany( collection.getOwner() ); 1211 collection.setElement( oneToMany ); 1212 bindOneToMany( oneToManyNode, oneToMany, mappings ); 1213 } 1215 else { 1216 Attribute tableNode = node.attribute( "table" ); 1218 String tableName; 1219 if ( tableNode != null ) { 1220 tableName = mappings.getNamingStrategy().tableName( tableNode.getValue() ); 1221 } 1222 else { 1223 tableName = mappings.getNamingStrategy().propertyToTableName( className, path ); 1224 } 1225 Attribute schemaNode = node.attribute( "schema" ); 1226 String schema = schemaNode == null ? mappings.getSchemaName() : schemaNode.getValue(); 1227 1228 Attribute catalogNode = node.attribute( "catalog" ); 1229 String catalog = catalogNode == null ? mappings.getCatalogName() : catalogNode 1230 .getValue(); 1231 1232 Table table = mappings.addTable( 1233 schema, 1234 catalog, 1235 tableName, 1236 getSubselect( node ), 1237 false ); 1238 collection.setCollectionTable( table ); 1239 bindComment(table, node); 1240 1241 log.info( "Mapping collection: " 1242 + collection.getRole() 1243 + " -> " 1244 + collection.getCollectionTable().getName() ); 1245 } 1246 1247 Attribute sortedAtt = node.attribute( "sort" ); 1249 if ( sortedAtt == null || sortedAtt.getValue().equals( "unsorted" ) ) { 1251 collection.setSorted( false ); 1252 } 1253 else { 1254 collection.setSorted( true ); 1255 String comparatorClassName = sortedAtt.getValue(); 1256 if ( !comparatorClassName.equals( "natural" ) ) { 1257 try { 1258 collection.setComparator( (Comparator ) ReflectHelper.classForName( 1259 comparatorClassName ).newInstance() ); 1260 } 1261 catch (Exception e) { 1262 throw new MappingException( "Could not instantiate comparator class: " 1263 + comparatorClassName ); 1264 } 1265 } 1266 } 1267 1268 Attribute cascadeAtt = node.attribute( "cascade" ); 1270 if ( cascadeAtt != null && cascadeAtt.getValue().indexOf( "delete-orphan" ) >= 0 ) { 1271 collection.setOrphanDelete( true ); 1272 } 1273 1274 handleCustomSQL( node, collection ); 1276 if ( collection instanceof List ) { 1278 mappings.addSecondPass( new ListSecondPass( node, mappings, (List ) collection ) ); 1279 } 1280 else if ( collection instanceof Map ) { 1281 mappings.addSecondPass( new MapSecondPass( node, mappings, (Map ) collection ) ); 1282 } 1283 else if ( collection instanceof IdentifierCollection ) { 1284 mappings.addSecondPass( new IdentifierCollectionSecondPass( 1285 node, 1286 mappings, 1287 (IdentifierCollection) collection ) ); 1288 } 1289 else { 1290 mappings.addSecondPass( new CollectionSecondPass( node, mappings, collection ) ); 1291 } 1292 1293 Iterator iter = node.elementIterator( "filter" ); 1294 while ( iter.hasNext() ) { 1295 final Element filter = (Element) iter.next(); 1296 parseFilter( filter, collection, mappings ); 1297 } 1298 1299 Iterator tables = node.elementIterator( "synchronize" ); 1300 while ( tables.hasNext() ) { 1301 collection.getSynchronizedTables().add( 1302 ( (Element) tables.next() ).attributeValue( "table" ) ); 1303 } 1304 1305 Element element = node.element( "loader" ); 1306 if ( element != null ) { 1307 collection.setLoaderName( element.attributeValue( "query-ref" ) ); 1308 } 1309 1310 collection.setReferencedPropertyName( node.element( "key" ).attributeValue( "property-ref" ) ); 1311 } 1312 1313 private static void initLaziness( 1314 Element node, 1315 Fetchable fetchable, 1316 Mappings mappings, 1317 String proxyVal, 1318 boolean defaultLazy 1319 ) { 1320 Attribute lazyNode = node.attribute( "lazy" ); 1321 boolean isLazyTrue = lazyNode == null ? 1322 defaultLazy && fetchable.isLazy() : lazyNode.getValue().equals(proxyVal); fetchable.setLazy( isLazyTrue ); 1325 } 1326 1327 private static void initLaziness( 1328 Element node, 1329 ToOne fetchable, 1330 Mappings mappings, 1331 boolean defaultLazy 1332 ) { 1333 if ( "no-proxy".equals( node.attributeValue( "lazy" ) ) ) { 1334 fetchable.setUnwrapProxy(true); 1335 fetchable.setLazy(true); 1336 } 1338 else { 1339 initLaziness(node, fetchable, mappings, "proxy", defaultLazy); 1340 } 1341 } 1342 1343 private static void bindColumnsOrFormula(Element node, SimpleValue simpleValue, String path, 1344 boolean isNullable, Mappings mappings) { 1345 Attribute formulaNode = node.attribute( "formula" ); 1346 if ( formulaNode != null ) { 1347 Formula f = new Formula(); 1348 f.setFormula( formulaNode.getText() ); 1349 simpleValue.addFormula( f ); 1350 } 1351 else { 1352 bindColumns( node, simpleValue, isNullable, true, path, mappings ); 1353 } 1354 } 1355 1356 private static void bindComment(Table table, Element node) { 1357 Element comment = node.element("comment"); 1358 if (comment!=null) table.setComment( comment.getTextTrim() ); 1359 } 1360 1361 public static void bindManyToOne(Element node, ManyToOne manyToOne, String path, 1362 boolean isNullable, Mappings mappings) throws MappingException { 1363 1364 bindColumnsOrFormula( node, manyToOne, path, isNullable, mappings ); 1365 initOuterJoinFetchSetting( node, manyToOne ); 1366 initLaziness( node, manyToOne, mappings, true ); 1367 1368 Attribute ukName = node.attribute( "property-ref" ); 1369 if ( ukName != null ) { 1370 manyToOne.setReferencedPropertyName( ukName.getValue() ); 1371 } 1372 1373 manyToOne.setReferencedEntityName( getEntityName( node, mappings ) ); 1374 1375 String embed = node.attributeValue( "embed-xml" ); 1376 manyToOne.setEmbedded( embed == null || "true".equals( embed ) ); 1377 1378 String notFound = node.attributeValue( "not-found" ); 1379 manyToOne.setIgnoreNotFound( "ignore".equals( notFound ) ); 1380 1381 if( ukName != null && !manyToOne.isIgnoreNotFound() ) { 1382 if ( !node.getName().equals("many-to-many") ) { mappings.addSecondPass( new ManyToOneSecondPass(mappings,manyToOne) ); 1384 } 1385 } 1386 1387 Attribute fkNode = node.attribute( "foreign-key" ); 1388 if ( fkNode != null ) manyToOne.setForeignKeyName( fkNode.getValue() ); 1389 1390 validateCascade( node, path ); 1391 } 1392 1393 private static void validateCascade(Element node, String path) { 1394 String cascade = node.attributeValue("cascade"); 1395 if ( cascade!=null && cascade.indexOf("delete-orphan")>0 ) { 1396 throw new MappingException("single-valued associations do not support orphan delete: " + path); 1397 } 1398 } 1399 1400 public static void bindAny(Element node, Any any, boolean isNullable, Mappings mappings) 1401 throws MappingException { 1402 any.setIdentifierType( getTypeFromXML( node ) ); 1403 Attribute metaAttribute = node.attribute( "meta-type" ); 1404 if ( metaAttribute != null ) { 1405 any.setMetaType( metaAttribute.getValue() ); 1406 1407 Iterator iter = node.elementIterator( "meta-value" ); 1408 if ( iter.hasNext() ) { 1409 HashMap values = new HashMap (); 1410 org.hibernate.type.Type metaType = TypeFactory.heuristicType( any.getMetaType() ); 1411 while ( iter.hasNext() ) { 1412 Element metaValue = (Element) iter.next(); 1413 try { 1414 Object value = ( (DiscriminatorType) metaType ).stringToObject( metaValue 1415 .attributeValue( "value" ) ); 1416 String entityName = getClassName( metaValue.attribute( "class" ), mappings ); 1417 values.put( value, entityName ); 1418 } 1419 catch (ClassCastException cce) { 1420 throw new MappingException( "meta-type was not a DiscriminatorType: " 1421 + metaType.getName() ); 1422 } 1423 catch (Exception e) { 1424 throw new MappingException( "could not interpret meta-value", e ); 1425 } 1426 } 1427 any.setMetaValues( values ); 1428 } 1429 1430 } 1431 1432 bindColumns( node, any, isNullable, false, null, mappings ); 1433 } 1434 1435 public static void bindOneToOne(Element node, OneToOne oneToOne, String path, boolean isNullable, 1436 Mappings mappings) throws MappingException { 1437 1438 bindColumns( node, oneToOne, isNullable, false, null, mappings ); 1439 1440 Attribute constrNode = node.attribute( "constrained" ); 1441 boolean constrained = constrNode != null && constrNode.getValue().equals( "true" ); 1442 oneToOne.setConstrained( constrained ); 1443 1444 oneToOne.setForeignKeyType( constrained ? 1445 ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT : 1446 ForeignKeyDirection.FOREIGN_KEY_TO_PARENT ); 1447 1448 initOuterJoinFetchSetting( node, oneToOne ); 1449 initLaziness( node, oneToOne, mappings, true ); 1450 1451 oneToOne.setEmbedded( "true".equals( node.attributeValue( "embed-xml" ) ) ); 1452 1453 Attribute fkNode = node.attribute( "foreign-key" ); 1454 if ( fkNode != null ) oneToOne.setForeignKeyName( fkNode.getValue() ); 1455 1456 Attribute ukName = node.attribute( "property-ref" ); 1457 if ( ukName != null ) oneToOne.setReferencedPropertyName( ukName.getValue() ); 1458 1459 oneToOne.setPropertyName( node.attributeValue( "name" ) ); 1460 1461 oneToOne.setReferencedEntityName( getEntityName( node, mappings ) ); 1462 1463 validateCascade( node, path ); 1464 } 1465 1466 public static void bindOneToMany(Element node, OneToMany oneToMany, Mappings mappings) 1467 throws MappingException { 1468 1469 oneToMany.setReferencedEntityName( getEntityName( node, mappings ) ); 1470 1471 String embed = node.attributeValue( "embed-xml" ); 1472 oneToMany.setEmbedded( embed == null || "true".equals( embed ) ); 1473 1474 String notFound = node.attributeValue( "not-found" ); 1475 oneToMany.setIgnoreNotFound( "ignore".equals( notFound ) ); 1476 1477 } 1478 1479 public static void bindColumn(Element node, Column column, boolean isNullable) { 1480 Attribute lengthNode = node.attribute( "length" ); 1481 if ( lengthNode != null ) column.setLength( Integer.parseInt( lengthNode.getValue() ) ); 1482 Attribute scalNode = node.attribute( "scale" ); 1483 if ( scalNode != null ) column.setScale( Integer.parseInt( scalNode.getValue() ) ); 1484 Attribute precNode = node.attribute( "precision" ); 1485 if ( precNode != null ) column.setPrecision( Integer.parseInt( precNode.getValue() ) ); 1486 1487 Attribute nullNode = node.attribute( "not-null" ); 1488 column.setNullable( nullNode == null ? isNullable : nullNode.getValue().equals( "false" ) ); 1489 1490 Attribute unqNode = node.attribute( "unique" ); 1491 if ( unqNode != null ) column.setUnique( unqNode.getValue().equals( "true" ) ); 1492 1493 column.setCheckConstraint( node.attributeValue( "check" ) ); 1494 1495 Attribute typeNode = node.attribute( "sql-type" ); 1496 if ( typeNode != null ) column.setSqlType( typeNode.getValue() ); 1497 1498 Element comment = node.element("comment"); 1499 if (comment!=null) column.setComment( comment.getTextTrim() ); 1500 1501 } 1502 1503 1506 public static void bindArray(Element node, Array array, String prefix, String path, 1507 Mappings mappings) throws MappingException { 1508 1509 bindCollection( node, array, prefix, path, mappings ); 1510 1511 Attribute att = node.attribute( "element-class" ); 1512 if ( att != null ) array.setElementClassName( getClassName( att, mappings ) ); 1513 1514 } 1515 1516 private static Class reflectedPropertyClass(String className, String propertyName) 1517 throws MappingException { 1518 if ( className == null ) return null; 1519 return ReflectHelper.reflectedPropertyClass( className, propertyName ); 1520 } 1521 1522 public static void bindComposite(Element node, Component component, String path, 1523 boolean isNullable, Mappings mappings, java.util.Map inheritedMetas) 1524 throws MappingException { 1525 bindComponent( 1526 node, 1527 component, 1528 null, 1529 null, 1530 path, 1531 isNullable, 1532 false, 1533 mappings, 1534 inheritedMetas, 1535 false 1536 ); 1537 } 1538 1539 public static void bindCompositeId(Element node, Component component, 1540 PersistentClass persistentClass, String propertyName, Mappings mappings, 1541 java.util.Map inheritedMetas) throws MappingException { 1542 1543 component.setKey( true ); 1544 1545 String path = StringHelper.qualify( 1546 persistentClass.getEntityName(), 1547 propertyName == null ? "id" : propertyName ); 1548 1549 bindComponent( 1550 node, 1551 component, 1552 persistentClass.getClassName(), 1553 propertyName, 1554 path, 1555 false, 1556 node.attribute( "class" ) == null 1557 && propertyName == null, 1558 mappings, 1559 inheritedMetas, 1560 false 1561 ); 1562 1563 if ( "true".equals( node.attributeValue("mapped") ) ) { 1564 if ( propertyName!=null ) { 1565 throw new MappingException("cannot combine mapped=\"true\" with specified name"); 1566 } 1567 Component mapper = new Component(persistentClass); 1568 bindComponent( 1569 node, 1570 mapper, 1571 persistentClass.getClassName(), 1572 null, 1573 path, 1574 false, 1575 true, 1576 mappings, 1577 inheritedMetas, 1578 true 1579 ); 1580 persistentClass.setIdentifierMapper(mapper); 1581 Property property = new Property(); 1582 property.setName("_identifierMapper"); 1583 property.setNodeName("id"); 1584 property.setUpdateable(false); 1585 property.setInsertable(false); 1586 property.setValue(mapper); 1587 property.setPropertyAccessorName( "embedded" ); 1588 persistentClass.addProperty(property); 1589 } 1590 1591 } 1592 1593 public static void bindComponent(Element node, Component component, String ownerClassName, 1594 String parentProperty, String path, boolean isNullable, boolean isEmbedded, 1595 Mappings mappings, java.util.Map inheritedMetas, boolean isIdentifierMapper) throws MappingException { 1596 1597 component.setEmbedded( isEmbedded ); 1598 1599 component.setMetaAttributes( getMetas( node, inheritedMetas ) ); 1600 1601 Attribute classNode = isIdentifierMapper ? null : node.attribute( "class" ); 1602 if ( classNode != null ) { 1603 component.setComponentClassName( getClassName( classNode, mappings ) ); 1604 } 1605 else if ( "dynamic-component".equals( node.getName() ) ) { 1606 component.setDynamic( true ); 1607 } 1608 else if ( isEmbedded ) { 1609 if ( component.getOwner().hasPojoRepresentation() ) { 1612 component.setComponentClassName( component.getOwner().getClassName() ); 1613 } 1614 else { 1615 component.setDynamic(true); 1616 } 1617 } 1618 else { 1619 if ( component.getOwner().hasPojoRepresentation() ) { 1621 Class reflectedClass = reflectedPropertyClass( ownerClassName, parentProperty ); 1622 if ( reflectedClass != null ) { 1623 component.setComponentClassName( reflectedClass.getName() ); 1624 } 1625 } 1626 else { 1627 component.setDynamic(true); 1628 } 1629 } 1630 1631 String nodeName = node.attributeValue( "node" ); 1632 if ( nodeName == null ) nodeName = node.attributeValue( "name" ); 1633 if ( nodeName == null ) nodeName = component.getOwner().getNodeName(); 1634 component.setNodeName( nodeName ); 1635 1636 Iterator iter = node.elementIterator(); 1637 while ( iter.hasNext() ) { 1638 1639 Element subnode = (Element) iter.next(); 1640 String name = subnode.getName(); 1641 String propertyName = getPropertyName( subnode ); 1642 String subpath = propertyName == null ? null : StringHelper 1643 .qualify( path, propertyName ); 1644 1645 CollectionType collectType = CollectionType.collectionTypeFromString( name ); 1646 Value value = null; 1647 if ( collectType != null ) { 1648 Collection collection = collectType.create( 1649 subnode, 1650 subpath, 1651 component.getOwner(), 1652 mappings 1653 ); 1654 mappings.addCollection( collection ); 1655 value = collection; 1656 } 1657 else if ( "many-to-one".equals( name ) || "key-many-to-one".equals( name ) ) { 1658 value = new ManyToOne( component.getTable() ); 1659 bindManyToOne( subnode, (ManyToOne) value, propertyName, isNullable, mappings ); 1660 } 1661 else if ( "one-to-one".equals( name ) ) { 1662 value = new OneToOne( component.getTable(), component.getOwner() ); 1663 bindOneToOne( subnode, (OneToOne) value, propertyName, isNullable, mappings ); 1664 } 1665 else if ( "any".equals( name ) ) { 1666 value = new Any( component.getTable() ); 1667 bindAny( subnode, (Any) value, isNullable, mappings ); 1668 } 1669 else if ( "property".equals( name ) || "key-property".equals( name ) ) { 1670 value = new SimpleValue( component.getTable() ); 1671 bindSimpleValue( subnode, (SimpleValue) value, isNullable, propertyName, mappings ); 1672 } 1673 else if ( "component".equals( name ) 1674 || "dynamic-component".equals( name ) 1675 || "nested-composite-element".equals( name ) ) { 1676 value = new Component( component ); bindComponent( 1678 subnode, 1679 (Component) value, 1680 component.getComponentClassName(), 1681 propertyName, 1682 subpath, 1683 isNullable, 1684 isEmbedded, 1685 mappings, 1686 inheritedMetas, 1687 isIdentifierMapper 1688 ); 1689 } 1690 else if ( "parent".equals( name ) ) { 1691 component.setParentProperty( propertyName ); 1692 } 1693 1694 if ( value != null ) { 1695 Property property = createProperty( value, propertyName, component 1696 .getComponentClassName(), subnode, mappings, inheritedMetas ); 1697 if (isIdentifierMapper) { 1698 property.setInsertable(false); 1699 property.setUpdateable(false); 1700 } 1701 component.addProperty( property ); 1702 } 1703 } 1704 1705 if ( "true".equals( node.attributeValue( "unique" ) ) ) { 1706 iter = component.getColumnIterator(); 1707 ArrayList cols = new ArrayList (); 1708 while ( iter.hasNext() ) { 1709 cols.add( iter.next() ); 1710 } 1711 component.getOwner().getTable().createUniqueKey( cols ); 1712 } 1713 1714 iter = node.elementIterator( "tuplizer" ); 1715 while ( iter.hasNext() ) { 1716 final Element tuplizerElem = ( Element ) iter.next(); 1717 EntityMode mode = EntityMode.parse( tuplizerElem.attributeValue( "entity-mode" ) ); 1718 component.addTuplizer( mode, node.attributeValue( "class" ) ); 1719 } 1720 } 1721 1722 private static String getTypeFromXML(Element node) throws MappingException { 1723 Attribute typeNode = node.attribute( "type" ); 1725 if ( typeNode == null ) typeNode = node.attribute( "id-type" ); if ( typeNode == null ) return null; return typeNode.getValue(); 1728 } 1729 1730 private static void initOuterJoinFetchSetting(Element node, Fetchable model) { 1731 Attribute fetchNode = node.attribute( "fetch" ); 1732 final FetchMode fetchStyle; 1733 boolean lazy = true; 1734 if ( fetchNode == null ) { 1735 Attribute jfNode = node.attribute( "outer-join" ); 1736 if ( jfNode == null ) { 1737 if ( "many-to-many".equals( node.getName() ) ) { 1738 lazy = false; 1742 fetchStyle = FetchMode.JOIN; 1743 } 1744 else if ( "one-to-one".equals( node.getName() ) ) { 1745 lazy = ( (OneToOne) model ).isConstrained(); 1749 fetchStyle = lazy ? FetchMode.DEFAULT : FetchMode.JOIN; 1750 } 1751 else { 1752 fetchStyle = FetchMode.DEFAULT; 1753 } 1754 } 1755 else { 1756 String eoj = jfNode.getValue(); 1758 if ( "auto".equals( eoj ) ) { 1759 fetchStyle = FetchMode.DEFAULT; 1760 } 1761 else { 1762 boolean join = "true".equals( eoj ); 1763 fetchStyle = join ? FetchMode.JOIN : FetchMode.SELECT; 1764 } 1765 } 1766 } 1767 else { 1768 boolean join = "join".equals( fetchNode.getValue() ); 1769 fetchStyle = join ? FetchMode.JOIN : FetchMode.SELECT; 1771 } 1772 model.setFetchMode( fetchStyle ); 1773 model.setLazy(lazy); 1774 } 1775 1776 private static void makeIdentifier(Element node, SimpleValue model, Mappings mappings) { 1777 1778 Element subnode = node.element( "generator" ); 1780 if ( subnode != null ) { 1781 model.setIdentifierGeneratorStrategy( subnode.attributeValue( "class" ) ); 1782 1783 Properties params = new Properties (); 1784 1785 if ( mappings.getSchemaName() != null ) { 1786 params.setProperty( PersistentIdentifierGenerator.SCHEMA, mappings.getSchemaName() ); 1787 } 1788 if ( mappings.getCatalogName() != null ) { 1789 params.setProperty( PersistentIdentifierGenerator.CATALOG, mappings.getCatalogName() ); 1790 } 1791 1792 Iterator iter = subnode.elementIterator( "param" ); 1793 while ( iter.hasNext() ) { 1794 Element childNode = (Element) iter.next(); 1795 params.setProperty( childNode.attributeValue( "name" ), childNode.getText() ); 1796 } 1797 1798 model.setIdentifierGeneratorProperties( params ); 1799 } 1800 1801 model.getTable().setIdentifierValue( model ); 1802 1803 Attribute nullValueNode = node.attribute( "unsaved-value" ); 1805 if ( nullValueNode != null ) { 1806 model.setNullValue( nullValueNode.getValue() ); 1807 } 1808 else { 1809 if ( "assigned".equals( model.getIdentifierGeneratorStrategy() ) ) { 1810 model.setNullValue( "undefined" ); 1811 } 1812 else { 1813 model.setNullValue( null ); 1814 } 1815 } 1816 } 1817 1818 private static final void makeVersion(Element node, SimpleValue model) { 1819 1820 Attribute nullValueNode = node.attribute( "unsaved-value" ); 1822 if ( nullValueNode != null ) { 1823 model.setNullValue( nullValueNode.getValue() ); 1824 } 1825 else { 1826 model.setNullValue( "undefined" ); 1827 } 1828 1829 } 1830 1831 protected static void createClassProperties(Element node, PersistentClass persistentClass, 1832 Mappings mappings, java.util.Map inheritedMetas) throws MappingException { 1833 createClassProperties(node, persistentClass, mappings, inheritedMetas, null, true, true, false); 1834 } 1835 1836 protected static void createClassProperties(Element node, PersistentClass persistentClass, 1837 Mappings mappings, java.util.Map inheritedMetas, UniqueKey uniqueKey, 1838 boolean mutable, boolean nullable, boolean naturalId) throws MappingException { 1839 1840 String entityName = persistentClass.getEntityName(); 1841 Table table = persistentClass.getTable(); 1842 1843 Iterator iter = node.elementIterator(); 1844 while ( iter.hasNext() ) { 1845 Element subnode = (Element) iter.next(); 1846 String name = subnode.getName(); 1847 String propertyName = subnode.attributeValue( "name" ); 1848 1849 CollectionType collectType = CollectionType.collectionTypeFromString( name ); 1850 Value value = null; 1851 if ( collectType != null ) { 1852 Collection collection = collectType.create( 1853 subnode, 1854 StringHelper.qualify( entityName, propertyName ), 1855 persistentClass, 1856 mappings 1857 ); 1858 mappings.addCollection( collection ); 1859 value = collection; 1860 } 1861 else if ( "many-to-one".equals( name ) ) { 1862 value = new ManyToOne( table ); 1863 bindManyToOne( subnode, (ManyToOne) value, propertyName, nullable, mappings ); 1864 } 1865 else if ( "any".equals( name ) ) { 1866 value = new Any( table ); 1867 bindAny( subnode, (Any) value, nullable, mappings ); 1868 } 1869 else if ( "one-to-one".equals( name ) ) { 1870 value = new OneToOne( table, persistentClass ); 1871 bindOneToOne( subnode, (OneToOne) value, propertyName, true, mappings ); 1872 } 1873 else if ( "property".equals( name ) ) { 1874 value = new SimpleValue( table ); 1875 bindSimpleValue( subnode, (SimpleValue) value, nullable, propertyName, mappings ); 1876 } 1877 else if ( "component".equals( name ) 1878 || "dynamic-component".equals( name ) 1879 || "properties".equals( name ) ) { 1880 String subpath = StringHelper.qualify( entityName, propertyName ); 1881 value = new Component( persistentClass ); 1882 1883 bindComponent( 1884 subnode, 1885 (Component) value, 1886 persistentClass.getClassName(), 1887 propertyName, 1888 subpath, 1889 true, 1890 "properties".equals( name ), 1891 mappings, 1892 inheritedMetas, 1893 false 1894 ); 1895 } 1896 else if ( "join".equals( name ) ) { 1897 Join join = new Join(); 1898 join.setPersistentClass( persistentClass ); 1899 bindJoin( subnode, join, mappings, inheritedMetas ); 1900 persistentClass.addJoin( join ); 1901 } 1902 else if ( "subclass".equals( name ) ) { 1903 handleSubclass( persistentClass, mappings, subnode, inheritedMetas ); 1904 } 1905 else if ( "joined-subclass".equals( name ) ) { 1906 handleJoinedSubclass( persistentClass, mappings, subnode, inheritedMetas ); 1907 } 1908 else if ( "union-subclass".equals( name ) ) { 1909 handleUnionSubclass( persistentClass, mappings, subnode, inheritedMetas ); 1910 } 1911 else if ( "filter".equals( name ) ) { 1912 parseFilter( subnode, persistentClass, mappings ); 1913 } 1914 else if ( "natural-id".equals( name ) ) { 1915 UniqueKey uk = new UniqueKey(); 1916 uk.setName("_UniqueKey"); 1917 uk.setTable(table); 1918 boolean mutableId = "true".equals( subnode.attributeValue("mutable") ); 1920 createClassProperties( 1921 subnode, 1922 persistentClass, 1923 mappings, 1924 inheritedMetas, 1925 uk, 1926 mutableId, 1927 false, 1928 true 1929 ); 1930 table.addUniqueKey(uk); 1931 } 1932 else if ( "query".equals(name) ) { 1933 bindNamedQuery(subnode, persistentClass.getEntityName(), mappings); 1934 } 1935 else if ( "sql-query".equals(name) ) { 1936 bindNamedSQLQuery(subnode, persistentClass.getEntityName(), mappings); 1937 } 1938 else if ( "resultset".equals(name) ) { 1939 bindResultSetMappingDefinition( subnode, persistentClass.getEntityName(), mappings ); 1940 } 1941 1942 if ( value != null ) { 1943 Property property = createProperty( value, propertyName, persistentClass 1944 .getClassName(), subnode, mappings, inheritedMetas ); 1945 if ( !mutable ) property.setUpdateable(false); 1946 if ( naturalId ) property.setNaturalIdentifier(true); 1947 persistentClass.addProperty( property ); 1948 if ( uniqueKey!=null ) uniqueKey.addColumns( property.getColumnIterator() ); 1949 } 1950 1951 } 1952 } 1953 1954 private static Property createProperty(final Value value, final String propertyName, 1955 final String className, final Element subnode, final Mappings mappings, 1956 java.util.Map inheritedMetas) throws MappingException { 1957 1958 value.setTypeUsingReflection( className, propertyName ); 1959 1960 if ( value instanceof ToOne ) { 1963 ToOne toOne = (ToOne) value; 1964 String propertyRef = toOne.getReferencedPropertyName(); 1965 if ( propertyRef != null ) { 1966 mappings.addUniquePropertyReference( toOne.getReferencedEntityName(), propertyRef ); 1967 } 1968 } 1969 else if ( value instanceof Collection ) { 1970 Collection coll = (Collection) value; 1971 String propertyRef = coll.getReferencedPropertyName(); 1972 if ( propertyRef != null ) { 1974 mappings.addPropertyReference( coll.getOwnerEntityName(), propertyRef ); 1975 } 1976 } 1977 1978 value.createForeignKey(); 1979 Property prop = new Property(); 1980 prop.setValue( value ); 1981 bindProperty( subnode, prop, mappings, inheritedMetas ); 1982 return prop; 1983 } 1984 1985 private static void handleUnionSubclass(PersistentClass model, Mappings mappings, 1986 Element subnode, java.util.Map inheritedMetas) throws MappingException { 1987 UnionSubclass subclass = new UnionSubclass( model ); 1988 bindUnionSubclass( subnode, subclass, mappings, inheritedMetas ); 1989 model.addSubclass( subclass ); 1990 mappings.addClass( subclass ); 1991 } 1992 1993 private static void handleJoinedSubclass(PersistentClass model, Mappings mappings, 1994 Element subnode, java.util.Map inheritedMetas) throws MappingException { 1995 JoinedSubclass subclass = new JoinedSubclass( model ); 1996 bindJoinedSubclass( subnode, subclass, mappings, inheritedMetas ); 1997 model.addSubclass( subclass ); 1998 mappings.addClass( subclass ); 1999 } 2000 2001 private static void handleSubclass(PersistentClass model, Mappings mappings, Element subnode, 2002 java.util.Map inheritedMetas) throws MappingException { 2003 Subclass subclass = new SingleTableSubclass( model ); 2004 bindSubclass( subnode, subclass, mappings, inheritedMetas ); 2005 model.addSubclass( subclass ); 2006 mappings.addClass( subclass ); 2007 } 2008 2009 2012 public static void bindListSecondPass(Element node, List list, java.util.Map classes, 2013 Mappings mappings, java.util.Map inheritedMetas) throws MappingException { 2014 2015 bindCollectionSecondPass( node, list, classes, mappings, inheritedMetas ); 2016 2017 Element subnode = node.element( "list-index" ); 2018 if ( subnode == null ) subnode = node.element( "index" ); 2019 SimpleValue iv = new SimpleValue( list.getCollectionTable() ); 2020 bindSimpleValue( 2021 subnode, 2022 iv, 2023 list.isOneToMany(), 2024 IndexedCollection.DEFAULT_INDEX_COLUMN_NAME, 2025 mappings 2026 ); 2027 iv.setTypeName( "integer" ); 2028 list.setIndex( iv ); 2029 String baseIndex = subnode.attributeValue( "base" ); 2030 if ( baseIndex != null ) list.setBaseIndex( Integer.parseInt( baseIndex ) ); 2031 list.setIndexNodeName( subnode.attributeValue("node") ); 2032 2033 if ( list.isOneToMany() && !list.getKey().isNullable() && !list.isInverse() ) { 2034 String entityName = ( (OneToMany) list.getElement() ).getReferencedEntityName(); 2035 PersistentClass referenced = mappings.getClass( entityName ); 2036 IndexBackref ib = new IndexBackref(); 2037 ib.setName( '_' + node.attributeValue( "name" ) + "IndexBackref" ); 2038 ib.setUpdateable( false ); 2039 ib.setSelectable( false ); 2040 ib.setCollectionRole( list.getRole() ); 2041 ib.setEntityName( list.getOwner().getEntityName() ); 2042 ib.setValue( list.getIndex() ); 2043 referenced.addProperty( ib ); 2046 } 2047 } 2048 2049 public static void bindIdentifierCollectionSecondPass(Element node, 2050 IdentifierCollection collection, java.util.Map persistentClasses, Mappings mappings, 2051 java.util.Map inheritedMetas) throws MappingException { 2052 2053 bindCollectionSecondPass( node, collection, persistentClasses, mappings, inheritedMetas ); 2054 2055 Element subnode = node.element( "collection-id" ); 2056 SimpleValue id = new SimpleValue( collection.getCollectionTable() ); 2057 bindSimpleValue( 2058 subnode, 2059 id, 2060 false, 2061 IdentifierCollection.DEFAULT_IDENTIFIER_COLUMN_NAME, 2062 mappings 2063 ); 2064 collection.setIdentifier( id ); 2065 makeIdentifier( subnode, id, mappings ); 2066 2067 } 2068 2069 2072 public static void bindMapSecondPass(Element node, Map map, java.util.Map classes, 2073 Mappings mappings, java.util.Map inheritedMetas) throws MappingException { 2074 2075 bindCollectionSecondPass( node, map, classes, mappings, inheritedMetas ); 2076 2077 Iterator iter = node.elementIterator(); 2078 while ( iter.hasNext() ) { 2079 Element subnode = (Element) iter.next(); 2080 String name = subnode.getName(); 2081 2082 if ( "index".equals( name ) || "map-key".equals( name ) ) { 2083 SimpleValue value = new SimpleValue( map.getCollectionTable() ); 2084 bindSimpleValue( 2085 subnode, 2086 value, 2087 map.isOneToMany(), 2088 IndexedCollection.DEFAULT_INDEX_COLUMN_NAME, 2089 mappings 2090 ); 2091 if ( !value.isTypeSpecified() ) { 2092 throw new MappingException( "map index element must specify a type: " 2093 + map.getRole() ); 2094 } 2095 map.setIndex( value ); 2096 map.setIndexNodeName( subnode.attributeValue("node") ); 2097 } 2098 else if ( "index-many-to-many".equals( name ) || "map-key-many-to-many".equals( name ) ) { 2099 ManyToOne mto = new ManyToOne( map.getCollectionTable() ); 2100 bindManyToOne( 2101 subnode, 2102 mto, 2103 IndexedCollection.DEFAULT_INDEX_COLUMN_NAME, 2104 map.isOneToMany(), 2105 mappings 2106 ); 2107 map.setIndex( mto ); 2108 2109 } 2110 else if ( "composite-index".equals( name ) || "composite-map-key".equals( name ) ) { 2111 Component component = new Component( map ); 2112 bindComposite( 2113 subnode, 2114 component, 2115 map.getRole() + ".index", 2116 map.isOneToMany(), 2117 mappings, 2118 inheritedMetas ); 2119 map.setIndex( component ); 2120 } 2121 else if ( "index-many-to-any".equals( name ) ) { 2122 Any any = new Any( map.getCollectionTable() ); 2123 bindAny( subnode, any, map.isOneToMany(), mappings ); 2124 map.setIndex( any ); 2125 } 2126 } 2127 2128 boolean indexIsFormula = false; 2130 Iterator colIter = map.getIndex().getColumnIterator(); 2131 while ( colIter.hasNext() ) { 2132 if ( ( (Selectable) colIter.next() ).isFormula() ) indexIsFormula = true; 2133 } 2134 2135 if ( map.isOneToMany() && !map.getKey().isNullable() && !map.isInverse() && !indexIsFormula ) { 2136 String entityName = ( (OneToMany) map.getElement() ).getReferencedEntityName(); 2137 PersistentClass referenced = mappings.getClass( entityName ); 2138 IndexBackref ib = new IndexBackref(); 2139 ib.setName( '_' + node.attributeValue( "name" ) + "IndexBackref" ); 2140 ib.setUpdateable( false ); 2141 ib.setSelectable( false ); 2142 ib.setCollectionRole( map.getRole() ); 2143 ib.setEntityName( map.getOwner().getEntityName() ); 2144 ib.setValue( map.getIndex() ); 2145 referenced.addProperty( ib ); 2148 } 2149 } 2150 2151 2154 public static void bindCollectionSecondPass(Element node, Collection collection, 2155 java.util.Map persistentClasses, Mappings mappings, java.util.Map inheritedMetas) 2156 throws MappingException { 2157 2158 if ( collection.isOneToMany() ) { 2159 OneToMany oneToMany = (OneToMany) collection.getElement(); 2160 String assocClass = oneToMany.getReferencedEntityName(); 2161 PersistentClass persistentClass = (PersistentClass) persistentClasses.get( assocClass ); 2162 if ( persistentClass == null ) { 2163 throw new MappingException( "Association references unmapped class: " + assocClass ); 2164 } 2165 oneToMany.setAssociatedClass( persistentClass ); 2166 collection.setCollectionTable( persistentClass.getTable() ); 2167 2168 log.info( "Mapping collection: " 2169 + collection.getRole() 2170 + " -> " 2171 + collection.getCollectionTable().getName() ); 2172 } 2173 2174 Attribute chNode = node.attribute( "check" ); 2176 if ( chNode != null ) { 2177 collection.getCollectionTable().addCheckConstraint( chNode.getValue() ); 2178 } 2179 2180 Iterator iter = node.elementIterator(); 2182 while ( iter.hasNext() ) { 2183 Element subnode = (Element) iter.next(); 2184 String name = subnode.getName(); 2185 2186 if ( "key".equals( name ) ) { 2187 KeyValue keyVal; 2188 String propRef = collection.getReferencedPropertyName(); 2189 if ( propRef == null ) { 2190 keyVal = collection.getOwner().getIdentifier(); 2191 } 2192 else { 2193 keyVal = (KeyValue) collection.getOwner().getProperty( propRef ).getValue(); 2194 } 2195 SimpleValue key = new DependantValue( collection.getCollectionTable(), keyVal ); 2196 key.setCascadeDeleteEnabled( "cascade" 2197 .equals( subnode.attributeValue( "on-delete" ) ) ); 2198 bindSimpleValue( 2199 subnode, 2200 key, 2201 collection.isOneToMany(), 2202 Collection.DEFAULT_KEY_COLUMN_NAME, 2203 mappings 2204 ); 2205 collection.setKey( key ); 2206 2207 Attribute notNull = subnode.attribute( "not-null" ); 2208 ( (DependantValue) key ).setNullable( notNull == null 2209 || notNull.getValue().equals( "false" ) ); 2210 Attribute updateable = subnode.attribute( "update" ); 2211 ( (DependantValue) key ).setUpdateable( updateable == null 2212 || updateable.getValue().equals( "true" ) ); 2213 2214 } 2215 else if ( "element".equals( name ) ) { 2216 SimpleValue elt = new SimpleValue( collection.getCollectionTable() ); 2217 collection.setElement( elt ); 2218 bindSimpleValue( 2219 subnode, 2220 elt, 2221 true, 2222 Collection.DEFAULT_ELEMENT_COLUMN_NAME, 2223 mappings ); 2224 } 2225 else if ( "many-to-many".equals( name ) ) { 2226 ManyToOne element = new ManyToOne( collection.getCollectionTable() ); 2227 collection.setElement( element ); 2228 bindManyToOne( 2229 subnode, 2230 element, 2231 Collection.DEFAULT_ELEMENT_COLUMN_NAME, 2232 false, 2233 mappings 2234 ); 2235 bindManyToManyFilters( collection, subnode, mappings ); 2236 } 2237 else if ( "composite-element".equals( name ) ) { 2238 Component element = new Component( collection ); 2239 collection.setElement( element ); 2240 bindComposite( 2241 subnode, 2242 element, 2243 collection.getRole() + ".element", 2244 true, 2245 mappings, 2246 inheritedMetas ); 2247 } 2248 else if ( "many-to-any".equals( name ) ) { 2249 Any element = new Any( collection.getCollectionTable() ); 2250 collection.setElement( element ); 2251 bindAny( subnode, element, true, mappings ); 2252 } 2253 else if ( "cache".equals( name ) ) { 2254 collection.setCacheConcurrencyStrategy( subnode.attributeValue( "usage" ) ); 2255 collection.setCacheRegionName( subnode.attributeValue( "region" ) ); 2256 } 2257 2258 String nodeName = subnode.attributeValue( "node" ); 2259 if ( nodeName != null ) collection.setElementNodeName( nodeName ); 2260 2261 } 2262 2263 if ( collection.isOneToMany() 2264 && !collection.isInverse() 2265 && !collection.getKey().isNullable() ) { 2266 String entityName = ( (OneToMany) collection.getElement() ).getReferencedEntityName(); 2268 PersistentClass referenced = mappings.getClass( entityName ); 2269 Backref prop = new Backref(); 2270 prop.setName( '_' + node.attributeValue( "name" ) + "Backref" ); 2271 prop.setUpdateable( false ); 2272 prop.setSelectable( false ); 2273 prop.setCollectionRole( collection.getRole() ); 2274 prop.setEntityName( collection.getOwner().getEntityName() ); 2275 prop.setValue( collection.getKey() ); 2276 referenced.addProperty( prop ); 2277 } 2278 } 2279 2280 private static void bindManyToManyFilters( 2281 Collection collection, 2282 Element manyToManyNode, 2283 Mappings model) throws MappingException { 2284 Attribute where = manyToManyNode.attribute( "where" ); 2286 String whereCondition = where == null ? null : where.getValue(); 2287 collection.setManyToManyWhere( whereCondition ); 2288 2289 Iterator filters = manyToManyNode.elementIterator( "filter" ); 2291 if ( ( filters.hasNext() || whereCondition != null ) && 2292 collection.getFetchMode() == FetchMode.JOIN && 2293 collection.getElement().getFetchMode() != FetchMode.JOIN ) { 2294 throw new MappingException( 2295 "many-to-many defining filter or where without join fetching " + 2296 "not valid within collection using join fetching [" + collection.getRole() + "]" 2297 ); 2298 } 2299 while ( filters.hasNext() ) { 2300 final Element filterElement = ( Element ) filters.next(); 2301 final String name = filterElement.attributeValue( "name" ); 2302 String condition = filterElement.getTextTrim(); 2303 if ( StringHelper.isEmpty(condition) ) condition = filterElement.attributeValue( "condition" ); 2304 if ( StringHelper.isEmpty(condition) ) { 2305 condition = model.getFilterDefinition(name).getDefaultFilterCondition(); 2306 } 2307 if ( condition==null) { 2308 throw new MappingException("no filter condition found for filter: " + name); 2309 } 2310 log.debug( "Applying many-to-many filter [" + name + "] as [" + condition + "] to role [" + collection.getRole() + "]" ); 2311 collection.addManyToManyFilter( name, condition ); 2312 } 2313 } 2314 2315 private static final LockMode getLockMode(String lockMode) { 2316 if ( lockMode == null || "read".equals( lockMode ) ) { 2317 return LockMode.READ; 2318 } 2319 else if ( "none".equals( lockMode ) ) { 2320 return LockMode.NONE; 2321 } 2322 else if ( "upgrade".equals( lockMode ) ) { 2323 return LockMode.UPGRADE; 2324 } 2325 else if ( "upgrade-nowait".equals( lockMode ) ) { 2326 return LockMode.UPGRADE_NOWAIT; 2327 } 2328 else if ( "upgrade-nowait".equals( lockMode ) ) { 2329 return LockMode.UPGRADE_NOWAIT; 2330 } 2331 else if ( "write".equals( lockMode ) ) { 2332 return LockMode.WRITE; 2333 } 2334 else { 2335 throw new MappingException( "unknown lockmode" ); 2336 } 2337 } 2338 2339 private static final FlushMode getFlushMode(String flushMode) { 2340 if ( flushMode == null ) { 2341 return null; 2342 } 2343 else if ( "auto".equals( flushMode ) ) { 2344 return FlushMode.AUTO; 2345 } 2346 else if ( "commit".equals( flushMode ) ) { 2347 return FlushMode.COMMIT; 2348 } 2349 else if ( "never".equals( flushMode ) ) { 2350 return FlushMode.NEVER; 2351 } 2352 else if ( "always".equals( flushMode ) ) { 2353 return FlushMode.ALWAYS; 2354 } 2355 else { 2356 throw new MappingException( "unknown flushmode" ); 2357 } 2358 } 2359 2360 private static void bindNamedQuery(Element queryElem, String path, Mappings mappings) { 2361 String queryName = queryElem.attributeValue( "name" ); 2362 if (path!=null) queryName = path + '.' + queryName; 2363 String query = queryElem.getText(); 2364 log.debug( "Named query: " + queryName + " -> " + query ); 2365 2366 boolean cacheable = "true".equals( queryElem.attributeValue( "cacheable" ) ); 2367 String region = queryElem.attributeValue( "cache-region" ); 2368 Attribute tAtt = queryElem.attribute( "timeout" ); 2369 Integer timeout = tAtt == null ? null : new Integer ( tAtt.getValue() ); 2370 Attribute fsAtt = queryElem.attribute( "fetch-size" ); 2371 Integer fetchSize = fsAtt == null ? null : new Integer ( fsAtt.getValue() ); 2372 2373 NamedQueryDefinition namedQuery = new NamedQueryDefinition( 2374 query, 2375 cacheable, 2376 region, 2377 timeout, 2378 fetchSize, 2379 getFlushMode( queryElem.attributeValue( "flush-mode" ) ) , 2380 getParameterTypes(queryElem) 2381 ); 2382 2383 mappings.addQuery( queryName, namedQuery ); 2384 } 2385 2386 private static java.util.Map getParameterTypes(Element queryElem) { 2387 java.util.Map result = new SequencedHashMap(); 2388 Iterator iter = queryElem.elementIterator("query-param"); 2389 while ( iter.hasNext() ) { 2390 Element element = (Element) iter.next(); 2391 result.put( 2392 element.attributeValue("name"), 2393 TypeFactory.heuristicType( element.attributeValue("type") ) 2394 ); 2395 } 2396 return result; 2397 } 2398 2399 2404 private static java.util.Map bindPropertyResults(String alias, Element returnElement) { 2405 2406 HashMap propertyresults = new HashMap (); 2408 Element discriminatorResult = returnElement.element("return-discriminator"); 2409 if(discriminatorResult!=null) { 2410 ArrayList resultColumns = getResultColumns(discriminatorResult); 2411 propertyresults.put("class", ArrayHelper.toStringArray(resultColumns) ); 2412 } 2413 2414 Iterator iterator = returnElement.elementIterator("return-property"); 2415 while ( iterator.hasNext() ) { 2416 Element propertyresult = (Element) iterator.next(); 2417 String name = propertyresult.attributeValue("name"); 2418 if ( "class".equals(name) ) { 2419 throw new MappingException("class is not a valid property name to use in a <return-property>. Use <return-discriminator> instead."); 2420 } 2421 ArrayList allResultColumns = getResultColumns(propertyresult); 2423 2424 if ( allResultColumns.isEmpty() ) { 2425 throw new MappingException("return-property for alias " + alias + " must specify at least one column or return-column name"); 2426 } 2427 String [] existing = (String []) propertyresults.put( name, ArrayHelper.toStringArray(allResultColumns) ); 2428 if (existing!=null) { 2429 throw new MappingException("duplicate return-property for property " + name + " on alias " + alias); 2430 } 2431 } 2432 return propertyresults.isEmpty() ? CollectionHelper.EMPTY_MAP : propertyresults; 2433 } 2434 2435 2439 private static ArrayList getResultColumns(Element propertyresult) { 2440 String column = propertyresult.attributeValue("column"); 2441 ArrayList allResultColumns = new ArrayList (); 2442 if(column!=null) allResultColumns.add(column); 2443 Iterator resultColumns = propertyresult.elementIterator("return-column"); 2444 while ( resultColumns.hasNext() ) { 2445 Element element = (Element) resultColumns.next(); 2446 allResultColumns.add( element.attributeValue("name") ); 2447 } 2448 return allResultColumns; 2449 } 2450 2451 private static ResultSetMappingDefinition buildResultSetMappingDefinition(Element resultSetElem, String path, Mappings mappings) { 2452 String resultSetName = resultSetElem.attribute( "name" ).getValue(); 2453 if (path != null) resultSetName = path + '.' + resultSetName; 2454 ResultSetMappingDefinition definition = new ResultSetMappingDefinition( resultSetName ); 2455 Iterator returns = resultSetElem.elementIterator( "return-scalar" ); 2456 while ( returns.hasNext() ) { 2457 Element returnElem = (Element) returns.next(); 2458 String column = returnElem.attributeValue( "column" ); 2459 Type type = TypeFactory.heuristicType( getTypeFromXML( returnElem ) ); 2460 if ( type == null ) { 2461 throw new MappingException( "could not determine type " + type ); 2462 } 2463 definition.addScalarQueryReturn( new SQLQueryScalarReturn( column, type ) ); 2464 } 2465 returns = resultSetElem.elementIterator(); 2466 int cnt = 0; 2467 while ( returns.hasNext() ) { 2468 cnt++; 2469 Element returnElem = (Element) returns.next(); 2470 String name = returnElem.getName(); 2471 if ( "return".equals( name ) ) { 2472 definition.addEntityQueryReturn( bindReturn( returnElem, mappings, cnt ) ); 2473 } 2474 else if ( "return-join".equals( name ) ) { 2475 definition.addEntityQueryReturn( bindReturnJoin( returnElem, mappings ) ); 2476 } 2477 else if ( "load-collection".equals( name ) ) { 2478 definition.addEntityQueryReturn( bindLoadCollection( returnElem, mappings ) ); 2479 } 2480 } 2481 return definition; 2482 } 2483 2484 private static SQLQueryRootReturn bindReturn(Element returnElem, Mappings mappings, int elementCount) { 2485 String alias = returnElem.attributeValue( "alias" ); 2486 if(StringHelper.isEmpty(alias)) { 2487 alias = "alias_" + elementCount; } 2489 2490 String entityName = getEntityName(returnElem, mappings); 2491 if(entityName==null) { 2492 throw new MappingException( "<return alias='" + alias + "'> must specify either a class or entity-name"); 2493 } 2494 LockMode lockMode = getLockMode( returnElem.attributeValue( "lock-mode" ) ); 2495 2496 java.util.Map propertyResults = bindPropertyResults(alias, returnElem); 2497 2498 return new SQLQueryRootReturn( 2499 alias, 2500 entityName, 2501 propertyResults, 2502 lockMode ); 2503 } 2504 2505 private static SQLQueryJoinReturn bindReturnJoin(Element returnElem, Mappings mappings) { 2506 String alias = returnElem.attributeValue( "alias" ); 2507 String roleAttribute = returnElem.attributeValue( "property" ); 2508 LockMode lockMode = getLockMode( returnElem.attributeValue( "lock-mode" ) ); 2509 int dot = roleAttribute.lastIndexOf( '.' ); 2510 if ( dot == -1 ) { 2511 throw new MappingException( "Role attribute for sql query return [alias=" 2512 + alias 2513 + "] not formatted correctly {owningAlias.propertyName}" ); 2514 } 2515 String roleOwnerAlias = roleAttribute.substring( 0, dot ); 2516 String roleProperty = roleAttribute.substring( dot + 1 ); 2517 2518 java.util.Map propertyResults = bindPropertyResults(alias, returnElem); 2519 2520 return new SQLQueryJoinReturn( 2521 alias, 2522 roleOwnerAlias, 2523 roleProperty, 2524 propertyResults, lockMode ); 2526 } 2527 2528 private static SQLQueryCollectionReturn bindLoadCollection(Element returnElem, Mappings mappings) { 2529 String alias = returnElem.attributeValue( "alias" ); 2530 String collectionAttribute = returnElem.attributeValue( "role" ); 2531 LockMode lockMode = getLockMode( returnElem.attributeValue( "lock-mode" ) ); 2532 int dot = collectionAttribute.lastIndexOf( '.' ); 2533 if ( dot == -1 ) { 2534 throw new MappingException( "Collection attribute for sql query return [alias=" 2535 + alias 2536 + "] not formatted correctly {OwnerClassName.propertyName}" ); 2537 } 2538 String ownerClassName = getClassName( collectionAttribute.substring( 0, dot ), mappings ); 2539 String ownerPropertyName = collectionAttribute.substring( dot + 1 ); 2540 2541 java.util.Map propertyResults = bindPropertyResults(alias, returnElem); 2542 2543 return new SQLQueryCollectionReturn( 2544 alias, 2545 ownerClassName, 2546 ownerPropertyName, 2547 propertyResults, 2548 lockMode ); 2549 } 2550 2551 private static void bindResultSetMappingDefinition(Element resultSetElem, String path, Mappings mappings) { 2552 ResultSetMappingDefinition definition = buildResultSetMappingDefinition( resultSetElem, path, mappings); 2553 mappings.addResultSetMapping( definition ); 2554 } 2555 2556 private static void bindNamedSQLQuery(Element queryElem, String path, Mappings mappings) { 2557 String queryName = queryElem.attribute( "name" ).getValue(); 2558 if (path!=null) queryName = path + '.' + queryName; 2559 2560 boolean cacheable = "true".equals( queryElem.attributeValue( "cacheable" ) ); 2561 String region = queryElem.attributeValue( "cache-region" ); 2562 Attribute tAtt = queryElem.attribute( "timeout" ); 2563 Integer timeout = tAtt == null ? null : new Integer ( tAtt.getValue() ); 2564 Attribute fsAtt = queryElem.attribute( "fetch-size" ); 2565 Integer fetchSize = fsAtt == null ? null : new Integer ( fsAtt.getValue() ); 2566 2567 java.util.List synchronizedTables = new ArrayList (); 2568 Iterator tables = queryElem.elementIterator( "synchronize" ); 2569 while ( tables.hasNext() ) { 2570 synchronizedTables.add( ( (Element) tables.next() ).attributeValue( "table" ) ); 2571 } 2572 boolean callable = "true".equals( queryElem.attributeValue( "callable" ) ); 2573 2574 NamedSQLQueryDefinition namedQuery; 2575 Attribute ref = queryElem.attribute( "resultset-ref" ); 2576 String resultSetRef = ref == null ? null : ref.getValue(); 2577 if ( StringHelper.isNotEmpty( resultSetRef ) ) { 2578 namedQuery = new NamedSQLQueryDefinition( 2579 queryElem.getText(), 2580 resultSetRef, 2581 synchronizedTables, 2582 cacheable, 2583 region, 2584 timeout, 2585 fetchSize, 2586 getFlushMode( queryElem.attributeValue( "flush-mode" ) ), 2587 getParameterTypes(queryElem), 2588 callable 2589 ); 2590 } 2592 else { 2593 ResultSetMappingDefinition definition = buildResultSetMappingDefinition(queryElem, path, mappings); 2594 namedQuery = new NamedSQLQueryDefinition( 2595 queryElem.getText(), 2596 definition.getEntityQueryReturns(), 2597 definition.getScalarQueryReturns(), 2598 synchronizedTables, 2599 cacheable, 2600 region, 2601 timeout, 2602 fetchSize, 2603 getFlushMode( queryElem.attributeValue( "flush-mode" ) ), 2604 getParameterTypes(queryElem), 2605 callable 2606 ); 2607 } 2608 2609 log.debug( "Named SQL query: " + queryName + " -> " + namedQuery.getQueryString() ); 2610 mappings.addSQLQuery( queryName, namedQuery ); 2611 } 2612 2613 private static String getPropertyName(Element node) { 2614 return node.attributeValue( "name" ); 2615 } 2616 2617 private static PersistentClass getSuperclass(Mappings mappings, Element subnode) 2618 throws MappingException { 2619 String superClass = getClassName( subnode.attributeValue( "extends" ), mappings ); 2620 PersistentClass superModel = mappings.getClass( superClass ); 2621 2622 if ( superModel == null ) { 2623 throw new MappingException( "Cannot extend unmapped class " + superClass ); 2624 } 2625 return superModel; 2626 } 2627 2628 abstract static class SecondPass implements Serializable { 2629 Element node; 2630 Mappings mappings; 2631 Collection collection; 2632 2633 SecondPass(Element node, Mappings mappings, Collection collection) { 2634 this.node = node; 2635 this.collection = collection; 2636 this.mappings = mappings; 2637 } 2638 2639 void doSecondPass(java.util.Map persistentClasses, java.util.Map inheritedMetas) 2640 throws MappingException { 2641 if ( log.isDebugEnabled() ) 2642 log.debug( "Second pass for collection: " + collection.getRole() ); 2643 2644 secondPass( persistentClasses, inheritedMetas ); 2645 collection.createAllKeys(); 2646 2647 if ( log.isDebugEnabled() ) { 2648 String msg = "Mapped collection key: " + columns( collection.getKey() ); 2649 if ( collection.isIndexed() ) 2650 msg += ", index: " + columns( ( (IndexedCollection) collection ).getIndex() ); 2651 if ( collection.isOneToMany() ) { 2652 msg += ", one-to-many: " 2653 + ( (OneToMany) collection.getElement() ).getReferencedEntityName(); 2654 } 2655 else { 2656 msg += ", element: " + columns( collection.getElement() ); 2657 } 2658 log.debug( msg ); 2659 } 2660 } 2661 2662 abstract void secondPass(java.util.Map persistentClasses, java.util.Map inheritedMetas) 2663 throws MappingException; 2664 } 2665 2666 static class CollectionSecondPass extends SecondPass { 2667 CollectionSecondPass(Element node, Mappings mappings, Collection collection) { 2668 super( node, mappings, collection ); 2669 } 2670 2671 void secondPass(java.util.Map persistentClasses, java.util.Map inheritedMetas) 2672 throws MappingException { 2673 HbmBinder.bindCollectionSecondPass( 2674 node, 2675 collection, 2676 persistentClasses, 2677 mappings, 2678 inheritedMetas ); 2679 } 2680 2681 } 2682 2683 static class IdentifierCollectionSecondPass extends SecondPass { 2684 IdentifierCollectionSecondPass(Element node, Mappings mappings, 2685 IdentifierCollection collection) { 2686 super( node, mappings, collection ); 2687 } 2688 2689 void secondPass(java.util.Map persistentClasses, java.util.Map inheritedMetas) 2690 throws MappingException { 2691 HbmBinder.bindIdentifierCollectionSecondPass( 2692 node, 2693 (IdentifierCollection) collection, 2694 persistentClasses, 2695 mappings, 2696 inheritedMetas ); 2697 } 2698 2699 } 2700 2701 static class MapSecondPass extends SecondPass { 2702 MapSecondPass(Element node, Mappings mappings, Map collection) { 2703 super( node, mappings, collection ); 2704 } 2705 2706 void secondPass(java.util.Map persistentClasses, java.util.Map inheritedMetas) 2707 throws MappingException { 2708 HbmBinder.bindMapSecondPass( 2709 node, 2710 (Map ) collection, 2711 persistentClasses, 2712 mappings, 2713 inheritedMetas ); 2714 } 2715 2716 } 2717 2718 static class ManyToOneSecondPass extends SecondPass { 2720 private final ManyToOne manyToOne; 2721 2722 ManyToOneSecondPass(Mappings mappings, ManyToOne manyToOne) { 2723 super( null, mappings, null); 2724 this.manyToOne = manyToOne; 2725 } 2726 2727 void doSecondPass(java.util.Map persistentClasses, java.util.Map inheritedMetas) throws MappingException { 2728 manyToOne.createPropertyRefConstraints(persistentClasses); 2729 } 2730 2731 void secondPass(java.util.Map persistentClasses, java.util.Map inheritedMetas) throws MappingException { 2732 } 2734 } 2735 2736 static class ListSecondPass extends SecondPass { 2737 ListSecondPass(Element node, Mappings mappings, List collection) { 2738 super( node, mappings, collection ); 2739 } 2740 2741 void secondPass(java.util.Map persistentClasses, java.util.Map inheritedMetas) 2742 throws MappingException { 2743 HbmBinder.bindListSecondPass( 2744 node, 2745 (List ) collection, 2746 persistentClasses, 2747 mappings, 2748 inheritedMetas ); 2749 } 2750 2751 } 2752 2753 abstract static class CollectionType { 2755 private String xmlTag; 2756 2757 public abstract Collection create(Element node, String path, PersistentClass owner, 2758 Mappings mappings) throws MappingException; 2759 2760 CollectionType(String xmlTag) { 2761 this.xmlTag = xmlTag; 2762 } 2763 2764 public String toString() { 2765 return xmlTag; 2766 } 2767 2768 private static final CollectionType MAP = new CollectionType( "map" ) { 2769 public Collection create(Element node, String path, PersistentClass owner, 2770 Mappings mappings) throws MappingException { 2771 Map map = new Map ( owner ); 2772 bindCollection( node, map, owner.getEntityName(), path, mappings ); 2773 return map; 2774 } 2775 }; 2776 private static final CollectionType SET = new CollectionType( "set" ) { 2777 public Collection create(Element node, String path, PersistentClass owner, 2778 Mappings mappings) throws MappingException { 2779 Set set = new Set ( owner ); 2780 bindCollection( node, set, owner.getEntityName(), path, mappings ); 2781 return set; 2782 } 2783 }; 2784 private static final CollectionType LIST = new CollectionType( "list" ) { 2785 public Collection create(Element node, String path, PersistentClass owner, 2786 Mappings mappings) throws MappingException { 2787 List list = new List ( owner ); 2788 bindCollection( node, list, owner.getEntityName(), path, mappings ); 2789 return list; 2790 } 2791 }; 2792 private static final CollectionType BAG = new CollectionType( "bag" ) { 2793 public Collection create(Element node, String path, PersistentClass owner, 2794 Mappings mappings) throws MappingException { 2795 Bag bag = new Bag( owner ); 2796 bindCollection( node, bag, owner.getEntityName(), path, mappings ); 2797 return bag; 2798 } 2799 }; 2800 private static final CollectionType IDBAG = new CollectionType( "idbag" ) { 2801 public Collection create(Element node, String path, PersistentClass owner, 2802 Mappings mappings) throws MappingException { 2803 IdentifierBag bag = new IdentifierBag( owner ); 2804 bindCollection( node, bag, owner.getEntityName(), path, mappings ); 2805 return bag; 2806 } 2807 }; 2808 private static final CollectionType ARRAY = new CollectionType( "array" ) { 2809 public Collection create(Element node, String path, PersistentClass owner, 2810 Mappings mappings) throws MappingException { 2811 Array array = new Array( owner ); 2812 bindArray( node, array, owner.getEntityName(), path, mappings ); 2813 return array; 2814 } 2815 }; 2816 private static final CollectionType PRIMITIVE_ARRAY = new CollectionType( "primitive-array" ) { 2817 public Collection create(Element node, String path, PersistentClass owner, 2818 Mappings mappings) throws MappingException { 2819 PrimitiveArray array = new PrimitiveArray( owner ); 2820 bindArray( node, array, owner.getEntityName(), path, mappings ); 2821 return array; 2822 } 2823 }; 2824 private static final HashMap INSTANCES = new HashMap (); 2825 2826 static { 2827 INSTANCES.put( MAP.toString(), MAP ); 2828 INSTANCES.put( BAG.toString(), BAG ); 2829 INSTANCES.put( IDBAG.toString(), IDBAG ); 2830 INSTANCES.put( SET.toString(), SET ); 2831 INSTANCES.put( LIST.toString(), LIST ); 2832 INSTANCES.put( ARRAY.toString(), ARRAY ); 2833 INSTANCES.put( PRIMITIVE_ARRAY.toString(), PRIMITIVE_ARRAY ); 2834 } 2835 2836 public static CollectionType collectionTypeFromString(String xmlTagName) { 2837 return (CollectionType) INSTANCES.get( xmlTagName ); 2838 } 2839 } 2840 2841 private static int getOptimisticLockMode(Attribute olAtt) throws MappingException { 2842 2843 if ( olAtt == null ) return Versioning.OPTIMISTIC_LOCK_VERSION; 2844 String olMode = olAtt.getValue(); 2845 if ( olMode == null || "version".equals( olMode ) ) { 2846 return Versioning.OPTIMISTIC_LOCK_VERSION; 2847 } 2848 else if ( "dirty".equals( olMode ) ) { 2849 return Versioning.OPTIMISTIC_LOCK_DIRTY; 2850 } 2851 else if ( "all".equals( olMode ) ) { 2852 return Versioning.OPTIMISTIC_LOCK_ALL; 2853 } 2854 else if ( "none".equals( olMode ) ) { 2855 return Versioning.OPTIMISTIC_LOCK_NONE; 2856 } 2857 else { 2858 throw new MappingException( "Unsupported optimistic-lock style: " + olMode ); 2859 } 2860 } 2861 2862 private static final java.util.Map getMetas(Element node, java.util.Map inheritedMeta) { 2863 return getMetas( node, inheritedMeta, false ); 2864 } 2865 2866 private static final java.util.Map getMetas(Element node, java.util.Map inheritedMeta, 2867 boolean onlyInheritable) { 2868 java.util.Map map = new HashMap (); 2869 map.putAll( inheritedMeta ); 2870 2871 Iterator iter = node.elementIterator( "meta" ); 2872 while ( iter.hasNext() ) { 2873 Element metaNode = (Element) iter.next(); 2874 boolean inheritable = Boolean 2875 .valueOf( metaNode.attributeValue( "inherit" ) ) 2876 .booleanValue(); 2877 if ( onlyInheritable & !inheritable ) { 2878 continue; 2879 } 2880 String name = metaNode.attributeValue( "attribute" ); 2881 2882 MetaAttribute meta = (MetaAttribute) map.get( name ); 2883 if ( meta == null ) { 2884 meta = new MetaAttribute( name ); 2885 map.put( name, meta ); 2886 } 2887 meta.addValue( metaNode.getText() ); 2888 } 2889 return map; 2890 } 2891 2892 private static String getEntityName(Element elem, Mappings model) { 2893 String entityName = elem.attributeValue( "entity-name" ); 2894 return entityName == null ? getClassName( elem.attribute( "class" ), model ) : entityName; 2895 } 2896 2897 private static String getClassName(Attribute att, Mappings model) { 2898 if ( att == null ) return null; 2899 return getClassName( att.getValue(), model ); 2900 } 2901 2902 private static String getClassName(String unqualifiedName, Mappings model) { 2903 if ( unqualifiedName == null ) return null; 2904 if ( unqualifiedName.indexOf( '.' ) < 0 && model.getDefaultPackage() != null ) { 2905 return model.getDefaultPackage() + '.' + unqualifiedName; 2906 } 2907 return unqualifiedName; 2908 } 2909 2910 private static void parseFilterDef(Element element, Mappings mappings) { 2911 String name = element.attributeValue( "name" ); 2912 log.debug( "Parsing filter-def [" + name + "]" ); 2913 FilterDefinition def = new FilterDefinition( name ); 2914 Iterator params = element.elementIterator( "filter-param" ); 2915 while ( params.hasNext() ) { 2916 final Element param = (Element) params.next(); 2917 final String paramName = param.attributeValue( "name" ); 2918 final String paramType = param.attributeValue( "type" ); 2919 log.debug( "adding filter parameter : " + paramName + " -> " + paramType ); 2920 final Type heuristicType = TypeFactory.heuristicType( paramType ); 2921 log.debug( "parameter heuristic type : " + heuristicType ); 2922 def.addParameterType( paramName, heuristicType ); 2923 } 2924 String condition = element.getTextTrim(); 2925 if ( StringHelper.isEmpty(condition) ) condition = element.attributeValue( "condition" ); 2926 def.setDefaultFilterCondition(condition); 2927 log.debug( "Parsed filter-def [" + name + "]" ); 2928 mappings.addFilterDefinition( def ); 2929 } 2930 2931 private static void parseFilter(Element filterElement, Filterable filterable, Mappings model) { 2932 final String name = filterElement.attributeValue( "name" ); 2933 String condition = filterElement.getTextTrim(); 2934 if ( StringHelper.isEmpty(condition) ) condition = filterElement.attributeValue( "condition" ); 2935 if ( StringHelper.isEmpty(condition) ) { 2937 condition = model.getFilterDefinition(name).getDefaultFilterCondition(); 2938 } 2939 if ( condition==null) { 2940 throw new MappingException("no filter condition found for filter: " + name); 2941 } 2942 log.debug( "Applying filter [" + name + "] as [" + condition + "]" ); 2943 filterable.addFilter( name, condition ); 2944 } 2945 2946 private static String getSubselect(Element element) { 2947 String subselect = element.attributeValue( "subselect" ); 2948 if ( subselect != null ) { 2949 return subselect; 2950 } 2951 else { 2952 Element subselectElement = element.element( "subselect" ); 2953 return subselectElement == null ? null : subselectElement.getText(); 2954 } 2955 } 2956 2957 2961 public static java.util.List getExtendsNeeded(Document doc, Mappings mappings) { 2962 2963 java.util.List extendz = new ArrayList (); 2964 2965 Iterator [] subclasses = new Iterator [3]; 2966 2967 final Element hmNode = doc.getRootElement(); 2968 Attribute packNode = hmNode.attribute( "package" ); 2969 if ( packNode != null ) mappings.setDefaultPackage( packNode.getValue() ); 2970 2971 subclasses[0] = hmNode.elementIterator( "subclass" ); 2972 subclasses[1] = hmNode.elementIterator( "joined-subclass" ); 2973 subclasses[2] = hmNode.elementIterator( "union-subclass" ); 2974 2975 Iterator iterator = new JoinedIterator( subclasses ); 2976 while ( iterator.hasNext() ) { 2977 Element element = (Element) iterator.next(); 2978 String superClass = getClassName( element.attributeValue( "extends" ), mappings ); 2979 if ( mappings.getClass( superClass ) == null ) { 2980 extendz.add( superClass ); 2981 } 2982 } 2983 2984 if ( !extendz.isEmpty() ) { 2985 java.util.List names = new ArrayList (); 2986 findClassNames( mappings, hmNode, names ); 2987 2988 java.util.Set set = new HashSet ( extendz ); 2989 set.removeAll( names ); 2990 2991 extendz.clear(); 2992 extendz.addAll( set ); 2993 } 2994 2995 return extendz; 2996 } 2997 2998 3003 private static void findClassNames(Mappings mappings, final Element startNode, 3004 final java.util.List names) { 3005 Iterator [] classes = new Iterator [4]; 3008 classes[0] = startNode.elementIterator( "class" ); 3009 classes[1] = startNode.elementIterator( "subclass" ); 3010 classes[2] = startNode.elementIterator( "joined-subclass" ); 3011 classes[3] = startNode.elementIterator( "union-subclass" ); 3012 3013 Iterator classIterator = new JoinedIterator( classes ); 3014 while ( classIterator.hasNext() ) { 3015 Element element = (Element) classIterator.next(); 3016 String entityName = element.attributeValue( "entity-name" ); 3017 if ( entityName == null ) entityName = getClassName( element.attribute("name"), mappings ); 3018 names.add( entityName ); 3019 findClassNames( mappings, element, names ); 3020 } 3021 } 3022 3023} 3024 | Popular Tags |