/*
 * 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().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 = 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
    @SuppressWarnings({"unchecked"})
    public Object clone() {
        EISOneToManyMapping clone = (EISOneToManyMapping)super.clone();
        clone.setSourceForeignKeysToTargetKeys((Map<DatabaseField, DatabaseField>)((HashMap<DatabaseField, DatabaseField>)getSourceForeignKeysToTargetKeys()).clone());
        return clone;
    }

    /**
     * Return all the fields mapped by the mapping.
     */
    @Override
    protected Vector<DatabaseField> collectFields() {
        if (isForeignKeyRelationship()) {
            if (this.getForeignKeyGroupingElement() != null) {
                Vector<DatabaseField> 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<AbstractRecord> 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:
     */
    @SuppressWarnings({"unchecked"})
    public Vector getForeignKeyRows(AbstractRecord row, AbstractSession session) {
        Vector<AbstractRecord> 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) {
                        Vector<?> vals = (Vector<?>) values;
                        int valuesSize = vals.size();
                        for (int j = 0; j < valuesSize; j++) {
                            AbstractRecord newRecord = this.descriptor.getObjectBuilder().createRecord(session);
                            newRecord.put(this.getSourceForeignKeyFields().get(0), vals.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<AbstractRecord>)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);

        if (getForeignKeyGroupingElement() != null) {
            Vector<AbstractRecord> nestedRows = new Vector<>(cp.sizeFor(attributeValue));
            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<Object> 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");
    }
}
