/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2021 IBM Corporation. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     07/16/2009-2.0 Guy Pelletier
//       - 277039: JPA 2.0 Cache Usage Settings
//     04/01/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 2)
//     09/09/2011-2.3.1 Guy Pelletier
//       - 356197: Add new VPD type to MultitenantType
//     11/10/2011-2.4 Guy Pelletier
//       - 357474: Address primaryKey option from tenant discriminator column
//     01/15/2016-2.7 Mythily Parthasarathy
//       - 485984: Retrieve FetchGroup info along with getReference() from cache
//     08/07/2016-2.7 Dalia Abo Sheasha
//       - 499335: Multiple embeddable fields can't reference same object
//     02/20/2018-2.7 Will Dazey
//       - 529602: Added support for CLOBs in DELETE statements for Oracle
package org.eclipse.persistence.internal.descriptors;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.Semaphore;

import org.eclipse.persistence.annotations.BatchFetchType;
import org.eclipse.persistence.annotations.CacheKeyType;
import org.eclipse.persistence.annotations.IdValidation;
import org.eclipse.persistence.descriptors.CachePolicy;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorEventManager;
import org.eclipse.persistence.descriptors.FetchGroupManager;
import org.eclipse.persistence.descriptors.InheritancePolicy;
import org.eclipse.persistence.descriptors.changetracking.ChangeTracker;
import org.eclipse.persistence.descriptors.changetracking.ObjectChangePolicy;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.internal.core.descriptors.CoreObjectBuilder;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform;
import org.eclipse.persistence.internal.databaseaccess.Platform;
import org.eclipse.persistence.internal.expressions.ObjectExpression;
import org.eclipse.persistence.internal.expressions.QueryKeyExpression;
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
import org.eclipse.persistence.internal.helper.ConcurrencySemaphore;
import org.eclipse.persistence.internal.helper.ConcurrencyUtil;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.IdentityHashSet;
import org.eclipse.persistence.internal.helper.InvalidObject;
import org.eclipse.persistence.internal.helper.ThreadCursoredList;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.indirection.ProxyIndirectionPolicy;
import org.eclipse.persistence.internal.queries.AttributeItem;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.queries.EntityFetchGroup;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.AggregateChangeRecord;
import org.eclipse.persistence.internal.sessions.AggregateObjectChangeSet;
import org.eclipse.persistence.internal.sessions.ArrayRecord;
import org.eclipse.persistence.internal.sessions.ChangeRecord;
import org.eclipse.persistence.internal.sessions.DirectToFieldChangeRecord;
import org.eclipse.persistence.internal.sessions.MergeManager;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.internal.sessions.ResultSetRecord;
import org.eclipse.persistence.internal.sessions.SimpleResultSetRecord;
import org.eclipse.persistence.internal.sessions.TransformationMappingChangeRecord;
import org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.AggregateObjectMapping;
import org.eclipse.persistence.mappings.ContainerMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DatabaseMapping.WriteType;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.mappings.foundation.AbstractColumnMapping;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
import org.eclipse.persistence.mappings.foundation.AbstractTransformationMapping;
import org.eclipse.persistence.mappings.querykeys.DirectQueryKey;
import org.eclipse.persistence.mappings.querykeys.QueryKey;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.queries.AttributeGroup;
import org.eclipse.persistence.queries.DataReadQuery;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.FetchGroupTracker;
import org.eclipse.persistence.queries.LoadGroup;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ObjectLevelModifyQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.QueryByExamplePolicy;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.WriteObjectQuery;
import org.eclipse.persistence.sessions.CopyGroup;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.sessions.remote.DistributedSession;

/**
 * <p><b>Purpose</b>: Object builder is one of the behavior class attached to descriptor.
 * It is responsible for building objects, rows, and extracting primary keys from
 * the object and the rows.
 *
 * @author Sati
 * @since TOPLink/Java 1.0
 */
public class ObjectBuilder extends CoreObjectBuilder<AbstractRecord, AbstractSession, DatabaseField, DatabaseMapping> implements Cloneable, Serializable {
    protected ClassDescriptor descriptor;
    /** Mappings keyed by attribute name. */
    protected Map<String, DatabaseMapping> mappingsByAttribute;
    /** Mappings keyed by database field. */
    protected Map<DatabaseField, DatabaseMapping> mappingsByField;
    /** List of read-only mappings using a database field. */
    protected Map<DatabaseField, List<DatabaseMapping>> readOnlyMappingsByField;
    /** Used to maintain identity on the field objects. Ensure they get the correct index/type. */
    protected Map<DatabaseField, DatabaseField> fieldsMap;
    /** Mapping for the primary key fields. */
    protected List<DatabaseMapping> primaryKeyMappings;
    /** The types for the primary key fields, in same order as descriptor's primary key fields. */
    protected List<Class> primaryKeyClassifications;
    /** All mapping other than primary key mappings. */
    protected transient List<DatabaseMapping> nonPrimaryKeyMappings;
    /** Expression for querying an object by primary key. */
    protected transient Expression primaryKeyExpression;
    /** PERF: Cache mapping that use joining. */
    protected List<DatabaseMapping> joinedAttributes;
    /** PERF: Cache mapping that use batch fetching. */
    protected List<DatabaseMapping> batchFetchedAttributes;
    /** PERF: Cache mapping that use batch fetching. */
    protected boolean hasInBatchFetchedAttribute;
    /** PERF: Cache mappings that require cloning. */
    protected List<DatabaseMapping> cloningMappings;
    /** PERF: Cache mappings that are eager loaded. */
    protected List<DatabaseMapping> eagerMappings;
    /** PERF: Cache relationship mappings. */
    protected List<DatabaseMapping> relationshipMappings;
    /** PERF: Cache if is a simple mapping, all direct. */
    protected boolean isSimple;
    /** PERF: Cache if has a wrapper policy. */
    protected boolean hasWrapperPolicy;
    /** PERF: Cache sequence mappings. */
    protected AbstractDirectMapping sequenceMapping;
    /** indicates whether part of primary key is unmapped - may happen only in case AggregateObject or AggregateCollection descriptor. */
    protected boolean mayHaveNullInPrimaryKey;
    /** attribute name corresponding to optimistic lock field, set only if optimistic locking is used */
    protected String lockAttribute;
    /** PERF: is there a mapping using indirection (could be nested in aggregate(s)), or any other reason to keep row after the object has been created.
     Used by ObjectLevelReadQuery ResultSetAccessOptimization. */
    protected boolean shouldKeepRow = false;
    /** PERF: is there an cache index field that's would not be selected by SOP query. Ignored unless descriptor uses SOP and CachePolicy has cache indexes. */
    protected boolean hasCacheIndexesInSopObject = false;
    /** Semaphore related properties. Transient to avoid serialization in clustered/replicated environments see CORBA tests*/
    private static final transient ThreadLocal<Boolean> SEMAPHORE_THREAD_LOCAL_VAR = new ThreadLocal<>();
    private static final transient int SEMAPHORE_MAX_NUMBER_THREADS = ConcurrencyUtil.SINGLETON.getNoOfThreadsAllowedToObjectBuildInParallel();
    private static final transient Semaphore SEMAPHORE_LIMIT_MAX_NUMBER_OF_THREADS_OBJECT_BUILDING = new Semaphore(SEMAPHORE_MAX_NUMBER_THREADS);
    private transient ConcurrencySemaphore objectBuilderSemaphore = new ConcurrencySemaphore(SEMAPHORE_THREAD_LOCAL_VAR, SEMAPHORE_MAX_NUMBER_THREADS, SEMAPHORE_LIMIT_MAX_NUMBER_OF_THREADS_OBJECT_BUILDING, this, "object_builder_semaphore_acquired_01");

    public ObjectBuilder(ClassDescriptor descriptor) {
        this.descriptor = descriptor;
        initialize(descriptor);
    }

    protected void initialize(ClassDescriptor descriptor) {
        this.mappingsByField = new HashMap(20);
        this.readOnlyMappingsByField = new HashMap(10);
        this.mappingsByAttribute = new HashMap(20);
        this.fieldsMap = new HashMap(20);
        this.primaryKeyMappings = new ArrayList(5);
        this.nonPrimaryKeyMappings = new ArrayList(10);
        this.cloningMappings = new ArrayList(10);
        this.eagerMappings = new ArrayList(5);
        this.relationshipMappings = new ArrayList(5);
    }

    /**
     * Create a new row/record for the object builder.
     * This allows subclasses to define different record types.
     */
    @Override
    public AbstractRecord createRecord(AbstractSession session) {
        return new DatabaseRecord();
    }

    /**
     * Create a new row/record for the object builder.
     * This allows subclasses to define different record types.
     */
    public AbstractRecord createRecord(int size, AbstractSession session) {
        return new DatabaseRecord(size);
    }

    /**
     * Create a new row/record for the object builder. This allows subclasses to
     * define different record types.  This will typically be called when a
     * record will be used for temporarily holding on to primary key fields.
     */
    protected AbstractRecord createRecordForPKExtraction(int size, AbstractSession session) {
        return createRecord(size, session);
    }

    /**
     * Add the primary key and its value to the Record for all the non default tables.
     * This method is used while writing into the multiple tables.
     */
    public void addPrimaryKeyForNonDefaultTable(AbstractRecord databaseRow) {
        // this method has been revised so it calls addPrimaryKeyForNonDefaultTable(AbstractRecord, Object, Session) is similar.
        // the session and object are null in this case.
        addPrimaryKeyForNonDefaultTable(databaseRow, null, null);
    }

    /**
     * Add the primary key and its value to the Record for all the non default tables.
     * This method is used while writing into the multiple tables.
     */
    public void addPrimaryKeyForNonDefaultTable(AbstractRecord databaseRow, Object object, AbstractSession session) {
        if (!this.descriptor.hasMultipleTables()) {
            return;
        }
        List<DatabaseTable> tables = this.descriptor.getTables();
        int size = tables.size();

        // Skip first table.
        for (int index = 1; index < size; index++) {
            DatabaseTable table = tables.get(index);
            Map<DatabaseField, DatabaseField> keyMapping = this.descriptor.getAdditionalTablePrimaryKeyFields().get(table);

            // Loop over the additionalTablePK fields and add the PK info for the table. The join might
            // be between a fk in the source table and pk in secondary table.
            if (keyMapping != null) {
                Iterator<DatabaseField> primaryKeyFieldEnum = keyMapping.keySet().iterator();
                Iterator<DatabaseField> secondaryKeyFieldEnum = keyMapping.values().iterator();
                while (primaryKeyFieldEnum.hasNext()) {
                    DatabaseField primaryKeyField = primaryKeyFieldEnum.next();
                    DatabaseField secondaryKeyField = secondaryKeyFieldEnum.next();
                    Object primaryValue = databaseRow.getIndicatingNoEntry(primaryKeyField);

                    // normally the primary key has a value, however if the multiple tables were joined by a foreign
                    // key the foreign key has a value.
                    if ((primaryValue == AbstractRecord.noEntry)) {
                        if (object != null) {
                            DatabaseMapping mapping = getMappingForField(secondaryKeyField);
                            if (mapping == null) {
                                throw DescriptorException.missingMappingForField(secondaryKeyField, this.descriptor);
                            }
                            mapping.writeFromObjectIntoRow(object, databaseRow, session, WriteType.UNDEFINED);
                        }
                        databaseRow.put(primaryKeyField, databaseRow.get(secondaryKeyField));
                    } else {
                        databaseRow.put(secondaryKeyField, primaryValue);
                    }
                }
            }
        }
    }

    /**
     * Clear any primary key cache data in the object.
     */
    public void clearPrimaryKey(Object object) {
        // PERF: If PersistenceEntity is caching the primary key this must be cleared as the primary key has changed.
        if (object instanceof PersistenceEntity) {
            ((PersistenceEntity)object)._persistence_setId(null);
        }
    }

    /**
     * Assign the fields in the row back into the object.
     * This is used by returning, as well as events and version locking.
     * If not null changeSet must correspond to object. changeSet is updated with all of the field values in the row.
     */
    public void assignReturnRow(Object object, AbstractSession writeSession, AbstractRecord row, ObjectChangeSet changeSet) throws DatabaseException {
        writeSession.log(SessionLog.FINEST, SessionLog.QUERY, "assign_return_row", row);

        // Require a query context to read into an object.
        ReadObjectQuery query = new ReadObjectQuery();
        query.setSession(writeSession);

        // To avoid processing the same mapping twice,
        // maintain Collection of mappings already used.
        HashSet handledMappings = null;
        int size = row.size();
        if (size > 1) {
            handledMappings = new HashSet(size);
        }
        List<DatabaseField> fields = row.getFields();
        for (int index = 0; index < size; index++) {
            DatabaseField field = fields.get(index);
            assignReturnValueForField(object, query, row, field, handledMappings, changeSet);
        }
    }

    /**
     * Assign the field value from the row to the object for all the mappings using field (read or write).
     * If not null changeSet must correspond to object. changeSet is updated with all of the field values in the row.
     */
    public void assignReturnValueForField(Object object, ReadObjectQuery query, AbstractRecord row, DatabaseField field, Collection handledMappings, ObjectChangeSet changeSet) {
        DatabaseMapping mapping = getMappingForField(field);
        if (mapping != null) {
            assignReturnValueToMapping(object,  query, row, field, mapping, handledMappings, changeSet);
        }
        List<DatabaseMapping> readOnlyMappings = getReadOnlyMappingsForField(field);
        if (readOnlyMappings != null) {
            int size = readOnlyMappings.size();
            for (int index = 0; index < size; index++) {
                mapping = readOnlyMappings.get(index);
                assignReturnValueToMapping(object, query, row, field, mapping, handledMappings, changeSet);
            }
        }
    }

    /**
     * INTERNAL:
     * Assign values from objectRow to the object through the mapping.
     * If not null changeSet must correspond to object. changeSet is updated with all of the field values in the row.
     */
    protected void assignReturnValueToMapping(Object object, ReadObjectQuery query, AbstractRecord row, DatabaseField field, DatabaseMapping mapping, Collection handledMappings, ObjectChangeSet changeSet) {
        if ((handledMappings != null) && handledMappings.contains(mapping)) {
            return;
        }
        if (mapping.isAbstractDirectMapping()) {
            if(changeSet != null && (!changeSet.isNew() || (query.getDescriptor() != null && query.getDescriptor().shouldUseFullChangeSetsForNewObjects()))) {
                DirectToFieldChangeRecord changeRecord = (DirectToFieldChangeRecord)changeSet.getChangesForAttributeNamed(mapping.getAttributeName());
                Object oldAttributeValue = null;
                if (changeRecord == null) {
                    oldAttributeValue = mapping.getAttributeValueFromObject(object);
                }

                //use null cachekey to ensure we build directly into the attribute
                Object attributeValue = mapping.readFromRowIntoObject(row, null, object, null, query, query.getSession(), true);

                if (changeRecord == null) {
                    // Don't use ObjectChangeSet.updateChangeRecordForAttributeWithMappedObject to avoid unnecessary conversion - attributeValue is already converted.
                    changeRecord = (DirectToFieldChangeRecord)((AbstractDirectMapping)mapping).internalBuildChangeRecord(attributeValue, oldAttributeValue, changeSet);
                    changeSet.addChange(changeRecord);
                } else {
                    changeRecord.setNewValue(attributeValue);
                }
            } else {
                mapping.readFromRowIntoObject(row, null, object, null, query, query.getSession(), true);
            }
        } else if (mapping.isAggregateObjectMapping()) {
            ((AggregateObjectMapping)mapping).readFromReturnRowIntoObject(row, object, query, handledMappings, changeSet);
        } else if (mapping.isTransformationMapping()) {
            ((AbstractTransformationMapping)mapping).readFromReturnRowIntoObject(row, object, query, handledMappings, changeSet);
        } else {
            query.getSession().log(SessionLog.FINEST, SessionLog.QUERY, "field_for_unsupported_mapping_returned", field, this.descriptor);
        }
    }

    /**
     * INTERNAL:
     * Update the object primary key by fetching a new sequence number from the accessor.
     * This assume the uses sequence numbers check has already been done.
     * @return the sequence value or null if not assigned.
     * @exception  DatabaseException - an error has occurred on the database.
     */
    public Object assignSequenceNumber(Object object, AbstractSession writeSession) throws DatabaseException {
        return assignSequenceNumber(object, writeSession, null);
    }

    /**
     * INTERNAL:
     * Update the writeQuery's object primary key by fetching a new sequence number from the accessor.
     * This assume the uses sequence numbers check has already been done.
     * Adds the assigned sequence value to writeQuery's modify row.
     * If object has a changeSet then sets sequence value into change set as an Id
     * adds it also to object's change set in a ChangeRecord if required.
     * @return the sequence value or null if not assigned.
     * @exception  DatabaseException - an error has occurred on the database.
     */
    public Object assignSequenceNumber(WriteObjectQuery writeQuery) throws DatabaseException {
        return assignSequenceNumber(writeQuery.getObject(), writeQuery.getSession(), writeQuery);
    }

    /**
     * INTERNAL:
     * Update the object primary key by fetching a new sequence number from the accessor.
     * This assume the uses sequence numbers check has already been done.
     * Adds the assigned sequence value to writeQuery's modify row.
     * If object has a changeSet then sets sequence value into change set as an Id
     * adds it also to object's change set in a ChangeRecord if required.
     * @return the sequence value or null if not assigned.
     * @exception  DatabaseException - an error has occurred on the database.
     */
    protected Object assignSequenceNumber(Object object, AbstractSession writeSession, WriteObjectQuery writeQuery) throws DatabaseException {
        DatabaseField sequenceNumberField = this.descriptor.getSequenceNumberField();
        Object existingValue = null;
        if (this.sequenceMapping != null) {
            existingValue = this.sequenceMapping.getAttributeValueFromObject(object);
        } else {
            existingValue = getBaseValueForField(sequenceNumberField, object);
        }

        // PERF: The (internal) support for letting the sequence decide this was removed,
        // as anything other than primitive should allow null and default as such.
        Object sequenceValue;
        int index = this.descriptor.getPrimaryKeyFields().indexOf(sequenceNumberField);
        if (isPrimaryKeyComponentInvalid(existingValue, index) || this.descriptor.getSequence().shouldAlwaysOverrideExistingValue()) {
            sequenceValue = writeSession.getSequencing().getNextValue(this.descriptor.getJavaClass());
        } else {
            return null;
        }

        // Check that the value is not null, this occurs on any databases using IDENTITY type sequencing.
        if (sequenceValue == null) {
            return null;
        }

        writeSession.log(SessionLog.FINEST, SessionLog.SEQUENCING, "assign_sequence", sequenceValue, object);
        Object convertedSequenceValue = null;
        if (this.sequenceMapping != null) {
            convertedSequenceValue = this.sequenceMapping.getObjectValue(sequenceValue, writeSession);
            this.sequenceMapping.setAttributeValueInObject(object, convertedSequenceValue);
        } else {
            // Now add the value to the object, this gets ugly.
            AbstractRecord tempRow = createRecord(1, writeSession);
            tempRow.put(sequenceNumberField, sequenceValue);

            // Require a query context to read into an object.
            ReadObjectQuery query = new ReadObjectQuery();
            query.setSession(writeSession);
            DatabaseMapping mapping = getBaseMappingForField(sequenceNumberField);
            Object sequenceIntoObject = getParentObjectForField(sequenceNumberField, object);

            // The following method will return the converted value for the sequence.
            convertedSequenceValue = mapping.readFromRowIntoObject(tempRow, null, sequenceIntoObject, null, query, writeSession, true);
        }

        // PERF: If PersistenceEntity is caching the primary key this must be cleared as the primary key has changed.
        clearPrimaryKey(object);

        if (writeQuery != null) {
            Object primaryKey = extractPrimaryKeyFromObject(object, writeSession);
            writeQuery.setPrimaryKey(primaryKey);
            AbstractRecord modifyRow = writeQuery.getModifyRow();
            // Update the row.
            modifyRow.put(sequenceNumberField, sequenceValue);
            if (descriptor.hasMultipleTables()) {
                addPrimaryKeyForNonDefaultTable(modifyRow, object, writeSession);
            }
            // Update the changeSet if there is one.
            if (writeSession.isUnitOfWork()) {
                ObjectChangeSet objectChangeSet = writeQuery.getObjectChangeSet();
                if ((objectChangeSet == null) && (((UnitOfWorkImpl)writeSession).getUnitOfWorkChangeSet() != null)) {
                    objectChangeSet = (ObjectChangeSet)((UnitOfWorkImpl)writeSession).getUnitOfWorkChangeSet().getObjectChangeSetForClone(object);
                }
                if (objectChangeSet != null) {
                    // objectChangeSet.isNew() == true
                    if (writeQuery.getDescriptor().shouldUseFullChangeSetsForNewObjects()) {
                        if (this.sequenceMapping != null) {
                            // Don't use ObjectChangeSet.updateChangeRecordForAttribute to avoid unnecessary conversion - convertedSequenceValue is already converted.
                            String attributeName = this.sequenceMapping.getAttributeName();
                            DirectToFieldChangeRecord changeRecord = (DirectToFieldChangeRecord)objectChangeSet.getChangesForAttributeNamed(attributeName);
                            if (changeRecord == null) {
                                changeRecord = new DirectToFieldChangeRecord(objectChangeSet);
                                changeRecord.setAttribute(attributeName);
                                changeRecord.setMapping(this.sequenceMapping);
                                objectChangeSet.addChange(changeRecord);
                            }
                            changeRecord.setNewValue(convertedSequenceValue);
                        } else {
                            ChangeRecord changeRecord = getBaseChangeRecordForField(objectChangeSet, object, sequenceNumberField, writeSession);
                            if (changeRecord.getMapping().isDirectCollectionMapping()) {
                                // assign converted value to the attribute
                                ((DirectToFieldChangeRecord)changeRecord).setNewValue(convertedSequenceValue);
                            } else if (changeRecord.getMapping().isTransformationMapping()) {
                                // put original (not converted) value into the record.
                                ((TransformationMappingChangeRecord)changeRecord).getRecord().put(sequenceNumberField, sequenceValue);
                            }
                        }
                    }
                    objectChangeSet.setId(primaryKey);
                }
            }
        }

        return convertedSequenceValue;
    }

    /**
     * Each mapping is recursed to assign values from the Record to the attributes in the domain object.
     */
    public void buildAttributesIntoObject(Object domainObject, CacheKey cacheKey, AbstractRecord databaseRow, ObjectBuildingQuery query, JoinedAttributeManager joinManager, FetchGroup executionFetchGroup, boolean forRefresh, AbstractSession targetSession) throws DatabaseException {
        if (this.descriptor.hasSerializedObjectPolicy() && query.shouldUseSerializedObjectPolicy()) {
            if (buildAttributesIntoObjectSOP(domainObject, cacheKey, databaseRow, query, joinManager, executionFetchGroup, forRefresh, targetSession)) {
                return;
            }
        }
        // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
        List<DatabaseMapping> mappings = this.descriptor.getMappings();

        // PERF: Cache if all mappings should be read.
        boolean readAllMappings = query.shouldReadAllMappings();
        boolean isTargetProtected = targetSession.isProtectedSession();
        int size = mappings.size();
        for (int index = 0; index < size; index++) {
            DatabaseMapping mapping = mappings.get(index);
            if (readAllMappings || query.shouldReadMapping(mapping, executionFetchGroup)) {
                mapping.readFromRowIntoObject(databaseRow, joinManager, domainObject, cacheKey, query, targetSession, isTargetProtected);
            }
        }

        // PERF: Avoid events if no listeners.
        if (this.descriptor.hasEventManager()) {
            postBuildAttributesIntoObjectEvent(domainObject, databaseRow, query, forRefresh);
        }
    }

    /**
     * Each mapping is recursed to assign values from the Record to the attributes in the domain object.
     * Should not be called unless (this.descriptor.hasSerializedObjectPolicy() &amp;&amp; query.shouldUseSerializedObjectPolicy())
     * This method populates the object only in if some mappings potentially should be read using sopObject and other mappings - not using it.
     * That happens when the row has been just read from the database and potentially has serialized object still in deserialized bits as a field value.
     * Note that  domainObject == sopObject is the same case, but (because domainObject has to be set into cache beforehand) extraction of sopObject
     * from bit was done right before this method is called.
     * Alternative situation is processing an empty row that has been created by foreign reference mapping
     * and holds nothing but sopObject (which is an attribute of the original sopObject) - this case falls through to buildAttributesIntoObject.
     * If attempt to deserialize sopObject from bits has failed, but SOP was setup to allow recovery
     * (all mapped all fields/value mapped to the object were read, not just those excluded from SOP)
     * then fall through to buildAttributesIntoObject.
     * Nothing should be done if sopObject is not null, but domainObject != sopObject:
     * the only way to get into this case should be with original query not maintaining cache,
     * through a back reference to the original object, which is already being built (or has been built).
     * @return whether the object has been populated with attributes, if not then buildAttributesIntoObject should be called.
     */
    protected boolean buildAttributesIntoObjectSOP(Object domainObject, CacheKey cacheKey, AbstractRecord databaseRow, ObjectBuildingQuery query, JoinedAttributeManager joinManager, FetchGroup executionFetchGroup, boolean forRefresh, AbstractSession targetSession) throws DatabaseException {
        Object sopObject = databaseRow.getSopObject();
        if (domainObject == sopObject) {
            // PERF: Cache if all mappings should be read.
            boolean readAllMappings = query.shouldReadAllMappings();
            boolean isTargetProtected = targetSession.isProtectedSession();
            // domainObject is sopObject
            for (DatabaseMapping mapping : this.descriptor.getMappings()) {
                if (readAllMappings || query.shouldReadMapping(mapping, executionFetchGroup)) {
                    // to avoid re-setting the same attribute value to domainObject
                    // only populate if either mapping (possibly nested) may reference entity or mapping does not use sopObject
                    if (mapping.hasNestedIdentityReference() || mapping.isOutOnlySopObject()) {
                        if (mapping.isOutSopObject()) {
                            // the mapping should be processed as if there is no sopObject
                            databaseRow.setSopObject(null);
                        } else {
                            databaseRow.setSopObject(sopObject);
                        }
                        mapping.readFromRowIntoObject(databaseRow, joinManager, domainObject, cacheKey, query, targetSession, isTargetProtected);
                    }
                }
            }
            // PERF: Avoid events if no listeners.
            if (this.descriptor.hasEventManager()) {
                postBuildAttributesIntoObjectEvent(domainObject, databaseRow, query, forRefresh);
            }
            // sopObject has been processed by all relevant mappings, no longer required.
            databaseRow.setSopObject(null);
            return true;
        } else {
            if (sopObject == null) {
                // serialized sopObject is a value corresponding to sopField in the row, row.sopObject==null;
                // the following line sets deserialized sopObject into row.sopObject variable and sets sopField's value to null;
                sopObject = this.descriptor.getSerializedObjectPolicy().getObjectFromRow(databaseRow, targetSession, (ObjectLevelReadQuery)query);
                if (sopObject != null) {
                    // PERF: Cache if all mappings should be read.
                    boolean readAllMappings = query.shouldReadAllMappings();
                    boolean isTargetProtected = targetSession.isProtectedSession();
                    for (DatabaseMapping mapping : this.descriptor.getMappings()) {
                        if (readAllMappings || query.shouldReadMapping(mapping, executionFetchGroup)) {
                            if (mapping.isOutSopObject()) {
                                // the mapping should be processed as if there is no sopObject
                                databaseRow.setSopObject(null);
                            } else {
                                databaseRow.setSopObject(sopObject);
                            }
                            mapping.readFromRowIntoObject(databaseRow, joinManager, domainObject, cacheKey, query, targetSession, isTargetProtected);
                        }
                    }
                    // PERF: Avoid events if no listeners.
                    if (this.descriptor.hasEventManager()) {
                        postBuildAttributesIntoObjectEvent(domainObject, databaseRow, query, forRefresh);
                    }
                    // sopObject has been processed by all relevant mappings, no longer required.
                    databaseRow.setSopObject(null);
                    return true;
                } else {
                    // SOP.getObjectFromRow returned null means serialized bits for sopObject either missing or deserilaized sopObject is invalid.
                    // If the method hasn't thrown exception then populating of the object is possible from the regular fields/values of the row
                    // (that means all fields/value mapped to the object were read, not just those excluded from SOP).
                    // return false and fall through to buildAttributesIntoObject
                    return false;
                }
            } else {
                // A mapping under SOP can't have another SOP on its reference descriptor,
                // but that's what seem to be happening.
                // The only way to get here should be with original query not maintaining cache,
                // through a back reference to the original object, which is already being built (or has been built).
                // Leave without building.
                return true;
            }
        }
    }

    protected void postBuildAttributesIntoObjectEvent(Object domainObject, AbstractRecord databaseRow, ObjectBuildingQuery query, boolean forRefresh) {
        DescriptorEventManager descriptorEventManager = this.descriptor.getDescriptorEventManager();
        if(descriptorEventManager.hasAnyEventListeners()) {
            // Need to run post build or refresh selector, currently check with the query for this,
            // I'm not sure which should be called it case of refresh building a new object, currently refresh is used...
            org.eclipse.persistence.descriptors.DescriptorEvent event = new DescriptorEvent(domainObject);
            event.setQuery(query);
            event.setSession(query.getSession());
            event.setRecord(databaseRow);
            if (forRefresh) {
                //this method can be called from different places within TopLink.  We may be
                //executing refresh query but building the object not refreshing so we must
                //throw the appropriate event.
                //bug 3325315
                event.setEventCode(DescriptorEventManager.PostRefreshEvent);
            } else {
                event.setEventCode(DescriptorEventManager.PostBuildEvent);
            }
            descriptorEventManager.executeEvent(event);
        }
    }

    /**
     * Returns the backup clone of the specified object. This is called only from unit of work.
     * The clone sent as parameter is always a working copy from the unit of work.
     */
    public Object buildBackupClone(Object clone, UnitOfWorkImpl unitOfWork) {
        // The copy policy builds clone    .
        ClassDescriptor descriptor = this.descriptor;
        Object backup = descriptor.getCopyPolicy().buildClone(clone, unitOfWork);

        // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
        List<DatabaseMapping> mappings = getCloningMappings();
        int size = mappings.size();
        if (descriptor.hasFetchGroupManager() && descriptor.getFetchGroupManager().isPartialObject(clone)) {
            FetchGroupManager fetchGroupManager = descriptor.getFetchGroupManager();
            for (int index = 0; index < size; index++) {
                DatabaseMapping mapping = mappings.get(index);
                if (fetchGroupManager.isAttributeFetched(clone, mapping.getAttributeName())) {
                    mapping.buildBackupClone(clone, backup, unitOfWork);
                }
            }
        } else {
            for (int index = 0; index < size; index++) {
                mappings.get(index).buildBackupClone(clone, backup, unitOfWork);
            }
        }

        return backup;
    }

    /**
     * Build and return the expression to use as the where clause to delete an object.
     * The row is passed to allow the version number to be extracted from it.
     * If called with usesOptimisticLocking==true the caller should make sure that descriptor uses optimistic locking policy.
     */
    public Expression buildDeleteExpression(DatabaseTable table, AbstractRecord row, boolean usesOptimisticLocking) {
        if (usesOptimisticLocking && (this.descriptor.getTables().firstElement().equals(table))) {
            return this.descriptor.getOptimisticLockingPolicy().buildDeleteExpression(table, primaryKeyExpression, row);
        } else {
            return buildPrimaryKeyExpression(table);
        }
    }

    /**
     * INTERNAL:
     * This method is used when Query By Example is used.  Going through the mappings one by one, this method
     * calls the specific buildExpression method corresponding to the type of mapping.  It then generates a
     * complete Expression by joining the individual Expressions.
     */
    public Expression buildExpressionFromExample(Object queryObject, QueryByExamplePolicy policy, Expression expressionBuilder, Map processedObjects, AbstractSession session) {
        if (processedObjects.containsKey(queryObject)) {
            //this object has already been queried on
            return null;
        }

        processedObjects.put(queryObject, queryObject);
        Expression expression = null;

        // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
        List<DatabaseMapping> mappings = this.descriptor.getMappings();
        for (int index = 0; index < mappings.size(); index++) {
            DatabaseMapping mapping = mappings.get(index);
            if (expression == null) {
                expression = mapping.buildExpression(queryObject, policy, expressionBuilder, processedObjects, session);
            } else {
                expression = expression.and(mapping.buildExpression(queryObject, policy, expressionBuilder, processedObjects, session));
            }
        }

        return expression;
    }

    /**
     * Return a new instance of the receiver's javaClass.
     */
    @Override
    public Object buildNewInstance() {
        return this.descriptor.getInstantiationPolicy().buildNewInstance();
    }

    /**
     * Return an instance of the receivers javaClass. Set the attributes of an instance
     * from the values stored in the database row.
     */
    public Object buildObject(ObjectLevelReadQuery query, AbstractRecord databaseRow) {
        // PERF: Avoid lazy init of join manager if no joining.
        JoinedAttributeManager joinManager = null;
        if (query.hasJoining()) {
            joinManager = query.getJoinedAttributeManager();
        }
        return buildObject(query, databaseRow, joinManager);
    }

    /**
     * Return an instance of the receivers javaClass. Set the attributes of an instance
     * from the values stored in the database row.
     */
    public Object buildObject(ObjectBuildingQuery query, AbstractRecord databaseRow, JoinedAttributeManager joinManager) {
        InheritancePolicy inheritancePolicy = null;
        if (this.descriptor.hasInheritance()) {
            inheritancePolicy = this.descriptor.getInheritancePolicy();
        }
        AbstractSession session = query.getSession();
        session.startOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
        Object domainObject = null;
        try {
            domainObject = buildObject(query, databaseRow, joinManager, session, this.descriptor, inheritancePolicy, session.isUnitOfWork(), query.shouldCacheQueryResults(), query.shouldUseWrapperPolicy());
        } finally {
            session.endOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
        }
        return domainObject;
    }

    /**
     * Return an instance of the receivers javaClass. Set the attributes of an instance
     * from the values stored in the database row.
     * This is wrapper method with semaphore logic.
     */
    public Object buildObject(ObjectBuildingQuery query, AbstractRecord databaseRow, JoinedAttributeManager joinManager,
                              AbstractSession session, ClassDescriptor concreteDescriptor, InheritancePolicy inheritancePolicy, boolean isUnitOfWork,
                              boolean shouldCacheQueryResults, boolean shouldUseWrapperPolicy) {
        boolean semaphoreWasAcquired = false;
        boolean useSemaphore = ConcurrencyUtil.SINGLETON.isUseSemaphoreInObjectBuilder();
        if (objectBuilderSemaphore == null) {
            objectBuilderSemaphore = new ConcurrencySemaphore(SEMAPHORE_THREAD_LOCAL_VAR, SEMAPHORE_MAX_NUMBER_THREADS, SEMAPHORE_LIMIT_MAX_NUMBER_OF_THREADS_OBJECT_BUILDING, this, "object_builder_semaphore_acquired_01");
        }
        try {
            semaphoreWasAcquired = objectBuilderSemaphore.acquireSemaphoreIfAppropriate(useSemaphore);
            return buildObjectInternal(query, databaseRow, joinManager, session, concreteDescriptor, inheritancePolicy, isUnitOfWork, shouldCacheQueryResults, shouldUseWrapperPolicy);
        } finally {
            objectBuilderSemaphore.releaseSemaphoreAllowOtherThreadsToStartDoingObjectBuilding(semaphoreWasAcquired);
        }
    }

    /**
     * Return an instance of the receivers javaClass. Set the attributes of an instance
     * from the values stored in the database row.
     */
    private Object buildObjectInternal(ObjectBuildingQuery query, AbstractRecord databaseRow, JoinedAttributeManager joinManager,
            AbstractSession session, ClassDescriptor concreteDescriptor, InheritancePolicy inheritancePolicy, boolean isUnitOfWork,
            boolean shouldCacheQueryResults, boolean shouldUseWrapperPolicy) {
        Object domainObject = null;
        CacheKey prefechedCacheKey = null;
        Object primaryKey = extractPrimaryKeyFromRow(databaseRow, session);
        // Check for null primary key, this is not allowed.
        if ((primaryKey == null) && (!query.hasPartialAttributeExpressions()) && (!this.descriptor.isAggregateCollectionDescriptor())) {
            //BUG 3168689: EJBQL: "Select Distinct s.customer from SpouseBean s"
            //BUG 3168699: EJBQL: "Select s.customer from SpouseBean s where s.id = '6'"
            //If we return either a single null, or a Collection containing at least
            //one null, then we want the nulls returned/included if the indicated
            //property is set in the query. (As opposed to throwing an Exception).
            if (query.shouldBuildNullForNullPk()) {
                return null;
            } else {
                throw QueryException.nullPrimaryKeyInBuildingObject(query, databaseRow);
            }
        }
        if (query.getPrefetchedCacheKeys() != null){
            prefechedCacheKey = query.getPrefetchedCacheKeys().get(primaryKey);
        }
        if ((inheritancePolicy != null) && inheritancePolicy.shouldReadSubclasses()) {
            Class classValue = inheritancePolicy.classFromRow(databaseRow, session);
            concreteDescriptor = inheritancePolicy.getDescriptor(classValue);
            if ((concreteDescriptor == null) && query.hasPartialAttributeExpressions()) {
                concreteDescriptor = this.descriptor;
            }
            if (concreteDescriptor == null) {
                throw QueryException.noDescriptorForClassFromInheritancePolicy(query, classValue);
            }
        }
        if (isUnitOfWork) {
            // Do not wrap yet if in UnitOfWork, as there is still much more
            // processing ahead.
            domainObject = buildObjectInUnitOfWork(query, joinManager, databaseRow, (UnitOfWorkImpl)session, primaryKey, prefechedCacheKey, concreteDescriptor);
        } else {
            domainObject = buildObject(false, query, databaseRow, session, primaryKey, prefechedCacheKey, concreteDescriptor, joinManager);
            if (shouldCacheQueryResults) {
                query.cacheResult(domainObject);
            }

            // wrap the object if the query requires it.
            if (shouldUseWrapperPolicy) {
                domainObject = concreteDescriptor.getObjectBuilder().wrapObject(domainObject, session);
            }
        }

        return domainObject;
    }

    /**
     * Force instantiation to any eager mappings.
     */
    public void instantiateEagerMappings(Object object, AbstractSession session) {
        // Force instantiation to eager mappings.
        if (!this.eagerMappings.isEmpty()) {
            FetchGroup fetchGroup = null;
            FetchGroupManager fetchGroupManager = this.descriptor.getFetchGroupManager();
            if (fetchGroupManager != null) {
                fetchGroup = fetchGroupManager.getObjectFetchGroup(object);
            }
            int size = this.eagerMappings.size();
            for (int index = 0; index < size; index++) {
                DatabaseMapping mapping = this.eagerMappings.get(index);
                if (fetchGroup == null || fetchGroup.containsAttributeInternal(mapping.getAttributeName())) {
                    mapping.instantiateAttribute(object, session);
                }
            }
        }
    }

    /**
     * Force instantiation to any mappings in the load group.
     */
    public void load(final Object object, AttributeGroup group, final AbstractSession session, final boolean fromFetchGroup) {
        FetchGroupManager fetchGroupManager = this.descriptor.getFetchGroupManager();
        if (fetchGroupManager != null) {
            FetchGroup fetchGroup = fetchGroupManager.getObjectFetchGroup(object);
            if (fetchGroup != null) {
                if (!fetchGroup.getAttributeNames().containsAll(group.getAttributeNames())) {
                    // trigger fetch group if it does not contain all attributes of the current group.
                    fetchGroup.onUnfetchedAttribute((FetchGroupTracker)object, null);
                }
            }
        }
        for (AttributeItem eachItem : group.getAllItems().values()) {
            final DatabaseMapping mapping = getMappingForAttributeName(eachItem.getAttributeName());
            final AttributeItem item = eachItem;
            if (mapping == null) {
                // no mapping found
                throw ValidationException.fetchGroupHasUnmappedAttribute(group, item.getAttributeName());
            }
            // Allow the attributes to be loaded on concurrent threads.
            // Only do so on a ServerSession, as other sessions are not thread safe.
            if (group.isConcurrent() && session.isServerSession()) {
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        mapping.load(object, item, session, fromFetchGroup);
                    }
                };
                session.getServerPlatform().launchContainerRunnable(runnable);
            } else {
                mapping.load(object, item, session, fromFetchGroup);
            }
        }
    }

    /**
     * Force instantiation of all indirections.
     */
    public void loadAll(Object object, AbstractSession session) {
        loadAll(object, session, new IdentityHashSet());
    }
    public void loadAll(Object object, AbstractSession session, IdentityHashSet loaded) {
        if (loaded.contains(object)) {
            return;
        }
        loaded.add(object);
        for (DatabaseMapping mapping : this.descriptor.getMappings()) {
            mapping.loadAll(object, session, loaded);
        }
    }

    /**
     * For executing all reads on the UnitOfWork, the session when building
     * objects from rows will now be the UnitOfWork.  Useful if the rows were
     * read via a dirty write connection and we want to avoid putting uncommitted
     * data in the global cache.
     * <p>
     * Decides whether to call either buildWorkingCopyCloneFromRow (bypassing
     * shared cache) or buildWorkingCopyCloneNormally (placing the result in the
     * shared cache).
     */
    protected Object buildObjectInUnitOfWork(ObjectBuildingQuery query, JoinedAttributeManager joinManager, AbstractRecord databaseRow, UnitOfWorkImpl unitOfWork, Object primaryKey, CacheKey preFetchedCacheKey, ClassDescriptor concreteDescriptor) throws DatabaseException, QueryException {
        // When in transaction we are reading via the write connection
        // and so do not want to corrupt the shared cache with dirty objects.
        // Hence we build and refresh clones directly from the database row.
        // PERF: Allow the session cached to still be used after early transaction if isolation setting has been set.
        CachePolicy cachePolicy = concreteDescriptor.getCachePolicy();
        if (!cachePolicy.shouldUseSessionCacheInUnitOfWorkEarlyTransaction()) {
            if (((unitOfWork.hasCommitManager() && unitOfWork.getCommitManager().isActive())
                    || unitOfWork.wasTransactionBegunPrematurely()
                    || cachePolicy.shouldIsolateObjectsInUnitOfWork()
                    || cachePolicy.shouldIsolateProtectedObjectsInUnitOfWork()
                    || query.shouldStoreBypassCache())
                        && (!unitOfWork.isClassReadOnly(concreteDescriptor.getJavaClass(), concreteDescriptor))) {
                // It is easier to switch once to the correct builder here.
                return concreteDescriptor.getObjectBuilder().buildWorkingCopyCloneFromRow(query, joinManager, databaseRow, unitOfWork, primaryKey, preFetchedCacheKey);
            }
        }

        return buildWorkingCopyCloneNormally(query, databaseRow, unitOfWork, primaryKey, preFetchedCacheKey, concreteDescriptor, joinManager);
    }

    /**
     * buildWorkingCopyCloneFromRow is an alternative to this which is the
     * normal behavior.
     * A row is read from the database, an original is built/refreshed/returned
     * from the shared cache, and the original is registered/conformed/reverted
     * in the UnitOfWork.
     * <p>
     * This default behavior is only safe when the query is executed on a read
     * connection, otherwise uncommitted data might get loaded into the shared
     * cache.
     * <p>
     * Represents the way TopLink has always worked.
     */
    protected Object buildWorkingCopyCloneNormally(ObjectBuildingQuery query, AbstractRecord databaseRow, UnitOfWorkImpl unitOfWork, Object primaryKey, CacheKey preFetchedCacheKey, ClassDescriptor concreteDescriptor, JoinedAttributeManager joinManager) throws DatabaseException, QueryException {
        // First check local unit of work cache.
        CacheKey unitOfWorkCacheKey = unitOfWork.getIdentityMapAccessorInstance().acquireLock(primaryKey, concreteDescriptor.getJavaClass(), concreteDescriptor, query.isCacheCheckComplete());
        Object clone = unitOfWorkCacheKey.getObject();
        boolean found = clone != null;
        Object original = null;
        try {
            // Only check parent cache if not in unit of work, or if a refresh is required.
            if (!found || query.shouldRefreshIdentityMapResult()
                    || query.shouldCacheQueryResults() // Need to build original to cache it.
                    || query.shouldRetrieveBypassCache()
                    || (concreteDescriptor.hasFetchGroupManager() && concreteDescriptor.getFetchGroupManager().isPartialObject(clone))) {
                // This is normal case when we are not in transaction.
                // Pass the query off to the parent.  Let it build the object and
                // cache it normally, then register/refresh it.
                AbstractSession session = unitOfWork.getParentIdentityMapSession(query);

                // forwarding queries to different sessions is now as simple as setting
                // the session on the query.
                query.setSession(session);
                if (session.isUnitOfWork()) {
                    // If a nested unit of work, recurse.
                    original = buildObjectInUnitOfWork(query, joinManager, databaseRow, (UnitOfWorkImpl)session, primaryKey, preFetchedCacheKey, concreteDescriptor);
                    //GFBug#404  Pass in joinManager or not based on if shouldCascadeCloneToJoinedRelationship is set to true
                    if (unitOfWork.shouldCascadeCloneToJoinedRelationship()) {
                        return query.registerIndividualResult(original, primaryKey, unitOfWork, joinManager, concreteDescriptor);
                    } else {
                        return query.registerIndividualResult(original, primaryKey, unitOfWork, null, concreteDescriptor);
                    }
                } else {
                    // PERF: This optimizes the normal case to avoid duplicate cache access.
                    CacheKey parentCacheKey = (CacheKey)buildObject(true, query, databaseRow, session, primaryKey, preFetchedCacheKey, concreteDescriptor, joinManager);
                    original = parentCacheKey.getObject();
                    if (query.shouldCacheQueryResults()) {
                        query.cacheResult(original);
                    }
                    // PERF: Do not register nor process read-only.
                    if (unitOfWork.isClassReadOnly(original.getClass(), concreteDescriptor)) {
                        // There is an obscure case where they object could be read-only and pessimistic.
                        // Record clone if referenced class has pessimistic locking policy.
                        query.recordCloneForPessimisticLocking(original, unitOfWork);
                        return original;
                    }
                    if (!query.isRegisteringResults()) {
                        return original;
                    }
                    if (clone == null) {
                        clone = unitOfWork.cloneAndRegisterObject(original, parentCacheKey, unitOfWorkCacheKey, concreteDescriptor);
                        // TODO-dclarke: At this point the clones do not have their fetch-group specified
                        // relationship attributes loaded
                    }
                    //bug3659327
                    //fetch group manager control fetch group support
                    if (concreteDescriptor.hasFetchGroupManager()) {
                        //if the object is already registered in uow, but it's partially fetched (fetch group case)
                        if (concreteDescriptor.getFetchGroupManager().shouldWriteInto(original, clone)) {
                            //there might be cases when reverting/refreshing clone is needed.
                            concreteDescriptor.getFetchGroupManager().writePartialIntoClones(original, clone, unitOfWork.getBackupClone(clone, concreteDescriptor), unitOfWork);
                        }
                    }
                }
            }
            query.postRegisterIndividualResult(clone, original, primaryKey, unitOfWork, joinManager, concreteDescriptor);
        } finally {
            unitOfWorkCacheKey.release();
            query.setSession(unitOfWork);
        }
        return clone;
    }

    /**
     * Return an instance of the receivers javaClass. Set the attributes of an instance
     * from the values stored in the database row.
     */
    protected Object buildObject(boolean returnCacheKey, ObjectBuildingQuery query, AbstractRecord databaseRow, AbstractSession session, Object primaryKey, CacheKey preFetchedCacheKey, ClassDescriptor concreteDescriptor, JoinedAttributeManager joinManager) throws DatabaseException, QueryException {
        boolean isProtected = concreteDescriptor.getCachePolicy().isProtectedIsolation();
        if (isProtected && session.isIsolatedClientSession()){
            return buildProtectedObject(returnCacheKey, query, databaseRow, session, primaryKey, preFetchedCacheKey, concreteDescriptor, joinManager);
        }
        Object domainObject = null;

        // Cache key is used for object locking.
        CacheKey cacheKey = null;
        // Keep track if we actually built/refresh the object.
        boolean cacheHit = true;
        boolean isSopQuery = concreteDescriptor.hasSerializedObjectPolicy() && query.shouldUseSerializedObjectPolicy();
        // has to cache this flag - sopObject is set to null in the row after it has been processed
        boolean hasSopObject = databaseRow.hasSopObject();
        boolean domainWasMissing = true;
        boolean shouldMaintainCache = query.shouldMaintainCache();
        ObjectBuilder concreteObjectBuilder = concreteDescriptor.getObjectBuilder();
        try {
            boolean shouldRetrieveBypassCache = query.shouldRetrieveBypassCache();
            boolean shouldStoreBypassCache = query.shouldStoreBypassCache();
            // Check if the objects exists in the identity map.
            if (shouldMaintainCache && (!shouldRetrieveBypassCache || !shouldStoreBypassCache)) {
                if (preFetchedCacheKey == null){
                    cacheKey = session.retrieveCacheKey(primaryKey, concreteDescriptor, joinManager, query);
                }else{
                    cacheKey = preFetchedCacheKey;
                    cacheKey.acquireLock(query);
                }
                if (cacheKey != null){
                    domainObject = cacheKey.getObject();
                }
                domainWasMissing = domainObject == null;
            }

            FetchGroup fetchGroup = query.getExecutionFetchGroup(concreteDescriptor);

            if (domainWasMissing || shouldRetrieveBypassCache) {
                cacheHit = false;
                if (domainObject == null || shouldStoreBypassCache) {
                    if (query.isReadObjectQuery() && ((ReadObjectQuery)query).shouldLoadResultIntoSelectionObject()) {
                        domainObject = ((ReadObjectQuery)query).getSelectionObject();
                    } else {
                        if (isSopQuery && !hasSopObject) {
                            // serialized sopObject is a value corresponding to sopField in the row, row.sopObject==null;
                            // the following line sets deserialized sopObject into row.sopObject variable and sets sopField's value to null;
                            domainObject = concreteDescriptor.getSerializedObjectPolicy().getObjectFromRow(databaseRow, session, (ObjectLevelReadQuery)query);
                        }
                        if (domainObject == null) {
                            domainObject = concreteObjectBuilder.buildNewInstance();
                        }
                    }
                }

                // The object must be registered before building its attributes to resolve circular dependencies.
                if (shouldMaintainCache && !shouldStoreBypassCache) {
                    if (domainWasMissing) {  // may have build a new domain even though there is one in the cache
                        cacheKey.setObject(domainObject);
                    }
                    copyQueryInfoToCacheKey(cacheKey, query, databaseRow, session, concreteDescriptor);
                } else if (cacheKey == null || (domainWasMissing && shouldRetrieveBypassCache)) {
                    cacheKey = new CacheKey(primaryKey);
                    cacheKey.setObject(domainObject);
                }
                concreteObjectBuilder.buildAttributesIntoObject(domainObject, cacheKey, databaseRow, query, joinManager, fetchGroup, false, session);
                if (isProtected && (cacheKey != null)) {
                    cacheForeignKeyValues(databaseRow, cacheKey, session);
                }
                if (shouldMaintainCache && !shouldStoreBypassCache) {
                    // Set the fetch group to the domain object, after built.
                    if ((fetchGroup != null) && concreteDescriptor.hasFetchGroupManager()) {
                        EntityFetchGroup entityFetchGroup = concreteDescriptor.getFetchGroupManager().getEntityFetchGroup(fetchGroup);
                        if (entityFetchGroup !=null){
                            entityFetchGroup.setOnEntity(domainObject, session);
                        }
                    }
                }
                // PERF: Cache the primary key and cache key if implements PersistenceEntity.
                if (domainObject instanceof PersistenceEntity) {
                    updateCachedAttributes((PersistenceEntity) domainObject, cacheKey, primaryKey);
                }
            } else {
                if (query.isReadObjectQuery() && ((ReadObjectQuery)query).shouldLoadResultIntoSelectionObject()) {
                    copyInto(domainObject, ((ReadObjectQuery)query).getSelectionObject());
                    domainObject = ((ReadObjectQuery)query).getSelectionObject();
                }

                //check if the cached object has been invalidated
                boolean isInvalidated = concreteDescriptor.getCacheInvalidationPolicy().isInvalidated(cacheKey, query.getExecutionTime());
                FetchGroupManager concreteFetchGroupManager = null;
                if (concreteDescriptor.hasFetchGroupManager()) {
                    concreteFetchGroupManager = concreteDescriptor.getFetchGroupManager();
                }

                //CR #4365 - Queryid comparison used to prevent infinite recursion on refresh object cascade all
                //if the concurrency manager is locked by the merge process then no refresh is required.
                // bug # 3388383 If this thread does not have the active lock then someone is building the object so in order to maintain data integrity this thread will not
                // fight to overwrite the object ( this also will avoid potential deadlock situations
                if ((cacheKey.getActiveThread() == Thread.currentThread()) && ((query.shouldRefreshIdentityMapResult() || concreteDescriptor.shouldAlwaysRefreshCache() || isInvalidated ) && ((cacheKey.getLastUpdatedQueryId() != query.getQueryId()) && !cacheKey.isLockedByMergeManager()))) {
                    cacheHit = refreshObjectIfRequired(concreteDescriptor, cacheKey, cacheKey.getObject(), query, joinManager, databaseRow, session, false);
                } else if ((concreteFetchGroupManager != null) && (concreteFetchGroupManager.isPartialObject(domainObject) && (!concreteFetchGroupManager.isObjectValidForFetchGroup(domainObject, concreteFetchGroupManager.getEntityFetchGroup(fetchGroup))))) {
                    cacheHit = false;
                    // The fetched object is not sufficient for the fetch group of the query
                    // refresh attributes of the query's fetch group.
                    concreteFetchGroupManager.unionEntityFetchGroupIntoObject(domainObject, concreteFetchGroupManager.getEntityFetchGroup(fetchGroup), session, false);
                    concreteObjectBuilder.buildAttributesIntoObject(domainObject, cacheKey, databaseRow, query, joinManager, fetchGroup, false, session);
                    if (cacheKey != null){
                        cacheForeignKeyValues(databaseRow, cacheKey, session);
                    }
                }
                // 3655915: a query with join/batch'ing that gets a cache hit
                // may require some attributes' valueholders to be re-built.
                else if (joinManager != null && joinManager.hasJoinedAttributeExpressions()) { //some queries like ObjRel do not support joining
                    loadJoinedAttributes(concreteDescriptor, domainObject, cacheKey, databaseRow, joinManager, query, false);
                } else if (query.isReadAllQuery() && ((ReadAllQuery)query).hasBatchReadAttributes()) {
                    loadBatchReadAttributes(concreteDescriptor, domainObject, cacheKey, databaseRow, query, joinManager, false);
                }
            }
        } finally {
            if (shouldMaintainCache && (cacheKey != null)) {
                // bug 2681401:
                // in case of exception (for instance, thrown by buildNewInstance())
                // cacheKey.getObject() may be null.
                if (cacheKey.getObject() != null) {
                    cacheKey.updateAccess();
                }

                // PERF: Only use deferred locking if required.
                if (query.requiresDeferredLocks()) {
                    cacheKey.releaseDeferredLock();
                } else {
                    cacheKey.release();
                }
            }
        }
        if (!cacheHit) {
            concreteObjectBuilder.instantiateEagerMappings(domainObject, session);
            if (shouldMaintainCache && (cacheKey != null)) {
                if (hasSopObject || (isSopQuery && this.hasCacheIndexesInSopObject)) {
                    // at least some of the cache index fields are missing from the row - extract index values from domainObject
                    concreteDescriptor.getCachePolicy().indexObjectInCache(cacheKey, domainObject, concreteDescriptor, session, !domainWasMissing);
                } else {
                    concreteDescriptor.getCachePolicy().indexObjectInCache(cacheKey, databaseRow, domainObject, concreteDescriptor, session, !domainWasMissing);
                }
            }
        }
        if (query instanceof ObjectLevelReadQuery) {
            LoadGroup group = query.getLoadGroup();
            if (group != null) {
                session.load(domainObject, group, query.getDescriptor(), false);
            }
        }
        if (session.getProject().allowExtendedCacheLogging() && cacheKey != null && cacheKey.getObject() != null) {
            session.log(SessionLog.FINEST, SessionLog.CACHE, "cache_item_creation", new Object[] {domainObject.getClass(), primaryKey, Thread.currentThread().getId(), Thread.currentThread().getName()});
        }
        if (returnCacheKey) {
            return cacheKey;
        } else {
            return domainObject;
        }
    }

    /**
     * Return an instance of the receivers javaClass. Set the attributes of an instance
     * from the values stored in the database row.
     */
    protected Object buildProtectedObject(boolean returnCacheKey, ObjectBuildingQuery query, AbstractRecord databaseRow, AbstractSession session, Object primaryKey, CacheKey preFetchedCacheKey, ClassDescriptor concreteDescriptor, JoinedAttributeManager joinManager) throws DatabaseException, QueryException {
        Object cachedObject = null;
        Object protectedObject = null;

        // Cache key is used for object locking.
        CacheKey cacheKey = null;
        CacheKey sharedCacheKey = null;

        // Keep track if we actually built/refresh the object.
        boolean cacheHit = true;
        try {
            // Check if the objects exists in the identity map.
            if (query.shouldMaintainCache() &&  (!query.shouldRetrieveBypassCache() || !query.shouldStoreBypassCache())) {
                cacheKey = session.retrieveCacheKey(primaryKey, concreteDescriptor, joinManager, query);
                protectedObject = cacheKey.getObject();
            }
            FetchGroup fetchGroup = query.getExecutionFetchGroup(concreteDescriptor);
            FetchGroupManager fetchGroupManager = concreteDescriptor.getFetchGroupManager();

            if (protectedObject == null || query.shouldRetrieveBypassCache()) {
                cacheHit = false;
                boolean domainWasMissing = protectedObject == null;
                if (protectedObject == null || query.shouldStoreBypassCache()){
                    if (query.isReadObjectQuery() && ((ReadObjectQuery)query).shouldLoadResultIntoSelectionObject()) {
                        protectedObject = ((ReadObjectQuery)query).getSelectionObject();
                    } else {
                        protectedObject = concreteDescriptor.getObjectBuilder().buildNewInstance();
                    }
                }
                // The object must be registered before building its attributes to resolve circular dependencies.
                // The object must be registered before building its attributes to resolve circular dependencies.
                if (query.shouldMaintainCache() && ! query.shouldStoreBypassCache()){
                    if (domainWasMissing) {  // may have build a new domain even though there is one in the cache
                        cacheKey.setObject(protectedObject);
                    }
                    copyQueryInfoToCacheKey(cacheKey, query, databaseRow, session, concreteDescriptor);
                }else if (cacheKey == null || (domainWasMissing && query.shouldRetrieveBypassCache())){
                    cacheKey = new CacheKey(primaryKey);
                    cacheKey.setObject(protectedObject);
                }


                // The object must be registered before building its attributes to resolve circular dependencies.
                if (query.shouldMaintainCache() && ! query.shouldStoreBypassCache()) {
                    if (preFetchedCacheKey == null){
                        sharedCacheKey = session.getParent().retrieveCacheKey(primaryKey, concreteDescriptor, joinManager, query);
                    }else{
                        sharedCacheKey = preFetchedCacheKey;
                        cacheKey.acquireLock(query);
                    }
                    if (sharedCacheKey.getObject() == null){
                        sharedCacheKey = (CacheKey) buildObject(true, query, databaseRow, session.getParent(), primaryKey, preFetchedCacheKey, concreteDescriptor, joinManager);
                        cachedObject = sharedCacheKey.getObject();
                    }
                }
                concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(protectedObject, sharedCacheKey, databaseRow, query, joinManager, fetchGroup, false, session);

                //if !protected the returned object and the domain object are the same.
                if (query.shouldMaintainCache() && ! query.shouldStoreBypassCache()) {
                    // Set the fetch group to the domain object, after built.
                    if ((fetchGroup != null) && concreteDescriptor.hasFetchGroupManager()) {
                        EntityFetchGroup entityFetchGroup = concreteDescriptor.getFetchGroupManager().getEntityFetchGroup(fetchGroup);
                        if (entityFetchGroup !=null){
                            entityFetchGroup.setOnEntity(protectedObject, session);
                        }
                    }
                }
                // PERF: Cache the primary key and cache key if implements PersistenceEntity.
                if (protectedObject instanceof PersistenceEntity) {
                    ((PersistenceEntity)protectedObject)._persistence_setId(primaryKey);
                }
            } else {
                if (query.isReadObjectQuery() && ((ReadObjectQuery)query).shouldLoadResultIntoSelectionObject()) {
                    copyInto(protectedObject, ((ReadObjectQuery)query).getSelectionObject());
                    protectedObject = ((ReadObjectQuery)query).getSelectionObject();
                }
                sharedCacheKey = session.getParent().retrieveCacheKey(primaryKey, concreteDescriptor, joinManager, query);
                cachedObject = sharedCacheKey.getObject();
                if (cachedObject == null){
                    sharedCacheKey = (CacheKey) buildObject(true, query, databaseRow, session.getParent(), primaryKey, preFetchedCacheKey, concreteDescriptor, joinManager);
                    cachedObject = sharedCacheKey.getObject();
                }

                //check if the cached object has been invalidated
                boolean isInvalidated = concreteDescriptor.getCacheInvalidationPolicy().isInvalidated(sharedCacheKey, query.getExecutionTime());

                //CR #4365 - Queryid comparison used to prevent infinite recursion on refresh object cascade all
                //if the concurrency manager is locked by the merge process then no refresh is required.
                // bug # 3388383 If this thread does not have the active lock then someone is building the object so in order to maintain data integrity this thread will not
                // fight to overwrite the object ( this also will avoid potential deadlock situations
                if ((sharedCacheKey.getActiveThread() == Thread.currentThread()) && ((query.shouldRefreshIdentityMapResult() || concreteDescriptor.shouldAlwaysRefreshCache() || isInvalidated) && ((sharedCacheKey.getLastUpdatedQueryId() != query.getQueryId()) && !sharedCacheKey.isLockedByMergeManager()))) {

                    //need to refresh. shared cache instance
                    cacheHit = refreshObjectIfRequired(concreteDescriptor, sharedCacheKey, cachedObject, query, joinManager, databaseRow, session.getParent(), true);
                    //shared cache was refreshed and a refresh has been requested so lets refresh the protected object as well
                    refreshObjectIfRequired(concreteDescriptor, sharedCacheKey, protectedObject, query, joinManager, databaseRow, session, true);
                } else if (fetchGroupManager != null && (fetchGroupManager.isPartialObject(protectedObject) && (!fetchGroupManager.isObjectValidForFetchGroup(protectedObject, fetchGroupManager.getEntityFetchGroup(fetchGroup))))) {
                    cacheHit = false;
                    // The fetched object is not sufficient for the fetch group of the query
                    // refresh attributes of the query's fetch group.
                    fetchGroupManager.unionEntityFetchGroupIntoObject(protectedObject, fetchGroupManager.getEntityFetchGroup(fetchGroup), session, false);
                    concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(protectedObject, sharedCacheKey, databaseRow, query, joinManager, fetchGroup, false, session);
                }
                // 3655915: a query with join/batch'ing that gets a cache hit
                // may require some attributes' valueholders to be re-built.
                else if (joinManager != null && joinManager.hasJoinedAttributeExpressions()) { //some queries like ObjRel do not support joining
                    loadJoinedAttributes(concreteDescriptor, cachedObject, sharedCacheKey, databaseRow, joinManager, query, false);
                    loadJoinedAttributes(concreteDescriptor, protectedObject, sharedCacheKey, databaseRow, joinManager, query, true);
                } else if (query.isReadAllQuery() && ((ReadAllQuery)query).hasBatchReadAttributes()) {
                    loadBatchReadAttributes(concreteDescriptor, cachedObject, sharedCacheKey, databaseRow, query, joinManager, false);
                    loadBatchReadAttributes(concreteDescriptor, protectedObject, sharedCacheKey, databaseRow, query, joinManager, true);
                }
            }
        } finally {
            if (query.shouldMaintainCache()){
                if (cacheKey != null) {
                    // bug 2681401:
                    // in case of exception (for instance, thrown by buildNewInstance())
                    // cacheKey.getObject() may be null.
                    if (cacheKey.getObject() != null) {
                        cacheKey.updateAccess();
                    }

                    // PERF: Only use deferred locking if required.
                    if (query.requiresDeferredLocks()) {
                        cacheKey.releaseDeferredLock();
                    } else {
                        cacheKey.release();
                    }
                }
                if (sharedCacheKey != null) {
                    // bug 2681401:
                    // in case of exception (for instance, thrown by buildNewInstance())
                    // sharedCacheKey() may be null.
                    if (sharedCacheKey.getObject() != null) {
                        sharedCacheKey.updateAccess();
                    }

                    // PERF: Only use deferred locking if required.
                    if (query.requiresDeferredLocks()) {
                        sharedCacheKey.releaseDeferredLock();
                    } else {
                        sharedCacheKey.release();
                    }
                }
            }
        }
        if (!cacheHit) {
            concreteDescriptor.getObjectBuilder().instantiateEagerMappings(protectedObject, session);
        }
        if (session.getProject().allowExtendedCacheLogging() && cacheKey != null && cacheKey.getObject() != null) {
            session.log(SessionLog.FINEST, SessionLog.CACHE, "cache_item_creation", new Object[] {protectedObject.getClass(), primaryKey, Thread.currentThread().getId(), Thread.currentThread().getName()});
        }
        if (returnCacheKey) {
            return cacheKey;
        } else {
            return protectedObject;
        }
    }

    /**
     * Clean up the cached object data and only revert the fetch group data back to the cached object.
     */
    private void revertFetchGroupData(Object domainObject, ClassDescriptor concreteDescriptor, CacheKey cacheKey, ObjectBuildingQuery query, JoinedAttributeManager joinManager, AbstractRecord databaseRow, AbstractSession session, boolean targetIsProtected) {
        FetchGroup fetchGroup = query.getExecutionFetchGroup(concreteDescriptor);
        FetchGroupManager fetchGroupManager = concreteDescriptor.getFetchGroupManager();
        //the cached object is either invalidated, or staled as the version is newer, or a refresh is explicitly set on the query.
        //clean all data of the cache object.
        fetchGroupManager.reset(domainObject);
        //set fetch group reference to the cached object
        fetchGroupManager.setObjectFetchGroup(domainObject, fetchGroupManager.getEntityFetchGroup(fetchGroup), session);
        // Bug 276362 - set the CacheKey's read time (to re-validate the CacheKey) before buildAttributesIntoObject is called
        cacheKey.setReadTime(query.getExecutionTime());
        //read in the fetch group data only
        concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(domainObject, cacheKey, databaseRow, query, joinManager, fetchGroup, false, session);
        //set refresh on fetch group
        fetchGroupManager.setRefreshOnFetchGroupToObject(domainObject, (query.shouldRefreshIdentityMapResult() || concreteDescriptor.shouldAlwaysRefreshCache()));
        //set query id to prevent infinite recursion on refresh object cascade all
        cacheKey.setLastUpdatedQueryId(query.getQueryId());
        //register the object into the IM and set the write lock object if applied.
        if (concreteDescriptor.usesOptimisticLocking()) {
            OptimisticLockingPolicy policy = concreteDescriptor.getOptimisticLockingPolicy();
            cacheKey.setWriteLockValue(policy.getValueToPutInCache(databaseRow, session));
        }
    }

    /**
     * Return a container which contains the instances of the receivers javaClass.
     * Set the fields of the instance to the values stored in the database rows.
     */
    public Object buildObjectsInto(ReadAllQuery query, List databaseRows, Object domainObjects) {
        if (databaseRows instanceof ThreadCursoredList) {
            return buildObjectsFromCursorInto(query, databaseRows, domainObjects);
        }
        int size = databaseRows.size();
        if (size > 0) {
            AbstractSession session = query.getSession();
            session.startOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
            try {
                InheritancePolicy inheritancePolicy = null;
                if (this.descriptor.hasInheritance()) {
                    inheritancePolicy = this.descriptor.getInheritancePolicy();
                }
                boolean isUnitOfWork = session.isUnitOfWork();
                boolean shouldCacheQueryResults = query.shouldCacheQueryResults();
                boolean shouldUseWrapperPolicy = query.shouldUseWrapperPolicy();
                // PERF: Avoid lazy init of join manager if no joining.
                JoinedAttributeManager joinManager = null;
                if (query.hasJoining()) {
                    joinManager = query.getJoinedAttributeManager();
                }
                if (this.descriptor.getCachePolicy().shouldPrefetchCacheKeys() && query.shouldMaintainCache() && ! query.shouldRetrieveBypassCache()){
                    Object[] pkList = new Object[size];
                    for (int i = 0; i< size; ++i){
                        pkList[i] = extractPrimaryKeyFromRow((AbstractRecord)databaseRows.get(i), session);
                    }
                    query.setPrefetchedCacheKeys(session.getIdentityMapAccessorInstance().getAllCacheKeysFromIdentityMapWithEntityPK(pkList, descriptor));
                }
                ContainerPolicy policy = query.getContainerPolicy();
                if (policy.shouldAddAll()) {
                    List domainObjectsIn = new ArrayList(size);
                    List<AbstractRecord> databaseRowsIn = new ArrayList(size);
                    for (int index = 0; index < size; index++) {
                        AbstractRecord databaseRow = (AbstractRecord)databaseRows.get(index);
                        // PERF: 1-m joining nulls out duplicate rows.
                        if (databaseRow != null) {
                            domainObjectsIn.add(buildObject(query, databaseRow, joinManager, session, this.descriptor, inheritancePolicy,
                                    isUnitOfWork, shouldCacheQueryResults, shouldUseWrapperPolicy));
                            databaseRowsIn.add(databaseRow);
                        }
                    }
                    policy.addAll(domainObjectsIn, domainObjects, session, databaseRowsIn, query, null, true);
                } else {
                    boolean quickAdd = (domainObjects instanceof Collection) && !this.hasWrapperPolicy;
                    for (int index = 0; index < size; index++) {
                        AbstractRecord databaseRow = (AbstractRecord)databaseRows.get(index);
                        // PERF: 1-m joining nulls out duplicate rows.
                        if (databaseRow != null) {
                            Object domainObject = buildObject(query, databaseRow, joinManager, session, this.descriptor, inheritancePolicy,
                                    isUnitOfWork, shouldCacheQueryResults, shouldUseWrapperPolicy);
                            if (quickAdd) {
                                ((Collection)domainObjects).add(domainObject);
                            } else {
                                policy.addInto(domainObject, domainObjects, session, databaseRow, query, null, true);
                            }
                        }

                    }
                }
            } finally {
                session.endOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
            }
        }
        return domainObjects;
    }

    /**
     * Version of buildObjectsInto method that takes call instead of rows.
     * Return a container which contains the instances of the receivers javaClass.
     * Set the fields of the instance to the values stored in the result set.
     */
    public Object buildObjectsFromResultSetInto(ReadAllQuery query, ResultSet resultSet, Vector fields, DatabaseField[] fieldsArray, Object domainObjects) throws SQLException {
        AbstractSession session = query.getSession();
        session.startOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
        try {
            boolean hasNext = resultSet.next();
            if (hasNext) {
                InheritancePolicy inheritancePolicy = null;
                if (this.descriptor.hasInheritance()) {
                    inheritancePolicy = this.descriptor.getInheritancePolicy();
                }
                boolean isUnitOfWork = session.isUnitOfWork();
                boolean shouldCacheQueryResults = query.shouldCacheQueryResults();
                boolean shouldUseWrapperPolicy = query.shouldUseWrapperPolicy();
                // PERF: Avoid lazy init of join manager if no joining.
                JoinedAttributeManager joinManager = null;
                if (query.hasJoining()) {
                    joinManager = query.getJoinedAttributeManager();
                }
                ContainerPolicy policy = query.getContainerPolicy();
                // !cp.shouldAddAll() - query with SortedListContainerPolicy - currently does not use this method
                boolean quickAdd = (domainObjects instanceof Collection) && !this.hasWrapperPolicy;
                ResultSetMetaData metaData = resultSet.getMetaData();
                ResultSetRecord row = null;
                AbstractSession executionSession = query.getExecutionSession();
                DatabaseAccessor dbAccessor = (DatabaseAccessor)query.getAccessor();
                DatabasePlatform platform = dbAccessor.getPlatform();
                boolean optimizeData = platform.shouldOptimizeDataConversion();
                if (this.isSimple) {
                    // None of the fields are relational - the row could be reused, just clear all the values.
                    row = new SimpleResultSetRecord(fields, fieldsArray, resultSet, metaData, dbAccessor, executionSession, platform, optimizeData);
                    if (this.descriptor.isDescriptorTypeAggregate()) {
                        // Aggregate Collection may have an unmapped primary key referencing the owner, the corresponding field will not be used when the object is populated and therefore may not be cleared.
                        ((SimpleResultSetRecord)row).setShouldKeepValues(true);
                    }
                }
                while (hasNext) {
                    if (!this.isSimple) {
                        row = new ResultSetRecord(fields, fieldsArray, resultSet, metaData, dbAccessor, executionSession, platform, optimizeData);
                    }
                    Object domainObject = buildObject(query, row, joinManager, session, this.descriptor, inheritancePolicy,
                            isUnitOfWork, shouldCacheQueryResults, shouldUseWrapperPolicy);
                    if (quickAdd) {
                        ((Collection)domainObjects).add(domainObject);
                    } else {
                        // query with MappedKeyMapPolicy currently does not use this method
                        policy.addInto(domainObject, domainObjects, session);
                    }

                    if (this.isSimple) {
                        ((SimpleResultSetRecord)row).reset();
                    } else {
                        if (this.shouldKeepRow) {
                            if (row.hasResultSet()) {
                                // ResultSet has not been fully triggered - that means the cached object was used.
                                // Yet the row still may be cached in a value holder (see loadBatchReadAttributes and loadJoinedAttributes methods).
                                // Remove ResultSet to avoid attempt to trigger it (already closed) when pk or fk values (already extracted) accessed when the value holder is instantiated.
                                row.removeResultSet();
                            } else {
                                row.removeNonIndirectionValues();
                            }
                        }
                    }
                    hasNext = resultSet.next();
                }
            }
        } finally {
            session.endOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
        }
        return domainObjects;
    }

    /**
     * Return a container which contains the instances of the receivers javaClass.
     * Set the fields of the instance to the values stored in the database rows.
     */
    public Object buildObjectsFromCursorInto(ReadAllQuery query, List databaseRows, Object domainObjects) {
        AbstractSession session = query.getSession();
        session.startOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
        try {
            InheritancePolicy inheritancePolicy = null;
            if (this.descriptor.hasInheritance()) {
                inheritancePolicy = this.descriptor.getInheritancePolicy();
            }
            boolean isUnitOfWork = session.isUnitOfWork();
            boolean shouldCacheQueryResults = query.shouldCacheQueryResults();
            boolean shouldUseWrapperPolicy = query.shouldUseWrapperPolicy();
            // PERF: Avoid lazy init of join manager if no joining.
            JoinedAttributeManager joinManager = null;
            if (query.hasJoining()) {
                joinManager = query.getJoinedAttributeManager();
            }
            ContainerPolicy policy = query.getContainerPolicy();
            if (policy.shouldAddAll()) {
                List domainObjectsIn = new ArrayList();
                List<AbstractRecord> databaseRowsIn = new ArrayList();
                for (Enumeration iterator = ((Vector)databaseRows).elements(); iterator.hasMoreElements(); ) {
                    AbstractRecord databaseRow = (AbstractRecord)iterator.nextElement();
                    // PERF: 1-m joining nulls out duplicate rows.
                    if (databaseRow != null) {
                        domainObjectsIn.add(buildObject(query, databaseRow, joinManager, session, this.descriptor, inheritancePolicy,
                                isUnitOfWork, shouldCacheQueryResults, shouldUseWrapperPolicy));
                        databaseRowsIn.add(databaseRow);
                    }
                }
                policy.addAll(domainObjectsIn, domainObjects, session, databaseRowsIn, query, null, true);
            } else {
                boolean quickAdd = (domainObjects instanceof Collection) && !this.hasWrapperPolicy;
                for (Enumeration iterator = ((Vector)databaseRows).elements(); iterator.hasMoreElements(); ) {
                    AbstractRecord databaseRow = (AbstractRecord)iterator.nextElement();
                    // PERF: 1-m joining nulls out duplicate rows.
                    if (databaseRow != null) {
                        Object domainObject = buildObject(query, databaseRow, joinManager, session, this.descriptor, inheritancePolicy,
                                isUnitOfWork, shouldCacheQueryResults, shouldUseWrapperPolicy);
                        if (quickAdd) {
                            ((Collection)domainObjects).add(domainObject);
                        } else {
                            policy.addInto(domainObject, domainObjects, session, databaseRow, query, null, true);
                        }
                    }
                }
            }
        } finally {
            session.endOperationProfile(SessionProfiler.ObjectBuilding, query, SessionProfiler.ALL);
        }
        return domainObjects;
    }

    /**
     * Build the primary key expression for the secondary table.
     */
    public Expression buildPrimaryKeyExpression(DatabaseTable table) throws DescriptorException {
        if (this.descriptor.getTables().firstElement().equals(table)) {
            return getPrimaryKeyExpression();
        }

        Map<DatabaseField, DatabaseField> keyMapping = this.descriptor.getAdditionalTablePrimaryKeyFields().get(table);
        if (keyMapping == null) {
            throw DescriptorException.multipleTablePrimaryKeyNotSpecified(this.descriptor);
        }

        ExpressionBuilder builder = new ExpressionBuilder();
        Expression expression = null;
        for (Iterator<DatabaseField> primaryKeyEnum = keyMapping.values().iterator(); primaryKeyEnum.hasNext();) {
            DatabaseField field = primaryKeyEnum.next();
            expression = (builder.getField(field).equal(builder.getParameter(field))).and(expression);
        }

        return expression;
    }

    /**
     * Build the primary key expression from the specified primary key values.
     */
    public Expression buildPrimaryKeyExpressionFromKeys(Object primaryKey, AbstractSession session) {
        Expression builder = new ExpressionBuilder();
        List<DatabaseField> primaryKeyFields = this.descriptor.getPrimaryKeyFields();

        if (this.descriptor.getCachePolicy().getCacheKeyType() == CacheKeyType.ID_VALUE) {
            return builder.getField(primaryKeyFields.get(0)).equal(primaryKey);
        }
        Expression expression = null;
        int size = primaryKeyFields.size();
        Object[] primaryKeyValues = null;
        if (primaryKey == null) {
            primaryKeyValues = new Object[size];
        } else {
            primaryKeyValues = ((CacheId)primaryKey).getPrimaryKey();
        }
        for (int index = 0; index < size; index++) {
            Object value = primaryKeyValues[index];
            DatabaseField field = primaryKeyFields.get(index);
            if (value != null) {
                Expression subExpression = builder.getField(field).equal(value);
                expression = subExpression.and(expression);
            }
        }

        return expression;
    }

    /**
     * Build the primary key expression from the specified domain object.
     */
    public Expression buildPrimaryKeyExpressionFromObject(Object domainObject, AbstractSession session) {
        return buildPrimaryKeyExpressionFromKeys(extractPrimaryKeyFromObject(domainObject, session), session);
    }

    /**
     * Build the row representation of an object.
     */
    public AbstractRecord buildRow(Object object, AbstractSession session, WriteType writeType) {
        return buildRow(createRecord(session), object, session, writeType);
    }

    /**
     * Build the row representation of an object.
     */
    public AbstractRecord buildRow(AbstractRecord databaseRow, Object object, AbstractSession session, WriteType writeType) {
        // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
        List<DatabaseMapping> mappings = this.descriptor.getMappings();
        int mappingsSize = mappings.size();
        for (int index = 0; index < mappingsSize; index++) {
            DatabaseMapping mapping = mappings.get(index);
            mapping.writeFromObjectIntoRow(object, databaseRow, session, writeType);
        }

        // If this descriptor is involved in inheritance add the class type.
        if (this.descriptor.hasInheritance()) {
            this.descriptor.getInheritancePolicy().addClassIndicatorFieldToRow(databaseRow);
        }

        // If this descriptor has multiple tables then we need to append the primary keys for
        // the non default tables.
        if (this.descriptor.hasMultipleTables() && !this.descriptor.isAggregateDescriptor()) {
            addPrimaryKeyForNonDefaultTable(databaseRow, object, session);
        }

        // If the session uses multi-tenancy, add the tenant id field.
        if (getDescriptor().hasMultitenantPolicy()) {
            getDescriptor().getMultitenantPolicy().addFieldsToRow(databaseRow, session);
        }

        return databaseRow;
    }
    /**
     * Build the row representation of the object for update. The row built does not
     * contain entries for uninstantiated attributes.
     */
    public AbstractRecord buildRowForShallowInsert(Object object, AbstractSession session) {
        return buildRowForShallowInsert(createRecord(session), object, session);
    }

    /**
     * Build the row representation of the object for update. The row built does not
     * contain entries for uninstantiated attributes.
     */
    public AbstractRecord buildRowForShallowInsert(AbstractRecord databaseRow, Object object, AbstractSession session) {
        // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
        List<DatabaseMapping> mappings = this.descriptor.getMappings();
        int mappingsSize = mappings.size();
        for (int index = 0; index < mappingsSize; index++) {
            DatabaseMapping mapping = mappings.get(index);
            mapping.writeFromObjectIntoRowForShallowInsert(object, databaseRow, session);
        }

        // If this descriptor is involved in inheritance add the class type.
        if (this.descriptor.hasInheritance()) {
            this.descriptor.getInheritancePolicy().addClassIndicatorFieldToRow(databaseRow);
        }

        // If this descriptor has multiple tables then we need to append the primary keys for
        // the non default tables.
        if (!this.descriptor.isAggregateDescriptor()) {
            addPrimaryKeyForNonDefaultTable(databaseRow, object, session);
        }

        // If the session uses multi-tenancy, add the tenant id field.
        if (getDescriptor().hasMultitenantPolicy()) {
            getDescriptor().getMultitenantPolicy().addFieldsToRow(databaseRow, session);
        }

        return databaseRow;
    }

    /**
     * Build the row representation of the object that contains only the fields nullified by shallow insert.
     */
    public AbstractRecord buildRowForUpdateAfterShallowInsert(Object object, AbstractSession session, DatabaseTable table) {
        return buildRowForUpdateAfterShallowInsert(createRecord(session), object, session, table);
    }

    /**
     * Build the row representation of the object that contains only the fields nullified by shallow insert.
     */
    public AbstractRecord buildRowForUpdateAfterShallowInsert(AbstractRecord databaseRow, Object object, AbstractSession session, DatabaseTable table) {
        for (DatabaseMapping mapping : this.descriptor.getMappings()) {
            mapping.writeFromObjectIntoRowForUpdateAfterShallowInsert(object, databaseRow, session, table);
        }
        return databaseRow;
    }

    /**
     * Build the row representation of the object that contains only the fields nullified by shallow insert, with all values set to null.
     */
    public AbstractRecord buildRowForUpdateBeforeShallowDelete(Object object, AbstractSession session, DatabaseTable table) {
        return buildRowForUpdateBeforeShallowDelete(createRecord(session), object, session, table);
    }

    /**
     * Build the row representation of the object that contains only the fields nullified by shallow insert, with all values set to null.
     */
    public AbstractRecord buildRowForUpdateBeforeShallowDelete(AbstractRecord databaseRow, Object object, AbstractSession session, DatabaseTable table) {
        for (DatabaseMapping mapping : this.descriptor.getMappings()) {
            mapping.writeFromObjectIntoRowForUpdateBeforeShallowDelete(object, databaseRow, session, table);
        }
        return databaseRow;
    }

    /**
     * Build the row representation of an object.
     * This is only used for aggregates.
     */
    public AbstractRecord buildRowWithChangeSet(AbstractRecord databaseRow, ObjectChangeSet objectChangeSet, AbstractSession session, WriteType writeType) {
        List<ChangeRecord> changes = (List)objectChangeSet.getChanges();
        int size = changes.size();
        for (int index = 0; index < size; index++) {
            ChangeRecord changeRecord = changes.get(index);
            DatabaseMapping mapping = changeRecord.getMapping();
            mapping.writeFromObjectIntoRowWithChangeRecord(changeRecord, databaseRow, session, writeType);
        }

        // If this descriptor is involved in inheritance add the class type.
        if (this.descriptor.hasInheritance()) {
            this.descriptor.getInheritancePolicy().addClassIndicatorFieldToRow(databaseRow);
        }

        // If the session uses multi-tenancy, add the tenant id field.
        if (getDescriptor().hasMultitenantPolicy()) {
            getDescriptor().getMultitenantPolicy().addFieldsToRow(databaseRow, session);
        }

        return databaseRow;
    }

    /**
     * Build the row representation of an object. The row built is used only for translations
     * for the expressions in the expression framework.
     */
    public AbstractRecord buildRowForTranslation(Object object, AbstractSession session) {
        AbstractRecord databaseRow = createRecord(session);
        List<DatabaseMapping> primaryKeyMappings = getPrimaryKeyMappings();
        int size = primaryKeyMappings.size();
        for (int index = 0; index < size; index++) {
            DatabaseMapping mapping = primaryKeyMappings.get(index);
            if (mapping != null) {
                mapping.writeFromObjectIntoRow(object, databaseRow, session, WriteType.UNDEFINED);
            }
        }

        // If this descriptor has multiple tables then we need to append the primary keys for
        // the non default tables, this is require for m-m, dc defined in the Builder that prefixes the wrong table name.
        // Ideally the mappings should take part in building the translation row so they can add required values.
        if (this.descriptor.hasMultipleTables()) {
            addPrimaryKeyForNonDefaultTable(databaseRow, object, session);
        }

        return databaseRow;
    }

    /**
     * Build the row representation of the object for update. The row built does not
     * contain entries for unchanged attributes.
     */
    public AbstractRecord buildRowForUpdate(WriteObjectQuery query) {
        AbstractRecord databaseRow = createRecord(query.getSession());
        return buildRowForUpdate(databaseRow, query);
    }

    /**
     * Build into the row representation of the object for update. The row does not
     * contain entries for unchanged attributes.
     */
    public AbstractRecord buildRowForUpdate(AbstractRecord databaseRow, WriteObjectQuery query) {
        for (Iterator<DatabaseMapping> mappings = getNonPrimaryKeyMappings().iterator(); mappings.hasNext();) {
            DatabaseMapping mapping = mappings.next();
            mapping.writeFromObjectIntoRowForUpdate(query, databaseRow);
        }

        // If this descriptor is involved in inheritance and is an Aggregate, add the class type.
        // Added Nov 8, 2000 Mostly by PWK but also JED
        // Prs 24801
        // Modified  Dec 11, 2000 TGW with assistance from PWK
        // Prs 27554
        if (this.descriptor.hasInheritance() && this.descriptor.isAggregateDescriptor()) {
            if (query.getObject() != null) {
                if (query.getBackupClone() == null) {
                    this.descriptor.getInheritancePolicy().addClassIndicatorFieldToRow(databaseRow);
                } else {
                    if (!query.getObject().getClass().equals(query.getBackupClone().getClass())) {
                        this.descriptor.getInheritancePolicy().addClassIndicatorFieldToRow(databaseRow);
                    }
                }
            }
        }

        // If the session uses multi-tenancy, add the tenant id field.
        if (getDescriptor().hasMultitenantPolicy()) {
            getDescriptor().getMultitenantPolicy().addFieldsToRow(databaseRow, query.getExecutionSession());
        }

        return databaseRow;
    }

    /**
     * Build the row representation of the object for update. The row built does not
     * contain entries for uninstantiated attributes.
     */
    public AbstractRecord buildRowForUpdateWithChangeSet(WriteObjectQuery query) {
        AbstractRecord databaseRow = createRecord(query.getSession());
        AbstractSession session = query.getSession();
        List<org.eclipse.persistence.sessions.changesets.ChangeRecord> changes = query.getObjectChangeSet().getChanges();
        int size = changes.size();
        for (int index = 0; index < size; index++) {
            ChangeRecord changeRecord = (ChangeRecord)changes.get(index);
            DatabaseMapping mapping = changeRecord.getMapping();
            mapping.writeFromObjectIntoRowWithChangeRecord(changeRecord, databaseRow, session, WriteType.UPDATE);
        }

        return databaseRow;
    }

    /**
     * Build the row representation of an object.
     */
    public AbstractRecord buildRowForWhereClause(ObjectLevelModifyQuery query) {
        AbstractRecord databaseRow = createRecord(query.getSession());

        // EL bug 319759
        if (query.isUpdateObjectQuery()) {
            query.setShouldValidateUpdateCallCacheUse(true);
        }

        for (Iterator<DatabaseMapping> mappings = this.descriptor.getMappings().iterator();
             mappings.hasNext();) {
            DatabaseMapping mapping = mappings.next();
            mapping.writeFromObjectIntoRowForWhereClause(query, databaseRow);
        }

        // If this descriptor has multiple tables then we need to append the primary keys for
        // the non default tables.
        if (!this.descriptor.isAggregateDescriptor()) {
            addPrimaryKeyForNonDefaultTable(databaseRow);
        }

        return databaseRow;
    }

    /**
     * Build the row from the primary key values.
     */
    public AbstractRecord writeIntoRowFromPrimaryKeyValues(AbstractRecord row, Object primaryKey, AbstractSession session, boolean convert) {
        List<DatabaseField> primaryKeyFields = this.descriptor.getPrimaryKeyFields();
        if (this.descriptor.getCachePolicy().getCacheKeyType() == CacheKeyType.ID_VALUE) {
            DatabaseField field = primaryKeyFields.get(0);
            Object value = primaryKey;
            value = session.getPlatform(this.descriptor.getJavaClass()).getConversionManager().convertObject(value, field.getType());
            row.put(field, value);
            return row;
        }
        int size = primaryKeyFields.size();
        Object[] primaryKeyValues = ((CacheId)primaryKey).getPrimaryKey();
        for (int index = 0; index < size; index++) {
            DatabaseField field = primaryKeyFields.get(index);
            Object value = primaryKeyValues[index];
            value = session.getPlatform(this.descriptor.getJavaClass()).getConversionManager().convertObject(value, field.getType());
            row.put(field, value);
        }

        return row;
    }

    /**
     * Build the row from the primary key values.
     */
    public AbstractRecord buildRowFromPrimaryKeyValues(Object key, AbstractSession session) {
        AbstractRecord databaseRow = createRecord(this.descriptor.getPrimaryKeyFields().size(), session);
        return writeIntoRowFromPrimaryKeyValues(databaseRow, key, session, true);
    }

    /**
     * Build the row of all of the fields used for insertion.
     */
    public AbstractRecord buildTemplateInsertRow(AbstractSession session) {
        AbstractRecord databaseRow = createRecord(session);
        buildTemplateInsertRow(session, databaseRow);
        return databaseRow;
    }

    public void buildTemplateInsertRow(AbstractSession session, AbstractRecord databaseRow) {
        for (Iterator<DatabaseMapping> mappings = this.descriptor.getMappings().iterator();
             mappings.hasNext();) {
            DatabaseMapping mapping = mappings.next();
            mapping.writeInsertFieldsIntoRow(databaseRow, session);
        }

        // If this descriptor is involved in inheritance add the class type.
        if (this.descriptor.hasInheritance()) {
            this.descriptor.getInheritancePolicy().addClassIndicatorFieldToInsertRow(databaseRow);
        }

        // If this descriptor has multiple tables then we need to append the primary keys for
        // the non default tables.
        if (!this.descriptor.isAggregateDescriptor()) {
            addPrimaryKeyForNonDefaultTable(databaseRow);
        }

        if (this.descriptor.usesOptimisticLocking()) {
            this.descriptor.getOptimisticLockingPolicy().addLockFieldsToUpdateRow(databaseRow, session);
        }

        // If the session uses multi-tenancy, add the tenant id field.
        if (this.descriptor.hasMultitenantPolicy()) {
            this.descriptor.getMultitenantPolicy().addFieldsToRow(databaseRow, session);
        }

        if (this.descriptor.hasSerializedObjectPolicy()) {
            databaseRow.put(this.descriptor.getSerializedObjectPolicy().getField(), null);
        }

        // remove any fields from the databaseRow
        trimFieldsForInsert(session, databaseRow);
    }

    /**
     * INTERNAL
     * Remove a potential sequence number field and invoke the ReturningPolicy trimModifyRowsForInsert method
     */
    public void trimFieldsForInsert(AbstractSession session, AbstractRecord databaseRow) {
        ClassDescriptor descriptor = this.descriptor;
        if (descriptor.usesSequenceNumbers() && descriptor.getSequence().shouldAcquireValueAfterInsert()) {
            databaseRow.remove(descriptor.getSequenceNumberField());
        }
        if (descriptor.hasReturningPolicy()) {
            descriptor.getReturningPolicy().trimModifyRowForInsert(databaseRow);
        }
    }

    /**
     * Build the row representation of the object for update. The row built does not
     * contain entries for uninstantiated attributes.
     */
    public AbstractRecord buildTemplateUpdateRow(AbstractSession session) {
        AbstractRecord databaseRow = createRecord(session);

        for (Iterator<DatabaseMapping> mappings = getNonPrimaryKeyMappings().iterator();
             mappings.hasNext();) {
            DatabaseMapping mapping = mappings.next();
            mapping.writeUpdateFieldsIntoRow(databaseRow, session);
        }

        if (this.descriptor.usesOptimisticLocking()) {
            this.descriptor.getOptimisticLockingPolicy().addLockFieldsToUpdateRow(databaseRow, session);
        }

        if (this.descriptor.hasSerializedObjectPolicy()) {
            databaseRow.put(this.descriptor.getSerializedObjectPolicy().getField(), null);
        }

        return databaseRow;
    }

    /**
     * Build and return the expression to use as the where clause to an update object.
     * The row is passed to allow the version number to be extracted from it.
     */
    public Expression buildUpdateExpression(DatabaseTable table, AbstractRecord transactionRow, AbstractRecord modifyRow) {
        // Only the first table must use the lock check.
        Expression primaryKeyExpression = buildPrimaryKeyExpression(table);
        if (this.descriptor.usesOptimisticLocking()) {
            return this.descriptor.getOptimisticLockingPolicy().buildUpdateExpression(table, primaryKeyExpression, transactionRow, modifyRow);
        } else {
            return primaryKeyExpression;
        }
    }

    /**
     * INTERNAL:
     * Build just the primary key mappings into the object.
     */
    public void buildPrimaryKeyAttributesIntoObject(Object original, AbstractRecord databaseRow, ObjectBuildingQuery query, AbstractSession session) throws DatabaseException, QueryException {
        // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
        List<DatabaseMapping> mappings = this.primaryKeyMappings;
        int mappingsSize = mappings.size();
        for (int i = 0; i < mappingsSize; i++) {
            DatabaseMapping mapping = mappings.get(i);
            mapping.buildShallowOriginalFromRow(databaseRow, original, null, query, session);
        }
    }

    /**
     * INTERNAL:
     * For reading through the write connection when in transaction,
     * We need a partially populated original, so that we
     * can build a clone using the copy policy, even though we can't
     * put this original in the shared cache yet; just build a
     * shallow original (i.e. just enough to copy over the primary
     * key and some direct attributes) and keep it on the UOW.
     */
    public void buildAttributesIntoShallowObject(Object original, AbstractRecord databaseRow, ObjectBuildingQuery query) throws DatabaseException, QueryException {
        AbstractSession executionSession = query.getSession().getExecutionSession(query);

        // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
        List<DatabaseMapping> pkMappings = getPrimaryKeyMappings();
        int mappingsSize = pkMappings.size();
        for (int i = 0; i < mappingsSize; i++) {
            DatabaseMapping mapping = pkMappings.get(i);

            //if (query.shouldReadMapping(mapping)) {
            if (!mapping.isAbstractColumnMapping()) {
                mapping.buildShallowOriginalFromRow(databaseRow, original, null, query, executionSession);
            }
        }
        List<DatabaseMapping> mappings = this.descriptor.getMappings();
        mappingsSize = mappings.size();
        for (int i = 0; i < mappingsSize; i++) {
            DatabaseMapping mapping = mappings.get(i);

            //if (query.shouldReadMapping(mapping)) {
            if (mapping.isAbstractColumnMapping()) {
                mapping.buildShallowOriginalFromRow(databaseRow, original, null, query, executionSession);
            }
        }
    }

    /**
     * INTERNAL:
     * For reading through the write connection when in transaction,
     * populate the clone directly from the database row.
     */
    public void buildAttributesIntoWorkingCopyClone(Object clone, CacheKey sharedCacheKey, ObjectBuildingQuery query, JoinedAttributeManager joinManager, AbstractRecord databaseRow, UnitOfWorkImpl unitOfWork, boolean forRefresh) throws DatabaseException, QueryException {
        if (this.descriptor.hasSerializedObjectPolicy() && query.shouldUseSerializedObjectPolicy()) {
            if (buildAttributesIntoWorkingCopyCloneSOP(clone, sharedCacheKey, query, joinManager, databaseRow, unitOfWork, forRefresh)) {
                return;
            }
        }
        // PERF: Cache if all mappings should be read.
        boolean readAllMappings = query.shouldReadAllMappings();
        List<DatabaseMapping> mappings = this.descriptor.getMappings();
        int size = mappings.size();
        FetchGroup executionFetchGroup = query.getExecutionFetchGroup(this.descriptor);
        for (int index = 0; index < size; index++) {
            DatabaseMapping mapping = mappings.get(index);
            if (readAllMappings || query.shouldReadMapping(mapping, executionFetchGroup)) {
                mapping.buildCloneFromRow(databaseRow, joinManager, clone, sharedCacheKey, query, unitOfWork, unitOfWork);
            }
        }

        // PERF: Avoid events if no listeners.
        if (this.descriptor.getEventManager().hasAnyEventListeners()) {
            postBuildAttributesIntoWorkingCopyCloneEvent(clone, databaseRow, query, unitOfWork, forRefresh);
        }
    }

    /**
     * For reading through the write connection when in transaction,
     * populate the clone directly from the database row.
     * Should not be called unless (this.descriptor.hasSerializedObjectPolicy() &amp;&amp; query.shouldUseSerializedObjectPolicy())
     * This method populates the object only in if some mappings potentially should be read using sopObject and other mappings - not using it.
     * That happens when the row has been just read from the database and potentially has serialized object still in deserialized bits as a field value.
     * Note that  clone == sopObject is the same case, but (because clone has to be set into cache beforehand) extraction of sopObject
     * from bit was done right before this method is called.
     * If attempt to deserialize sopObject from bits has failed, but SOP was setup to allow recovery
     * (all mapped all fields/value mapped to the object were read, not just those excluded from SOP)
     * then fall through to buildAttributesIntoWorkingCopyClone.
     * Nothing should be done if sopObject is not null, but clone != sopObject:
     * the only way to get into this case should be with original query not maintaining cache,
     * through a back reference to the original object, which is already being built (or has been built).
     * @return whether the object has been populated with attributes, if not then buildAttributesIntoWorkingCopyClone should be called.
     */
    protected boolean buildAttributesIntoWorkingCopyCloneSOP(Object clone, CacheKey sharedCacheKey, ObjectBuildingQuery query, JoinedAttributeManager joinManager, AbstractRecord databaseRow, UnitOfWorkImpl unitOfWork, boolean forRefresh) throws DatabaseException {
        Object sopObject = databaseRow.getSopObject();
        if (clone == sopObject) {
            // clone is sopObject
            // PERF: Cache if all mappings should be read.
            boolean readAllMappings = query.shouldReadAllMappings();
            FetchGroup executionFetchGroup = query.getExecutionFetchGroup(this.descriptor);
            for (DatabaseMapping mapping : this.descriptor.getMappings()) {
                if (readAllMappings || query.shouldReadMapping(mapping, executionFetchGroup)) {
                    // to avoid re-setting the same attribute value to domainObject
                    // only populate if either mapping (possibly nested) may reference entity or mapping does not use sopObject
                    if (mapping.hasNestedIdentityReference() || mapping.isOutOnlySopObject()) {
                        if (mapping.isOutSopObject()) {
                            // the mapping should be processed as if there is no sopObject
                            databaseRow.setSopObject(null);
                            mapping.buildCloneFromRow(databaseRow, joinManager, clone, sharedCacheKey, query, unitOfWork, unitOfWork);
                        } else {
                            databaseRow.setSopObject(sopObject);
                            mapping.buildCloneFromRow(databaseRow, joinManager, clone, sharedCacheKey, query, unitOfWork, unitOfWork);
                        }
                    }
                }
            }
            // PERF: Avoid events if no listeners.
            if (this.descriptor.hasEventManager()) {
                postBuildAttributesIntoWorkingCopyCloneEvent(clone, databaseRow, query, unitOfWork, forRefresh);
            }
            // sopObject has been processed by all relevant mappings, no longer required.
            databaseRow.setSopObject(null);
            return true;
        } else {
            if (sopObject == null) {
                // serialized sopObject is a value corresponding to sopField in the row, row.sopObject==null;
                // the following line sets deserialized sopObject into row.sopObject variable and sets sopField's value to null;
                sopObject = this.descriptor.getSerializedObjectPolicy().getObjectFromRow(databaseRow, unitOfWork, (ObjectLevelReadQuery)query);
                if (sopObject != null) {
                    // PERF: Cache if all mappings should be read.
                    boolean readAllMappings = query.shouldReadAllMappings();
                    FetchGroup executionFetchGroup = query.getExecutionFetchGroup(this.descriptor);
                    for (DatabaseMapping mapping : this.descriptor.getMappings()) {
                        if (readAllMappings || query.shouldReadMapping(mapping, executionFetchGroup)) {
                            if (mapping.isOutSopObject()) {
                                // the mapping should be processed as if there is no sopObject
                                databaseRow.setSopObject(null);
                                mapping.buildCloneFromRow(databaseRow, joinManager, clone, sharedCacheKey, query, unitOfWork, unitOfWork);
                            } else {
                                databaseRow.setSopObject(sopObject);
                                mapping.buildCloneFromRow(databaseRow, joinManager, clone, sharedCacheKey, query, unitOfWork, unitOfWork);
                            }
                        }
                    }
                    // PERF: Avoid events if no listeners.
                    if (this.descriptor.hasEventManager()) {
                        postBuildAttributesIntoWorkingCopyCloneEvent(clone, databaseRow, query, unitOfWork, forRefresh);
                    }
                    // sopObject has been processed by all relevant mappings, no longer required.
                    databaseRow.setSopObject(null);
                    return true;
                } else {
                    // SOP failed to create sopObject, but exception hasn't been thrown.
                    // That means recovery is possible - fall through to to buildAttributesIntoWorkingCopyClone
                    return false;
                }
            } else {
                // A mapping under SOP can't have another SOP on its reference descriptor,
                // but that's what seem to be happening.
                // The only way to get here should be with original query not maintaining cache,
                // through a back reference to the original object, which is already being built (or has been built).
                // Leave without building.
                return true;
            }
        }
    }

    protected void postBuildAttributesIntoWorkingCopyCloneEvent(Object clone, AbstractRecord databaseRow, ObjectBuildingQuery query, UnitOfWorkImpl unitOfWork, boolean forRefresh) {
        // Need to run post build or refresh selector, currently check with the query for this,
        // I'm not sure which should be called it case of refresh building a new object, currently refresh is used...
        DescriptorEvent event = new DescriptorEvent(clone);
        event.setQuery(query);
        event.setSession(unitOfWork);
        event.setDescriptor(this.descriptor);
        event.setRecord(databaseRow);
        if (forRefresh) {
            event.setEventCode(DescriptorEventManager.PostRefreshEvent);
        } else {
            event.setEventCode(DescriptorEventManager.PostBuildEvent);
            //fire a postBuildEvent then the postCloneEvent
            unitOfWork.deferEvent(event);

            event = new DescriptorEvent(clone);
            event.setQuery(query);
            event.setSession(unitOfWork);
            event.setDescriptor(this.descriptor);
            event.setRecord(databaseRow);
            //bug 259404: ensure postClone is called for objects built directly into the UnitOfWork
            //in this case, the original is the clone
            event.setOriginalObject(clone);
            event.setEventCode(DescriptorEventManager.PostCloneEvent);
        }
        unitOfWork.deferEvent(event);
    }

    /**
     * INTERNAL:
     * Builds a working copy clone directly from the database row.
     * This is the key method that allows us to execute queries against a
     * UnitOfWork while in transaction and not cache the results in the shared
     * cache.  This is because we might violate transaction isolation by
     * putting uncommitted versions of objects in the shared cache.
     */
    protected Object buildWorkingCopyCloneFromRow(ObjectBuildingQuery query, JoinedAttributeManager joinManager, AbstractRecord databaseRow, UnitOfWorkImpl unitOfWork, Object primaryKey, CacheKey preFetchedCacheKey) throws DatabaseException, QueryException {
        ClassDescriptor descriptor = this.descriptor;

        // If the clone already exists then it may only need to be refreshed or returned.
        // We call directly on the identity map to avoid going to the parent,
        // registering if found, and wrapping the result.
        // Acquire or create the cache key as is need once the object is build anyway.
        CacheKey unitOfWorkCacheKey = unitOfWork.getIdentityMapAccessorInstance().getIdentityMapManager().acquireLock(primaryKey, descriptor.getJavaClass(), false, descriptor, true);
        Object workingClone = unitOfWorkCacheKey.getObject();
        FetchGroup fetchGroup = query.getExecutionFetchGroup(descriptor);
        FetchGroupManager fetchGroupManager = descriptor.getFetchGroupManager();
        try {
            // If there is a clone, and it is not a refresh then just return it.
            boolean wasAClone = workingClone != null;
            boolean isARefresh = query.shouldRefreshIdentityMapResult() || (query.isLockQuery() && (!wasAClone || !query.isClonePessimisticLocked(workingClone, unitOfWork)));
            // Also need to refresh if the clone is a partial object and query requires more than its fetch group.
            if (wasAClone && fetchGroupManager != null && (fetchGroupManager.isPartialObject(workingClone) && (!fetchGroupManager.isObjectValidForFetchGroup(workingClone, fetchGroupManager.getEntityFetchGroup(fetchGroup))))) {
                isARefresh = true;
            }
            if (wasAClone && (!isARefresh)) {
                return workingClone;
            }

            boolean wasAnOriginal = false;
            boolean isIsolated = descriptor.getCachePolicy().shouldIsolateObjectsInUnitOfWork()
                    || (descriptor.shouldIsolateObjectsInUnitOfWorkEarlyTransaction() && unitOfWork.wasTransactionBegunPrematurely());

            Object original = null;
            CacheKey originalCacheKey = null;
            // If not refreshing can get the object from the cache.
            if ((!isARefresh) && (!isIsolated) && !query.shouldRetrieveBypassCache() && !unitOfWork.shouldReadFromDB() && (!unitOfWork.shouldForceReadFromDB(query, primaryKey))) {
                AbstractSession session = unitOfWork.getParentIdentityMapSession(query);
                if (preFetchedCacheKey == null){
                    originalCacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(primaryKey, descriptor.getJavaClass(), descriptor, false);
                }else{
                    originalCacheKey = preFetchedCacheKey;
                    originalCacheKey.acquireLock(query);
                }
                if (originalCacheKey != null) {
                    // PERF: Read-lock is not required on object as unit of work will acquire this on clone and object cannot gc and object identity is maintained.
                    original = originalCacheKey.getObject();
                    wasAnOriginal = original != null;
                    // If the original is invalid or always refresh then need to refresh.
                    isARefresh = wasAnOriginal && (descriptor.shouldAlwaysRefreshCache() || descriptor.getCacheInvalidationPolicy().isInvalidated(originalCacheKey, query.getExecutionTime()));
                    // Otherwise can just register the cached original object and return it.
                    if (wasAnOriginal && (!isARefresh)){
                        if (descriptor.getCachePolicy().isSharedIsolation() || !descriptor.shouldIsolateProtectedObjectsInUnitOfWork()) {
                            // using shared isolation and the original is from the shared cache
                            // or using protected isolation and isolated client sessions
                            return unitOfWork.cloneAndRegisterObject(original, originalCacheKey, unitOfWorkCacheKey, descriptor);
                        }
                    }
                }
            }

            if (!wasAClone) {
                // This code is copied from UnitOfWork.cloneAndRegisterObject.  Unlike
                // that method we don't need to lock the shared cache, because
                // are not building off of an original in the shared cache.
                // The copy policy is easier to invoke if we have an original.
                if (wasAnOriginal && !query.shouldRetrieveBypassCache()) {
                    workingClone = instantiateWorkingCopyClone(original, unitOfWork);
                    // intentionally put nothing in clones to originals, unless really was one.
                    unitOfWork.getCloneToOriginals().put(workingClone, original);
                } else {
                    if (descriptor.hasSerializedObjectPolicy() && query.shouldUseSerializedObjectPolicy() && !databaseRow.hasSopObject()) {
                        // serialized sopObject is a value corresponding to sopField in the row, row.sopObject==null;
                        // the following line sets deserialized sopObject into row.sopObject variable and sets sopField's value to null;
                        workingClone = descriptor.getSerializedObjectPolicy().getObjectFromRow(databaseRow, unitOfWork, (ObjectLevelReadQuery)query);
                    }
                    if (workingClone == null) {
                        // What happens if a copy policy is defined is not pleasant.
                        //workingClone = instantiateWorkingCopyCloneFromRow(databaseRow, query, primaryKey, unitOfWork);
                        // Create a new instance instead. The object is populated later by buildAttributesIntoWorkingCopyClone method.
                        workingClone = buildNewInstance();
                    }
                }

                // This must be registered before it is built to avoid cycles.
                // The version and read is set below in copyQueryInfoToCacheKey.
                unitOfWorkCacheKey.setObject(workingClone);

                // This must be registered before it is built to avoid cycles.
                unitOfWork.getCloneMapping().put(workingClone, workingClone);
            }

            // Must avoid infinite loops while refreshing.
            if (wasAClone && (unitOfWorkCacheKey.getLastUpdatedQueryId() >= query.getQueryId())) {
                return workingClone;
            }
            copyQueryInfoToCacheKey(unitOfWorkCacheKey, query, databaseRow, unitOfWork, descriptor);

            ObjectChangePolicy policy = descriptor.getObjectChangePolicy();
            // If it was a clone the change listener must be cleared after.
            if (!wasAClone) {
                // The change listener must be set before building the clone as aggregate/collections need the listener.
                policy.setChangeListener(workingClone, unitOfWork, descriptor);
            }

            // Turn it 'off' to prevent unwanted events.
            policy.dissableEventProcessing(workingClone);
            if (isARefresh && fetchGroupManager != null) {
                fetchGroupManager.setObjectFetchGroup(workingClone, query.getExecutionFetchGroup(this.descriptor), unitOfWork);
            }
            if (!unitOfWork.wasTransactionBegunPrematurely() && descriptor.getCachePolicy().isProtectedIsolation() && !isIsolated && !query.shouldStoreBypassCache()) {
                // we are at this point because we have isolated protected entities to the UnitOfWork
                // we should ensure that we populate the cache as well.
                originalCacheKey = (CacheKey) buildObject(true, query, databaseRow, unitOfWork.getParentIdentityMapSession(descriptor, false, true), primaryKey, preFetchedCacheKey, descriptor, joinManager);
            }
            //If we are unable to access the shared cache because of any of the above settings at this point
            // the cachekey will be null so the attribute building will not be able to access the shared cache.
            if (isARefresh){
                //if we need to refresh the UOW then remove the cache key and the clone will be rebuilt not using any of the
                //cache.  This should be updated to force the buildAttributesIntoWorkingCopyClone to refresh the objects
                originalCacheKey = null;
            }
            // Build/refresh the clone from the row.
            buildAttributesIntoWorkingCopyClone(workingClone, originalCacheKey, query, joinManager, databaseRow, unitOfWork, wasAClone);
            // Set fetch group after building object if not a refresh to avoid checking fetch during building.
            if ((!isARefresh) && fetchGroupManager != null) {
               if (wasAnOriginal) {
                 //485984: Save the FetchGroup from the original
                   fetchGroupManager.setObjectFetchGroup(workingClone, fetchGroupManager.getObjectFetchGroup(original), unitOfWork);
               } else {
                   fetchGroupManager.setObjectFetchGroup(workingClone, query.getExecutionFetchGroup(this.descriptor), unitOfWork);
               }
            }
            Object backupClone = policy.buildBackupClone(workingClone, this, unitOfWork);

            // If it was a clone the change listener must be cleared.
            if (wasAClone) {
                policy.clearChanges(workingClone, unitOfWork, descriptor, isARefresh);
            }
            policy.enableEventProcessing(workingClone);
            unitOfWork.getCloneMapping().put(workingClone, backupClone);
            query.recordCloneForPessimisticLocking(workingClone, unitOfWork);
            // PERF: Cache the primary key if implements PersistenceEntity.
            if (workingClone instanceof PersistenceEntity) {
                ((PersistenceEntity)workingClone)._persistence_setId(primaryKey);
            }
        } finally {
            unitOfWorkCacheKey.release();
        }
        instantiateEagerMappings(workingClone, unitOfWork);

        return workingClone;
    }

    /**
     * INTERNAL:
     * Builds a working copy clone directly from a result set.
     * PERF: This method is optimized for a specific case of building objects
     * so can avoid many of the normal checks, only queries that have this criteria
     * can use this method of building objects.
     * This is wrapper method with semaphore logic.
     */
    public Object buildObjectFromResultSet(ObjectBuildingQuery query, JoinedAttributeManager joinManager, ResultSet resultSet, AbstractSession executionSession, DatabaseAccessor accessor, ResultSetMetaData metaData, DatabasePlatform platform, Vector fieldsList, DatabaseField[] fieldsArray) throws SQLException {
        boolean semaphoreWasAcquired = false;
        boolean useSemaphore = ConcurrencyUtil.SINGLETON.isUseSemaphoreInObjectBuilder();
        if (objectBuilderSemaphore == null) {
            objectBuilderSemaphore = new ConcurrencySemaphore(SEMAPHORE_THREAD_LOCAL_VAR, SEMAPHORE_MAX_NUMBER_THREADS, SEMAPHORE_LIMIT_MAX_NUMBER_OF_THREADS_OBJECT_BUILDING, this, "object_builder_semaphore_acquired_01");
        }
        try {
            semaphoreWasAcquired = objectBuilderSemaphore.acquireSemaphoreIfAppropriate(useSemaphore);
            return buildObjectFromResultSetInternal(query, joinManager, resultSet, executionSession, accessor, metaData, platform, fieldsList, fieldsArray);
        } finally {
            objectBuilderSemaphore.releaseSemaphoreAllowOtherThreadsToStartDoingObjectBuilding(semaphoreWasAcquired);
        }
    }

    /**
     * INTERNAL:
     * Builds a working copy clone directly from a result set.
     * PERF: This method is optimized for a specific case of building objects
     * so can avoid many of the normal checks, only queries that have this criteria
     * can use this method of building objects.
     */
    private Object buildObjectFromResultSetInternal(ObjectBuildingQuery query, JoinedAttributeManager joinManager, ResultSet resultSet, AbstractSession executionSession, DatabaseAccessor accessor, ResultSetMetaData metaData, DatabasePlatform platform, Vector fieldsList, DatabaseField[] fieldsArray) throws SQLException {
        ClassDescriptor descriptor = this.descriptor;
        int pkFieldsSize = descriptor.getPrimaryKeyFields().size();
        DatabaseMapping primaryKeyMapping = null;
        AbstractRecord row = null;
        Object[] values = null;
        Object primaryKey;
        if (isSimple && pkFieldsSize == 1) {
            primaryKeyMapping = this.primaryKeyMappings.get(0);
            primaryKey = primaryKeyMapping.valueFromResultSet(resultSet, query, executionSession, accessor, metaData, 1, platform);
        } else {
            values = new Object[fieldsArray.length];
            row = new ArrayRecord(fieldsList, fieldsArray, values);
            accessor.populateRow(fieldsArray, values, resultSet, metaData, executionSession, 0, pkFieldsSize);
            primaryKey = extractPrimaryKeyFromRow(row, executionSession);
        }

        UnitOfWorkImpl unitOfWork = null;
        AbstractSession session = executionSession;
        boolean isolated = !descriptor.getCachePolicy().isSharedIsolation();
        if (session.isUnitOfWork()) {
            unitOfWork = (UnitOfWorkImpl)executionSession;
            isolated |= unitOfWork.wasTransactionBegunPrematurely() && descriptor.shouldIsolateObjectsInUnitOfWorkEarlyTransaction();
        }

        CacheKey cacheKey = session.getIdentityMapAccessorInstance().getIdentityMapManager().acquireLock(primaryKey, descriptor.getJavaClass(), false, descriptor, query.isCacheCheckComplete());
        CacheKey cacheKeyToUse = cacheKey;
        CacheKey parentCacheKey = null;
        Object object = cacheKey.getObject();
        try {
            // Found locally in the unit of work, or session query and found in the session.
            if (object != null) {
                return object;
            }
            if ((unitOfWork != null) && !isolated) {
                // Need to lookup in the session.
                session = unitOfWork.getParentIdentityMapSession(query);
                parentCacheKey = session.getIdentityMapAccessorInstance().getIdentityMapManager().acquireLock(primaryKey, descriptor.getJavaClass(), false, descriptor, query.isCacheCheckComplete());
                cacheKeyToUse = parentCacheKey;
                object = parentCacheKey.getObject();
            }
            // If the object is not in the cache, it needs to be built, this is building in the unit of work if isolated.
            if (object == null) {
                object = buildNewInstance();
                if (unitOfWork == null) {
                    cacheKey.setObject(object);
                } else {
                    if (isolated) {
                        cacheKey.setObject(object);
                        unitOfWork.getCloneMapping().put(object, object);
                    } else {
                        parentCacheKey.setObject(object);
                    }
                }

                List<DatabaseMapping> mappings = descriptor.getMappings();
                int size = mappings.size();

                if (isSimple) {
                    int shift = descriptor.getTables().size() * pkFieldsSize;
                    if (primaryKeyMapping != null) {
                        // simple primary key - set pk directly through the mapping
                        primaryKeyMapping.setAttributeValueInObject(object, primaryKey);
                    } else {
                        // composite primary key - set pk using pkRow
                        boolean isTargetProtected = session.isProtectedSession();
                        for (int index = 0; index < pkFieldsSize; index++) {
                            DatabaseMapping mapping = mappings.get(index);
                            mapping.readFromRowIntoObject(row, joinManager, object, cacheKeyToUse, query, session, isTargetProtected);
                        }
                    }
                    // set the rest using mappings directly
                    for (int index = pkFieldsSize; index < size; index++) {
                        DatabaseMapping mapping = mappings.get(index);
                        mapping.readFromResultSetIntoObject(resultSet, object, query, session, accessor, metaData, index + shift, platform);
                    }
                } else {
                    boolean isTargetProtected = session.isProtectedSession();
                    accessor.populateRow(fieldsArray, values, resultSet, metaData, session, pkFieldsSize, fieldsArray.length);
                    for (int index = 0; index < size; index++) {
                        DatabaseMapping mapping = mappings.get(index);
                        mapping.readFromRowIntoObject(row, joinManager, object, cacheKeyToUse, query, session, isTargetProtected);
                    }
                }

                ((PersistenceEntity)object)._persistence_setId(primaryKey);
                if ((unitOfWork != null) && isolated) {
                    ObjectChangePolicy policy = descriptor.getObjectChangePolicy();
                    policy.setChangeListener(object, unitOfWork, descriptor);
                }
            }
            if ((unitOfWork != null) && !isolated) {
                // Need to clone the object in the unit of work.
                // TODO: Doesn't work all the time
                // With one setup (jpa2.performance tests) produces a shallow clone (which is good enough for isSimple==true case only),
                // in other (jpa.advanced tests) - just a brand new empty object.
                Object clone = instantiateWorkingCopyClone(object, unitOfWork);
                ((PersistenceEntity)clone)._persistence_setId(cacheKey.getKey());
                unitOfWork.getCloneMapping().put(clone, clone);
                unitOfWork.getCloneToOriginals().put(clone, object);
                cacheKey.setObject(clone);
                ObjectChangePolicy policy = descriptor.getObjectChangePolicy();
                policy.setChangeListener(clone, unitOfWork, descriptor);
                object = clone;
            }
        } finally {
            cacheKey.release();
            if (parentCacheKey != null) {
                parentCacheKey.release();
            }
        }

        return object;
    }

    /**
     * Returns a clone of itself.
     */
    @Override
    public Object clone() {
        ObjectBuilder objectBuilder = null;
        try {
            objectBuilder = (ObjectBuilder)super.clone();
        } catch (CloneNotSupportedException exception) {
            throw new InternalError(exception.toString());
        }
        // Only the shallow copy is created. The entries never change in these data structures
        objectBuilder.setMappingsByAttribute(new HashMap(getMappingsByAttribute()));
        objectBuilder.setMappingsByField(new HashMap(getMappingsByField()));
        objectBuilder.setFieldsMap(new HashMap(getFieldsMap()));
        objectBuilder.setReadOnlyMappingsByField(new HashMap(getReadOnlyMappingsByField()));
        objectBuilder.setPrimaryKeyMappings(new ArrayList(getPrimaryKeyMappings()));
        if (nonPrimaryKeyMappings != null) {
            objectBuilder.setNonPrimaryKeyMappings(new ArrayList(getNonPrimaryKeyMappings()));
        }
        objectBuilder.cloningMappings = new ArrayList(this.cloningMappings);
        objectBuilder.eagerMappings = new ArrayList(this.eagerMappings);
        objectBuilder.relationshipMappings = new ArrayList(this.relationshipMappings);

        return objectBuilder;
    }

    /**
     * INTERNAL:
     * This method is used by the UnitOfWork to cascade registration of new objects.
     * It may raise exceptions as described in the EJB3 specification
     */
    public void cascadePerformRemove(Object object, UnitOfWorkImpl uow, Map visitedObjects) {
        // PERF: Only process relationships.
        if (!this.isSimple) {
            List<DatabaseMapping> mappings = this.relationshipMappings;
            for (int index = 0; index < mappings.size(); index++) {
                DatabaseMapping mapping = mappings.get(index);
                mapping.cascadePerformRemoveIfRequired(object, uow, visitedObjects);
            }
        }
    }

    /**
     * INTERNAL:
     * This method is used to iterate over the specified object's mappings and cascade
     * remove orphaned private owned objects from the UnitOfWorkChangeSet and IdentityMap.
     */
    public void cascadePerformRemovePrivateOwnedObjectFromChangeSet(Object object, UnitOfWorkImpl uow, Map visitedObjects) {
        if (object != null && !this.isSimple) {
            for (DatabaseMapping mapping : this.relationshipMappings) {
                // only cascade into private owned mappings
                if (mapping.isPrivateOwned()) {
                    mapping.cascadePerformRemovePrivateOwnedObjectFromChangeSetIfRequired(object, uow, visitedObjects);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * This method is used to store the FK values used for this mapping in the cachekey.
     * This is used when the mapping is protected but we have retrieved the fk values and will cache
     * them for use when the entity is cloned.
     */
    public void cacheForeignKeyValues(AbstractRecord databaseRecord, CacheKey cacheKey, AbstractSession session) {
        Set<DatabaseField> foreignKeys = this.descriptor.getForeignKeyValuesForCaching();
        if (foreignKeys.isEmpty()) {
            return;
        }
        DatabaseRecord cacheRecord = new DatabaseRecord(foreignKeys.size());
        for (DatabaseField field : foreignKeys) {
            cacheRecord.put(field, databaseRecord.get(field));
        }
        cacheKey.setProtectedForeignKeys(cacheRecord);

    }

    /**
     * INTERNAL:
     * This method is used to store the FK values used for this mapping in the cachekey.
     * This is used when the mapping is protected but we have retrieved the fk values and will cache
     * them for use when the entity is cloned.
     */
    public void cacheForeignKeyValues(Object source, CacheKey cacheKey, ClassDescriptor descriptor, AbstractSession session) {
        Set<DatabaseField> foreignKeys = this.descriptor.getForeignKeyValuesForCaching();
        if (foreignKeys.isEmpty()) {
            return;
        }
        DatabaseRecord cacheRecord = new DatabaseRecord(foreignKeys.size());
        for (DatabaseField field : foreignKeys) {
            cacheRecord.put(field, extractValueFromObjectForField(source, field, session));
        }
        cacheKey.setProtectedForeignKeys(cacheRecord);
    }

    /**
     * INTERNAL:
     * Cascade discover and persist new objects during commit.
     * It may raise exceptions as described in the EJB3 specification
     */
    public void cascadeDiscoverAndPersistUnregisteredNewObjects(Object object, Map newObjects, Map unregisteredExistingObjects, Map visitedObjects, UnitOfWorkImpl uow, Set cascadeErrors) {
        // PERF: Only process relationships.
        if (!this.isSimple) {
            List<DatabaseMapping> mappings = this.relationshipMappings;
            int size = mappings.size();
            FetchGroupManager fetchGroupManager = descriptor.getFetchGroupManager();
            // Only cascade fetched mappings.
            if ((fetchGroupManager != null) && fetchGroupManager.isPartialObject(object)) {
                for (int index = 0; index < size; index++) {
                    DatabaseMapping mapping = mappings.get(index);
                    if (fetchGroupManager.isAttributeFetched(object, mapping.getAttributeName())) {
                        mapping.cascadeDiscoverAndPersistUnregisteredNewObjects(object, newObjects, unregisteredExistingObjects, visitedObjects, uow, cascadeErrors);
                    }
                }
            } else {
                for (int index = 0; index < size; index++) {
                    DatabaseMapping mapping = mappings.get(index);
                    mapping.cascadeDiscoverAndPersistUnregisteredNewObjects(object, newObjects, unregisteredExistingObjects, visitedObjects, uow, cascadeErrors);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * This method is used by the UnitOfWork to cascade registration of new objects.
     * It may raise exceptions as described in the EJB3 specification
     */
    public void cascadeRegisterNewForCreate(Object object, UnitOfWorkImpl uow, Map visitedObjects) {
        // PERF: Only process relationships.
        if (!this.isSimple) {
            List<DatabaseMapping> mappings = this.relationshipMappings;
            int size = mappings.size();
            FetchGroupManager fetchGroupManager = this.descriptor.getFetchGroupManager();
            // Only cascade fetched mappings.
            if ((fetchGroupManager != null) && fetchGroupManager.isPartialObject(object)) {
                for (int index = 0; index < size; index++) {
                    DatabaseMapping mapping = mappings.get(index);
                    if (fetchGroupManager.isAttributeFetched(object, mapping.getAttributeName())) {
                        mapping.cascadeRegisterNewIfRequired(object, uow, visitedObjects);
                    }
                }
            } else {
                for (int index = 0; index < size; index++) {
                    DatabaseMapping mapping = mappings.get(index);
                    mapping.cascadeRegisterNewIfRequired(object, uow, visitedObjects);
                }
            }
        }
        // Allow persist to set the partitioning connection.
        if (this.descriptor.getPartitioningPolicy() != null) {
            this.descriptor.getPartitioningPolicy().partitionPersist(uow.getParent(), object, this.descriptor);
        }
    }

    /**
     * INTERNAL:
     * This method creates a records change set for a particular object.
     * It should only be used by aggregates.
     * @return ObjectChangeSet
     */
    public ObjectChangeSet compareForChange(Object clone, Object backUp, UnitOfWorkChangeSet changeSet, AbstractSession session) {
        // delegate the change comparison to this objects ObjectChangePolicy - TGW
        return descriptor.getObjectChangePolicy().calculateChanges(clone, backUp, backUp == null, changeSet, ((UnitOfWorkImpl)session), this.descriptor, true);
    }

    /**
     * Compares the two specified objects
     */
    public boolean compareObjects(Object firstObject, Object secondObject, AbstractSession session) {
        // PERF: Avoid iterator.
        List<DatabaseMapping> mappings = this.descriptor.getMappings();
        for (int index = 0; index < mappings.size(); index++) {
            DatabaseMapping mapping = mappings.get(index);

            if (!mapping.compareObjects(firstObject, secondObject, session)) {
                Object firstValue = mapping.getAttributeValueFromObject(firstObject);
                Object secondValue = mapping.getAttributeValueFromObject(secondObject);
                session.log(SessionLog.FINEST, SessionLog.QUERY, "compare_failed", mapping, firstValue, secondValue);
                return false;
            }
        }

        return true;
    }

    /**
     * Copy each attribute from one object into the other.
     */
    public void copyInto(Object source, Object target, boolean cloneOneToOneValueHolders) {
        // PERF: Avoid iterator.
        List<DatabaseMapping> mappings = this.descriptor.getMappings();
        for (int index = 0; index < mappings.size(); index++) {
            DatabaseMapping mapping = mappings.get(index);
            Object value = null;
            if (cloneOneToOneValueHolders && mapping.isForeignReferenceMapping()){
                value = ((ForeignReferenceMapping)mapping).getAttributeValueWithClonedValueHolders(source);
            } else {
                value = mapping.getAttributeValueFromObject(source);
            }
            mapping.setAttributeValueInObject(target, value);
        }
    }

    /**
     * Copy each attribute from one object into the other.
     */
    public void copyInto(Object source, Object target) {
        copyInto(source, target, false);
    }

    /**
     * Return a copy of the object.
     * This is NOT used for unit of work but for templatizing an object.
     * The depth and primary key reseting are passed in.
     */
    public Object copyObject(Object original, CopyGroup copyGroup) {
        Object copy = copyGroup.getCopies().get(original);
        if (copyGroup.shouldCascadeTree()) {
            FetchGroupManager fetchGroupManager = this.descriptor.getFetchGroupManager();
            if (fetchGroupManager != null) {
                // empty copy group means all the attributes should be copied - don't alter it.
                if (copyGroup.hasItems()) {
                    // by default add primary key attribute(s) if not already in the group
                    if (!copyGroup.shouldResetPrimaryKey()) {
                        for (DatabaseMapping mapping : this.primaryKeyMappings) {
                            String name = mapping.getAttributeName();
                            if (!copyGroup.containsAttributeInternal(name)) {
                               copyGroup.addAttribute(name);
                            }
                        }
                    } else {
                        for (DatabaseMapping mapping : this.primaryKeyMappings) {
                            if (mapping.isForeignReferenceMapping()) {
                                String name = mapping.getAttributeName();
                                if (!copyGroup.containsAttributeInternal(name)) {
                                   copyGroup.addAttribute(name);
                                }
                            }
                        }
                    }

                    // by default version attribute if not already in the group
                    if (!copyGroup.shouldResetVersion()) {
                        if (this.lockAttribute != null) {
                            if (!copyGroup.containsAttributeInternal(this.lockAttribute)) {
                               copyGroup.addAttribute(this.lockAttribute);
                            }
                        }
                    }

                    FetchGroup fetchGroup = fetchGroupManager.getObjectFetchGroup(original);
                    if (fetchGroup != null) {
                        if (!fetchGroup.getAttributeNames().containsAll(copyGroup.getAttributeNames())) {
                            // trigger fetch group if it does not contain all attributes of the copy group.
                            fetchGroup.onUnfetchedAttribute((FetchGroupTracker)original, null);
                        }
                    }
                }

                // Entity fetch group currently set on copyObject
                EntityFetchGroup existingEntityFetchGroup = null;
                if (copy != null) {
                    Object[] copyArray = (Object[])copy;
                    // copy of the original
                    copy = copyArray[0];
                    // A set of CopyGroups that have visited.
                    Set<CopyGroup> visitedCopyGroups = (Set<CopyGroup>)copyArray[1];

                    if(visitedCopyGroups.contains(copyGroup)) {
                        // original has been already visited with this copyGroup - leave
                        return copy;
                    } else {
                        visitedCopyGroups.add(copyGroup);
                    }

                    existingEntityFetchGroup = fetchGroupManager.getObjectEntityFetchGroup(copy);
                }

                // Entity fetch group that will be assigned to copyObject
                EntityFetchGroup newEntityFetchGroup = null;

                // Attributes to be visited - only reference mappings will be visited.
                // If null then all attributes should be visited.
                Set<String> attributesToVisit = copyGroup.getAttributeNames();
                // Attributes to be copied
                Set<String> attributesToCopy = attributesToVisit;
                boolean shouldCopyAllAttributes = false;
                boolean shouldAssignNewEntityFetchGroup = false;
                if(copy != null && existingEntityFetchGroup == null) {
                    // all attributes have been already copied
                    attributesToCopy = null;
                } else {
                    // Entity fetch group corresponding to copyPolicy.
                    // Note that empty, or null, or containing all arguments attributesToCopy
                    // results in copyGroupFetchGroup = null;
                    EntityFetchGroup copyGroupEntityFetchGroup = fetchGroupManager.getEntityFetchGroup(attributesToCopy);
                    if(copyGroupEntityFetchGroup == null) {
                        // all attributes will be copied
                        shouldCopyAllAttributes = true;
                    }

                    if(copy != null) {
                        if(copyGroupEntityFetchGroup != null) {
                            if(!copyGroup.shouldResetPrimaryKey()) {
                                if(!existingEntityFetchGroup.getAttributeNames().containsAll(attributesToCopy)) {
                                    // Entity fetch group that will be assigned to copy object
                                    newEntityFetchGroup = fetchGroupManager.flatUnionFetchGroups(existingEntityFetchGroup, copyGroupEntityFetchGroup, false);
                                    shouldAssignNewEntityFetchGroup = true;
                                }
                            }
                            attributesToCopy = new HashSet(attributesToCopy);
                            attributesToCopy.removeAll(existingEntityFetchGroup.getAttributeNames());
                        }
                    } else {
                        // copy does not exist - create it
                        copy = copyGroup.getSession().getDescriptor(original).getObjectBuilder().buildNewInstance();
                        Set<CopyGroup> visitedCopyGroups = new HashSet();
                        visitedCopyGroups.add(copyGroup);
                        copyGroup.getCopies().put(original, new Object[]{copy, visitedCopyGroups});
                        if(!copyGroup.shouldResetPrimaryKey()) {
                            newEntityFetchGroup = copyGroupEntityFetchGroup;
                            shouldAssignNewEntityFetchGroup = true;
                        }
                    }
                }
                if(shouldAssignNewEntityFetchGroup) {
                    fetchGroupManager.setObjectFetchGroup(copy, newEntityFetchGroup, null);
                }

                for (DatabaseMapping mapping : getDescriptor().getMappings()) {
                    String name = mapping.getAttributeName();
                    boolean shouldCopy = shouldCopyAllAttributes || (attributesToCopy != null && attributesToCopy.contains(name));
                    boolean shouldVisit = attributesToVisit == null || attributesToVisit.contains(name);
                    if(shouldCopy || shouldVisit) {
                        boolean isVisiting = false;
                        // unless it's a reference mapping pass copyGroup - just to carry the session.
                        CopyGroup mappingCopyGroup = copyGroup;
                        if(mapping.isForeignReferenceMapping()) {
                            ForeignReferenceMapping frMapping = (ForeignReferenceMapping)mapping;
                            ClassDescriptor referenceDescriptor = frMapping.getReferenceDescriptor();
                            if(referenceDescriptor != null) {
                                isVisiting = true;
                                mappingCopyGroup = copyGroup.getGroup(name);
                                if(mappingCopyGroup == null) {
                                    FetchGroupManager referenceFetchGroupManager = referenceDescriptor.getFetchGroupManager();
                                    if(referenceFetchGroupManager != null) {
                                        EntityFetchGroup nonReferenceEntityFetchGroup = referenceFetchGroupManager.getNonReferenceEntityFetchGroup(copyGroup.shouldResetPrimaryKey(), copyGroup.shouldResetVersion());
                                        if(nonReferenceEntityFetchGroup != null) {
                                            mappingCopyGroup = nonReferenceEntityFetchGroup.toCopyGroup();
                                        } else {
                                            // null nonReferenceEntityFetchGroup is equivalent to containing all attributes:
                                            // create a new empty CopyGroup.
                                            mappingCopyGroup = new CopyGroup();
                                            mappingCopyGroup.shouldCascadeTree();
                                        }
                                    } else {
                                        // TODO: would that work?
                                        mappingCopyGroup = new CopyGroup();
                                        mappingCopyGroup.dontCascade();
                                        isVisiting = false;
                                    }
                                    mappingCopyGroup.setCopies(copyGroup.getCopies());
                                    mappingCopyGroup.setShouldResetPrimaryKey(copyGroup.shouldResetPrimaryKey());
                                    mappingCopyGroup.setShouldResetVersion(copyGroup.shouldResetVersion());
                                }
                                mappingCopyGroup.setSession(copyGroup.getSession());
                            }
                        } else if (mapping.isAggregateObjectMapping()) {
                            mappingCopyGroup = new CopyGroup();
                        }
                        if(shouldCopy || isVisiting) {
                            // TODO: optimization: (even when isVisiting == true) redefine buildCopy to take shouldCopy and don't copy if not required.
                            mapping.buildCopy(copy, original, mappingCopyGroup);
                        }
                    }
                }
            } else {
                // fetchGroupManager == null
                // TODO
            }

        } else {
            // ! copyGroup.shouldCascadeTree()
            if (copy != null) {
                return copy;
            }

            copy = instantiateClone(original, copyGroup.getSession());
            copyGroup.getCopies().put(original, copy);

            // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
            List<DatabaseMapping> mappings = getCloningMappings();
            int size = mappings.size();
            for (int index = 0; index < size; index++) {
                mappings.get(index).buildCopy(copy, original, copyGroup);
            }

            if (copyGroup.shouldResetPrimaryKey() && (!(this.descriptor.isDescriptorTypeAggregate()))) {
                // Do not reset if any of the keys is mapped through a 1-1, i.e. back reference id has already changed.
                boolean hasOneToOne = false;
                List<DatabaseMapping> primaryKeyMappings = getPrimaryKeyMappings();
                size = primaryKeyMappings.size();
                for (int index = 0; index < size; index++) {
                    if (primaryKeyMappings.get(index).isOneToOneMapping()) {
                        hasOneToOne = true;
                    }
                }
                if (!hasOneToOne) {
                    for (int index = 0; index < size; index++) {
                        DatabaseMapping mapping = primaryKeyMappings.get(index);

                        // Only null out direct mappings, as others will be nulled in the respective objects.
                        if (mapping.isAbstractColumnMapping()) {
                            Object nullValue = ((AbstractColumnMapping)mapping).getObjectValue(null, copyGroup.getSession());
                            mapping.setAttributeValueInObject(copy, nullValue);
                        } else if (mapping.isTransformationMapping()) {
                            mapping.setAttributeValueInObject(copy, null);
                        }
                    }
                }
            }

            // PERF: Avoid events if no listeners.
            if (this.descriptor.getEventManager().hasAnyEventListeners()) {
                org.eclipse.persistence.descriptors.DescriptorEvent event = new org.eclipse.persistence.descriptors.DescriptorEvent(copy);
                event.setSession(copyGroup.getSession());
                event.setOriginalObject(original);
                event.setEventCode(DescriptorEventManager.PostCloneEvent);
                this.descriptor.getEventManager().executeEvent(event);
            }
        }

        return copy;
    }

    /**
     * INTERNAL:
     * Used by the ObjectBuilder to create an ObjectChangeSet for the specified clone object.
     * @return ObjectChangeSet the newly created changeSet representing the clone object
     * @param clone the object to convert to a changeSet.
     * @param uowChangeSet the owner of this changeSet.
     */
    public ObjectChangeSet createObjectChangeSet(Object clone, UnitOfWorkChangeSet uowChangeSet, AbstractSession session) {
        boolean isNew = ((UnitOfWorkImpl)session).isCloneNewObject(clone);
        return createObjectChangeSet(clone, uowChangeSet, isNew, session);
    }

    /**
     * INTERNAL:
     * Used by the ObjectBuilder to create an ObjectChangeSet for the specified clone object.
     * @return ObjectChangeSet the newly created changeSet representing the clone object
     * @param clone the object to convert to a changeSet.
     * @param uowChangeSet the owner of this changeSet.
     * @param isNew signifies if the clone object is a new object.
     */
    public ObjectChangeSet createObjectChangeSet(Object clone, UnitOfWorkChangeSet uowChangeSet, boolean isNew, AbstractSession session) {
        return createObjectChangeSet(clone, uowChangeSet, isNew, false, session);
    }

    /**
     * INTERNAL:
     * Used by the ObjectBuilder to create an ObjectChangeSet for the specified clone object.
     * @return ObjectChangeSet the newly created changeSet representing the clone object
     * @param clone the object to convert to a changeSet.
     * @param uowChangeSet the owner of this changeSet.
     * @param isNew signifies if the clone object is a new object.
     * @param assignPrimaryKeyIfExisting signifies if the primary key of the change set should be updated if existing.
     */
    public ObjectChangeSet createObjectChangeSet(Object clone, UnitOfWorkChangeSet uowChangeSet, boolean isNew, boolean assignPrimaryKeyIfExisting, AbstractSession session) {
        ObjectChangeSet changes = (ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(clone);
        if (changes == null || changes.getDescriptor() != this.descriptor) {
            if (this.descriptor.isAggregateDescriptor()) {
                changes = new AggregateObjectChangeSet(CacheId.EMPTY, this.descriptor, clone, uowChangeSet, isNew);
            } else {
                changes = new ObjectChangeSet(extractPrimaryKeyFromObject(clone, session, true), this.descriptor, clone, uowChangeSet, isNew);
            }
            changes.setIsAggregate(this.descriptor.isDescriptorTypeAggregate());
            uowChangeSet.addObjectChangeSetForIdentity(changes, clone);
        } else{
            if (isNew && !changes.isNew()) {
                //this is an unregistered new object that we found during change calc
                //or change listener update.  Let's switch it to be new.
                changes.setIsNew(isNew);
            }
            if (assignPrimaryKeyIfExisting) {
                if (!changes.isAggregate()) {
                    // If creating a new change set for a new object, the original change set (from change tracking) may have not had the primary key.
                    Object primaryKey = extractPrimaryKeyFromObject(clone, session, true);
                    if (primaryKey != null) {
                        changes.setId(primaryKey);
                    }
                }
           }
        }
        return changes;
    }

    /**
     * Creates and stores primary key expression.
     */
    public void createPrimaryKeyExpression(AbstractSession session) {
        Expression expression = null;
        Expression builder = new ExpressionBuilder();
        Expression subExp1;
        Expression subExp2;
        Expression subExpression;
        List<DatabaseField> primaryKeyFields = this.descriptor.getPrimaryKeyFields();

        if(null != primaryKeyFields) {
            for (int index = 0; index < primaryKeyFields.size(); index++) {
                DatabaseField primaryKeyField = primaryKeyFields.get(index);
                subExpression = ((DatasourcePlatform)session.getDatasourcePlatform()).createExpressionFor(primaryKeyField, builder);

                if (expression == null) {
                    expression = subExpression;
                } else {
                    expression = expression.and(subExpression);
                }
            }
        }

        setPrimaryKeyExpression(expression);
    }

    /**
     * Return the row with primary keys and their values from the given expression.
     */
    public Object extractPrimaryKeyFromExpression(boolean requiresExactMatch, Expression expression, AbstractRecord translationRow, AbstractSession session) {
        AbstractRecord primaryKeyRow = createRecord(getPrimaryKeyMappings().size(), session);

        expression.getBuilder().setSession(session.getRootSession(null));
        // Get all the field & values from expression.
        boolean isValid = expression.extractPrimaryKeyValues(requiresExactMatch, this.descriptor, primaryKeyRow, translationRow);
        if (requiresExactMatch && (!isValid)) {
            return null;
        }

        // Check that the sizes match.
        if (primaryKeyRow.size() != this.descriptor.getPrimaryKeyFields().size()) {
            return null;
        }

        Object primaryKey = extractPrimaryKeyFromRow(primaryKeyRow, session);
        if ((primaryKey == null) && isValid) {
            return InvalidObject.instance;
        }
        return primaryKey;
    }

    /**
     * Return if the expression is by primary key.
     */
    public boolean isPrimaryKeyExpression(boolean requiresExactMatch, Expression expression, AbstractSession session) {
        expression.getBuilder().setSession(session.getRootSession(null));
        List<DatabaseField> keyFields = this.descriptor.getPrimaryKeyFields();
        int size = keyFields.size();
        Set<DatabaseField> fields = new HashSet(size);
        boolean isValid = expression.extractFields(requiresExactMatch, true, this.descriptor, keyFields, fields);
        if (requiresExactMatch && (!isValid)) {
            return false;
        }
        // Check that the sizes match.
        if (fields.size() != size) {
            return false;
        }
        return true;
    }

    /**
     * Extract primary key attribute values from the domainObject.
     */
    @Override
    public Object extractPrimaryKeyFromObject(Object domainObject, AbstractSession session) {
        return extractPrimaryKeyFromObject(domainObject, session, false);
    }

    /**
     * Extract primary key attribute values from the domainObject.
     */
    public Object extractPrimaryKeyFromObject(Object domainObject, AbstractSession session, boolean shouldReturnNullIfNull) {
        if (domainObject == null) {
            return null;
        }
        // Avoid using the cached id for XML, as the relational descriptor may be different than the xml one.
        boolean isPersistenceEntity = (domainObject instanceof PersistenceEntity) && (!isXMLObjectBuilder());
        if (isPersistenceEntity) {
            Object primaryKey = ((PersistenceEntity)domainObject)._persistence_getId();
            if (primaryKey != null) {
                return primaryKey;
            }
        }
        ClassDescriptor descriptor = this.descriptor;
        boolean isNull = false;
        // Allow for inheritance, the concrete descriptor must always be used.
        if (descriptor.hasInheritance() && (domainObject.getClass() != descriptor.getJavaClass()) && (!domainObject.getClass().getSuperclass().equals(descriptor.getJavaClass()))) {
            return session.getDescriptor(domainObject).getObjectBuilder().extractPrimaryKeyFromObject(domainObject, session, shouldReturnNullIfNull);
        }

        CacheKeyType cacheKeyType = descriptor.getCachePolicy().getCacheKeyType();
        List<DatabaseField> primaryKeyFields = descriptor.getPrimaryKeyFields();
        Object[] primaryKeyValues = null;
        if (cacheKeyType != CacheKeyType.ID_VALUE) {
            primaryKeyValues = new Object[primaryKeyFields.size()];
        }
        List<DatabaseMapping> mappings = getPrimaryKeyMappings();
        int size = mappings.size();
        // PERF: optimize simple case of direct mapped singleton primary key.
        if (descriptor.hasSimplePrimaryKey()) {
            // PERF: use index not enumeration.
            for (int index = 0; index < size; index++) {
                AbstractColumnMapping mapping = (AbstractColumnMapping)mappings.get(index);
                Object keyValue = mapping.valueFromObject(domainObject, primaryKeyFields.get(index), session);
                if (isPrimaryKeyComponentInvalid(keyValue, index)) {
                    if (shouldReturnNullIfNull) {
                        return null;
                    }
                    isNull = true;
                }
                if (cacheKeyType == CacheKeyType.ID_VALUE) {
                    if (isPersistenceEntity && (!isNull)) {
                        ((PersistenceEntity)domainObject)._persistence_setId(keyValue);
                    }
                    return keyValue;
                } else {
                    primaryKeyValues[index] = keyValue;
                }
            }
        } else {
            AbstractRecord databaseRow = createRecordForPKExtraction(size, session);
            Set<DatabaseMapping> writtenMappings = new HashSet<>(size);
            // PERF: use index not enumeration
            for (int index = 0; index < size; index++) {
                DatabaseMapping mapping = mappings.get(index);
                // Bug 489783 - PERF: only write a PK mapping once when iterating
                // Primary key mapping may be null for aggregate collection.
                if (mapping != null && !writtenMappings.contains(mapping)) {
                    mapping.writeFromObjectIntoRow(domainObject, databaseRow, session, WriteType.UNDEFINED);
                    writtenMappings.add(mapping);
                }
            }
            List<Class> primaryKeyClassifications = getPrimaryKeyClassifications();
            Platform platform = session.getPlatform(domainObject.getClass());
            // PERF: use index not enumeration
            for (int index = 0; index < size; index++) {
                // Ensure that the type extracted from the object is the same type as in the descriptor,
                // the main reason for this is that 1-1 can optimize on vh by getting from the row as the row-type.
                Class classification = primaryKeyClassifications.get(index);
                Object value = databaseRow.get(primaryKeyFields.get(index));
                if (isPrimaryKeyComponentInvalid(value, index)) {
                    if (shouldReturnNullIfNull) {
                        return null;
                    }
                    isNull = true;
                }
                value = platform.convertObject(value, classification);
                if (cacheKeyType == CacheKeyType.ID_VALUE) {
                    if (isPersistenceEntity && (!isNull)) {
                        ((PersistenceEntity)domainObject)._persistence_setId(value);
                    }
                    return value;
                } else {
                    primaryKeyValues[index] = value;
                }
            }
        }
        CacheId id = new CacheId(primaryKeyValues);
        if (isPersistenceEntity && (!isNull)) {
            ((PersistenceEntity)domainObject)._persistence_setId(id);
        }
        return id;
    }

    /**
     * Extract primary key values from the specified row.
     * null is returned if the row does not contain the key.
     */
    public Object extractPrimaryKeyFromRow(AbstractRecord databaseRow, AbstractSession session) {
        if (databaseRow.hasSopObject()) {
            // Entity referencing ForeignReferenceMapping has set attribute extracted from sopObject as a sopObject into a new empty row.
            return extractPrimaryKeyFromObject(databaseRow.getSopObject(), session);
        }
        List<DatabaseField> primaryKeyFields = this.descriptor.getPrimaryKeyFields();
        if(null == primaryKeyFields) {
            return null;
        }
        List<Class> primaryKeyClassifications = getPrimaryKeyClassifications();
        int size = primaryKeyFields.size();
        Object[] primaryKeyValues = null;
        CacheKeyType cacheKeyType = this.descriptor.getCachePolicy().getCacheKeyType();
        if (cacheKeyType != CacheKeyType.ID_VALUE) {
            primaryKeyValues = new Object[size];
        }
        int numberOfNulls = 0;

        // PERF: use index not enumeration
        for (int index = 0; index < size; index++) {
            DatabaseField field = primaryKeyFields.get(index);

            // Ensure that the type extracted from the row is the same type as in the object.
            Class classification = primaryKeyClassifications.get(index);
            Object value = databaseRow.get(field);
            if (value != null) {
                if (value.getClass() != classification) {
                    value = session.getPlatform(this.descriptor.getJavaClass()).convertObject(value, classification);
                }
                if (cacheKeyType == CacheKeyType.ID_VALUE) {
                    return value;
                }
                primaryKeyValues[index] = value;
            } else {
                if (this.mayHaveNullInPrimaryKey) {
                    numberOfNulls++;
                    if (numberOfNulls < size) {
                        primaryKeyValues[index] = null;
                    } else {
                        // Must have some non null elements. If all elements are null return null.
                        return null;
                    }
                } else {
                    return null;
                }
            }
        }

        return new CacheId(primaryKeyValues);
    }

    /**
     * Return the row with primary keys and their values from the given expression.
     */
    public AbstractRecord extractPrimaryKeyRowFromExpression(Expression expression, AbstractRecord translationRow, AbstractSession session) {
        if (translationRow != null && translationRow.hasSopObject()) {
            return translationRow;
        }
        AbstractRecord primaryKeyRow = createRecord(getPrimaryKeyMappings().size(), session);

        expression.getBuilder().setSession(session.getRootSession(null));
        // Get all the field & values from expression
        boolean isValid = expression.extractPrimaryKeyValues(true, this.descriptor, primaryKeyRow, translationRow);
        if (!isValid) {
            return null;
        }

        // Check that the sizes match up
        if (primaryKeyRow.size() != this.descriptor.getPrimaryKeyFields().size()) {
            return null;
        }

        return primaryKeyRow;
    }

    /**
     * Return the row from the given expression.
     */
    public AbstractRecord extractRowFromExpression(Expression expression, AbstractRecord translationRow, AbstractSession session) {
        AbstractRecord record = createRecord(session);

        expression.getBuilder().setSession(session.getRootSession(null));
        // Get all the field & values from expression
        boolean isValid = expression.extractValues(false, false, this.descriptor, record, translationRow);
        if (!isValid) {
            return null;
        }

        return record;
    }

    /**
     * Extract primary key attribute values from the domainObject.
     */
    public AbstractRecord extractPrimaryKeyRowFromObject(Object domainObject, AbstractSession session) {
        AbstractRecord databaseRow = createRecord(getPrimaryKeyMappings().size(), session);

        // PERF: use index not enumeration.
        for (int index = 0; index < getPrimaryKeyMappings().size(); index++) {
            getPrimaryKeyMappings().get(index).writeFromObjectIntoRow(domainObject, databaseRow, session, WriteType.UNDEFINED);
        }

        // PERF: optimize simple primary key case, no need to remap.
        if (this.descriptor.hasSimplePrimaryKey()) {
            return databaseRow;
        }
        AbstractRecord primaryKeyRow = createRecord(getPrimaryKeyMappings().size(), session);
        List<DatabaseField> primaryKeyFields = this.descriptor.getPrimaryKeyFields();
        for (int index = 0; index < primaryKeyFields.size(); index++) {
            // Ensure that the type extracted from the object is the same type as in the descriptor,
            // the main reason for this is that 1-1 can optimize on vh by getting from the row as the row-type.
            Class classification = getPrimaryKeyClassifications().get(index);
            DatabaseField field = primaryKeyFields.get(index);
            Object value = databaseRow.get(field);
            primaryKeyRow.put(field, session.getPlatform(domainObject.getClass()).convertObject(value, classification));
        }

        return primaryKeyRow;
    }

    /**
     * Extract the value of the primary key attribute from the specified object.
     */
    public Object extractValueFromObjectForField(Object domainObject, DatabaseField field, AbstractSession session) throws DescriptorException {
        // Allow for inheritance, the concrete descriptor must always be used.
        ClassDescriptor descriptor = null;//this variable will be assigned in the final

        if (this.descriptor.hasInheritance() && (domainObject.getClass() != this.descriptor.getJavaClass()) && ((descriptor = session.getDescriptor(domainObject)).getJavaClass() != this.descriptor.getJavaClass())) {
            if(descriptor.isAggregateCollectionDescriptor()) {
                descriptor = this.descriptor.getInheritancePolicy().getDescriptor(descriptor.getJavaClass());
            }
            return descriptor.getObjectBuilder().extractValueFromObjectForField(domainObject, field, session);
        } else {
            DatabaseMapping mapping = getMappingForField(field);
            if (mapping == null) {
                throw DescriptorException.missingMappingForField(field, this.descriptor);
            }

            return mapping.valueFromObject(domainObject, field, session);
        }
    }
    /**
     * INTERNAL:
     * An object has been serialized from the server to the client.
     * Replace the transient attributes of the remote value holders
     * with client-side objects.
     */
    public void fixObjectReferences(Object object, Map objectDescriptors, Map processedObjects, ObjectLevelReadQuery query, DistributedSession session) {
        // PERF: Only process relationships.
        if (!this.isSimple) {
            List<DatabaseMapping> mappings = this.relationshipMappings;
            for (int index = 0; index < mappings.size(); index++) {
                mappings.get(index).fixObjectReferences(object, objectDescriptors, processedObjects, query, session);
            }
        }
    }

    /**
     * Return the base ChangeRecord for the given DatabaseField.
     * The object and all its relevant aggregates must exist.
     * The returned ChangeRecord is
     * either DirectToFieldChangeRecord or TransformationMappingChangeRecord,
     * or null.
     */
    public ChangeRecord getBaseChangeRecordForField(ObjectChangeSet objectChangeSet, Object object, DatabaseField databaseField, AbstractSession session) {
        DatabaseMapping mapping = getMappingForField(databaseField);

        // Drill down through the mappings until we get the direct mapping to the databaseField.
        while (mapping.isAggregateObjectMapping()) {
            String attributeName = mapping.getAttributeName();
            Object aggregate = mapping.getAttributeValueFromObject(object);
            ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();
            AggregateChangeRecord aggregateChangeRecord = (AggregateChangeRecord)objectChangeSet.getChangesForAttributeNamed(attributeName);
            if (aggregateChangeRecord == null) {
                aggregateChangeRecord = new AggregateChangeRecord(objectChangeSet);
                aggregateChangeRecord.setAttribute(attributeName);
                aggregateChangeRecord.setMapping(mapping);
                objectChangeSet.addChange(aggregateChangeRecord);
            }
            ObjectChangeSet aggregateChangeSet = (ObjectChangeSet)aggregateChangeRecord.getChangedObject();
            if (aggregateChangeSet == null) {
                aggregateChangeSet = referenceDescriptor.getObjectBuilder().createObjectChangeSet(aggregate, (UnitOfWorkChangeSet)objectChangeSet.getUOWChangeSet(), session);
                aggregateChangeRecord.setChangedObject(aggregateChangeSet);
            }

            mapping = referenceDescriptor.getObjectBuilder().getMappingForField(databaseField);
            objectChangeSet = aggregateChangeSet;
            object = aggregate;
        }

        String attributeName = mapping.getAttributeName();
        if (mapping.isAbstractDirectMapping()) {
            DirectToFieldChangeRecord changeRecord = (DirectToFieldChangeRecord)objectChangeSet.getChangesForAttributeNamed(attributeName);
            if (changeRecord == null) {
                changeRecord = new DirectToFieldChangeRecord(objectChangeSet);
                changeRecord.setAttribute(attributeName);
                changeRecord.setMapping(mapping);
                objectChangeSet.addChange(changeRecord);
            }
            return changeRecord;
        } else if (mapping.isTransformationMapping()) {
            TransformationMappingChangeRecord changeRecord = (TransformationMappingChangeRecord)objectChangeSet.getChangesForAttributeNamed(attributeName);
            if (changeRecord == null) {
                changeRecord = new TransformationMappingChangeRecord(objectChangeSet);
                changeRecord.setAttribute(attributeName);
                changeRecord.setMapping(mapping);
                objectChangeSet.addChange(changeRecord);
            }
            return changeRecord;
        } else {
            session.log(SessionLog.FINEST, SessionLog.QUERY, "field_for_unsupported_mapping_returned", databaseField, getDescriptor());
            return null;
        }
    }

    /**
     * Return the base mapping for the given DatabaseField.
     */
    public DatabaseMapping getBaseMappingForField(DatabaseField databaseField) {
        DatabaseMapping mapping = getMappingForField(databaseField);

        // Drill down through the mappings until we get the direct mapping to the databaseField.
        while ((mapping != null) && mapping.isAggregateObjectMapping()) {
            mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(databaseField);
        }
        return mapping;
    }

    /**
     * Return the base value that is mapped to for given field.
     */
    public Object getBaseValueForField(DatabaseField databaseField, Object domainObject) {
        Object valueIntoObject = domainObject;
        DatabaseMapping mapping = getMappingForField(databaseField);

        // Drill down through the aggregate mappings to get to the direct to field mapping.
        while (mapping.isAggregateObjectMapping()) {
            valueIntoObject = mapping.getAttributeValueFromObject(valueIntoObject);
            mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(databaseField);
        }
        // Bug 422610
        if (valueIntoObject == null) {
            return null;
        }
        return mapping.getAttributeValueFromObject(valueIntoObject);
    }

    /**
     * Return the descriptor
     */
    public ClassDescriptor getDescriptor() {
        return descriptor;
    }

    /**
     * INTERNAL:
     * Return the classification for the field contained in the mapping.
     * This is used to convert the row value to a consistent java value.
     */
    public Class getFieldClassification(DatabaseField fieldToClassify) throws DescriptorException {
        DatabaseMapping mapping = getMappingForField(fieldToClassify);
        if (mapping == null) {
            // Means that the mapping is read-only or the classification is unknown,
            // this is normally not an issue as the classification is only really used for primary keys
            // and only when the database type can be different and not polymorphic than the object type.
            return null;
        }

        return mapping.getFieldClassification(fieldToClassify);
    }

    /**
     * Return the field used for the query key name.
     */
    public DatabaseField getFieldForQueryKeyName(String name) {
        QueryKey key = this.descriptor.getQueryKeyNamed(name);
        if (key == null) {
            DatabaseMapping mapping = getMappingForAttributeName(name);
            if (mapping == null) {
                return null;
            }
            if (mapping.getFields().isEmpty()) {
                return null;
            }
            return mapping.getFields().get(0);
        }
        if (key.isDirectQueryKey()) {
            return ((DirectQueryKey)key).getField();
        }
        return null;
    }

    /**
     * Return the fields map.
     * Used to maintain identity on the field objects. Ensure they get the correct index/type.
     */
    public Map<DatabaseField, DatabaseField> getFieldsMap() {
        return fieldsMap;
    }

    /**
     * Return the fields map.
     * Used to maintain identity on the field objects. Ensure they get the correct index/type.
     */
    protected void setFieldsMap(Map fieldsMap) {
        this.fieldsMap = fieldsMap;
    }

    /**
     * PERF:
     * Return all mappings that require cloning.
     * This allows for simple directs to be avoided when using clone copying.
     */
    public List<DatabaseMapping> getCloningMappings() {
        return cloningMappings;
    }

    /**
     * PERF:
     * Return if the descriptor has no complex mappings, all direct.
     */
    public boolean isSimple() {
        return isSimple;
    }

    /**
     * PERF:
     * Return all relationship mappings.
     */
    public List<DatabaseMapping> getRelationshipMappings() {
        return relationshipMappings;
    }

    /**
     * PERF:
     * Return all mappings that are eager loaded (but use indirection).
     * This allows for eager mappings to still benefit from indirection for locking and change tracking.
     */
    public List<DatabaseMapping> getEagerMappings() {
        return eagerMappings;
    }

    /**
     * Answers the attributes which are always joined to the original query on reads.
     */
    public List<DatabaseMapping> getJoinedAttributes() {
        return joinedAttributes;
    }

    /**
     * Return the mappings that are always batch fetched.
     */
    public List<DatabaseMapping> getBatchFetchedAttributes() {
        return this.batchFetchedAttributes;
    }

    /**
     * PERF:
     * Return the sequence mapping.
     */
    public AbstractDirectMapping getSequenceMapping() {
        return sequenceMapping;
    }

    /**
     * PERF:
     * Set the sequence mapping.
     */
    public void setSequenceMapping(AbstractDirectMapping sequenceMapping) {
        this.sequenceMapping = sequenceMapping;
    }

    /**
     * Answers if any attributes are to be joined / returned in the same select
     * statement.
     */
    public boolean hasJoinedAttributes() {
        return (this.joinedAttributes != null);
    }

    /**
     * Return is any mappings are always batch fetched.
     */
    public boolean hasBatchFetchedAttributes() {
        return (this.batchFetchedAttributes != null);
    }

    /**
     * Return is any mappings are always batch fetched using IN.
     */
    public boolean hasInBatchFetchedAttribute() {
        return this.hasInBatchFetchedAttribute;
    }

    /**
     * Set if any mappings are always batch fetched using IN.
     */
    public void setHasInBatchFetchedAttribute(boolean hasInBatchFetchedAttribute) {
        this.hasInBatchFetchedAttribute = hasInBatchFetchedAttribute;
    }

    /**
     * Return the mapping for the specified attribute name.
     */
    public DatabaseMapping getMappingForAttributeName(String name) {
        return getMappingsByAttribute().get(name);
    }

    /**
     * Return al the mapping for the specified field.
     */
    @Override
    public DatabaseMapping getMappingForField(DatabaseField field) {
        return getMappingsByField().get(field);
    }

    /**
     * Return all the read-only mapping for the specified field.
     */
    public List<DatabaseMapping> getReadOnlyMappingsForField(DatabaseField field) {
        return getReadOnlyMappingsByField().get(field);
    }

    /**
     * Return all the mapping to attribute associations
     */
    protected Map<String, DatabaseMapping> getMappingsByAttribute() {
        return mappingsByAttribute;
    }

    /**
     * INTERNAL:
     * Return all the mapping to field associations
     */
    public Map<DatabaseField, DatabaseMapping> getMappingsByField() {
        return mappingsByField;
    }

    /**
     * INTERNAL:
     * Return all the read-only mapping to field associations
     */
    public Map<DatabaseField, List<DatabaseMapping>> getReadOnlyMappingsByField() {
        return readOnlyMappingsByField;
    }

    /**
     * Return the non primary key mappings.
     */
    protected List<DatabaseMapping> getNonPrimaryKeyMappings() {
        return nonPrimaryKeyMappings;
    }

    /**
     * Return the base value that is mapped to for given field.
     */
    public Object getParentObjectForField(DatabaseField databaseField, Object domainObject) {
        Object valueIntoObject = domainObject;
        DatabaseMapping mapping = getMappingForField(databaseField);

        // Drill down through the aggregate mappings to get to the direct to field mapping.
        while (mapping.isAggregateObjectMapping()) {
            valueIntoObject = mapping.getAttributeValueFromObject(valueIntoObject);
            mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(databaseField);
        }
        return valueIntoObject;
    }

    /**
     * Return primary key classifications.
     * These are used to ensure a consistent type for the pk values.
     */
    public List<Class> getPrimaryKeyClassifications() {
        if (primaryKeyClassifications == null) {
            List<DatabaseField> primaryKeyFields = this.descriptor.getPrimaryKeyFields();
            if(null == primaryKeyFields) {
                return Collections.emptyList();
            }
            List<Class> classifications = new ArrayList(primaryKeyFields.size());

            for (int index = 0; index < primaryKeyFields.size(); index++) {
                if (getPrimaryKeyMappings().size() < (index + 1)) { // Check for failed initialization to avoid cascaded errors.
                    classifications.add(null);
                } else {
                    DatabaseMapping mapping = getPrimaryKeyMappings().get(index);
                    DatabaseField field = primaryKeyFields.get(index);
                    if (mapping != null) {
                        classifications.add(Helper.getObjectClass(mapping.getFieldClassification(field)));
                    } else {
                        classifications.add(null);
                    }
                }
            }
            primaryKeyClassifications = classifications;
        }
        return primaryKeyClassifications;
    }

    /**
     * Return the primary key expression
     */
    public Expression getPrimaryKeyExpression() {
        return primaryKeyExpression;
    }

    /**
     * Return primary key mappings.
     */
    public List<DatabaseMapping> getPrimaryKeyMappings() {
        return primaryKeyMappings;
    }

    /**
     * INTERNAL: return a database field based on a query key name
     */
    public DatabaseField getTargetFieldForQueryKeyName(String queryKeyName) {
        DatabaseMapping mapping = getMappingForAttributeName(queryKeyName);
        if ((mapping != null) && mapping.isAbstractColumnMapping()) {
            return mapping.getField();
        }

        //mapping is either null or not direct to field.
        //check query keys
        QueryKey queryKey = this.descriptor.getQueryKeyNamed(queryKeyName);
        if ((queryKey != null) && queryKey.isDirectQueryKey()) {
            return ((DirectQueryKey)queryKey).getField();
        }

        //nothing found
        return null;
    }

    /**
     * Cache all the mappings by their attribute and fields.
     */
    public void initialize(AbstractSession session) throws DescriptorException {
        getMappingsByField().clear();
        getReadOnlyMappingsByField().clear();
        getMappingsByAttribute().clear();
        getCloningMappings().clear();
        getEagerMappings().clear();
        getRelationshipMappings().clear();
        if (nonPrimaryKeyMappings == null) {
            nonPrimaryKeyMappings = new ArrayList(10);
        }

        for (Enumeration<DatabaseMapping> mappings = this.descriptor.getMappings().elements();
             mappings.hasMoreElements();) {
            DatabaseMapping mapping = mappings.nextElement();

            // Add attribute to mapping association
            if (!mapping.isWriteOnly()) {
                getMappingsByAttribute().put(mapping.getAttributeName(), mapping);
            }
            // Cache mappings that require cloning.
            if (mapping.isCloningRequired()) {
                getCloningMappings().add(mapping);
            }
            // Cache eager mappings.
            if (mapping.isForeignReferenceMapping() && ((ForeignReferenceMapping)mapping).usesIndirection() && (!mapping.isLazy())) {
                getEagerMappings().add(mapping);
            }

            if (mapping.getReferenceDescriptor() != null && mapping.isCollectionMapping()){
                // only process writable mappings on the defining class in the case of inheritance
                if (getDescriptor() == mapping.getDescriptor()){
                    ((ContainerMapping)mapping).getContainerPolicy().processAdditionalWritableMapKeyFields(session);
                }
            }

            // Cache relationship mappings.
            if (!mapping.isAbstractColumnMapping()) {
                getRelationshipMappings().add(mapping);
            }

            // Add field to mapping association
            for (DatabaseField field : mapping.getFields()) {

                if (mapping.isReadOnly()) {
                    List<DatabaseMapping> readOnlyMappings = getReadOnlyMappingsByField().get(field);

                    if (readOnlyMappings == null) {
                        readOnlyMappings = new ArrayList();
                        getReadOnlyMappingsByField().put(field, readOnlyMappings);
                    }

                    readOnlyMappings.add(mapping);
                } else {
                    if (mapping.isAggregateObjectMapping()) {
                        // For Embeddable class, we need to test read-only
                        // status of individual fields in the embeddable.
                        ObjectBuilder aggregateObjectBuilder = mapping.getReferenceDescriptor().getObjectBuilder();

                        // Look in the non-read-only fields mapping
                        DatabaseMapping aggregatedFieldMapping = aggregateObjectBuilder.getMappingForField(field);

                        if (aggregatedFieldMapping == null) { // mapping must be read-only
                            List<DatabaseMapping> readOnlyMappings = getReadOnlyMappingsByField().get(field);

                            if (readOnlyMappings == null) {
                                readOnlyMappings = new ArrayList();
                                getReadOnlyMappingsByField().put(field, readOnlyMappings);
                            }

                            readOnlyMappings.add(mapping);
                        } else {
                            getMappingsByField().put(field, mapping);
                        }
                    } else { // Not an embeddable mapping
                        if (getMappingsByField().containsKey(field) || mapping.getDescriptor().getAdditionalWritableMapKeyFields().contains(field)) {
                            session.getIntegrityChecker().handleError(DescriptorException.multipleWriteMappingsForField(field.toString(), mapping));
                        } else {
                            getMappingsByField().put(field, mapping);
                        }
                    }
                }
            }
        }
        this.isSimple = getRelationshipMappings().isEmpty();

        initializePrimaryKey(session);
        initializeJoinedAttributes();
        initializeBatchFetchedAttributes();

        if (this.descriptor.usesSequenceNumbers()) {
            DatabaseMapping sequenceMapping = getMappingForField(this.descriptor.getSequenceNumberField());
            if ((sequenceMapping != null) && sequenceMapping.isDirectToFieldMapping()) {
                setSequenceMapping((AbstractDirectMapping)sequenceMapping);
            }
        }
        if(this.descriptor.usesOptimisticLocking()) {
            DatabaseField lockField = this.descriptor.getOptimisticLockingPolicy().getWriteLockField();
            if (lockField != null) {
                DatabaseMapping lockMapping = getDescriptor().getObjectBuilder().getMappingForField(lockField);
                if (lockMapping != null) {
                    this.lockAttribute = lockMapping.getAttributeName();
                }
            }
        }

    }

    public boolean isPrimaryKeyComponentInvalid(Object keyValue, int index) {
        IdValidation idValidation;
        if (index < 0) {
            idValidation = this.descriptor.getIdValidation();
        } else {
            idValidation = this.descriptor.getPrimaryKeyIdValidations().get(index);
        }
        if (idValidation == IdValidation.ZERO) {
            return keyValue == null || Helper.isEquivalentToNull(keyValue);
        } else if (idValidation == IdValidation.NULL) {
            return keyValue == null;
        } else if (idValidation == IdValidation.NEGATIVE) {
            return keyValue == null || Helper.isNumberNegativeOrZero(keyValue);
        } else {
            // idValidation == IdValidation.NONE
            return false;
        }
    }

    public void recordPrivateOwnedRemovals(Object object, UnitOfWorkImpl uow, boolean initialPass) {
        if (!this.descriptor.isDescriptorTypeAggregate()){
            if (!initialPass && uow.getDeletedObjects().containsKey(object)){
                return;
            }
            // do not delete private owned objects that do not exist
            if (uow.doesObjectExist(object)){
                uow.getDeletedObjects().put(object, object);
            } else {
                uow.getCommitManager().markIgnoreCommit(object);
            }
        }
        if (this.descriptor.hasMappingsPostCalculateChanges()){
            for (DatabaseMapping mapping : this.descriptor.getMappingsPostCalculateChanges()){
                mapping.recordPrivateOwnedRemovals(object, uow);
            }
        }
    }

    /**
     * INTERNAL:
     * Post initializations after mappings are initialized.
     */
    public void postInitialize(AbstractSession session) throws DescriptorException {
        // PERF: Cache if needs to unwrap to optimize unwrapping.
        this.hasWrapperPolicy = this.descriptor.hasWrapperPolicy() || session.getProject().hasProxyIndirection();
        // PERF: Used by ObjectLevelReadQuery ResultSetAccessOptimization.
        this.shouldKeepRow = false;
        for (DatabaseField field : this.descriptor.getFields()) {
            if (field.keepInRow()) {
                this.shouldKeepRow = true;
                break;
            }
        }
        // PERF: is there an cache index field that's would not be selected by SOP query. Ignored unless descriptor uses SOP and CachePolicy has cache indexes.
        if (this.descriptor.hasSerializedObjectPolicy() && this.descriptor.getCachePolicy().hasCacheIndexes()) {
            for (List<DatabaseField> indexFields : this.descriptor.getCachePolicy().getCacheIndexes().keySet()) {
                if (!this.descriptor.getSerializedObjectPolicy().getSelectionFields().containsAll(indexFields)) {
                    this.hasCacheIndexesInSopObject = true;
                    break;
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Iterates through all one to one mappings and checks if any of them use joining.
     * <p>
     * By caching the result query execution in the case where there are no joined
     * attributes can be improved.
     */
    public void initializeJoinedAttributes() {
        // For concurrency don't worry about doing this work twice, just make sure
        // if it happens don't add the same joined attributes twice.
        List<DatabaseMapping> joinedAttributes = null;
        List<DatabaseMapping> mappings = this.descriptor.getMappings();
        for (int i = 0; i < mappings.size(); i++) {
            DatabaseMapping mapping = mappings.get(i);
            if (mapping.isForeignReferenceMapping() && ((ForeignReferenceMapping)mapping).isJoinFetched()) {
                if (joinedAttributes == null) {
                    joinedAttributes = new ArrayList();
                }
                joinedAttributes.add(mapping);
            }
        }
        this.joinedAttributes = joinedAttributes;
    }

    /**
     * INTERNAL:
     * Iterates through all one to one mappings and checks if any of them use batch fetching.
     * <p>
     * By caching the result query execution in the case where there are no batch fetched
     * attributes can be improved.
     */
    public void initializeBatchFetchedAttributes() {
        List<DatabaseMapping> batchedAttributes = null;
        for (DatabaseMapping mapping : this.descriptor.getMappings()) {
            if (mapping.isForeignReferenceMapping() && ((ForeignReferenceMapping)mapping).shouldUseBatchReading()) {
                if (batchedAttributes == null) {
                    batchedAttributes = new ArrayList();
                }
                batchedAttributes.add(mapping);
                if (((ForeignReferenceMapping)mapping).getBatchFetchType() == BatchFetchType.IN) {
                    this.hasInBatchFetchedAttribute = true;
                }
            } else if (mapping.isAggregateObjectMapping()) {
                if (mapping.getReferenceDescriptor().getObjectBuilder().hasInBatchFetchedAttribute()) {
                    this.hasInBatchFetchedAttribute = true;
                }
            }
        }
        this.batchFetchedAttributes = batchedAttributes;

        if (this.hasInBatchFetchedAttribute && this.descriptor.hasInheritance()) {
            ClassDescriptor parent = this.descriptor.getInheritancePolicy().getParentDescriptor();
            while (parent != null) {
                parent.getObjectBuilder().setHasInBatchFetchedAttribute(true);
                parent = parent.getInheritancePolicy().getParentDescriptor();
            }
        }
    }

    /**
     * Initialize a cache key.  Called by buildObject and now also by
     * buildWorkingCopyCloneFromRow.
     */
    protected void copyQueryInfoToCacheKey(CacheKey cacheKey, ObjectBuildingQuery query, AbstractRecord databaseRow, AbstractSession session, ClassDescriptor concreteDescriptor) {
        //CR #4365 - used to prevent infinite recursion on refresh object cascade all
        cacheKey.setLastUpdatedQueryId(query.getQueryId());

        if (concreteDescriptor.usesOptimisticLocking()) {
            OptimisticLockingPolicy policy = concreteDescriptor.getOptimisticLockingPolicy();
            Object cacheValue = policy.getValueToPutInCache(databaseRow, session);

            //register the object into the IM and set the write lock object
            cacheKey.setWriteLockValue(cacheValue);
        }
        cacheKey.setReadTime(query.getExecutionTime());
    }

    /**
     * Cache primary key and non primary key mappings.
     */
    public void initializePrimaryKey(AbstractSession session) throws DescriptorException {
        List<DatabaseField> primaryKeyFields = this.descriptor.getPrimaryKeyFields();
        if ((null == primaryKeyFields || primaryKeyFields.isEmpty()) && getDescriptor().isAggregateCollectionDescriptor()) {
            // populate primaryKeys with all mapped fields found in the main table.
            DatabaseTable defaultTable = getDescriptor().getDefaultTable();
            Iterator<DatabaseField> it = getDescriptor().getFields().iterator();
            while(it.hasNext()) {
                DatabaseField field = it.next();
                if(field.getTable().equals(defaultTable) && getMappingsByField().containsKey(field)) {
                    primaryKeyFields.add(field);
                }
            }
            List<DatabaseField> additionalFields = this.descriptor.getAdditionalAggregateCollectionKeyFields();
            for(int i=0; i < additionalFields.size(); i++) {
                DatabaseField additionalField = additionalFields.get(i);
                if(!primaryKeyFields.contains(additionalField)) {
                    primaryKeyFields.add(additionalField);
                }
            }
        }
        createPrimaryKeyExpression(session);

        if(null != primaryKeyMappings) {
            primaryKeyMappings.clear();
        }

        // This must be before because the secondary table primary key fields are registered after
        //but no point doing it if the nonPrimaryKeyMappings collection is null
        if (nonPrimaryKeyMappings != null) {
            nonPrimaryKeyMappings.clear();
            for (Iterator<DatabaseField> fields = getMappingsByField().keySet().iterator(); fields.hasNext();) {
                DatabaseField field = fields.next();
                if (null ==primaryKeyFields || !primaryKeyFields.contains(field)) {
                    DatabaseMapping mapping = getMappingForField(field);
                    if (!getNonPrimaryKeyMappings().contains(mapping)) {
                        getNonPrimaryKeyMappings().add(mapping);
                    }
                }
            }
        }

        if(null != primaryKeyFields) {
            for (int index = 0; index < primaryKeyFields.size(); index++) {
                DatabaseField primaryKeyField = primaryKeyFields.get(index);
                DatabaseMapping mapping = getMappingForField(primaryKeyField);

                if (mapping == null) {
                    if(this.descriptor.isDescriptorTypeAggregate()) {
                        this.mayHaveNullInPrimaryKey = true;
                    } else {
                        throw DescriptorException.noMappingForPrimaryKey(primaryKeyField, this.descriptor);
                    }
                }

                getPrimaryKeyMappings().add(mapping);
                if (mapping != null) {
                    mapping.setIsPrimaryKeyMapping(true);
                }

                // Use the same mapping to map the additional table primary key fields.
                // This is required if someone tries to map to one of these fields.
                if (this.descriptor.hasMultipleTables() && (mapping != null)) {
                    for (Map keyMapping : this.descriptor.getAdditionalTablePrimaryKeyFields().values()) {
                        DatabaseField secondaryField = (DatabaseField) keyMapping.get(primaryKeyField);

                        // This can be null in the custom multiple join case
                        if (secondaryField != null) {
                            getMappingsByField().put(secondaryField, mapping);

                            if (mapping.isAggregateObjectMapping()) {
                                // GF#1153,1391
                                // If AggregateObjectMapping contain primary keys and the descriptor has multiple tables
                                // AggregateObjectMapping should know the the primary key join columns (secondaryField here)
                                // to handle some cases properly
                                ((AggregateObjectMapping) mapping).addPrimaryKeyJoinField(primaryKeyField, secondaryField);
                            }
                        }
                    }
                }
            }
        }

        // PERF: compute if primary key is mapped through direct mappings,
        // to allow fast extraction.
        boolean hasSimplePrimaryKey = true;
        if(null != primaryKeyMappings) {
            for (int index = 0; index < getPrimaryKeyMappings().size(); index++) {
                DatabaseMapping mapping = getPrimaryKeyMappings().get(index);

                // Primary key mapping may be null for aggregate collection.
                if ((mapping == null) || (!mapping.isAbstractColumnMapping())) {
                    hasSimplePrimaryKey = false;
                    break;
                }
            }
        }
        this.descriptor.setHasSimplePrimaryKey(hasSimplePrimaryKey);

        // Set id validation, zero is allowed for composite primary keys.
        boolean wasIdValidationSet = true;
        if (this.descriptor.getIdValidation() == null) {
            wasIdValidationSet = false;
            List<DatabaseField> descriptorPrimaryKeyFields = this.descriptor.getPrimaryKeyFields();
            if (descriptorPrimaryKeyFields != null && descriptorPrimaryKeyFields.size() > 1) {
                this.descriptor.setIdValidation(IdValidation.NULL);
            } else {
                this.descriptor.setIdValidation(IdValidation.ZERO);
            }
        }
        // Initialize id validation per field, default sequence to allowing zero.
        // This defaults to allowing zero for the other fields.
        if (this.descriptor.getPrimaryKeyFields() != null && this.descriptor.getPrimaryKeyIdValidations() == null) {
            this.descriptor.setPrimaryKeyIdValidations(new ArrayList(this.descriptor.getPrimaryKeyFields().size()));
            for (DatabaseField field : this.descriptor.getPrimaryKeyFields()) {
                if (!wasIdValidationSet && this.descriptor.usesSequenceNumbers() && field.equals(this.descriptor.getSequenceNumberField())) {
                    this.descriptor.getPrimaryKeyIdValidations().add(IdValidation.ZERO);
                } else {
                    this.descriptor.getPrimaryKeyIdValidations().add(this.descriptor.getIdValidation());
                }
            }
        }
    }

    /**
     * Returns the clone of the specified object. This is called only from unit of work.
     * This only instantiates the clone instance, it does not clone the attributes,
     * this allows the stub of the clone to be registered before cloning its parts.
     */
    public Object instantiateClone(Object domainObject, AbstractSession session) {
        Object clone = this.descriptor.getCopyPolicy().buildClone(domainObject, session);
        // Clear change tracker.
        if (clone instanceof ChangeTracker) {
            ((ChangeTracker)clone)._persistence_setPropertyChangeListener(null);
        }
        if(clone instanceof FetchGroupTracker) {
            ((FetchGroupTracker)clone)._persistence_setFetchGroup(null);
            ((FetchGroupTracker)clone)._persistence_setSession(null);
        }
        clearPrimaryKey(clone);
        return clone;
    }

    /**
     * Returns the clone of the specified object. This is called only from unit of work.
     * The domainObject sent as parameter is always a copy from the parent of unit of work.
     * bug 2612602 make a call to build a working clone.  This will in turn call the copy policy
     * to make a working clone.  This allows for lighter and heavier clones to
     * be created based on their use.
     * this allows the stub of the clone to be registered before cloning its parts.
     */
    public Object instantiateWorkingCopyClone(Object domainObject, AbstractSession session) {
        return this.descriptor.getCopyPolicy().buildWorkingCopyClone(domainObject, session);
    }

    /**
     * It is now possible to build working copy clones directly from rows.
     * <p>An intermediary original is no longer needed.
     * <p>This has ramifications to the copy policy and cmp, for clones are
     * no longer built via cloning.
     * <p>Instead the copy policy must in some cases not copy at all.
     * this allows the stub of the clone to be registered before cloning its parts.
     */
    public Object instantiateWorkingCopyCloneFromRow(AbstractRecord row, ObjectBuildingQuery query, Object primaryKey, UnitOfWorkImpl unitOfWork) {
        return this.descriptor.getCopyPolicy().buildWorkingCopyCloneFromRow(row, query, primaryKey, unitOfWork);
    }

    public boolean isPrimaryKeyMapping(DatabaseMapping mapping) {
        return getPrimaryKeyMappings().contains(mapping);
    }

    /**
     * INTERNAL:
     * Perform the iteration operation on the objects attributes through the mappings.
     */
    public void iterate(DescriptorIterator iterator) {
        List<DatabaseMapping> mappings;
        // Only iterate on relationships if required.
        if (iterator.shouldIterateOnPrimitives()) {
            mappings = this.descriptor.getMappings();
        } else {
            // PERF: Only process relationships.
            if (this.isSimple) {
                return;
            }
            mappings = this.relationshipMappings;
        }
        int mappingsSize = mappings.size();
        for (int index = 0; index < mappingsSize; index++) {
            mappings.get(index).iterate(iterator);
        }
    }

    /**
     * INTERNAL:
     * Merge changes between the objects, this merge algorithm is dependent on the merge manager.
     */
    public void mergeChangesIntoObject(Object target, ObjectChangeSet changeSet, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        mergeChangesIntoObject(target, changeSet, source, mergeManager, targetSession, false, false);
    }

    /**
     * INTERNAL:
     * Merge changes between the objects, this merge algorithm is dependent on the merge manager.
     */
    public void mergeChangesIntoObject(Object target, ObjectChangeSet changeSet, Object source, MergeManager mergeManager, AbstractSession targetSession, boolean isTargetCloneOfOriginal, boolean shouldMergeFetchGroup) {
        // PERF: Just merge the object for new objects, as the change set is not populated.
        if ((source != null) && changeSet.isNew() && (!this.descriptor.shouldUseFullChangeSetsForNewObjects())) {
            mergeIntoObject(target,  changeSet, true, source, mergeManager, targetSession, false, isTargetCloneOfOriginal, shouldMergeFetchGroup);
        } else {
            List<org.eclipse.persistence.sessions.changesets.ChangeRecord> changes = changeSet.getChanges();
            int size = changes.size();
            for (int index = 0; index < size; index++) {
                ChangeRecord record = (ChangeRecord)changes.get(index);
                //cr 4236, use ObjectBuilder getMappingForAttributeName not the Descriptor one because the
                // ObjectBuilder method is much more efficient.
                DatabaseMapping mapping = getMappingForAttributeName(record.getAttribute());
                mapping.mergeChangesIntoObject(target, record, source, mergeManager, targetSession);
            }
            // PERF: Avoid events if no listeners.
            // Event is already raised in mergeIntoObject, avoid calling twice.
            if (this.descriptor.getEventManager().hasAnyEventListeners()) {
                DescriptorEvent event = new DescriptorEvent(target);
                event.setSession(mergeManager.getSession());
                event.setOriginalObject(source);
                event.setChangeSet(changeSet);
                event.setEventCode(DescriptorEventManager.PostMergeEvent);
                this.descriptor.getEventManager().executeEvent(event);
            }
        }
        this.descriptor.getCachePolicy().indexObjectInCache(changeSet, target, this.descriptor, targetSession);
    }

    /**
     * INTERNAL:
     * Merge the contents of one object into another, this merge algorithm is dependent on the merge manager.
     * This merge also prevents the extra step of calculating the changes when it is not required.
     */
    public void mergeIntoObject(Object target, boolean isUnInitialized, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        mergeIntoObject(target, null, isUnInitialized, source, mergeManager, targetSession, false, false, false);
    }

    /**
     * INTERNAL:
     * Merge the contents of one object into another, this merge algorithm is dependent on the merge manager.
     * This merge also prevents the extra step of calculating the changes when it is not required.
     * If 'cascadeOnly' is true, only foreign reference mappings are merged.
     * If 'isTargetCloneOfOriginal' then the target was create through a shallow clone of the source, so merge basics is not required.
     */
    public void mergeIntoObject(Object target, ObjectChangeSet changeSet, boolean isUnInitialized, Object source, MergeManager mergeManager, AbstractSession targetSession, boolean cascadeOnly, boolean isTargetCloneOfOriginal, boolean shouldMergeFetchGroup) {
        // cascadeOnly is introduced to optimize merge
        // for GF#1139 Cascade merge operations to relationship mappings even if already registered

        FetchGroup sourceFetchGroup = null;
        FetchGroup targetFetchGroup = null;
        if(this.descriptor.hasFetchGroupManager()) {
            sourceFetchGroup = this.descriptor.getFetchGroupManager().getObjectFetchGroup(source);
            targetFetchGroup = this.descriptor.getFetchGroupManager().getObjectFetchGroup(target);
            if(targetFetchGroup != null) {
                if(!targetFetchGroup.isSupersetOf(sourceFetchGroup)) {
                    targetFetchGroup.onUnfetchedAttribute((FetchGroupTracker)target, null);
                }
            } else if (shouldMergeFetchGroup && sourceFetchGroup != null){
                    this.descriptor.getFetchGroupManager().setObjectFetchGroup(target, sourceFetchGroup, targetSession);
            }
        }
        // PERF: Avoid synchronized enumerator as is concurrency bottleneck.
        List<DatabaseMapping> mappings = this.descriptor.getMappings();
        int size = mappings.size();
        for (int index = 0; index < size; index++) {
            DatabaseMapping mapping = mappings.get(index);
            if (((!cascadeOnly && !isTargetCloneOfOriginal)
                    || (cascadeOnly && mapping.isForeignReferenceMapping())
                    || (isTargetCloneOfOriginal && mapping.isCloningRequired()))
                  && (sourceFetchGroup == null || sourceFetchGroup.containsAttributeInternal(mapping.getAttributeName()))) {
                mapping.mergeIntoObject(target, isUnInitialized, source, mergeManager, targetSession);
            }
        }

        // PERF: Avoid events if no listeners.
        if (this.descriptor.getEventManager().hasAnyEventListeners()) {
            DescriptorEvent event = new DescriptorEvent(target);
            event.setSession(mergeManager.getSession());
            event.setOriginalObject(source);
            event.setChangeSet(changeSet);
            event.setEventCode(DescriptorEventManager.PostMergeEvent);
            this.descriptor.getEventManager().executeEvent(event);
        }
    }

    /**
     * Clones the attributes of the specified object. This is called only from unit of work.
     * The domainObject sent as parameter is always a copy from the parent of unit of work.
     */
    public void populateAttributesForClone(Object original, CacheKey cacheKey, Object clone, Integer refreshCascade, AbstractSession cloningSession) {
        List<DatabaseMapping> mappings = getCloningMappings();
        int size = mappings.size();
        if (this.descriptor.hasFetchGroupManager() && this.descriptor.getFetchGroupManager().isPartialObject(original)) {
            FetchGroupManager fetchGroupManager = this.descriptor.getFetchGroupManager();
            for (int index = 0; index < size; index++) {
                DatabaseMapping mapping = mappings.get(index);
                if (fetchGroupManager.isAttributeFetched(original, mapping.getAttributeName())) {
                    mapping.buildClone(original, cacheKey, clone, refreshCascade, cloningSession);
                }
            }
        } else {
            for (int index = 0; index < size; index++) {
                mappings.get(index).buildClone(original, cacheKey, clone, refreshCascade, cloningSession);
            }
        }

        // PERF: Avoid events if no listeners.
        if (this.descriptor.getEventManager().hasAnyEventListeners()) {
            DescriptorEvent event = new DescriptorEvent(clone);
            event.setSession(cloningSession);
            event.setOriginalObject(original);
            event.setDescriptor(descriptor);
            event.setEventCode(DescriptorEventManager.PostCloneEvent);
            cloningSession.deferEvent(event);
        }
    }

    protected void loadBatchReadAttributes(ClassDescriptor concreteDescriptor, Object sourceObject, CacheKey cacheKey, AbstractRecord databaseRow, ObjectBuildingQuery query, JoinedAttributeManager joinManager, boolean isTargetProtected){
        boolean useOnlyMappingsExcludedFromSOP = false;
        if (concreteDescriptor.hasSerializedObjectPolicy() && query.shouldUseSerializedObjectPolicy()) {
            // if true then sopObject has not been deserialized, that means sourceObject has been cached.
            useOnlyMappingsExcludedFromSOP = databaseRow.get(concreteDescriptor.getSerializedObjectPolicy().getField()) != null;
        }
        boolean isUntriggeredResultSetRecord = databaseRow instanceof ResultSetRecord && ((ResultSetRecord)databaseRow).hasResultSet();
        List<Expression> batchExpressions = ((ReadAllQuery)query).getBatchReadAttributeExpressions();
        int size = batchExpressions.size();
        for (int index = 0; index < size; index++) {
            QueryKeyExpression queryKeyExpression = (QueryKeyExpression)batchExpressions.get(index);
            // Only worry about immediate attributes.
            if (queryKeyExpression.getBaseExpression().isExpressionBuilder()) {
                DatabaseMapping mapping = getMappingForAttributeName(queryKeyExpression.getName());

                if (mapping == null) {
                    throw ValidationException.missingMappingForAttribute(concreteDescriptor, queryKeyExpression.getName(), this.toString());
                } else {
                    if (!useOnlyMappingsExcludedFromSOP || mapping.isOutSopObject()) {
                        // Bug 4230655 - do not replace instantiated valueholders.
                        Object attributeValue = mapping.getAttributeValueFromObject(sourceObject);
                        if ((attributeValue != null) && mapping.isForeignReferenceMapping() && ((ForeignReferenceMapping)mapping).usesIndirection() && (!((ForeignReferenceMapping)mapping).getIndirectionPolicy().objectIsInstantiated(attributeValue))) {
                            if (isUntriggeredResultSetRecord && mapping.isObjectReferenceMapping() && ((ObjectReferenceMapping)mapping).isForeignKeyRelationship() && !mapping.isPrimaryKeyMapping()) {
                                // ResultSetRecord hasn't been triggered (still has ResultSet), but values for its primary key field(s) were already extracted from ResultSet,
                                // still need to extract values from ResultSet for foreign key fields.
                                for (DatabaseField field : mapping.getFields()) {
                                    // extract the values from ResultSet into the row
                                    databaseRow.get(field);
                                }
                            }
                            AbstractSession session = query.getExecutionSession();
                            mapping.readFromRowIntoObject(databaseRow, joinManager, sourceObject, cacheKey, query, query.getExecutionSession(),isTargetProtected);
                            session.getIdentityMapAccessorInstance().getIdentityMap(concreteDescriptor).lazyRelationshipLoaded(sourceObject, (ValueHolderInterface) ((ForeignReferenceMapping)mapping).getIndirectionPolicy().getOriginalValueHolder(attributeValue, session), (ForeignReferenceMapping)mapping);
                        }
                    }
                }
            }
        }
    }

    protected void loadJoinedAttributes(ClassDescriptor concreteDescriptor, Object sourceObject, CacheKey cacheKey, AbstractRecord databaseRow, JoinedAttributeManager joinManager, ObjectBuildingQuery query, boolean isTargetProtected){
        boolean useOnlyMappingsExcludedFromSOP = false;
        if (concreteDescriptor.hasSerializedObjectPolicy() && query.shouldUseSerializedObjectPolicy()) {
            // sopObject has not been deserialized, sourceObject must be cached
            useOnlyMappingsExcludedFromSOP = databaseRow.get(concreteDescriptor.getSerializedObjectPolicy().getField()) != null;
        }
        Boolean isUntriggeredResultSetRecord = null;
        List<Expression> joinExpressions = joinManager.getJoinedAttributeExpressions();
        int size = joinExpressions.size();
        for (int index = 0; index < size; index++) {
            QueryKeyExpression queryKeyExpression = (QueryKeyExpression)joinExpressions.get(index);
            QueryKeyExpression baseExpression = (QueryKeyExpression)joinManager.getJoinedAttributes().get(index);
            DatabaseMapping mapping = joinManager.getJoinedAttributeMappings().get(index);

            // Only worry about immediate (excluding aggregates) foreign reference mapping attributes.
            if (queryKeyExpression == baseExpression) {
                if (mapping == null) {
                    throw ValidationException.missingMappingForAttribute(concreteDescriptor, queryKeyExpression.getName(), toString());
                } else {
                    if (!useOnlyMappingsExcludedFromSOP || mapping.isOutSopObject()) {
                        //get the intermediate objects between this expression node and the base builder
                        Object intermediateValue = joinManager.getValueFromObjectForExpression(query.getExecutionSession(), sourceObject, (ObjectExpression)baseExpression.getBaseExpression());
                        // Bug 4230655 - do not replace instantiated valueholders.
                        Object attributeValue = mapping.getAttributeValueFromObject(intermediateValue);
                        if ((attributeValue != null) && mapping.isForeignReferenceMapping() && ((ForeignReferenceMapping)mapping).usesIndirection() && (!((ForeignReferenceMapping)mapping).getIndirectionPolicy().objectIsInstantiated(attributeValue))) {
                            if (mapping.isObjectReferenceMapping() && ((ObjectReferenceMapping)mapping).isForeignKeyRelationship() && !mapping.isPrimaryKeyMapping()) {
                                if (isUntriggeredResultSetRecord == null) {
                                    isUntriggeredResultSetRecord = databaseRow instanceof ResultSetRecord && ((ResultSetRecord) databaseRow).hasResultSet();
                                }
                                if (isUntriggeredResultSetRecord) {
                                    for (DatabaseField field : mapping.getFields()) {
                                        // extract the values from ResultSet into the row
                                        databaseRow.get(field);
                                    }
                                }
                            }
                            AbstractSession session = query.getExecutionSession();
                            mapping.readFromRowIntoObject(databaseRow, joinManager, intermediateValue, cacheKey, query, query.getExecutionSession(), isTargetProtected);
                            session.getIdentityMapAccessorInstance().getIdentityMap(concreteDescriptor).lazyRelationshipLoaded(intermediateValue, (ValueHolderInterface) ((ForeignReferenceMapping)mapping).getIndirectionPolicy().getOriginalValueHolder(attributeValue, session), (ForeignReferenceMapping)mapping);
                        }
                    }
                }
            }
        }
    }
    /**
     * This method is called when a cached Entity needs to be refreshed
     */
    protected boolean refreshObjectIfRequired(ClassDescriptor concreteDescriptor, CacheKey cacheKey, Object domainObject, ObjectBuildingQuery query, JoinedAttributeManager joinManager, AbstractRecord databaseRow, AbstractSession session, boolean targetIsProtected){
        boolean cacheHit = true;
        FetchGroup fetchGroup = query.getExecutionFetchGroup(concreteDescriptor);
        FetchGroupManager fetchGroupManager = concreteDescriptor.getFetchGroupManager();
        //cached object might be partially fetched, only refresh the fetch group attributes of the query if
        //the cached partial object is not invalidated and does not contain all data for the fetch group.
        if (fetchGroupManager != null && fetchGroupManager.isPartialObject(domainObject)) {
            cacheHit = false;
            //only ObjectLevelReadQuery and above support partial objects
            revertFetchGroupData(domainObject, concreteDescriptor, cacheKey, (query), joinManager, databaseRow, session, targetIsProtected);
        } else {
            boolean refreshRequired = true;
            if (concreteDescriptor.usesOptimisticLocking()) {
                OptimisticLockingPolicy policy = concreteDescriptor.getOptimisticLockingPolicy();
                Object cacheValue = policy.getValueToPutInCache(databaseRow, session);
                if (concreteDescriptor.getCachePolicy().shouldOnlyRefreshCacheIfNewerVersion()) {
                    if (cacheValue == null) {
                        refreshRequired = policy.isNewerVersion(databaseRow, domainObject, cacheKey.getKey(), session);
                    } else {
                        // avoid extracting lock value from the row for the second time, that would unnecessary trigger ResultSetRecord
                        refreshRequired = policy.isNewerVersion(cacheValue, domainObject, cacheKey.getKey(), session);
                    }
                    if (!refreshRequired) {
                        cacheKey.setReadTime(query.getExecutionTime());
                    }
                }
                if (refreshRequired) {
                    // Update the write lock value.
                    cacheKey.setWriteLockValue(cacheValue);
                }
            }
            if (refreshRequired) {
                cacheHit = false;
                // CR #4365 - used to prevent infinite recursion on refresh object cascade all.
                cacheKey.setLastUpdatedQueryId(query.getQueryId());
                // Bug 276362 - set the CacheKey's read time (re-validating the CacheKey) before buildAttributesIntoObject is called
                cacheKey.setReadTime(query.getExecutionTime());
                concreteDescriptor.getObjectBuilder().buildAttributesIntoObject(domainObject, cacheKey, databaseRow, query, joinManager, fetchGroup, true, session);
            }
        }
        if (session.getProject().allowExtendedCacheLogging() && cacheKey != null && cacheKey.getObject() != null) {
            session.log(SessionLog.FINEST, SessionLog.CACHE, "cache_item_refresh", new Object[] {domainObject.getClass(), cacheKey.getKey(), Thread.currentThread().getId(), Thread.currentThread().getName()});
        }
        return cacheHit;
    }

    /**
     * Rehash any maps based on fields.
     * This is used to clone descriptors for aggregates, which hammer field names,
     * it is probably better not to hammer the field name and this should be refactored.
     */
    public void rehashFieldDependancies(AbstractSession session) {
        setMappingsByField(Helper.rehashMap(getMappingsByField()));
        setReadOnlyMappingsByField(Helper.rehashMap(getReadOnlyMappingsByField()));
        setFieldsMap(Helper.rehashMap(getFieldsMap()));
        setPrimaryKeyMappings(new ArrayList(2));
        setNonPrimaryKeyMappings(new ArrayList(2));
        initializePrimaryKey(session);
    }

    /**
     * Set the descriptor.
     */
    public void setDescriptor(ClassDescriptor aDescriptor) {
        descriptor = aDescriptor;
    }

    /**
     * All the mappings and their respective attribute associations are cached for performance improvement.
     */
    protected void setMappingsByAttribute(Map<String, DatabaseMapping> theAttributeMappings) {
        mappingsByAttribute = theAttributeMappings;
    }

    /**
     * INTERNAL:
     * All the mappings and their respective field associations are cached for performance improvement.
     */
    public void setMappingsByField(Map<DatabaseField, DatabaseMapping> theFieldMappings) {
        mappingsByField = theFieldMappings;
    }

    /**
     * INTERNAL:
     * All the read-only mappings and their respective field associations are cached for performance improvement.
     */
    public void setReadOnlyMappingsByField(Map<DatabaseField, List<DatabaseMapping>> theReadOnlyFieldMappings) {
        readOnlyMappingsByField = theReadOnlyFieldMappings;
    }

    /**
     * The non primary key mappings are cached to improve performance.
     */
    protected void setNonPrimaryKeyMappings(List<DatabaseMapping> theNonPrimaryKeyMappings) {
        nonPrimaryKeyMappings = theNonPrimaryKeyMappings;
    }

    /**
     * INTERNAL:
     * Set primary key classifications.
     * These are used to ensure a consistent type for the pk values.
     */
    public void setPrimaryKeyClassifications(List<Class> primaryKeyClassifications) {
        this.primaryKeyClassifications = primaryKeyClassifications;
    }

    /**
     * The primary key expression is cached to improve performance.
     */
    public void setPrimaryKeyExpression(Expression criteria) {
        primaryKeyExpression = criteria;
    }

    /**
     * The primary key mappings are cached to improve performance.
     */
    protected void setPrimaryKeyMappings(List<DatabaseMapping> thePrimaryKeyMappings) {
        primaryKeyMappings = thePrimaryKeyMappings;
    }

    @Override
    public String toString() {
        return Helper.getShortClassName(getClass()) + "(" + this.descriptor.toString() + ")";
    }

    /**
     * Unwrap the object if required.
     * This is used for the wrapper policy support and EJB.
     */
    public Object unwrapObject(Object proxy, AbstractSession session) {
        if (!this.hasWrapperPolicy) {
            return proxy;
        }
        if (proxy == null) {
            return null;
        }
        // PERF: Using direct variable access.

        // Check if already unwrapped.
        if ((!this.descriptor.hasWrapperPolicy()) || (this.descriptor.getJavaClass() == proxy.getClass()) || (!this.descriptor.getWrapperPolicy().isWrapped(proxy))) {
            if (session.getProject().hasProxyIndirection()) {
                //Bug#3947714  Check and trigger the proxy here
                return ProxyIndirectionPolicy.getValueFromProxy(proxy);
            }
            return proxy;
        }

        // Allow for inheritance, the concrete wrapper must always be used.
        if (this.descriptor.hasInheritance() && (this.descriptor.getInheritancePolicy().hasChildren())) {
            ClassDescriptor descriptor = session.getDescriptor(proxy);
            if (descriptor != this.descriptor) {
                return descriptor.getObjectBuilder().unwrapObject(proxy, session);
            }
        }

        return this.descriptor.getWrapperPolicy().unwrapObject(proxy, session);
    }

    /**
     * INTERNAL:
     * Used to updated any attributes that may be cached on a woven entity
     */
    public void updateCachedAttributes(PersistenceEntity persistenceEntity, CacheKey cacheKey, Object primaryKey){
        persistenceEntity._persistence_setCacheKey(cacheKey);
        persistenceEntity._persistence_setId(primaryKey);
    }

    /**
     * Validates the object builder. This is done once the object builder initialized and descriptor
     * fires this validation.
     */
    public void validate(AbstractSession session) throws DescriptorException {
        if (this.descriptor.usesSequenceNumbers()) {
            if (getMappingForField(this.descriptor.getSequenceNumberField()) == null) {
                throw DescriptorException.mappingForSequenceNumberField(this.descriptor);
            }
        }
    }

    /**
     * Verify that an object has been deleted from the database.
     * An object can span multiple tables.  A query is performed on each of
     * these tables using the primary key values of the object as the selection
     * criteria.  If the query returns a result then the object has not been
     * deleted from the database.  If no result is returned then each of the
     * mappings is asked to verify that the object has been deleted. If all mappings
     * answer true then the result is true.
     */
    public boolean verifyDelete(Object object, AbstractSession session) {
        AbstractRecord translationRow = buildRowForTranslation(object, session);

        // If a call is used generated SQL cannot be executed, the call must be used.
        if ((this.descriptor.getQueryManager().getReadObjectQuery() != null) && this.descriptor.getQueryManager().getReadObjectQuery().isCallQuery()) {
            Object result = session.readObject(object);
            if (result != null) {
                return false;
            }
        } else {
            for (Enumeration<DatabaseTable> tables = this.descriptor.getTables().elements();
                 tables.hasMoreElements();) {
                DatabaseTable table = tables.nextElement();

                SQLSelectStatement sqlStatement = new SQLSelectStatement();
                sqlStatement.addTable(table);
                if (table == this.descriptor.getTables().firstElement()) {
                    sqlStatement.setWhereClause((Expression)getPrimaryKeyExpression().clone());
                } else {
                    sqlStatement.setWhereClause(buildPrimaryKeyExpression(table));
                }
                DatabaseField all = new DatabaseField("*");
                all.setTable(table);
                sqlStatement.addField(all);
                sqlStatement.normalize(session, null);

                DataReadQuery dataReadQuery = new DataReadQuery();
                dataReadQuery.setSQLStatement(sqlStatement);
                dataReadQuery.setSessionName(this.descriptor.getSessionName());

                // execute the query and check if there is a valid result
                List queryResults = (List)session.executeQuery(dataReadQuery, translationRow);
                if (!queryResults.isEmpty()) {
                    return false;
                }
            }
        }

        // now ask each of the mappings to verify that the object has been deleted.
        for (Enumeration<DatabaseMapping> mappings = this.descriptor.getMappings().elements();
             mappings.hasMoreElements();) {
            DatabaseMapping mapping = mappings.nextElement();

            if (!mapping.verifyDelete(object, session)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Return if the descriptor has a wrapper policy.
     * Cache for performance.
     */
    public boolean hasWrapperPolicy() {
        return hasWrapperPolicy;
    }

    /**
     * Set if the descriptor has a wrapper policy.
     * Cached for performance.
     */
    public void setHasWrapperPolicy(boolean hasWrapperPolicy) {
        this.hasWrapperPolicy = hasWrapperPolicy;
    }

    /**
     * Wrap the object if required.
     * This is used for the wrapper policy support and EJB.
     */
    public Object wrapObject(Object implementation, AbstractSession session) {
        if (!this.hasWrapperPolicy) {
            return implementation;
        }
        if (implementation == null) {
            return null;
        }
        // PERF: Using direct variable access.

        // Check if already wrapped.
        if ((!this.descriptor.hasWrapperPolicy()) || this.descriptor.getWrapperPolicy().isWrapped(implementation)) {
            return implementation;
        }

        // Allow for inheritance, the concrete wrapper must always be used.
        if (this.descriptor.hasInheritance() && this.descriptor.getInheritancePolicy().hasChildren() && (implementation.getClass() != this.descriptor.getJavaClass())) {
            ClassDescriptor descriptor = session.getDescriptor(implementation);
            if (descriptor != this.descriptor) {
                return descriptor.getObjectBuilder().wrapObject(implementation, session);
            }
        }
        return this.descriptor.getWrapperPolicy().wrapObject(implementation, session);
    }

    public boolean isXMLObjectBuilder() {
        return false;
    }

    public String getLockAttribute() {
        return this.lockAttribute;
    }

    public boolean shouldKeepRow() {
        return this.shouldKeepRow;
    }

    public boolean hasCacheIndexesInSopObject() {
        return this.hasCacheIndexesInSopObject;
    }

    @Override
    public AbstractRecord createRecordFromXMLContext(XMLContext context) {
        return createRecord((AbstractSession)context.getSession());
    }
}
