/*
 * 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
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.internal.oxm.XPathEngine;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.ChangeRecord;
import org.eclipse.persistence.internal.sessions.MergeManager;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkChangeSet;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.mappings.CollectionMapping;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.record.DOMRecord;
import org.eclipse.persistence.oxm.record.XMLRecord;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.DataModifyQuery;
import org.eclipse.persistence.queries.DeleteAllQuery;
import org.eclipse.persistence.queries.DeleteObjectQuery;
import org.eclipse.persistence.queries.InsertObjectQuery;
import org.eclipse.persistence.queries.ModifyQuery;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ObjectLevelModifyQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.QueryByExamplePolicy;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.queries.WriteObjectQuery;
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.
 *
 * <table border="1">
 * <caption>Record formats</caption>
 * <tr>
 * <th id="c1">Record Type</th>
 * <th id="c2">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));
    }

    @Override
    public boolean hasCustomDeleteAllQuery() {
        return hasCustomDeleteAllQuery;
    }

    @Override
    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.
     */
    @Override
    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<DatabaseField> 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.
     */
    @Override
    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);
    }

    /**
     * INTERNAL:
     * If the mapping has a foreign key, it is order, so must use a different merge.
     */
    @Override
    public void mergeChangesIntoObject(Object target, ChangeRecord chgRecord, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        if (isForeignKeyRelationship()) {
            (new EISOneToManyMappingHelper(this)).mergeChangesIntoObject(target, chgRecord, source, mergeManager, targetSession);
            return;
        }
        super.mergeChangesIntoObject(target, chgRecord, source, mergeManager, targetSession);
    }

    /**
     * INTERNAL:
     * If the mapping has a foreign key, it is order, so must use a different merge.
     */
    @Override
    public void mergeIntoObject(Object target, boolean isTargetUnInitialized, Object source, MergeManager mergeManager, AbstractSession targetSession) {
        if (isForeignKeyRelationship()) {
            (new EISOneToManyMappingHelper(this)).mergeIntoObject(target, isTargetUnInitialized, source, mergeManager, targetSession);
            return;
        }
        super.mergeIntoObject(target, isTargetUnInitialized, source, mergeManager, targetSession);
    }

    /**
     * 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.
     */
    @Override
    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");
    }
}
