1 package org.hibernate.mapping; 3 4 import java.io.Serializable ; 5 import java.util.ArrayList ; 6 import java.util.HashMap ; 7 import java.util.HashSet ; 8 import java.util.Iterator ; 9 import java.util.Set ; 10 11 import org.hibernate.MappingException; 12 import org.hibernate.EntityMode; 13 import org.hibernate.dialect.Dialect; 14 import org.hibernate.engine.Mapping; 15 import org.hibernate.sql.Alias; 16 import org.hibernate.util.EmptyIterator; 17 import org.hibernate.util.JoinedIterator; 18 import org.hibernate.util.ReflectHelper; 19 import org.hibernate.util.SingletonIterator; 20 import org.hibernate.util.StringHelper; 21 22 27 public abstract class PersistentClass implements Serializable , Filterable, MetaAttributable { 28 29 private static final Alias PK_ALIAS = new Alias(15, "PK"); 30 31 public static final String NULL_DISCRIMINATOR_MAPPING = "null"; 32 public static final String NOT_NULL_DISCRIMINATOR_MAPPING = "not null"; 33 34 private String entityName; 35 36 private String className; 37 private String proxyInterfaceName; 38 39 private String nodeName; 40 41 private String discriminatorValue; 42 private boolean lazy; 43 private ArrayList properties = new ArrayList (); 44 private final ArrayList subclasses = new ArrayList (); 45 private final ArrayList subclassProperties = new ArrayList (); 46 private final ArrayList subclassTables = new ArrayList (); 47 private boolean dynamicInsert; 48 private boolean dynamicUpdate; 49 private int batchSize=-1; 50 private boolean selectBeforeUpdate; 51 private int optimisticLockMode; 52 private java.util.Map metaAttributes; 53 private ArrayList joins = new ArrayList (); 54 private final ArrayList subclassJoins = new ArrayList (); 55 private final java.util.Map filters = new HashMap (); 56 protected final java.util.Set synchronizedTables = new HashSet (); 57 private String loaderName; 58 private boolean isAbstract; 59 private boolean hasSubselectLoadableCollections; 60 private Component identifierMapper; 61 62 private String customSQLInsert; 64 private String customSQLUpdate; 65 private String customSQLDelete; 66 private boolean customInsertCallable; 67 private boolean customUpdateCallable; 68 private boolean customDeleteCallable; 69 70 private String temporaryIdTableName; 71 private String temporaryIdTableDDL; 72 73 private java.util.Map tuplizerImpls; 74 75 public String getClassName() { 76 return className; 77 } 78 79 public void setClassName(String className) { 80 this.className = className==null ? null : className.intern(); 81 } 82 83 public String getProxyInterfaceName() { 84 return proxyInterfaceName; 85 } 86 87 public void setProxyInterfaceName(String proxyInterfaceName) { 88 this.proxyInterfaceName = proxyInterfaceName; 89 } 90 91 public Class getMappedClass() throws MappingException { 92 if (className==null) return null; 93 try { 94 return ReflectHelper.classForName(className); 95 } 96 catch (ClassNotFoundException cnfe) { 97 throw new MappingException("entity class not found: " + className, cnfe); 98 } 99 } 100 101 public Class getProxyInterface() { 102 if (proxyInterfaceName==null) return null; 103 try { 104 return ReflectHelper.classForName(proxyInterfaceName); 105 } 106 catch (ClassNotFoundException cnfe) { 107 throw new MappingException("proxy class not found: " + proxyInterfaceName, cnfe); 108 } 109 } 110 public boolean useDynamicInsert() { 111 return dynamicInsert; 112 } 113 114 abstract int nextSubclassId(); 115 public abstract int getSubclassId(); 116 117 public boolean useDynamicUpdate() { 118 return dynamicUpdate; 119 } 120 121 public void setDynamicInsert(boolean dynamicInsert) { 122 this.dynamicInsert = dynamicInsert; 123 } 124 125 public void setDynamicUpdate(boolean dynamicUpdate) { 126 this.dynamicUpdate = dynamicUpdate; 127 } 128 129 130 public String getDiscriminatorValue() { 131 return discriminatorValue; 132 } 133 134 public void addSubclass(Subclass subclass) throws MappingException { 135 PersistentClass superclass = getSuperclass(); 137 while (superclass!=null) { 138 if( subclass.getEntityName().equals( superclass.getEntityName() ) ) { 139 throw new MappingException( 140 "Circular inheritance mapping detected: " + 141 subclass.getEntityName() + 142 " will have it self as superclass when extending " + 143 getEntityName() 144 ); 145 } 146 superclass = superclass.getSuperclass(); 147 } 148 subclasses.add(subclass); 149 } 150 151 public boolean hasSubclasses() { 152 return subclasses.size() > 0; 153 } 154 155 public int getSubclassSpan() { 156 int n = subclasses.size(); 157 Iterator iter = subclasses.iterator(); 158 while ( iter.hasNext() ) { 159 n += ( (Subclass) iter.next() ).getSubclassSpan(); 160 } 161 return n; 162 } 163 167 public Iterator getSubclassIterator() { 168 Iterator [] iters = new Iterator [ subclasses.size() + 1 ]; 169 Iterator iter = subclasses.iterator(); 170 int i=0; 171 while ( iter.hasNext() ) { 172 iters[i++] = ( (Subclass) iter.next() ).getSubclassIterator(); 173 } 174 iters[i] = subclasses.iterator(); 175 return new JoinedIterator(iters); 176 } 177 178 public Iterator getSubclassClosureIterator() { 179 ArrayList iters = new ArrayList (); 180 iters.add( new SingletonIterator(this) ); 181 Iterator iter = getSubclassIterator(); 182 while ( iter.hasNext() ) { 183 PersistentClass clazz = (PersistentClass) iter.next(); 184 iters.add( clazz.getSubclassClosureIterator() ); 185 } 186 return new JoinedIterator(iters); 187 } 188 189 public Table getIdentityTable() { 190 return getRootTable(); 191 } 192 193 public Iterator getDirectSubclasses() { 194 return subclasses.iterator(); 195 } 196 197 public void addProperty(Property p) { 198 properties.add(p); 199 p.setPersistentClass(this); 200 } 201 202 public abstract Table getTable(); 203 204 public String getEntityName() { 205 return entityName; 206 } 207 208 public abstract boolean isMutable(); 209 public abstract boolean hasIdentifierProperty(); 210 public abstract Property getIdentifierProperty(); 211 public abstract KeyValue getIdentifier(); 212 public abstract Property getVersion(); 213 public abstract Value getDiscriminator(); 214 public abstract boolean isInherited(); 215 public abstract boolean isPolymorphic(); 216 public abstract boolean isVersioned(); 217 public abstract String getCacheConcurrencyStrategy(); 218 public abstract PersistentClass getSuperclass(); 219 public abstract boolean isExplicitPolymorphism(); 220 public abstract boolean isDiscriminatorInsertable(); 221 222 public abstract Iterator getPropertyClosureIterator(); 223 public abstract Iterator getTableClosureIterator(); 224 public abstract Iterator getKeyClosureIterator(); 225 226 protected void addSubclassProperty(Property prop) { 227 subclassProperties.add(prop); 228 } 229 protected void addSubclassJoin(Join join) { 230 subclassJoins.add(join); 231 } 232 protected void addSubclassTable(Table subclassTable) { 233 subclassTables.add(subclassTable); 234 } 235 public Iterator getSubclassPropertyClosureIterator() { 236 ArrayList iters = new ArrayList (); 237 iters.add( getPropertyClosureIterator() ); 238 iters.add( subclassProperties.iterator() ); 239 for ( int i=0; i<subclassJoins.size(); i++ ) { 240 Join join = (Join) subclassJoins.get(i); 241 iters.add( join.getPropertyIterator() ); 242 } 243 return new JoinedIterator(iters); 244 } 245 public Iterator getSubclassJoinClosureIterator() { 246 return new JoinedIterator( getJoinClosureIterator(), subclassJoins.iterator() ); 247 } 248 public Iterator getSubclassTableClosureIterator() { 249 return new JoinedIterator( getTableClosureIterator(), subclassTables.iterator() ); 250 } 251 252 public boolean isClassOrSuperclassJoin(Join join) { 253 return joins.contains(join); 254 } 255 256 public boolean isClassOrSuperclassTable(Table closureTable) { 257 return getTable()==closureTable; 258 } 259 260 public boolean isLazy() { 261 return lazy; 262 } 263 264 public void setLazy(boolean lazy) { 265 this.lazy = lazy; 266 } 267 268 public abstract boolean hasEmbeddedIdentifier(); 269 public abstract Class getEntityPersisterClass(); 270 public abstract void setEntityPersisterClass(Class classPersisterClass); 271 public abstract Table getRootTable(); 272 public abstract RootClass getRootClass(); 273 public abstract KeyValue getKey(); 274 275 public void setDiscriminatorValue(String discriminatorValue) { 276 this.discriminatorValue = discriminatorValue; 277 } 278 279 public void setEntityName(String entityName) { 280 this.entityName = entityName==null ? null : entityName.intern(); 281 } 282 283 public void createPrimaryKey() { 284 PrimaryKey pk = new PrimaryKey(); 286 Table table = getTable(); 287 pk.setTable(table); 288 pk.setName( PK_ALIAS.toAliasString( table.getName() ) ); 289 table.setPrimaryKey(pk); 290 291 pk.addColumns( getKey().getColumnIterator() ); 292 } 293 294 public abstract String getWhere(); 295 296 public int getBatchSize() { 297 return batchSize; 298 } 299 300 public void setBatchSize(int batchSize) { 301 this.batchSize = batchSize; 302 } 303 304 public boolean hasSelectBeforeUpdate() { 305 return selectBeforeUpdate; 306 } 307 308 public void setSelectBeforeUpdate(boolean selectBeforeUpdate) { 309 this.selectBeforeUpdate = selectBeforeUpdate; 310 } 311 312 public Iterator getReferenceablePropertyIterator() { 313 return getPropertyClosureIterator(); 314 } 315 316 public Property getReferencedProperty(String propertyPath) throws MappingException { 317 Iterator iter = getReferenceablePropertyIterator(); 318 Property property = null; 319 while ( iter.hasNext() ) { 320 Property prop = (Property) iter.next(); 321 if ( prop.getName().equals( StringHelper.root(propertyPath) ) ) { 322 property = prop; 323 break; 324 } 325 } 326 327 if (property==null) { 328 throw new MappingException( 329 "property-ref not found: " + propertyPath + 330 "in entity: " + getEntityName() 331 ); 332 } 333 334 if ( propertyPath.indexOf('.')>0 ) { 335 property = ( (Component) property.getValue() ).getProperty( StringHelper.unroot(propertyPath) ); 336 } 337 338 return property; 339 } 340 341 public Property getProperty(String propertyName) throws MappingException { 342 Iterator iter = getPropertyClosureIterator(); 343 while ( iter.hasNext() ) { 344 Property prop = (Property) iter.next(); 345 if ( prop.getName().equals( StringHelper.root(propertyName) ) ) { 346 return prop; 347 } 348 } 349 throw new MappingException("property not found: " + propertyName); 350 } 351 352 public int getOptimisticLockMode() { 353 return optimisticLockMode; 354 } 355 356 public void setOptimisticLockMode(int optimisticLockMode) { 357 this.optimisticLockMode = optimisticLockMode; 358 } 359 360 public void validate(Mapping mapping) throws MappingException { 361 Iterator iter = getPropertyIterator(); 362 while ( iter.hasNext() ) { 363 Property prop = (Property) iter.next(); 364 if ( !prop.isValid(mapping) ) { 365 throw new MappingException( 366 "property mapping has wrong number of columns: " + 367 StringHelper.qualify( getEntityName(), prop.getName() ) + 368 " type: " + 369 prop.getType().getName() 370 ); 371 } 372 } 373 checkPropertyDuplication(); 374 checkColumnDuplication(); 375 } 376 377 private void checkPropertyDuplication() throws MappingException { 378 HashSet names = new HashSet (); 379 Iterator iter = getPropertyIterator(); 380 while ( iter.hasNext() ) { 381 Property prop = (Property) iter.next(); 382 if ( !names.add( prop.getName() ) ) { 383 throw new MappingException( "duplicate property mapping: " + prop.getName() ); 384 } 385 } 386 } 387 388 public boolean isDiscriminatorValueNotNull() { 389 return NOT_NULL_DISCRIMINATOR_MAPPING.equals( getDiscriminatorValue() ); 390 } 391 public boolean isDiscriminatorValueNull() { 392 return NULL_DISCRIMINATOR_MAPPING.equals( getDiscriminatorValue() ); 393 } 394 395 public java.util.Map getMetaAttributes() { 396 return metaAttributes; 397 } 398 399 public void setMetaAttributes(java.util.Map metas) { 400 this.metaAttributes = metas; 401 } 402 403 public MetaAttribute getMetaAttribute(String name) { 404 return metaAttributes==null?null:(MetaAttribute) metaAttributes.get(name); 405 } 406 407 public String toString() { 408 return getClass().getName() + '(' + getEntityName() + ')'; 409 } 410 411 public Iterator getJoinIterator() { 412 return joins.iterator(); 413 } 414 415 public Iterator getJoinClosureIterator() { 416 return joins.iterator(); 417 } 418 419 public void addJoin(Join join) { 420 joins.add(join); 421 join.setPersistentClass(this); 422 } 423 424 public int getJoinClosureSpan() { 425 return joins.size(); 426 } 427 428 public int getPropertyClosureSpan() { 429 int span = properties.size(); 430 for ( int i=0; i<joins.size(); i++ ) { 431 Join join = (Join) joins.get(i); 432 span += join.getPropertySpan(); 433 } 434 return span; 435 } 436 437 public int getJoinNumber(Property prop) { 438 int result=1; 439 Iterator iter = getSubclassJoinClosureIterator(); 440 while ( iter.hasNext() ) { 441 Join join = (Join) iter.next(); 442 if ( join.containsProperty(prop) ) return result; 443 result++; 444 } 445 return 0; 446 } 447 448 public Iterator getPropertyIterator() { 449 ArrayList iterators = new ArrayList (); 450 iterators.add( properties.iterator() ); 451 for ( int i=0; i<joins.size(); i++ ) { 452 Join join = (Join) joins.get(i); 453 iterators.add( join.getPropertyIterator() ); 454 } 455 return new JoinedIterator(iterators); 456 } 457 458 public Iterator getUnjoinedPropertyIterator() { 459 return properties.iterator(); 460 } 461 462 public void setCustomSQLInsert(String customSQLInsert, boolean callable) { 463 this.customSQLInsert = customSQLInsert; 464 this.customInsertCallable = callable; 465 } 466 467 public String getCustomSQLInsert() { 468 return customSQLInsert; 469 } 470 471 public boolean isCustomInsertCallable() { 472 return customInsertCallable; 473 } 474 475 public void setCustomSQLUpdate(String customSQLUpdate, boolean callable) { 476 this.customSQLUpdate = customSQLUpdate; 477 this.customUpdateCallable = callable; 478 } 479 480 public String getCustomSQLUpdate() { 481 return customSQLUpdate; 482 } 483 484 public boolean isCustomUpdateCallable() { 485 return customUpdateCallable; 486 } 487 488 public void setCustomSQLDelete(String customSQLDelete, boolean callable) { 489 this.customSQLDelete = customSQLDelete; 490 this.customDeleteCallable = callable; 491 } 492 493 public String getCustomSQLDelete() { 494 return customSQLDelete; 495 } 496 497 public boolean isCustomDeleteCallable() { 498 return customDeleteCallable; 499 } 500 501 public void addFilter(String name, String condition) { 502 filters.put(name, condition); 503 } 504 505 public java.util.Map getFilterMap() { 506 return filters; 507 } 508 509 public boolean isForceDiscriminator() { 510 return false; 511 } 512 513 public abstract boolean isJoinedSubclass(); 514 515 public String getLoaderName() { 516 return loaderName; 517 } 518 519 public void setLoaderName(String loaderName) { 520 this.loaderName = loaderName==null ? null : loaderName.intern(); 521 } 522 523 public abstract java.util.Set getSynchronizedTables(); 524 525 public void addSynchronizedTable(String table) { 526 synchronizedTables.add(table); 527 } 528 public boolean isAbstract() { 529 return isAbstract; 530 } 531 532 public void setAbstract(boolean isAbstract) { 533 this.isAbstract = isAbstract; 534 } 535 536 protected void checkColumnDuplication(Set distinctColumns, Iterator columns) 537 throws MappingException { 538 while ( columns.hasNext() ) { 539 Selectable columnOrFormula = (Selectable) columns.next(); 540 if ( !columnOrFormula.isFormula() ) { 541 Column col = (Column) columnOrFormula; 542 if ( !distinctColumns.add( col.getName() ) ) { 543 throw new MappingException( 544 "Repeated column in mapping for entity: " + 545 getEntityName() + 546 " column: " + 547 col.getName() + 548 " (should be mapped with insert=\"false\" update=\"false\")" 549 ); 550 } 551 } 552 } 553 } 554 555 protected void checkPropertyColumnDuplication(Set distinctColumns, Iterator properties) 556 throws MappingException { 557 while ( properties.hasNext() ) { 558 Property prop = (Property) properties.next(); 559 if ( prop.getValue() instanceof Component ) { Component component = (Component) prop.getValue(); 561 checkPropertyColumnDuplication( distinctColumns, component.getPropertyIterator() ); 562 } 563 else { 564 if ( prop.isUpdateable() || prop.isInsertable() ) { 565 checkColumnDuplication( distinctColumns, prop.getColumnIterator() ); 566 } 567 } 568 } 569 } 570 571 protected Iterator getNonDuplicatedPropertyIterator() { 572 return getUnjoinedPropertyIterator(); 573 } 574 575 protected Iterator getDiscriminatorColumnIterator() { 576 return EmptyIterator.INSTANCE; 577 } 578 579 protected void checkColumnDuplication() { 580 HashSet cols = new HashSet (); 581 checkColumnDuplication( cols, getKey().getColumnIterator() ); 582 checkColumnDuplication( cols, getDiscriminatorColumnIterator() ); 583 checkPropertyColumnDuplication( cols, getNonDuplicatedPropertyIterator() ); 584 Iterator iter = getJoinIterator(); 585 while ( iter.hasNext() ) { 586 cols.clear(); 587 Join join = (Join) iter.next(); 588 checkColumnDuplication( cols, join.getKey().getColumnIterator() ); 589 checkPropertyColumnDuplication( cols, join.getPropertyIterator() ); 590 } 591 } 592 593 public abstract Object accept(PersistentClassVisitor mv); 594 595 public String getNodeName() { 596 return nodeName; 597 } 598 599 public void setNodeName(String nodeName) { 600 this.nodeName = nodeName; 601 } 602 603 public boolean hasPojoRepresentation() { 604 return getClassName()!=null; 605 } 606 607 public boolean hasDom4jRepresentation() { 608 return getNodeName()!=null; 609 } 610 611 public boolean hasSubselectLoadableCollections() { 612 return hasSubselectLoadableCollections; 613 } 614 615 public void setSubselectLoadableCollections(boolean hasSubselectCollections) { 616 this.hasSubselectLoadableCollections = hasSubselectCollections; 617 } 618 619 public void prepareTemporaryTables(Mapping mapping, Dialect dialect) { 620 if ( dialect.supportsTemporaryTables() ) { 621 temporaryIdTableName = dialect.generateTemporaryTableName( getTable().getName() ); 622 Table table = new Table(); 623 table.setName( temporaryIdTableName ); 624 Iterator itr = getTable().getPrimaryKey().getColumnIterator(); 625 while( itr.hasNext() ) { 626 table.addColumn( ( Column ) itr.next() ); 627 } 628 temporaryIdTableDDL = table.sqlTemporaryTableCreateString( dialect, mapping ); 629 } 630 } 631 632 public String getTemporaryIdTableName() { 633 return temporaryIdTableName; 634 } 635 636 public String getTemporaryIdTableDDL() { 637 return temporaryIdTableDDL; 638 } 639 640 public Component getIdentifierMapper() { 641 return identifierMapper; 642 } 643 644 public void setIdentifierMapper(Component handle) { 645 this.identifierMapper = handle; 646 } 647 648 public void addTuplizer(EntityMode entityMode, String implClassName) { 649 if ( tuplizerImpls == null ) { 650 tuplizerImpls = new HashMap (); 651 } 652 tuplizerImpls.put( entityMode, implClassName ); 653 } 654 655 public String getTuplizerImplClassName(EntityMode mode) { 656 if ( tuplizerImpls == null ) return null; 657 return ( String ) tuplizerImpls.get( mode ); 658 } 659 660 public boolean hasNaturalId() { 661 Iterator props = getRootClass().getPropertyIterator(); 662 while ( props.hasNext() ) { 663 if ( ( (Property) props.next() ).isNaturalIdentifier() ) { 664 return true; 665 } 666 } 667 return false; 668 } 669 } | Popular Tags |