/**
   * INTERNAL: This method is used when computing the nested queries for batch read mappings. It
   * recurses computing the nested mapping queries.
   */
  protected void computeNestedQueriesForBatchReadExpressions(Vector batchReadExpressions) {
    for (int index = 0; index < batchReadExpressions.size(); index++) {
      ObjectExpression objectExpression = (ObjectExpression) batchReadExpressions.get(index);

      // Expression may not have been initialized.
      ExpressionBuilder builder = objectExpression.getBuilder();
      builder.setSession(getSession().getRootSession(null));
      builder.setQueryClass(getReferenceClass());

      // PERF: Cache join attribute names.
      ObjectExpression baseExpression = objectExpression;
      while (!baseExpression.getBaseExpression().isExpressionBuilder()) {
        baseExpression = (ObjectExpression) baseExpression.getBaseExpression();
      }
      this.batchReadAttributes.add(baseExpression.getName());

      // Ignore nested
      if (objectExpression.getBaseExpression().isExpressionBuilder()) {
        DatabaseMapping mapping = objectExpression.getMapping();
        if ((mapping != null) && mapping.isForeignReferenceMapping()) {
          // A nested query must be built to pass to the descriptor that looks like the real query
          // execution would.
          ReadQuery nestedQuery = ((ForeignReferenceMapping) mapping).prepareNestedBatchQuery(this);
          // Register the nested query to be used by the mapping for all the objects.
          getBatchReadMappingQueries().put(mapping, nestedQuery);
        }
      }
    }
  }
 /**
  * INTERNAL: Execute the query building the objects directly from the database result-set.
  *
  * @exception DatabaseException - an error has occurred on the database
  * @return object - the first object found or null if none.
  */
 protected Object executeObjectLevelReadQueryFromResultSet() throws DatabaseException {
   UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl) getSession();
   DatabaseAccessor accessor = (DatabaseAccessor) unitOfWork.getAccessor();
   DatabasePlatform platform = accessor.getPlatform();
   DatabaseCall call = (DatabaseCall) getCall().clone();
   call.setQuery(this);
   call.translate(this.translationRow, null, unitOfWork);
   Statement statement = null;
   ResultSet resultSet = null;
   boolean exceptionOccured = false;
   try {
     accessor.incrementCallCount(unitOfWork);
     statement = call.prepareStatement(accessor, this.translationRow, unitOfWork);
     resultSet = accessor.executeSelect(call, statement, unitOfWork);
     ResultSetMetaData metaData = resultSet.getMetaData();
     Vector results = new Vector();
     ObjectBuilder builder = this.descriptor.getObjectBuilder();
     while (resultSet.next()) {
       results.add(
           builder.buildWorkingCopyCloneFromResultSet(
               this,
               this.joinedAttributeManager,
               resultSet,
               unitOfWork,
               accessor,
               metaData,
               platform));
     }
     return results;
   } catch (SQLException exception) {
     exceptionOccured = true;
     DatabaseException commException =
         accessor.processExceptionForCommError(session, exception, call);
     if (commException != null) throw commException;
     throw DatabaseException.sqlException(exception, call, accessor, unitOfWork, false);
   } finally {
     try {
       if (resultSet != null) {
         resultSet.close();
       }
       if (statement != null) {
         accessor.releaseStatement(statement, call.getSQLString(), call, unitOfWork);
       }
     } catch (SQLException exception) {
       if (!exceptionOccured) {
         // in the case of an external connection pool the connection may be null after the
         // statement release
         // if it is null we will be unable to check the connection for a comm error and
         // therefore must return as if it was not a comm error.
         DatabaseException commException =
             accessor.processExceptionForCommError(session, exception, call);
         if (commException != null) throw commException;
         throw DatabaseException.sqlException(exception, call, accessor, session, false);
       }
     }
   }
 }
 /** INTERNAL: Return if the attribute is specified for batch reading. */
 public boolean isAttributeBatchRead(String attributeName) {
   if (!hasBatchReadAttributes()) {
     return false;
   }
   Vector batchReadAttributeExpressions = getBatchReadAttributeExpressions();
   int size = batchReadAttributeExpressions.size();
   for (int index = 0; index < size; index++) {
     QueryKeyExpression expression = (QueryKeyExpression) batchReadAttributeExpressions.get(index);
     while (!expression.getBaseExpression().isExpressionBuilder()) {
       expression = (QueryKeyExpression) expression.getBaseExpression();
     }
     if (expression.getName().equals(attributeName)) {
       return true;
     }
   }
   return false;
 }
  /** Retrieve next page size of objects from the remote cursored stream */
  public Vector cursoredStreamNextPage(
      RemoteCursoredStream remoteCursoredStream,
      ReadQuery query,
      DistributedSession session,
      int pageSize) {
    Transporter transporter = null;
    try {
      transporter =
          getRemoteSessionController()
              .cursoredStreamNextPage(new Transporter(remoteCursoredStream.getID()), pageSize);
    } catch (RemoteException exception) {
      throw CommunicationException.errorInInvocation(exception);
    }

    if (transporter == null) {
      return null;
    }

    if (!transporter.wasOperationSuccessful()) {
      throw transporter.getException();
    }

    Vector serverNextPageObjects = (Vector) transporter.getObject();
    if (serverNextPageObjects == null) {
      cursoredStreamClose(remoteCursoredStream.getID());
      return null;
    }
    Vector clientNextPageObjects = serverNextPageObjects;
    if (query.isReadAllQuery() && (!query.isReportQuery())) { // could be DataReadQuery
      clientNextPageObjects = new Vector(serverNextPageObjects.size());
      for (Enumeration objEnum = serverNextPageObjects.elements(); objEnum.hasMoreElements(); ) {
        // 2612538 - the default size of Map (32) is appropriate
        Object clientObject =
            session.getObjectCorrespondingTo(
                objEnum.nextElement(),
                transporter.getObjectDescriptors(),
                new IdentityHashMap(),
                (ObjectLevelReadQuery) query);
        clientNextPageObjects.addElement(clientObject);
      }
    }

    return clientNextPageObjects;
  }
 /** INTERNAL: Return true is this query has batching */
 public boolean hasBatchReadAttributes() {
   return (batchReadAttributeExpressions != null) && (!batchReadAttributeExpressions.isEmpty());
 }
  /** 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;
    }
  }