/**
  * 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. Get the rows and build the object from the rows.
   *
   * @exception DatabaseException - an error has occurred on the database
   * @return java.lang.Object collection of objects resulting from execution of query.
   */
  protected Object executeObjectLevelReadQuery() throws DatabaseException {
    Object result = null;

    if (getContainerPolicy().overridesRead()) {
      return getContainerPolicy().execute();
    }

    if (this.descriptor.isDescriptorForInterface()) {
      Object returnValue =
          this.descriptor.getInterfacePolicy().selectAllObjectsUsingMultipleTableSubclassRead(this);
      setExecutionTime(System.currentTimeMillis());
      return returnValue;
    }

    List rows = getQueryMechanism().selectAllRows();
    setExecutionTime(System.currentTimeMillis());

    // If using 1-m joins, must set all rows.
    if (hasJoining() && this.joinedAttributeManager.isToManyJoin()) {
      this.joinedAttributeManager.setDataResults(rows, this.session);
    }

    if (this.session.isUnitOfWork()) {
      result =
          registerResultInUnitOfWork(
              rows, (UnitOfWorkImpl) this.session, this.translationRow, true); //
    } else {
      result = getContainerPolicy().containerInstance(rows.size());
      this.descriptor.getObjectBuilder().buildObjectsInto(this, rows, result);
    }

    if (this.shouldIncludeData) {
      ComplexQueryResult complexResult = new ComplexQueryResult();
      complexResult.setResult(result);
      complexResult.setData(rows);
      return complexResult;
    }

    // Add the other (already registered) results and return them.
    if (getDescriptor().hasTablePerClassPolicy()) {
      result =
          containerPolicy.concatenateContainers(
              result,
              getDescriptor()
                  .getTablePerClassPolicy()
                  .selectAllObjectsUsingMultipleTableSubclassRead(this));
    }

    return result;
  }
 /**
  * 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: Configure the mapping to use an instance of the specified container class to hold the
  * target objects.
  *
  * <p>jdk1.2.x: The container class must implement (directly or indirectly) the Collection
  * interface.
  *
  * <p>jdk1.1.x: The container class must be a subclass of Vector.
  */
 public void useCollectionClass(Class concreteClass) {
   // Set container policy.
   setContainerPolicy(ContainerPolicy.buildPolicyFor(concreteClass));
 }
  /**
   * INTERNAL: All objects queried via a UnitOfWork get registered here. If the query went to the
   * database.
   *
   * <p>Involves registering the query result individually and in totality, and hence refreshing /
   * conforming is done here.
   *
   * @param result may be collection (read all) or an object (read one), or even a cursor. If in
   *     transaction the shared cache will be bypassed, meaning the result may not be originals from
   *     the parent but raw database rows.
   * @param unitOfWork the unitOfWork the result is being registered in.
   * @param arguments the original arguments/parameters passed to the query execution. Used by
   *     conforming
   * @param buildDirectlyFromRows If in transaction must construct a registered result from raw
   *     database rows.
   * @return the final (conformed, refreshed, wrapped) UnitOfWork query result
   */
  public Object registerResultInUnitOfWork(
      Object result,
      UnitOfWorkImpl unitOfWork,
      AbstractRecord arguments,
      boolean buildDirectlyFromRows) {
    // For bug 2612366: Conforming results in UOW extremely slow.
    // Replacing results with registered versions in the UOW is a part of
    // conforming and is now done while conforming to maximize performance.
    if (shouldConformResultsInUnitOfWork()
        || this.descriptor.shouldAlwaysConformResultsInUnitOfWork()) {
      return conformResult(result, unitOfWork, arguments, buildDirectlyFromRows);
    }

    // When building directly from rows, one of the performance benefits
    // is that we no longer have to wrap and then unwrap the originals.
    // result is just a vector, not a collection of wrapped originals.
    // Also for cursors the initial connection is automatically registered.
    if (buildDirectlyFromRows) {
      List<AbstractRecord> rows = (List<AbstractRecord>) result;
      ContainerPolicy cp = getContainerPolicy();
      int size = rows.size();
      Object clones = cp.containerInstance(size);
      for (int index = 0; index < size; index++) {
        AbstractRecord row = rows.get(index);

        // null is placed in the row collection for 1-m joining to filter duplicate rows.
        if (row != null) {
          Object clone = buildObject(row);
          cp.addInto(clone, clones, unitOfWork, row, this);
        }
      }
      return clones;
    }

    ContainerPolicy cp;
    Cursor cursor = null;

    // If the query is redirected then the collection returned might no longer
    // correspond to the original container policy.  CR#2342-S.M.
    if (getRedirector() != null) {
      cp = ContainerPolicy.buildPolicyFor(result.getClass());
    } else {
      cp = getContainerPolicy();
    }

    // In the case of cursors just register the initially read collection.
    if (cp.isCursorPolicy()) {
      cursor = (Cursor) result;
      // In nested UnitOfWork session might have been session of the parent.
      cursor.setSession(unitOfWork);
      cp = ContainerPolicy.buildPolicyFor(ClassConstants.Vector_class);
      result = cursor.getObjectCollection();
    }

    Object clones = cp.containerInstance(cp.sizeFor(result));
    AbstractSession sessionToUse = unitOfWork.getParent();
    for (Object iter = cp.iteratorFor(result); cp.hasNext(iter); ) {
      Object object = cp.next(iter, sessionToUse);
      Object clone = registerIndividualResult(object, unitOfWork, this.joinedAttributeManager);
      cp.addInto(clone, clones, unitOfWork);
    }
    if (cursor != null) {
      cursor.setObjectCollection((Vector) clones);
      return cursor;
    } else {
      return clones;
    }
  }
 /**
  * PUBLIC: Return a new read all query. A reference class must be specified before execution. It
  * is better to provide the class and expression builder on construction to ensure a single
  * expression builder is used. If no selection criteria is specified this will read all objects of
  * the class from the database.
  */
 public ReadAllQuery() {
   super();
   setContainerPolicy(ContainerPolicy.buildDefaultPolicy());
 }
  /** INTERNAL: Conform the result if specified. */
  protected Object conformResult(
      Object result,
      UnitOfWorkImpl unitOfWork,
      AbstractRecord arguments,
      boolean buildDirectlyFromRows) {
    if (getSelectionCriteria() != null) {
      ExpressionBuilder builder = getSelectionCriteria().getBuilder();
      builder.setSession(unitOfWork.getRootSession(null));
      builder.setQueryClass(getReferenceClass());
    }

    // If the query is redirected then the collection returned might no longer
    // correspond to the original container policy.  CR#2342-S.M.
    ContainerPolicy cp;
    if (getRedirector() != null) {
      cp = ContainerPolicy.buildPolicyFor(result.getClass());
    } else {
      cp = getContainerPolicy();
    }

    // This code is now a great deal different...  For one, registration is done
    // as part of conforming.  Also, this should only be called if one actually
    // is conforming.
    // First scan the UnitOfWork for conforming instances.
    // This will walk through the entire cache of registered objects.
    // Let p be objects from result not in the cache.
    // Let c be objects from cache.
    // Presently p intersect c = empty set, but later p subset c.
    // By checking cache now doesConform will be called p fewer times.
    Map indexedInterimResult =
        unitOfWork.scanForConformingInstances(
            getSelectionCriteria(), getReferenceClass(), arguments, this);

    Cursor cursor = null;
    // In the case of cursors just conform/register the initially read collection.
    if (cp.isCursorPolicy()) {
      cursor = (Cursor) result;
      cp = ContainerPolicy.buildPolicyFor(ClassConstants.Vector_class);
      // In nested UnitOfWork session might have been session of the parent.
      cursor.setSession(unitOfWork);
      result = cursor.getObjectCollection();
      // for later incremental conforming...
      cursor.setInitiallyConformingIndex(indexedInterimResult);
      cursor.setSelectionCriteriaClone(getSelectionCriteria());
      cursor.setTranslationRow(arguments);
    }

    // Now conform the result from the database.
    // Remove any deleted or changed objects that no longer conform.
    // Deletes will only work for simple queries, queries with or's or anyof's may not return
    // correct results when untriggered indirection is in the model.
    Vector fromDatabase = null;

    // When building directly from rows, one of the performance benefits
    // is that we no longer have to wrap and then unwrap the originals.
    // result is just a vector, not a container of wrapped originals.
    if (buildDirectlyFromRows) {
      Vector rows = (Vector) result;
      fromDatabase = new Vector(rows.size());
      for (int i = 0; i < rows.size(); i++) {
        Object object = rows.elementAt(i);
        // null is placed in the row collection for 1-m joining to filter duplicate rows.
        if (object != null) {
          Object clone =
              conformIndividualResult(
                  object,
                  unitOfWork,
                  arguments,
                  getSelectionCriteria(),
                  indexedInterimResult,
                  buildDirectlyFromRows);
          if (clone != null) {
            fromDatabase.addElement(clone);
          }
        }
      }
    } else {
      fromDatabase = new Vector(cp.sizeFor(result));
      AbstractSession sessionToUse = unitOfWork.getParent();
      for (Object iter = cp.iteratorFor(result); cp.hasNext(iter); ) {
        Object object = cp.next(iter, sessionToUse);
        Object clone =
            conformIndividualResult(
                object,
                unitOfWork,
                arguments,
                getSelectionCriteria(),
                indexedInterimResult,
                buildDirectlyFromRows);
        if (clone != null) {
          fromDatabase.addElement(clone);
        }
      }
    }

    // Now add the unwrapped conforming instances into an appropriate container.
    // Wrapping is done automatically.
    // Make sure a vector of exactly the right size is returned.
    Object conformedResult =
        cp.containerInstance(indexedInterimResult.size() + fromDatabase.size());
    Object eachClone;
    for (Iterator enumtr = indexedInterimResult.values().iterator(); enumtr.hasNext(); ) {
      eachClone = enumtr.next();
      cp.addInto(eachClone, conformedResult, unitOfWork);
    }
    for (Enumeration enumtr = fromDatabase.elements(); enumtr.hasMoreElements(); ) {
      eachClone = enumtr.nextElement();
      cp.addInto(eachClone, conformedResult, unitOfWork);
    }

    if (cursor != null) {
      cursor.setObjectCollection((Vector) conformedResult);

      // For nested UOW must copy all in object collection to
      // initiallyConformingIndex, as some of these could have been from
      // the parent UnitOfWork.
      if (unitOfWork.isNestedUnitOfWork()) {
        for (Enumeration enumtr = cursor.getObjectCollection().elements();
            enumtr.hasMoreElements(); ) {
          Object clone = enumtr.nextElement();
          indexedInterimResult.put(clone, clone);
        }
      }
      return cursor;
    } else {
      return conformedResult;
    }
  }