/*******************************************************************************
 * Copyright (c) 1998, 2013 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 v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
 ******************************************************************************/  
package org.eclipse.persistence.eis.mappings;

import java.util.*;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.internal.sessions.*;
import org.eclipse.persistence.internal.queries.*;
import org.eclipse.persistence.eis.EISCollectionChangeRecord;
import org.eclipse.persistence.eis.EISOrderedCollectionChangeRecord;

/**
 * INTERNAL:
 * Helper class to consolidate all the heinous comparing
 * and merging code for the EIS one to many mappings.
 */
public class EISOneToManyMappingHelper {

    /** The mapping that needs help comparing and merging. */
    private EISOneToManyMapping mapping;
    private static Object XXX = new Object();// object used to marked cleared out slots when comparing

    /**
     * Constructor.
     */
    public EISOneToManyMappingHelper(EISOneToManyMapping mapping) {
        super();
        this.mapping = mapping;
    }

    /**
     * Convenience method.
     */
    private Object buildAddedElementFromChangeSet(Object changeSet, MergeManager mergeManager, AbstractSession targetSession) {
        return this.getMapping().buildAddedElementFromChangeSet(changeSet, mergeManager, targetSession);
    }

    /**
     * Convenience method.
     */
    private Object buildChangeSet(Object element, ObjectChangeSet owner, AbstractSession session) {
        return this.getMapping().buildChangeSet(element, owner, session);
    }

    /**
     * Convenience method.
     */
    private Object buildElementFromElement(Object element, MergeManager mergeManager, AbstractSession targetSession) {
        return this.getMapping().buildElementFromElement(element, mergeManager, targetSession);
    }

    /**
     * Convenience method.
     */
    private Object buildRemovedElementFromChangeSet(Object changeSet, MergeManager mergeManager, AbstractSession targetSession) {
        return this.getMapping().buildRemovedElementFromChangeSet(changeSet, mergeManager, targetSession);
    }

    /**
     * Compare the attributes. Return true if they are alike.
     * Assume the passed-in attributes are non-null.
     */
    private boolean compareAttributeValues(Object collection1, Object collection2, AbstractSession session) {
        ContainerPolicy cp = this.getContainerPolicy();

        if (cp.sizeFor(collection1) != cp.sizeFor(collection2)) {
            return false;
        }

        // if they are both empty, go no further...
        if (cp.sizeFor(collection1) == 0) {
            return true;
        }

        if (cp.hasOrder()) {
            return this.compareAttributeValuesWithOrder(collection1, collection2, session);
        } else {
            return this.compareAttributeValuesWithoutOrder(collection1, collection2, session);
        }
    }

    /**
     * Build and return the change record that results
     * from comparing the two collection attributes.
     * The order of the elements is significant.
     */
    private ChangeRecord compareAttributeValuesForChangeWithOrder(Object cloneCollection, Object backupCollection, ObjectChangeSet owner, AbstractSession session) {
        ContainerPolicy cp = this.getContainerPolicy();

        Vector cloneVector = cp.vectorFor(cloneCollection, session);// convert it to a Vector so we can preserve the order and use indexes
        Vector backupVector = cp.vectorFor(backupCollection, session);// "clone" it so we can clear out the slots

        EISOrderedCollectionChangeRecord changeRecord = new EISOrderedCollectionChangeRecord(owner, this.getAttributeName(), this.getDatabaseMapping());

        for (int i = 0; i < cloneVector.size(); i++) {
            Object cloneElement = cloneVector.elementAt(i);
            boolean found = false;
            for (int j = 0; j < backupVector.size(); j++) {
                if (this.compareElementsForChange(cloneElement, backupVector.elementAt(j), session)) {
                    // the clone element was found in the backup collection
                    found = true;
                    backupVector.setElementAt(XXX, j);// clear out the matching backup element

                    changeRecord.addMovedChangeSet(this.buildChangeSet(cloneElement, owner, session), j, i);
                    break;// matching backup element found - skip the rest of them
                }
            }
            if (!found) {
                // the clone element was not found, so it must have been added
                changeRecord.addAddedChangeSet(this.buildChangeSet(cloneElement, owner, session), i);
            }
        }

        for (int i = 0; i < backupVector.size(); i++) {
            Object backupElement = backupVector.elementAt(i);
            if (backupElement != XXX) {
                // the backup element was not in the clone collection, so it must have been removed
                changeRecord.addRemovedChangeSet(this.buildChangeSet(backupElement, owner, session), i);
            }
        }

        if (changeRecord.hasChanges()) {
            return changeRecord;
        } else {
            return null;
        }
    }

    /**
     * Build and return the change record that results
     * from comparing the two collection attributes.
     * Ignore the order of the elements.
     */
    private ChangeRecord compareAttributeValuesForChangeWithoutOrder(Object cloneCollection, Object backupCollection, ObjectChangeSet owner, AbstractSession session) {
        ContainerPolicy cp = this.getContainerPolicy();

        Vector backupVector = cp.vectorFor(backupCollection, session);// "clone" it so we can clear out the slots

        EISCollectionChangeRecord changeRecord = new EISCollectionChangeRecord(owner, this.getAttributeName(), this.getDatabaseMapping());
        for (Object cloneIter = cp.iteratorFor(cloneCollection); cp.hasNext(cloneIter);) {
            Object cloneElement = cp.next(cloneIter, session);

            boolean found = false;
            for (int i = 0; i < backupVector.size(); i++) {
                if (this.compareElementsForChange(cloneElement, backupVector.elementAt(i), session)) {
                    // the clone element was found in the backup collection
                    found = true;
                    backupVector.setElementAt(XXX, i);// clear out the matching backup element
                    if (this.mapKeyHasChanged(cloneElement, session)) {
                        changeRecord.addChangedMapKeyChangeSet(this.buildChangeSet(cloneElement, owner, session));
                    }
                    break;// matching backup element found - skip the rest of them
                }
            }
            if (!found) {
                // the clone element was not found, so it must have been added
                changeRecord.addAddedChangeSet(this.buildChangeSet(cloneElement, owner, session));
            }
        }

        for (int i = 0; i < backupVector.size(); i++) {
            Object backupElement = backupVector.elementAt(i);
            if (backupElement != XXX) {
                // the backup element was not in the clone collection, so it must have been removed
                changeRecord.addRemovedChangeSet(this.buildChangeSet(backupElement, owner, session));
            }
        }

        if (changeRecord.hasChanges()) {
            return changeRecord;
        } else {
            return null;
        }
    }

    /**
     * Compare the attributes. Return true if they are alike.
     * The order of the elements is significant.
     */
    private boolean compareAttributeValuesWithOrder(Object collection1, Object collection2, AbstractSession session) {
        ContainerPolicy cp = this.getContainerPolicy();

        Object iter1 = cp.iteratorFor(collection1);
        Object iter2 = cp.iteratorFor(collection2);

        while (cp.hasNext(iter1)) {
            if (!this.compareElements(cp.next(iter1, session), cp.next(iter2, session), session)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Compare the attributes. Return true if they are alike.
     * Ignore the order of the elements.
     */
    private boolean compareAttributeValuesWithoutOrder(Object collection1, Object collection2, AbstractSession session) {
        ContainerPolicy cp = this.getContainerPolicy();

        Vector vector2 = cp.vectorFor(collection2, session);// "clone" it so we can clear out the slots

        for (Object iter1 = cp.iteratorFor(collection1); cp.hasNext(iter1);) {
            Object element1 = cp.next(iter1, session);

            boolean found = false;
            for (int i = 0; i < vector2.size(); i++) {
                if (this.compareElements(element1, vector2.elementAt(i), session)) {
                    found = true;
                    vector2.setElementAt(XXX, i);// clear out the matching element
                    break;// matching element found - skip the rest of them
                }
            }
            if (!found) {
                return false;
            }
        }

        // look for elements that were not in collection1
        for (Enumeration stream = vector2.elements(); stream.hasMoreElements();) {
            if (stream.nextElement() != XXX) {
                return false;
            }
        }
        return true;
    }

    /**
     * Convenience method.
     * Check for null values before delegating to the mapping.
     */
    private boolean compareElements(Object element1, Object element2, AbstractSession session) {
        if ((element1 == null) && (element2 == null)) {
            return true;
        }
        if ((element1 == null) || (element2 == null)) {
            return false;
        }
        if (element2 == XXX) {// if element2 was marked as cleared out, it is not a match
            return false;
        }
        return this.getMapping().compareElements(element1, element2, session);
    }

    /**
     * Convenience method.
     * Check for null values before delegating to the mapping.
     */
    private boolean compareElementsForChange(Object element1, Object element2, AbstractSession session) {
        if ((element1 == null) && (element2 == null)) {
            return true;
        }
        if ((element1 == null) || (element2 == null)) {
            return false;
        }
        if (element2 == XXX) {// if element2 was marked as cleared out, it is not a match
            return false;
        }
        return this.getMapping().compareElementsForChange(element1, element2, session);
    }

    /**
     * INTERNAL:
     * Build and return the change record that results
     * from comparing the two collection attributes.
     */
    public ChangeRecord compareForChange(Object clone, Object backup, ObjectChangeSet owner, AbstractSession session) {
        ContainerPolicy cp = this.getContainerPolicy();
        Object cloneCollection = this.getRealCollectionAttributeValueFromObject(clone, session);

        Object backupCollection = null;
        if (owner.isNew()) {
            backupCollection = cp.containerInstance(1);
        } else {
            backupCollection = this.getRealCollectionAttributeValueFromObject(backup, session);
        }

        if (cp.hasOrder()) {
            return this.compareAttributeValuesForChangeWithOrder(cloneCollection, backupCollection, owner, session);
        } else {
            return this.compareAttributeValuesForChangeWithoutOrder(cloneCollection, backupCollection, owner, session);
        }
    }

    /**
     * INTERNAL:
     * Compare the attributes belonging to this mapping for the objects.
     */
    public boolean compareObjects(Object object1, Object object2, AbstractSession session) {
        return this.compareAttributeValues(this.getRealCollectionAttributeValueFromObject(object1, session), this.getRealCollectionAttributeValueFromObject(object2, session), session);
    }

    /**
     * Convenience method.
     */
    private String getAttributeName() {
        return this.getMapping().getAttributeName();
    }

    /**
     * Convenience method.
     */
    private ContainerPolicy getContainerPolicy() {
        return this.getMapping().getContainerPolicy();
    }

    /**
     * INTERNAL:
     * Return the mapping, casted a bit more generally.
     */
    public DatabaseMapping getDatabaseMapping() {
        return this.getMapping();
    }

    /**
     * INTERNAL:
     * Return the mapping.
     */
    public EISOneToManyMapping getMapping() {
        return mapping;
    }

    /**
     * Convenience method.
     */
    private Object getRealCollectionAttributeValueFromObject(Object object, AbstractSession session) {
        return this.getMapping().getRealCollectionAttributeValueFromObject(object, session);
    }

    /**
     * Convenience method.
     */
    private boolean mapKeyHasChanged(Object element, AbstractSession session) {
        return this.getMapping().mapKeyHasChanged(element, session);
    }

    /**
     * INTERNAL:
     * Merge changes from the source to the target object.
     */
    public void mergeChangesIntoObject(Object target, ChangeRecord changeRecord, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        if (this.getContainerPolicy().hasOrder()) {
            this.mergeChangesIntoObjectWithOrder(target, changeRecord, source, mergeManager, targetSession);
        } else {
            this.mergeChangesIntoObjectWithoutOrder(target, changeRecord, source, mergeManager, targetSession);
        }
    }

    /**
     * Merge changes from the source to the target object.
     * Simply replace the entire target collection.
     */
    private void mergeChangesIntoObjectWithOrder(Object target, ChangeRecord changeRecord, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        ContainerPolicy cp = this.getContainerPolicy();
        AbstractSession session = mergeManager.getSession();

        Vector changes = ((EISOrderedCollectionChangeRecord)changeRecord).getNewCollection();
        Object targetCollection = cp.containerInstance(changes.size());

        for (Enumeration stream = changes.elements(); stream.hasMoreElements();) {
            Object targetElement = this.buildAddedElementFromChangeSet(stream.nextElement(), mergeManager, targetSession);
            cp.addInto(targetElement, targetCollection, session);
        }

        // reset the attribute to allow for set method to re-morph changes if the collection is not being stored directly
        this.setRealAttributeValueInObject(target, targetCollection);
    }

    /**
     * Merge changes from the source to the target object.
     * Make the necessary removals and adds and map key modifications.
     */
    private void mergeChangesIntoObjectWithoutOrder(Object target, ChangeRecord changeRecord, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        EISCollectionChangeRecord sdkChangeRecord = (EISCollectionChangeRecord)changeRecord;
        ContainerPolicy cp = this.getContainerPolicy();
        AbstractSession session = mergeManager.getSession();

        Object targetCollection = null;
        if (sdkChangeRecord.getOwner().isNew()) {
            targetCollection = cp.containerInstance(sdkChangeRecord.getAdds().size());
        } else {
            targetCollection = this.getRealCollectionAttributeValueFromObject(target, session);
        }

        Vector removes = sdkChangeRecord.getRemoves();
        Vector adds = sdkChangeRecord.getAdds();
        Vector changedMapKeys = sdkChangeRecord.getChangedMapKeys();

        synchronized (targetCollection) {
            for (Enumeration stream = removes.elements(); stream.hasMoreElements();) {
                Object removeElement = this.buildRemovedElementFromChangeSet(stream.nextElement(), mergeManager, targetSession);

                Object targetElement = null;
                for (Object iter = cp.iteratorFor(targetCollection); cp.hasNext(iter);) {
                    targetElement = cp.next(iter, session);
                    if (this.compareElements(targetElement, removeElement, session)) {
                        break;// matching element found - skip the rest of them
                    }
                }
                if (targetElement != null) {
                    // a matching element was found, remove it
                    cp.removeFrom(targetElement, targetCollection, session);
                }
            }

            for (Enumeration stream = adds.elements(); stream.hasMoreElements();) {
                Object addElement = this.buildAddedElementFromChangeSet(stream.nextElement(), mergeManager, targetSession);
                cp.addInto(addElement, targetCollection, session);
            }

            for (Enumeration stream = changedMapKeys.elements(); stream.hasMoreElements();) {
                Object changedMapKeyElement = this.buildAddedElementFromChangeSet(stream.nextElement(), mergeManager, targetSession);
                Object originalElement = ((UnitOfWorkImpl)session).getOriginalVersionOfObject(changedMapKeyElement);
                cp.removeFrom(originalElement, targetCollection, session);
                cp.addInto(changedMapKeyElement, targetCollection, session);
            }
        }

        // reset the attribute to allow for set method to re-morph changes if the collection is not being stored directly
        this.setRealAttributeValueInObject(target, targetCollection);
    }

    /**
     * INTERNAL:
     * Merge changes from the source to the target object.
     * Simply replace the entire target collection.
     */
    public void mergeIntoObject(Object target, boolean isTargetUnInitialized, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        ContainerPolicy cp = this.getContainerPolicy();
        AbstractSession session = mergeManager.getSession();

        Object sourceCollection = this.getRealCollectionAttributeValueFromObject(source, session);
        Object targetCollection = cp.containerInstance(cp.sizeFor(sourceCollection));

        for (Object iter = cp.iteratorFor(sourceCollection); cp.hasNext(iter);) {
            Object targetElement = this.buildElementFromElement(cp.next(iter, session), mergeManager, targetSession);
            cp.addInto(targetElement, targetCollection, session);
        }

        // reset the attribute to allow for set method to re-morph changes if the collection is not being stored directly
        this.setRealAttributeValueInObject(target, targetCollection);
    }

    /**
     * Convenience method.
     */
    private void setRealAttributeValueInObject(Object object, Object attributeValue) {
        this.getMapping().setRealAttributeValueInObject(object, attributeValue);
    }

    /**
     * ADVANCED:
     * This method is used to add an object to a collection once the changeSet is applied.
     * The referenceKey parameter should only be used for direct Maps.
     */
    public void simpleAddToCollectionChangeRecord(Object referenceKey, Object changeSetToAdd, ObjectChangeSet changeSet, AbstractSession session) {
        if (this.getContainerPolicy().hasOrder()) {
            this.simpleAddToCollectionChangeRecordWithOrder(referenceKey, changeSetToAdd, changeSet, session);
        } else {
            this.simpleAddToCollectionChangeRecordWithoutOrder(referenceKey, changeSetToAdd, changeSet, session);
        }
    }

    /**
     * Add stuff to an ordered collection.
     */
    private void simpleAddToCollectionChangeRecordWithOrder(Object referenceKey, Object changeSetToAdd, ObjectChangeSet changeSet, AbstractSession session) {
        EISOrderedCollectionChangeRecord changeRecord = (EISOrderedCollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName());
        if (changeRecord == null) {
            changeRecord = new EISOrderedCollectionChangeRecord(changeSet, this.getAttributeName(), this.getDatabaseMapping());
            changeSet.addChange(changeRecord);
        }
        changeRecord.simpleAddChangeSet(changeSetToAdd);
    }

    /**
     * Add stuff to an unordered collection.
     */
    private void simpleAddToCollectionChangeRecordWithoutOrder(Object referenceKey, Object changeSetToAdd, ObjectChangeSet changeSet, AbstractSession session) {
        EISCollectionChangeRecord changeRecord = (EISCollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName());
        if (changeRecord == null) {
            changeRecord = new EISCollectionChangeRecord(changeSet, this.getAttributeName(), this.getDatabaseMapping());
            changeSet.addChange(changeRecord);
        }
        changeRecord.simpleAddChangeSet(changeSetToAdd);
    }

    /**
     * ADVANCED:
     * This method is used to remove an object from a collection once the changeSet is applied.
     * The referenceKey parameter should only be used for direct Maps.
     */
    public void simpleRemoveFromCollectionChangeRecord(Object referenceKey, Object changeSetToRemove, ObjectChangeSet changeSet, AbstractSession session) {
        if (this.getContainerPolicy().hasOrder()) {
            this.simpleRemoveFromCollectionChangeRecordWithOrder(referenceKey, changeSetToRemove, changeSet, session);
        } else {
            this.simpleRemoveFromCollectionChangeRecordWithoutOrder(referenceKey, changeSetToRemove, changeSet, session);
        }
    }

    /**
     * Remove stuff from an ordered collection.
     */
    private void simpleRemoveFromCollectionChangeRecordWithOrder(Object referenceKey, Object changeSetToRemove, ObjectChangeSet changeSet, AbstractSession session) {
        EISOrderedCollectionChangeRecord changeRecord = (EISOrderedCollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName());
        if (changeRecord == null) {
            changeRecord = new EISOrderedCollectionChangeRecord(changeSet, this.getAttributeName(), this.getDatabaseMapping());
            changeSet.addChange(changeRecord);
        }
        changeRecord.simpleRemoveChangeSet(changeSetToRemove);
    }

    /**
     * Remove stuff from an unordered collection.
     */
    private void simpleRemoveFromCollectionChangeRecordWithoutOrder(Object referenceKey, Object changeSetToRemove, ObjectChangeSet changeSet, AbstractSession session) {
        EISCollectionChangeRecord changeRecord = (EISCollectionChangeRecord)changeSet.getChangesForAttributeNamed(this.getAttributeName());
        if (changeRecord == null) {
            changeRecord = new EISCollectionChangeRecord(changeSet, this.getAttributeName(), this.getDatabaseMapping());
            changeSet.addChange(changeRecord);
        }
        changeRecord.simpleRemoveChangeSet(changeSetToRemove);
    }
}
