Open Source Repository

Home /hibernate/hibernate-3.2.4.ga | Repository Home


org/hibernate/engine/loading/LoadContexts.java
package org.hibernate.engine.loading;

import java.sql.ResultSet;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;
import java.util.HashMap;
import java.io.Serializable;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.hibernate.util.IdentityMap;
import org.hibernate.engine.PersistenceContext;
import org.hibernate.engine.CollectionKey;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.EntityMode;

/**
 * Maps {@link ResultSet result-sets} to specific contextual data
 * related to processing that {@link ResultSet result-sets}.
 <p/>
 * Implementation note: internally an {@link IdentityMap} is used to maintain
 * the mappings; {@link IdentityMap} was chosen because I'd rather not be
 * dependent upon potentially bad {@link ResultSet#equals} and {ResultSet#hashCode}
 * implementations.
 <p/>
 * Considering the JDBC-redesign work, would further like this contextual info
 * not mapped seperately, but available based on the result set being processed.
 * This would also allow maintaining a single mapping as we could reliably get
 * notification of the result-set closing...
 *
 @author Steve Ebersole
 */
public class LoadContexts {
  private static final Log log = LogFactory.getLogLoadContexts.class );

  private final PersistenceContext persistenceContext;
  private Map collectionLoadContexts;
  private Map entityLoadContexts;

  private Map xrefLoadingCollectionEntries;

  /**
   * Creates and binds this to the given persistence context.
   *
   @param persistenceContext The persistence context to which this
   * will be bound.
   */
  public LoadContexts(PersistenceContext persistenceContext) {
    this.persistenceContext = persistenceContext;
  }

  /**
   * Retrieves the persistence context to which this is bound.
   *
   @return The persistence context to which this is bound.
   */
  public PersistenceContext getPersistenceContext() {
    return persistenceContext;
  }

  /**
   * Get the {@link CollectionLoadContext} associated with the given
   {@link ResultSet}, creating one if needed.
   *
   @param resultSet The result set for which to retrieve the context.
   @return The processing context.
   */
  public CollectionLoadContext getCollectionLoadContext(ResultSet resultSet) {
    CollectionLoadContext context = null;
    if collectionLoadContexts == null ) {
      collectionLoadContexts = IdentityMap.instantiate);
    }
    else {
      context = CollectionLoadContext collectionLoadContexts.getresultSet );
    }
    if context == null ) {
      if log.isTraceEnabled() ) {
        log.trace"constructing collection load context for result set [" + resultSet + "]" );
      }
      context = new CollectionLoadContextthis, resultSet );
      collectionLoadContexts.putresultSet, context );
    }
    return context;
  }

  /**
   * Attempt to locate the loading collection given the owner's key.  The lookup here
   * occurs against all result-set contexts...
   *
   @param persister The collection persister
   @param ownerKey The owner key
   @return The loading collection, or null if not found.
   */
  public PersistentCollection locateLoadingCollection(CollectionPersister persister, Serializable ownerKey) {
    LoadingCollectionEntry lce = locateLoadingCollectionEntrynew CollectionKeypersister, ownerKey, getEntityMode() ) );
    if lce != null ) {
      if log.isTraceEnabled() ) {
        log.trace"returning loading collection:" + MessageHelper.collectionInfoStringpersister, ownerKey, getSession().getFactory() ) );
      }
      return lce.getCollection();
    }
    else {
      // todo : should really move this log statement to CollectionType, where this is used from...
      if log.isTraceEnabled() ) {
        log.trace"creating collection wrapper:" + MessageHelper.collectionInfoStringpersister, ownerKey, getSession().getFactory() ) );
      }
      return null;
    }
  }

  /**
   * Locate the LoadingCollectionEntry within *any* of the tracked
   {@link CollectionLoadContext}s.
   <p/>
   * Implementation note: package protected, as this is meant solely for use
   * by {@link CollectionLoadContext} to be able to locate collections
   * being loaded by other {@link CollectionLoadContext}s/{@link ResultSet}s.
   *
   @param key The collection key.
   @return The located entry; or null.
   */
  LoadingCollectionEntry locateLoadingCollectionEntry(CollectionKey key) {
    if xrefLoadingCollectionEntries == null ) {
      return null;
    }
    if log.isTraceEnabled() ) {
      log.trace"attempting to locate loading collection entry [" + key + "] in any result-set context" );
    }
    LoadingCollectionEntry rtn = LoadingCollectionEntry xrefLoadingCollectionEntries.getkey );
    if log.isTraceEnabled() ) {
      if rtn == null ) {
        log.trace"collection [" + key + "] located in load context" );
      }
      else {
        log.trace"collection [" + key + "] not located in load context" );
      }
    }
    return rtn;
  }

  /*package*/void registerLoadingCollectionEntry(CollectionKey entryKey, LoadingCollectionEntry entry) {
    if xrefLoadingCollectionEntries == null ) {
      xrefLoadingCollectionEntries = new HashMap();
    }
    xrefLoadingCollectionEntries.putentryKey, entry );
  }

  /*package*/Map getLoadingCollectionEntryMap() {
    return xrefLoadingCollectionEntries;
  }

  /*package*/void cleanupCollectionEntries(Set entryKeys) {
    Iterator itr = entryKeys.iterator();
    while itr.hasNext() ) {
      final CollectionKey entryKey = CollectionKey itr.next();
      xrefLoadingCollectionEntries.removeentryKey );
    }
  }

  public EntityLoadContext getEntityLoadContext(ResultSet resultSet) {
    EntityLoadContext context = null;
    if entityLoadContexts == null ) {
      entityLoadContexts = IdentityMap.instantiate);
    }
    else {
      context = EntityLoadContext entityLoadContexts.getresultSet );
    }
    if context == null ) {
      context = new EntityLoadContextthis, resultSet );
      entityLoadContexts.putresultSet, context );
    }
    return context;
  }

  public void cleanup(ResultSet resultSet) {
    if collectionLoadContexts != null ) {
      CollectionLoadContext collectionLoadContext = CollectionLoadContext collectionLoadContexts.removeresultSet );
      collectionLoadContext.cleanup();
    }
    if entityLoadContexts != null ) {
      EntityLoadContext entityLoadContext = EntityLoadContext entityLoadContexts.removeresultSet );
      entityLoadContext.cleanup();
    }
  }

  private SessionImplementor getSession() {
    return getPersistenceContext().getSession();
  }

  private EntityMode getEntityMode() {
    return getSession().getEntityMode();
  }

}