Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » type » [javadoc | source]
    1   /*
    2    * Hibernate, Relational Persistence for Idiomatic Java
    3    *
    4    * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
    5    * indicated by the @author tags or express copyright attribution
    6    * statements applied by the authors.  All third-party contributions are
    7    * distributed under license by Red Hat Middleware LLC.
    8    *
    9    * This copyrighted material is made available to anyone wishing to use, modify,
   10    * copy, or redistribute it subject to the terms and conditions of the GNU
   11    * Lesser General Public License, as published by the Free Software Foundation.
   12    *
   13    * This program is distributed in the hope that it will be useful,
   14    * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15    * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   16    * for more details.
   17    *
   18    * You should have received a copy of the GNU Lesser General Public License
   19    * along with this distribution; if not, write to:
   20    * Free Software Foundation, Inc.
   21    * 51 Franklin Street, Fifth Floor
   22    * Boston, MA  02110-1301  USA
   23    *
   24    */
   25   package org.hibernate.type;
   26   
   27   import java.io.Serializable;
   28   import java.sql.PreparedStatement;
   29   import java.sql.ResultSet;
   30   import java.sql.SQLException;
   31   import java.util.ArrayList;
   32   import java.util.Collection;
   33   import java.util.Iterator;
   34   import java.util.List;
   35   import java.util.Map;
   36   
   37   import org.dom4j.Element;
   38   import org.dom4j.Node;
   39   
   40   import org.hibernate.EntityMode;
   41   import org.hibernate.Hibernate;
   42   import org.hibernate.HibernateException;
   43   import org.hibernate.MappingException;
   44   import org.hibernate.collection.PersistentCollection;
   45   import org.hibernate.engine.CollectionKey;
   46   import org.hibernate.engine.EntityEntry;
   47   import org.hibernate.engine.Mapping;
   48   import org.hibernate.engine.PersistenceContext;
   49   import org.hibernate.engine.SessionFactoryImplementor;
   50   import org.hibernate.engine.SessionImplementor;
   51   import org.hibernate.persister.collection.CollectionPersister;
   52   import org.hibernate.persister.collection.QueryableCollection;
   53   import org.hibernate.persister.entity.EntityPersister;
   54   import org.hibernate.persister.entity.Joinable;
   55   import org.hibernate.proxy.HibernateProxy;
   56   import org.hibernate.proxy.LazyInitializer;
   57   import org.hibernate.util.ArrayHelper;
   58   import org.hibernate.util.MarkerObject;
   59   
   60   /**
   61    * A type that handles Hibernate <tt>PersistentCollection</tt>s (including arrays).
   62    * 
   63    * @author Gavin King
   64    */
   65   public abstract class CollectionType extends AbstractType implements AssociationType {
   66   
   67   	private static final Object NOT_NULL_COLLECTION = new MarkerObject( "NOT NULL COLLECTION" );
   68   	public static final Object UNFETCHED_COLLECTION = new MarkerObject( "UNFETCHED COLLECTION" );
   69   
   70   	private final String role;
   71   	private final String foreignKeyPropertyName;
   72   	private final boolean isEmbeddedInXML;
   73   
   74   	public CollectionType(String role, String foreignKeyPropertyName, boolean isEmbeddedInXML) {
   75   		this.role = role;
   76   		this.foreignKeyPropertyName = foreignKeyPropertyName;
   77   		this.isEmbeddedInXML = isEmbeddedInXML;
   78   	}
   79   	
   80   	public boolean isEmbeddedInXML() {
   81   		return isEmbeddedInXML;
   82   	}
   83   
   84   	public String getRole() {
   85   		return role;
   86   	}
   87   
   88   	public Object indexOf(Object collection, Object element) {
   89   		throw new UnsupportedOperationException( "generic collections don't have indexes" );
   90   	}
   91   
   92   	public boolean contains(Object collection, Object childObject, SessionImplementor session) {
   93   		// we do not have to worry about queued additions to uninitialized
   94   		// collections, since they can only occur for inverse collections!
   95   		Iterator elems = getElementsIterator( collection, session );
   96   		while ( elems.hasNext() ) {
   97   			Object element = elems.next();
   98   			// worrying about proxies is perhaps a little bit of overkill here...
   99   			if ( element instanceof HibernateProxy ) {
  100   				LazyInitializer li = ( (HibernateProxy) element ).getHibernateLazyInitializer();
  101   				if ( !li.isUninitialized() ) element = li.getImplementation();
  102   			}
  103   			if ( element == childObject ) return true;
  104   		}
  105   		return false;
  106   	}
  107   
  108   	public boolean isCollectionType() {
  109   		return true;
  110   	}
  111   
  112   	public final boolean isEqual(Object x, Object y, EntityMode entityMode) {
  113   		return x == y
  114   			|| ( x instanceof PersistentCollection && ( (PersistentCollection) x ).isWrapper( y ) )
  115   			|| ( y instanceof PersistentCollection && ( (PersistentCollection) y ).isWrapper( x ) );
  116   	}
  117   
  118   	public int compare(Object x, Object y, EntityMode entityMode) {
  119   		return 0; // collections cannot be compared
  120   	}
  121   
  122   	public int getHashCode(Object x, EntityMode entityMode) {
  123   		throw new UnsupportedOperationException( "cannot perform lookups on collections" );
  124   	}
  125   
  126   	/**
  127   	 * Instantiate an uninitialized collection wrapper or holder. Callers MUST add the holder to the
  128   	 * persistence context!
  129   	 *
  130   	 * @param session The session from which the request is originating.
  131   	 * @param persister The underlying collection persister (metadata)
  132   	 * @param key The owner key.
  133   	 * @return The instantiated collection.
  134   	 */
  135   	public abstract PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister, Serializable key);
  136   
  137   	public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner) throws SQLException {
  138   		return nullSafeGet( rs, new String[] { name }, session, owner );
  139   	}
  140   
  141   	public Object nullSafeGet(ResultSet rs, String[] name, SessionImplementor session, Object owner)
  142   			throws HibernateException, SQLException {
  143   		return resolve( null, session, owner );
  144   	}
  145   
  146   	public final void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable,
  147   			SessionImplementor session) throws HibernateException, SQLException {
  148   		//NOOP
  149   	}
  150   
  151   	public void nullSafeSet(PreparedStatement st, Object value, int index,
  152   			SessionImplementor session) throws HibernateException, SQLException {
  153   	}
  154   
  155   	public int[] sqlTypes(Mapping session) throws MappingException {
  156   		return ArrayHelper.EMPTY_INT_ARRAY;
  157   	}
  158   
  159   	public int getColumnSpan(Mapping session) throws MappingException {
  160   		return 0;
  161   	}
  162   
  163   	public String toLoggableString(Object value, SessionFactoryImplementor factory)
  164   			throws HibernateException {
  165   		if ( value == null ) {
  166   			return "null";
  167   		}
  168   		else if ( !Hibernate.isInitialized( value ) ) {
  169   			return "<uninitialized>";
  170   		}
  171   		else {
  172   			return renderLoggableString( value, factory );
  173   		}
  174   	}
  175   
  176   	protected String renderLoggableString(Object value, SessionFactoryImplementor factory)
  177   			throws HibernateException {
  178   		if ( Element.class.isInstance( value ) ) {
  179   			// for DOM4J "collections" only
  180   			// TODO: it would be better if this was done at the higher level by Printer
  181   			return ( ( Element ) value ).asXML();
  182   		}
  183   		else {
  184   			List list = new ArrayList();
  185   			Type elemType = getElementType( factory );
  186   			Iterator iter = getElementsIterator( value );
  187   			while ( iter.hasNext() ) {
  188   				list.add( elemType.toLoggableString( iter.next(), factory ) );
  189   			}
  190   			return list.toString();
  191   		}
  192   	}
  193   
  194   	public Object deepCopy(Object value, EntityMode entityMode, SessionFactoryImplementor factory)
  195   			throws HibernateException {
  196   		return value;
  197   	}
  198   
  199   	public String getName() {
  200   		return getReturnedClass().getName() + '(' + getRole() + ')';
  201   	}
  202   
  203   	/**
  204   	 * Get an iterator over the element set of the collection, which may not yet be wrapped
  205   	 *
  206   	 * @param collection The collection to be iterated
  207   	 * @param session The session from which the request is originating.
  208   	 * @return The iterator.
  209   	 */
  210   	public Iterator getElementsIterator(Object collection, SessionImplementor session) {
  211   		if ( session.getEntityMode()==EntityMode.DOM4J ) {
  212   			final SessionFactoryImplementor factory = session.getFactory();
  213   			final CollectionPersister persister = factory.getCollectionPersister( getRole() );
  214   			final Type elementType = persister.getElementType();
  215   			
  216   			List elements = ( (Element) collection ).elements( persister.getElementNodeName() );
  217   			ArrayList results = new ArrayList();
  218   			for ( int i=0; i<elements.size(); i++ ) {
  219   				Element value = (Element) elements.get(i);
  220   				results.add( elementType.fromXMLNode( value, factory ) );
  221   			}
  222   			return results.iterator();
  223   		}
  224   		else {
  225   			return getElementsIterator(collection);
  226   		}
  227   	}
  228   
  229   	/**
  230   	 * Get an iterator over the element set of the collection in POJO mode
  231   	 *
  232   	 * @param collection The collection to be iterated
  233   	 * @return The iterator.
  234   	 */
  235   	protected Iterator getElementsIterator(Object collection) {
  236   		return ( (Collection) collection ).iterator();
  237   	}
  238   
  239   	public boolean isMutable() {
  240   		return false;
  241   	}
  242   
  243   	public Serializable disassemble(Object value, SessionImplementor session, Object owner)
  244   			throws HibernateException {
  245   		//remember the uk value
  246   		
  247   		//This solution would allow us to eliminate the owner arg to disassemble(), but
  248   		//what if the collection was null, and then later had elements added? seems unsafe
  249   		//session.getPersistenceContext().getCollectionEntry( (PersistentCollection) value ).getKey();
  250   		
  251   		final Serializable key = getKeyOfOwner(owner, session);
  252   		if (key==null) {
  253   			return null;
  254   		}
  255   		else {
  256   			return getPersister(session)
  257   					.getKeyType()
  258   					.disassemble( key, session, owner );
  259   		}
  260   	}
  261   
  262   	public Object assemble(Serializable cached, SessionImplementor session, Object owner)
  263   			throws HibernateException {
  264   		//we must use the "remembered" uk value, since it is 
  265   		//not available from the EntityEntry during assembly
  266   		if (cached==null) {
  267   			return null;
  268   		}
  269   		else {
  270   			final Serializable key = (Serializable) getPersister(session)
  271   					.getKeyType()
  272   					.assemble( cached, session, owner);
  273   			return resolveKey( key, session, owner );
  274   		}
  275   	}
  276   
  277   	/**
  278   	 * Is the owning entity versioned?
  279   	 *
  280   	 * @param session The session from which the request is originating.
  281   	 * @return True if the collection owner is versioned; false otherwise.
  282   	 * @throws org.hibernate.MappingException Indicates our persister could not be located.
  283   	 */
  284   	private boolean isOwnerVersioned(SessionImplementor session) throws MappingException {
  285   		return getPersister( session ).getOwnerEntityPersister().isVersioned();
  286   	}
  287   
  288   	/**
  289   	 * Get our underlying collection persister (using the session to access the
  290   	 * factory).
  291   	 *
  292   	 * @param session The session from which the request is originating.
  293   	 * @return The underlying collection persister
  294   	 */
  295   	private CollectionPersister getPersister(SessionImplementor session) {
  296   		return session.getFactory().getCollectionPersister( role );
  297   	}
  298   
  299   	public boolean isDirty(Object old, Object current, SessionImplementor session)
  300   			throws HibernateException {
  301   
  302   		// collections don't dirty an unversioned parent entity
  303   
  304   		// TODO: I don't really like this implementation; it would be better if
  305   		// this was handled by searchForDirtyCollections()
  306   		return isOwnerVersioned( session ) && super.isDirty( old, current, session );
  307   		// return false;
  308   
  309   	}
  310   
  311   	public boolean isDirty(Object old, Object current, boolean[] checkable, SessionImplementor session)
  312   			throws HibernateException {
  313   		return isDirty(old, current, session);
  314   	}
  315   
  316   	/**
  317   	 * Wrap the naked collection instance in a wrapper, or instantiate a
  318   	 * holder. Callers <b>MUST</b> add the holder to the persistence context!
  319   	 *
  320   	 * @param session The session from which the request is originating.
  321   	 * @param collection The bare collection to be wrapped.
  322   	 * @return The wrapped collection.
  323   	 */
  324   	public abstract PersistentCollection wrap(SessionImplementor session, Object collection);
  325   
  326   	/**
  327   	 * Note: return true because this type is castable to <tt>AssociationType</tt>. Not because
  328   	 * all collections are associations.
  329   	 */
  330   	public boolean isAssociationType() {
  331   		return true;
  332   	}
  333   
  334   	public ForeignKeyDirection getForeignKeyDirection() {
  335   		return ForeignKeyDirection.FOREIGN_KEY_TO_PARENT;
  336   	}
  337   
  338   	/**
  339   	 * Get the key value from the owning entity instance, usually the identifier, but might be some
  340   	 * other unique key, in the case of property-ref
  341   	 *
  342   	 * @param owner The collection owner
  343   	 * @param session The session from which the request is originating.
  344   	 * @return The collection owner's key
  345   	 */
  346   	public Serializable getKeyOfOwner(Object owner, SessionImplementor session) {
  347   		
  348   		EntityEntry entityEntry = session.getPersistenceContext().getEntry( owner );
  349   		if ( entityEntry == null ) return null; // This just handles a particular case of component
  350   									  // projection, perhaps get rid of it and throw an exception
  351   		
  352   		if ( foreignKeyPropertyName == null ) {
  353   			return entityEntry.getId();
  354   		}
  355   		else {
  356   			// TODO: at the point where we are resolving collection references, we don't
  357   			// know if the uk value has been resolved (depends if it was earlier or
  358   			// later in the mapping document) - now, we could try and use e.getStatus()
  359   			// to decide to semiResolve(), trouble is that initializeEntity() reuses
  360   			// the same array for resolved and hydrated values
  361   			Object id;
  362   			if ( entityEntry.getLoadedState() != null ) {
  363   				id = entityEntry.getLoadedValue( foreignKeyPropertyName );
  364   			}
  365   			else {
  366   				id = entityEntry.getPersister().getPropertyValue( owner, foreignKeyPropertyName, session.getEntityMode() );
  367   			}
  368   
  369   			// NOTE VERY HACKISH WORKAROUND!!
  370   			// TODO: Fix this so it will work for non-POJO entity mode
  371   			Type keyType = getPersister( session ).getKeyType();
  372   			if ( !keyType.getReturnedClass().isInstance( id ) ) {
  373   				id = (Serializable) keyType.semiResolve(
  374   						entityEntry.getLoadedValue( foreignKeyPropertyName ),
  375   						session,
  376   						owner 
  377   					);
  378   			}
  379   
  380   			return (Serializable) id;
  381   		}
  382   	}
  383   
  384   	/**
  385   	 * Get the id value from the owning entity key, usually the same as the key, but might be some
  386   	 * other property, in the case of property-ref
  387   	 *
  388   	 * @param key The collection owner key
  389   	 * @param session The session from which the request is originating.
  390   	 * @return The collection owner's id, if it can be obtained from the key;
  391   	 * otherwise, null is returned
  392   	 */
  393   	public Serializable getIdOfOwnerOrNull(Serializable key, SessionImplementor session) {
  394   		Serializable ownerId = null;
  395   		if ( foreignKeyPropertyName == null ) {
  396   			ownerId = key;
  397   		}
  398   		else {
  399   			Type keyType = getPersister( session ).getKeyType();
  400   			EntityPersister ownerPersister = getPersister( session ).getOwnerEntityPersister();
  401   			// TODO: Fix this so it will work for non-POJO entity mode
  402   			Class ownerMappedClass = ownerPersister.getMappedClass( session.getEntityMode() );
  403   			if ( ownerMappedClass.isAssignableFrom( keyType.getReturnedClass() ) &&
  404   					keyType.getReturnedClass().isInstance( key ) ) {
  405   				// the key is the owning entity itself, so get the ID from the key
  406   				ownerId = ownerPersister.getIdentifier( key, session.getEntityMode() );
  407   			}
  408   			else {
  409   				// TODO: check if key contains the owner ID
  410   			}
  411   		}
  412   		return ownerId;
  413   	}
  414   
  415   	public Object hydrate(ResultSet rs, String[] name, SessionImplementor session, Object owner) {
  416   		// can't just return null here, since that would
  417   		// cause an owning component to become null
  418   		return NOT_NULL_COLLECTION;
  419   	}
  420   
  421   	public Object resolve(Object value, SessionImplementor session, Object owner)
  422   			throws HibernateException {
  423   		
  424   		return resolveKey( getKeyOfOwner( owner, session ), session, owner );
  425   	}
  426   	
  427   	private Object resolveKey(Serializable key, SessionImplementor session, Object owner) {
  428   		// if (key==null) throw new AssertionFailure("owner identifier unknown when re-assembling
  429   		// collection reference");
  430   		return key == null ? null : // TODO: can this case really occur??
  431   			getCollection( key, session, owner );
  432   	}
  433   
  434   	public Object semiResolve(Object value, SessionImplementor session, Object owner)
  435   			throws HibernateException {
  436   		throw new UnsupportedOperationException(
  437   			"collection mappings may not form part of a property-ref" );
  438   	}
  439   
  440   	public boolean isArrayType() {
  441   		return false;
  442   	}
  443   
  444   	public boolean useLHSPrimaryKey() {
  445   		return foreignKeyPropertyName == null;
  446   	}
  447   
  448   	public String getRHSUniqueKeyPropertyName() {
  449   		return null;
  450   	}
  451   
  452   	public Joinable getAssociatedJoinable(SessionFactoryImplementor factory)
  453   			throws MappingException {
  454   		return (Joinable) factory.getCollectionPersister( role );
  455   	}
  456   
  457   	public boolean isModified(Object old, Object current, boolean[] checkable, SessionImplementor session) throws HibernateException {
  458   		return false;
  459   	}
  460   
  461   	public String getAssociatedEntityName(SessionFactoryImplementor factory)
  462   			throws MappingException {
  463   		try {
  464   			
  465   			QueryableCollection collectionPersister = (QueryableCollection) factory
  466   					.getCollectionPersister( role );
  467   			
  468   			if ( !collectionPersister.getElementType().isEntityType() ) {
  469   				throw new MappingException( 
  470   						"collection was not an association: " + 
  471   						collectionPersister.getRole() 
  472   					);
  473   			}
  474   			
  475   			return collectionPersister.getElementPersister().getEntityName();
  476   			
  477   		}
  478   		catch (ClassCastException cce) {
  479   			throw new MappingException( "collection role is not queryable " + role );
  480   		}
  481   	}
  482   
  483   	/**
  484   	 * Replace the elements of a collection with the elements of another collection.
  485   	 *
  486   	 * @param original The 'source' of the replacement elements (where we copy from)
  487   	 * @param target The target of the replacement elements (where we copy to)
  488   	 * @param owner The owner of the collection being merged
  489   	 * @param copyCache The map of elements already replaced.
  490   	 * @param session The session from which the merge event originated.
  491   	 * @return The merged collection.
  492   	 */
  493   	public Object replaceElements(
  494   			Object original,
  495   			Object target,
  496   			Object owner,
  497   			Map copyCache,
  498   			SessionImplementor session) {
  499   		// TODO: does not work for EntityMode.DOM4J yet!
  500   		java.util.Collection result = ( java.util.Collection ) target;
  501   		result.clear();
  502   
  503   		// copy elements into newly empty target collection
  504   		Type elemType = getElementType( session.getFactory() );
  505   		Iterator iter = ( (java.util.Collection) original ).iterator();
  506   		while ( iter.hasNext() ) {
  507   			result.add( elemType.replace( iter.next(), null, session, owner, copyCache ) );
  508   		}
  509   
  510   		// if the original is a PersistentCollection, and that original
  511   		// was not flagged as dirty, then reset the target's dirty flag
  512   		// here after the copy operation.
  513   		// </p>
  514   		// One thing to be careful of here is a "bare" original collection
  515   		// in which case we should never ever ever reset the dirty flag
  516   		// on the target because we simply do not know...
  517   		if ( original instanceof PersistentCollection ) {
  518   			if ( result instanceof PersistentCollection ) {
  519   				if ( ! ( ( PersistentCollection ) original ).isDirty() ) {
  520   					( ( PersistentCollection ) result ).clearDirty();
  521   				}
  522   			}
  523   		}
  524   
  525   		return result;
  526   	}
  527   
  528   	/**
  529   	 * Instantiate a new "underlying" collection exhibiting the same capacity
  530   	 * charactersitcs and the passed "original".
  531   	 *
  532   	 * @param original The original collection.
  533   	 * @return The newly instantiated collection.
  534   	 */
  535   	protected Object instantiateResult(Object original) {
  536   		// by default just use an unanticipated capacity since we don't
  537   		// know how to extract the capacity to use from original here...
  538   		return instantiate( -1 );
  539   	}
  540   
  541   	/**
  542   	 * Instantiate an empty instance of the "underlying" collection (not a wrapper),
  543   	 * but with the given anticipated size (i.e. accounting for initial capacity
  544   	 * and perhaps load factor).
  545   	 *
  546   	 * @param anticipatedSize The anticipated size of the instaniated collection
  547   	 * after we are done populating it.
  548   	 * @return A newly instantiated collection to be wrapped.
  549   	 */
  550   	public abstract Object instantiate(int anticipatedSize);
  551   
  552   	/**
  553   	 * {@inheritDoc}
  554   	 */
  555   	public Object replace(
  556   			final Object original,
  557   			final Object target,
  558   			final SessionImplementor session,
  559   			final Object owner,
  560   			final Map copyCache) throws HibernateException {
  561   		if ( original == null ) {
  562   			return null;
  563   		}
  564   		if ( !Hibernate.isInitialized( original ) ) {
  565   			return target;
  566   		}
  567   
  568   		// for a null target, or a target which is the same as the original, we
  569   		// need to put the merged elements in a new collection
  570   		Object result = target == null || target == original ? instantiateResult( original ) : target;
  571   		
  572   		//for arrays, replaceElements() may return a different reference, since
  573   		//the array length might not match
  574   		result = replaceElements( original, result, owner, copyCache, session );
  575   
  576   		if ( original == target ) {
  577   			// get the elements back into the target making sure to handle dirty flag
  578   			boolean wasClean = PersistentCollection.class.isInstance( target ) && !( ( PersistentCollection ) target ).isDirty();
  579   			//TODO: this is a little inefficient, don't need to do a whole
  580   			//      deep replaceElements() call
  581   			replaceElements( result, target, owner, copyCache, session );
  582   			if ( wasClean ) {
  583   				( ( PersistentCollection ) target ).clearDirty();
  584   			}
  585   			result = target;
  586   		}
  587   
  588   		return result;
  589   	}
  590   
  591   	/**
  592   	 * Get the Hibernate type of the collection elements
  593   	 *
  594   	 * @param factory The session factory.
  595   	 * @return The type of the collection elements
  596   	 * @throws MappingException Indicates the underlying persister could not be located.
  597   	 */
  598   	public final Type getElementType(SessionFactoryImplementor factory) throws MappingException {
  599   		return factory.getCollectionPersister( getRole() ).getElementType();
  600   	}
  601   
  602   	public String toString() {
  603   		return getClass().getName() + '(' + getRole() + ')';
  604   	}
  605   
  606   	public String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters)
  607   			throws MappingException {
  608   		return getAssociatedJoinable( factory ).filterFragment( alias, enabledFilters );
  609   	}
  610   
  611   	/**
  612   	 * instantiate a collection wrapper (called when loading an object)
  613   	 *
  614   	 * @param key The collection owner key
  615   	 * @param session The session from which the request is originating.
  616   	 * @param owner The collection owner
  617   	 * @return The collection
  618   	 */
  619   	public Object getCollection(Serializable key, SessionImplementor session, Object owner) {
  620   
  621   		CollectionPersister persister = getPersister( session );
  622   		final PersistenceContext persistenceContext = session.getPersistenceContext();
  623   		final EntityMode entityMode = session.getEntityMode();
  624   
  625   		if (entityMode==EntityMode.DOM4J && !isEmbeddedInXML) {
  626   			return UNFETCHED_COLLECTION;
  627   		}
  628   		
  629   		// check if collection is currently being loaded
  630   		PersistentCollection collection = persistenceContext.getLoadContexts().locateLoadingCollection( persister, key );
  631   		
  632   		if ( collection == null ) {
  633   			
  634   			// check if it is already completely loaded, but unowned
  635   			collection = persistenceContext.useUnownedCollection( new CollectionKey(persister, key, entityMode) );
  636   			
  637   			if ( collection == null ) {
  638   				// create a new collection wrapper, to be initialized later
  639   				collection = instantiate( session, persister, key );
  640   				collection.setOwner(owner);
  641   	
  642   				persistenceContext.addUninitializedCollection( persister, collection, key );
  643   	
  644   				// some collections are not lazy:
  645   				if ( initializeImmediately( entityMode ) ) {
  646   					session.initializeCollection( collection, false );
  647   				}
  648   				else if ( !persister.isLazy() ) {
  649   					persistenceContext.addNonLazyCollection( collection );
  650   				}
  651   	
  652   				if ( hasHolder( entityMode ) ) {
  653   					session.getPersistenceContext().addCollectionHolder( collection );
  654   				}
  655   				
  656   			}
  657   			
  658   		}
  659   		
  660   		collection.setOwner(owner);
  661   
  662   		return collection.getValue();
  663   	}
  664   
  665   	public boolean hasHolder(EntityMode entityMode) {
  666   		return entityMode == EntityMode.DOM4J;
  667   	}
  668   
  669   	protected boolean initializeImmediately(EntityMode entityMode) {
  670   		return entityMode == EntityMode.DOM4J;
  671   	}
  672   
  673   	public String getLHSPropertyName() {
  674   		return foreignKeyPropertyName;
  675   	}
  676   
  677   	public boolean isXMLElement() {
  678   		return true;
  679   	}
  680   
  681   	public Object fromXMLNode(Node xml, Mapping factory) throws HibernateException {
  682   		return xml;
  683   	}
  684   
  685   	public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) 
  686   	throws HibernateException {
  687   		if ( !isEmbeddedInXML ) {
  688   			node.detach();
  689   		}
  690   		else {
  691   			replaceNode( node, (Element) value );
  692   		}
  693   	}
  694   	
  695   	/**
  696   	 * We always need to dirty check the collection because we sometimes 
  697   	 * need to incremement version number of owner and also because of 
  698   	 * how assemble/disassemble is implemented for uks
  699   	 */
  700   	public boolean isAlwaysDirtyChecked() {
  701   		return true; 
  702   	}
  703   
  704   	public boolean[] toColumnNullness(Object value, Mapping mapping) {
  705   		return ArrayHelper.EMPTY_BOOLEAN_ARRAY;
  706   	}
  707   }

Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » type » [javadoc | source]