/**
  * PUBLIC: Configure the query to use an instance of the specified container class to hold the
  * result objects. The key used to index the value in the Map is the value returned by a call to
  * the specified zero-argument method. The method must be implemented by the class (or a
  * superclass) of the value to be inserted into the Map.
  *
  * <p>jdk1.2.x: The container class must implement (directly or indirectly) the Map interface.
  *
  * <p>jdk1.1.x: The container class must be a subclass of Hashtable.
  *
  * <p>The referenceClass must set before calling this method.
  */
 public void useMapClass(Class concreteClass, String methodName) {
   // the reference class has to be specified before coming here
   if (getReferenceClass() == null) {
     throw QueryException.referenceClassMissing(this);
   }
   ContainerPolicy policy = ContainerPolicy.buildPolicyFor(concreteClass);
   policy.setKeyName(methodName, getReferenceClass().getName());
   setContainerPolicy(policy);
 }
 /**
  * INTERNAL: Execute the query. If there are cached results return those. This must override the
  * super to support result caching.
  *
  * @param session - the session in which the receiver will be executed.
  * @return An object or vector, the result of executing the query.
  * @exception DatabaseException - an error has occurred on the database
  */
 public Object execute(AbstractSession session, AbstractRecord row) throws DatabaseException {
   if (shouldCacheQueryResults()) {
     if (getContainerPolicy().overridesRead()) {
       throw QueryException.cannotCacheCursorResultsOnQuery(this);
     }
     if (shouldConformResultsInUnitOfWork()) {
       throw QueryException.cannotConformAndCacheQueryResults(this);
     }
     if (isPrepared()) { // only prepared queries can have cached results.
       Object queryResults = getQueryResults(session, row, true);
       if (queryResults != null) {
         if (QueryMonitor.shouldMonitor()) {
           QueryMonitor.incrementReadAllHits(this);
         }
         // bug6138532 - check for "cached no results" (InvalidObject singleton) in query
         // results, and return an empty container instance as configured
         if (queryResults == InvalidObject.instance) {
           return getContainerPolicy().containerInstance(0);
         }
         Collection results = (Collection) queryResults;
         if (session.isUnitOfWork()) {
           ContainerPolicy policy = getContainerPolicy();
           Object resultCollection = policy.containerInstance(results.size());
           Object iterator = policy.iteratorFor(results);
           while (policy.hasNext(iterator)) {
             Object result =
                 ((UnitOfWorkImpl) session)
                     .registerExistingObject(policy.next(iterator, session), this.descriptor);
             policy.addInto(result, resultCollection, session);
           }
           return resultCollection;
         }
         return results;
       }
     }
   }
   if (QueryMonitor.shouldMonitor()) {
     QueryMonitor.incrementReadAllMisses(this);
   }
   return super.execute(session, row);
 }
 /**
  * PUBLIC: Specify the foreign-reference mapped attribute to be optimized in this query. The query
  * will execute normally, however when any of the batched parts is accessed, the parts will all be
  * read in a single query, this allows all of the data required for the parts to be read in a
  * single query instead of (n) queries. This should be used when the application knows that it
  * requires the part for all of the objects being read. This can be used for one-to-one,
  * one-to-many, many-to-many and direct collection mappings.
  *
  * <p>The use of the expression allows for nested batch reading to be expressed.
  *
  * <p>Example: query.addBatchReadAttribute("phoneNumbers")
  *
  * @see #addBatchReadAttribute(Expression)
  * @see ObjectLevelReadQuery#addJoinedAttribute(String)
  */
 public void addBatchReadAttribute(String attributeName) {
   if (!getQueryMechanism().isExpressionQueryMechanism()) {
     throw QueryException.batchReadingNotSupported(this);
   }
   getBatchReadAttributeExpressions().add(getExpressionBuilder().get(attributeName));
 }