/**
   * INTERNAL: Return the value of the field from the row or a value holder on the query to obtain
   * the object. Check for batch + aggregation reading.
   */
  public Object valueFromRow(
      AbstractRecord row,
      JoinedAttributeManager joinManager,
      ObjectBuildingQuery query,
      AbstractSession executionSession)
      throws DatabaseException {
    Ref ref = (Ref) row.get(getField());

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

    Struct struct;
    try {
      ((DatabaseAccessor) executionSession.getAccessor()).incrementCallCount(executionSession);
      java.sql.Connection connection =
          ((DatabaseAccessor) executionSession.getAccessor()).getConnection();
      struct =
          (Struct) executionSession.getPlatform().getRefValue(ref, executionSession, connection);
    } catch (java.sql.SQLException exception) {
      throw DatabaseException.sqlException(exception, executionSession, false);
    }
    AbstractRecord targetRow =
        ((ObjectRelationalDataTypeDescriptor) getReferenceDescriptor())
            .buildRowFromStructure(struct);
    ((DatabaseAccessor) executionSession.getAccessor()).decrementCallCount();

    return getReferenceDescriptor().getObjectBuilder().buildObject(query, targetRow, joinManager);
  }
  /** Delete all of the objects with the matching class. */
  public void deleteAllObjects(Class theClass, List objects, AbstractSession session) {
    ClassDescriptor descriptor = null;

    if (((UnitOfWorkImpl) session).shouldOrderUpdates()) { // bug 331064 - Sort the delete order
      objects = sort(theClass, objects);
    }

    int size = objects.size();
    for (int index = 0; index < size; index++) {
      Object objectToDelete = objects.get(index);
      if (objectToDelete.getClass() == theClass) {
        if (descriptor == null) {
          descriptor = session.getDescriptor(theClass);
        }
        // PERF: Get the descriptor query, to avoid extra query creation.
        DeleteObjectQuery deleteQuery = descriptor.getQueryManager().getDeleteQuery();
        if (deleteQuery == null) {
          deleteQuery = new DeleteObjectQuery();
          deleteQuery.setDescriptor(descriptor);
        } else {
          // Ensure original query has been prepared.
          deleteQuery.checkPrepare(session, deleteQuery.getTranslationRow());
          deleteQuery = (DeleteObjectQuery) deleteQuery.clone();
        }
        deleteQuery.setIsExecutionClone(true);
        deleteQuery.setObject(objectToDelete);
        session.executeQuery(deleteQuery);
      }
    }
  }
  /**
   * delete all of the objects as a single transaction. This should delete the object in the correct
   * order to maintain referential integrity.
   */
  public void deleteAllObjects(List objects)
      throws RuntimeException, DatabaseException, OptimisticLockException {
    this.isActive = true;
    AbstractSession session = getSession();
    session.beginTransaction();

    try {
      // PERF: Optimize single object case.
      if (objects.size() == 1) {
        deleteAllObjects(objects.get(0).getClass(), objects, session);
      } else {
        List commitOrder = getCommitOrder();
        for (int orderIndex = commitOrder.size() - 1; orderIndex >= 0; orderIndex--) {
          Class theClass = (Class) commitOrder.get(orderIndex);
          deleteAllObjects(theClass, objects, session);
        }
      }

      session.commitTransaction();
    } catch (RuntimeException exception) {
      try {
        session.rollbackTransaction();
      } catch (Exception ignore) {
      }
      throw exception;
    } finally {
      reinitialize();
      this.isActive = false;
    }
  }
 /**
  * Commit all of the objects of the class type in the change set. This allows for the order of the
  * classes to be processed optimally.
  */
 protected void commitNewObjectsForClassWithChangeSet(
     UnitOfWorkChangeSet uowChangeSet, Class theClass) {
   Map<ObjectChangeSet, ObjectChangeSet> newObjectChangesList =
       uowChangeSet.getNewObjectChangeSets().get(theClass);
   if (newObjectChangesList != null) { // may be no changes for that class type.
     AbstractSession session = getSession();
     ClassDescriptor descriptor = session.getDescriptor(theClass);
     List<ObjectChangeSet> newChangeSets = new ArrayList(newObjectChangesList.values());
     int size = newChangeSets.size();
     for (int index = 0; index < size; index++) {
       ObjectChangeSet changeSetToWrite = newChangeSets.get(index);
       Object objectToWrite = changeSetToWrite.getUnitOfWorkClone();
       if (!isProcessedCommit(objectToWrite)) {
         // PERF: Get the descriptor query, to avoid extra query creation.
         InsertObjectQuery commitQuery = descriptor.getQueryManager().getInsertQuery();
         if (commitQuery == null) {
           commitQuery = new InsertObjectQuery();
           commitQuery.setDescriptor(descriptor);
         } else {
           // Ensure original query has been prepared.
           commitQuery.checkPrepare(session, commitQuery.getTranslationRow());
           commitQuery = (InsertObjectQuery) commitQuery.clone();
         }
         commitQuery.setIsExecutionClone(true);
         commitQuery.setObjectChangeSet(changeSetToWrite);
         commitQuery.setObject(objectToWrite);
         commitQuery.cascadeOnlyDependentParts();
         commitQuery.setModifyRow(null);
         session.executeQuery(commitQuery);
       }
       uowChangeSet.putNewObjectInChangesList(changeSetToWrite, session);
     }
   }
 }
 /**
  * Commit changed of the objects of the class type in the change set. This allows for the order of
  * the classes to be processed optimally.
  */
 protected void commitChangedObjectsForClassWithChangeSet(
     UnitOfWorkChangeSet uowChangeSet, Class theClass) {
   Map<ObjectChangeSet, ObjectChangeSet> objectChangesList =
       uowChangeSet.getObjectChanges().get(theClass);
   if (objectChangesList != null) { // may be no changes for that class type.		
     ClassDescriptor descriptor = null;
     AbstractSession session = getSession();
     Collection<ObjectChangeSet> changes = objectChangesList.values();
     if (((UnitOfWorkImpl) session).shouldOrderUpdates()) {
       changes = new ArrayList(objectChangesList.values());
       Collections.sort((List) changes);
     }
     for (ObjectChangeSet changeSetToWrite : changes) {
       Object objectToWrite = changeSetToWrite.getUnitOfWorkClone();
       if (descriptor == null) {
         descriptor = session.getDescriptor(objectToWrite);
       }
       if (!isProcessedCommit(objectToWrite)) {
         // Commit and resume on failure can cause a new change set to be in existing, so need to
         // check here.
         WriteObjectQuery commitQuery = null;
         if (changeSetToWrite.isNew()) {
           commitQuery = new InsertObjectQuery();
         } else {
           commitQuery = new UpdateObjectQuery();
         }
         commitQuery.setIsExecutionClone(true);
         commitQuery.setDescriptor(descriptor);
         commitQuery.setObjectChangeSet(changeSetToWrite);
         commitQuery.setObject(objectToWrite);
         commitQuery.cascadeOnlyDependentParts();
         // removed checking session type to set cascade level
         // will always be a unitOfWork so we need to cascade dependent parts
         session.executeQuery(commitQuery);
       }
     }
   }
 }
 // bug 331064 - Sort the delete order based on PKs.
 private List sort(Class theClass, List objects) {
   ClassDescriptor descriptor = session.getDescriptor(theClass);
   org.eclipse.persistence.internal.descriptors.ObjectBuilder objectBuilder =
       descriptor.getObjectBuilder();
   int size = objects.size();
   TreeMap sortedObjects = new TreeMap();
   for (int index = 0; index < size; index++) {
     Object objectToDelete = objects.get(index);
     if (objectToDelete.getClass() == theClass) {
       sortedObjects.put(
           objectBuilder.extractPrimaryKeyFromObject(objectToDelete, session), objectToDelete);
     }
   }
   return new ArrayList(sortedObjects.values());
 }
  /** INTERNAL: Initialize the mapping. */
  public void initialize(AbstractSession session) throws DescriptorException {
    setReferenceDescriptor(session.getDescriptor(getReferenceClass()));

    if (referenceDescriptor == null) {
      throw DescriptorException.descriptorIsMissing(getReferenceClass().getName(), this);
    }

    // For bug 2730536 convert the field to be an ObjectRelationalDatabaseField.
    ObjectRelationalDatabaseField field = (ObjectRelationalDatabaseField) getField();
    field.setSqlType(java.sql.Types.REF);
    if (referenceDescriptor instanceof ObjectRelationalDataTypeDescriptor) {
      field.setSqlTypeName(
          ((ObjectRelationalDataTypeDescriptor) referenceDescriptor).getStructureName());
    }

    setField(getDescriptor().buildField(getField()));
    setFields(collectFields());

    // Ref mapping requires native connection in WLS as the Ref is wrapped.
    getDescriptor().setIsNativeConnectionRequired(true);
  }