/*******************************************************************************
 * 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.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.eis.EISDescriptor;
import org.eclipse.persistence.eis.EISException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.OptimisticLockException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.indirection.ValueHolder;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.indirection.EISOneToManyQueryBasedValueHolder;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.internal.oxm.XPathEngine;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.sessions.*;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.oxm.record.DOMRecord;
import org.eclipse.persistence.oxm.record.XMLRecord;
import org.eclipse.persistence.queries.*;
import org.w3c.dom.Element;

/**
 * <p>An EIS one-to-many mapping is a reference mapping that represents the relationship between 
 * a single source object and a collection of mapped persistent Java objects.  The source object usually 
 * contains a foreign key (pointer) to the target objects (key on source); alternatively, the target 
 * objects may contain a foreign key to the source object (key on target).  Because both the source 
 * and target objects use interactions, they must all be configured as root object types.  
 * 
 * <p><table border="1">
 * <tr>
 * <th id="c1" align="left">Record Type</th>
 * <th id="c2" align="left">Description</th>
 * </tr>
 * <tr>
 * <td headers="c1">Indexed</td>
 * <td headers="c2">Ordered collection of record elements.  The indexed record EIS format 
 * enables Java class attribute values to be retreived by position or index.</td>
 * </tr>
 * <tr>
 * <td headers="c1">Mapped</td>
 * <td headers="c2">Key-value map based representation of record elements.  The mapped record
 * EIS format enables Java class attribute values to be retreived by an object key.</td>
 * </tr>
 * <tr>
 * <td headers="c1">XML</td>
 * <td headers="c2">Record/Map representation of an XML DOM element.</td>
 * </tr>
 * </table>
 * 
 * @see org.eclipse.persistence.eis.EISDescriptor#useIndexedRecordFormat
 * @see org.eclipse.persistence.eis.EISDescriptor#useMappedRecordFormat
 * @see org.eclipse.persistence.eis.EISDescriptor#useXMLRecordFormat
 * 
 * @since Oracle TopLink 10<i>g</i> Release 2 (10.1.3)
 */
public class EISOneToManyMapping extends CollectionMapping implements EISMapping {

    /** Keeps track if any of the fields are foreign keys. */
    protected boolean isForeignKeyRelationship;

    /** The target foreign key fields that reference the sourceKeyFields. */
    protected transient List<DatabaseField> targetForeignKeyFields;

    /** The (typically primary) source key fields that are referenced by the targetForeignKeyFields. */
    protected transient List<DatabaseField> sourceForeignKeyFields;

    /** This maps the source foreign key fields to the corresponding (primary) target key fields. */
    protected transient Map<DatabaseField, DatabaseField> sourceForeignKeysToTargetKeys;

    /** The grouping-element field. */
    protected DatabaseField foreignKeyGroupingElement;

    public EISOneToManyMapping() {
        this.isForeignKeyRelationship = false;
        this.sourceForeignKeyFields = new ArrayList(1);
        this.targetForeignKeyFields = new ArrayList(1);
        this.sourceForeignKeysToTargetKeys = new HashMap(2);
        this.deleteAllQuery = new DeleteAllQuery();
    }

    /**
     * INTERNAL:
     */
    @Override
    public boolean isEISMapping() {
        return true;
    }

    /**
     * PUBLIC:
     * Define the source foreign key relationship in the one-to-many mapping.
     * This method is used for composite source foreign key relationships.
     * That is, the source object's table has multiple foreign key fields
     * that are references to
     * the target object's (typically primary) key fields.
     * Both the source foreign key field name and the corresponding
     * target primary key field name must be specified.
     */
    @Override
    public void addForeignKeyField(DatabaseField sourceForeignKeyField, DatabaseField targetKeyField) {
        this.getSourceForeignKeyFields().add(sourceForeignKeyField);
        this.getTargetForeignKeyFields().add(targetKeyField);

        this.setIsForeignKeyRelationship(true);
    }

    /**
     * PUBLIC:
     * Define the source foreign key relationship in the one-to-many mapping.
     * This method is used for composite source foreign key relationships.
     * That is, the source object's table has multiple foreign key fields
     * that are references to
     * the target object's (typically primary) key fields.
     * Both the source foreign key field name and the corresponding
     * target primary key field name must be specified.
     */
    public void addForeignKeyFieldName(String sourceForeignKeyFieldName, String targetKeyFieldName) {
        this.addForeignKeyField(new DatabaseField(sourceForeignKeyFieldName), new DatabaseField(targetKeyFieldName));
    }

    /**
     * INTERNAL:
     * Return if the 1-M mapping has a foreign key dependency to its target.
     * This is true if any of the foreign key fields are true foreign keys,
     * i.e. populated on write from the targets primary key.
     */
    public boolean isForeignKeyRelationship() {
        return isForeignKeyRelationship;
    }

    /**
     * INTERNAL:
     * Set if the 1-M mapping has a foreign key dependency to its target.
     * This is true if any of the foreign key fields are true foreign keys,
     * i.e. populated on write from the targets primary key.
     */
    public void setIsForeignKeyRelationship(boolean isForeignKeyRelationship) {
        this.isForeignKeyRelationship = isForeignKeyRelationship;
    }

    /**
     * Get the grouping element field on the mapping.
     * This is an optional setting.
     */
    public DatabaseField getForeignKeyGroupingElement() {
        return this.foreignKeyGroupingElement;
    }

    /**
     * Set the grouping element field on the mapping.
     * This is an optional setting; however it is a required setting when
     * there are more than one foreign keys specified
     */
    public void setForeignKeyGroupingElement(String name) {
        setForeignKeyGroupingElement(new DatabaseField(name));
    }

    public boolean hasCustomDeleteAllQuery() {
        return hasCustomDeleteAllQuery;
    }

    public ModifyQuery getDeleteAllQuery() {
        if (deleteAllQuery == null) {
            deleteAllQuery = new DataModifyQuery();
        }
        return deleteAllQuery;
    }

    /**
     * PUBLIC:
     * The default delete all call for this mapping can be overridden by specifying the new call.
     * This call is responsible for doing the deletion required by the mapping,
     * such as optimized delete all of target objects for 1-M.
     */
    public void setDeleteAllCall(Call call) {
        DeleteAllQuery deleteAllQuery = new DeleteAllQuery();
        deleteAllQuery.setCall(call);
        setDeleteAllQuery(deleteAllQuery);
        setHasCustomDeleteAllQuery(true);
    }

    /**
     * Set if the grouping element field on the mapping.
     * This is an optional setting; however it is a required setting when
     * there are more than one foreign keys specified.
     */
    public void setForeignKeyGroupingElement(DatabaseField field) {
        this.foreignKeyGroupingElement = field;
    }

    /**
     * INTERNAL:
     * Return the source foreign key fields.
     */
    public List<DatabaseField> getSourceForeignKeyFields() {
        return sourceForeignKeyFields;
    }

    /**
     * INTERNAL:
     * Sets the source foreign key fields.
     */
    public void setSourceForeignKeyFields(List<DatabaseField> fields) {
        sourceForeignKeyFields = fields;
        if ((fields != null) && (fields.size() > 0)) {
            this.setIsForeignKeyRelationship(true);
        }
    }

    /**
     * INTERNAL:
     * Return the source foreign key fields.
     */
    public List<DatabaseField> getTargetForeignKeyFields() {
        return targetForeignKeyFields;
    }

    /**
     * INTERNAL:
     * Sets the target foreign key fields.
     */
    public void setTargetForeignKeyFields(List<DatabaseField> fields) {
        targetForeignKeyFields = fields;
    }

    /**
    * INTERNAL:
    * Sets the target foreign key fields.
    */
    public Map<DatabaseField, DatabaseField> getSourceForeignKeysToTargetKeys() {
        return sourceForeignKeysToTargetKeys;
    }

    /**
     * INTERNAL:
     * Set the source keys to target keys fields association.
     */
    public void setSourceForeignKeysToTargetKeys(Map<DatabaseField, DatabaseField> sourceToTargetKeyFields) {
        this.sourceForeignKeysToTargetKeys = sourceToTargetKeyFields;
        if ((sourceToTargetKeyFields != null) && (sourceToTargetKeyFields.keySet() != null) && (sourceToTargetKeyFields.keySet().size() > 0)) {
            this.setIsForeignKeyRelationship(true);
        }
    }

    /**
     * INTERNAL:
     * Return whether the mapping has any inverse constraint dependencies,
     * such as foreign keys.
     */
    @Override
    public boolean hasInverseConstraintDependency() {
        return true;
    }

    /**
     * INTERNAL:
     * Initialize the mapping.
     */
    @Override
    public void initialize(AbstractSession session) throws DescriptorException {
        super.initialize(session);

        if ((this.getForeignKeyGroupingElement() == null) && (this.getSourceForeignKeysToTargetKeys().size() > 1)) {
            throw EISException.groupingElementRequired();
        }

        if (this.getForeignKeyGroupingElement() != null) {
            DatabaseField field = this.getDescriptor().buildField(this.getForeignKeyGroupingElement());
            setForeignKeyGroupingElement(field);
        }

        this.initializeSourceForeignKeysToTargetKeys();
        
        if (shouldInitializeSelectionCriteria()) {
            initializeSelectionCriteria(session);
        }

        this.initializeDeleteAllQuery();
    }

    /**
     * INTERNAL:
     * Selection criteria is created with source foreign keys and target keys.
     * This criteria is then used to read target records from the table.
     *
     * CR#3922 - This method is almost the same as buildSelectionCriteria() the difference
     * is that getSelectionCriteria() is called
     */
    protected void initializeSelectionCriteria(AbstractSession session) {
        if (this.getSourceForeignKeysToTargetKeys().isEmpty()) {
            throw DescriptorException.noForeignKeysAreSpecified(this);
        }

        Expression criteria;
        Expression builder = new ExpressionBuilder();
        Iterator keyIterator = getSourceForeignKeysToTargetKeys().keySet().iterator();
        while (keyIterator.hasNext()) {
            DatabaseField foreignKey = (DatabaseField)keyIterator.next();
            DatabaseField targetKey = getSourceForeignKeysToTargetKeys().get(foreignKey);

            Expression expression = builder.getField(targetKey).equal(builder.getParameter(foreignKey));
            criteria = expression.and(getSelectionCriteria());
            setSelectionCriteria(criteria);
        }
    }

    protected void initializeSourceForeignKeysToTargetKeys() throws DescriptorException {
        // Since we require a custom selection query, these keys are optional.
        if (getSourceForeignKeyFields().size() != getTargetForeignKeyFields().size()) {
            throw DescriptorException.sizeMismatchOfForeignKeys(this);
        }

        for (int i = 0; i < getTargetForeignKeyFields().size(); i++) {
            DatabaseField field = getReferenceDescriptor().buildField(getTargetForeignKeyFields().get(i));
            getTargetForeignKeyFields().set(i, field);
        }

        for (int i = 0; i < getSourceForeignKeyFields().size(); i++) {
            DatabaseField field = getDescriptor().buildField(getSourceForeignKeyFields().get(i));
            getSourceForeignKeyFields().set(i, field);
            getSourceForeignKeysToTargetKeys().put(field, getTargetForeignKeyFields().get(i));
        }
    }

    /**
     * Initialize the delete all query.
     * This query is used to delete the collection of objects from the
     * database.
     */
    protected void initializeDeleteAllQuery() {
        ((DeleteAllQuery)this.getDeleteAllQuery()).setReferenceClass(this.getReferenceClass());
        if (!this.hasCustomDeleteAllQuery()) {
            // the selection criteria are re-used by the delete all query
            this.getDeleteAllQuery().setSelectionCriteria(this.getSelectionCriteria());
        }
    }
    
    /**
     * Fix field names for XML data descriptors.
     * Since fields are fixed to use text() by default in descriptor, ensure the correct non text field is used here.
     */
    @Override
    public void preInitialize(AbstractSession session) {
        super.preInitialize(session);
        if (((EISDescriptor)this.descriptor).isXMLFormat()) {
            if ((this.foreignKeyGroupingElement != null) && !(this.foreignKeyGroupingElement instanceof XMLField)) {
                XMLField newField = new XMLField(this.foreignKeyGroupingElement.getName());
                this.foreignKeyGroupingElement = newField;
            }
        }
    }

    /**
     * Return whether any process leading to object modification
     * should also affect its parts.
     * Used by write, insert, update, and delete.
     */
    @Override
    protected boolean shouldObjectModifyCascadeToParts(ObjectLevelModifyQuery query) {
        if (isForeignKeyRelationship()) {
            return super.shouldObjectModifyCascadeToParts(query);
        } else {
            if (this.isReadOnly()) {
                return false;
            }

            if (this.isPrivateOwned()) {
                return true;
            }

            return query.shouldCascadeAllParts();
        }
    }

    /**
     * INTERNAL:
     * Used to verify whether the specified object is deleted or not.
     */
    @Override
    public boolean verifyDelete(Object object, AbstractSession session) throws DatabaseException {
        if (this.isPrivateOwned()) {
            Object objects = this.getRealCollectionAttributeValueFromObject(object, session);

            ContainerPolicy containerPolicy = getContainerPolicy();
            for (Object iter = containerPolicy.iteratorFor(objects); containerPolicy.hasNext(iter);) {
                if (!session.verifyDelete(containerPolicy.next(iter, session))) {
                    return false;
                }
            }
        }
        return true;

    }

    /**
     * INTERNAL:
     * Insert the reference objects.
     */
    @Override
    public void postInsert(WriteObjectQuery query) throws DatabaseException, OptimisticLockException {
        if (isForeignKeyRelationship()) {
            return;
        }

        if (!this.shouldObjectModifyCascadeToParts(query)) {
            return;
        }

        // only cascade dependents in UOW
        if (query.shouldCascadeOnlyDependentParts()) {
            return;
        }

        Object objects = this.getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());

        // insert each object one by one
        ContainerPolicy cp = this.getContainerPolicy();
        for (Object iter = cp.iteratorFor(objects); cp.hasNext(iter);) {
            Object object = cp.next(iter, query.getSession());
            if (this.isPrivateOwned()) {
                // no need to set changeSet as insert is a straight copy
                InsertObjectQuery insertQuery = new InsertObjectQuery();
                insertQuery.setIsExecutionClone(true);
                insertQuery.setObject(object);
                insertQuery.setCascadePolicy(query.getCascadePolicy());
                query.getSession().executeQuery(insertQuery);
            } else {
                // This will happen in a or cascaded query.
                // This is done only for persistence by reachability and is not required if the targets are in the queue anyway
                // Avoid cycles by checking commit manager, this is allowed because there is no dependency.
                if (!query.getSession().getCommitManager().isCommitInPreModify(object)) {
                    WriteObjectQuery writeQuery = new WriteObjectQuery();
                    writeQuery.setIsExecutionClone(true);
                    writeQuery.setObject(object);
                    writeQuery.setCascadePolicy(query.getCascadePolicy());
                    query.getSession().executeQuery(writeQuery);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Update the reference objects.
     */
    @Override
    public void postUpdate(WriteObjectQuery query) throws DatabaseException, OptimisticLockException {
        if (isForeignKeyRelationship()) {
            return;
        }

        if (!shouldObjectModifyCascadeToParts(query)) {
            return;
        }

        // if the target objects are not instantiated, they could not have been changed....
        if (!isAttributeValueInstantiatedOrChanged(query.getObject())) {
            return;
        }

        if (query.getObjectChangeSet() != null) {
            // UnitOfWork
            writeChanges(query.getObjectChangeSet(), query);
        } else {
            // OLD COMMIT    
            compareObjectsAndWrite(query);
        }
    }

    /**
     * INTERNAL:
     * Delete the reference objects.
     */
    @Override
    public void postDelete(DeleteObjectQuery query) throws DatabaseException, OptimisticLockException {
        if (!isForeignKeyRelationship()) {
            return;
        }

        if (!this.shouldObjectModifyCascadeToParts(query)) {
            return;
        }
        Object referenceObjects = this.getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());

        // if we have a custom delete all query, use it;
        // otherwise, delete the reference objects one by one
        if (this.hasCustomDeleteAllQuery()) {
            this.deleteAll(query, referenceObjects);
        } else {
            ContainerPolicy cp = this.getContainerPolicy();
            for (Object iter = cp.iteratorFor(referenceObjects); cp.hasNext(iter);) {
                DeleteObjectQuery deleteQuery = new DeleteObjectQuery();
                deleteQuery.setIsExecutionClone(true);
                deleteQuery.setObject(cp.next(iter, query.getSession()));
                deleteQuery.setCascadePolicy(query.getCascadePolicy());
                query.getSession().executeQuery(deleteQuery);
            }
            if (!query.getSession().isUnitOfWork()) {
                // This deletes any objects on the database, as the collection in memory may have been changed.
                // This is not required for unit of work, as the update would have already deleted these objects,
                // and the backup copy will include the same objects, causing double deletes.
                this.deleteReferenceObjectsLeftOnDatabase(query);
            }
        }
    }

    /**
     * INTERNAL:
     * Delete the reference objects.
     */
    @Override
    public void preDelete(DeleteObjectQuery query) throws DatabaseException, OptimisticLockException {
        if (isForeignKeyRelationship()) {
            return;
        }

        if (!this.shouldObjectModifyCascadeToParts(query)) {
            return;
        }

        Object objects = this.getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());
        ContainerPolicy cp = this.getContainerPolicy();

        // if privately-owned parts have their privately-owned sub-parts, delete them one by one;
        // else delete everything in one shot
        if (this.mustDeleteReferenceObjectsOneByOne()) {
            for (Object iter = cp.iteratorFor(objects); cp.hasNext(iter);) {
                DeleteObjectQuery deleteQuery = new DeleteObjectQuery();
                deleteQuery.setIsExecutionClone(true);
                deleteQuery.setObject(cp.next(iter, query.getSession()));
                deleteQuery.setCascadePolicy(query.getCascadePolicy());
                query.getSession().executeQuery(deleteQuery);
            }
            if (!query.getSession().isUnitOfWork()) {
                // This deletes any objects on the database, as the collection in memory may have been changed.
                // This is not required for unit of work, as the update would have already deleted these objects,
                // and the backup copy will include the same objects causing double deletes.
                this.deleteReferenceObjectsLeftOnDatabase(query);
            }
        } else {
            this.deleteAll(query);
        }
    }

    /**
    * INTERNAL:
    * Insert privately owned parts
    */
    @Override
    public void preInsert(WriteObjectQuery query) throws DatabaseException, OptimisticLockException {
        if (!this.isForeignKeyRelationship()) {
            return;
        }

        if (!this.shouldObjectModifyCascadeToParts(query)) {
            return;
        }

        // only cascade dependents in UOW
        if (query.shouldCascadeOnlyDependentParts()) {
            return;
        }

        Object objects = this.getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());

        // insert each object one by one
        ContainerPolicy cp = this.getContainerPolicy();
        for (Object iter = cp.iteratorFor(objects); cp.hasNext(iter);) {
            Object object = cp.next(iter, query.getSession());
            if (this.isPrivateOwned()) {
                // no need to set changeset here as insert is just a copy of the object anyway
                InsertObjectQuery insertQuery = new InsertObjectQuery();
                insertQuery.setIsExecutionClone(true);
                insertQuery.setObject(object);
                insertQuery.setCascadePolicy(query.getCascadePolicy());
                query.getSession().executeQuery(insertQuery);
            } else {
                // This will happen in a unit of work or cascaded query.
                // This is done only for persistence by reachability and is not required if the targets are in the queue anyway
                // Avoid cycles by checking commit manager, this is allowed because there is no dependency.
                if (!query.getSession().getCommitManager().isCommitInPreModify(object)) {
                    WriteObjectQuery writeQuery = new WriteObjectQuery();
                    writeQuery.setIsExecutionClone(true);
                    if (query.getSession().isUnitOfWork()) {
                        UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet)((UnitOfWorkImpl)query.getSession()).getUnitOfWorkChangeSet();
                        if (uowChangeSet != null) {
                            writeQuery.setObjectChangeSet((ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(object));
                        }
                    }
                    writeQuery.setObject(object);
                    writeQuery.setCascadePolicy(query.getCascadePolicy());
                    query.getSession().executeQuery(writeQuery);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Update the privately owned parts.
     */
    @Override
    public void preUpdate(WriteObjectQuery query) throws DatabaseException, OptimisticLockException {
        if (!isForeignKeyRelationship()) {
            return;
        }

        if (!shouldObjectModifyCascadeToParts(query)) {
            return;
        }

        // if the target objects are not instantiated, they could not have been changed....
        if (!isAttributeValueInstantiatedOrChanged(query.getObject())) {
            return;
        }

        if (query.getObjectChangeSet() != null) {
            // UnitOfWork
            writeChanges(query.getObjectChangeSet(), query);
        } else {
            // OLD COMMIT    
            compareObjectsAndWrite(query);
        }
    }

    /**
     * INTERNAL:
     * Build and return a new element based on the change set.
     */
    public Object buildAddedElementFromChangeSet(Object changeSet, MergeManager mergeManager, AbstractSession targetSession) {
        ObjectChangeSet objectChangeSet = (ObjectChangeSet)changeSet;

        if (this.shouldMergeCascadeParts(mergeManager)) {
            Object targetElement = null;
            if (mergeManager.shouldMergeChangesIntoDistributedCache()) {
                targetElement = objectChangeSet.getTargetVersionOfSourceObject(mergeManager, mergeManager.getSession(), true);
            } else {
                targetElement = objectChangeSet.getUnitOfWorkClone();
            }
            mergeManager.mergeChanges(targetElement, objectChangeSet, targetSession);
        }

        return this.buildElementFromChangeSet(changeSet, mergeManager, targetSession);
    }

    /**
     * INTERNAL:
     * Build and return a change set for the specified element.
     */
    public Object buildChangeSet(Object element, ObjectChangeSet owner, AbstractSession session) {
        ObjectBuilder objectBuilder = session.getDescriptor(element).getObjectBuilder();
        return objectBuilder.createObjectChangeSet(element, (UnitOfWorkChangeSet)owner.getUOWChangeSet(), session);
    }

    /**
     * Build and return a new element based on the change set.
     */
    protected Object buildElementFromChangeSet(Object changeSet, MergeManager mergeManager, AbstractSession targetSession) {
        return ((ObjectChangeSet)changeSet).getTargetVersionOfSourceObject(mergeManager, targetSession);
    }

    /**
     * INTERNAL:
     * Build and return a new element based on the specified element.
     */
    public Object buildElementFromElement(Object element, MergeManager mergeManager, AbstractSession targetSession) {
        if (this.shouldMergeCascadeParts(mergeManager)) {
            ObjectChangeSet objectChangeSet = null;
            if (mergeManager.getSession().isUnitOfWork()) {
                UnitOfWorkChangeSet uowChangeSet = (UnitOfWorkChangeSet)((UnitOfWorkImpl)mergeManager.getSession()).getUnitOfWorkChangeSet();
                if (uowChangeSet != null) {
                    objectChangeSet = (ObjectChangeSet)uowChangeSet.getObjectChangeSetForClone(element);
                }
            }
            Object mergeElement = mergeManager.getObjectToMerge(element, referenceDescriptor, targetSession);
            mergeManager.mergeChanges(mergeElement, objectChangeSet, targetSession);
        }

        return mergeManager.getTargetVersionOfSourceObject(element, referenceDescriptor, targetSession);

    }

    /**
     * INTERNAL:
     * In case Query By Example is used, this method builds and returns an expression that
     * corresponds to a single attribute and it's value.
     */
    public Expression buildExpression(Object queryObject, QueryByExamplePolicy policy, Expression expressionBuilder, Map processedObjects, AbstractSession session) {
        if (policy.shouldValidateExample()){
            throw QueryException.unsupportedMappingQueryByExample(queryObject.getClass().getName(), this);
        }
        return null;
    }

    /**
     * INTERNAL:
     * Build and return a new element based on the change set.
     */
    public Object buildRemovedElementFromChangeSet(Object changeSet, MergeManager mergeManager, AbstractSession targetSession) {
        ObjectChangeSet objectChangeSet = (ObjectChangeSet)changeSet;

        if (!mergeManager.shouldMergeChangesIntoDistributedCache()) {
            mergeManager.registerRemovedNewObjectIfRequired(objectChangeSet.getUnitOfWorkClone());
        }

        return this.buildElementFromChangeSet(changeSet, mergeManager, targetSession);
    }

    /**
     * INTERNAL:
     * Clone the appropriate attributes.
     */
    @Override
    public Object clone() {
        EISOneToManyMapping clone = (EISOneToManyMapping)super.clone();
        clone.setSourceForeignKeysToTargetKeys((Map)((HashMap)getSourceForeignKeysToTargetKeys()).clone());
        return clone;
    }

    /**
     * Return all the fields mapped by the mapping.
     */
    @Override
    protected Vector collectFields() {
        if (isForeignKeyRelationship()) {
            if (this.getForeignKeyGroupingElement() != null) {
                Vector fields = new Vector(1);
                fields.addElement(this.getForeignKeyGroupingElement());
                return fields;
            } else {
                return NO_FIELDS;
            }
        } else {
            return NO_FIELDS;
        }
    }

    /**
     * INTERNAL:
     * Compare the non-null elements and return true if they are alike.
     */
    public boolean compareElements(Object element1, Object element2, AbstractSession session) {
        if (!isForeignKeyRelationship()) {
            return false;
        }

        Object primaryKey1 = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(element1, session);
        Object primaryKey2 = getReferenceDescriptor().getObjectBuilder().extractPrimaryKeyFromObject(element2, session);

        if (!primaryKey1.equals(primaryKey2)) {
            return false;
        }

        if (this.isPrivateOwned()) {
            return session.compareObjects(element1, element2);
        } else {
            return true;
        }
    }

    /**
     * INTERNAL:
     * Return whether the element's user-defined Map key has changed
     * since it was cloned from the original version.
     * Object elements can change their keys without detection.
     * Get the original object and compare keys.
     */
    public boolean mapKeyHasChanged(Object element, AbstractSession session) {
        //CR 4172 compare keys will now get backup if required
        return !this.getContainerPolicy().compareKeys(element, session);
    }

    /**
     * INTERNAL:
     * Compare the non-null elements and return true if they are alike.
     * Here we use object identity.
     */
    public boolean compareElementsForChange(Object element1, Object element2, AbstractSession session) {
        return element1 == element2;
    }

    /**
     * INTERNAL:
     * Compare the changes between two collections. Element comparisons are
     * made using identity and, when appropriate, the value of the element's key
     * for the Map container.
     */
    @Override
    public ChangeRecord compareForChange(Object clone, Object backup, ObjectChangeSet owner, AbstractSession session) {
        if (isForeignKeyRelationship()) {
            if ((this.getAttributeValueFromObject(clone) != null) && (!this.isAttributeValueInstantiatedOrChanged(clone))) {
                return null;// never instantiated - no changes to report
            }
            return (new EISOneToManyMappingHelper(this)).compareForChange(clone, backup, owner, session);
        } else {
            return super.compareForChange(clone, backup, owner, session);
        }
    }

    /**
     * INTERNAL:
     * Compare the attributes belonging to this mapping for the objects.
     */
    @Override
    public boolean compareObjects(Object object1, Object object2, AbstractSession session) {
        if (isForeignKeyRelationship()) {
            return (new EISOneToManyMappingHelper(this)).compareObjects(object1, object2, session);
        }
        return super.compareObjects(object1, object2, session);
    }

    /**
     * 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) {
        (new EISOneToManyMappingHelper(this)).simpleAddToCollectionChangeRecord(referenceKey, changeSetToAdd, changeSet, session);
    }

    /**
     * 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) {
        (new EISOneToManyMappingHelper(this)).simpleRemoveFromCollectionChangeRecord(referenceKey, changeSetToRemove, changeSet, session);
    }

    /**
     * Delete all the reference objects.
     */
    protected void deleteAll(DeleteObjectQuery query, Object referenceObjects) throws DatabaseException {
        ((DeleteAllQuery)this.getDeleteAllQuery()).executeDeleteAll(query.getSession().getSessionForClass(this.getReferenceClass()), query.getTranslationRow(), this.getContainerPolicy().vectorFor(referenceObjects, query.getSession()));
    }

    /**
     * Delete all the reference objects.
     */
    protected void deleteAll(DeleteObjectQuery query) throws DatabaseException {
        Object referenceObjects = this.getRealCollectionAttributeValueFromObject(query.getObject(), query.getSession());
        deleteAll(query, referenceObjects);
    }

    /**
     * This method will make sure that all the records privately owned by this mapping are
     * actually removed. If such records are found then those are all read and removed one
     * by one along with their privately owned parts.
     */
    protected void deleteReferenceObjectsLeftOnDatabase(DeleteObjectQuery query) throws DatabaseException, OptimisticLockException {
        Object objects = this.readPrivateOwnedForObject(query);

        // delete all these objects one by one
        ContainerPolicy cp = this.getContainerPolicy();
        for (Object iter = cp.iteratorFor(objects); cp.hasNext(iter);) {
            query.getSession().deleteObject(cp.next(iter, query.getSession()));
        }
    }

    /**
     * Build and return a database row that contains a foreign key for the specified reference 
     * object.  This will be stored in the nested row(s).
     */
    protected AbstractRecord extractKeyRowFromReferenceObject(Object object, AbstractSession session, AbstractRecord parentRecord) {
        int size = this.sourceForeignKeyFields.size();
        AbstractRecord result;
        if (((EISDescriptor) this.getDescriptor()).isXMLFormat()) {
            Element newNode = XPathEngine.getInstance().createUnownedElement(((XMLRecord)parentRecord).getDOM(), (XMLField)getForeignKeyGroupingElement());
            result = new DOMRecord(newNode);
            ((DOMRecord)result).setSession(session);
        } else {
            result = this.descriptor.getObjectBuilder().createRecord(size, session);
        }
        for (int index = 0; index < size; index++) {
            DatabaseField fkField = this.sourceForeignKeyFields.get(index);
            if (object == null) {
                result.add(fkField, null);
            } else {
                DatabaseField pkField = this.sourceForeignKeysToTargetKeys.get(fkField);
                Object value = this.referenceDescriptor.getObjectBuilder().extractValueFromObjectForField(object, pkField, session);
                result.add(fkField, value);
            }
        }
        return result;
    }

    /**
     * INTERNAL:
     * Return the value of the reference attribute or a value holder.
     * Check whether the mapping's attribute should be optimized through batch and joining.
     */
    @Override
    public Object valueFromRow(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, CacheKey cacheKey, AbstractSession executionSession, boolean isTargetProtected, Boolean[] wasCacheUsed) throws DatabaseException {
        if (this.descriptor.getCachePolicy().isProtectedIsolation()) {
            if (this.isCacheable && isTargetProtected && cacheKey != null) {
                //cachekey will be null when isolating to uow
                //used cached collection
                Object cached = cacheKey.getObject();
                if (cached != null) {
                    if (wasCacheUsed != null){
                        wasCacheUsed[0] = Boolean.TRUE;
                    }
                    //this will just clone the indirection.
                    //the indirection object is responsible for cloning the value.
                    return getAttributeValueFromObject(cached);
                }
            } else if (!this.isCacheable && !isTargetProtected && cacheKey != null) {
                return this.indirectionPolicy.buildIndirectObject(new ValueHolder(null));
            }
        }
        if (((EISDescriptor) this.getDescriptor()).isXMLFormat()) {
            ((XMLRecord) row).setSession(executionSession);
        }
        
        ReadQuery targetQuery = getSelectionQuery();
        if (!this.isForeignKeyRelationship) {
            // if the source query is cascading then the target query must use the same settings
            if (targetQuery.isObjectLevelReadQuery() && (sourceQuery.shouldCascadeAllParts() || (sourceQuery.shouldCascadePrivateParts() && isPrivateOwned()) || (sourceQuery.shouldCascadeByMapping() && this.cascadeRefresh))) {
                targetQuery = (ObjectLevelReadQuery)targetQuery.clone();
                ((ObjectLevelReadQuery)targetQuery).setShouldRefreshIdentityMapResult(sourceQuery.shouldRefreshIdentityMapResult());
                targetQuery.setCascadePolicy(sourceQuery.getCascadePolicy());
                //CR #4365
                targetQuery.setQueryId(sourceQuery.getQueryId());
                // For queries that have turned caching off, such as aggregate collection, leave it off.
                if (targetQuery.shouldMaintainCache()) {
                    targetQuery.setShouldMaintainCache(sourceQuery.shouldMaintainCache());
                }
            }

            return getIndirectionPolicy().valueFromQuery(targetQuery, row, sourceQuery.getSession());
        } else {
            if (getIndirectionPolicy().usesIndirection()) {
                EISOneToManyQueryBasedValueHolder valueholder = new EISOneToManyQueryBasedValueHolder(this, targetQuery, row, sourceQuery.getSession());
                return getIndirectionPolicy().buildIndirectObject(valueholder);
            } else {
                Vector subRows = getForeignKeyRows(row, executionSession);

                if (subRows == null) {
                    return null;
                }

                ContainerPolicy cp = this.getContainerPolicy();
                Object results = cp.containerInstance(subRows.size());

                for (int i = 0; i < subRows.size(); i++) {
                    XMLRecord subRow = (XMLRecord)subRows.elementAt(i);
                    subRow.setSession(executionSession);
                    Object object = getIndirectionPolicy().valueFromQuery(targetQuery, subRow, sourceQuery.getSession());
                    if (object instanceof Collection) {
                        java.util.Iterator iter = ((Collection)object).iterator();
                        while (iter.hasNext()) {
                            cp.addInto(iter.next(), results, executionSession);
                        }
                    } else if (object instanceof java.util.Map) {
                        java.util.Iterator iter = ((java.util.Map)object).values().iterator();
                        while (iter.hasNext()) {
                            cp.addInto(iter.next(), results, executionSession);
                        }
                    } else {
                        cp.addInto(object, results, executionSession);
                    }
                }
                if (cp.sizeFor(results) == 0) {
                    return null;
                }
                return results;
            }
        }
    }

    /**
     * INTERNAL:
     */
    public Vector getForeignKeyRows(AbstractRecord row, AbstractSession session) {
        Vector subRows = new Vector();
        if (getForeignKeyGroupingElement() == null) {
            if (this.getSourceForeignKeyFields().size() > 0) {
                Object values = row.getValues(this.getSourceForeignKeyFields().get(0));

                if (values != null) {
                    if (values instanceof Vector) {
                        int valuesSize = ((Vector)values).size();
                        for (int j = 0; j < valuesSize; j++) {
                            AbstractRecord newRecord = this.descriptor.getObjectBuilder().createRecord(session);
                            newRecord.put(this.getSourceForeignKeyFields().get(0), ((Vector)values).get(j));
                            subRows.add(newRecord);
                        }
                    } else {
                        AbstractRecord newRecord = this.descriptor.getObjectBuilder().createRecord(session);
                        newRecord.put(getSourceForeignKeyFields().get(0), values);
                        subRows.add(newRecord);
                    }
                }
            }
        } else {
            subRows = (Vector)row.getValues(getForeignKeyGroupingElement());
        }
        return subRows;
    }

    /**
     * INTERNAL:
     * Get the appropriate attribute value from the object
     * and put it in the appropriate field of the database row.
     * Loop through the reference objects and extract the
     * primary keys and put them in the vector of "nested" rows.
     */
    @Override
    public void writeFromObjectIntoRow(Object object, AbstractRecord row, AbstractSession session, WriteType writeType) {
        if (!isForeignKeyRelationship) {
            return;
        }

        if (((getSourceForeignKeysToTargetKeys()) == null) || (getSourceForeignKeysToTargetKeys().size() == 0)) {
            return;
        }

        if (this.isReadOnly()) {
            return;
        }

        AbstractRecord referenceRow = this.getIndirectionPolicy().extractReferenceRow(this.getAttributeValueFromObject(object));
        if (referenceRow != null) {
            // the reference objects have not been instantiated - use the value from the original row				
            if (getForeignKeyGroupingElement() != null) {
                row.put(this.getForeignKeyGroupingElement(), referenceRow.getValues(this.getForeignKeyGroupingElement()));
            } else if (getSourceForeignKeyFields().size() > 0) {
                DatabaseField foreignKeyField = getSourceForeignKeyFields().get(0);
                row.put(foreignKeyField, referenceRow.getValues(foreignKeyField));
            }
            return;
        }

        ContainerPolicy cp = this.getContainerPolicy();

        // extract the keys from the objects
        Object attributeValue = this.getRealCollectionAttributeValueFromObject(object, session);
        Vector nestedRows = new Vector(cp.sizeFor(attributeValue));

        if (getForeignKeyGroupingElement() != null) {
            for (Object iter = cp.iteratorFor(attributeValue); cp.hasNext(iter);) {
                AbstractRecord nestedRow = extractKeyRowFromReferenceObject(cp.next(iter, session), session, row);
                nestedRows.add(nestedRow);
            }
            row.add(this.getForeignKeyGroupingElement(), nestedRows);
        } else {
            DatabaseField singleField = getSourceForeignKeyFields().get(0);
            DatabaseField pkField = getSourceForeignKeysToTargetKeys().get(singleField);
            List foreignKeys = new ArrayList(cp.sizeFor(attributeValue));
            for (Object iter = cp.iteratorFor(attributeValue); cp.hasNext(iter);) {
                Object singleValue = getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(cp.next(iter, session), pkField, session);
                foreignKeys.add(singleValue);
            }
            row.add(singleField, foreignKeys);
        }
    }

    /**
     * INTERNAL:
     * This row is built for shallow insert which happens in case of bidirectional inserts.
     * The foreign keys must be set to null to avoid constraints.
     */
    @Override
    public void writeFromObjectIntoRowForShallowInsert(Object object, AbstractRecord row, AbstractSession session) {
        if (isForeignKeyRelationship() && !isReadOnly()) {
            if (getForeignKeyGroupingElement() != null) {
                row.put(getForeignKeyGroupingElement(), null);
            } else if (this.getSourceForeignKeyFields().size() > 0) {
                row.put(getSourceForeignKeyFields().get(0), null);
            }
        } else {
            super.writeFromObjectIntoRowForShallowInsert(object, row, session);
        }
    }

    /**
     * INTERNAL:
     * This row is built for update after shallow insert which happens in case of bidirectional inserts.
     * It contains the foreign keys with non null values that were set to null for shallow insert.
     * If mapping overrides writeFromObjectIntoRowForShallowInsert method it must override this one, too.
     */
    public void writeFromObjectIntoRowForUpdateAfterShallowInsert(Object object, AbstractRecord row, AbstractSession session, DatabaseTable table) {
        if (isReadOnly() || !isForeignKeyRelationship()) {
            return;
        }
        if (getForeignKeyGroupingElement() != null) {
            if (!getForeignKeyGroupingElement().getTable().equals(table)) {
                return;
            }
        } else if (this.getSourceForeignKeyFields().size() > 0) {
            if (!getSourceForeignKeyFields().get(0).getTable().equals(table)) {
                return;
            }
        }
        writeFromObjectIntoRow(object, row, session, WriteType.UPDATE);
    }
    
    /**
     * INTERNAL:
     * This row is built for shallow insert which happens in case of bidirectional inserts.
     * The foreign keys must be set to null to avoid constraints.
     */
    @Override
    public void writeFromObjectIntoRowForShallowInsertWithChangeRecord(ChangeRecord changeRecord, AbstractRecord row, AbstractSession session) {
        if (isForeignKeyRelationship() && !isReadOnly()) {
            if (getForeignKeyGroupingElement() != null) {
                row.put(getForeignKeyGroupingElement(), null);
            } else if (this.getSourceForeignKeyFields().size() > 0) {
                row.put(getSourceForeignKeyFields().get(0), null);
            }
        } else {
            super.writeFromObjectIntoRowForShallowInsertWithChangeRecord(changeRecord, row, session);
        }
    }

    /**
     * INTERNAL:
     * If any of the references objects has changed, write out
     * all the keys.
     */
    @Override
    public void writeFromObjectIntoRowForUpdate(WriteObjectQuery writeQuery, AbstractRecord row) throws DescriptorException {
        if (!this.isAttributeValueInstantiatedOrChanged(writeQuery.getObject())) {
            return;
        }

        AbstractSession session = writeQuery.getSession();

        if (session.isUnitOfWork()) {
            // PRS2074 fix for "traditional" Indirection
            Object collection1 = this.getRealCollectionAttributeValueFromObject(writeQuery.getObject(), session);
            Object collection2 = this.getRealCollectionAttributeValueFromObject(writeQuery.getBackupClone(), session);
            if (this.compareObjectsWithoutPrivateOwned(collection1, collection2, session)) {
                return;// nothing has changed - don't put anything in the row
            }
        }
        this.writeFromObjectIntoRow(writeQuery.getObject(), row, session, WriteType.UPDATE);

    }

    /**
     * INTERNAL:
     * Get the appropriate attribute value from the object
     * and put it in the appropriate field of the database row.
     * Loop through the reference objects and extract the
     * primary keys and put them in the vector of "nested" rows.
     */
    @Override
    public void writeFromObjectIntoRowWithChangeRecord(ChangeRecord changeRecord, AbstractRecord row, AbstractSession session, WriteType writeType) {
        if (isForeignKeyRelationship()) {
            Object object = ((ObjectChangeSet)changeRecord.getOwner()).getUnitOfWorkClone();
            this.writeFromObjectIntoRow(object, row, session, writeType);
        } else {
            super.writeFromObjectIntoRowWithChangeRecord(changeRecord, row, session, writeType);
        }
    }

    /**
     * INTERNAL:
     * Write fields needed for insert into the template for with null values.
     */
    @Override
    public void writeInsertFieldsIntoRow(AbstractRecord row, AbstractSession session) {
        if (isForeignKeyRelationship() && !isReadOnly()) {
            if (getForeignKeyGroupingElement() != null) {
                row.put(getForeignKeyGroupingElement(), null);
            } else if (this.getSourceForeignKeyFields().size() > 0) {
                row.put(getSourceForeignKeyFields().get(0), null);
            }
        } else {
            super.writeInsertFieldsIntoRow(row, session);
        }
    }

    /**
     * INTERNAL:
     * This method is not supported in an EIS environment.
     */
    @Override
    public void setSelectionSQLString(String sqlString) {
        throw DescriptorException.invalidMappingOperation(this, "setSelectionSQLString");
    }

    /**
     * INTERNAL:
     * This method is not supported in an EIS environment.
     */
    @Override
    public void setDeleteAllSQLString(String sqlString) {
        throw DescriptorException.invalidMappingOperation(this, "setDeleteAllSQLString");
    }
}
