/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. 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
//     08/15/2008-1.0.1 Chris Delahunt
//       - 237545: List attribute types on OneToMany using @OrderBy does not work with attribute change tracking
package org.eclipse.persistence.internal.queries;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.ListIterator;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.IndexedObject;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.ChangeRecord;
import org.eclipse.persistence.internal.sessions.MergeManager;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.internal.sessions.OrderedChangeObject;
import org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet;
import org.eclipse.persistence.internal.sessions.CollectionChangeRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.annotations.OrderCorrectionType;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.changetracking.CollectionChangeEvent;
import org.eclipse.persistence.indirection.IndirectCollection;
import org.eclipse.persistence.indirection.IndirectList;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.queries.DataReadQuery;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadQuery;

/**
 * <p><b>Purpose</b>: A OrderedListContainerPolicy is ContainerPolicy whose
 * container class implements the List interface and is ordered by an @OrderBy.
 * </p>
 * <p><b>Responsibilities</b>:
 * Provide the functionality to operate on an instance of a List.</p>
 *
 * @see ContainerPolicy
 * @see CollectionContainerPolicy
 * @see ListContainerPolicy
 */
public class OrderedListContainerPolicy extends ListContainerPolicy {
    protected static final String NOT_SET = "NOT_SET";
    protected DatabaseField listOrderField;
    protected OrderCorrectionType orderCorrectionType;

    /**
     * INTERNAL:
     * Construct a new policy.
     */
    public OrderedListContainerPolicy() {
        super();
    }

    /**
     * INTERNAL:
     * Construct a new policy for the specified class.
     */
    public OrderedListContainerPolicy(Class containerClass) {
        super(containerClass);
    }

    /**
     * INTERNAL:
     * Construct a new policy for the specified class name.
     */
    public OrderedListContainerPolicy(String containerClassName) {
        super(containerClassName);
    }

    /**
     * INTERNAL:
     * Add a list of elements to container.
     * This is used to add to a collection independent of JDK 1.1 and 1.2.
     * The session may be required to wrap for the wrapper policy.
     * The row may be required by subclasses
     * Return whether the container changed
     */
    @Override
    public boolean addAll(List elements, Object container, AbstractSession session, List<AbstractRecord> dbRows, ObjectBuildingQuery query, CacheKey parentCacheKey, boolean isTargetProtected) {
        if(this.listOrderField == null) {
            return super.addAll(elements, container, session, dbRows, query, parentCacheKey, isTargetProtected);
        } else {
            return addAll(elements, container, session, dbRows, query, parentCacheKey);
        }
    }

    /**
     * INTERNAL:
     * Add a list of elements to container.
     * This is used to add to a collection independent of JDK 1.1 and 1.2.
     * The session may be required to wrap for the wrapper policy.
     * The row may be required by subclasses
     * Return whether the container changed
     */
    @Override
    public boolean addAll(List elements, Object container, AbstractSession session, List<AbstractRecord> dbRows, DataReadQuery query, CacheKey parentCacheKey, boolean isTargetProtected) {
        if(this.listOrderField == null) {
            return super.addAll(elements, container, session, dbRows, query, parentCacheKey, isTargetProtected);
        } else {
            return addAll(elements, container, session, dbRows, query, parentCacheKey);
        }
    }

    protected boolean addAll(List elements, Object container, AbstractSession session, List<AbstractRecord> dbRows, ReadQuery query, CacheKey parentCacheKey) {
        int size = dbRows.size();

        if(this.elementDescriptor != null && this.elementDescriptor.getObjectBuilder().hasWrapperPolicy()) {
            ObjectBuilder objectBuilder = this.elementDescriptor.getObjectBuilder();
            List wrappedElements = new ArrayList(size);
            for(int i=0; i < size; i++) {
                wrappedElements.add(objectBuilder.wrapObject(elements.get(i), session));
            }
            elements = wrappedElements;
        }

        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();

        // populate container with a dummy so the container.set(i, obj) could be used later.
        for(int i=0; i < size; i++) {
            ((List)container).add(NOT_SET);
        }
        // insert the elements into container
        boolean failed = false;
        for(int i=0; i < size; i++) {
            AbstractRecord row = dbRows.get(i);
            Object orderValue = row.get(this.listOrderField);
            // order value is null
            if(orderValue == null) {
                failed = true;
                break;
            }
            int intOrderValue = ((Integer)conversionManager.convertObject(orderValue, Integer.class)).intValue();
            try {
                // one or more elements have the same order value
                if(NOT_SET != ((List)container).set(intOrderValue, elements.get(i))) {
                    failed = true;
                    break;
                }
            } catch(IndexOutOfBoundsException indexException) {
                // order value negative or greater/equal to size
                failed = true;
                break;
            }
        }

        if(failed) {
            ((List)container).clear();

            // extract order list - it will be set into exception or used by order correction.
            List<Integer> orderList = new ArrayList(size);
            for(int i=0; i < size; i++) {
                AbstractRecord row = dbRows.get(i);
                Object orderValue = row.get(this.listOrderField);
                if(orderValue == null) {
                    orderList.add(null);
                } else {
                    orderList.add((Integer)conversionManager.convertObject(orderValue, Integer.class));
                }
            }

            if(this.orderCorrectionType == OrderCorrectionType.READ || this.orderCorrectionType == OrderCorrectionType.READ_WRITE) {
                // pair each element with its order index
                List<IndexedObject> indexedElements = new ArrayList(size);
                for(int i=0; i < size; i++) {
                    indexedElements.add(new IndexedObject(orderList.get(i), elements.get(i)));
                }

                // put elements in order and add to container
                ((List)container).addAll(correctOrderList(indexedElements));

                if(this.orderCorrectionType == OrderCorrectionType.READ_WRITE) {
                    // mark IndirectList to have broken order
                    ((IndirectList)container).setIsListOrderBrokenInDb(true);
                }
            } else {
                // this.orderCorrectionType == OrderCorrectionType.EXCEPTION
                throw QueryException.listOrderFieldWrongValue(query, this.listOrderField, orderList);
            }
        }
        return size > 0;
    }

    /**
     * INTERNAL:
     * Add element into a container which implements the List interface.
     * Add at a particular index.
     */
    protected void addIntoAtIndex(Integer index, Object object, Object container, AbstractSession session) {
        if (hasElementDescriptor()) {
            object = getElementDescriptor().getObjectBuilder().wrapObject(object, session);
        }

        try {
            if (index == null || (index.intValue() > sizeFor(container))) {
                // The index can be larger than the size on a merge,
                // so should be added to the end, it may also be null if the
                // index was unknown, such as an event using the add API.
                ((List)container).add(object);
            } else {
                ((List)container).add(index.intValue(), object);
            }
        } catch (ClassCastException ex1) {
            throw QueryException.cannotAddElement(object, container, ex1);
        } catch (IllegalArgumentException ex2) {
            throw QueryException.cannotAddElement(object, container, ex2);
        } catch (UnsupportedOperationException ex3) {
            throw QueryException.cannotAddElement(object, container, ex3);
        }
    }

    /**
     * INTERNAL:
     * This method is used to calculate the differences between two collections.
     * This algorithm is a work in progress. It works great and all, but like
     * anything, you can always make it better.
     */
    @Override
    public void compareCollectionsForChange(Object oldList, Object newList, CollectionChangeRecord changeRecord, AbstractSession session, ClassDescriptor referenceDescriptor) {
        List orderedObjectsToAdd = new ArrayList();
        Map indicesToRemove = new HashMap();
        Map oldListIndexValue = new HashMap();
        IdentityHashMap oldListValueIndex = new IdentityHashMap();
        IdentityHashMap objectsToAdd = new IdentityHashMap();
        Map<Object, Integer> newListValueIndex = new IdentityHashMap();

        // Step 1 - Go through the old list.
        if (oldList != null) {
            ListIterator iterator = (ListIterator)iteratorFor(oldList);

            while (iterator.hasNext()) {
                Integer index = Integer.valueOf(iterator.nextIndex());
                Object value = iterator.next();
                oldListValueIndex.put(value, index);
                oldListIndexValue.put(index, value);
                indicesToRemove.put(index, index);
            }
        }

        // Step 2 - Go though the new list.
        if (newList != null) {
            // Step i - Gather the list info.
            ListIterator iterator = (ListIterator)iteratorFor(newList);
            while (iterator.hasNext()) {
                newListValueIndex.put(iterator.next(), Integer.valueOf(iterator.previousIndex()));
            }

            // Step ii - Go through the new list again.
            int index = 0;
            int offset = 0;
            iterator = (ListIterator)iteratorFor(newList);
            while (iterator.hasNext()) {
                index = iterator.nextIndex();
                Object currentObject = iterator.next();

                // If value is null then nothing can be done with it.
                if (currentObject != null) {
                    if (oldListValueIndex.containsKey(currentObject)) {
                        int oldIndex = ((Integer) oldListValueIndex.get(currentObject)).intValue();
                        oldListValueIndex.remove(currentObject);

                        if (index == oldIndex) {
                            indicesToRemove.remove(Integer.valueOf(oldIndex));
                            offset = 0; // Reset the offset, assume we're back on track.
                        } else if (index == (oldIndex + offset)) {
                            // We're in the right spot according to the offset.
                            indicesToRemove.remove(Integer.valueOf(oldIndex));
                        } else {
                            // Time to be clever and figure out why we're not in the right spot!
                            int movedObjects = 0;
                            int deletedObjects = 0;
                            boolean moved = true;

                            if (oldIndex < index) {
                                ++offset;
                            } else {
                                for (int i = oldIndex - 1; i >= index; i--) {
                                    Object oldObject = oldListIndexValue.get(Integer.valueOf(i));
                                    if (newListValueIndex.containsKey(oldObject)) {
                                        ++movedObjects;
                                    } else {
                                        ++deletedObjects;
                                    }
                                }

                                if (index == ((oldIndex + offset) - deletedObjects)) {
                                    // We fell into place because of deleted objects.
                                    offset = offset - deletedObjects;
                                    moved = false;
                                } else if (movedObjects > 1) {
                                    // Assume we moved down, bumping everyone by one.
                                    ++offset;
                                } else {
                                    // Assume we moved down unless the object that was
                                    // here before is directly beside us.
                                    Object oldObject = oldListIndexValue.get(Integer.valueOf(index));

                                    if (newListValueIndex.containsKey(oldObject)) {
                                        if (((newListValueIndex.get(oldObject)).intValue() - index) > 1) {
                                            moved = false; // Assume the old object moved up.
                                            --offset;
                                        }
                                    }
                                }
                            }

                            if (moved) {
                                // Add ourselves to the ordered add list.
                                orderedObjectsToAdd.add(currentObject);
                            } else {
                                // Take us off the removed list.
                                indicesToRemove.remove(Integer.valueOf(oldIndex));
                            }
                        }
                    } else {
                        ++offset;
                        objectsToAdd.put(currentObject, currentObject);
                        orderedObjectsToAdd.add(currentObject);
                    }
                } else {
                    // If we find nulls we need decrease our offset.
                    offset--;
                }
            }
        }

        // Sort the remove indices that are left and set the data on the collection change
        // record to be processed on the merge.
        List orderedIndicesToRemove = new ArrayList(indicesToRemove.values());
        Collections.sort(orderedIndicesToRemove);
        changeRecord.addAdditionChange(objectsToAdd, this, (UnitOfWorkChangeSet) changeRecord.getOwner().getUOWChangeSet(), session);
        changeRecord.addRemoveChange(oldListValueIndex, this, (UnitOfWorkChangeSet) changeRecord.getOwner().getUOWChangeSet(), session);
        changeRecord.addOrderedAdditionChange(orderedObjectsToAdd, newListValueIndex, (UnitOfWorkChangeSet) changeRecord.getOwner().getUOWChangeSet(), session);
        changeRecord.addOrderedRemoveChange(orderedIndicesToRemove, oldListIndexValue, (UnitOfWorkChangeSet) changeRecord.getOwner().getUOWChangeSet(), session);
    }

    /**
     * PUBLIC:
     * Correct object's order in the list.
     * The method is called only in one case - when the list of order indexes read from db is invalid
     * (contains nulls, duplicates, negative values, values greater/equal list size).
     * Each element of the indexedObjects is a pair of the order index and the corresponding object.
     * The goal of the method is to return back the list of objects (not indexed objects!) in the correct order.
     * The objects should not be altered.
     *
     * The default implementation of the method sorts indexedObjects according to their indexes (null less than any non-null).
     * For example:
     *   indexedObjects = {{2, objectA}, {5, ObjectB}}  returns {objectA, objectB};
     *   indexedObjects = {{2, objectA}, {-1, ObjectB}}  returns {objectB, objectA};
     *   indexedObjects = {{2, objectA}, {null, ObjectB}}  returns {objectB, objectA};
     *
     * This method could be overridden by the user.
     */
    public List correctOrderList(List<IndexedObject> indexedObjects) {
        Collections.sort(indexedObjects);
        int size = indexedObjects.size();
        List objects = new ArrayList(size);
        for(int i=0; i < size; i++) {
            objects.add(indexedObjects.get(i).getObject());
        }
        return objects;
    }

    /**
     * INTERNAL:
     * Used to create an iterator on a the Map object passed to CollectionChangeRecord.addRemoveChange()
     * to access the values to be removed.  In the case of some container policies the values will actually
     * be the keys.
     */
    @Override
    public Iterator getChangeValuesFrom(Map map) {
        return map.keySet().iterator();
    }

    public DatabaseField getListOrderField() {
        return this.listOrderField;
    }

    public void setListOrderField(DatabaseField field) {
        this.listOrderField = field;
    }

    public OrderCorrectionType getOrderCorrectionType() {
        return this.orderCorrectionType;
    }

    public void setOrderCorrectionType(OrderCorrectionType orderCorrectionType) {
        if(this.orderCorrectionType == orderCorrectionType) {
            return;
        }
        if(orderCorrectionType == OrderCorrectionType.READ_WRITE) {
            if(getContainerClass() == null || !IndirectList.class.isAssignableFrom(getContainerClass())) {
                setContainerClass(IndirectList.class);
            }
        }
        this.orderCorrectionType = orderCorrectionType;
    }

    /**
     * INTERNAL:
     * Return an list iterator for the given container.
     */
    @Override
    public Object iteratorFor(Object container) {
        return ((List)container).listIterator();
    }

    @Override
    public boolean isOrderedListPolicy() {
        return true;
    }

    /**
     * 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 change set.
     * Synchronize if system property is specified. If not, default to clone the
     * target collection. No need to synchronize if the collection is new.
     */
    @Override
    public void mergeChanges(CollectionChangeRecord changeRecord, Object valueOfTarget, boolean shouldMergeCascadeParts, MergeManager mergeManager, AbstractSession targetSession, boolean isSynchronizeOnMerge) {
        if (isSynchronizeOnMerge && !changeRecord.getOwner().isNew()) {
            // Ensure the collection is synchronized while changes are being made,
            // clone also synchronizes on collection (does not have cache key read-lock for indirection).
            // Must synchronize of the real collection as the clone does so.
            Object synchronizedValueOfTarget = valueOfTarget;
            if (valueOfTarget instanceof IndirectCollection) {
                synchronizedValueOfTarget = ((IndirectCollection)valueOfTarget).getDelegateObject();
            }
            synchronized(synchronizedValueOfTarget) {
                mergeChanges(changeRecord, valueOfTarget, shouldMergeCascadeParts, mergeManager, targetSession);
            }
        } else {
            mergeChanges(changeRecord, valueOfTarget, shouldMergeCascadeParts, mergeManager, targetSession);
        }
    }

    /**
     * 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 change set.
     */
    @Override
    protected void mergeChanges(CollectionChangeRecord changeRecord, Object valueOfTarget, boolean shouldMergeCascadeParts, MergeManager mergeManager, AbstractSession targetSession) {
        ObjectChangeSet objectChanges;
        if(changeRecord.orderHasBeenRepaired() && valueOfTarget instanceof IndirectList) {
            ((IndirectList)valueOfTarget).setIsListOrderBrokenInDb(false);
        }
        if (!changeRecord.getOrderedChangeObjectList().isEmpty()) {
            Iterator objects =changeRecord.getOrderedChangeObjectList().iterator();
            while (objects.hasNext()){
                OrderedChangeObject changeObject = (OrderedChangeObject)objects.next();
                objectChanges = changeObject.getChangeSet();
                if (changeObject.getChangeType() == CollectionChangeEvent.REMOVE){
                    boolean objectRemoved = changeRecord.getRemoveObjectList().containsKey(objectChanges);
                    Object objectToRemove = objectChanges.getTargetVersionOfSourceObject(mergeManager, targetSession);

                    //if objectToRemove is null, we can't look it up in the collection.
                    // This should not happen unless identity is lost.
                    if (objectToRemove != null) {
                        Integer index = changeObject.getIndex();
                        if (index!=null){
                            if (objectToRemove.equals(get(index, valueOfTarget, mergeManager.getSession()))) {
                                removeFromAtIndex(index, valueOfTarget);
                            } else {
                                // Object is in the cache, but the collection doesn't have it at the location we expect
                                // Collection is invalid with respect to these changes, so invalidate the parent and abort
                                Object key = changeRecord.getOwner().getId();
                                targetSession.getIdentityMapAccessor().invalidateObject(key, changeRecord.getOwner().getClassType(targetSession));
                                return;
                            }
                        } else {
                            removeFrom(objectToRemove, valueOfTarget, targetSession);
                        }

                        if ((! mergeManager.shouldMergeChangesIntoDistributedCache()) && changeRecord.getMapping().isPrivateOwned()) {
                            // Check that the object was actually removed and not moved.
                            if (objectRemoved) {
                                mergeManager.registerRemovedNewObjectIfRequired(objectChanges.getUnitOfWorkClone());
                            }
                        }
                    }


                } else { //getChangeType == add
                    boolean objectAdded = changeRecord.getAddObjectList().containsKey(objectChanges);
                    Object object = null;
                    // The object was actually added and not moved.
                    if (objectAdded && shouldMergeCascadeParts) {
                        object = mergeCascadeParts(objectChanges, mergeManager, targetSession);
                    }

                    if (object == null) {
                        // Retrieve the object to be added to the collection.
                        object = objectChanges.getTargetVersionOfSourceObject(mergeManager, targetSession);
                    }

                    // Assume at this point the above merge will have created a new
                    // object if required and that the object was actually added and
                    // not moved.
                    if (objectAdded && mergeManager.shouldMergeChangesIntoDistributedCache()) {
                        // Bugs 4458089 & 4454532 - check if collection contains new item before adding
                        // during merge into distributed cache
                        if (! contains(object, valueOfTarget, mergeManager.getSession())) {
                            addIntoAtIndex(changeObject.getIndex(), object, valueOfTarget, mergeManager.getSession());
                        }
                    } else {
                        addIntoAtIndex(changeObject.getIndex(), object, valueOfTarget, targetSession);
                    }
                }
            }
        } else {
            //Deferred change tracking merge behavior
            // Step 1 - iterate over the removed changes and remove them from the container.
            List<Integer> removedIndices = changeRecord.getOrderedRemoveObjectIndices();

            if (removedIndices.isEmpty()) {
                // Check if we have removed objects via a
                // simpleRemoveFromCollectionChangeRecord API call.
                Iterator removedObjects = changeRecord.getRemoveObjectList().keySet().iterator();

                while (removedObjects.hasNext()) {
                    objectChanges = (ObjectChangeSet) removedObjects.next();
                    removeFrom(objectChanges.getOldKey(), objectChanges.getTargetVersionOfSourceObject(mergeManager, targetSession), valueOfTarget, targetSession);
                    registerRemoveNewObjectIfRequired(objectChanges, mergeManager);
                }
            } else {
                for (int i = removedIndices.size() - 1; i >= 0; i--) {
                    Integer index = removedIndices.get(i);
                    objectChanges = (ObjectChangeSet) changeRecord.getOrderedRemoveObject(index);
                    Object objectToRemove = objectChanges.getTargetVersionOfSourceObject(mergeManager, targetSession);
                    if ( (objectToRemove!=null) &&
                                (objectToRemove.equals(get(index, valueOfTarget, mergeManager.getSession()) )) ) {
                        removeFromAtIndex(index, valueOfTarget);
                        // The object was actually removed and not moved.
                        if (changeRecord.getRemoveObjectList().containsKey(objectChanges)) {
                            registerRemoveNewObjectIfRequired(objectChanges, mergeManager);
                        }
                    } else {

                        //Object is either not in the cache, or not at the location we expect
                        // Collection is invalid with respect to these changes, so invalidate the parent and abort
                        Object key = changeRecord.getOwner().getId();
                        targetSession.getIdentityMapAccessor().invalidateObject(key, changeRecord.getOwner().getClassType(targetSession));
                        return;
                    }
                }
            }

            // Step 2 - iterate over the added changes and add them to the container.
            for (ObjectChangeSet addChangeSet : changeRecord.getOrderedAddObjects()) {
                objectChanges =  addChangeSet;
                boolean objectAdded = changeRecord.getAddObjectList().containsKey(objectChanges);
                Object object = null;

                // The object was actually added and not moved.
                if (objectAdded && shouldMergeCascadeParts) {
                    object = mergeCascadeParts(objectChanges, mergeManager, targetSession);
                }

                if (object == null) {
                    // Retrieve the object to be added to the collection.
                    object = objectChanges.getTargetVersionOfSourceObject(mergeManager, targetSession);
                }

                // Assume at this point the above merge will have created a new
                // object if required and that the object was actually added and
                // not moved.
                if (objectAdded && mergeManager.shouldMergeChangesIntoDistributedCache()) {
                    // Bugs 4458089 & 4454532 - check if collection contains new item before adding
                    // during merge into distributed cache
                    if (! contains(object, valueOfTarget, mergeManager.getSession())) {
                        addIntoAtIndex(changeRecord.getOrderedAddObjectIndex(objectChanges), object, valueOfTarget, mergeManager.getSession());
                    }
                } else {
                    addIntoAtIndex(changeRecord.getOrderedAddObjectIndex(objectChanges), object, valueOfTarget, targetSession);
                }
            }
        }
    }

    /**
     * INTERNAL:
     */
    protected void registerRemoveNewObjectIfRequired(ObjectChangeSet objectChanges, MergeManager mergeManager) {
        if (! mergeManager.shouldMergeChangesIntoDistributedCache()) {
            mergeManager.registerRemovedNewObjectIfRequired(objectChanges.getUnitOfWorkClone());
        }
    }

    /**
     * INTERNAL:
     * Remove the element at the specified index.
     */
    protected void removeFromAtIndex(int index, Object container) {
        try {
            ((List) container).remove(index);
        } catch (ClassCastException ex1) {
            throw QueryException.cannotRemoveFromContainer(Integer.valueOf(index), container, this);
        } catch (IllegalArgumentException ex2) {
            throw QueryException.cannotRemoveFromContainer(Integer.valueOf(index), container, this);
        } catch (UnsupportedOperationException ex3) {
            throw QueryException.cannotRemoveFromContainer(Integer.valueOf(index), container, this);
        }
    }

    /**
     * This method is used to bridge the behavior between Attribute Change Tracking and
     * deferred change tracking with respect to adding the same instance multiple times.
     * Each ContainerPolicy type will implement specific behavior for the collection
     * type it is wrapping.  These methods are only valid for collections containing object references
     */
    @Override
    public void recordAddToCollectionInChangeRecord(ObjectChangeSet changeSetToAdd, CollectionChangeRecord collectionChangeRecord){
        OrderedChangeObject orderedChangeObject = new OrderedChangeObject(CollectionChangeEvent.ADD, null, changeSetToAdd);
        collectionChangeRecord.getOrderedChangeObjectList().add(orderedChangeObject);
    }

    @Override
    public void recordRemoveFromCollectionInChangeRecord(ObjectChangeSet changeSetToRemove, CollectionChangeRecord collectionChangeRecord){
        OrderedChangeObject orderedChangeObject = new OrderedChangeObject(CollectionChangeEvent.REMOVE, null, changeSetToRemove);
        collectionChangeRecord.getOrderedChangeObjectList().add(orderedChangeObject);
    }

    @Override
    public void recordUpdateToCollectionInChangeRecord(CollectionChangeEvent event, ObjectChangeSet changeSet, CollectionChangeRecord collectionChangeRecord){
        int changeType = event.getChangeType();
        if (changeType == CollectionChangeEvent.ADD) {
            super.recordAddToCollectionInChangeRecord(changeSet, collectionChangeRecord);
        } else if (changeType == CollectionChangeEvent.REMOVE) {
            super.recordRemoveFromCollectionInChangeRecord(changeSet, collectionChangeRecord);
        } else {
            throw ValidationException.wrongCollectionChangeEventType(changeType);
        }

        OrderedChangeObject orderedChangeObject = new OrderedChangeObject(changeType, event.getIndex(), changeSet, event.getNewValue());
        collectionChangeRecord.getOrderedChangeObjectList().add(orderedChangeObject);
    }

    /**
     * INTERNAL:
     * Indicates whether addAll method should be called to add entire collection,
     * or it's possible to call addInto multiple times instead.
     */
    @Override
    public boolean shouldAddAll() {
        return this.listOrderField != null;
    }

    /**
     * INTERNAL:
     * Return any additional fields required by the policy for a fetch join.
     */
    @Override
    public List<DatabaseField> getAdditionalFieldsForJoin(CollectionMapping baseMapping) {
        if (this.listOrderField != null) {
            List<DatabaseField> fields = new ArrayList<>(1);
            fields.add(this.listOrderField);
            return fields;
        }
        return null;
    }

    /**
     * INTERNAL:
     * Add the index field count.
     */
    @Override
    public int updateJoinedMappingIndexesForMapKey(Map<DatabaseMapping, Object> indexList, int index) {
        if (this.listOrderField != null) {
            return 1;
        }
        return 0;
    }

    /**
     * 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, ForeignReferenceMapping mapping, UnitOfWorkChangeSet parentUOWChangeSet, UnitOfWorkImpl unitOfWork){
        ObjectChangeSet sourceSet = parentUOWChangeSet.getCloneToObjectChangeSet().get(source);
        for (OrderedChangeObject changeObject : ((CollectionChangeRecord)changeRecord).getOrderedChangeObjectList()){
            if (changeObject.getChangeSet() == sourceSet){
                changeObject.setChangeSet(((UnitOfWorkChangeSet)unitOfWork.getUnitOfWorkChangeSet()).findOrCreateLocalObjectChangeSet(target, mapping.getReferenceDescriptor(), unitOfWork.isCloneNewObject(target)));
            }
            return;
        }
    }

    /**
     * INTERNAL:
     * Return any tables that will be required when this mapping is used as part of a join query.
     */
    @Override
    public List<DatabaseTable> getAdditionalTablesForJoinQuery() {
        if (this.listOrderField != null) {
            List tables = new ArrayList(1);
            tables.add(this.listOrderField.getTable());
            return tables;
        }
        return null;
    }

    /**
     * INTERNAL:
     * Add the index field to the query.
     */
    @Override
    public void addAdditionalFieldsToQuery(ReadQuery selectionQuery, Expression baseExpression) {
        if (this.listOrderField != null) {
            if (selectionQuery.isObjectLevelReadQuery()) {
                ((ObjectLevelReadQuery)selectionQuery).addAdditionalField(baseExpression.getField(this.listOrderField));
            } else {
                ((SQLSelectStatement) selectionQuery.getSQLStatement()).addField(baseExpression.getField(this.listOrderField));
            }
        }
    }
}
