1 package org.hibernate.type; 3 4 import java.io.Serializable ; 5 import java.sql.PreparedStatement ; 6 import java.sql.ResultSet ; 7 import java.sql.SQLException ; 8 import java.util.ArrayList ; 9 import java.util.Collection ; 10 import java.util.Iterator ; 11 import java.util.List ; 12 import java.util.Map ; 13 14 import org.dom4j.Element; 15 import org.dom4j.Node; 16 import org.hibernate.EntityMode; 17 import org.hibernate.Hibernate; 18 import org.hibernate.HibernateException; 19 import org.hibernate.MappingException; 20 import org.hibernate.collection.PersistentCollection; 21 import org.hibernate.engine.CollectionKey; 22 import org.hibernate.engine.EntityEntry; 23 import org.hibernate.engine.Mapping; 24 import org.hibernate.engine.PersistenceContext; 25 import org.hibernate.engine.SessionFactoryImplementor; 26 import org.hibernate.engine.SessionImplementor; 27 import org.hibernate.persister.collection.CollectionPersister; 28 import org.hibernate.persister.collection.QueryableCollection; 29 import org.hibernate.persister.entity.Joinable; 30 import org.hibernate.proxy.HibernateProxy; 31 import org.hibernate.proxy.LazyInitializer; 32 import org.hibernate.util.ArrayHelper; 33 import org.hibernate.util.MarkerObject; 34 35 40 public abstract class CollectionType extends AbstractType implements AssociationType { 41 42 private static final Object NOT_NULL_COLLECTION = new MarkerObject( "NOT NULL COLLECTION" ); 43 public static final Object UNFETCHED_COLLECTION = new MarkerObject( "UNFETCHED COLLECTION" ); 44 45 private final String role; 46 private final String foreignKeyPropertyName; 47 private final boolean isEmbeddedInXML; 48 49 public CollectionType(String role, String foreignKeyPropertyName, boolean isEmbeddedInXML) { 50 this.role = role; 51 this.foreignKeyPropertyName = foreignKeyPropertyName; 52 this.isEmbeddedInXML = isEmbeddedInXML; 53 } 54 55 public boolean isEmbeddedInXML() { 56 return isEmbeddedInXML; 57 } 58 59 public String getRole() { 60 return role; 61 } 62 63 public Object indexOf(Object collection, Object element) { 64 throw new UnsupportedOperationException ( "generic collections don't have indexes" ); 65 } 66 67 public boolean contains(Object collection, Object childObject, CollectionPersister persister, 68 SessionImplementor session) { 69 Iterator elems = getElementsIterator( collection, session ); 72 while ( elems.hasNext() ) { 73 Object element = elems.next(); 74 if ( element instanceof HibernateProxy ) { 76 LazyInitializer li = ( (HibernateProxy) element ).getHibernateLazyInitializer(); 77 if ( !li.isUninitialized() ) element = li.getImplementation(); 78 } 79 if ( element == childObject ) return true; 80 } 81 return false; 82 } 83 84 public boolean isCollectionType() { 85 return true; 86 } 87 88 public final boolean isEqual(Object x, Object y, EntityMode entityMode) { 89 return x == y 90 || ( x instanceof PersistentCollection && ( (PersistentCollection) x ).isWrapper( y ) ) 91 || ( y instanceof PersistentCollection && ( (PersistentCollection) y ).isWrapper( x ) ); 92 } 93 94 public int compare(Object x, Object y, EntityMode entityMode) { 95 return 0; } 97 98 public int getHashCode(Object x, EntityMode entityMode) { 99 throw new UnsupportedOperationException ( "cannot perform lookups on collections" ); 100 } 101 102 106 public abstract PersistentCollection instantiate(SessionImplementor session, 107 CollectionPersister persister, Serializable key) throws HibernateException; 108 109 public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner) 110 throws HibernateException, SQLException { 111 return nullSafeGet( rs, new String [] { name }, session, owner ); 112 } 113 114 public Object nullSafeGet(ResultSet rs, String [] name, SessionImplementor session, Object owner) 115 throws HibernateException, SQLException { 116 return resolve( null, session, owner ); 117 } 118 119 public final void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, 120 SessionImplementor session) throws HibernateException, SQLException { 121 } 123 124 public void nullSafeSet(PreparedStatement st, Object value, int index, 125 SessionImplementor session) throws HibernateException, SQLException { 126 } 127 128 public int[] sqlTypes(Mapping session) throws MappingException { 129 return ArrayHelper.EMPTY_INT_ARRAY; 130 } 131 132 public int getColumnSpan(Mapping session) throws MappingException { 133 return 0; 134 } 135 136 public String toLoggableString(Object value, SessionFactoryImplementor factory) 137 throws HibernateException { 138 139 if ( value == null ) return "null"; 140 141 if ( Hibernate.isInitialized( value ) ) { 142 if ( getReturnedClass().isInstance(value) ) { 143 List list = new ArrayList (); 144 Type elemType = getElementType( factory ); 145 Iterator iter = getElementsIterator( value ); 146 while ( iter.hasNext() ) { 147 list.add( elemType.toLoggableString( iter.next(), factory ) ); 148 } 149 return list.toString(); 150 } 151 else { 152 return ( (Element) value ).asXML(); } 155 } 156 else { 157 return "<uninitialized>"; 158 } 159 160 } 161 162 public Object deepCopy(Object value, EntityMode entityMode, SessionFactoryImplementor factory) 163 throws HibernateException { 164 return value; 165 } 166 167 public String getName() { 168 return getReturnedClass().getName() + '(' + getRole() + ')'; 169 } 170 171 174 public Iterator getElementsIterator(Object collection, SessionImplementor session) { 175 if ( session.getEntityMode()==EntityMode.DOM4J ) { 176 final SessionFactoryImplementor factory = session.getFactory(); 177 final CollectionPersister persister = factory.getCollectionPersister( getRole() ); 178 final Type elementType = persister.getElementType(); 179 180 List elements = ( (Element) collection ).elements( persister.getElementNodeName() ); 181 ArrayList results = new ArrayList (); 182 for ( int i=0; i<elements.size(); i++ ) { 183 Element value = (Element) elements.get(i); 184 results.add( elementType.fromXMLNode( value, factory ) ); 185 } 186 return results.iterator(); 187 } 188 else { 189 return getElementsIterator(collection); 190 } 191 } 192 193 196 protected Iterator getElementsIterator(Object collection) { 197 return ( (Collection ) collection ).iterator(); 198 } 199 200 public boolean isMutable() { 201 return false; 202 } 203 204 public Serializable disassemble(Object value, SessionImplementor session, Object owner) 205 throws HibernateException { 206 208 212 final Serializable key = getKeyOfOwner(owner, session); 213 if (key==null) { 214 return null; 215 } 216 else { 217 return getPersister(session) 218 .getKeyType() 219 .disassemble( key, session, owner ); 220 } 221 } 222 223 public Object assemble(Serializable cached, SessionImplementor session, Object owner) 224 throws HibernateException { 225 if (cached==null) { 228 return null; 229 } 230 else { 231 final Serializable key = (Serializable ) getPersister(session) 232 .getKeyType() 233 .assemble( cached, session, owner); 234 return resolveKey( key, session, owner ); 235 } 236 } 237 238 241 private boolean isOwnerVersioned(SessionImplementor session) throws MappingException { 242 return getPersister( session ) 243 .getOwnerEntityPersister() 244 .isVersioned(); 245 } 246 247 private CollectionPersister getPersister(SessionImplementor session) { 248 return session.getFactory() 249 .getCollectionPersister( role ); 250 } 251 252 public boolean isDirty(Object old, Object current, SessionImplementor session) 253 throws HibernateException { 254 255 257 return isOwnerVersioned( session ) && super.isDirty( old, current, session ); 260 262 } 263 264 268 public abstract PersistentCollection wrap(SessionImplementor session, Object collection); 269 270 274 public boolean isAssociationType() { 275 return true; 276 } 277 278 public ForeignKeyDirection getForeignKeyDirection() { 279 return ForeignKeyDirection.FOREIGN_KEY_TO_PARENT; 280 } 281 282 286 public Serializable getKeyOfOwner(Object owner, SessionImplementor session) { 287 288 EntityEntry e = session.getPersistenceContext().getEntry( owner ); 289 if ( e == null ) return null; 292 if ( foreignKeyPropertyName == null ) { 293 return e.getId(); 294 } 295 else { 296 Object id = e.getLoadedValue( foreignKeyPropertyName ); 302 303 Type keyType = getPersister( session ).getKeyType(); 305 if ( !keyType.getReturnedClass().isInstance( id ) ) { 306 id = (Serializable ) keyType.semiResolve( 307 e.getLoadedValue( foreignKeyPropertyName ), 308 session, 309 owner 310 ); 311 } 312 313 return (Serializable ) id; 314 } 315 } 316 317 public Object hydrate(ResultSet rs, String [] name, SessionImplementor session, Object owner) { 318 return NOT_NULL_COLLECTION; 321 } 322 323 public Object resolve(Object value, SessionImplementor session, Object owner) 324 throws HibernateException { 325 326 return resolveKey( getKeyOfOwner( owner, session ), session, owner ); 327 } 328 329 private Object resolveKey(Serializable key, SessionImplementor session, Object owner) { 330 return key == null ? null : getCollection( key, session, owner ); 334 } 335 336 public Object semiResolve(Object value, SessionImplementor session, Object owner) 337 throws HibernateException { 338 throw new UnsupportedOperationException ( 339 "collection mappings may not form part of a property-ref" ); 340 } 341 342 public boolean isArrayType() { 343 return false; 344 } 345 346 public boolean useLHSPrimaryKey() { 347 return foreignKeyPropertyName == null; 348 } 349 350 public String getRHSUniqueKeyPropertyName() { 351 return null; 352 } 353 354 public Joinable getAssociatedJoinable(SessionFactoryImplementor factory) 355 throws MappingException { 356 return (Joinable) factory.getCollectionPersister( role ); 357 } 358 359 public boolean isModified(Object old, Object current, SessionImplementor session) throws HibernateException { 360 return false; 361 } 362 363 public String getAssociatedEntityName(SessionFactoryImplementor factory) 364 throws MappingException { 365 try { 366 367 QueryableCollection collectionPersister = (QueryableCollection) factory 368 .getCollectionPersister( role ); 369 370 if ( !collectionPersister.getElementType().isEntityType() ) { 371 throw new MappingException( 372 "collection was not an association: " + 373 collectionPersister.getRole() 374 ); 375 } 376 377 return collectionPersister.getElementPersister().getEntityName(); 378 379 } 380 catch (ClassCastException cce) { 381 throw new MappingException( "collection role is not queryable " + role ); 382 } 383 } 384 385 388 public Object replaceElements(Object original, Object target, Object owner, Map copyCache, 389 SessionImplementor session) throws HibernateException { 390 391 393 java.util.Collection result = (java.util.Collection ) target; 394 395 result.clear(); 396 397 Type elemType = getElementType( session.getFactory() ); 399 Iterator iter = ( (java.util.Collection ) original ).iterator(); 400 while ( iter.hasNext() ) { 401 result.add( elemType.replace( iter.next(), null, session, owner, copyCache ) ); 402 } 403 404 return result; 405 406 } 407 408 411 public abstract Object instantiate(Object original); 412 413 public Object replace(final Object original, final Object target, 414 final SessionImplementor session, final Object owner, final Map copyCache) 415 throws HibernateException { 416 417 if ( original == null ) return null; 418 if ( !Hibernate.isInitialized( original ) ) return target; 419 421 Object result = target==null || target==original ? instantiate( original ) : target; 423 424 result = replaceElements( original, result, owner, copyCache, session ); 427 428 if (original==target) { 429 replaceElements( result, target, owner, copyCache, session ); 433 result = target; 434 } 435 436 return result; 437 438 } 439 440 443 public final Type getElementType(SessionFactoryImplementor factory) throws MappingException { 444 return factory.getCollectionPersister( getRole() ).getElementType(); 445 } 446 447 public String toString() { 448 return getClass().getName() + '(' + getRole() + ')'; 449 } 450 451 public String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters) 452 throws MappingException { 453 return getAssociatedJoinable( factory ).filterFragment( alias, enabledFilters ); 454 } 455 456 459 public Object getCollection(Serializable key, SessionImplementor session, Object owner) 460 throws HibernateException { 461 462 CollectionPersister persister = getPersister( session ); 463 final PersistenceContext persistenceContext = session.getPersistenceContext(); 464 final EntityMode entityMode = session.getEntityMode(); 465 466 if (entityMode==EntityMode.DOM4J && !isEmbeddedInXML) { 467 return UNFETCHED_COLLECTION; 468 } 469 470 PersistentCollection collection = persistenceContext 472 .getCollectionLoadContext() 473 .getLoadingCollection( persister, key, entityMode ); 474 475 if ( collection == null ) { 476 477 collection = persistenceContext.useUnownedCollection( new CollectionKey(persister, key, entityMode) ); 479 480 if (collection==null) { 481 482 collection = instantiate( session, persister, key ); 484 collection.setOwner(owner); 485 486 persistenceContext.addUninitializedCollection( persister, collection, key ); 487 488 if ( initializeImmediately( entityMode ) ) { 490 session.initializeCollection( collection, false ); 491 } 492 else if ( !persister.isLazy() ) { 493 persistenceContext.addNonLazyCollection( collection ); 494 } 495 496 if ( hasHolder( entityMode ) ) { 497 session.getPersistenceContext().addCollectionHolder( collection ); 498 } 499 500 } 501 502 } 503 504 collection.setOwner(owner); 505 506 return collection.getValue(); 507 } 508 509 public boolean hasHolder(EntityMode entityMode) { 510 return entityMode == EntityMode.DOM4J; 511 } 512 513 protected boolean initializeImmediately(EntityMode entityMode) { 514 return entityMode == EntityMode.DOM4J; 515 } 516 517 public String getLHSPropertyName() { 518 return foreignKeyPropertyName; 519 } 520 521 public boolean isXMLElement() { 522 return true; 523 } 524 525 public Object fromXMLNode(Node xml, Mapping factory) throws HibernateException { 526 return xml; 527 } 528 529 public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) 530 throws HibernateException { 531 if ( !isEmbeddedInXML ) { 532 node.detach(); 533 } 534 else { 535 replaceNode( node, (Element) value ); 536 } 537 } 538 539 public boolean isAlwaysDirtyChecked() { 540 return true; 541 } 544 545 public boolean[] toColumnNullness(Object value, Mapping mapping) { 546 return ArrayHelper.EMPTY_BOOLEAN_ARRAY; 547 } 548 } 549 | Popular Tags |