FileDocCategorySizeDatePackage
CollectionType.javaAPI DocHibernate 3.2.521343Mon Mar 19 14:43:46 GMT 2007org.hibernate.type

CollectionType

public abstract class CollectionType extends AbstractType implements AssociationType
A type that handles Hibernate PersistentCollections (including arrays).
author
Gavin King

Fields Summary
private static final Object
NOT_NULL_COLLECTION
public static final Object
UNFETCHED_COLLECTION
private final String
role
private final String
foreignKeyPropertyName
private final boolean
isEmbeddedInXML
Constructors Summary
public CollectionType(String role, String foreignKeyPropertyName, boolean isEmbeddedInXML)


	       
		this.role = role;
		this.foreignKeyPropertyName = foreignKeyPropertyName;
		this.isEmbeddedInXML = isEmbeddedInXML;
	
Methods Summary
public java.lang.Objectassemble(java.io.Serializable cached, org.hibernate.engine.SessionImplementor session, java.lang.Object owner)

		//we must use the "remembered" uk value, since it is 
		//not available from the EntityEntry during assembly
		if (cached==null) {
			return null;
		}
		else {
			final Serializable key = (Serializable) getPersister(session)
					.getKeyType()
					.assemble( cached, session, owner);
			return resolveKey( key, session, owner );
		}
	
public intcompare(java.lang.Object x, java.lang.Object y, org.hibernate.EntityMode entityMode)

		return 0; // collections cannot be compared
	
public booleancontains(java.lang.Object collection, java.lang.Object childObject, org.hibernate.engine.SessionImplementor session)

		// we do not have to worry about queued additions to uninitialized
		// collections, since they can only occur for inverse collections!
		Iterator elems = getElementsIterator( collection, session );
		while ( elems.hasNext() ) {
			Object element = elems.next();
			// worrying about proxies is perhaps a little bit of overkill here...
			if ( element instanceof HibernateProxy ) {
				LazyInitializer li = ( (HibernateProxy) element ).getHibernateLazyInitializer();
				if ( !li.isUninitialized() ) element = li.getImplementation();
			}
			if ( element == childObject ) return true;
		}
		return false;
	
public java.lang.ObjectdeepCopy(java.lang.Object value, org.hibernate.EntityMode entityMode, org.hibernate.engine.SessionFactoryImplementor factory)

		return value;
	
public java.io.Serializabledisassemble(java.lang.Object value, org.hibernate.engine.SessionImplementor session, java.lang.Object owner)

		//remember the uk value
		
		//This solution would allow us to eliminate the owner arg to disassemble(), but
		//what if the collection was null, and then later had elements added? seems unsafe
		//session.getPersistenceContext().getCollectionEntry( (PersistentCollection) value ).getKey();
		
		final Serializable key = getKeyOfOwner(owner, session);
		if (key==null) {
			return null;
		}
		else {
			return getPersister(session)
					.getKeyType()
					.disassemble( key, session, owner );
		}
	
public java.lang.ObjectfromXMLNode(org.dom4j.Node xml, org.hibernate.engine.Mapping factory)

		return xml;
	
public java.lang.StringgetAssociatedEntityName(org.hibernate.engine.SessionFactoryImplementor factory)

		try {
			
			QueryableCollection collectionPersister = (QueryableCollection) factory
					.getCollectionPersister( role );
			
			if ( !collectionPersister.getElementType().isEntityType() ) {
				throw new MappingException( 
						"collection was not an association: " + 
						collectionPersister.getRole() 
					);
			}
			
			return collectionPersister.getElementPersister().getEntityName();
			
		}
		catch (ClassCastException cce) {
			throw new MappingException( "collection role is not queryable " + role );
		}
	
public org.hibernate.persister.entity.JoinablegetAssociatedJoinable(org.hibernate.engine.SessionFactoryImplementor factory)

		return (Joinable) factory.getCollectionPersister( role );
	
public java.lang.ObjectgetCollection(java.io.Serializable key, org.hibernate.engine.SessionImplementor session, java.lang.Object owner)
instantiate a collection wrapper (called when loading an object)

param
key The collection owner key
param
session The session from which the request is originating.
param
owner The collection owner
return
The collection


		CollectionPersister persister = getPersister( session );
		final PersistenceContext persistenceContext = session.getPersistenceContext();
		final EntityMode entityMode = session.getEntityMode();

		if (entityMode==EntityMode.DOM4J && !isEmbeddedInXML) {
			return UNFETCHED_COLLECTION;
		}

		// check if collection is currently being loaded
		PersistentCollection collection = persistenceContext.getLoadContexts().locateLoadingCollection( persister, key );
		if ( collection == null ) {
			// check if it is already completely loaded, but unowned
			collection = persistenceContext.useUnownedCollection( new CollectionKey(persister, key, entityMode) );
			if ( collection == null ) {
				// create a new collection wrapper, to be initialized later
				collection = instantiate( session, persister, key );
				collection.setOwner( owner );

				persistenceContext.addUninitializedCollection( persister, collection, key );

				// some collections are not lazy:
				if ( initializeImmediately( entityMode ) ) {
					session.initializeCollection( collection, false );
				}
				else if ( !persister.isLazy() ) {
					persistenceContext.addNonLazyCollection( collection );
				}
	
				if ( hasHolder( entityMode ) ) {
					session.getPersistenceContext().addCollectionHolder( collection );
				}
			}
		}
		collection.setOwner( owner );
		return collection.getValue();
	
public intgetColumnSpan(org.hibernate.engine.Mapping session)

		return 0;
	
public final TypegetElementType(org.hibernate.engine.SessionFactoryImplementor factory)
Get the Hibernate type of the collection elements

		return factory.getCollectionPersister( getRole() ).getElementType();
	
public java.util.IteratorgetElementsIterator(java.lang.Object collection, org.hibernate.engine.SessionImplementor session)
Get an iterator over the element set of the collection, which may not yet be wrapped

param
collection The collection to be iterated
param
session The session from which the request is originating.
return
The iterator.

		if ( session.getEntityMode()==EntityMode.DOM4J ) {
			final SessionFactoryImplementor factory = session.getFactory();
			final CollectionPersister persister = factory.getCollectionPersister( getRole() );
			final Type elementType = persister.getElementType();
			
			List elements = ( (Element) collection ).elements( persister.getElementNodeName() );
			ArrayList results = new ArrayList();
			for ( int i=0; i<elements.size(); i++ ) {
				Element value = (Element) elements.get(i);
				results.add( elementType.fromXMLNode( value, factory ) );
			}
			return results.iterator();
		}
		else {
			return getElementsIterator(collection);
		}
	
protected java.util.IteratorgetElementsIterator(java.lang.Object collection)
Get an iterator over the element set of the collection in POJO mode

param
collection The collection to be iterated
return
The iterator.

		return ( (Collection) collection ).iterator();
	
public ForeignKeyDirectiongetForeignKeyDirection()

		return ForeignKeyDirection.FOREIGN_KEY_TO_PARENT;
	
public intgetHashCode(java.lang.Object x, org.hibernate.EntityMode entityMode)

		throw new UnsupportedOperationException( "cannot perform lookups on collections" );
	
public java.io.SerializablegetKeyOfOwner(java.lang.Object owner, org.hibernate.engine.SessionImplementor session)
Get the key value from the owning entity instance, usually the identifier, but might be some other unique key, in the case of property-ref

param
owner The collection owner
param
session The session from which the request is originating.
return
The collection owner's key

		
		EntityEntry entityEntry = session.getPersistenceContext().getEntry( owner );
		if ( entityEntry == null ) return null; // This just handles a particular case of component
									  // projection, perhaps get rid of it and throw an exception
		
		if ( foreignKeyPropertyName == null ) {
			return entityEntry.getId();
		}
		else {
			// TODO: at the point where we are resolving collection references, we don't
			// know if the uk value has been resolved (depends if it was earlier or
			// later in the mapping document) - now, we could try and use e.getStatus()
			// to decide to semiResolve(), trouble is that initializeEntity() reuses
			// the same array for resolved and hydrated values
			Object id;
			if ( entityEntry.getLoadedState() != null ) {
				id = entityEntry.getLoadedValue( foreignKeyPropertyName );
			}
			else {
				id = entityEntry.getPersister().getPropertyValue( owner, foreignKeyPropertyName, session.getEntityMode() );
			}

			// NOTE VERY HACKISH WORKAROUND!!
			Type keyType = getPersister( session ).getKeyType();
			if ( !keyType.getReturnedClass().isInstance( id ) ) {
				id = (Serializable) keyType.semiResolve(
						entityEntry.getLoadedValue( foreignKeyPropertyName ),
						session,
						owner 
					);
			}

			return (Serializable) id;
		}
	
public java.lang.StringgetLHSPropertyName()

		return foreignKeyPropertyName;
	
public java.lang.StringgetName()

		return getReturnedClass().getName() + '(" + getRole() + ')";
	
public java.lang.StringgetOnCondition(java.lang.String alias, org.hibernate.engine.SessionFactoryImplementor factory, java.util.Map enabledFilters)

		return getAssociatedJoinable( factory ).filterFragment( alias, enabledFilters );
	
private org.hibernate.persister.collection.CollectionPersistergetPersister(org.hibernate.engine.SessionImplementor session)
Get our underlying collection persister (using the session to access the factory).

param
session The session from which the request is originating.
return
The underlying collection persister
throws
org.hibernate.MappingException Indicates the underlying persister could not be located.

		return session.getFactory().getCollectionPersister( role );
	
public java.lang.StringgetRHSUniqueKeyPropertyName()

		return null;
	
public java.lang.StringgetRole()

		return role;
	
public booleanhasHolder(org.hibernate.EntityMode entityMode)

		return entityMode == EntityMode.DOM4J;
	
public java.lang.Objecthydrate(java.sql.ResultSet rs, java.lang.String[] name, org.hibernate.engine.SessionImplementor session, java.lang.Object owner)

		// can't just return null here, since that would
		// cause an owning component to become null
		return NOT_NULL_COLLECTION;
	
public java.lang.ObjectindexOf(java.lang.Object collection, java.lang.Object element)

		throw new UnsupportedOperationException( "generic collections don't have indexes" );
	
protected booleaninitializeImmediately(org.hibernate.EntityMode entityMode)

		return entityMode == EntityMode.DOM4J;
	
public abstract org.hibernate.collection.PersistentCollectioninstantiate(org.hibernate.engine.SessionImplementor session, org.hibernate.persister.collection.CollectionPersister persister, java.io.Serializable key)
Instantiate an uninitialized collection wrapper or holder. Callers MUST add the holder to the persistence context!

param
session The session from which the request is originating.
param
persister The underlying collection persister (metadata)
param
key The owner key.
return
The instantiated collection.

public abstract java.lang.Objectinstantiate(int anticipatedSize)
Instantiate an empty instance of the "underlying" collection (not a wrapper), but with the given anticipated size (i.e. accounting for initial capacity and perhaps load factor).

param
anticipatedSize The anticipated size of the instaniated collection after we are done populating it.
return
A newly instantiated collection to be wrapped.

protected java.lang.ObjectinstantiateResult(java.lang.Object original)
Instantiate a new "underlying" collection exhibiting the same capacity charactersitcs and the passed "original".

param
original The original collection.
return
The newly instantiated collection.

		// by default just use an unanticipated capacity since we don't
		// know how to extract the capacity to use from original here...
		return instantiate( -1 );
	
public booleanisAlwaysDirtyChecked()
We always need to dirty check the collection because we sometimes need to incremement version number of owner and also because of how assemble/disassemble is implemented for uks

		return true; 
	
public booleanisArrayType()

		return false;
	
public booleanisAssociationType()
Note: return true because this type is castable to AssociationType. Not because all collections are associations.

		return true;
	
public booleanisCollectionType()

		return true;
	
public booleanisDirty(java.lang.Object old, java.lang.Object current, org.hibernate.engine.SessionImplementor session)


		// collections don't dirty an unversioned parent entity

		// TODO: I don't really like this implementation; it would be better if
		// this was handled by searchForDirtyCollections()
		return isOwnerVersioned( session ) && super.isDirty( old, current, session );
		// return false;

	
public booleanisDirty(java.lang.Object old, java.lang.Object current, boolean[] checkable, org.hibernate.engine.SessionImplementor session)

		return isDirty(old, current, session);
	
public booleanisEmbeddedInXML()

		return isEmbeddedInXML;
	
public final booleanisEqual(java.lang.Object x, java.lang.Object y, org.hibernate.EntityMode entityMode)

		return x == y
			|| ( x instanceof PersistentCollection && ( (PersistentCollection) x ).isWrapper( y ) )
			|| ( y instanceof PersistentCollection && ( (PersistentCollection) y ).isWrapper( x ) );
	
public booleanisModified(java.lang.Object old, java.lang.Object current, boolean[] checkable, org.hibernate.engine.SessionImplementor session)

		return false;
	
public booleanisMutable()

		return false;
	
private booleanisOwnerVersioned(org.hibernate.engine.SessionImplementor session)
Is the owning entity versioned?

param
session The session from which the request is originating.
return
True if the collection owner is versioned; false otherwise.
throws
MappingException Indicates the underlying persister could not be located.

		return getPersister( session ).getOwnerEntityPersister().isVersioned();
	
public booleanisXMLElement()

		return true;
	
public java.lang.ObjectnullSafeGet(java.sql.ResultSet rs, java.lang.String name, org.hibernate.engine.SessionImplementor session, java.lang.Object owner)

		return nullSafeGet( rs, new String[] { name }, session, owner );
	
public java.lang.ObjectnullSafeGet(java.sql.ResultSet rs, java.lang.String[] name, org.hibernate.engine.SessionImplementor session, java.lang.Object owner)

		return resolve( null, session, owner );
	
public final voidnullSafeSet(java.sql.PreparedStatement st, java.lang.Object value, int index, boolean[] settable, org.hibernate.engine.SessionImplementor session)

		//NOOP
	
public voidnullSafeSet(java.sql.PreparedStatement st, java.lang.Object value, int index, org.hibernate.engine.SessionImplementor session)

	
protected java.lang.StringrenderLoggableString(java.lang.Object value, org.hibernate.engine.SessionFactoryImplementor factory)

		if ( Element.class.isInstance( value ) ) {
			// for DOM4J "collections" only
			// TODO: it would be better if this was done at the higher level by Printer
			return ( ( Element ) value ).asXML();
		}
		else {
			List list = new ArrayList();
			Type elemType = getElementType( factory );
			Iterator iter = getElementsIterator( value );
			while ( iter.hasNext() ) {
				list.add( elemType.toLoggableString( iter.next(), factory ) );
			}
			return list.toString();
		}
	
public java.lang.Objectreplace(java.lang.Object original, java.lang.Object target, org.hibernate.engine.SessionImplementor session, java.lang.Object owner, java.util.Map copyCache)
{@inheritDoc}

		if ( original == null ) {
			return null;
		}
		if ( !Hibernate.isInitialized( original ) ) {
			return target;
		}

		// for a null target, or a target which is the same as the original, we
		// need to put the merged elements in a new collection
		Object result = target == null || target == original ? instantiateResult( original ) : target;
		
		//for arrays, replaceElements() may return a different reference, since
		//the array length might not match
		result = replaceElements( original, result, owner, copyCache, session );
		
		if (original==target) {
			//get the elements back into the target
			//TODO: this is a little inefficient, don't need to do a whole
			//      deep replaceElements() call
			replaceElements( result, target, owner, copyCache, session );
			result = target;
		}
				
		return result;
	
public java.lang.ObjectreplaceElements(java.lang.Object original, java.lang.Object target, java.lang.Object owner, java.util.Map copyCache, org.hibernate.engine.SessionImplementor session)
Replace the elements of a collection with the elements of another collection.

param
original The 'source' of the replacement elements (where we copy from)
param
target The target of the replacement elements (where we copy to)
param
owner The owner of the collection being merged
param
copyCache The map of elements already replaced.
param
session The session from which the merge event originated.
return
The merged collection.

		// TODO: does not work for EntityMode.DOM4J yet!
		java.util.Collection result = ( java.util.Collection ) target;
		result.clear();

		// copy elements into newly empty target collection
		Type elemType = getElementType( session.getFactory() );
		Iterator iter = ( (java.util.Collection) original ).iterator();
		while ( iter.hasNext() ) {
			result.add( elemType.replace( iter.next(), null, session, owner, copyCache ) );
		}

		// if the original is a PersistentCollection, and that original
		// was not flagged as dirty, then reset the target's dirty flag
		// here after the copy operation.
		// </p>
		// One thing to be careful of here is a "bare" original collection
		// in which case we should never ever ever reset the dirty flag
		// on the target because we simply do not know...
		if ( original instanceof PersistentCollection ) {
			if ( result instanceof PersistentCollection ) {
				if ( ! ( ( PersistentCollection ) original ).isDirty() ) {
					( ( PersistentCollection ) result ).clearDirty();
				}
			}
		}

		return result;
	
public java.lang.Objectresolve(java.lang.Object value, org.hibernate.engine.SessionImplementor session, java.lang.Object owner)

		
		return resolveKey( getKeyOfOwner( owner, session ), session, owner );
	
private java.lang.ObjectresolveKey(java.io.Serializable key, org.hibernate.engine.SessionImplementor session, java.lang.Object owner)

		// if (key==null) throw new AssertionFailure("owner identifier unknown when re-assembling
		// collection reference");
		return key == null ? null : // TODO: can this case really occur??
			getCollection( key, session, owner );
	
public java.lang.ObjectsemiResolve(java.lang.Object value, org.hibernate.engine.SessionImplementor session, java.lang.Object owner)

		throw new UnsupportedOperationException(
			"collection mappings may not form part of a property-ref" );
	
public voidsetToXMLNode(org.dom4j.Node node, java.lang.Object value, org.hibernate.engine.SessionFactoryImplementor factory)

		if ( !isEmbeddedInXML ) {
			node.detach();
		}
		else {
			replaceNode( node, (Element) value );
		}
	
public int[]sqlTypes(org.hibernate.engine.Mapping session)

		return ArrayHelper.EMPTY_INT_ARRAY;
	
public boolean[]toColumnNullness(java.lang.Object value, org.hibernate.engine.Mapping mapping)

		return ArrayHelper.EMPTY_BOOLEAN_ARRAY;
	
public java.lang.StringtoLoggableString(java.lang.Object value, org.hibernate.engine.SessionFactoryImplementor factory)

		if ( value == null ) {
			return "null";
		}
		else if ( !Hibernate.isInitialized( value ) ) {
			return "<uninitialized>";
		}
		else {
			return renderLoggableString( value, factory );
		}
	
public java.lang.StringtoString()

		return getClass().getName() + '(" + getRole() + ')";
	
public booleanuseLHSPrimaryKey()

		return foreignKeyPropertyName == null;
	
public abstract org.hibernate.collection.PersistentCollectionwrap(org.hibernate.engine.SessionImplementor session, java.lang.Object collection)
Wrap the naked collection instance in a wrapper, or instantiate a holder. Callers MUST add the holder to the persistence context!

param
session The session from which the request is originating.
param
collection The bare collection to be wrapped.
return
The wrapped collection.