/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2018 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
//     02/26/2009-2.0 Guy Pelletier
//       - 264001: dot notation for mapped-by and order-by
//     08/23/2010-2.2 Michael O'Brien
//        - 323043: application.xml module ordering may cause weaving not to occur causing an NPE.
//                       warn if expected "_persistence_//_vh" method not found
//                       instead of throwing NPE during deploy validation.
//     07/19/2011-2.2.1 Guy Pelletier
//       - 338812: ManyToMany mapping in aggregate object violate integrity constraint on deletion
//     04/09/2012-2.4 Guy Pelletier
//       - 374377: OrderBy with ElementCollection doesn't work
//     14/05/2012-2.4 Guy Pelletier
//       - 376603: Provide for table per tenant support for multitenant applications
//     08/29/2016 Jody Grassel
//       - 500441: Eclipselink core has System.getProperty() calls that are not potentially executed under doPriv()
package org.eclipse.persistence.mappings;

import java.beans.PropertyChangeListener;
import java.util.*;

import org.eclipse.persistence.annotations.OrderCorrectionType;
import org.eclipse.persistence.config.SystemProperties;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.changetracking.*;
import org.eclipse.persistence.internal.descriptors.changetracking.*;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.indirection.*;
import org.eclipse.persistence.internal.descriptors.*;
import org.eclipse.persistence.internal.expressions.*;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.indirection.*;
import org.eclipse.persistence.internal.queries.*;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.sessions.remote.*;
import org.eclipse.persistence.internal.sessions.*;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.sessions.remote.*;
import org.eclipse.persistence.sessions.CopyGroup;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.Project;

/**
 * <p><b>Purpose</b>: Abstract class for relationship mappings which store collection of objects
 *
 * @author Sati
 * @since TOPLink/Java 1.0
 */
public abstract class CollectionMapping extends ForeignReferenceMapping implements ContainerMapping {

    /** Used for delete all in m-m, dc and delete all optimization in 1-m. */
    protected transient ModifyQuery deleteAllQuery;
    protected transient boolean hasCustomDeleteAllQuery;
    protected ContainerPolicy containerPolicy;
    protected boolean hasOrderBy;

    /** Field holds the order of elements in the list in the db, requires collection of type List, may be not null only in case isListOrderFieldSupported==true */
    protected DatabaseField listOrderField;
    /** Indicates whether the mapping supports listOrderField, if it doesn't attempt to set listOrderField throws exception. */
    protected boolean isListOrderFieldSupported;
    /** Query used when order of list members is changed. Used only if listOrderField!=null */
    protected transient DataModifyQuery changeOrderTargetQuery;
    /**
     * Specifies what should be done if the list of values read from listOrserField is invalid
     * (there should be no nulls, no duplicates, no "holes").
     **/
    protected OrderCorrectionType orderCorrectionType;

    /** Store if the mapping can batch delete reference objects. */
    protected Boolean mustDeleteReferenceObjectsOneByOne = null;

    /** Flag to indicate if collection needs to be synchronized instead of cloning during merge. */
    protected static boolean isSynchronizeOnMerge = Boolean.getBoolean("eclipselink.synchronizeCollectionOnMerge");

    /**
     * PUBLIC:
     * Default constructor.
     */
    protected CollectionMapping() {
        this.selectionQuery = new ReadAllQuery();
        this.hasCustomDeleteAllQuery = false;
        this.containerPolicy = ContainerPolicy.buildDefaultPolicy();
        this.hasOrderBy = false;
        this.isListOrderFieldSupported = false;
    }

    /**
     * PUBLIC:
     * Provide order support for queryKeyName in ascending order
     */
    public void addAscendingOrdering(String queryKeyName) {
        this.hasOrderBy = true;
        if (queryKeyName == null) {
            return;
        }

        ((ReadAllQuery)getSelectionQuery()).addAscendingOrdering(queryKeyName);
    }

    /**
     * PUBLIC:
     * Provide order support for queryKeyName in descending order.
     */
    public void addDescendingOrdering(String queryKeyName) {
        this.hasOrderBy = true;
        if (queryKeyName == null) {
            return;
        }

        ((ReadAllQuery)getSelectionQuery()).addDescendingOrdering(queryKeyName);
    }

    /**
     * PUBLIC:
     * Provide order support for queryKeyName in descending or ascending order.
     * Called from the jpa metadata processing of an order by value.
     */
    public void addOrderBy(String queryKeyName, boolean isDescending) {
        if (isDescending) {
            addDescendingOrdering(queryKeyName);
        } else {
            addAscendingOrdering(queryKeyName);
        }
    }

    /**
     * PUBLIC:
     * Provide order support for queryKeyName in ascending or descending order.
     * Called from the jpa metadata processing of an order by value. The
     * aggregate name may be chained through the dot notation.
     */
    public void addAggregateOrderBy(String aggregateName, String queryKeyName, boolean isDescending) {
        this.hasOrderBy = true;

        ReadAllQuery readAllQuery = (ReadAllQuery) getSelectionQuery();
        ExpressionBuilder builder = readAllQuery.getExpressionBuilder();
        Expression expression = null;

        if (aggregateName.contains(".")) {
            StringTokenizer st = new StringTokenizer(aggregateName, ".");
            while (st.hasMoreTokens()) {
                if (expression == null) {
                    expression = builder.get(st.nextToken());
                } else {
                    expression = expression.get(st.nextToken());
                }
            }

            expression = expression.get(queryKeyName);
        } else {
            // Single level aggregate
            if (aggregateName.equals("")) {
                expression = builder.get(queryKeyName);
            } else {
                expression = builder.get(aggregateName).get(queryKeyName);
            }
        }

        if (isDescending) {
            readAllQuery.addOrdering(expression.descending());
        } else {
            readAllQuery.addOrdering(expression.ascending());
        }
    }

    /**
     * INTERNAL:
     * Used during building the backup shallow copy to copy
     * the vector without re-registering the target objects.
     */
    @Override
    public Object buildBackupCloneForPartObject(Object attributeValue, Object clone, Object backup, UnitOfWorkImpl unitOfWork) {
        // Check for null
        if (attributeValue == null) {
            return this.containerPolicy.containerInstance(1);
        } else {
            return this.containerPolicy.cloneFor(attributeValue);
        }
    }

    /**
     * INTERNAL:
     * Require for cloning, the part must be cloned.
     * Ignore the objects, use the attribute value.
     */
    @Override
    public Object buildCloneForPartObject(Object attributeValue, Object original, CacheKey cacheKey, Object clone, AbstractSession cloningSession, Integer refreshCascade, boolean isExisting, boolean isFromSharedCache) {
        ContainerPolicy containerPolicy = this.containerPolicy;
        if (attributeValue == null) {
            Object container = containerPolicy.containerInstance(1);
            if (cloningSession.isUnitOfWork() && (this.getDescriptor().getObjectChangePolicy().isObjectChangeTrackingPolicy()) && ((clone != null) && (((ChangeTracker)clone)._persistence_getPropertyChangeListener() != null)) && (container instanceof CollectionChangeTracker)) {
                ((CollectionChangeTracker)container).setTrackedAttributeName(this.getAttributeName());
                ((CollectionChangeTracker)container)._persistence_setPropertyChangeListener(((ChangeTracker)clone)._persistence_getPropertyChangeListener());
            }
            return container;
        }
        Object clonedAttributeValue = containerPolicy.containerInstance(containerPolicy.sizeFor(attributeValue));

        Object temporaryCollection = null;
        if (isSynchronizeOnMerge) {
            // I need to synchronize here to prevent the collection from changing while I am cloning it.
            // This will occur when I am merging into the cache and I am instantiating a UOW valueHolder at the same time
            // I can not synchronize around the clone, as this will cause deadlocks, so I will need to copy the collection then create the clones
            // I will use a temporary collection to help speed up the process
            synchronized (attributeValue) {
                temporaryCollection = containerPolicy.cloneFor(attributeValue);
            }
        } else {
            // Clone is used while merging into cache. It can operate directly without synchronize/clone.
            temporaryCollection = attributeValue;
        }
        for (Object valuesIterator = containerPolicy.iteratorFor(temporaryCollection);containerPolicy.hasNext(valuesIterator);){
            containerPolicy.addNextValueFromIteratorInto(valuesIterator, clone, cacheKey, clonedAttributeValue, this, refreshCascade, cloningSession, isExisting, isFromSharedCache);
        }
        if (cloningSession.isUnitOfWork() && (this.getDescriptor().getObjectChangePolicy().isObjectChangeTrackingPolicy()) && ((clone != null) && (((ChangeTracker)clone)._persistence_getPropertyChangeListener() != null)) && (clonedAttributeValue instanceof CollectionChangeTracker)) {
            ((CollectionChangeTracker)clonedAttributeValue).setTrackedAttributeName(this.getAttributeName());
            ((CollectionChangeTracker)clonedAttributeValue)._persistence_setPropertyChangeListener(((ChangeTracker)clone)._persistence_getPropertyChangeListener());
        }
        if(temporaryCollection instanceof IndirectList) {
            ((IndirectList)clonedAttributeValue).setIsListOrderBrokenInDb(((IndirectList)temporaryCollection).isListOrderBrokenInDb());
        }
        return clonedAttributeValue;
    }

    /**
     * INTERNAL:
     * Performs a first level clone of the attribute.  This generally means on the container will be cloned.
     */
    @Override
    public Object buildContainerClone(Object attributeValue, AbstractSession cloningSession){
        Object newContainer = this.containerPolicy.containerInstance(this.containerPolicy.sizeFor(attributeValue));
        Object valuesIterator = this.containerPolicy.iteratorFor(attributeValue);
        while (this.containerPolicy.hasNext(valuesIterator)) {
            Object originalValue = this.containerPolicy.next(valuesIterator, cloningSession);
            this.containerPolicy.addInto(originalValue, newContainer, cloningSession);
        }
        return newContainer;
    }

   /**
     * INTERNAL:
     * Copy of the attribute of the object.
     * This is NOT used for unit of work but for templatizing an object.
     */
    @Override
    public void buildCopy(Object copy, Object original, CopyGroup group) {
        Object attributeValue = getRealCollectionAttributeValueFromObject(original, group.getSession());
        Object valuesIterator = this.containerPolicy.iteratorFor(attributeValue);
        attributeValue = this.containerPolicy.containerInstance(this.containerPolicy.sizeFor(attributeValue));
        while (this.containerPolicy.hasNext(valuesIterator)) {
            Object originalValue = this.containerPolicy.next(valuesIterator, group.getSession());
            Object copyValue = originalValue;
            Object originalKey = this.containerPolicy.keyFromIterator(valuesIterator);
            Object copyKey = originalKey;
            if (group.shouldCascadeAllParts() || (group.shouldCascadePrivateParts() && isPrivateOwned()) || group.shouldCascadeTree()) {
                copyValue = copyElement(originalValue, group);
                copyKey = group.getSession().copyInternal(originalKey, group);
            } else {
                // Check for backrefs to copies.
                copyValue = group.getCopies().get(originalValue);
                if (copyValue == null) {
                    copyValue = originalValue;
                }
            }
            this.containerPolicy.addInto(copyKey, copyValue, attributeValue, group.getSession());
        }
        // if value holder is used, then the value holder shared with original substituted for a new ValueHolder.
        getIndirectionPolicy().reset(copy);
        setRealAttributeValueInObject(copy, attributeValue);
    }

    /**
     * INTERNAL:
     * Copies member's value
     */
    protected Object copyElement(Object original, CopyGroup group) {
        return group.getSession().copyInternal(original, group);
    }

    /**
     * INTERNAL:
     * Clone the element, if necessary.
     */
    public Object buildElementUnitOfWorkClone(Object element, Object parent, Integer refreshCascade, UnitOfWorkImpl unitOfWork, boolean isExisting, boolean isFromSharedCache) {
        // optimize registration to knowledge of existence
        if (refreshCascade != null ){
            switch(refreshCascade){
            case ObjectBuildingQuery.CascadeAllParts :
                return unitOfWork.mergeClone(element, MergeManager.CASCADE_ALL_PARTS, true);
            case ObjectBuildingQuery.CascadePrivateParts :
                return unitOfWork.mergeClone(element, MergeManager.CASCADE_PRIVATE_PARTS, true);
            case ObjectBuildingQuery.CascadeByMapping :
                return unitOfWork.mergeClone(element, MergeManager.CASCADE_BY_MAPPING, true);
            default:
                return unitOfWork.mergeClone(element, MergeManager.NO_CASCADE, true);
            }
        }else{
            if (isExisting) {
                return unitOfWork.registerExistingObject(element, isFromSharedCache);
            } else {// not known whether existing or not
                return unitOfWork.registerObject(element);
            }
        }
    }

    /**
     * INTERNAL:
     * Clone the element, if necessary.
     */
    public Object buildElementClone(Object element, Object parent, CacheKey parentCacheKey, Integer refreshCascade, AbstractSession cloningSession, boolean isExisting, boolean isFromSharedCache) {
        if (cloningSession.isUnitOfWork()){
            return buildElementUnitOfWorkClone(element, parent, refreshCascade, (UnitOfWorkImpl)cloningSession, isExisting, isFromSharedCache);
        }
        if (referenceDescriptor.getCachePolicy().isProtectedIsolation()){
            return cloningSession.createProtectedInstanceFromCachedData(element, refreshCascade, referenceDescriptor);
        }
        return element;
    }

    /**
     * INTERNAL:
     * In case Query By Example is used, this method generates an expression from a attribute value pair.  Since
     * this is an Aggregate mapping, a recursive call is made to the buildExpressionFromExample method of
     * ObjectBuilder.
     */
    @Override
    public Expression buildExpression(Object queryObject, QueryByExamplePolicy policy, Expression expressionBuilder, Map processedObjects, AbstractSession session) {
        String bypassProperty = PrivilegedAccessHelper.getSystemProperty(SystemProperties.DO_NOT_PROCESS_XTOMANY_FOR_QBE);
        if (this.getContainerPolicy().isMapPolicy() ||  (bypassProperty != null && bypassProperty.toLowerCase().equals("true")) ){
            // not supported
            return super.buildExpression(queryObject, policy, expressionBuilder, processedObjects, session);
        }
        String attributeName = this.getAttributeName();
        Object attributeValue = this.getRealAttributeValueFromObject(queryObject, session);
        if (attributeValue != null && getContainerPolicy().isEmpty(attributeValue)){
            //empty is the same as null
            attributeValue = null;
        }

        if (!policy.shouldIncludeInQuery(queryObject.getClass(), attributeName, attributeValue)) {
            //the attribute name and value pair is not to be included in the query.
            return null;
        }

        if (attributeValue == null) {
            //even though it is null, it is to be always included in the query
            Expression expression = expressionBuilder.anyOf(attributeName);
            return policy.completeExpressionForNull(expression);
        }

        Object iterator = getContainerPolicy().iteratorFor(attributeValue);
        Expression exp = null;
        ObjectBuilder objectBuilder = getReferenceDescriptor().getObjectBuilder();
        Expression base = expressionBuilder.anyOf(attributeName);
        while(getContainerPolicy().hasNext(iterator)){
            Object element = getContainerPolicy().next(iterator, session);
            if (exp == null){
                exp = objectBuilder.buildExpressionFromExample(element, policy, base, processedObjects, session);
            }else{
                exp = exp.or(objectBuilder.buildExpressionFromExample(element, policy, base, processedObjects, session));
            }
        }
        return exp;
    }

    /**
     * INTERNAL:
     * This method will access the target relationship and create a list of information to rebuild the relationship.
     * This method is used in combination with the CachedValueHolder to store references to PK's to be loaded
     * from a cache instead of a query.
     */
    @Override
    public Object[] buildReferencesPKList(Object entity, Object attribute, AbstractSession session){
        Object container = indirectionPolicy.getRealAttributeValueFromObject(entity, attribute);
        return containerPolicy.buildReferencesPKList(container, session);
    }

    /**
     * INTERNAL:
     * Cascade perform delete through mappings that require the cascade
     */
    @Override
    public void cascadePerformRemoveIfRequired(Object object, UnitOfWorkImpl uow, Map visitedObjects) {
        if (!this.cascadeRemove) {
            return;
        }
        Object cloneAttribute = getAttributeValueFromObject(object);
        if (cloneAttribute == null) {
            return;
        }
        // PERF: If private owned and not instantiated, then avoid instantiating, delete-all will handle deletion.
        if ((this.isPrivateOwned) && usesIndirection() && (!mustDeleteReferenceObjectsOneByOne())) {
            if (!this.indirectionPolicy.objectIsEasilyInstantiated(cloneAttribute)) {
                return;
            }
        }

        ContainerPolicy cp = this.containerPolicy;
        Object cloneObjectCollection = null;
        cloneObjectCollection = getRealCollectionAttributeValueFromObject(object, uow);
        Object cloneIter = cp.iteratorFor(cloneObjectCollection);
        while (cp.hasNext(cloneIter)) {
            Object wrappedObject = cp.nextEntry(cloneIter, uow);
            Object nextObject = cp.unwrapIteratorResult(wrappedObject);
            if ((nextObject != null) && (!visitedObjects.containsKey(nextObject))) {
                visitedObjects.put(nextObject, nextObject);
                if (this.isCascadeOnDeleteSetOnDatabase && isOneToManyMapping()) {
                    uow.getCascadeDeleteObjects().add(nextObject);
                }
                uow.performRemove(nextObject, visitedObjects);
                cp.cascadePerformRemoveIfRequired(wrappedObject, uow, visitedObjects);
            }
        }
    }

    /**
     * INTERNAL:
     * Cascade perform removal of orphaned private owned objects from the UnitOfWorkChangeSet
     */
    @Override
    public void cascadePerformRemovePrivateOwnedObjectFromChangeSetIfRequired(Object object, UnitOfWorkImpl uow, Map visitedObjects) {
        // if the object is not instantiated, do not instantiate or cascade
        Object attributeValue = getAttributeValueFromObject(object);
        if (attributeValue != null && this.indirectionPolicy.objectIsInstantiated(attributeValue)) {
            Object realObjectCollection = getRealCollectionAttributeValueFromObject(object, uow);
            ContainerPolicy cp = this.containerPolicy;
            for (Object cloneIter = cp.iteratorFor(realObjectCollection); cp.hasNext(cloneIter);) {
                Object nextObject = cp.next(cloneIter, uow);
                if (nextObject != null && !visitedObjects.containsKey(nextObject)) {
                    visitedObjects.put(nextObject, nextObject);
                    // remove the object from the UnitOfWork ChangeSet
                    uow.performRemovePrivateOwnedObjectFromChangeSet(nextObject, visitedObjects);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Cascade discover and persist new objects during commit.
     */
    @Override
    public void cascadeDiscoverAndPersistUnregisteredNewObjects(Object object, Map newObjects, Map unregisteredExistingObjects, Map visitedObjects, UnitOfWorkImpl uow, Set cascadeErrors) {
        Object cloneAttribute = getAttributeValueFromObject(object);
        if ((cloneAttribute == null) || (!this.indirectionPolicy.objectIsInstantiated(cloneAttribute))) {
            if (cloneAttribute instanceof IndirectCollection)  {
                IndirectCollection collection = (IndirectCollection)cloneAttribute;
                if (collection.hasDeferredChanges()) {
                    Iterator iterator = collection.getAddedElements().iterator();
                    boolean cascade = isCascadePersist();
                    while (iterator.hasNext()) {
                        Object nextObject = iterator.next();
                        // remove private owned object from uow list
                        if (isCandidateForPrivateOwnedRemoval()){
                            uow.removePrivateOwnedObject(this, nextObject);
                        }
                        uow.discoverAndPersistUnregisteredNewObjects(nextObject, cascade, newObjects, unregisteredExistingObjects, visitedObjects, cascadeErrors);
                    }
                }
            }
            return;
        }

        ContainerPolicy containerPolicy = this.containerPolicy;
        Object cloneObjectCollection = getRealCollectionAttributeValueFromObject(object, uow);
        Object iterator = containerPolicy.iteratorFor(cloneObjectCollection);
        boolean cascade = isCascadePersist();
        while (containerPolicy.hasNext(iterator)) {
            Object wrappedObject = containerPolicy.nextEntry(iterator, uow);
            Object nextObject = containerPolicy.unwrapIteratorResult(wrappedObject);
            // remove private owned object from uow list
            if (isCandidateForPrivateOwnedRemoval()) {
                uow.removePrivateOwnedObject(this, nextObject);
            }
            uow.discoverAndPersistUnregisteredNewObjects(nextObject, cascade, newObjects, unregisteredExistingObjects, visitedObjects, cascadeErrors);
            containerPolicy.cascadeDiscoverAndPersistUnregisteredNewObjects(wrappedObject, newObjects, unregisteredExistingObjects, visitedObjects, uow, cascadeErrors);
        }
    }

    /**
     * INTERNAL:
     * Cascade registerNew for Create through mappings that require the cascade
     */
    @Override
    public void cascadeRegisterNewIfRequired(Object object, UnitOfWorkImpl uow, Map visitedObjects) {
        if (!this.cascadePersist) {
            return;
        }
        Object attributeValue = getAttributeValueFromObject(object);
        if ((attributeValue == null)
            // Also check if the source is new, then must always cascade.
            || (!this.indirectionPolicy.objectIsInstantiated(attributeValue) && !uow.isCloneNewObject(object))) {
            return;
        }

        ContainerPolicy cp = this.containerPolicy;
        Object cloneObjectCollection = null;
        cloneObjectCollection = getRealCollectionAttributeValueFromObject(object, uow);
        Object cloneIter = cp.iteratorFor(cloneObjectCollection);
        // add private owned objects to uow list if mapping is a candidate and uow should discover new objects and the source object is new.
        boolean shouldAddPrivateOwnedObject = isCandidateForPrivateOwnedRemoval() && uow.shouldDiscoverNewObjects() && uow.isCloneNewObject(object);
        while (cp.hasNext(cloneIter)) {
            Object wrappedObject = cp.nextEntry(cloneIter, uow);
            Object nextObject = cp.unwrapIteratorResult(wrappedObject);
            if (shouldAddPrivateOwnedObject && nextObject != null) {
                uow.addPrivateOwnedObject(this, nextObject);
            }
            uow.registerNewObjectForPersist(nextObject, visitedObjects);
            cp.cascadeRegisterNewIfRequired(wrappedObject, uow, visitedObjects);
        }
    }

    /**
     * INTERNAL:
     * This method is used to store the FK fields that can be cached that correspond to noncacheable mappings
     * the FK field values will be used to re-issue the query when cloning the shared cache entity
     */
    @Override
    public void collectQueryParameters(Set<DatabaseField> record){
        //no-op for mappings that do not support PROTECTED cache isolation
    }

    /**
     * INTERNAL:
     * Used by AttributeLevelChangeTracking to update a changeRecord with calculated changes
     * as apposed to detected changes.  If an attribute can not be change tracked it's
     * changes can be detected through this process.
     */
    @Override
    public void calculateDeferredChanges(ChangeRecord changeRecord, AbstractSession session) {
        CollectionChangeRecord collectionRecord = (CollectionChangeRecord)changeRecord;
        // TODO: Handle events that fired after collection was replaced.
        compareCollectionsForChange(collectionRecord.getOriginalCollection(), collectionRecord.getLatestCollection(), collectionRecord, session);

        if(this.isPrivateOwned()) {
            postCalculateChanges(collectionRecord, (UnitOfWorkImpl)session);
        }
    }

    /**
     * INTERNAL:
     * The mapping clones itself to create deep copy.
     */
    @Override
    public Object clone() {
        CollectionMapping clone = (CollectionMapping)super.clone();
        clone.setDeleteAllQuery((ModifyQuery)getDeleteAllQuery().clone());
        if (this.listOrderField != null) {
            clone.listOrderField = this.listOrderField.clone();
        }
        if(this.changeOrderTargetQuery != null) {
            clone.changeOrderTargetQuery = (DataModifyQuery)this.changeOrderTargetQuery.clone();
        }

        // Clone the container policy.
        clone.containerPolicy = (ContainerPolicy) this.containerPolicy.clone();

        return clone;
    }

    /**
     * INTERNAL:
     * This method is used to calculate the differences between two collections.
     */
    public void compareCollectionsForChange(Object oldCollection, Object newCollection, ChangeRecord changeRecord, AbstractSession session) {
        this.containerPolicy.compareCollectionsForChange(oldCollection, newCollection, (CollectionChangeRecord) changeRecord, session, getReferenceDescriptor());
    }

    /**
     * INTERNAL:
     * This method is used to create a change record from comparing two collections.
     */
    @Override
    public ChangeRecord compareForChange(Object clone, Object backUp, ObjectChangeSet owner, AbstractSession session) {
        Object cloneAttribute = null;
        Object backUpAttribute = null;

        Object backUpObjectCollection = null;

        cloneAttribute = getAttributeValueFromObject(clone);

        if ((cloneAttribute != null) && (!this.indirectionPolicy.objectIsInstantiated(cloneAttribute))) {
            return null;
        }

        if (!owner.isNew()) {// if the changeSet is for a new object then we must record all of the attributes
            backUpAttribute = getAttributeValueFromObject(backUp);

            if ((cloneAttribute == null) && (backUpAttribute == null)) {
                return null;
            }

            backUpObjectCollection = getRealCollectionAttributeValueFromObject(backUp, session);
        }

        Object cloneObjectCollection = null;
        if (cloneAttribute != null) {
            cloneObjectCollection = getRealCollectionAttributeValueFromObject(clone, session);
        } else {
            cloneObjectCollection = this.containerPolicy.containerInstance(1);
        }

        CollectionChangeRecord changeRecord = new CollectionChangeRecord(owner);
        changeRecord.setAttribute(getAttributeName());
        changeRecord.setMapping(this);
        compareCollectionsForChange(backUpObjectCollection, cloneObjectCollection, changeRecord, session);
        if (changeRecord.hasChanges()) {
            changeRecord.setOriginalCollection(backUpObjectCollection);
            return changeRecord;
        }
        return null;
    }

    /**
     * INTERNAL:
     * Compare the attributes belonging to this mapping for the objects.
     */
    @Override
    public boolean compareObjects(Object firstObject, Object secondObject, AbstractSession session) {
        Object firstObjectCollection = getRealCollectionAttributeValueFromObject(firstObject, session);
        Object secondObjectCollection = getRealCollectionAttributeValueFromObject(secondObject, session);

        return super.compareObjects(firstObjectCollection, secondObjectCollection, session);
    }

    /**
     * INTERNAL:
     * Write the changes defined in the change set for the mapping.
     * Mapping added or removed events are raised to allow the mapping to write the changes as required.
     */
    public void writeChanges(ObjectChangeSet changeSet, WriteObjectQuery query) throws DatabaseException, OptimisticLockException {
        CollectionChangeRecord record = (CollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName());
        if (record != null) {
            for (ObjectChangeSet removedChangeSet : record.getRemoveObjectList().values()) {
                objectRemovedDuringUpdate(query, this.containerPolicy.getCloneDataFromChangeSet(removedChangeSet), null);
                if (removedChangeSet.getOldKey() != null){
                    this.containerPolicy.propogatePostUpdate(query, removedChangeSet.getOldKey());
                }
            }
            Map extraData = null;
            Object currentObjects = null;
            for (ObjectChangeSet addedChangeSet : record.getAddObjectList().values()) {
                if (this.listOrderField != null) {
                    extraData = new HashMap(1);
                    Integer addedIndexInList = record.getOrderedAddObjectIndices().get(addedChangeSet);
                    if (addedIndexInList == null) {
                        if (currentObjects == null) {
                            currentObjects = getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());
                        }
                        addedIndexInList = ((List)currentObjects).indexOf(addedChangeSet.getUnitOfWorkClone());
                    }
                    extraData.put(this.listOrderField, addedIndexInList);
                }
                objectAddedDuringUpdate(query, this.containerPolicy.getCloneDataFromChangeSet(addedChangeSet), addedChangeSet, extraData);
                if (addedChangeSet.getNewKey() != null){
                    this.containerPolicy.propogatePostUpdate(query, addedChangeSet.getNewKey());
                }
            }
            if (this.listOrderField != null) {
                // This is a hacky check for attribute change tracking, if the backup clone is different, then is using deferred.
                List previousList = (List)getRealCollectionAttributeValueFromObject(query.getBackupClone(), query.getSession());
                int previousSize = previousList.size();
                if (currentObjects == null) {
                    currentObjects = getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());
                }
                List currentList = (List)currentObjects;
                int currentSize = currentList.size();
                boolean shouldRepairOrder = false;
                if(currentList instanceof IndirectList) {
                    shouldRepairOrder = ((IndirectList)currentList).isListOrderBrokenInDb();
                }
                if(previousList == currentList) {
                    // previousList is not available

                    // The same size as previous list,
                    // at the i-th position holds the index of the i-th original object in the current list (-1 if the object was removed):
                    // for example: {0, -1, 1, -1, 3} means that:
                    //   previous(0) == current(0);
                    //   previous(1) was removed;
                    //   previous(2) == current(1);
                    //   previous(3) was removed;
                    //   previous(4) == current(3);
                    // current(1) and current(3) were also on previous list, but with different indexes: they are the ones that should have their index changed.
                    List<Integer> currentIndexes = record.getCurrentIndexesOfOriginalObjects(currentList);
                    for(int i=0; i < currentIndexes.size(); i++) {
                        int currentIndex = currentIndexes.get(i);
                        if((currentIndex >= 0) && (currentIndex != i || shouldRepairOrder)) {
                            objectOrderChangedDuringUpdate(query, currentList.get(currentIndex), currentIndex);
                        }
                    }
                } else {
                    for (int i=0; i < previousSize; i++) {
                        // TODO: should we check for previousObject != null?
                        Object prevObject = previousList.get(i);
                        Object currentObject = null;
                        if(i < currentSize) {
                            currentObject = currentList.get(i);
                        }
                        if(prevObject != currentObject || shouldRepairOrder) {
                            // object has either been removed or its index in the List has changed
                            int newIndex = currentList.indexOf(prevObject);
                            if(newIndex >= 0) {
                                objectOrderChangedDuringUpdate(query, prevObject, newIndex);
                            }
                        }
                    }
                }
                if (shouldRepairOrder) {
                    ((IndirectList)currentList).setIsListOrderBrokenInDb(false);
                    record.setOrderHasBeenRepaired(true);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * The memory objects are compared and only the changes are written to the database.
     */
    protected void compareObjectsAndWrite(WriteObjectQuery query) throws DatabaseException, OptimisticLockException {
        Object currentObjects = getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());
        Object previousObjects = readPrivateOwnedForObject(query);
        if (previousObjects == null) {
            previousObjects = getContainerPolicy().containerInstance(1);
        }
        if (this.listOrderField != null && this.isAggregateCollectionMapping()) {
            compareListsAndWrite((List)previousObjects, (List)currentObjects, query);
            return;
        }

        ContainerPolicy cp = this.containerPolicy;

        Map previousObjectsByKey = new HashMap(cp.sizeFor(previousObjects)); // Read from db or from backup in uow.
        Map currentObjectsByKey = new HashMap(cp.sizeFor(currentObjects)); // Current value of object's attribute (clone in uow).

        Map keysOfCurrentObjects = new IdentityHashMap(cp.sizeFor(currentObjects) + 1);

        // First index the current objects by their primary key.
        for (Object currentObjectsIter = cp.iteratorFor(currentObjects);
                 cp.hasNext(currentObjectsIter);) {
            Object currentObject = cp.next(currentObjectsIter, query.getSession());
            try {
                Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(currentObject, query.getSession());
                currentObjectsByKey.put(primaryKey, currentObject);
                keysOfCurrentObjects.put(currentObject, primaryKey);
            } catch (NullPointerException e) {
                // For CR#2646 quietly discard nulls added to a collection mapping.
                // This try-catch is essentially a null check on currentObject, for
                // ideally the customer should check for these themselves.
                if (currentObject != null) {
                    throw e;
                }
            }
        }

        // Next index the previous objects (read from db or from backup in uow)
        // and process the difference to current (optimized in same loop).
        for (Object previousObjectsIter = cp.iteratorFor(previousObjects);
                 cp.hasNext(previousObjectsIter);) {
            Object wrappedObject = cp.nextEntry(previousObjectsIter, query.getSession());
            Map mapKeyFields = containerPolicy.getKeyMappingDataForWriteQuery(wrappedObject, query.getSession());
            Object previousObject = containerPolicy.unwrapIteratorResult(wrappedObject);
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(previousObject, query.getSession());
            previousObjectsByKey.put(primaryKey, previousObject);
            // Delete must occur first, in case object with same pk is removed and added,
            // (technically should not happen, but same applies to unique constraints)
            if (!currentObjectsByKey.containsKey(primaryKey)) {
                objectRemovedDuringUpdate(query, wrappedObject, mapKeyFields);
                cp.propogatePostUpdate(query, wrappedObject);
            }
        }

        for (Object currentObjectsIter = cp.iteratorFor(currentObjects);
                 cp.hasNext(currentObjectsIter);) {
            Object wrappedObject = cp.nextEntry(currentObjectsIter, query.getSession());
            Object currentObject = containerPolicy.unwrapIteratorResult(wrappedObject);
            try {
                Map mapKeyFields = containerPolicy.getKeyMappingDataForWriteQuery(wrappedObject, query.getSession());
                Object primaryKey = keysOfCurrentObjects.get(currentObject);

                if (!(previousObjectsByKey.containsKey(primaryKey))) {
                    objectAddedDuringUpdate(query, currentObject, null, mapKeyFields);
                    cp.propogatePostUpdate(query, wrappedObject);
                } else {
                    objectUnchangedDuringUpdate(query, currentObject, previousObjectsByKey, primaryKey);
                }
            } catch (NullPointerException e) {
                // For CR#2646 skip currentObject if it is null.
                if (currentObject != null) {
                    throw e;
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Old and new lists are compared and only the changes are written to the database.
     * Currently there's no support for listOrderField in CollectionMapping in case there's no change sets,
     * so this method currently never called (currently only overriding method in AggregateCollectionMapping is called).
     * This method should be implemented to support listOrderField functionality without change sets.
     */
    protected void compareListsAndWrite(List previousList, List currentList, WriteObjectQuery query) throws DatabaseException, OptimisticLockException {
    }

    /**
     * Compare two objects if their parts are not private owned
     */
    @Override
    protected boolean compareObjectsWithoutPrivateOwned(Object firstCollection, Object secondCollection, AbstractSession session) {
        if(this.listOrderField != null) {
            return compareLists((List)firstCollection, (List)secondCollection, session, false);
        }

        ContainerPolicy cp = this.containerPolicy;
        if (cp.sizeFor(firstCollection) != cp.sizeFor(secondCollection)) {
            return false;
        }

        Object firstIter = cp.iteratorFor(firstCollection);
        Object secondIter = cp.iteratorFor(secondCollection);

        Map keyValues = new HashMap();

        if (isMapKeyMapping()) {
            while (cp.hasNext(secondIter)) {
                Map.Entry secondObject = (Map.Entry)cp.nextEntry(secondIter, session);
                Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject.getValue(), session);
                Object key = secondObject.getKey();
                keyValues.put(key, primaryKey);
            }
            while (cp.hasNext(firstIter)) {
                Map.Entry firstObject = (Map.Entry)cp.nextEntry(firstIter, session);
                Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject.getValue(), session);
                Object key = firstObject.getKey();
                if (!primaryKey.equals(keyValues.get(key))) {
                    return false;
                }
            }
        } else {
            while (cp.hasNext(secondIter)) {
                Object secondObject = cp.next(secondIter, session);
                Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject, session);
                keyValues.put(primaryKey, primaryKey);
            }
            while (cp.hasNext(firstIter)) {
                Object firstObject = cp.next(firstIter, session);
                Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject, session);
                if (!keyValues.containsKey(primaryKey)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Compare two objects if their parts are private owned
     */
    @Override
    protected boolean compareObjectsWithPrivateOwned(Object firstCollection, Object secondCollection, AbstractSession session) {
        if(this.listOrderField != null) {
            return compareLists((List)firstCollection, (List)secondCollection, session, true);
        }

        ContainerPolicy cp = this.containerPolicy;
        if (cp.sizeFor(firstCollection) != cp.sizeFor(secondCollection)) {
            return false;
        }

        Object firstIter = cp.iteratorFor(firstCollection);
        Object secondIter = cp.iteratorFor(secondCollection);

        Map keyValueToObject = new HashMap(cp.sizeFor(firstCollection));

        while (cp.hasNext(secondIter)) {
            Object secondObject = cp.next(secondIter, session);
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject, session);
            keyValueToObject.put(primaryKey, secondObject);
        }

        while (cp.hasNext(firstIter)) {
            Object firstObject = cp.next(firstIter, session);
            Object primaryKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject, session);

            if (keyValueToObject.containsKey(primaryKey)) {
                Object object = keyValueToObject.get(primaryKey);

                if (!session.compareObjects(firstObject, object)) {
                    return false;
                }
            } else {
                return false;
            }
        }

        return true;
    }

    /**
     * Compare two lists. For equality the order of the elements should be the same.
     * Used only if listOrderField != null
     */
    protected boolean compareLists(List firstList, List secondList, AbstractSession session, boolean withPrivateOwned) {
        if (firstList.size() != secondList.size()) {
            return false;
        }

        int size = firstList.size();
        for(int i=0; i < size; i++) {
            Object firstObject = firstList.get(i);
            Object secondObject = secondList.get(i);
            if(withPrivateOwned) {
                if(!session.compareObjects(firstObject, secondObject)) {
                    return false;
                }
            } else {
                Object firstKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(firstObject, session);
                Object secondKey = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(secondObject, session);
                if (!firstKey.equals(secondKey)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this mapping to actual class-based
     * settings
     * This method is implemented by subclasses as necessary.
     */
    @Override
    public void convertClassNamesToClasses(ClassLoader classLoader){
        super.convertClassNamesToClasses(classLoader);
        containerPolicy.convertClassNamesToClasses(classLoader);
    }

    /**
     * INTERNAL:
     * Extract the value from the batch optimized query, this should be supported by most query types.
     */
    @Override
    public Object extractResultFromBatchQuery(ReadQuery batchQuery, CacheKey parentCacheKey, AbstractRecord sourceRow, AbstractSession session, ObjectLevelReadQuery originalQuery) throws QueryException {
        Object result = super.extractResultFromBatchQuery(batchQuery, parentCacheKey, sourceRow, session, originalQuery);
        // The source object might not have any target objects.
        if (result == null) {
            return this.containerPolicy.containerInstance();
        } else {
            return result;
        }
    }

    /**
     * INTERNAL:
     * Prepare and execute the batch query and store the
     * results for each source object in a map keyed by the
     * mappings source keys of the source objects.
     */
    @Override
    protected void executeBatchQuery(DatabaseQuery query, CacheKey parentCacheKey, Map referenceObjectsByKey, AbstractSession session, AbstractRecord translationRow) {
        // Execute query and index resulting object sets by key.
        ReadAllQuery batchQuery = (ReadAllQuery)query;
        ComplexQueryResult complexResult = (ComplexQueryResult)session.executeQuery(batchQuery, translationRow);
        Object results = complexResult.getResult();
        Iterator<AbstractRecord> rowsIterator = ((List<AbstractRecord>)complexResult.getData()).iterator();
        ContainerPolicy queryContainerPolicy = batchQuery.getContainerPolicy();
        if (this.containerPolicy.shouldAddAll()) {
            // Indexed list mappings require special add that include the row data with the index.
            Map<Object, List[]> referenceObjectsAndRowsByKey = new HashMap();
            for (Object objectsIterator = queryContainerPolicy.iteratorFor(results); queryContainerPolicy.hasNext(objectsIterator);) {
                Object eachReferenceObject = queryContainerPolicy.next(objectsIterator, session);
                AbstractRecord row = rowsIterator.next();
                Object eachReferenceKey = extractKeyFromTargetRow(row, session);
                List[] objectsAndRows = referenceObjectsAndRowsByKey.get(eachReferenceKey);
                if (objectsAndRows == null) {
                    objectsAndRows = new List[]{new ArrayList(), new ArrayList()};
                    referenceObjectsAndRowsByKey.put(eachReferenceKey, objectsAndRows);
                }
                objectsAndRows[0].add(eachReferenceObject);
                objectsAndRows[1].add(row);
            }

            Iterator<Map.Entry<Object, List[]>> iterator = referenceObjectsAndRowsByKey.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<Object, List[]> entry = iterator.next();
                Object eachReferenceKey = entry.getKey();
                List objects = entry.getValue()[0];
                List<AbstractRecord> rows = entry.getValue()[1];
                Object container = this.containerPolicy.containerInstance(objects.size());
                this.containerPolicy.addAll(objects, container, query.getSession(), rows, batchQuery, parentCacheKey, true);
                referenceObjectsByKey.put(eachReferenceKey, container);
            }
        } else {
            // Non-indexed list, either normal collection, or a map key.
            for (Object objectsIterator = queryContainerPolicy.iteratorFor(results); queryContainerPolicy.hasNext(objectsIterator);) {
                Object eachReferenceObject = queryContainerPolicy.next(objectsIterator, session);
                AbstractRecord row = rowsIterator.next();
                // Handle duplicate rows in the ComplexQueryResult being replaced with null, as a
                // result of duplicate filtering being true for constructing the ComplexQueryResult
                while (row == null && rowsIterator.hasNext()) {
                    row = rowsIterator.next();
                }
                Object eachReferenceKey = extractKeyFromTargetRow(row, session);

                Object container = referenceObjectsByKey.get(eachReferenceKey);
                if ((container == null) || (container == Helper.NULL_VALUE)) {
                    container = this.containerPolicy.containerInstance();
                    referenceObjectsByKey.put(eachReferenceKey, container);
                }
                this.containerPolicy.addInto(eachReferenceObject, container, session, row, batchQuery, parentCacheKey, true);
            }
        }
    }

    /**
     * INTERNAL:
     * Extract the source primary key value from the target row.
     * Used for batch reading, most following same order and fields as in the mapping.
     * The method should be overridden by classes that support batch reading.
     */
    protected Object extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
        throw QueryException.batchReadingNotSupported(this, null);
    }

    /**
     * INTERNAL:
     * We are not using a remote valueholder
     * so we need to replace the reference object(s) with
     * the corresponding object(s) from the remote session.
     */
    @Override
    public void fixRealObjectReferences(Object object, Map objectDescriptors, Map processedObjects, ObjectLevelReadQuery query, DistributedSession session) {
        //bug 4147755 getRealAttribute... / setReal
        Object attributeValue = getRealAttributeValueFromObject(object, session);

        // the object collection could be null, check here to avoid NPE
        if (attributeValue == null) {
            setAttributeValueInObject(object, null);
            return;
        }

        ObjectLevelReadQuery tempQuery = query;
        if (!tempQuery.shouldMaintainCache()) {
            if ((!tempQuery.shouldCascadeParts()) || (tempQuery.shouldCascadePrivateParts() && (!isPrivateOwned()))) {
                tempQuery = null;
            }
        }

        Object remoteAttributeValue = session.getObjectsCorrespondingToAll(attributeValue, objectDescriptors, processedObjects, tempQuery, this.containerPolicy);
        setRealAttributeValueInObject(object, remoteAttributeValue);
    }


    /**
     * INTERNAL:
     * Returns the receiver's containerPolicy.
     */
    @Override
    public ContainerPolicy getContainerPolicy() {
        return containerPolicy;
    }

    protected ModifyQuery getDeleteAllQuery() {
        if (deleteAllQuery == null) {
            deleteAllQuery = new DataModifyQuery();
        }
        return deleteAllQuery;
    }

    /**
     * INTERNAL:
     * Returns the join criteria stored in the mapping selection query. This criteria
     * is used to read reference objects across the tables from the database.
     */
    @Override
    public Expression getJoinCriteria(ObjectExpression context, Expression base) {
        Expression selectionCriteria = getSelectionCriteria();
        Expression keySelectionCriteria = this.containerPolicy.getKeySelectionCriteria();
        if (keySelectionCriteria != null) {
            selectionCriteria = selectionCriteria.and(keySelectionCriteria);
        }
        return context.getBaseExpression().twist(selectionCriteria, base);
    }

    /**
     * INTERNAL:
     * return the object on the client corresponding to the specified object.
     * CollectionMappings have to worry about
     * maintaining object identity.
     */
    @Override
    public Object getObjectCorrespondingTo(Object object, DistributedSession session, Map objectDescriptors, Map processedObjects, ObjectLevelReadQuery query) {
        return session.getObjectsCorrespondingToAll(object, objectDescriptors, processedObjects, query, this.containerPolicy);
    }

    /**
     * INTERNAL:
     * Return the ordering query keys.
     * Used for Workbench integration.
     */
    public List<Expression> getOrderByQueryKeyExpressions() {
        List<Expression>  expressions = new ArrayList<> ();

        if ((getSelectionQuery() != null) && getSelectionQuery().isReadAllQuery()) {
            for (Expression orderExpression : ((ReadAllQuery)getSelectionQuery()).getOrderByExpressions()) {
                if (orderExpression.isFunctionExpression() && ((FunctionExpression)orderExpression).getBaseExpression().isQueryKeyExpression()) {
                    expressions.add(orderExpression);
                }
            }
        }

        return expressions;
    }

    /**
     * INTERNAL:
     * Get the container policy from the selection query for this mapping. This
     * method is overridden in DirectCollectionMapping since  its selection
     * query is a DataReadQuery.
     */
    protected ContainerPolicy getSelectionQueryContainerPolicy() {
        return ((ReadAllQuery) getSelectionQuery()).getContainerPolicy();
    }

    /**
     * Convenience method.
     * Return the value of an attribute, unwrapping value holders if necessary.
     * If the value is null, build a new container.
     */
    @Override
    public Object getRealCollectionAttributeValueFromObject(Object object, AbstractSession session) throws DescriptorException {
        Object value = getRealAttributeValueFromObject(object, session);
        if (value == null) {
            value = this.containerPolicy.containerInstance(1);
        }
        return value;
    }

    /**
     * PUBLIC:
     * Field holds the order of elements in the list in the db, requires collection of type List;
     * may be not null only in case isListOrderFieldSupported==true.
     */
    public DatabaseField getListOrderField() {
        return listOrderField;
    }

    /**
     * INTERNAL:
     * Returns list of primary key fields from the reference descriptor.
     */
    public List<DatabaseField> getTargetPrimaryKeyFields() {
        return getReferenceDescriptor().getPrimaryKeyFields();
    }

    /**
     * PUBLIC:
     * Specifies what should be done if the list of values read from listOrserField is invalid
     * (there should be no nulls, no duplicates, no "holes").
     */
    public OrderCorrectionType getOrderCorrectionType() {
        return this.orderCorrectionType;
    }

    protected boolean hasCustomDeleteAllQuery() {
        return hasCustomDeleteAllQuery;
    }

    /**
     * INTERNAL:
     * Return true if ascending or descending ordering has been set on this
     * mapping via the @OrderBy annotation.
     */
    public boolean hasOrderBy() {
        return hasOrderBy;
    }

    /**
     * INTERNAL:
     * Initialize the state of mapping.
     */
    @Override
    public void initialize(AbstractSession session) throws DescriptorException {
        super.initialize(session);
        setFields(collectFields());
        this.containerPolicy.prepare(getSelectionQuery(), session);

        // Check that the container policy is correct for the collection type.
        if ((!usesIndirection()) && (!getAttributeAccessor().getAttributeClass().isAssignableFrom(this.containerPolicy.getContainerClass()))) {
            throw DescriptorException.incorrectCollectionPolicy(this, getAttributeAccessor().getAttributeClass(), this.containerPolicy.getContainerClass());
        }

        if(listOrderField != null) {
            initializeListOrderField(session);
        }
    }

    /**
     * INTERNAL:
     * Initializes listOrderField.
     * Precondition: listOrderField != null.
     */
    protected void initializeListOrderField(AbstractSession session) {
        if(!List.class.isAssignableFrom(getAttributeAccessor().getAttributeClass())) {
            throw DescriptorException.listOrderFieldRequiersList(getDescriptor(), this);
        }

        boolean isAttributeAssignableFromIndirectList = getAttributeAccessor().getAttributeClass().isAssignableFrom(IndirectList.class);

        if(this.orderCorrectionType == null) {
            // set default validation mode
            if(isAttributeAssignableFromIndirectList) {
                this.orderCorrectionType = OrderCorrectionType.READ_WRITE;
            } else {
                this.orderCorrectionType = OrderCorrectionType.READ;
            }
        } else if(this.orderCorrectionType == OrderCorrectionType.READ_WRITE) {
            //OrderValidationMode.CORRECTION sets container class to IndirectList, make sure the attribute is of compatible type.
            if(!isAttributeAssignableFromIndirectList) {
                throw DescriptorException.listOrderFieldRequiersIndirectList(getDescriptor(), this);
            }
        }

        ContainerPolicy originalQueryContainerPolicy = getSelectionQueryContainerPolicy();

        if(!this.containerPolicy.isOrderedListPolicy()) {
            setContainerPolicy(new OrderedListContainerPolicy(this.containerPolicy.getContainerClass()));
            // re-prepare replaced container policy as we are initializing
            getContainerPolicy().prepare(getSelectionQuery(), session);
        }
        OrderedListContainerPolicy orderedListContainerPolicy = (OrderedListContainerPolicy)this.containerPolicy;
        orderedListContainerPolicy.setListOrderField(this.listOrderField);
        orderedListContainerPolicy.setOrderCorrectionType(this.orderCorrectionType);

        // If ContainerPolicy's container class is IndirectList, originalQueryContainerPolicy's container class is not (likely Vector)
        // and orderCorrectionType doesn't require query to use IndirectList - then query will keep a separate container policy
        // that uses its original container class (likely Vector) - this is the same optimization as used in useTransparentList method.
        if(this.containerPolicy.getContainerClass().isAssignableFrom(IndirectList.class) &&
           !IndirectList.class.isAssignableFrom(originalQueryContainerPolicy.getContainerClass()) &&
           this.orderCorrectionType != OrderCorrectionType.READ_WRITE ||
           originalQueryContainerPolicy == this.getSelectionQueryContainerPolicy())
        {
            OrderedListContainerPolicy queryOrderedListContainerPolicy;
            if(originalQueryContainerPolicy.getClass().equals(orderedListContainerPolicy.getClass())) {
                // original query container policy
                queryOrderedListContainerPolicy = (OrderedListContainerPolicy)originalQueryContainerPolicy;
                queryOrderedListContainerPolicy.setListOrderField(this.listOrderField);
                queryOrderedListContainerPolicy.setOrderCorrectionType(this.orderCorrectionType);
            } else {
                // clone mapping's container policy
                queryOrderedListContainerPolicy = (OrderedListContainerPolicy)orderedListContainerPolicy.clone();
                queryOrderedListContainerPolicy.setContainerClass(originalQueryContainerPolicy.getContainerClass());
                setSelectionQueryContainerPolicy(queryOrderedListContainerPolicy);
            }
        }

        if(this.listOrderField.getType() == null) {
            this.listOrderField.setType(Integer.class);
        }

        buildListOrderField();

        // DirectCollectMap - that uses DataReadQuery - adds listOrderField to selection query in initializeSelectionStatement method.
        if (getSelectionQuery().isReadAllQuery()) {
            if(shouldUseListOrderFieldTableExpression()) {
                initializeListOrderFieldTable(session);
            }
        }

        initializeChangeOrderTargetQuery(session);
    }

    /**
     * INTERNAL:
     * Initializes listOrderField's table, does nothing by default.
     * Precondition: listOrderField != null.
     */
    protected void initializeListOrderFieldTable(AbstractSession session) {
    }

    /**
     * INTERNAL:
     * Verifies listOrderField's table, if none found sets the default one.
     * Precondition: listOrderField != null.
     */
    protected void buildListOrderField() {
        if(this.listOrderField.hasTableName()) {
            if(!this.getReferenceDescriptor().getDefaultTable().equals(this.listOrderField.getTable())) {
                throw DescriptorException.listOrderFieldTableIsWrong(this.getDescriptor(), this, this.listOrderField.getTable(), this.getReferenceDescriptor().getDefaultTable());
            }
        } else {
            this.listOrderField.setTable(this.getReferenceDescriptor().getDefaultTable());
        }
        this.listOrderField = this.getReferenceDescriptor().buildField(this.listOrderField);
    }


    /**
     * ADVANCED:
     * This method should only be called after this mapping's indirection policy has been set
     *
     * IndirectList and IndirectSet can be configured not to instantiate the list from the
     * database when you add and remove from them.  IndirectList defaults to this behavior. When
     * Set to true, the collection associated with this TransparentIndirection will be setup so as
     * not to instantiate for adds and removes.  The weakness of this setting for an IndirectSet is
     * that when the set is not instantiated, if a duplicate element is added, it will not be
     * detected until commit time.
     */
    public Boolean shouldUseLazyInstantiationForIndirectCollection() {
        if (getIndirectionPolicy() == null){
            return null;
        }
        return getIndirectionPolicy().shouldUseLazyInstantiation();
    }

    /**
     * INTERNAL:
     * Indicates whether getListOrderFieldExpression method should create field expression based on table expression.
     */
    public boolean shouldUseListOrderFieldTableExpression() {
        return false;
    }

    /**
     * INTERNAL:
     * Initialize changeOrderTargetQuery.
     */
    protected void initializeChangeOrderTargetQuery(AbstractSession session) {
    }

    /**
     * INTERNAL:
     * Return whether this mapping is a Collection type.
     */
    @Override
    public boolean isCollectionMapping() {
        return true;
    }

    /**
     * INTERNAL:
     * Return if this mapping has a mapped key that uses a OneToOne (object).
     */
    public boolean isMapKeyObjectRelationship() {
        return this.containerPolicy.isMapKeyObject();
    }

    /**
     * INTERNAL:
     * The referenced object is checked if it is instantiated or not,
     * also check if it has been changed (as indirect collections avoid instantiation on add/remove.
     */
    public boolean isAttributeValueInstantiatedOrChanged(Object object) {
        return this.indirectionPolicy.objectIsInstantiatedOrChanged(getAttributeValueFromObject(object));
    }

    /**
     * INTERNAL:
     * Iterate on the specified element.
     */
    public void iterateOnElement(DescriptorIterator iterator, Object element) {
        iterator.iterateReferenceObjectForMapping(element, this);
    }

    /**
     * INTERNAL:
     * Iterate on the attribute value.
     * The value holder has already been processed.
     */
    @Override
    public void iterateOnRealAttributeValue(DescriptorIterator iterator, Object realAttributeValue) {
        if (realAttributeValue == null) {
            return;
        }
        ContainerPolicy cp = this.containerPolicy;
        for (Object iter = cp.iteratorFor(realAttributeValue); cp.hasNext(iter);) {
            Object wrappedObject = cp.nextEntry(iter, iterator.getSession());
            Object object = cp.unwrapIteratorResult(wrappedObject);
            iterateOnElement(iterator, object);
            cp.iterateOnMapKey(iterator, wrappedObject);
        }
    }

    /**
     * Force instantiation of the load group.
     */
    @Override
    public void load(final Object object, AttributeItem item, final AbstractSession session, final boolean fromFetchGroup) {
        instantiateAttribute(object, session);
        if (item.getGroup() != null && (!fromFetchGroup || session.isUnitOfWork()) ){
            //if UOW make sure the nested attributes are loaded as the clones will not be instantiated
            Object value = getRealAttributeValueFromObject(object, session);
            ContainerPolicy cp = this.containerPolicy;
            for (Object iterator = cp.iteratorFor(value); cp.hasNext(iterator);) {
                Object wrappedObject = cp.nextEntry(iterator, session);
                Object nestedObject = cp.unwrapIteratorResult(wrappedObject);
                session.load(nestedObject, item.getGroup(nestedObject.getClass()), getReferenceDescriptor(), fromFetchGroup);
            }
        }
    }

    /**
     * Force instantiation of all indirections.
     */
    @Override
    public void loadAll(Object object, AbstractSession session, IdentityHashSet loaded) {
        instantiateAttribute(object, session);
        ClassDescriptor referenceDescriptor = getReferenceDescriptor();
        if (referenceDescriptor != null) {
            boolean hasInheritance = referenceDescriptor.hasInheritance() || referenceDescriptor.hasTablePerClassPolicy();
            Object value = getRealAttributeValueFromObject(object, session);
            ContainerPolicy cp = this.containerPolicy;
            for (Object iterator = cp.iteratorFor(value); cp.hasNext(iterator);) {
                Object wrappedObject = cp.nextEntry(iterator, session);
                Object nestedObject = cp.unwrapIteratorResult(wrappedObject);
                if (hasInheritance && !nestedObject.getClass().equals(referenceDescriptor.getJavaClass())){
                    ClassDescriptor concreteReferenceDescriptor = referenceDescriptor.getInheritancePolicy().getDescriptor(nestedObject.getClass());
                    concreteReferenceDescriptor.getObjectBuilder().loadAll(nestedObject, session, loaded);
                } else {
                    referenceDescriptor.getObjectBuilder().loadAll(nestedObject, session, loaded);
                }
            }
        }
    }

    /**
     * ADVANCED:
     * Return whether the reference objects must be deleted
     * one by one, as opposed to with a single DELETE statement.
     */
    public boolean mustDeleteReferenceObjectsOneByOne() {
        return this.mustDeleteReferenceObjectsOneByOne == null || this.mustDeleteReferenceObjectsOneByOne;
    }

    /**
     * INTERNAL:
     * Merge changes from the source to the target object.
     * Because this is a collection mapping, values are added to or removed from the
     * collection based on the changeset
     */
    @Override
    public void mergeChangesIntoObject(Object target, ChangeRecord chgRecord, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        if (this.descriptor.getCachePolicy().isProtectedIsolation()&& !this.isCacheable && !targetSession.isProtectedSession()){
            setAttributeValueInObject(target, this.indirectionPolicy.buildIndirectObject(new ValueHolder(null)));
            return;
        }
        Object valueOfTarget = null;
        Object valueOfSource = null;
        ContainerPolicy containerPolicy = this.containerPolicy;
        CollectionChangeRecord changeRecord = (CollectionChangeRecord) chgRecord;
        UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet)changeRecord.getOwner().getUOWChangeSet();

        // Collect the changes into a vector. Check to see if the target has an instantiated
        // collection, if it does then iterate over the changes and merge the collections.
        if (isAttributeValueInstantiated(target)) {
            // If it is new will need a new collection.
            if (changeRecord.getOwner().isNew()) {
                valueOfTarget = containerPolicy.containerInstance(changeRecord.getAddObjectList().size());
            } else {
                if (isSynchronizeOnMerge) {
                    valueOfTarget = getRealCollectionAttributeValueFromObject(target, mergeManager.getSession());
                } else {
                    // Clone instead of synchronization to avoid possible deadlocks.
                    valueOfTarget = containerPolicy.cloneFor(getRealCollectionAttributeValueFromObject(target, mergeManager.getSession()));
                }
            }

            containerPolicy.mergeChanges(changeRecord, valueOfTarget, shouldMergeCascadeParts(mergeManager), mergeManager, targetSession, isSynchronizeOnMerge);
        } else {
            // The valueholder has not been instantiated
            if (mergeManager.shouldMergeChangesIntoDistributedCache()) {
                return; // do nothing
            }
            // PERF: Also avoid merge if source has not been instantiated for indirect collection adds.
            if (!isAttributeValueInstantiated(source)) {
                return;
            }
            // If I'm not merging on another server then create instance of the collection
            valueOfSource = getRealCollectionAttributeValueFromObject(source, mergeManager.getSession());
            Object iterator = containerPolicy.iteratorFor(valueOfSource);
            valueOfTarget = containerPolicy.containerInstance(containerPolicy.sizeFor(valueOfSource));
            while (containerPolicy.hasNext(iterator)) {
                // CR#2195 Problem with merging Collection mapping in unit of work and inheritance.
                Object objectToMerge = containerPolicy.next(iterator, mergeManager.getSession());
                if (shouldMergeCascadeParts(mergeManager) && (valueOfSource != null)) {
                    ObjectChangeSet changeSet = (ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(objectToMerge);
                    mergeManager.mergeChanges(objectToMerge, changeSet, targetSession);
                }

                // Let the mergemanager get it because I don't have the change for the object.
                // CR#2188 Problem with merging Collection mapping in unit of work and transparent indirection.
                containerPolicy.addInto(mergeManager.getTargetVersionOfSourceObject(objectToMerge, referenceDescriptor, targetSession), valueOfTarget, mergeManager.getSession());
            }
        }
        if (valueOfTarget == null) {
            valueOfTarget = containerPolicy.containerInstance();
        }
        setRealAttributeValueInObject(target, valueOfTarget);
    }

    /**
     * INTERNAL:
     * Merge changes from the source to the target object. This merge is only called when a changeSet for the target
     * does not exist or the target is uninitialized
     */
    @Override
    public void mergeIntoObject(Object target, boolean isTargetUnInitialized, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        if (this.descriptor.getCachePolicy().isProtectedIsolation() && !this.isCacheable && !targetSession.isProtectedSession()){
            setAttributeValueInObject(target, this.indirectionPolicy.buildIndirectObject(new ValueHolder(null)));
            return;
        }
        if (isTargetUnInitialized) {
            // This will happen if the target object was removed from the cache before the commit was attempted
            if (mergeManager.shouldMergeWorkingCopyIntoOriginal() && (!isAttributeValueInstantiated(source))) {
                setAttributeValueInObject(target, this.indirectionPolicy.getOriginalIndirectionObject(getAttributeValueFromObject(source), targetSession));
                return;
            }
        }
        if (!shouldMergeCascadeReference(mergeManager)) {
            // This is only going to happen on mergeClone, and we should not attempt to merge the reference
            return;
        }
        if (mergeManager.shouldRefreshRemoteObject() && usesIndirection()) {
            mergeRemoteValueHolder(target, source, mergeManager);
            return;
        }
        if (mergeManager.isForRefresh()) {
            if (!isAttributeValueInstantiated(target)) {
                if(shouldRefreshCascadeParts(mergeManager)){
                    // We must clone and set the value holder from the source to the target.
                    // This ensures any cascaded refresh will be applied to the UOW backup valueholder
                    Object attributeValue = getAttributeValueFromObject(source);
                    Object clonedAttributeValue = this.indirectionPolicy.cloneAttribute(attributeValue, source, null, target, null, mergeManager.getSession(), false); // building clone from an original not a row.
                    setAttributeValueInObject(target, clonedAttributeValue);
                }

                // This will occur when the clone's value has not been instantiated yet and we do not need
                // the refresh that attribute
                return;
            }
        } else if (!isAttributeValueInstantiatedOrChanged(source)) {
            // I am merging from a clone into an original.  No need to do merge if the attribute was never
            // modified
            return;
        }

        Object valueOfSource = getRealCollectionAttributeValueFromObject(source, mergeManager.getSession());

        // There is a very special case when merging into the shared cache that the original
        // has been refreshed and now has non-instantiated indirection objects.
        // Force instantiation is not necessary and can cause problem with JTS drivers.
        AbstractSession mergeSession = mergeManager.getSession();
        Object valueOfTarget = getRealCollectionAttributeValueFromObject(target, mergeSession);
        ContainerPolicy containerPolicy = this.containerPolicy;
        // BUG#5190470 Must force instantiation of indirection collections.
        containerPolicy.sizeFor(valueOfTarget);
        boolean fireChangeEvents = false;
        ObjectChangeListener listener = null;
        Object valueOfSourceCloned = null;
        if (!mergeManager.isForRefresh()) {
            // EL Bug 338504 - No Need to clone in this case.
            valueOfSourceCloned = valueOfSource;
            // if we are copying from original to clone then the source will be
            // instantiated anyway and we must continue to use the UnitOfWork
            // valueholder in the case of transparent indirection
            Object newContainer = containerPolicy.containerInstance(containerPolicy.sizeFor(valueOfSourceCloned));
            if ((this.descriptor.getObjectChangePolicy().isObjectChangeTrackingPolicy()) && (target instanceof ChangeTracker) && (((ChangeTracker)target)._persistence_getPropertyChangeListener() != null)) {
                // Avoid triggering events if we are dealing with the same list.
                // We rebuild the new container though since any cascade merge
                // activity such as lifecycle methods etc will be captured on
                // newly registered objects and not the clones and we need to
                // make sure the target has these updates once we are done.
                fireChangeEvents = (valueOfSourceCloned != valueOfTarget);
                // Collections may not be indirect list or may have been replaced with user collection.
                Object iterator = containerPolicy.iteratorFor(valueOfTarget);
                listener = (ObjectChangeListener)((ChangeTracker)target)._persistence_getPropertyChangeListener();
                if (fireChangeEvents) {
                    // Objects removed from the first position in the list, so the index of the removed object is always 0.
                    // When event is processed the index is used only in listOrderField case, ignored otherwise.
                    Integer zero = 0;
                    while (containerPolicy.hasNext(iterator)) {
                        CollectionChangeEvent event = containerPolicy.createChangeEvent(target, getAttributeName(), valueOfTarget, containerPolicy.next(iterator, mergeSession), CollectionChangeEvent.REMOVE, zero, false);
                        listener.internalPropertyChange(event);
                    }
                }
                if (newContainer instanceof ChangeTracker) {
                    ((CollectionChangeTracker)newContainer).setTrackedAttributeName(getAttributeName());
                    ((CollectionChangeTracker)newContainer)._persistence_setPropertyChangeListener(listener);
                }
                if (valueOfTarget instanceof ChangeTracker) {
                    ((ChangeTracker)valueOfTarget)._persistence_setPropertyChangeListener(null);//remove listener
                }
            }
            valueOfTarget = newContainer;
        } else {
            if (isSynchronizeOnMerge) {
                // EL Bug 338504 - It needs to iterate on object which can possibly
                // cause a deadlock scenario while merging changes from original
                // to the working copy during rollback of the transaction. So, clone
                // the original object instead of synchronizing on it and use cloned
                // object to iterate and merge changes to the working copy.
                synchronized(valueOfSource) {
                    valueOfSourceCloned = containerPolicy.cloneFor(valueOfSource);
                }
            } else {
                valueOfSourceCloned = valueOfSource;
            }
            //bug 3953038 - set a new collection in the object until merge completes, this
            //              prevents rel-maint. from adding duplicates.
            setRealAttributeValueInObject(target, containerPolicy.containerInstance(containerPolicy.sizeFor(valueOfSourceCloned)));
            containerPolicy.clear(valueOfTarget);
        }

        Object sourceIterator = containerPolicy.iteratorFor(valueOfSourceCloned);
        // Index of the added object - objects are added to the end of the list.
        // When event is processed the index is used only in listOrderField case, ignored otherwise.
        int i = 0;
        while (containerPolicy.hasNext(sourceIterator)) {
            Object wrappedObject = containerPolicy.nextEntry(sourceIterator, mergeManager.getSession());
            Object object = containerPolicy.unwrapIteratorResult(wrappedObject);
            if (object == null) {
                continue;// skip the null
            }
            if (shouldMergeCascadeParts(mergeManager)) {
                Object mergedObject = null;
                if ((mergeManager.getSession().isUnitOfWork()) && (((UnitOfWorkImpl)mergeManager.getSession()).getUnitOfWorkChangeSet() != null)) {
                    // If it is a unit of work, we have to check if I have a change Set for this object
                    mergedObject = mergeManager.mergeChanges(mergeManager.getObjectToMerge(object, referenceDescriptor, targetSession), (ObjectChangeSet)((UnitOfWorkImpl)mergeManager.getSession()).getUnitOfWorkChangeSet().getObjectChangeSetForClone(object), targetSession);
                    if (listener != null && !fireChangeEvents && mergedObject != object){
                        // we are merging a collection into itself that contained detached or new Entities.  make sure to remove the
                        // old change records // bug 302293
                        this.descriptor.getObjectChangePolicy().updateListenerForSelfMerge(listener, this, object, mergedObject, (UnitOfWorkImpl) mergeManager.getSession());
                    }
                } else {
                    mergedObject = mergeManager.mergeChanges(mergeManager.getObjectToMerge(object, referenceDescriptor, targetSession), null, targetSession);
                }
            }
            wrappedObject = containerPolicy.createWrappedObjectFromExistingWrappedObject(wrappedObject, source, referenceDescriptor, mergeManager, targetSession);
            if (isSynchronizeOnMerge) {
                synchronized (valueOfTarget) {
                    if (fireChangeEvents) {
                        //Collections may not be indirect list or may have been replaced with user collection.
                        //bug 304251: let the ContainerPolicy decide what changeevent object to create
                        CollectionChangeEvent event = containerPolicy.createChangeEvent(target, getAttributeName(), valueOfTarget, wrappedObject, CollectionChangeEvent.ADD, i++, false);
                        listener.internalPropertyChange(event);
                    }
                    containerPolicy.addInto(wrappedObject, valueOfTarget, mergeManager.getSession());
                }
            } else {
                if (fireChangeEvents) {
                    //Collections may not be indirect list or may have been replaced with user collection.
                    //bug 304251: let the ContainerPolicy decide what changeevent object to create
                    CollectionChangeEvent event = containerPolicy.createChangeEvent(target, getAttributeName(), valueOfTarget, wrappedObject, CollectionChangeEvent.ADD, i++, false);
                    listener.internalPropertyChange(event);
                }
                containerPolicy.addInto(wrappedObject, valueOfTarget, mergeManager.getSession());
            }
        }
        if (fireChangeEvents && (this.descriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy())) {
            // check that there were changes, if not then remove the record.
            ObjectChangeSet changeSet = ((AttributeChangeListener)((ChangeTracker)target)._persistence_getPropertyChangeListener()).getObjectChangeSet();
            //Bug4910642  Add NullPointer check
            if (changeSet != null) {
                CollectionChangeRecord changeRecord = (CollectionChangeRecord)changeSet.getChangesForAttributeNamed(getAttributeName());
                if (changeRecord != null) {
                    if (!changeRecord.isDeferred()) {
                        if (!changeRecord.hasChanges()) {
                            changeSet.removeChange(getAttributeName());
                        }
                    } else {
                        // Must reset the latest collection.
                        changeRecord.setLatestCollection(valueOfTarget);
                    }
                }
            }
        }

        // Must re-set variable to allow for set method to re-morph changes if the collection is not being stored directly.
        setRealAttributeValueInObject(target, valueOfTarget);
    }

    /**
     * INTERNAL:
     * An object was added to the collection during an update, insert it if private.
     */
    protected void objectAddedDuringUpdate(ObjectLevelModifyQuery query, Object objectAdded, ObjectChangeSet changeSet, Map extraData) throws DatabaseException, OptimisticLockException {
        if (!shouldObjectModifyCascadeToParts(query)) {// Called always for M-M
            return;
        }

        // Only cascade dependents writes in uow.
        if (query.shouldCascadeOnlyDependentParts()) {
            return;
        }

        // Insert must not be done for uow or cascaded queries and we must cascade to cascade policy.
        // We should distinguish between insert and write (optimization/paraniod).
        if (isPrivateOwned()) {
            InsertObjectQuery insertQuery = new InsertObjectQuery();
            insertQuery.setIsExecutionClone(true);
            insertQuery.setObject(containerPolicy.unwrapIteratorResult(objectAdded));
            insertQuery.setCascadePolicy(query.getCascadePolicy());
            query.getSession().executeQuery(insertQuery);
        } else {
            // Always write for updates, either private or in uow if calling this method.
            UnitOfWorkChangeSet uowChangeSet = null;
            if ((changeSet == null) && query.getSession().isUnitOfWork() && (((UnitOfWorkImpl)query.getSession()).getUnitOfWorkChangeSet() != null)) {
                uowChangeSet = (UnitOfWorkChangeSet)((UnitOfWorkImpl)query.getSession()).getUnitOfWorkChangeSet();
                changeSet = (ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(query.getObject());
            }
            WriteObjectQuery writeQuery = new WriteObjectQuery();
            writeQuery.setIsExecutionClone(true);
            writeQuery.setObject(containerPolicy.unwrapIteratorResult(objectAdded));
            writeQuery.setObjectChangeSet(changeSet);
            writeQuery.setCascadePolicy(query.getCascadePolicy());
            query.getSession().executeQuery(writeQuery);
        }
    }

    protected void objectOrderChangedDuringUpdate(WriteObjectQuery query, Object orderChangedObject, int orderIndex) {
        prepareTranslationRow(query.getTranslationRow(), query.getObject(), query.getDescriptor(), query.getSession());
        AbstractRecord databaseRow = new DatabaseRecord();

        // Extract target field and its value. Construct insert statement and execute it
        List<DatabaseField> targetPrimaryKeyFields = getTargetPrimaryKeyFields();
        int size = targetPrimaryKeyFields.size();
        for (int index = 0; index < size; index++) {
            DatabaseField targetPrimaryKey = targetPrimaryKeyFields.get(index);
            Object targetKeyValue = getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(orderChangedObject, targetPrimaryKey, query.getSession());
            databaseRow.put(targetPrimaryKey, targetKeyValue);
        }
        databaseRow.put(listOrderField, orderIndex);

        query.getSession().executeQuery(changeOrderTargetQuery, databaseRow);
    }

    /**
     * INTERNAL:
     * An object was removed to the collection during an update, delete it if private.
     */
    protected void objectRemovedDuringUpdate(ObjectLevelModifyQuery query, Object objectDeleted, Map extraData) throws DatabaseException, OptimisticLockException {
        if (isPrivateOwned()) {// Must check ownership for uow and cascading.
            if (!query.shouldCascadeOnlyDependentParts()) {
                containerPolicy.deleteWrappedObject(objectDeleted, query.getSession());
            }
        }
    }

    /**
     * INTERNAL:
     * An object is still in the collection, update it as it may have changed.
     */
    protected void objectUnchangedDuringUpdate(ObjectLevelModifyQuery query, Object object) throws DatabaseException, OptimisticLockException {
        if (!shouldObjectModifyCascadeToParts(query)) {// Called always for M-M
            return;
        }

        // Only cascade dependents writes in uow.
        if (query.shouldCascadeOnlyDependentParts()) {
            return;
        }

        // Always write for updates, either private or in uow if calling this method.
        WriteObjectQuery writeQuery = new WriteObjectQuery();
        writeQuery.setIsExecutionClone(true);
        writeQuery.setObject(object);
        writeQuery.setCascadePolicy(query.getCascadePolicy());
        query.getSession().executeQuery(writeQuery);
    }

    /**
     * INTERNAL:
     * Overridden by mappings that require additional processing of the change record after the record has been calculated.
     */
    @Override
    public void postCalculateChanges(org.eclipse.persistence.sessions.changesets.ChangeRecord changeRecord, UnitOfWorkImpl uow) {
        // no need for private owned check.  This code is only registered for private owned mappings.
        // targets are added to and/or removed to/from the source.
        CollectionChangeRecord collectionChangeRecord = (CollectionChangeRecord)changeRecord;
        Iterator it = collectionChangeRecord.getRemoveObjectList().values().iterator();
        while(it.hasNext()) {
            ObjectChangeSet ocs = (ObjectChangeSet)it.next();
            containerPolicy.postCalculateChanges(ocs, referenceDescriptor, this, uow);
        }
    }

    /**
     * INTERNAL:
     * Overridden by mappings that require additional processing of the change record after the record has been calculated.
     */
    @Override
    public void recordPrivateOwnedRemovals(Object object, UnitOfWorkImpl uow) {
        // no need for private owned check.  This code is only registered for private owned mappings.
        // targets are added to and/or removed to/from the source.
        if (mustDeleteReferenceObjectsOneByOne()) {
            Iterator it = (Iterator) containerPolicy.iteratorFor(getRealAttributeValueFromObject(object, uow));
            while (it.hasNext()) {
                Object clone = it.next();
                containerPolicy.recordPrivateOwnedRemovals(clone, referenceDescriptor, uow);
            }
        }
    }

    /**
     * INTERNAL:
     * Add additional fields
     */
    @Override
    protected void postPrepareNestedBatchQuery(ReadQuery batchQuery, ObjectLevelReadQuery query) {
        super.postPrepareNestedBatchQuery(batchQuery, query);
        ReadAllQuery mappingBatchQuery = (ReadAllQuery)batchQuery;
        mappingBatchQuery.setShouldIncludeData(true);
        this.containerPolicy.addAdditionalFieldsToQuery(mappingBatchQuery, getAdditionalFieldsBaseExpression(mappingBatchQuery));
    }

    /**
     * INTERNAL:
     * Return the base expression to use for adding fields to the query.
     * Normally this is the query's builder, but may be the join table for m-m.
     */
    protected Expression getAdditionalFieldsBaseExpression(ReadQuery query) {
        return ((ReadAllQuery)query).getExpressionBuilder();
    }

    /**
     * INTERNAL:
     * copies the non primary key information into the row currently used only in ManyToMany
     */
    protected void prepareTranslationRow(AbstractRecord translationRow, Object object, ClassDescriptor descriptor, AbstractSession session) {
        //Do nothing for the generic Collection Mapping
    }

    /**
     * INTERNAL:
     * A subclass should implement this method if it wants different behavior.
     * Recurse thru the parts to delete the reference objects after the actual object is deleted.
     */
    @Override
    public void postDelete(DeleteObjectQuery query) throws DatabaseException {
        if (this.containerPolicy.propagatesEventsToCollection()){
            Object queryObject = query.getObject();
            Object values = getAttributeValueFromObject(queryObject);
            Object iterator = containerPolicy.iteratorFor(values);
            while (containerPolicy.hasNext(iterator)){
                Object wrappedObject = containerPolicy.nextEntry(iterator, query.getSession());
                containerPolicy.propogatePostDelete(query, wrappedObject);
            }
        }
    }

    /**
     * INTERNAL:
     * Ensure the container policy is post initialized
     */
    @Override
    public void postInitialize(AbstractSession session) {
        super.postInitialize(session);
        this.containerPolicy.postInitialize(session);
        if (this.referenceDescriptor != null && this.mustDeleteReferenceObjectsOneByOne == null) {
            this.mustDeleteReferenceObjectsOneByOne = this.referenceDescriptor.hasDependencyOnParts()
                    || this.referenceDescriptor.usesOptimisticLocking()
                    || (this.referenceDescriptor.hasInheritance() && this.referenceDescriptor.getInheritancePolicy().shouldReadSubclasses())
                    || this.referenceDescriptor.hasMultipleTables() || this.containerPolicy.propagatesEventsToCollection()
                    || this.referenceDescriptor.hasRelationshipsExceptBackpointer(descriptor);
        } else if (this.mustDeleteReferenceObjectsOneByOne == null) {
            this.mustDeleteReferenceObjectsOneByOne = false;
        }
    }

    /**
     * INTERNAL:
     * A subclass should implement this method if it wants different behavior.
     * Recurse thru the parts to delete the reference objects after the actual object is deleted.
     */
    @Override
    public void postInsert(WriteObjectQuery query) throws DatabaseException {
        if (this.containerPolicy.propagatesEventsToCollection()){
            Object queryObject = query.getObject();
            Object values = getAttributeValueFromObject(queryObject);
            Object iterator = containerPolicy.iteratorFor(values);
            while (containerPolicy.hasNext(iterator)){
                Object wrappedObject = containerPolicy.nextEntry(iterator, query.getSession());
                containerPolicy.propogatePostInsert(query, wrappedObject);
            }
        }
    }

    /**
     * INTERNAL:
     * Propagate preInsert event to container policy if necessary
     */
    @Override
    public void preInsert(WriteObjectQuery query) throws DatabaseException, OptimisticLockException {
        if (this.containerPolicy.propagatesEventsToCollection()){
            Object queryObject = query.getObject();
            Object values = getAttributeValueFromObject(queryObject);
            Object iterator = containerPolicy.iteratorFor(values);
            while (containerPolicy.hasNext(iterator)){
                Object wrappedObject = containerPolicy.nextEntry(iterator, query.getSession());
                containerPolicy.propogatePreInsert(query, wrappedObject);
            }
        }
    }


    /**
     * INTERNAL:
     * Propagate preUpdate event to container policy if necessary
     */
    @Override
    public void preUpdate(WriteObjectQuery query) throws DatabaseException {
        if (this.containerPolicy.propagatesEventsToCollection()){
            Object queryObject = query.getObject();
            Object values = getAttributeValueFromObject(queryObject);
            Object iterator = containerPolicy.iteratorFor(values);
            while (containerPolicy.hasNext(iterator)){
                Object wrappedObject = containerPolicy.nextEntry(iterator, query.getSession());
                containerPolicy.propogatePreUpdate(query, wrappedObject);
            }
        }
    }

    /**
     * INTERNAL:
     * An object is still in the collection, update it as it may have changed.
     */
    protected void objectUnchangedDuringUpdate(ObjectLevelModifyQuery query, Object object, Map backupclones, Object key) throws DatabaseException, OptimisticLockException {
        objectUnchangedDuringUpdate(query, object);
    }

    /**
     * INTERNAL:
     * All the privately owned parts are read
     */
    protected Object readPrivateOwnedForObject(ObjectLevelModifyQuery modifyQuery) throws DatabaseException {
        if (modifyQuery.getSession().isUnitOfWork()) {
            return getRealCollectionAttributeValueFromObject(modifyQuery.getBackupClone(), modifyQuery.getSession());
        } else {
            // cr 3819
            prepareTranslationRow(modifyQuery.getTranslationRow(), modifyQuery.getObject(), modifyQuery.getDescriptor(), modifyQuery.getSession());
            return modifyQuery.getSession().executeQuery(getSelectionQuery(), modifyQuery.getTranslationRow());
        }
    }

    /**
     * INTERNAL:
     * replace the value holders in the specified reference object(s)
     */
    @Override
    public Map replaceValueHoldersIn(Object object, RemoteSessionController controller) {
        return controller.replaceValueHoldersInAll(object, this.containerPolicy);
    }

    /**
     * ADVANCED:
     * Configure the mapping to use a container policy.
     * The policy manages the access to the collection.
     */
    @Override
    public void setContainerPolicy(ContainerPolicy containerPolicy) {
        this.containerPolicy = containerPolicy;
        ((ReadAllQuery)getSelectionQuery()).setContainerPolicy(containerPolicy);
    }

    /**
     * PUBLIC:
     * The default delete all query for mapping can be overridden by specifying the new query.
     * This query is responsible for doing the deletion required by the mapping,
     * such as deletion of all the rows from join table for M-M, or optimized delete all of target objects for 1-M.
     */
    public void setCustomDeleteAllQuery(ModifyQuery query) {
        setDeleteAllQuery(query);
        setHasCustomDeleteAllQuery(true);
    }

    protected void setDeleteAllQuery(ModifyQuery query) {
        deleteAllQuery = query;
    }

    /**
     * PUBLIC:
     * Set the receiver's delete all SQL string. This allows the user to override the SQL
     * generated by TopLink, with there own SQL or procedure call. The arguments are
     * translated from the fields of the source row, through replacing the field names
     * marked by '#' with the values for those fields.
     * This SQL is responsible for doing the deletion required by the mapping,
     * such as deletion of all the rows from join table for M-M, or optimized delete all of target objects for 1-M.
     * Example, 'delete from PROJ_EMP where EMP_ID = #EMP_ID'.
     */
    public void setDeleteAllSQLString(String sqlString) {
        DataModifyQuery query = new DataModifyQuery();
        query.setSQLString(sqlString);
        setCustomDeleteAllQuery(query);
    }

    /**
     * PUBLIC:
     * Set the receiver's delete all call. This allows the user to override the SQL
     * generated by TopLink, with there own SQL or procedure call. The arguments are
     * translated from the fields of the source row.
     * This call is responsible for doing the deletion required by the mapping,
     * such as deletion of all the rows from join table for M-M, or optimized delete all of target objects for 1-M.
     * Example, 'new SQLCall("delete from PROJ_EMP where EMP_ID = #EMP_ID")'.
     */
    public void setDeleteAllCall(Call call) {
        DataModifyQuery query = new DataModifyQuery();
        query.setCall(call);
        setCustomDeleteAllQuery(query);
    }

    protected void setHasCustomDeleteAllQuery(boolean bool) {
        hasCustomDeleteAllQuery = bool;
    }

    /**
     * INTERNAL:
     * Set the container policy on the selection query for this mapping. This
     * method is overridden in DirectCollectionMapping since  its selection
     * query is a DataReadQuery.
     */
    protected void setSelectionQueryContainerPolicy(ContainerPolicy containerPolicy) {
        ((ReadAllQuery) getSelectionQuery()).setContainerPolicy(containerPolicy);
    }

    /**
     * PUBLIC:
     * Set the name of the session to execute the mapping's queries under.
     * This can be used by the session broker to override the default session
     * to be used for the target class.
     */
    public void setSessionName(String name) {
        getDeleteAllQuery().setSessionName(name);
        getSelectionQuery().setSessionName(name);
    }
    /**
     * ADVANCED:
     * Calling this method will only affect behavior of mappings using transparent indirection
     * This method should only be called after this mapping's indirection policy has been set
     *
     * IndirectList and IndirectSet can be configured not to instantiate the list from the
     * database when you add and remove from them.  IndirectList defaults to this behavior. When
     * Set to true, the collection associated with this TransparentIndirection will be setup so as
     * not to instantiate for adds and removes.  The weakness of this setting for an IndirectSet is
     * that when the set is not instantiated, if a duplicate element is added, it will not be
     * detected until commit time.
     */
    public void setUseLazyInstantiationForIndirectCollection(Boolean useLazyInstantiation) {
        if (getIndirectionPolicy() != null){
            getIndirectionPolicy().setUseLazyInstantiation(useLazyInstantiation);
        }
    }

    /**
     * ADVANCED:
     * This method is used to have an object add to a collection once the changeSet is applied
     * The referenceKey parameter should only be used for direct Maps.
     */
    @Override
    public void simpleAddToCollectionChangeRecord(Object referenceKey, Object changeSetToAdd, ObjectChangeSet changeSet, AbstractSession session) {
        CollectionChangeRecord collectionChangeRecord = (CollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName());
        if (collectionChangeRecord == null) {
            collectionChangeRecord = new CollectionChangeRecord(changeSet);
            collectionChangeRecord.setAttribute(getAttributeName());
            collectionChangeRecord.setMapping(this);
            changeSet.addChange(collectionChangeRecord);
        }
        this.containerPolicy.recordAddToCollectionInChangeRecord((ObjectChangeSet)changeSetToAdd, collectionChangeRecord);
        if (referenceKey != null) {
            ((ObjectChangeSet)changeSetToAdd).setNewKey(referenceKey);
        }
    }

    /**
     * ADVANCED:
     * This method is used to have an object removed from a collection once the changeSet is applied
     * The referenceKey parameter should only be used for direct Maps.
     */
    @Override
    public void simpleRemoveFromCollectionChangeRecord(Object referenceKey, Object changeSetToRemove, ObjectChangeSet changeSet, AbstractSession session) {
        CollectionChangeRecord collectionChangeRecord = (CollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName());
        if (collectionChangeRecord == null) {
            collectionChangeRecord = new CollectionChangeRecord(changeSet);
            collectionChangeRecord.setAttribute(getAttributeName());
            collectionChangeRecord.setMapping(this);
            changeSet.addChange(collectionChangeRecord);
        }
        this.containerPolicy.recordRemoveFromCollectionInChangeRecord((ObjectChangeSet)changeSetToRemove, collectionChangeRecord);
        if (referenceKey != null) {
            ((ObjectChangeSet)changeSetToRemove).setOldKey(referenceKey);
        }
    }

    /**
     * INTERNAL:
     * Either create a new change record or update with the new value.  This is used
     * by attribute change tracking.
     * Specifically in a collection mapping this will be called when the customer
     * Set a new collection.  In this case we will need to mark the change record
     * with the new and the old versions of the collection.
     * And mark the ObjectChangeSet with the attribute name then when the changes are calculated
     * force a compare on the collections to determine changes.
     */
    @Override
    public void updateChangeRecord(Object clone, Object newValue, Object oldValue, ObjectChangeSet objectChangeSet, UnitOfWorkImpl uow) {
        CollectionChangeRecord collectionChangeRecord = (CollectionChangeRecord)objectChangeSet.getChangesForAttributeNamed(this.getAttributeName());
        if (collectionChangeRecord == null) {
            collectionChangeRecord = new CollectionChangeRecord(objectChangeSet);
            collectionChangeRecord.setAttribute(getAttributeName());
            collectionChangeRecord.setMapping(this);
            objectChangeSet.addChange(collectionChangeRecord);
        }
        // the order is essential - the record should be set to deferred before recreateOriginalCollection is called -
        // otherwise will keep altering the change record while adding/removing each element into/from the original collection.
        collectionChangeRecord.setIsDeferred(true);
        objectChangeSet.deferredDetectionRequiredOn(getAttributeName());
        if (collectionChangeRecord.getOriginalCollection() == null) {
            collectionChangeRecord.recreateOriginalCollection(oldValue, uow);
        }
        collectionChangeRecord.setLatestCollection(newValue);
    }

    /**
     * INTERNAL:
     * Update a ChangeRecord to replace the ChangeSet for the old entity with the changeSet for the new Entity.  This is
     * used when an Entity is merged into itself and the Entity reference new or detached entities.
     */
    @Override
    public void updateChangeRecordForSelfMerge(ChangeRecord changeRecord, Object source, Object target, UnitOfWorkChangeSet parentUOWChangeSet, UnitOfWorkImpl unitOfWork){
        getContainerPolicy().updateChangeRecordForSelfMerge(changeRecord, source, target, this, parentUOWChangeSet, unitOfWork);
    }

    /**
     * INTERNAL:
     * Add or removes a new value and its change set to the collection change record based on the event passed in.  This is used by
     * attribute change tracking.
     */
    @Override
    public void updateCollectionChangeRecord(CollectionChangeEvent event, ObjectChangeSet changeSet, UnitOfWorkImpl uow) {
        if (event !=null && event.getNewValue() != null) {
            Object newValue = event.getNewValue();
            ClassDescriptor descriptor;

            //PERF: Use referenceDescriptor if it does not have inheritance
            if (!getReferenceDescriptor().hasInheritance() && !getReferenceDescriptor().hasTablePerClassPolicy()) {
                descriptor = getReferenceDescriptor();
            } else {
                descriptor = uow.getDescriptor(newValue);
            }
            newValue = descriptor.getObjectBuilder().unwrapObject(newValue, uow);
            ObjectChangeSet changeSetToAdd = descriptor.getObjectBuilder().createObjectChangeSet(newValue, (UnitOfWorkChangeSet)changeSet.getUOWChangeSet(), uow);

            CollectionChangeRecord collectionChangeRecord = (CollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName());
            if (collectionChangeRecord == null) {
                collectionChangeRecord = new CollectionChangeRecord(changeSet);
                collectionChangeRecord.setAttribute(getAttributeName());
                collectionChangeRecord.setMapping(this);
                changeSet.addChange(collectionChangeRecord);
            }
            if(!collectionChangeRecord.isDeferred()) {
                this.containerPolicy.recordUpdateToCollectionInChangeRecord(event, changeSetToAdd, collectionChangeRecord);
            }
        }
    }

    /**
     * INTERNAL:
     * Set the change listener in the collection.
     * If the collection is not indirect it must be re-built.
     * This is used for resuming or flushing units of work.
     */
    @Override
    public void setChangeListener(Object clone, PropertyChangeListener listener, UnitOfWorkImpl uow) {
        if (this.indirectionPolicy.usesTransparentIndirection() && isAttributeValueInstantiated(clone)) {
            Object attributeValue = getRealAttributeValueFromObject(clone, uow);
            if (!(attributeValue instanceof CollectionChangeTracker)) {
                Object container = attributeValue;
                ContainerPolicy containerPolicy = this.containerPolicy;
                if (attributeValue == null) {
                    container = containerPolicy.containerInstance(1);
                } else {
                    container = containerPolicy.containerInstance(containerPolicy.sizeFor(attributeValue));
                    for (Object iterator = containerPolicy.iteratorFor(attributeValue); containerPolicy.hasNext(iterator);) {
                        containerPolicy.addInto(containerPolicy.nextEntry(iterator, uow), container, uow);
                    }
                }
                setRealAttributeValueInObject(clone, container);
                ((CollectionChangeTracker)container).setTrackedAttributeName(getAttributeName());
                ((CollectionChangeTracker)container)._persistence_setPropertyChangeListener(listener);
            } else {
                ((CollectionChangeTracker)attributeValue).setTrackedAttributeName(getAttributeName());
                ((CollectionChangeTracker)attributeValue)._persistence_setPropertyChangeListener(listener);
            }
        }
        if (this.indirectionPolicy.usesTransparentIndirection()){
            ((IndirectCollection)getRealAttributeValueFromObject(clone, uow)).clearDeferredChanges();
        }

    }

    /**
     * PUBLIC:
     * indicates whether the mapping supports listOrderField, if it doesn't attempt to set listOrderField throws exception.
     */
    public boolean isListOrderFieldSupported() {
        return isListOrderFieldSupported;
    }

    /**
     * PUBLIC:
     * Field holds the order of elements in the list in the db, requires collection of type List.
     * Throws exception if the mapping doesn't support listOrderField.
     */
    public void setListOrderField(DatabaseField field) {
        if(field != null) {
            if(isListOrderFieldSupported) {
                this.listOrderField = field;
            } else {
                throw ValidationException.listOrderFieldNotSupported(this);
            }
        } else {
            this.listOrderField = null;
        }
    }

    /**
     * PUBLIC:
     * Field holds the order of elements in the list in the db, requires collection of type List.
     * Throws exception if the mapping doesn't support listOrderField.
     */
    public void setListOrderFieldName(String fieldName) {
        setListOrderField(new DatabaseField(fieldName));
    }


    /**
     * ADVANCED::
     * Return whether the reference objects must be deleted
     * one by one, as opposed to with a single DELETE statement.
     * Note: Calling this method disables an optimization of the delete
     * behavior
     */
    public void setMustDeleteReferenceObjectsOneByOne(Boolean deleteOneByOne) {
        this.mustDeleteReferenceObjectsOneByOne = deleteOneByOne;
    }

    /**
     * PUBLIC:
     * Specifies what should be done if the list of values read from listOrserField is invalid
     * (there should be no nulls, no duplicates, no "holes").
     */
    public void setOrderCorrectionType(OrderCorrectionType orderCorrectionType) {
        this.orderCorrectionType = orderCorrectionType;
    }

    /**
     * PUBLIC:
     * Configure the mapping to use an instance of the specified container class
     * to hold the target objects.
     * Note that if listOrderField is used then setListOrderField method
     * should be called before this method.
     * <p>The container class must implement (directly or indirectly) the
     * <code>java.util.Collection</code> interface.
     */
    @Override
    public void useCollectionClass(Class concreteClass) {
        ContainerPolicy policy = ContainerPolicy.buildPolicyFor(concreteClass, hasOrderBy() || listOrderField != null);
        setContainerPolicy(policy);
    }

    /**
     * PUBLIC:
     * Configure the mapping to use an instance of the specified container class
     * to hold the target objects.
     * <p>The container class must implement (directly or indirectly) the
     * <code>java.util.SortedSet</code> interface.
     */
    public void useSortedSetClass(Class concreteClass, Comparator comparator) {
        try {
            SortedCollectionContainerPolicy policy = (SortedCollectionContainerPolicy)ContainerPolicy.buildPolicyFor(concreteClass);
            policy.setComparator(comparator);
            setContainerPolicy(policy);
        } catch (ClassCastException e) {
            useCollectionClass(concreteClass);
        }
    }

    /**
     * INTERNAL:
     * Configure the mapping to use an instance of the specified container class name
     * to hold the target objects. This method is used by MW.
     * <p>The container class must implement (directly or indirectly) the
     * <code>java.util.SortedSet</code> interface.
     */
    public void useSortedSetClassName(String className) {
        this.useSortedSetClassName(className, null);
    }

    /**
     * INTERNAL:
     * Configure the mapping to use an instance of the specified container class name
     * to hold the target objects. This method is used by MW.
     * <p>The container class must implement (directly or indirectly) the
     * <code>java.util.SortedSet</code> interface.
     */
    public void useSortedSetClassName(String className, String comparatorClassName) {
        SortedCollectionContainerPolicy policy = new SortedCollectionContainerPolicy(className);
        policy.setComparatorClassName(comparatorClassName);
        setContainerPolicy(policy);
    }

    /**
     * INTERNAL:
     * Used to set the collection class by name.
     * This is required when building from metadata to allow the correct class loader to be used.
     */
    @Override
    public void useCollectionClassName(String concreteClassName) {
        setContainerPolicy(new CollectionContainerPolicy(concreteClassName));
    }

    /**
     * INTERNAL:
     * Used to set the collection class by name.
     * This is required when building from metadata to allow the correct class loader to be used.
     */
    @Override
    public void useListClassName(String concreteClassName) {
        setContainerPolicy(new ListContainerPolicy(concreteClassName));
    }

    /**
     * PUBLIC:
     * Configure the mapping to use an instance of the specified container class
     * to hold the target objects. The key used to index a value in the
     * <code>Map</code> is the value returned by a call to the specified
     * zero-argument method.
     * The method must be implemented by the class (or a superclass) of any
     * value to be inserted into the <code>Map</code>.
     * <p>The container class must implement (directly or indirectly) the
     * <code>java.util.Map</code> interface.
     * <p>To facilitate resolving the method, the mapping's referenceClass
     * must set before calling this method.
     */
    @Override
    public void useMapClass(Class concreteClass, String keyName) {
        // the reference class has to be specified before coming here
        if (getReferenceClassName() == null) {
            throw DescriptorException.referenceClassNotSpecified(this);
        }
        ContainerPolicy policy = ContainerPolicy.buildPolicyFor(concreteClass);
        policy.setKeyName(keyName, getReferenceClassName());

        setContainerPolicy(policy);
    }

    /**
     * PUBLIC:
     * Configure the mapping to use an instance of the specified container
     * class to hold the target objects. The key used to index a value in the
     * <code>Map</code> is an instance of the composite primary key class.
     * <p> To facilitate resolving the primary key class, the mapping's
     * referenceClass must set before calling this method.
     * <p> The container class must implement (directly or indirectly) the
     * <code>java.util.Map</code> interface.
     */
    public void useMapClass(Class concreteClass) {
        useMapClass(concreteClass, null);
    }

    /**
     * INTERNAL:
     * Not sure were this is used, MW?
     */
    @Override
    public void useMapClassName(String concreteClassName, String methodName) {
        // the reference class has to be specified before coming here
        if (getReferenceClassName() == null) {
            throw DescriptorException.referenceClassNotSpecified(this);
        }
        MapContainerPolicy policy = new MapContainerPolicy(concreteClassName);
        policy.setKeyName(methodName, getReferenceClass().getName());

        setContainerPolicy(policy);
    }

    /**
     * PUBLIC:
     * If transparent indirection is used, a special collection will be placed in the source
     * object's attribute.
     * Fetching of the contents of the collection from the database will be delayed
     * until absolutely necessary. (Any message sent to the collection will cause
     * the contents to be faulted in from the database.)
     * This can result in rather significant performance gains, without having to change
     * the source object's attribute from Collection (or List or Vector) to
     * ValueHolderInterface.
     */
    public void useTransparentCollection() {
        setIndirectionPolicy(new TransparentIndirectionPolicy());
        useCollectionClass(ClassConstants.IndirectList_Class);
    }

    /**
     * PUBLIC:
     * If transparent indirection is used, a special collection will be placed in the source
     * object's attribute.
     * Fetching of the contents of the collection from the database will be delayed
     * until absolutely necessary. (Any message sent to the collection will cause
     * the contents to be faulted in from the database.)
     * This can result in rather significant performance gains, without having to change
     * the source object's attribute from Set to
     * ValueHolderInterface.
     */
    public void useTransparentSet() {
        setIndirectionPolicy(new TransparentIndirectionPolicy());
        useCollectionClass(IndirectSet.class);
        setSelectionQueryContainerPolicy(ContainerPolicy.buildPolicyFor(HashSet.class));
    }

    /**
     * PUBLIC:
     * If transparent indirection is used, a special collection will be placed in the source
     * object's attribute.
     * Fetching of the contents of the collection from the database will be delayed
     * until absolutely necessary. (Any message sent to the collection will cause
     * the contents to be faulted in from the database.)
     * This can result in rather significant performance gains, without having to change
     * the source object's attribute from List to
     * ValueHolderInterface.
     */
    public void useTransparentList() {
        setIndirectionPolicy(new TransparentIndirectionPolicy());
        useCollectionClass(ClassConstants.IndirectList_Class);
        setSelectionQueryContainerPolicy(ContainerPolicy.buildPolicyFor(Vector.class, hasOrderBy() || listOrderField != null));
    }

    /**
     * PUBLIC:
     * If transparent indirection is used, a special map will be placed in the source
     * object's attribute.
     * Fetching of the contents of the map from the database will be delayed
     * until absolutely necessary. (Any message sent to the map will cause
     * the contents to be faulted in from the database.)
     * This can result in rather significant performance gains, without having to change
     * the source object's attribute from Map (or Map or Hashtable) to
     * ValueHolderInterface.<p>
     * The key used in the Map is the value returned by a call to the zero parameter
     * method named methodName. The method should be a zero argument method implemented (or
     * inherited) by the value to be inserted into the Map.
     */
    public void useTransparentMap(String methodName) {
        setIndirectionPolicy(new TransparentIndirectionPolicy());
        useMapClass(ClassConstants.IndirectMap_Class, methodName);
        ContainerPolicy policy = ContainerPolicy.buildPolicyFor(Hashtable.class);
        policy.setKeyName(methodName, getReferenceClass());
        setSelectionQueryContainerPolicy(policy);
    }

    /**
     * INTERNAL:
     * To validate mappings declaration
     */
    @Override
    public void validateBeforeInitialization(AbstractSession session) throws DescriptorException {
        super.validateBeforeInitialization(session);

        this.indirectionPolicy.validateContainerPolicy(session.getIntegrityChecker());

        if (getAttributeAccessor() instanceof InstanceVariableAttributeAccessor) {
            Class attributeType = ((InstanceVariableAttributeAccessor)getAttributeAccessor()).getAttributeType();
            this.indirectionPolicy.validateDeclaredAttributeTypeForCollection(attributeType, session.getIntegrityChecker());
        } else if (getAttributeAccessor().isMethodAttributeAccessor()) {
            // 323403
            Class returnType = ((MethodAttributeAccessor)getAttributeAccessor()).getGetMethodReturnType();
            this.indirectionPolicy.validateGetMethodReturnTypeForCollection(returnType, session.getIntegrityChecker());

            Class parameterType = ((MethodAttributeAccessor)getAttributeAccessor()).getSetMethodParameterType();
            this.indirectionPolicy.validateSetMethodParameterTypeForCollection(parameterType, session.getIntegrityChecker());
        }
    }

    /**
     * INTERNAL:
     * Checks if object is deleted from the database or not.
     */
    @Override
    public boolean verifyDelete(Object object, AbstractSession session) throws DatabaseException {
        // Row is built for translation
        if (isReadOnly()) {
            return true;
        }

        if (isPrivateOwned() || isCascadeRemove()) {
            Object objects = getRealCollectionAttributeValueFromObject(object, session);

            ContainerPolicy containerPolicy = this.containerPolicy;
            for (Object iter = containerPolicy.iteratorFor(objects); containerPolicy.hasNext(iter);) {
                if (!session.verifyDelete(containerPolicy.next(iter, session))) {
                    return false;
                }
            }
        }

        AbstractRecord row = getDescriptor().getObjectBuilder().buildRowForTranslation(object, session);

        //cr 3819 added the line below to fix the translationtable to ensure that it
        // contains the required values
        prepareTranslationRow(row, object, getDescriptor(), session);
        Object value = session.executeQuery(getSelectionQuery(), row);

        return this.containerPolicy.isEmpty(value);
    }

    /**
     * INTERNAL:
     * Return if this mapping supports change tracking.
     */
    @Override
    public boolean isChangeTrackingSupported(Project project) {
        return this.indirectionPolicy.usesTransparentIndirection();
    }

    /**
     * INTERNAL:
     * Directly build a change record without comparison
     */
    @Override
    public ChangeRecord buildChangeRecord(Object clone, ObjectChangeSet owner, AbstractSession session) {
        Object cloneAttribute = null;
        cloneAttribute = getAttributeValueFromObject(clone);
        if ((cloneAttribute != null) && (!this.indirectionPolicy.objectIsInstantiated(cloneAttribute))) {
            return null;
        }

        // 2612538 - the default size of Map (32) is appropriate
        IdentityHashMap cloneKeyValues = new IdentityHashMap();
        ContainerPolicy cp = this.containerPolicy;
        Object cloneObjectCollection = null;
        if (cloneAttribute != null) {
            cloneObjectCollection = getRealCollectionAttributeValueFromObject(clone, session);
        } else {
            cloneObjectCollection = cp.containerInstance(1);
        }
        Object cloneIter = cp.iteratorFor(cloneObjectCollection);

        while (cp.hasNext(cloneIter)) {
            Object firstObject = cp.next(cloneIter, session);
            if (firstObject != null) {
                cloneKeyValues.put(firstObject, firstObject);
            }
        }

        CollectionChangeRecord changeRecord = new CollectionChangeRecord(owner);
        changeRecord.setAttribute(getAttributeName());
        changeRecord.setMapping(this);
        changeRecord.addAdditionChange(cloneKeyValues, cp, (UnitOfWorkChangeSet)owner.getUOWChangeSet(), session);
        if (changeRecord.hasChanges()) {
            return changeRecord;
        }
        return null;
    }

    /**
     * INTERNAL:
     * This method is used to load a relationship from a list of PKs. This list
     * may be available if the relationship has been cached.
     */
    @Override
    public Object valueFromPKList(Object[] pks, AbstractRecord foreignKeys, AbstractSession session){
        ContainerPolicy cp = this.containerPolicy;
        return cp.valueFromPKList(pks, foreignKeys, this, session);
    }

    /**
     * INTERNAL:
     * Return the value of the field from the row or a value holder on the query to obtain the object.
     * To get here the mapping's isJoiningSupported() should return true.
     */
    @Override
    protected Object valueFromRowInternalWithJoin(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, CacheKey parentCacheKey, AbstractSession executionSession, boolean isTargetProtected) throws DatabaseException {

        Object value = this.containerPolicy.containerInstance();
        // Extract the primary key of the source object, to filter only the joined rows for that object.
        Object sourceKey = this.descriptor.getObjectBuilder().extractPrimaryKeyFromRow(row, executionSession);
        // If the query was using joining, all of the result rows by primary key will have been computed.
        List<AbstractRecord> rows = joinManager.getDataResultsByPrimaryKey().get(sourceKey);
        // If no 1-m rows were fetch joined, then get the value normally,
        // this can occur with pagination where the last row may not be complete.
        if (rows == null) {
            return valueFromRowInternal(row, joinManager, sourceQuery, executionSession);
        }
        int size = rows.size();
        if (size > 0) {
            // A nested query must be built to pass to the descriptor that looks like the real query execution would,
            // these should be cached on the query during prepare.
            ObjectLevelReadQuery nestedQuery = prepareNestedJoinQueryClone(row, rows, joinManager, sourceQuery, executionSession);

            // A set of target cache keys must be maintained to avoid duplicates from multiple 1-m joins.
            Set targetPrimaryKeys = new HashSet();

            ArrayList targetObjects = null;
            ArrayList<AbstractRecord> targetRows = null;
            boolean shouldAddAll = this.containerPolicy.shouldAddAll();
            if (shouldAddAll) {
                targetObjects = new ArrayList(size);
                targetRows = new ArrayList(size);
            }

            // For each rows, extract the target row and build the target object and add to the collection.
            ObjectBuilder referenceBuilder = getReferenceDescriptor().getObjectBuilder();
            JoinedAttributeManager referenceJoinManager = null;
            if (nestedQuery.hasJoining()) {
                referenceJoinManager = nestedQuery.getJoinedAttributeManager();
            }
            for (int index = 0; index < size; index++) {
                AbstractRecord sourceRow = rows.get(index);
                AbstractRecord targetRow = sourceRow;
                // The field for many objects may be in the row,
                // so build the subpartion of the row through the computed values in the query,
                // this also helps the field indexing match.
                targetRow = trimRowForJoin(targetRow, joinManager, executionSession);

                // Partial object queries must select the primary key of the source and related objects.
                // If the target joined rows in null (outerjoin) means an empty collection.
                Object targetKey = referenceBuilder.extractPrimaryKeyFromRow(targetRow, executionSession);
                if (targetKey == null) {
                    // A null primary key means an empty collection returned as nulls from an outerjoin.
                    return this.indirectionPolicy.valueFromRow(value);
                }

                // Only build/add the target object once, skip duplicates from multiple 1-m joins.
                if (!targetPrimaryKeys.contains(targetKey)) {
                    nestedQuery.setTranslationRow(targetRow);
                    targetPrimaryKeys.add(targetKey);
                    Object targetObject = referenceBuilder.buildObject(nestedQuery, targetRow, referenceJoinManager);
                    Object targetMapKey = this.containerPolicy.buildKeyFromJoinedRow(targetRow, joinManager, nestedQuery, parentCacheKey, executionSession, isTargetProtected);
                    nestedQuery.setTranslationRow(null);
                    if (targetMapKey == null){
                        if (shouldAddAll) {
                            targetObjects.add(targetObject);
                            targetRows.add(targetRow);
                        } else {
                            this.containerPolicy.addInto(targetObject, value, executionSession);
                        }
                    } else {
                        this.containerPolicy.addInto(targetMapKey, targetObject, value, executionSession);
                    }
                }
            }
            if (shouldAddAll) {
                this.containerPolicy.addAll(targetObjects, value, executionSession, targetRows, nestedQuery, parentCacheKey, isTargetProtected);
            }
        }
        return this.indirectionPolicy.valueFromRow(value);
    }
}
