/*
 * 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:
//     07/16/2009 Andrei Ilitchev
//       - Bug 282553: JPA 2.0 JoinTable support for OneToOne and ManyToOne
//     14/05/2012-2.4 Guy Pelletier
//       - 376603: Provide for table per tenant support for multitenant applications
package org.eclipse.persistence.mappings;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.TablePerMultitenantPolicy;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.databaseaccess.Platform;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.expressions.FieldExpression;
import org.eclipse.persistence.internal.expressions.ForUpdateClause;
import org.eclipse.persistence.internal.expressions.ForUpdateOfClause;
import org.eclipse.persistence.internal.expressions.SQLDeleteStatement;
import org.eclipse.persistence.internal.expressions.SQLInsertStatement;
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.ForeignReferenceMapping.ExtendPessimisticLockScope;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.DataModifyQuery;
import org.eclipse.persistence.queries.DirectReadQuery;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.sessions.DatabaseRecord;

/**
 * <p><b>Purpose</b>: Contains relation table functionality
 * that was originally defined in ManyToManyMapping
 * and now is shared with OneToOneMapping.
 */
public class RelationTableMechanism  implements Cloneable, java.io.Serializable {
    /** The intermediate relation table. */
    protected DatabaseTable relationTable;

    /** The field in the source table that corresponds to the key in the relation table */
    protected Vector<DatabaseField> sourceKeyFields;

    /**  The field in the target table that corresponds to the key in the relation table */
    protected Vector<DatabaseField> targetKeyFields;

    /** The field in the intermediate table that corresponds to the key in the source table */
    protected Vector<DatabaseField> sourceRelationKeyFields;

    /** The field in the intermediate table that corresponds to the key in the target table */
    protected Vector<DatabaseField> targetRelationKeyFields;

    /** Query used for single row deletion. */
    protected DataModifyQuery deleteQuery;
    protected boolean hasCustomDeleteQuery;

    /** Used for insertion. */
    protected DataModifyQuery insertQuery;
    protected boolean hasCustomInsertQuery;

    protected ReadQuery lockRelationTableQuery;

    public RelationTableMechanism() {
        this.insertQuery = new DataModifyQuery();
        this.deleteQuery = new DataModifyQuery();
        this.sourceRelationKeyFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
        this.targetRelationKeyFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
        this.sourceKeyFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
        this.targetKeyFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
        this.hasCustomDeleteQuery = false;
        this.hasCustomInsertQuery = false;
    }

    /**
     * PUBLIC:
     * Add the fields in the intermediate table that corresponds to the primary
     * key in the source table. This method is used if the keys are composite.
     */
    public void addSourceRelationKeyField(DatabaseField sourceRelationKeyField, DatabaseField sourcePrimaryKeyField) {
        getSourceRelationKeyFields().addElement(sourceRelationKeyField);
        getSourceKeyFields().addElement(sourcePrimaryKeyField);
    }

    /**
     * PUBLIC:
     * Add the fields in the intermediate table that corresponds to the primary
     * key in the source table. This method is used if the keys are composite.
     */
    public void addSourceRelationKeyFieldName(String sourceRelationKeyFieldName, String sourcePrimaryKeyFieldName) {
        addSourceRelationKeyField(new DatabaseField(sourceRelationKeyFieldName), new DatabaseField(sourcePrimaryKeyFieldName));
    }

    /**
     * PUBLIC:
     * Add the fields in the intermediate table that corresponds to the primary
     * key in the target table. This method is used if the keys are composite.
     */
    public void addTargetRelationKeyField(DatabaseField targetRelationKeyField, DatabaseField targetPrimaryKeyField) {
        getTargetRelationKeyFields().addElement(targetRelationKeyField);
        getTargetKeyFields().addElement(targetPrimaryKeyField);
    }

    /**
     * PUBLIC:
     * Add the fields in the intermediate table that corresponds to the primary
     * key in the target table. This method is used if the keys are composite.
     */
    public void addTargetRelationKeyFieldName(String targetRelationKeyFieldName, String targetPrimaryKeyFieldName) {
        addTargetRelationKeyField(new DatabaseField(targetRelationKeyFieldName), new DatabaseField(targetPrimaryKeyFieldName));
    }

    /**
     * INTERNAL:
     * Selection criteria is created to read target records from the table.
     */
    Expression buildSelectionCriteria(ForeignReferenceMapping mapping, Expression criteria) {
        return buildSelectionCriteriaAndAddFieldsToQueryInternal(mapping, criteria, true, false);
    }

    Expression buildSelectionCriteriaAndAddFieldsToQuery(ForeignReferenceMapping mapping, Expression criteria) {
        return buildSelectionCriteriaAndAddFieldsToQueryInternal(mapping, criteria, true, true);
    }

    /**
     * INTERNAL:
     * Build the selection criteria to join the source, relation, and target tables.
     */
    public Expression buildSelectionCriteriaAndAddFieldsToQueryInternal(ForeignReferenceMapping mapping, Expression criteria, boolean shouldAddTargetFields, boolean shouldAddFieldsToQuery) {
        Expression builder = new ExpressionBuilder();
        Expression linkTable = builder.getTable(this.relationTable);

        if (shouldAddTargetFields) {
            Iterator<DatabaseField> targetKeyIterator = getTargetKeyFields().iterator();
            Iterator<DatabaseField> relationKeyIterator = getTargetRelationKeyFields().iterator();
            while (targetKeyIterator.hasNext()) {
                DatabaseField relationKey = relationKeyIterator.next();
                DatabaseField targetKey = targetKeyIterator.next();
                Expression expression = builder.getField(targetKey).equal(linkTable.getField(relationKey));
                if (criteria == null) {
                    criteria = expression;
                } else {
                    criteria = expression.and(criteria);
                }
            }
        }

        Iterator<DatabaseField> relationKeyIterator = getSourceRelationKeyFields().iterator();
        Iterator<DatabaseField> sourceKeyIterator = getSourceKeyFields().iterator();

        while (relationKeyIterator.hasNext()) {
            DatabaseField relationKey = relationKeyIterator.next();
            DatabaseField sourceKey = sourceKeyIterator.next();
            Expression expression = linkTable.getField(relationKey).equal(builder.getParameter(sourceKey));
            if (criteria == null) {
                criteria = expression;
            } else {
                criteria = expression.and(criteria);
            }
        }

        if (shouldAddFieldsToQuery && mapping.isCollectionMapping()) {
            mapping.getContainerPolicy().addAdditionalFieldsToQuery(mapping.getSelectionQuery(), linkTable);
        }

        return criteria;
    }

    /**
     * INTERNAL:
     * This method is used to store the FK fields that can be cached that correspond to noncacheable mappings
     * the FK field values will be used to re-issue the query when cloning the shared cache entity
     */
    protected void collectQueryParameters(Set<DatabaseField> cacheFields){
        for (DatabaseField field : getSourceKeyFields()) {
            cacheFields.add(field);
        }
    }

    /**
     * INTERNAL:
     * The mapping clones itself to create deep copy.
     */
    @Override
    public Object clone() {
        RelationTableMechanism clone;
        try {
            clone = (RelationTableMechanism)super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError();
        }

        clone.setTargetKeyFields(cloneFields(getTargetKeyFields()));
        clone.setSourceKeyFields(cloneFields(getSourceKeyFields()));
        clone.setTargetRelationKeyFields(cloneFields(getTargetRelationKeyFields()));
        clone.setSourceRelationKeyFields(cloneFields(getSourceRelationKeyFields()));

        clone.setInsertQuery((DataModifyQuery) insertQuery.clone());
        clone.setDeleteQuery((DataModifyQuery) deleteQuery.clone());
        if(lockRelationTableQuery != null) {
            clone.lockRelationTableQuery = (DirectReadQuery)lockRelationTableQuery.clone();
        }

        return clone;
    }

    /**
     * INTERNAL:
     * Helper method to clone vector of fields (used in aggregate initialization cloning).
     */
    protected Vector cloneFields(Vector fields) {
        Vector clonedFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance();
        for (Enumeration fieldsEnum = fields.elements(); fieldsEnum.hasMoreElements();) {
            clonedFields.addElement(((DatabaseField)fieldsEnum.nextElement()).clone());
        }

        return clonedFields;
    }

    protected DataModifyQuery getDeleteQuery() {
        return deleteQuery;
    }

    /**
     * INTERNAL:
     * Returns a query that
     */
    ReadQuery getLockRelationTableQueryClone(AbstractSession session, short lockMode) {
        DirectReadQuery lockRelationTableQueryClone = (DirectReadQuery)lockRelationTableQuery.clone();
        SQLSelectStatement statement = new SQLSelectStatement();
        statement.addTable(this.relationTable);
        statement.addField(this.sourceRelationKeyFields.get(0).clone());
        statement.setWhereClause((Expression)lockRelationTableQuery.getSelectionCriteria().clone());
        statement.setLockingClause(new ForUpdateClause(lockMode));
        statement.normalize(session, null);
        lockRelationTableQueryClone.setSQLStatement(statement);
        lockRelationTableQueryClone.setIsExecutionClone(true);
        return lockRelationTableQueryClone;
    }

    /**
     * INTERNAL:
     * Return relation table locking clause.
     */
    public void setRelationTableLockingClause(ObjectLevelReadQuery targetQuery, ObjectBuildingQuery sourceQuery) {
        ForUpdateOfClause lockingClause = new ForUpdateOfClause();
        lockingClause.setLockMode(sourceQuery.getLockMode());
        FieldExpression exp = (FieldExpression)targetQuery.getExpressionBuilder().getTable(this.relationTable).getField(this.sourceRelationKeyFields.get(0));
        lockingClause.addLockedExpression(exp);
        targetQuery.setLockingClause(lockingClause);
        // locking clause is not compatible with DISTINCT
        targetQuery.setShouldOuterJoinSubclasses(true);
    }

    protected DataModifyQuery getInsertQuery() {
        return insertQuery;
    }

    /**
     * INTERNAL:
     * Return the relation table associated with the mapping.
     */
    public DatabaseTable getRelationTable() {
        return relationTable;
    }

    /**
     * PUBLIC:
     * Return the relation table name associated with the mapping.
     */
    public String getRelationTableName() {
        if (relationTable == null) {
            return null;
        }
        return relationTable.getName();
    }

    /**
     * PUBLIC:
     * Return the relation table qualified name associated with the mapping.
     */
    public String getRelationTableQualifiedName() {
        if (relationTable == null) {
            return null;
        }
        return relationTable.getQualifiedName();
    }

    /**
     * PUBLIC:
     * Return the source key field names associated with the mapping.
     * These are in-order with the sourceRelationKeyFieldNames.
     */
    public Vector getSourceKeyFieldNames() {
        Vector fieldNames = new Vector(getSourceKeyFields().size());
        for (Enumeration<DatabaseField> fieldsEnum = getSourceKeyFields().elements();
             fieldsEnum.hasMoreElements();) {
            fieldNames.addElement(((DatabaseField)fieldsEnum.nextElement()).getQualifiedName());
        }

        return fieldNames;
    }

    /**
     * INTERNAL:
     * Return the selection criteria used to IN batch fetching.
     */
    protected Expression buildBatchCriteria(ExpressionBuilder builder, ObjectLevelReadQuery query) {
        Expression linkTable = builder.getTable(this.relationTable);
        Expression criteria = null;
        int size = this.targetRelationKeyFields.size();
        for (int index = 0; index < size; index++) {
            DatabaseField relationKey = this.targetRelationKeyFields.get(index);
            DatabaseField targetKey = this.targetKeyFields.get(index);
            criteria = builder.getField(targetKey).equal(linkTable.getField(relationKey)).and(criteria);
        }
        size = this.sourceRelationKeyFields.size();
        if (size > 1) {
            // Support composite keys using nested IN.
            List<Expression> fields = new ArrayList<>(size);
            for (DatabaseField sourceRelationKeyField : this.sourceRelationKeyFields) {
                fields.add(linkTable.getField(sourceRelationKeyField));
            }
            return criteria.and(query.getSession().getPlatform().buildBatchCriteriaForComplexId(builder, fields));
        } else {
            return criteria.and(query.getSession().getPlatform().buildBatchCriteria(builder, linkTable.getField(this.sourceRelationKeyFields.get(0))));
        }
    }

    /**
     * INTERNAL:
     * Add the addition join fields to the batch query.
     */
    public void postPrepareNestedBatchQuery(ReadQuery batchQuery, ObjectLevelReadQuery query) {
        ReadAllQuery mappingBatchQuery = (ReadAllQuery)batchQuery;
        mappingBatchQuery.setShouldIncludeData(true);
        Expression linkTable = mappingBatchQuery.getExpressionBuilder().getTable(this.relationTable);
        for (DatabaseField relationField : this.sourceRelationKeyFields) {
            mappingBatchQuery.getAdditionalFields().add(linkTable.getField(relationField));
        }
    }

    /**
     * INTERNAL:
     * Extract the foreign key value from the source row.
     */
    protected Object extractBatchKeyFromRow(AbstractRecord row, AbstractSession session) {
        Object[] key;
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
        List<DatabaseField> sourceKeyFields = this.sourceKeyFields;
        int size = sourceKeyFields.size();
        key = new Object[size];
        for (int index = 0; index < size; index++) {
            DatabaseField field = sourceKeyFields.get(index);
            Object value = row.get(field);
            // Must ensure the classification gets a cache hit.
            key[index] = conversionManager.convertObject(value, field.getType());
        }
        return new CacheId(key);
    }

    /**
     * INTERNAL:
     * Extract the source primary key value from the relation row.
     * Used for batch reading, most following same order and fields as in the mapping.
     */
    protected Object extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
        int size = getSourceRelationKeyFields().size();
        Object[] key = new Object[size];
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
        for (int index = 0; index < size; index++) {
            DatabaseField relationField = this.sourceRelationKeyFields.get(index);
            DatabaseField sourceField = this.sourceKeyFields.get(index);
            Object value = row.get(relationField);
            // Must ensure the classification gets a cache hit.
            value = conversionManager.convertObject(value, sourceField.getType());
            key[index] = value;
        }
        return new CacheId(key);
    }

    /**
     * INTERNAL:
     * Return all the source key fields associated with the mapping.
     */
    public Vector<DatabaseField> getSourceKeyFields() {
        return sourceKeyFields;
    }

    /**
     * PUBLIC:
     * Return the source relation key field names associated with the mapping.
     * These are in-order with the sourceKeyFieldNames.
     */
    public Vector getSourceRelationKeyFieldNames() {
        Vector fieldNames = new Vector(getSourceRelationKeyFields().size());
        for (Enumeration<DatabaseField> fieldsEnum = getSourceRelationKeyFields().elements();
             fieldsEnum.hasMoreElements();) {
            fieldNames.addElement(((DatabaseField)fieldsEnum.nextElement()).getQualifiedName());
        }

        return fieldNames;
    }

    /**
     * INTERNAL:
     * Return all the source relation key fields associated with the mapping.
     */
    public Vector<DatabaseField> getSourceRelationKeyFields() {
        return sourceRelationKeyFields;
    }

    /**
     * PUBLIC:
     * Return the target key field names associated with the mapping.
     * These are in-order with the targetRelationKeyFieldNames.
     */
    public Vector getTargetKeyFieldNames() {
        Vector fieldNames = new Vector(getTargetKeyFields().size());
        for (Enumeration<DatabaseField> fieldsEnum = getTargetKeyFields().elements();
             fieldsEnum.hasMoreElements();) {
            fieldNames.addElement(((DatabaseField)fieldsEnum.nextElement()).getQualifiedName());
        }

        return fieldNames;
    }

    /**
     * INTERNAL:
     * Return the relation field for the target field.
     */
    public DatabaseField getRelationFieldForTargetField(DatabaseField targetField) {
        int index = this.targetKeyFields.indexOf(targetField);
        if (index == -1) {
            return null;
        }
        return this.targetRelationKeyFields.get(index);
    }

    /**
     * INTERNAL:
     * Return all the target keys associated with the mapping.
     */
    public Vector<DatabaseField> getTargetKeyFields() {
        return targetKeyFields;
    }

    /**
     * PUBLIC:
     * Return the target relation key field names associated with the mapping.
     * These are in-order with the targetKeyFieldNames.
     */
    public Vector getTargetRelationKeyFieldNames() {
        Vector fieldNames = new Vector(getTargetRelationKeyFields().size());
        for (Enumeration<DatabaseField> fieldsEnum = getTargetRelationKeyFields().elements();
             fieldsEnum.hasMoreElements();) {
            fieldNames.addElement(((DatabaseField)fieldsEnum.nextElement()).getQualifiedName());
        }

        return fieldNames;
    }

    /**
     * INTERNAL:
     * Return all the target relation key fields associated with the mapping.
     */
    public Vector<DatabaseField> getTargetRelationKeyFields() {
        return targetRelationKeyFields;
    }

    protected boolean hasCustomDeleteQuery() {
        return hasCustomDeleteQuery;
    }

    protected boolean hasCustomInsertQuery() {
        return hasCustomInsertQuery;
    }

    /**
     * INTERNAL:
     * Indicates whether the mechanism has relation table.
     */
    public boolean hasRelationTable() {
        return relationTable != null && relationTable.getName().length() > 0;
    }

    /**
     * INTERNAL:
     * Initialize
     */
    public void initialize(AbstractSession session, ForeignReferenceMapping mapping) throws DescriptorException {
        initializeRelationTable(session, mapping);
        initializeSourceRelationKeys(mapping);
        initializeTargetRelationKeys(mapping);

        if (isSingleSourceRelationKeySpecified()) {
            initializeSourceKeysWithDefaults(mapping);
        } else {
            initializeSourceKeys(mapping);
        }

        if (isSingleTargetRelationKeySpecified()) {
            initializeTargetKeysWithDefaults(session, mapping);
        } else {
            initializeTargetKeys(session, mapping);
        }

        if (getRelationTable().getName().indexOf(' ') != -1) {
            //table names contains a space so needs to be quoted.
            String beginQuote = session.getDatasourcePlatform().getStartDelimiter();
            String endQuote = session.getDatasourcePlatform().getEndDelimiter();
            //Ensure this table name hasn't already been quoted.
            if (getRelationTable().getName().indexOf(beginQuote) == -1) {
                getRelationTable().setName(beginQuote + getRelationTable().getName() + endQuote);
            }
        }

        if (mapping.isCollectionMapping()) {
            mapping.getContainerPolicy().initialize(session, getRelationTable());
        }

        initializeInsertQuery(session, mapping);
        initializeDeleteQuery(session, mapping);

        if (mapping.extendPessimisticLockScope != ExtendPessimisticLockScope.NONE) {
            initializeExtendPessipisticLockScope(session, mapping);
        }
    }

    /**
     * INTERNAL:
     * Initialize delete query. This query is used to delete a specific row from the join table in uow,
     * given the objects on both sides of the relation.
     */
    protected void initializeDeleteQuery(AbstractSession session, ForeignReferenceMapping mapping) {
        if (!getDeleteQuery().hasSessionName()) {
            getDeleteQuery().setSessionName(session.getName());
        }
        if (getDeleteQuery().getPartitioningPolicy() == null) {
            getDeleteQuery().setPartitioningPolicy(mapping.getPartitioningPolicy());
        }
        getInsertQuery().setName(mapping.getAttributeName());
        if (hasCustomDeleteQuery()) {
            return;
        }

        // Build where clause expression.
        Expression whereClause = null;
        Expression builder = new ExpressionBuilder();

        for (DatabaseField relationKey : getSourceRelationKeyFields()) {
            Expression expression = builder.getField(relationKey).equal(builder.getParameter(relationKey));
            whereClause = expression.and(whereClause);
        }

        if (mapping.isCollectionMapping()) {
            for (DatabaseField relationKey : getTargetRelationKeyFields()) {
                Expression expression = builder.getField(relationKey).equal(builder.getParameter(relationKey));
                whereClause = expression.and(whereClause);
            }
        }

        SQLDeleteStatement statement = new SQLDeleteStatement();
        statement.setTable(getRelationTable());
        statement.setWhereClause(whereClause);
        getDeleteQuery().setSQLStatement(statement);
    }

    /**
     * INTERNAL:
     * Initialize extendPessimisticLockeScope and lockRelationTableQuery (if required).
     */
    protected void initializeExtendPessipisticLockScope(AbstractSession session, ForeignReferenceMapping mapping) {
        if(mapping.usesIndirection()) {
            if(session.getPlatform().isForUpdateCompatibleWithDistinct() && session.getPlatform().supportsLockingQueriesWithMultipleTables()) {
                mapping.extendPessimisticLockScope = ExtendPessimisticLockScope.SOURCE_QUERY;
            } else {
                mapping.extendPessimisticLockScope = ExtendPessimisticLockScope.DEDICATED_QUERY;
            }
        } else {
            if(session.getPlatform().supportsIndividualTableLocking() && session.getPlatform().supportsLockingQueriesWithMultipleTables()) {
                mapping.extendPessimisticLockScope = ExtendPessimisticLockScope.TARGET_QUERY;
            } else {
                mapping.extendPessimisticLockScope = ExtendPessimisticLockScope.DEDICATED_QUERY;
            }
        }

        if(mapping.extendPessimisticLockScope == ExtendPessimisticLockScope.DEDICATED_QUERY) {
            Expression startCriteria = mapping.getSelectionQuery().getSelectionCriteria();
            if(startCriteria != null) {
                startCriteria = (Expression)startCriteria.clone();
            }
            initializeLockRelationTableQuery(session, mapping, startCriteria);
        }
    }

    /**
     * INTERNAL:
     * Initialize insert query. This query is used to insert the collection of objects into the
     * relation table.
     */
    protected void initializeInsertQuery(AbstractSession session, ForeignReferenceMapping mapping) {
        if (!getInsertQuery().hasSessionName()) {
            getInsertQuery().setSessionName(session.getName());
        }
        if (getInsertQuery().getPartitioningPolicy() == null) {
            getInsertQuery().setPartitioningPolicy(mapping.getPartitioningPolicy());
        }
        getInsertQuery().setName(mapping.getAttributeName());
        if (hasCustomInsertQuery()) {
            return;
        }

        SQLInsertStatement statement = new SQLInsertStatement();
        statement.setTable(getRelationTable());
        AbstractRecord joinRow = new DatabaseRecord();
        for (DatabaseField field : getTargetRelationKeyFields()) {
            joinRow.put(field, null);
        }
        for (DatabaseField field : getSourceRelationKeyFields()) {
            joinRow.put(field, null);
        }
        if (mapping.isCollectionMapping()) {
            CollectionMapping collectionMapping = (CollectionMapping)mapping;
            if (collectionMapping.getListOrderField() != null) {
                joinRow.put(collectionMapping.getListOrderField(), null);
            }
            collectionMapping.getContainerPolicy().addFieldsForMapKey(joinRow);
        }
        statement.setModifyRow(joinRow);
        getInsertQuery().setSQLStatement(statement);
        getInsertQuery().setModifyRow(joinRow);
    }

    /**
     * INTERNAL:
     * Initialize lockRelationTableQuery.
     */
    protected void initializeLockRelationTableQuery(AbstractSession session, ForeignReferenceMapping mapping, Expression startCriteria) {
        lockRelationTableQuery = new DirectReadQuery();
        Expression criteria = buildSelectionCriteriaAndAddFieldsToQueryInternal(mapping, startCriteria, false, false);
        SQLSelectStatement statement = new SQLSelectStatement();
        statement.addTable(this.relationTable);
        statement.addField(this.sourceRelationKeyFields.get(0).clone());
        statement.setWhereClause(criteria);
        statement.normalize(session, null);
        lockRelationTableQuery.setSQLStatement(statement);
        lockRelationTableQuery.setSessionName(session.getName());
    }

    /**
     * INTERNAL:
     * Set the table qualifier on the relation table if required
     */
    protected void initializeRelationTable(AbstractSession session, ForeignReferenceMapping mapping) throws DescriptorException {
        Platform platform = session.getDatasourcePlatform();

        // We need to look up the relation table name from the reference
        // descriptor if we are the non owning side of a bidirectional mapping
        // to a table per tenant descriptor.
        if (mapping.isReadOnly() && mapping.getReferenceDescriptor().hasTablePerMultitenantPolicy()) {
            setRelationTable(((TablePerMultitenantPolicy) mapping.getReferenceDescriptor().getMultitenantPolicy()).getTable(getRelationTable()));
        }

        if (!hasRelationTable()) {
            throw DescriptorException.noRelationTable(mapping);
        }

        if (platform.getTableQualifier().length() > 0) {
            if (getRelationTable().getTableQualifier().length() == 0) {
                getRelationTable().setTableQualifier(platform.getTableQualifier());
            }
        }
    }
    /**
     * INTERNAL:
     * All the source key field names are converted to DatabaseField and stored.
     */
    protected void initializeSourceKeys(ForeignReferenceMapping mapping) {
        for (int index = 0; index < getSourceKeyFields().size(); index++) {
            DatabaseField field = mapping.getDescriptor().buildField(getSourceKeyFields().get(index));
            if (mapping.usesIndirection()) {
                field.setKeepInRow(true);
            }
            getSourceKeyFields().set(index, field);
        }
    }

    /**
     * INTERNAL:
     * If a user does not specify the source key then the primary keys of the source table are used.
     */
    protected void initializeSourceKeysWithDefaults(DatabaseMapping mapping) {
        List<DatabaseField> primaryKeyFields = mapping.getDescriptor().getPrimaryKeyFields();
        for (int index = 0; index < primaryKeyFields.size(); index++) {
            DatabaseField field = primaryKeyFields.get(index);
            if (((ForeignReferenceMapping)mapping).usesIndirection()) {
                field.setKeepInRow(true);
            }
            getSourceKeyFields().addElement(field);
        }
    }

    /**
     * INTERNAL:
     * All the source relation key field names are converted to DatabaseField and stored.
     */
    protected void initializeSourceRelationKeys(ForeignReferenceMapping mapping) throws DescriptorException {
        if (getSourceRelationKeyFields().size() == 0) {
            throw DescriptorException.noSourceRelationKeysSpecified(mapping);
        }

        for (Enumeration<DatabaseField> entry = getSourceRelationKeyFields().elements(); entry.hasMoreElements();) {
            DatabaseField field = (DatabaseField)entry.nextElement();

            // Update the fields table first if the mapping is from a table per tenant entity.
            ClassDescriptor sourceDescriptor = mapping.getDescriptor();
            if (sourceDescriptor.hasTablePerMultitenantPolicy()) {
                field.setTable(((TablePerMultitenantPolicy) sourceDescriptor.getMultitenantPolicy()).getTable(field.getTable()));
            }

            if (field.hasTableName() && (!(field.getTableName().equals(getRelationTable().getName())))) {
                throw DescriptorException.relationKeyFieldNotProperlySpecified(field, mapping);
            }
            field.setTable(getRelationTable());
        }
    }

    /**
     * INTERNAL:
     * All the target key field names are converted to DatabaseField and stored.
     */
    protected void initializeTargetKeys(AbstractSession session, ForeignReferenceMapping mapping) {
        for (int index = 0; index < getTargetKeyFields().size(); index++) {
            DatabaseField field = mapping.getReferenceDescriptor().buildField(getTargetKeyFields().get(index));
            getTargetKeyFields().set(index, field);
        }
    }

    /**
     * INTERNAL:
     * If a user does not specify the target key then the primary keys of the target table are used.
     */
    protected void initializeTargetKeysWithDefaults(AbstractSession session, ForeignReferenceMapping mapping) {
        List<DatabaseField> primaryKeyFields = mapping.getReferenceDescriptor().getPrimaryKeyFields();
        for (int index = 0; index < primaryKeyFields.size(); index++) {
            getTargetKeyFields().addElement(primaryKeyFields.get(index));
        }
    }

    /**
     * INTERNAL:
     * All the target relation key field names are converted to DatabaseField and stored.
     */
    protected void initializeTargetRelationKeys(ForeignReferenceMapping mapping) {
        if (getTargetRelationKeyFields().size() == 0) {
            throw DescriptorException.noTargetRelationKeysSpecified(mapping);
        }

        for (Enumeration<DatabaseField> targetEnum = getTargetRelationKeyFields().elements(); targetEnum.hasMoreElements();) {
            DatabaseField field = (DatabaseField)targetEnum.nextElement();

            // Update the fields table first if the mapping is from a table per tenant entity.
            ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();
            if (referenceDescriptor.hasTablePerMultitenantPolicy()) {
                field.setTable(((TablePerMultitenantPolicy) referenceDescriptor.getMultitenantPolicy()).getTable(field.getTable()));
            }

            if (field.hasTableName() && (!(field.getTableName().equals(getRelationTable().getName())))) {
                throw DescriptorException.relationKeyFieldNotProperlySpecified(field, mapping);
            }
            field.setTable(getRelationTable());
        }
    }

    /**
     * INTERNAL:
     * Checks if a single source key was specified.
     */
    protected boolean isSingleSourceRelationKeySpecified() {
        return getSourceKeyFields().isEmpty();
    }

    /**
     * INTERNAL:
     * Checks if a single target key was specified.
     */
    protected boolean isSingleTargetRelationKeySpecified() {
        return getTargetKeyFields().isEmpty();
    }

    /**
     * INTERNAL:
     * Adds to the passed expression a single relation table field joined to source field.
     * Used to extend pessimistic locking clause in source query.
     */
    public Expression joinRelationTableField(Expression expression, Expression baseExpression) {
        return baseExpression.getField(this.sourceKeyFields.get(0)).equal(baseExpression.getTable(relationTable).getField(this.sourceRelationKeyFields.get(0))).and(expression);
    }

    /**
     * PUBLIC:
     * The default delete query for mapping can be overridden by specifying the new query.
     * This query must delete the row from the M-M join table.
     */
    public void setCustomDeleteQuery(DataModifyQuery query) {
        setDeleteQuery(query);
        setHasCustomDeleteQuery(true);
    }

    /**
     * PUBLIC:
     * The default insert query for mapping can be overridden by specifying the new query.
     * This query must insert the row into the M-M join table.
     */
    public void setCustomInsertQuery(DataModifyQuery query) {
        setInsertQuery(query);
        setHasCustomInsertQuery(true);
    }

    protected void setDeleteQuery(DataModifyQuery deleteQuery) {
        this.deleteQuery = deleteQuery;
    }

    /**
     * PUBLIC:
     * Set the receiver's delete SQL string. This allows the user to override the SQL
     * generated by TOPLink, with there own SQL or procedure call. The arguments are
     * translated from the fields of the source row, through replacing the field names
     * marked by '#' with the values for those fields.
     * This is used to delete a single entry from the M-M join table.
     * Example, 'delete from PROJ_EMP where PROJ_ID = #PROJ_ID AND EMP_ID = #EMP_ID'.
     */
    public void setDeleteSQLString(String sqlString) {
        DataModifyQuery query = new DataModifyQuery();
        query.setSQLString(sqlString);
        setCustomDeleteQuery(query);
    }

    /**
     * PUBLIC:
     * Set the receiver's delete Call. This allows the user to override the SQL
     * generated by TOPLink, with there own SQL or procedure call. The arguments are
     * translated from the fields of the source row.
     * This is used to delete a single entry from the M-M join table.
     * Example, 'new SQLCall("delete from PROJ_EMP where PROJ_ID = #PROJ_ID AND EMP_ID = #EMP_ID")'.
     */
    public void setDeleteCall(Call call) {
        DataModifyQuery query = new DataModifyQuery();
        query.setCall(call);
        setCustomDeleteQuery(query);
    }

    protected void setHasCustomDeleteQuery(boolean hasCustomDeleteQuery) {
        this.hasCustomDeleteQuery = hasCustomDeleteQuery;
    }

    protected void setHasCustomInsertQuery(boolean bool) {
        hasCustomInsertQuery = bool;
    }

    protected void setInsertQuery(DataModifyQuery insertQuery) {
        this.insertQuery = insertQuery;
    }

    /**
     * PUBLIC:
     * Set the receiver's insert SQL string. This allows the user to override the SQL
     * generated by TOPLink, with there own SQL or procedure call. The arguments are
     * translated from the fields of the source row, through replacing the field names
     * marked by '#' with the values for those fields.
     * This is used to insert an entry into the M-M join table.
     * Example, 'insert into PROJ_EMP (EMP_ID, PROJ_ID) values (#EMP_ID, #PROJ_ID)'.
     */
    public void setInsertSQLString(String sqlString) {
        DataModifyQuery query = new DataModifyQuery();
        query.setSQLString(sqlString);
        setCustomInsertQuery(query);
    }

    /**
     * PUBLIC:
     * Set the receiver's insert Call. This allows the user to override the SQL
     * generated by TOPLink, with there own SQL or procedure call. The arguments are
     * translated from the fields of the source row.
     * This is used to insert an entry into the M-M join table.
     * Example, 'new SQLCall("insert into PROJ_EMP (EMP_ID, PROJ_ID) values (#EMP_ID, #PROJ_ID)")'.
     */
    public void setInsertCall(Call call) {
        DataModifyQuery query = new DataModifyQuery();
        query.setCall(call);
        setCustomInsertQuery(query);
    }

    /**
     * PUBLIC:
     * Set the relational table.
     * This is the join table that store both the source and target primary keys.
     */
    public void setRelationTable(DatabaseTable relationTable) {
        this.relationTable = relationTable;
    }

    /**
     * PUBLIC:
     * Set the name of the relational table.
     * This is the join table that store both the source and target primary keys.
     */
    public void setRelationTableName(String tableName) {
        relationTable = new DatabaseTable(tableName);
    }

    /**
     * PUBLIC:
     * Set the name of the session to execute the mapping's queries under.
     * This can be used by the session broker to override the default session
     * to be used for the target class.
     */
    public void setSessionName(String name) {
        getInsertQuery().setSessionName(name);
        getDeleteQuery().setSessionName(name);
    }

    /**
     * PUBLIC:
     * Set the source key field names associated with the mapping.
     * These must be in-order with the sourceRelationKeyFieldNames.
     */
    public void setSourceKeyFieldNames(Vector fieldNames) {
        Vector fields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(fieldNames.size());
        for (Enumeration fieldNamesEnum = fieldNames.elements(); fieldNamesEnum.hasMoreElements();) {
            fields.addElement(new DatabaseField((String)fieldNamesEnum.nextElement()));
        }

        setSourceKeyFields(fields);
    }

    /**
     * INTERNAL:
     * Set the source fields.
     */
    public void setSourceKeyFields(Vector<DatabaseField> sourceKeyFields) {
        this.sourceKeyFields = sourceKeyFields;
    }

    /**
     * PUBLIC:
     * Set the source key field in the relation table.
     * This is the name of the foreign key in the relation table to the source's primary key field.
     * This method is used if the source primary key is a singleton only.
     */
    public void setSourceRelationKeyFieldName(String sourceRelationKeyFieldName) {
        getSourceRelationKeyFields().addElement(new DatabaseField(sourceRelationKeyFieldName));
    }

    /**
     * PUBLIC:
     * Set the source relation key field names associated with the mapping.
     * These must be in-order with the sourceKeyFieldNames.
     */
    public void setSourceRelationKeyFieldNames(Vector fieldNames) {
        Vector fields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(fieldNames.size());
        for (Enumeration fieldNamesEnum = fieldNames.elements(); fieldNamesEnum.hasMoreElements();) {
            fields.addElement(new DatabaseField((String)fieldNamesEnum.nextElement()));
        }

        setSourceRelationKeyFields(fields);
    }

    /**
     * INTERNAL:
     * Set the source fields.
     */
    public void setSourceRelationKeyFields(Vector<DatabaseField> sourceRelationKeyFields) {
        this.sourceRelationKeyFields = sourceRelationKeyFields;
    }

    /**
     * INTERNAL:
     * Set the target key field names associated with the mapping.
     * These must be in-order with the targetRelationKeyFieldNames.
     */
    public void setTargetKeyFieldNames(Vector fieldNames) {
        Vector fields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(fieldNames.size());
        for (Enumeration fieldNamesEnum = fieldNames.elements(); fieldNamesEnum.hasMoreElements();) {
            fields.addElement(new DatabaseField((String)fieldNamesEnum.nextElement()));
        }

        setTargetKeyFields(fields);
    }

    /**
     * INTERNAL:
     * Set the target fields.
     */
    public void setTargetKeyFields(Vector<DatabaseField> targetKeyFields) {
        this.targetKeyFields = targetKeyFields;
    }

    /**
     * PUBLIC:
     * Set the target key field in the relation table.
     * This is the name of the foreign key in the relation table to the target's primary key field.
     * This method is used if the target's primary key is a singleton only.
     */
    public void setTargetRelationKeyFieldName(String targetRelationKeyFieldName) {
        getTargetRelationKeyFields().addElement(new DatabaseField(targetRelationKeyFieldName));
    }

    /**
     * INTERNAL:
     * Set the target relation key field names associated with the mapping.
     * These must be in-order with the targetKeyFieldNames.
     */
    public void setTargetRelationKeyFieldNames(Vector fieldNames) {
        Vector fields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(fieldNames.size());
        for (Enumeration fieldNamesEnum = fieldNames.elements(); fieldNamesEnum.hasMoreElements();) {
            fields.addElement(new DatabaseField((String)fieldNamesEnum.nextElement()));
        }

        setTargetRelationKeyFields(fields);
    }

    /**
     * INTERNAL:
     * Set the target fields.
     */
    public void setTargetRelationKeyFields(Vector<DatabaseField> targetRelationKeyFields) {
        this.targetRelationKeyFields = targetRelationKeyFields;
    }

    /**
     * INTERNAL:
     * Create a row that contains source relation fields with values extracted from the source object.
     */
    public AbstractRecord buildRelationTableSourceRow(Object sourceObject, AbstractSession session, ForeignReferenceMapping mapping) {
        AbstractRecord databaseRow = new DatabaseRecord();
        return addRelationTableSourceRow(sourceObject, session, databaseRow, mapping);
    }

    /**
     * INTERNAL:
     * Add to a row source relation fields with values extracted from the source object.
     */
    public AbstractRecord addRelationTableSourceRow(Object sourceObject, AbstractSession session, AbstractRecord databaseRow, ForeignReferenceMapping mapping) {
        ObjectBuilder builder = mapping.getDescriptor().getObjectBuilder();
        int size = sourceKeyFields.size();
        for(int i=0; i < size; i++) {
            Object sourceValue = builder.extractValueFromObjectForField(sourceObject, sourceKeyFields.get(i), session);
            databaseRow.put(sourceRelationKeyFields.get(i), sourceValue);
        }
        return databaseRow;
    }

    /**
     * INTERNAL:
     * Create a row that contains source relation fields with values extracted from the source row.
     */
    public AbstractRecord buildRelationTableSourceRow(AbstractRecord sourceRow) {
        AbstractRecord databaseRow = new DatabaseRecord();
        return addRelationTableSourceRow(sourceRow, databaseRow);
    }

    /**
     * INTERNAL:
     * Add to a row source relation fields with values extracted from the source row.
     */
    public AbstractRecord addRelationTableSourceRow(AbstractRecord sourceRow, AbstractRecord databaseRow) {
        int size = sourceKeyFields.size();
        for(int i=0; i < size; i++) {
            Object sourceValue = sourceRow.get(sourceKeyFields.get(i));
            databaseRow.put(sourceRelationKeyFields.get(i), sourceValue);
        }
        return databaseRow;
    }

    /**
     * INTERNAL:
     * Add to a row target relation fields with values extracted from the target object.
     */
    public AbstractRecord addRelationTableTargetRow(Object targetObject, AbstractSession session, AbstractRecord databaseRow, ForeignReferenceMapping mapping) {
        ObjectBuilder builder = mapping.getReferenceDescriptor().getObjectBuilder();
        int size = targetKeyFields.size();
        for(int i=0; i < size; i++) {
            Object sourceValue = builder.extractValueFromObjectForField(targetObject, targetKeyFields.get(i), session);
            databaseRow.put(targetRelationKeyFields.get(i), sourceValue);
        }
        return databaseRow;
    }

    /**
     * INTERNAL:
     * Create a row that contains source relation fields with values extracted from the source object
     * and target relation fields with values extracted from the target object.
     */
    public AbstractRecord buildRelationTableSourceAndTargetRow(Object sourceObject, Object targetObject, AbstractSession session, ForeignReferenceMapping mapping) {
        AbstractRecord databaseRow = buildRelationTableSourceRow(sourceObject, session, mapping);
        databaseRow = addRelationTableTargetRow(targetObject, session, databaseRow, mapping);
        return databaseRow;
    }

    /**
     * INTERNAL:
     * Create a row that contains source relation fields with values extracted from the source row
     * and target relation fields with values extracted from the target object.
     */
    public AbstractRecord buildRelationTableSourceAndTargetRow(AbstractRecord sourceRow, Object targetObject, AbstractSession session, ForeignReferenceMapping mapping) {
        AbstractRecord databaseRow = buildRelationTableSourceRow(sourceRow);
        databaseRow = addRelationTableTargetRow(targetObject, session, databaseRow, mapping);
        return databaseRow;
    }
}
