/*
 * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2020 IBM Corporation. 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
//     05/14/2012-2.4 Guy Pelletier
//       - 376603: Provide for table per tenant support for multitenant applications
//     02/11/2013-2.5 Guy Pelletier
//       - 365931: @JoinColumn(name="FK_DEPT",insertable = false, updatable = true) causes INSERT statement to include this data value that it is associated with
package org.eclipse.persistence.mappings;

import java.util.*;

import org.eclipse.persistence.annotations.CacheKeyType;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.internal.identitymaps.*;
import org.eclipse.persistence.internal.indirection.ProxyIndirectionPolicy;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.queries.MappedKeyMapContainerPolicy;
import org.eclipse.persistence.internal.sessions.*;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.internal.descriptors.CascadeLockingPolicy;
import org.eclipse.persistence.internal.descriptors.DescriptorIterator;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.expressions.ConstantExpression;
import org.eclipse.persistence.internal.expressions.ObjectExpression;
import org.eclipse.persistence.internal.expressions.FieldExpression;
import org.eclipse.persistence.internal.expressions.ParameterExpression;
import org.eclipse.persistence.internal.expressions.QueryKeyExpression;
import org.eclipse.persistence.internal.expressions.SQLSelectStatement;
import org.eclipse.persistence.mappings.foundation.MapKeyMapping;
import org.eclipse.persistence.mappings.querykeys.OneToOneQueryKey;
import org.eclipse.persistence.mappings.querykeys.QueryKey;

/**
 * <p><b>Purpose</b>: One to one mappings are used to represent a pointer references
 * between two java objects. This mappings is usually represented by a single pointer
 * (stored in an instance variable) between the source and target objects. In the relational
 * database tables, these mappings are normally implemented using foreign keys.
 *
 * @author Sati
 * @since TOPLink/Java 1.0
 */
public class OneToOneMapping extends ObjectReferenceMapping implements RelationalMapping, MapKeyMapping {

    /** Maps the source foreign/primary key fields to the target primary/foreign key fields. */
    protected Map<DatabaseField, DatabaseField> sourceToTargetKeyFields;

    /** Maps the target primary/foreign key fields to the source foreign/primary key fields. */
    protected Map<DatabaseField, DatabaseField> targetToSourceKeyFields;

    /** Keeps track of which fields are foreign keys on a per field basis (can have mixed foreign key relationships). */
    /** These are used for non-unit of work modification to check if the value of the 1-1 was changed and a deletion is required. */
    protected boolean shouldVerifyDelete;
    protected transient Expression privateOwnedCriteria;

    public DatabaseTable keyTableForMapKey = null;

    protected static final String setObject = "setObject";

    /** Mechanism holds relationTable and all fields and queries associated with it. */
    protected RelationTableMechanism mechanism;

    /**
     * Define if this mapping is really for a OneToOne relationship.
     * This is a backward compatibility issue, in that before the ManyToOneMapping
     * was created OneToOneMapping was used for both.
     */
    protected boolean isOneToOneRelationship = false;

    /**
     * Defines if this mapping was built using primary key join columns.
     */
    protected boolean isOneToOnePrimaryKeyRelationship = false;

    /**
     * Keep track of which fields are insertable and updatable.
     */
    protected HashSet<DatabaseField> insertableFields = new HashSet<>();
    protected HashSet<DatabaseField> updatableFields = new HashSet<>();

    /**
     * Keep a reference to the source and target expressions to post initialize
     * when building a selection criteria early.
     */
    protected transient List<Expression> sourceExpressionsToPostInitialize;
    protected transient List<Expression> targetExpressionsToPostInitialize;

    /**
     * Mode for writeFromObjectIntoRowInternal method
     */
    protected enum ShallowMode {
        Insert,
        UpdateAfterInsert,
        UpdateBeforeDelete
    }

    /**
     * PUBLIC:
     * Default constructor.
     */
    public OneToOneMapping() {
        this.selectionQuery = new ReadObjectQuery();
        this.sourceToTargetKeyFields = new HashMap(2);
        this.targetToSourceKeyFields = new HashMap(2);
        this.foreignKeyFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
        this.sourceExpressionsToPostInitialize = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
        this.targetExpressionsToPostInitialize = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);
        this.isForeignKeyRelationship = false;
        this.shouldVerifyDelete = true;
    }

    /**
     * INTERNAL:
     */
    @Override
    public boolean isRelationalMapping() {
        return true;
    }

    /**
     * INTERNAL:
     * Used when initializing queries for mappings that use a Map.
     * Called when the selection query is being initialized to add the fields for the map key to the query.
     */
    @Override
    public void addAdditionalFieldsToQuery(ReadQuery selectionQuery, Expression baseExpression){
        for (DatabaseField field : getForeignKeyFields()) {
            if (selectionQuery.isObjectLevelReadQuery()){
                ((ObjectLevelReadQuery)selectionQuery).addAdditionalField(baseExpression.getField(field));
            } else if (selectionQuery.isDataReadQuery()){
                ((SQLSelectStatement) selectionQuery.getSQLStatement()).addField(field);
            }
        }
    }

    /**
     * INTERNAL:
     * Used when initializing queries for mappings that use a Map
     * Called when the insert query is being initialized to ensure the fields for the map key are in the insert query
     */
    @Override
    public void addFieldsForMapKey(AbstractRecord joinRow){
        Iterator i = getForeignKeyFields().iterator();
        while (i.hasNext()){
            joinRow.put((DatabaseField)i.next(), null);
        }
    }

    /**
     * PUBLIC:
     * Define the foreign key relationship in the 1-1 mapping.
     * This method is used for composite foreign key relationships,
     * that is the source object's table has multiple foreign key fields to
     * the target object's primary key fields.
     * Both the source foreign key field and the target foreign key field must
     * be specified.
     * When a foreign key is specified TopLink will automatically populate the
     * value for that field from the target object when the object is written to
     * the database. If the foreign key is also mapped through a direct-to-field
     * then the direct-to-field must be set read-only.
     */
    @Override
    public void addForeignKeyField(DatabaseField sourceForeignKeyField, DatabaseField targetPrimaryKeyField) {
        setIsForeignKeyRelationship(true);
        getForeignKeyFields().addElement(sourceForeignKeyField);

        getSourceToTargetKeyFields().put(sourceForeignKeyField, targetPrimaryKeyField);
        getTargetToSourceKeyFields().put(targetPrimaryKeyField, sourceForeignKeyField);
    }

    /**
     * PUBLIC:
     * Define the foreign key relationship in the 1-1 mapping.
     * This method is used for composite foreign key relationships,
     * that is the source object's table has multiple foreign key fields to
     * the target object's primary key fields.
     * Both the source foreign key field name and the target foreign key field
     * name must be specified.
     * When a foreign key is specified TopLink will automatically populate the
     * value for that field from the target object when the object is written to
     * the database. If the foreign key is also mapped through a direct-to-field
     * then the direct-to-field must be set read-only.
     */
    public void addForeignKeyFieldName(String sourceForeignKeyFieldName, String targetPrimaryKeyFieldName) {
        addForeignKeyField(new DatabaseField(sourceForeignKeyFieldName), new DatabaseField(targetPrimaryKeyFieldName));
    }

    /**
     * PUBLIC:
     * Define the target foreign key relationship in the 1-1 mapping.
     * This method is used for composite target foreign key relationships,
     * that is the target object's table has multiple foreign key fields to
     * the source object's primary key fields.
     * Both the target foreign key field and the source primary key field must
     * be specified.
     * The distinction between a foreign key and target foreign key is that the
     * 1-1 mapping will not populate the target foreign key value when written
     * (because it is in the target table). Normally 1-1's are through foreign
     * keys but in bi-directional 1-1's the back reference will be a target
     * foreign key. In obscure composite legacy data models a 1-1 may consist of
     * a foreign key part and a target foreign key part, in this case both
     * method will be called with the correct parts.
     */
    @Override
    public void addTargetForeignKeyField(DatabaseField targetForeignKeyField, DatabaseField sourcePrimaryKeyField) {
        getSourceToTargetKeyFields().put(sourcePrimaryKeyField, targetForeignKeyField);
        getTargetToSourceKeyFields().put(targetForeignKeyField, sourcePrimaryKeyField);
    }

    /**
     * PUBLIC:
     * Define the target foreign key relationship in the 1-1 mapping.
     * This method is used for composite target foreign key relationships,
     * that is the target object's table has multiple foreign key fields to
     * the source object's primary key fields.
     * Both the target foreign key field name and the source primary key field
     * name must be specified.
     * The distinction between a foreign key and target foreign key is that the
     * 1-1 mapping will not populate the target foreign key value when written
     * (because it is in the target table). Normally 1-1's are through foreign
     * keys but in bi-directional 1-1's the back reference will be a target
     * foreign key. In obscure composite legacy data models a 1-1 may consist of
     * a foreign key part and a target foreign key part, in this case both
     * method will be called with the correct parts.
     */
    public void addTargetForeignKeyFieldName(String targetForeignKeyFieldName, String sourcePrimaryKeyFieldName) {
        addTargetForeignKeyField(new DatabaseField(targetForeignKeyFieldName), new DatabaseField(sourcePrimaryKeyFieldName));
    }

    /**
     * INTERNAL:
     * For mappings used as MapKeys in MappedKeyContainerPolicy.  Add the target of this mapping to the deleted
     * objects list if necessary
     *
     * This method is used for removal of private owned relationships.
     */
    @Override
    public void addKeyToDeletedObjectsList(Object object, Map deletedObjects){
        deletedObjects.put(object, object);
    }

    /**
     * Build a clone of the given element in a unitOfWork.
     */
    @Override
    public Object buildElementClone(Object attributeValue, Object parent, CacheKey cacheKey, Integer refreshCascade, AbstractSession cloningSession, boolean isExisting, boolean isFromSharedCache){
        return buildCloneForPartObject(attributeValue, null, cacheKey, parent, cloningSession, refreshCascade, isExisting, isFromSharedCache);
    }

    /**
     * INTERNAL:
     * Used to allow object level comparisons.
     */
    @Override
    public Expression buildObjectJoinExpression(Expression expression, Object value, AbstractSession session) {
        Expression base = ((ObjectExpression)expression).getBaseExpression();
        Expression foreignKeyJoin = null;

        if(this.mechanism == null) {
            // Allow for equal null.
            if (value == null) {
                if (!isForeignKeyRelationship()) {
                    // ELBug#331352
                    // Need to do a join and compare target foreign key to null.
                    for (DatabaseField field : getSourceToTargetKeyFields().values()) {
                        Expression join = null;
                        join = expression.getField(field).equal(null);
                        if (foreignKeyJoin == null) {
                            foreignKeyJoin = join;
                        } else {
                            foreignKeyJoin = foreignKeyJoin.and(join);
                        }
                    }
                } else {
                    for (DatabaseField field : getSourceToTargetKeyFields().keySet()) {
                        Expression join = null;
                        join = base.getField(field).equal(null);
                        if (foreignKeyJoin == null) {
                            foreignKeyJoin = join;
                        } else {
                            foreignKeyJoin = foreignKeyJoin.and(join);
                        }
                    }
                }
            } else {
                if (!getReferenceDescriptor().getJavaClass().isInstance(value)) {
                    // Bug 3894351 - ensure any proxys are triggered so we can do a proper class comparison
                    value = ProxyIndirectionPolicy.getValueFromProxy(value);
                    if (!getReferenceDescriptor().getJavaClass().isInstance(value)) {
                        throw QueryException.incorrectClassForObjectComparison(base, value, this);
                    }
                }

                Iterator keyIterator = Arrays.asList(((CacheId)extractKeyFromReferenceObject(value, session)).getPrimaryKey()).iterator();
                for (DatabaseField field : getSourceToTargetKeyFields().keySet()) {
                    Expression join = null;
                    join = base.getField(field).equal(keyIterator.next());
                    if (foreignKeyJoin == null) {
                        foreignKeyJoin = join;
                    } else {
                        foreignKeyJoin = foreignKeyJoin.and(join);
                    }
                }
            }
        } else {
            int size = this.mechanism.sourceKeyFields.size();
            Object key = null;
            if (value != null) {
                if (!getReferenceDescriptor().getJavaClass().isInstance(value)) {
                    // Bug 3894351 - ensure any proxys are triggered so we can do a proper class comparison
                    value = ProxyIndirectionPolicy.getValueFromProxy(value);
                    if (!getReferenceDescriptor().getJavaClass().isInstance(value)) {
                        throw QueryException.incorrectClassForObjectComparison(base, value, this);
                    }
                }
                key = extractKeyFromReferenceObject(value, session);
                boolean allNulls = true;
                for (int i=0; i < size; i++) {
                    if (((CacheId)key).getPrimaryKey()[i] != null) {
                        allNulls = false;
                        break;
                    }
                }
                // the same case
                if (allNulls) {
                    value = null;
                }
            }
            if (value != null) {
                for(int i=0; i < size; i++) {
                    DatabaseField field = this.mechanism.sourceKeyFields.get(i);
                    Expression join = null;
                    join = base.getField(field).equal(((CacheId)key).getPrimaryKey()[i]);
                    if (foreignKeyJoin == null) {
                        foreignKeyJoin = join;
                    } else {
                        foreignKeyJoin = foreignKeyJoin.and(join);
                    }
                }
            } else {
                ReportQuery subQuery = new ReportQuery(this.descriptor.getJavaClass(), new ExpressionBuilder());
                Expression relationTableExp = subQuery.getExpressionBuilder().getTable(this.mechanism.relationTable);
                Expression subSelectExp = null;
                for(int i=0; i < size; i++) {
                    subSelectExp = relationTableExp.getField(this.mechanism.sourceRelationKeyFields.get(i)).equal(base.getField(this.mechanism.sourceKeyFields.get(i))).and(subSelectExp);
                }
                subQuery.setSelectionCriteria(subSelectExp);
                subQuery.dontRetrievePrimaryKeys();
                subQuery.addAttribute("", subQuery.getExpressionBuilder().getField(this.mechanism.sourceKeyFields.get(0)));
                foreignKeyJoin = base.notExists(subQuery);
            }
        }
        return foreignKeyJoin;
    }

    /**
     * INTERNAL:
     * Used to allow object level comparisons.
     */
    @Override
    public Expression buildObjectJoinExpression(Expression expression, Expression argument, AbstractSession session) {
        Expression base = ((org.eclipse.persistence.internal.expressions.ObjectExpression)expression).getBaseExpression();
        Expression foreignKeyJoin = null;
        if(this.mechanism == null) {
            if (expression==argument){
                for (Iterator sourceFieldsEnum = getSourceToTargetKeyFields().keySet().iterator();
                         sourceFieldsEnum.hasNext();) {
                    DatabaseField field = (DatabaseField)sourceFieldsEnum.next();
                    Expression join = base.getField(field);
                    join = join.equal(join);
                    if (foreignKeyJoin == null) {
                        foreignKeyJoin = join;
                    } else {
                        foreignKeyJoin = foreignKeyJoin.and(join);
                    }
                }
            }else{
                Iterator targetFieldsEnum = getSourceToTargetKeyFields().values().iterator();
                for (Iterator sourceFieldsEnum = getSourceToTargetKeyFields().keySet().iterator();
                         sourceFieldsEnum.hasNext();) {
                    DatabaseField sourceField = (DatabaseField)sourceFieldsEnum.next();
                    DatabaseField targetField = (DatabaseField)targetFieldsEnum.next();
                    Expression join = null;
                    join = base.getField(sourceField).equal(argument.getField(targetField));
                    if (foreignKeyJoin == null) {
                        foreignKeyJoin = join;
                    } else {
                        foreignKeyJoin = foreignKeyJoin.and(join);
                    }
                }
            }
        } else {
            if (expression==argument){
                foreignKeyJoin = (new ConstantExpression(0, base)).equal(new ConstantExpression(0, base));
            }else{
                int size = this.mechanism.sourceKeyFields.size();
                Expression relTable = base.getTable(this.mechanism.getRelationTable());
                for(int i=0; i < size; i++) {
                    Expression source = base.getField(this.mechanism.sourceKeyFields.get(i));
                    Expression sourceRel = relTable.getField(this.mechanism.sourceRelationKeyFields.get(i));
                    Expression targetRel = relTable.getField(this.mechanism.targetRelationKeyFields.get(i));
                    Expression target = argument.getField(this.mechanism.targetKeyFields.get(i));
                    foreignKeyJoin = source.equal(sourceRel).and(targetRel.equal(target)).and(foreignKeyJoin);
                }
            }
        }
        return foreignKeyJoin;
    }

    /**
     * INTERNAL:
     * Certain key mappings favor different types of selection query.  Return the appropriate
     * type of selectionQuery
     * @return
     */
    @Override
    public ReadQuery buildSelectionQueryForDirectCollectionKeyMapping(ContainerPolicy containerPolicy){
        DataReadQuery query = new DataReadQuery();
        query.setSQLStatement(new SQLSelectStatement());
        query.setContainerPolicy(containerPolicy);
        return query;
    }

    /**
     * INTERNAL:
     * This methods clones all the fields and ensures that each collection refers to
     * the same clones.
     */
    @Override
    public Object clone() {
        OneToOneMapping clone = (OneToOneMapping)super.clone();
        if(this.mechanism == null) {
            clone.setForeignKeyFields(org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(getForeignKeyFields().size()));
            clone.setSourceToTargetKeyFields(new HashMap(getSourceToTargetKeyFields().size()));
            clone.setTargetToSourceKeyFields(new HashMap(getTargetToSourceKeyFields().size()));

            // DatabaseField overrides equals, so we need to use an IdentifyHashMap for this implementation
            // to make sure we are using the object references to lookup clone references
            AbstractMap<DatabaseField, DatabaseField> fieldToCloneMap = new IdentityHashMap<DatabaseField, DatabaseField>(getTargetToSourceKeyFields().size());

            //clone foreign keys and save the clones in a lookup table
            for (Enumeration<DatabaseField> enumtr = getForeignKeyFields().elements(); enumtr.hasMoreElements();) {
                DatabaseField field = enumtr.nextElement();
                DatabaseField fieldClone = field.clone();
                fieldToCloneMap.put(field, fieldClone);
                clone.getForeignKeyFields().addElement(fieldClone);
            }

            // lookup references in the map to get the associated clone reference. If it doesn't exist, create a new one.
            for (Iterator<DatabaseField> sourceEnum = getSourceToTargetKeyFields().keySet().iterator();
                     sourceEnum.hasNext();) {
                DatabaseField sourceField = sourceEnum.next();
                DatabaseField targetField = getSourceToTargetKeyFields().get(sourceField);

                DatabaseField targetClone;
                DatabaseField sourceClone;

                targetClone = fieldToCloneMap.get(targetField);
                if (targetClone == null) {
                    targetClone = targetField.clone();
                    fieldToCloneMap.put(targetField, targetClone);
                }
                sourceClone = fieldToCloneMap.get(sourceField);
                if (sourceClone == null) {
                    sourceClone = sourceField.clone();
                    fieldToCloneMap.put(sourceField, sourceClone);
                }
                clone.getSourceToTargetKeyFields().put(sourceClone, targetClone);
            }

            // lookup references in the map to get the associated clone reference. If it doesn't exist, create a new one.
            for (Iterator<DatabaseField> targetEnum = getTargetToSourceKeyFields().keySet().iterator();
                     targetEnum.hasNext();) {
                DatabaseField targetField = targetEnum.next();
                DatabaseField sourceField = getTargetToSourceKeyFields().get(targetField);

                DatabaseField targetClone;
                DatabaseField sourceClone;

                targetClone = fieldToCloneMap.get(targetField);
                if (targetClone == null) {
                    targetClone = targetField.clone();
                    fieldToCloneMap.put(targetField, targetClone);
                }
                sourceClone = fieldToCloneMap.get(sourceField);
                if (sourceClone == null) {
                    sourceClone = sourceField.clone();
                    fieldToCloneMap.put(sourceField, sourceClone);
                }
                clone.getTargetToSourceKeyFields().put(targetClone, sourceClone);
            }
        } else {
            clone.mechanism = (RelationTableMechanism)this.mechanism.clone();
        }
        return clone;
    }

    @Override
    public void collectQueryParameters(Set<DatabaseField> cacheFields){
        for (DatabaseField field : sourceToTargetKeyFields.keySet()) {
            cacheFields.add(field);
        }
    }

    /**
     * INTERNAL
     * Called when a DatabaseMapping is used to map the key in a collection.  Returns the key.
     */
    @Override
    public Object createMapComponentFromRow(AbstractRecord dbRow, ObjectBuildingQuery query, CacheKey parentCacheKey, AbstractSession session, boolean isTargetProtected){
        return session.executeQuery(getSelectionQuery(), dbRow);
    }

    /**
     * INTERNAL:
     * Creates the Array of simple types used to recreate this map.
     */
    @Override
    public Object createSerializableMapKeyInfo(Object key, AbstractSession session){
        return referenceDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(key, session);
    }

    /**
     * INTERNAL:
     * Create an instance of the Key object from the key information extracted from the map.
     * This may return the value directly in case of a simple key or will be used as the FK to load a related entity.
     */
    @Override
    public List<Object> createMapComponentsFromSerializableKeyInfo(Object[] keyInfo, AbstractSession session){
        List<Object> orderedResult = new ArrayList<>(keyInfo.length);
        Map<Object, Object> fromCache = session.getIdentityMapAccessorInstance().getAllFromIdentityMapWithEntityPK(keyInfo, referenceDescriptor);
        List foreignKeyValues = new ArrayList(keyInfo.length - fromCache.size());

        CacheKeyType cacheKeyType = referenceDescriptor.getCachePolicy().getCacheKeyType();
        for (int index = 0; index < keyInfo.length; ++index){
            Object pk = keyInfo[index];
            if (!fromCache.containsKey(pk)){
                if (cacheKeyType == CacheKeyType.CACHE_ID){
                    foreignKeyValues.add(Arrays.asList(((CacheId)pk).getPrimaryKey()));
                }else{
                    foreignKeyValues.add(pk);
                }
            }
        }
        if (!foreignKeyValues.isEmpty()){
            ReadAllQuery query = new ReadAllQuery(referenceDescriptor.getJavaClass());
            query.setIsExecutionClone(true);
            query.addArgument(ForeignReferenceMapping.QUERY_BATCH_PARAMETER);
            query.addArgumentValue(foreignKeyValues);
            query.setSession(session);
            query.setSelectionCriteria(referenceDescriptor.buildBatchCriteriaByPK(query.getExpressionBuilder(), query));
            Collection<Object> temp = (Collection<Object>) session.executeQuery(query);
            for (Object element: temp){
                Object pk = referenceDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(element, session);
                fromCache.put(pk, element);
            }
        }
        for(Object key : keyInfo){
            orderedResult.add(fromCache.get(key));
        }
        return orderedResult;
    }

    /**
     * INTERNAL:
     * Create an instance of the Key object from the key information extracted from the map.
     * This key object may be a shallow stub of the actual object if the key is an Entity type.
     */
    @Override
    public Object createStubbedMapComponentFromSerializableKeyInfo(Object keyInfo, AbstractSession session) {
        ObjectBuilder builder = this.referenceDescriptor.getObjectBuilder();
        ObjectBuildingQuery clonedQuery = (ObjectBuildingQuery) getSelectionQuery().clone();
        clonedQuery.setSession(session);
        Object newObject = referenceDescriptor.getInstantiationPolicy().buildNewInstance();
        builder.buildPrimaryKeyAttributesIntoObject(newObject, builder.buildRowFromPrimaryKeyValues(keyInfo, session), clonedQuery, session);
        return newObject;
    }

    /**
     * INTERNAL
     * Called when a DatabaseMapping is used to map the key in a collection.  Returns the key.
     */
    @Override
    public Object createMapComponentFromJoinedRow(AbstractRecord dbRow, JoinedAttributeManager joinManager, ObjectBuildingQuery query, CacheKey parentCacheKey, AbstractSession session, boolean isTargetProtected){
        return valueFromRowInternalWithJoin(dbRow, joinManager, query, parentCacheKey, session, isTargetProtected);
    }

    /**
     * INTERNAL:
     * Create a query key that links to the map key
     * @return
     */
    @Override
    public QueryKey createQueryKeyForMapKey(){
        OneToOneQueryKey key = new OneToOneQueryKey();
        key.setDescriptor(getReferenceDescriptor());
        key.setReferenceClass(getReferenceClass());
        key.setJoinCriteria(getAdditionalSelectionCriteriaForMapKey());
        return key;
    }

    /**
     * INTERNAL:
     * For mappings used as MapKeys in MappedKeyContainerPolicy, Delete the passed object if necessary.
     *
     * This method is used for removal of private owned relationships
     *
     * @param objectDeleted
     * @param session
     */
    @Override
    public void deleteMapKey(Object objectDeleted, AbstractSession session){
        session.deleteObject(objectDeleted);
    }

    /**
     * INTERNAL:
     * Adds locking clause to the target query to extend pessimistic lock scope.
     */
    @Override
    protected void extendPessimisticLockScopeInTargetQuery(ObjectLevelReadQuery targetQuery, ObjectBuildingQuery sourceQuery) {
        if(this.mechanism == null) {
            super.extendPessimisticLockScopeInTargetQuery(targetQuery, sourceQuery);
        } else {
            this.mechanism.setRelationTableLockingClause(targetQuery, sourceQuery);
        }
    }

    /**
     * INTERNAL:
     * Called only if both
     * shouldExtendPessimisticLockScope and shouldExtendPessimisticLockScopeInSourceQuery are true.
     * Adds fields to be locked to the where clause of the source query.
     * Note that the sourceQuery must be ObjectLevelReadQuery so that it has ExpressionBuilder.
     *
     * This method must be implemented in subclasses that allow
     * setting shouldExtendPessimisticLockScopeInSourceQuery to true.
     */
    @Override
    public void extendPessimisticLockScopeInSourceQuery(ObjectLevelReadQuery sourceQuery) {
        Expression exp = sourceQuery.getSelectionCriteria();
        if(this.mechanism == null) {
            ExpressionBuilder builder = sourceQuery.getExpressionBuilder();
            Iterator<Map.Entry<DatabaseField, DatabaseField>> it = this.getSourceToTargetKeyFields().entrySet().iterator();
            Map.Entry<DatabaseField, DatabaseField> entry = it.next();
            exp = builder.getField(entry.getKey()).equal(builder.get(this.getAttributeName()).getField(entry.getValue())).and(exp);
        } else {
            exp = this.mechanism.joinRelationTableField(exp, sourceQuery.getExpressionBuilder());
        }
        sourceQuery.setSelectionCriteria(exp);
    }

    /**
     * INTERNAL:
     * Extract the foreign key value from the source row.
     */
    @Override
    protected Object extractBatchKeyFromRow(AbstractRecord row, AbstractSession session) {
        if (this.mechanism != null) {
            return this.mechanism.extractBatchKeyFromRow(row, session);
        }
        Object[] key;
        ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
        key = new Object[this.sourceToTargetKeyFields.size()];
        int index = 0;
        for (DatabaseField field : this.sourceToTargetKeyFields.keySet()) {
            Object value = row.get(field);
            if (value == null) {
                return null;
            }
            // Must ensure the classification gets a cache hit.
            try {
                value = conversionManager.convertObject(value, field.getType());
            } catch (ConversionException exception) {
                throw ConversionException.couldNotBeConverted(this, this.descriptor, exception);
            }
            key[index] = value;
            index++;
        }
        return new CacheId(key);
    }

    /**
     * INTERNAL:
     * Extract the fields for the Map key from the object to use in a query
     */
    @Override
    public Map extractIdentityFieldsForQuery(Object object, AbstractSession session){
        Map keyFields = new HashMap();
         for (int index = 0; index < getForeignKeyFields().size(); index++) {
            DatabaseField targetRelationField = getForeignKeyFields().elementAt(index);
            DatabaseField targetKey = getSourceToTargetKeyFields().get(targetRelationField);
            Object value = getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(object, targetKey, session);
            keyFields.put(targetRelationField, value);
        }
        return keyFields;
    }

    /**
     * INTERNAL:
     * Extract the key value from the reference object.
     */
    protected Object extractKeyFromReferenceObject(Object object, AbstractSession session) {
        ObjectBuilder objectBuilder = getReferenceDescriptor().getObjectBuilder();
        Object[] key;
        if (this.mechanism == null) {
            key = new Object[getSourceToTargetKeyFields().size()];
            int index = 0;
            for (DatabaseField field : getSourceToTargetKeyFields().values()) {
                if (object == null) {
                    key[index] = null;
                } else {
                    key[index] = objectBuilder.extractValueFromObjectForField(object, field, session);
                }
                index++;
            }
        } else {
            int size = this.mechanism.targetKeyFields.size();
            key = new Object[size];
            for (int i = 0; i < size; i++) {
                if (object == null) {
                    key[i] = null;
                } else {
                    DatabaseField field = this.mechanism.targetKeyFields.get(i);
                    key[i] = objectBuilder.extractValueFromObjectForField(object, field, session);
                }
            }
        }

        return new CacheId(key);
    }

    /**
     * INTERNAL:
     * Return the primary key for the reference object (i.e. the object
     * object referenced by domainObject and specified by mapping).
     * This key will be used by a RemoteValueHolder.
     */
    @Override
    public Object extractPrimaryKeysForReferenceObjectFromRow(AbstractRecord row) {
        List primaryKeyFields = getReferenceDescriptor().getPrimaryKeyFields();
        Object[] result = new  Object[primaryKeyFields.size()];
        for (int index = 0; index < primaryKeyFields.size(); index++) {
            DatabaseField targetKeyField = (DatabaseField)primaryKeyFields.get(index);
            DatabaseField sourceKeyField = getTargetToSourceKeyFields().get(targetKeyField);
            if (sourceKeyField == null) {
                return null;
            }
            result[index] = row.get(sourceKeyField);
            if (getReferenceDescriptor().getCachePolicy().getCacheKeyType() == CacheKeyType.ID_VALUE) {
                return result[index];
            }
        }
        return new CacheId(result);
    }

    /**
     * INTERNAL:
     * Allow the mapping the do any further batch preparation.
     */
    @Override
    protected void postPrepareNestedBatchQuery(ReadQuery batchQuery, ObjectLevelReadQuery query) {
        super.postPrepareNestedBatchQuery(batchQuery, query);
        // Force a distinct to filter out m-1 duplicates.
        // Only set if really a m-1, not a 1-1
        if (!this.isOneToOneRelationship && ((ObjectLevelReadQuery)batchQuery).getBatchFetchPolicy().isJOIN()) {
            if (!((ObjectLevelReadQuery)batchQuery).isDistinctComputed() && (batchQuery.getSession().getPlatform().isLobCompatibleWithDistinct() || !Helper.hasLob(batchQuery.getDescriptor().getSelectionFields((ObjectLevelReadQuery)batchQuery)))) {
                ((ObjectLevelReadQuery)batchQuery).useDistinct();
            }
        }
        if (this.mechanism != null) {
            this.mechanism.postPrepareNestedBatchQuery(batchQuery, query);
        }
    }

    /**
     * INTERNAL:
     * Return the selection criteria used to IN batch fetching.
     */
    @Override
    protected Expression buildBatchCriteria(ExpressionBuilder builder, ObjectLevelReadQuery query) {
        if (this.mechanism == null) {
            int size = this.sourceToTargetKeyFields.size();
            if (size > 1) {
                // Support composite keys using nested IN.
                List<Expression> fields = new ArrayList<>(size);
                for (DatabaseField targetForeignKeyField : this.sourceToTargetKeyFields.values()) {
                    fields.add(builder.getField(targetForeignKeyField));
                }
                return query.getSession().getPlatform().buildBatchCriteriaForComplexId(builder, fields);
            } else {
                return query.getSession().getPlatform().buildBatchCriteria(builder, builder.getField(this.sourceToTargetKeyFields.values().iterator().next()));
            }
        } else {
            return this.mechanism.buildBatchCriteria(builder, query);
        }
    }

    /**
     * INTERNAL:
     * Prepare and execute the batch query and store the
     * results for each source object in a map keyed by the
     * mappings source keys of the source objects.
     */
    @Override
    protected void executeBatchQuery(DatabaseQuery query, CacheKey parentCacheKey, Map referenceObjectsByKey, AbstractSession session, AbstractRecord translationRow) {
        // Execute query and index resulting objects by key.
        List results;
        ObjectBuilder builder = query.getDescriptor().getObjectBuilder();
        if (this.mechanism == null) {
            results = (List)session.executeQuery(query, translationRow);
            for (Object eachReferenceObject : results) {
                Object eachReferenceKey = extractKeyFromReferenceObject(eachReferenceObject, session);
                referenceObjectsByKey.put(eachReferenceKey, builder.wrapObject(eachReferenceObject, session));
            }
        } else {
            ComplexQueryResult complexResult = (ComplexQueryResult)session.executeQuery(query, translationRow);
            results = (List)complexResult.getResult();
            List<AbstractRecord> rows = (List)complexResult.getData();
            int size = results.size();
            for (int index = 0; index < size; index++) {
                AbstractRecord row = rows.get(index);
                Object key = this.mechanism.extractKeyFromTargetRow(row, session);
                referenceObjectsByKey.put(key, builder.wrapObject(results.get(index), session));
            }
        }
    }

    /**
     * INTERNAL:
     * Check if the target object is in the cache if possible based on the target key value.
     * Return null if the target key is not the primary key, or if the query is refreshing.
     */
    @Override
    protected Object checkCacheForBatchKey(AbstractRecord sourceRow, Object foreignKey, Map batchObjects, ReadQuery batchQuery, ObjectLevelReadQuery originalQuery, AbstractSession session) {
        if (((ReadAllQuery)batchQuery).shouldRefreshIdentityMapResult() || (!batchQuery.shouldMaintainCache())) {
            return null;
        }
        // Check the cache using the source row and selection query.
        Object cachedObject = this.selectionQuery.checkEarlyReturn(session, sourceRow);
        if ((cachedObject != null) && (batchObjects != null)) {
            batchObjects.put(foreignKey, cachedObject);
        }
        return cachedObject;
    }

    /**
     * INTERNAL:
     * Return the selection criteria necessary to select the target object when this mapping
     * is a map key.
     * @return
     */
    @Override
    public Expression getAdditionalSelectionCriteriaForMapKey(){
        return buildSelectionCriteria(false, false);
    }

    /**
     * INTERNAL:
     * Return any tables that will be required when this mapping is used as part of a join query
     */
    @Override
    public List<DatabaseTable> getAdditionalTablesForJoinQuery(){
        List<DatabaseTable> tables = new ArrayList<>(getReferenceDescriptor().getTables().size() + 1);
        tables.addAll(getReferenceDescriptor().getTables());
        if (keyTableForMapKey != null){
            tables.add(keyTableForMapKey);
        }
        return tables;
    }

    /**
     * INTERNAL:
     * Should be overridden by subclass that allows setting
     * extendPessimisticLockScope to DEDICATED_QUERY.
     */
    @Override
    protected ReadQuery getExtendPessimisticLockScopeDedicatedQuery(AbstractSession session, short lockMode) {
        if(this.mechanism != null) {
            return this.mechanism.getLockRelationTableQueryClone(session, lockMode);
        } else {
            return super.getExtendPessimisticLockScopeDedicatedQuery(session, lockMode);
        }
    }

    /**
     * INTERNAL:
     * Return the classification for the field contained in the mapping.
     * This is used to convert the row value to a consistent java value.
     */
    @Override
    public Class getFieldClassification(DatabaseField fieldToClassify) throws DescriptorException {
        DatabaseField fieldInTarget = getSourceToTargetKeyFields().get(fieldToClassify);
        if (fieldInTarget == null) {
            return null;// Can be registered as multiple table secondary field mapping
        }
        DatabaseMapping mapping = getReferenceDescriptor().getObjectBuilder().getMappingForField(fieldInTarget);
        if (mapping == null) {
            return null;// Means that the mapping is read-only
        }
        return mapping.getFieldClassification(fieldInTarget);
    }

    /**
     * PUBLIC:
     * Return the foreign key field names associated with the mapping.
     * These are only the source fields that are writable.
     */
    public Vector getForeignKeyFieldNames() {
        Vector fieldNames = new Vector(getForeignKeyFields().size());
        for (Enumeration fieldsEnum = getForeignKeyFields().elements();
                 fieldsEnum.hasMoreElements();) {
            fieldNames.addElement(((DatabaseField)fieldsEnum.nextElement()).getQualifiedName());
        }

        return fieldNames;
    }

    /**
     * INTERNAL:
     * Return source key fields for translation by an AggregateObjectMapping
     */
    @Override
    public Collection getFieldsForTranslationInAggregate() {
        return getSourceToTargetKeyFields().keySet();
    }

    /**
     * Return the appropriate map that maps the "foreign keys"
     * to the "primary keys".
     */
    protected Map getForeignKeysToPrimaryKeys() {
        if (this.isForeignKeyRelationship()) {
            return this.getSourceToTargetKeyFields();
        } else {
            return this.getTargetToSourceKeyFields();
        }
    }


    /**
     * INTERNAL:
     * Return a Map of any foreign keys defined within the the MapKey
     * @return
     */
    @Override
    public Map<DatabaseField, DatabaseField> getForeignKeyFieldsForMapKey(){
        return getSourceToTargetKeyFields();
    }

    /**
     * INTERNAL:
     * Return the fields that make up the identity of the mapped object.  For mappings with
     * a primary key, it will be the set of fields in the primary key.  For mappings without
     * a primary key it will likely be all the fields
     * @return
     */
    @Override
    public List<DatabaseField> getIdentityFieldsForMapKey(){
        return getForeignKeyFields();
    }


    /**
     * INTERNAL:
     * Return the query that is used when this mapping is part of a joined relationship
     *
     * This method is used when this mapping is used to map the key in a Map
     */
    @Override
    public ObjectLevelReadQuery getNestedJoinQuery(JoinedAttributeManager joinManager, ObjectLevelReadQuery query, AbstractSession session){
        return prepareNestedJoins(joinManager, query, session);
    }

    /**
     * INTERNAL:
     * Get all the fields for the map key
     */
    @Override
    public List<DatabaseField> getAllFieldsForMapKey(){
        List<DatabaseField> fields = new ArrayList(getReferenceDescriptor().getAllSelectionFields().size() + getForeignKeyFields().size());
        fields.addAll(getReferenceDescriptor().getAllSelectionFields());
        fields.addAll(getForeignKeyFields());
        return fields;
    }

    /**
     * INTERNAL:
     * Return a vector of the foreign key fields in the same order
     * as the corresponding primary key fields are in their descriptor.
     */
    public Vector getOrderedForeignKeyFields() {
        List primaryKeyFields = getPrimaryKeyDescriptor().getPrimaryKeyFields();
        Vector result = new Vector(primaryKeyFields.size());

        for (int index = 0; index < primaryKeyFields.size(); index++) {
            DatabaseField pkField = (DatabaseField)primaryKeyFields.get(index);
            boolean found = false;
            for (Iterator fkStream = this.getForeignKeysToPrimaryKeys().keySet().iterator();
                     fkStream.hasNext();) {
                DatabaseField fkField = (DatabaseField)fkStream.next();

                if (this.getForeignKeysToPrimaryKeys().get(fkField).equals(pkField)) {
                    found = true;
                    result.addElement(fkField);
                    break;
                }
            }
            if (!found) {
                throw DescriptorException.missingForeignKeyTranslation(this, pkField);
            }
        }
        return result;
    }

    /**
     * Return the descriptor for whichever side of the
     * relation has the "primary key".
    */
    protected ClassDescriptor getPrimaryKeyDescriptor() {
        if (this.isForeignKeyRelationship()) {
            return this.getReferenceDescriptor();
        } else {
            return this.getDescriptor();
        }
    }

    /**
     * INTERNAL:
     * The private owned criteria is only used outside of the unit of work to compare the previous value of the reference.
     */
    public Expression getPrivateOwnedCriteria() {
        if (privateOwnedCriteria == null) {
            initializePrivateOwnedCriteria();
        }
        return privateOwnedCriteria;
    }

    /**
     * INTERNAL:
     * Return a collection of the source to target field value associations.
     */
    public Vector getSourceToTargetKeyFieldAssociations() {
        Vector associations = new Vector(getSourceToTargetKeyFields().size());
        Iterator sourceFieldEnum = getSourceToTargetKeyFields().keySet().iterator();
        Iterator targetFieldEnum = getSourceToTargetKeyFields().values().iterator();
        while (sourceFieldEnum.hasNext()) {
            Object fieldValue = ((DatabaseField)sourceFieldEnum.next()).getQualifiedName();
            Object attributeValue = ((DatabaseField)targetFieldEnum.next()).getQualifiedName();
            associations.addElement(new Association(fieldValue, attributeValue));
        }

        return associations;
    }

    /**
     * INTERNAL:
     * Returns the source keys to target keys fields association.
     */
    public Map<DatabaseField, DatabaseField> getSourceToTargetKeyFields() {
        return sourceToTargetKeyFields;
    }

    /**
     * INTERNAL:
     * Returns the target keys to source keys fields association.
     */
    public Map<DatabaseField, DatabaseField> getTargetToSourceKeyFields() {
        return targetToSourceKeyFields;
    }

    /**
     * INTERNAL:
     * If required, get the targetVersion of the source object from the merge manager
     *
     * Used with MapKeyContainerPolicy to abstract getting the target version of a source key
     * @return
     */
    @Override
    public Object getTargetVersionOfSourceObject(Object object, Object parent, MergeManager mergeManager, AbstractSession targetSession){
       return  mergeManager.getTargetVersionOfSourceObject(object, referenceDescriptor, targetSession);
    }

    /**
     * INTERNAL:
     * Return the class this key mapping maps or the descriptor for it
     * @return
     */
    @Override
    public Class getMapKeyTargetType(){
        return getReferenceClass();
    }

    /**
     * INTERNAL:
     * Initialize the mapping.
     */
    @Override
    public void initialize(AbstractSession session) throws DescriptorException {
        if (session.hasBroker()) {
            if (getReferenceClass() == null) {
                throw DescriptorException.referenceClassNotSpecified(this);
            }
            // substitute session that owns the mapping for the session that owns reference descriptor.
            session = session.getBroker().getSessionForClass(getReferenceClass());
        }

        super.initialize(session);
        if (isForeignKeyRelationship() && !isMapKeyMapping()) {
            getDescriptor().addPreDeleteMapping(this);
        }

        // Capture our foreign key field specifications here. We need to build
        // the fields first to ensure they have a table associated with them.
        // Also must be careful to not set the flags based on a previously
        // built field (multiple mappings to the same field) since we need to
        // capture the flags from the field set directly on this mapping.
        for (DatabaseField field : getForeignKeyFields()) {
            DatabaseField builtField = getDescriptor().buildField(field, keyTableForMapKey);

            if (builtField == field || builtField.isTranslated()) {
                // same instance or translated, look at the built field.
                updateInsertableAndUpdatableFields(builtField);
            } else {
                // previously built field and not translated, look at the original field.
                updateInsertableAndUpdatableFields(field);
            }
        }

        if (this.mechanism != null) {
            if (this.mechanism.hasRelationTable()) {
                if(!this.foreignKeyFields.isEmpty() || !this.sourceToTargetKeyFields.isEmpty() || !this.targetToSourceKeyFields.isEmpty()) {
                    throw DescriptorException.oneToOneMappingConflict(this.getDescriptor(), this);
                }
                this.foreignKeyFields = null;
                this.sourceToTargetKeyFields = null;
                this.targetToSourceKeyFields = null;

                this.mechanism.initialize(session, this);
            } else {
                this.mechanism = null;
            }
        }

        if (this.mechanism == null) {
            // Must set table of foreign keys.
            for (int index = 0; index < getForeignKeyFields().size(); index++) {
                DatabaseField foreignKeyField = getForeignKeyFields().get(index);
                foreignKeyField = getDescriptor().buildField(foreignKeyField, keyTableForMapKey);
                getForeignKeyFields().set(index, foreignKeyField);
            }

            // If only a selection criteria is specified then the foreign keys do not have to be initialized.
            if (!(getTargetToSourceKeyFields().isEmpty() && getSourceToTargetKeyFields().isEmpty())) {
                if (getTargetToSourceKeyFields().isEmpty() || getSourceToTargetKeyFields().isEmpty()) {
                    initializeForeignKeysWithDefaults(session);
                } else {
                    initializeForeignKeys(session);
                }
            }

            // Check if any foreign keys reference a secondary table.
            if (getReferenceDescriptor().getTables().size() > 1) {
                DatabaseTable firstTable = getReferenceDescriptor().getTables().get(0);
                for (DatabaseField field : getSourceToTargetKeyFields().values()) {
                    if (!field.getTable().equals(firstTable)) {
                        getReferenceDescriptor().setHasMultipleTableConstraintDependecy(true);
                    }
                }
            }

            // Check if any foreign keys reference a secondary table.
            if (getDescriptor().getTables().size() > 1) {
                DatabaseTable firstTable = getDescriptor().getTables().get(0);
                for (DatabaseField field : getSourceToTargetKeyFields().keySet()) {
                    if (!field.getTable().equals(firstTable)) {
                        getDescriptor().setHasMultipleTableConstraintDependecy(true);
                    }
                }
            }
        }

        if (shouldInitializeSelectionCriteria()) {
            if (shouldForceInitializationOfSelectionCriteria()) {
                setSelectionCriteria(buildSelectionCriteria());
            } else {
                setSelectionCriteria(buildSelectionCriteria(true, true));
            }
        } else {
            setShouldVerifyDelete(false);
        }

        setFields(collectFields());
    }

    /**
     * INTERNAL:
     * The foreign keys primary keys are stored as database fields in the map.
     */
    protected void initializeForeignKeys(AbstractSession session) {
        HashMap<DatabaseField, DatabaseField> newSourceToTargetKeyFields = new HashMap(getSourceToTargetKeyFields().size());
        HashMap<DatabaseField, DatabaseField> newTargetToSourceKeyFields = new HashMap(getTargetToSourceKeyFields().size());
        Iterator<Map.Entry<DatabaseField, DatabaseField>> iterator = getSourceToTargetKeyFields().entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<DatabaseField, DatabaseField> entry = iterator.next();
            DatabaseField sourceField = entry.getKey();
            sourceField = getDescriptor().buildField(sourceField, keyTableForMapKey);
            if (usesIndirection()) {
                sourceField.setKeepInRow(true);
            }
            DatabaseField targetField = entry.getValue();
            targetField = getReferenceDescriptor().buildField(targetField, keyTableForMapKey);
            newSourceToTargetKeyFields.put(sourceField, targetField);
            newTargetToSourceKeyFields.put(targetField, sourceField);
        }
        setSourceToTargetKeyFields(newSourceToTargetKeyFields);
        setTargetToSourceKeyFields(newTargetToSourceKeyFields);
    }

    /**
     * INTERNAL:
     * The foreign keys primary keys are stored as database fields in the map.
     */
    protected void initializeForeignKeysWithDefaults(AbstractSession session) {
        if (isForeignKeyRelationship()) {
            if (getSourceToTargetKeyFields().size() != 1) {
                throw DescriptorException.foreignKeysDefinedIncorrectly(this);
            }
            List<DatabaseField> targetKeys = getReferenceDescriptor().getPrimaryKeyFields();
            if (targetKeys.size() != 1) {
                //target and source keys are not the same size.
                throw DescriptorException.sizeMismatchOfForeignKeys(this);
            }

            //grab the only element out of the map
            DatabaseField sourceField = getSourceToTargetKeyFields().keySet().iterator().next();
            sourceField = getDescriptor().buildField(sourceField);
            if (usesIndirection()) {
                sourceField.setKeepInRow(true);
            }
            getSourceToTargetKeyFields().clear();
            getTargetToSourceKeyFields().clear();
            getSourceToTargetKeyFields().put(sourceField, targetKeys.get(0));
            getTargetToSourceKeyFields().put(targetKeys.get(0), sourceField);
        } else {
            if (getTargetToSourceKeyFields().size() != 1) {
                throw DescriptorException.foreignKeysDefinedIncorrectly(this);
            }
            List<DatabaseField> sourceKeys = getDescriptor().getPrimaryKeyFields();
            if (sourceKeys.size() != 1) {
                //target and source keys are not the same size.
                throw DescriptorException.sizeMismatchOfForeignKeys(this);
            }

            //grab the only element out of the map
            DatabaseField targetField = getTargetToSourceKeyFields().keySet().iterator().next();
            targetField = getReferenceDescriptor().buildField(targetField);
            getSourceToTargetKeyFields().clear();
            getTargetToSourceKeyFields().clear();
            getTargetToSourceKeyFields().put(targetField, sourceKeys.get(0));
            getSourceToTargetKeyFields().put(sourceKeys.get(0), targetField);
        }
    }

    /**
     * INTERNAL:
     * Selection criteria is created with source foreign keys and target keys.
     */
    protected void initializePrivateOwnedCriteria() {
        if (!isForeignKeyRelationship()) {
            setPrivateOwnedCriteria(getSelectionCriteria());
        } else {
            Expression pkCriteria = getDescriptor().getObjectBuilder().getPrimaryKeyExpression();
            ExpressionBuilder builder = new ExpressionBuilder();
            Expression backRef = builder.getManualQueryKey(getAttributeName() + "-back-ref", getDescriptor());
            Expression newPKCriteria = pkCriteria.rebuildOn(backRef);
            Expression twistedSelection = backRef.twist(getSelectionCriteria(), builder);
            if (getDescriptor().getQueryManager().getAdditionalJoinExpression() != null) {
                // We don't have to twist the additional join because it's all against the same node, which is our base
                // but we do have to rebuild it onto the manual query key
                Expression rebuiltAdditional = getDescriptor().getQueryManager().getAdditionalJoinExpression().rebuildOn(backRef);
                if (twistedSelection == null) {
                    twistedSelection = rebuiltAdditional;
                } else {
                    twistedSelection = twistedSelection.and(rebuiltAdditional);
                }
            }
            setPrivateOwnedCriteria(newPKCriteria.and(twistedSelection));
        }
    }

    /**
     * INTERNAL:
     * Making any mapping changes necessary to use a the mapping as a map key prior to initializing the mapping
     */
    @Override
    public void preinitializeMapKey(DatabaseTable table) throws DescriptorException {
        keyTableForMapKey = table;
    }

    /**
     * INTERNAL:
     * Need to set the field type for the foreign key fields for a map key, as the fields are not contained in any descriptor.
     */
    @Override
    public void postInitializeMapKey(MappedKeyMapContainerPolicy policy) {
        for (DatabaseField foreignKey : getSourceToTargetKeyFields().keySet()) {
            if (foreignKey.getType() == null) {
                foreignKey.setType(getFieldClassification(foreignKey));
            }
        }
    }

    /**
     * INTERNAL:
     * Post-initialize source and target expression fields created when a mapping's selectionCriteria
     * is created early with only partly initialized fields.
     */
    @Override
    public void postInitializeSourceAndTargetExpressions() {
        // EL Bug 426500
        // postInitialize and set source expression fields using my descriptor
        if (this.sourceExpressionsToPostInitialize != null && this.sourceExpressionsToPostInitialize.size() > 0) {
            ClassDescriptor descriptor = getDescriptor();
            ObjectBuilder objectBuilder = descriptor.getObjectBuilder();
            for (Iterator<Expression> expressions = this.sourceExpressionsToPostInitialize.iterator(); expressions.hasNext();) {
                Expression expression = expressions.next();
                DatabaseField field = null;
                if (expression.isParameterExpression()) {
                    field = ((ParameterExpression)expression).getField();
                } else if (expression.isFieldExpression()) {
                    field = ((FieldExpression)expression).getField();
                }
                if (field != null && (field.getType() == null || field.getTypeName() == null)) {
                    field.setType(objectBuilder.getFieldClassification(field));
                }
            }
        }

        // postInitialize and set target expression fields using my reference descriptor
        if (this.targetExpressionsToPostInitialize != null && this.targetExpressionsToPostInitialize.size() > 0) {
            ClassDescriptor descriptor = getReferenceDescriptor();
            ObjectBuilder objectBuilder = descriptor.getObjectBuilder();
            for (Iterator<Expression> expressions = this.targetExpressionsToPostInitialize.iterator(); expressions.hasNext();) {
                Expression expression = expressions.next();
                DatabaseField field = null;
                if (expression.isParameterExpression()) {
                    field = ((ParameterExpression)expression).getField();
                } else if (expression.isFieldExpression()) {
                    field = ((FieldExpression)expression).getField();
                }
                if (field != null && (field.getType() == null || field.getTypeName() == null)) {
                    field.setType(objectBuilder.getFieldClassification(field));
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Prepare a cascade locking policy.
     */
    @Override
    public void prepareCascadeLockingPolicy() {
        CascadeLockingPolicy policy = new CascadeLockingPolicy(getDescriptor(), getReferenceDescriptor());
        policy.setQueryKeyFields(getSourceToTargetKeyFields(), ! isForeignKeyRelationship());
        getReferenceDescriptor().addCascadeLockingPolicy(policy);
    }

    /**
     * This method would allow customers to get the potential selection criteria for a mapping
     * prior to initialization.  This would allow them to more easily create an amendment method
     * that would amend the SQL for the join.
     */
    public Expression buildSelectionCriteria() {
        return buildSelectionCriteria(true, false);
    }

    /**
     * INTERNAL:
     * Build the selection criteria for this mapping.  Allows several variations.
     *
     * Either a parameter can be used for the join or simply the database field
     *
     * The existing selection criteria can be built upon or a whole new criteria can be built.
     */
    public Expression buildSelectionCriteria(boolean useParameter, boolean usePreviousSelectionCriteria){
        Expression criteria = null;
        if (usePreviousSelectionCriteria){
            criteria = getSelectionCriteria();
        }

        if(this.mechanism == null) {
            Expression builder = new ExpressionBuilder();
            // CR3922
            if (getSourceToTargetKeyFields().isEmpty()) {
                throw DescriptorException.noForeignKeysAreSpecified(this);
            }

            for (Iterator keys = getSourceToTargetKeyFields().keySet().iterator(); keys.hasNext();) {
                DatabaseField foreignKey = (DatabaseField)keys.next();
                DatabaseField targetKey = getSourceToTargetKeyFields().get(foreignKey);

                Expression targetKeyExpression = builder.getField(targetKey);
                Expression sourceKeyExpression = null;

                if (useParameter){
                    sourceKeyExpression = builder.getParameter(foreignKey);
                } else {
                    sourceKeyExpression = builder.getField(foreignKey);
                }

                if (usePreviousSelectionCriteria == false) {
                    this.sourceExpressionsToPostInitialize.add(sourceKeyExpression);
                    this.targetExpressionsToPostInitialize.add(targetKeyExpression);
                }

                Expression expression = targetKeyExpression.equal(sourceKeyExpression);
                criteria = expression.and(criteria);
            }
        } else {
            criteria = this.mechanism.buildSelectionCriteria(this, criteria);
        }
        return criteria;
    }

    /**
     * INTERNAL:
     * Builds a shallow original object.  Only direct attributes and primary
     * keys are populated.  In this way the minimum original required for
     * instantiating a working copy clone can be built without placing it in
     * the shared cache (no concern over cycles).
     */
    @Override
    public void buildShallowOriginalFromRow(AbstractRecord databaseRow, Object original, JoinedAttributeManager joinManager, ObjectBuildingQuery query, AbstractSession executionSession) {
        // Now we are only building this original so we can extract the primary
        // key out of it.  If the primary key is stored across a 1-1 a value
        // holder needs to be built/triggered to get at it.
        // In this case recursively build the shallow original across the 1-1.
        // We only need the primary key for that object, and we know
        // what that primary key is: it is the foreign key in our row.
        ClassDescriptor descriptor = getReferenceDescriptor();
        AbstractRecord targetRow = new DatabaseRecord();

        for (Iterator keys = getSourceToTargetKeyFields().keySet().iterator(); keys.hasNext();) {
            DatabaseField foreignKey = (DatabaseField)keys.next();
            DatabaseField targetKey = getSourceToTargetKeyFields().get(foreignKey);

            targetRow.put(targetKey, databaseRow.get(foreignKey));
        }

        Object targetObject = descriptor.getObjectBuilder().buildNewInstance();
        descriptor.getObjectBuilder().buildAttributesIntoShallowObject(targetObject, databaseRow, query);
        targetObject = getIndirectionPolicy().valueFromRow(targetObject);

        setAttributeValueInObject(original, targetObject);
    }

    /**
     * INTERNAL:
     */
    @Override
    public boolean isOneToOneMapping() {
        return true;
    }

    /**
     * INTERNAL:
     */
    @Override
    public boolean isOwned(){
        return this.hasRelationTable() && ! this.isReadOnly;
    }

    /**
     * INTERNAL:
     * Reads the private owned object.
     */
    @Override
    protected Object readPrivateOwnedForObject(ObjectLevelModifyQuery modifyQuery) throws DatabaseException {
        if (modifyQuery.getSession().isUnitOfWork()) {
            return super.readPrivateOwnedForObject(modifyQuery);
        } else {
            if (!shouldVerifyDelete()) {
                return null;
            }
            ReadObjectQuery readQuery = (ReadObjectQuery)getSelectionQuery().clone();

            readQuery.setSelectionCriteria(getPrivateOwnedCriteria());
            return modifyQuery.getSession().executeQuery(readQuery, modifyQuery.getTranslationRow());
        }
    }

    /**
     * INTERNAL:
     * Rehash any map based on fields.
     * This is used to clone descriptors for aggregates, which hammer field names,
     * it is probably better not to hammer the field name and this should be refactored.
     */
    @Override
    public void rehashFieldDependancies(AbstractSession session) {
        setSourceToTargetKeyFields(Helper.rehashMap(getSourceToTargetKeyFields()));

        // Go through the fks again and make updates for any translated fields.
        for (DatabaseField field : getSourceToTargetKeyFields().keySet()) {
            if (field.isTranslated()) {
                updateInsertableAndUpdatableFields(field);
            }
        }
    }

    /**
     * INTERNAL:
     * Return whether this mapping requires extra queries to update the rows if it is
     * used as a key in a map.  This will typically be true if there are any parts to this mapping
     * that are not read-only.
     */
    @Override
    public boolean requiresDataModificationEventsForMapKey() {
        return true;
    }

    /**
     * Return if this mapping is really for a OneToOne relationship.
     * This is a backward compatibility issue, in that before the ManyToOneMapping
     * was created OneToOneMapping was used for both.
     * false means it may be a OneToOne or a ManyToOne (unknown).
     */
    public boolean isOneToOneRelationship() {
        return isOneToOneRelationship;
    }

    /**
     * Return if this mapping is mapped using primary key join columns.
     */
    public boolean isOneToOnePrimaryKeyRelationship() {
        return isOneToOnePrimaryKeyRelationship;
    }

    /**
     * Define if this mapping is really for a OneToOne relationship.
     * This is a backward compatibility issue, in that before the ManyToOneMapping
     * was created OneToOneMapping was used for both.
     */
    public void setIsOneToOneRelationship(boolean isOneToOneRelationship) {
        this.isOneToOneRelationship = isOneToOneRelationship;
    }

    /**
     * Set if this mapping is defined using primary key join columns.
     */
    public void setIsOneToOnePrimaryKeyRelationship(boolean isOneToOnePrimaryKeyRelationship) {
        this.isOneToOnePrimaryKeyRelationship = isOneToOnePrimaryKeyRelationship;
    }

    /**
     * PUBLIC:
     * Define the foreign key relationship in the 1-1 mapping.
     * This method is used for singleton foreign key relationships only,
     * that is the source object's table has a foreign key field to
     * the target object's primary key field.
     * Only the source foreign key field name is specified.
     * When a foreign key is specified TopLink will automatically populate the value
     * for that field from the target object when the object is written to the database.
     * If the foreign key is also mapped through a direct-to-field then the direct-to-field must
     * be set read-only.
     */
    public void setForeignKeyFieldName(String sourceForeignKeyFieldName) {
        DatabaseField sourceField = new DatabaseField(sourceForeignKeyFieldName);

        setIsForeignKeyRelationship(true);
        getForeignKeyFields().addElement(sourceField);
        getSourceToTargetKeyFields().put(sourceField, new DatabaseField());
    }

    /**
     * PUBLIC:
     * Return the foreign key field names associated with the mapping.
     * These are only the source fields that are writable.
     */
    public void setForeignKeyFieldNames(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()));
        }

        setForeignKeyFields(fields);
    }

    /**
     * INTERNAL:
     * Private owned criteria is used to verify the deletion of the target.
     * It joins from the source table on the foreign key to the target table,
     * with a parameterization of the primary key of the source object.
     */
    protected void setPrivateOwnedCriteria(Expression expression) {
        privateOwnedCriteria = expression;
    }

    /**
     * PUBLIC:
     * Verify delete is used during delete and update on private 1:1's outside of a unit of work only.
     * It checks for the previous value of the target object through joining the source and target tables.
     * By default it is always done, but may be disabled for performance on distributed database reasons.
     * In the unit of work the previous value is obtained from the backup-clone so it is never used.
     */
    public void setShouldVerifyDelete(boolean shouldVerifyDelete) {
        this.shouldVerifyDelete = shouldVerifyDelete;
    }

    /**
     * INTERNAL:
     * Set a collection of the source to target field associations.
     */
    public void setSourceToTargetKeyFieldAssociations(Vector sourceToTargetKeyFieldAssociations) {
        setSourceToTargetKeyFields(new HashMap(sourceToTargetKeyFieldAssociations.size() + 1));
        setTargetToSourceKeyFields(new HashMap(sourceToTargetKeyFieldAssociations.size() + 1));
        for (Enumeration associationsEnum = sourceToTargetKeyFieldAssociations.elements();
                 associationsEnum.hasMoreElements();) {
            Association association = (Association)associationsEnum.nextElement();
            DatabaseField sourceField = new DatabaseField((String)association.getKey());
            DatabaseField targetField = new DatabaseField((String)association.getValue());
            getSourceToTargetKeyFields().put(sourceField, targetField);
            getTargetToSourceKeyFields().put(targetField, sourceField);
        }
    }

    /**
     * INTERNAL:
     * Set the source keys to target keys fields association.
     */
    public void setSourceToTargetKeyFields(Map<DatabaseField, DatabaseField> sourceToTargetKeyFields) {
        this.sourceToTargetKeyFields = sourceToTargetKeyFields;
    }

    /**
     * PUBLIC:
     * Define the target foreign key relationship in the 1-1 mapping.
     * This method is used for singleton target foreign key relationships only,
     * that is the target object's table has a foreign key field to
     * the source object's primary key field.
     * The target foreign key field name is specified.
     * The distinction between a foreign key and target foreign key is that the 1-1
     * mapping will not populate the target foreign key value when written (because it is in the target table).
     * Normally 1-1's are through foreign keys but in bi-directional 1-1's
     * the back reference will be a target foreign key.
     */
    public void setTargetForeignKeyFieldName(String targetForeignKeyFieldName) {
        DatabaseField targetField = new DatabaseField(targetForeignKeyFieldName);
        getTargetToSourceKeyFields().put(targetField, new DatabaseField());
    }

    /**
     * INTERNAL:
     * Set the target keys to source keys fields association.
     */
    public void setTargetToSourceKeyFields(Map<DatabaseField, DatabaseField> targetToSourceKeyFields) {
        this.targetToSourceKeyFields = targetToSourceKeyFields;
    }


    /**
     * PUBLIC:
     * Verify delete is used during delete and update outside of a unit of work only.
     * It checks for the previous value of the target object through joining the source and target tables.
     */
    public boolean shouldVerifyDelete() {
        return shouldVerifyDelete;
    }

    /**
     * INTERNAL:
     * By default returns true. Will also return true if:
     * 1 - WriteType is INSERT and the field is insertable.
     * 2 - WriteType is UPDATE and the field is updatable.
     */
    protected boolean shouldWriteField(DatabaseField field, WriteType writeType) {
        if (writeType.equals(WriteType.INSERT)) {
            return insertableFields.contains(field);
        } else if (writeType.equals(WriteType.UPDATE)) {
            return updatableFields.contains(field);
        } else {
            return true; // UNDEFINED, default is to write.
        }
    }

    /**
     * INTERNAL
     * Return true if this mapping supports cascaded version optimistic locking.
     */
    @Override
    public boolean isCascadedLockingSupported() {
        return true;
    }

    /**
     * INTERNAL:
     * Return if this mapping support joining.
     */
    @Override
    public boolean isJoiningSupported() {
        return true;
    }

    /**
     * INTERNAL:
     * Called when iterating through descriptors to handle iteration on this mapping when it is used as a MapKey
     */
    @Override
    public void iterateOnMapKey(DescriptorIterator iterator, Object element){
        this.getIndirectionPolicy().iterateOnAttributeValue(iterator, element);
    }

    /**
     * INTERNAL:
     * Allow the key mapping to unwrap the object.
     */
    @Override
    public Object unwrapKey(Object key, AbstractSession session){
        return getDescriptor().getObjectBuilder().unwrapObject(key, session);
    }

    /**
     * INTERNAL:
     * Add the field to the updatable and/or insertable list. Remove any
     * previous field under the same name, otherwise shouldn't matter if we
     * leave an old name (before translation) in the list as it should 'never'
     * be used anyway.
     */
    protected void updateInsertableAndUpdatableFields(DatabaseField field) {
        insertableFields.remove(field);
        updatableFields.remove(field);

        if (field.isInsertable()) {
            insertableFields.add(field);
        }

        if (field.isUpdatable()) {
            updatableFields.add(field);
        }
    }

    /**
     * INTERNAL:
     * Allow the key mapping to wrap the object.
     */
    @Override
    public Object wrapKey(Object key, AbstractSession session){
        return getDescriptor().getObjectBuilder().wrapObject(key, session);
    }

    /**
     * INTERNAL:
     * A subclass should implement this method if it wants different behavior.
     * Write the foreign key values from the attribute to the row.
     */
    @Override
    public void writeFromAttributeIntoRow(Object attribute, AbstractRecord row, AbstractSession session)
    {
          for (Enumeration fieldsEnum = getForeignKeyFields().elements(); fieldsEnum.hasMoreElements();) {
                  DatabaseField sourceKey = (DatabaseField) fieldsEnum.nextElement();
                  DatabaseField targetKey = getSourceToTargetKeyFields().get(sourceKey);
                  Object referenceValue = null;
                          // If privately owned part is null then method cannot be invoked.
                  if (attribute != null) {
                          referenceValue = getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(attribute, targetKey, session);
                  }
                  row.add(sourceKey, referenceValue);
          }
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     */
    @Override
    public Object valueFromObject(Object object, DatabaseField field, AbstractSession session) {
        // First check if the value can be obtained from the value holder's row.
        Object attributeValue = getAttributeValueFromObject(object);
        AbstractRecord referenceRow = this.indirectionPolicy.extractReferenceRow(attributeValue);
        if (referenceRow != null) {
            Object value = referenceRow.get(field);
            Class type = getFieldClassification(field);
            if ((value == null) || (value.getClass() != type)) {
                // Must ensure the classification to get a cache hit.
                try {
                    value = session.getDatasourcePlatform().convertObject(value, type);
                } catch (ConversionException exception) {
                    throw ConversionException.couldNotBeConverted(this, getDescriptor(), exception);
                }
            }
            return value;
        }

        Object referenceObject = getRealAttributeValueFromAttribute(attributeValue, object, session);
        if (referenceObject == null) {
            return null;
        }
        DatabaseField targetField;
        if(this.mechanism == null) {
            targetField = this.sourceToTargetKeyFields.get(field);
        } else {
            targetField = this.mechanism.targetKeyFields.get(this.mechanism.sourceKeyFields.indexOf(field));
        }

        return this.referenceDescriptor.getObjectBuilder().extractValueFromObjectForField(referenceObject, targetField, session);
    }

    /**
     * INTERNAL:
     * Return the value of the field from the row or a value holder on the query to obtain the object.
     * Check for batch + aggregation reading.
     */
    @Override
    protected Object valueFromRowInternalWithJoin(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, CacheKey parentCacheKey, AbstractSession executionSession, boolean isTargetProtected) throws DatabaseException {
        // PERF: Direct variable access.
        Object referenceObject;
        // CR #... the field for many objects may be in the row,
        // so build the subpartion of the row through the computed values in the query,
        // this also helps the field indexing match.
        AbstractRecord targetRow = trimRowForJoin(row, joinManager, executionSession);
        // PERF: Only check for null row if an outer-join was used.
        if (((joinManager != null) && joinManager.hasOuterJoinedAttributeQuery()) && !sourceQuery.hasPartialAttributeExpressions()) {
            Object key = this.referenceDescriptor.getObjectBuilder().extractPrimaryKeyFromRow(targetRow, executionSession);
            if (key == null) {
                return this.indirectionPolicy.nullValueFromRow();
            }
        }
        // A nested query must be built to pass to the descriptor that looks like the real query execution would,
        // these should be cached on the query during prepare.
        ObjectLevelReadQuery nestedQuery = prepareNestedJoinQueryClone(row, null, joinManager, sourceQuery, executionSession);
        nestedQuery.setTranslationRow(targetRow);
        nestedQuery.setRequiresDeferredLocks(sourceQuery.requiresDeferredLocks());
        nestedQuery.setPrefetchedCacheKeys(sourceQuery.getPrefetchedCacheKeys());
        nestedQuery.setShouldRefreshIdentityMapResult(sourceQuery.shouldRefreshIdentityMapResult());
        referenceObject = this.referenceDescriptor.getObjectBuilder().buildObject(nestedQuery, targetRow);

        // For bug 3641713 buildObject doesn't wrap if called on a UnitOfWork for performance reasons,
        // must wrap here as this is the last time we can look at the query and tell whether to wrap or not.
        if (nestedQuery.shouldUseWrapperPolicy() && executionSession.isUnitOfWork()) {
            referenceObject = this.referenceDescriptor.getObjectBuilder().wrapObject(referenceObject, executionSession);
        }
        return this.indirectionPolicy.valueFromRow(referenceObject);
    }

    /**
     * INTERNAL:
     * Return the value of the field from the row or a value holder on the query to obtain the object.
     * Check for batch + aggregation reading.
     */
    @Override
    protected Object valueFromRowInternal(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, AbstractSession executionSession, boolean shouldUseSopObject) throws DatabaseException {
        // If any field in the foreign key is null then it means there are no referenced objects
        // Skip for partial objects as fk may not be present.
        if (!shouldUseSopObject) {
            int size = this.fields.size();
            for (int index = 0; index < size; index++) {
                DatabaseField field = this.fields.get(index);
                if (row.get(field) == null) {
                    return this.indirectionPolicy.nullValueFromRow();
                }
            }
        }

        // Call the default which executes the selection query,
        // or wraps the query with a value holder.
        return super.valueFromRowInternal(row, joinManager, sourceQuery, executionSession, shouldUseSopObject);
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     */
    @Override
    public void writeFromObjectIntoRow(Object object, AbstractRecord databaseRow, AbstractSession session, WriteType writeType) {
        if (this.isReadOnly || (!this.isForeignKeyRelationship)) {
            return;
        }
        writeFromObjectIntoRowInternal(object, databaseRow, session, null, writeType);
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     * The fields and the values added to the row depend on ShallowMode mode:
     *   null - all fields with their values from object;
     *   Insert - nullable fields added with value null, non nullable fields added with their values from object;
     *   UpdateAfterInsert - nullable fields added with with their non-null values from object, non nullable fields (and nullable with null values) are ignored;
     *   UpdateBeforeDelete - the same fields as for UpdateAfterShallowInsert - but all values are nulls.
     */
    protected void writeFromObjectIntoRowInternal(Object object, AbstractRecord databaseRow, AbstractSession session, ShallowMode mode, WriteType writeType) {
        List<DatabaseField> foreignKeyFields = getForeignKeyFields();
        if (mode != null) {
            List<DatabaseField> nonNullableFields = null;

            for (DatabaseField field : foreignKeyFields) {
                if (field.isNullable()) {
                    if (mode == ShallowMode.Insert && shouldWriteField(field, writeType)) {
                        // add a nullable field with a null value
                        databaseRow.add(field, null);
                    }
                } else {
                    if (nonNullableFields == null) {
                        nonNullableFields = new ArrayList<>();
                    }

                    nonNullableFields.add(field);
                }
            }

            if (nonNullableFields == null) {
                // all foreignKeyFields are nullable
                if (mode == ShallowMode.Insert) {
                    // nothing else to do
                    return;
                }
                // UpdateAfterInsert or UpdateBeforeDelete: all nullable foreignKeyFields will be processed
            } else {
                if (mode == ShallowMode.Insert) {
                    // all non nullable foreignKeyFields will be processed
                    foreignKeyFields = nonNullableFields;
                } else {
                    // UpdateAfterInsert or UpdateBeforeDelete
                    if (foreignKeyFields.size() == nonNullableFields.size()) {
                        // all fields are non nullable - nothing else to do
                        return;
                    } else {
                        // all nullable foreignKeyFields will be processed
                        foreignKeyFields = new ArrayList<>(foreignKeyFields);
                        foreignKeyFields.removeAll(nonNullableFields);
                    }
                }
            }
        }

        Object attributeValue = getAttributeValueFromObject(object);
        // If the value holder has the row, avoid instantiation and just use it.
        AbstractRecord referenceRow = this.indirectionPolicy.extractReferenceRow(attributeValue);
        if (referenceRow == null) {
            // Extract from object.
            Object referenceObject = getRealAttributeValueFromAttribute(attributeValue, object, session);

            for (DatabaseField sourceKey : foreignKeyFields) {
                Object referenceValue = null;

                // If privately owned part is null then method cannot be invoked.
                if (referenceObject != null) {
                    DatabaseField targetKey = this.sourceToTargetKeyFields.get(sourceKey);
                    referenceValue = this.referenceDescriptor.getObjectBuilder().extractValueFromObjectForField(referenceObject, targetKey, session);
                }

                if (mode == null) {
                    // EL Bug 319759 - if a field is null, then the update call cache should not be used
                    if (referenceValue == null) {
                        databaseRow.setNullValueInFields(true);
                    }
                } else {
                    if (referenceValue == null) {
                        if (mode != ShallowMode.Insert) {
                            // both UpdateAfterInsert and UpdateBeforeDelete ignore null values
                            continue;
                        }
                    } else {
                        if (mode == ShallowMode.UpdateBeforeDelete) {
                            // UpdateBeforeDelete adds nulls instead of non nulls
                            referenceValue = null;
                        }
                    }
                }

                // Check updatable and insertable based on the write type.
                if (shouldWriteField(sourceKey, writeType)) {
                    databaseRow.add(sourceKey, referenceValue);
                }
            }
        } else {
            for (DatabaseField sourceKey : foreignKeyFields) {
                Object referenceValue = referenceRow.get(sourceKey);

                if (mode == null) {
                    // EL Bug 319759 - if a field is null, then the update call cache should not be used
                    if (referenceValue == null) {
                        databaseRow.setNullValueInFields(true);
                    }
                } else {
                    if (referenceValue == null) {
                        if (mode != ShallowMode.Insert) {
                            // both UpdateAfterInsert and UpdateBeforeDelete ignore null values
                            continue;
                        }
                    } else {
                        if (mode == ShallowMode.UpdateBeforeDelete) {
                            // UpdateBeforeDelete adds nulls instead of non nulls
                            referenceValue = null;
                        }
                    }
                }

                // Check updatable and insertable based on the write type.
                if (shouldWriteField(sourceKey, writeType)) {
                    databaseRow.add(sourceKey, referenceValue);
                }
            }
        }
    }

    /**
     * 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 databaseRow, AbstractSession session) {
        if (this.isReadOnly || (!this.isForeignKeyRelationship)) {
            return;
        }
        writeFromObjectIntoRowInternal(object, databaseRow, session, ShallowMode.Insert, WriteType.INSERT);
    }

    /**
     * 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.
     */
    @Override
    public void writeFromObjectIntoRowForUpdateAfterShallowInsert(Object object, AbstractRecord databaseRow, AbstractSession session, DatabaseTable table) {
        if (this.isReadOnly || (!this.isForeignKeyRelationship) || !getFields().get(0).getTable().equals(table) || isPrimaryKeyMapping()) {
            return;
        }
        writeFromObjectIntoRowInternal(object, databaseRow, session, ShallowMode.UpdateAfterInsert, WriteType.UNDEFINED);
    }

    /**
     * INTERNAL:
     * This row is built for update before shallow delete which happens in case of bidirectional inserts.
     * It contains the same fields as the row built by writeFromObjectIntoRowForUpdateAfterShallowInsert, but all the values are null.
     */
    @Override
    public void writeFromObjectIntoRowForUpdateBeforeShallowDelete(Object object, AbstractRecord databaseRow, AbstractSession session, DatabaseTable table) {
        if (this.isReadOnly || (!this.isForeignKeyRelationship) || !getFields().get(0).getTable().equals(table) || isPrimaryKeyMapping()) {
            return;
        }
        writeFromObjectIntoRowInternal(object, databaseRow, session, ShallowMode.UpdateBeforeDelete, WriteType.UNDEFINED);
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     * Validation preventing primary key updates is implemented here.
     */
    @Override
    public void writeFromObjectIntoRowWithChangeRecord(ChangeRecord changeRecord, AbstractRecord databaseRow, AbstractSession session, WriteType writeType) {
        if ((!this.isReadOnly) && this.isPrimaryKeyMapping && (!changeRecord.getOwner().isNew())) {
           throw ValidationException.primaryKeyUpdateDisallowed(changeRecord.getOwner().getClassName(), changeRecord.getAttribute());
        }

        // The object must be used here as the foreign key may include more than just the
        // primary key of the referenced object and the changeSet may not have the required information.
        Object object = ((ObjectChangeSet)changeRecord.getOwner()).getUnitOfWorkClone();
        writeFromObjectIntoRow(object, databaseRow, session, writeType);
    }

    /**
     * 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 databaseRow, AbstractSession session) {
        if (isReadOnly() || (!isForeignKeyRelationship())) {
            return;
        }

        for (Enumeration fieldsEnum = getForeignKeyFields().elements();
                 fieldsEnum.hasMoreElements();) {
            DatabaseField sourceKey = (DatabaseField)fieldsEnum.nextElement();
            databaseRow.add(sourceKey, null);
        }
    }

    /**
     * INTERNAL:
     * Write fields needed for insert into the template for with null values.
     */
    @Override
    public void writeInsertFieldsIntoRow(AbstractRecord databaseRow, AbstractSession session) {
        if (isReadOnly() || (!isForeignKeyRelationship())) {
            return;
        }

        for (Enumeration fieldsEnum = getForeignKeyFields().elements(); fieldsEnum.hasMoreElements();) {
            DatabaseField sourceKey = (DatabaseField)fieldsEnum.nextElement();

            if (shouldWriteField(sourceKey, WriteType.INSERT)) {
                databaseRow.add(sourceKey, null);
            }
        }
    }

    /**
     * PUBLIC:
     * Indicates whether the mapping has RelationTableMechanism.
     */
    @Override
    public boolean hasRelationTableMechanism() {
        return this.mechanism != null;
    }

    /**
     * PUBLIC:
     * Indicates whether the mapping has RelationTable.
     */
    public boolean hasRelationTable() {
        return this.mechanism != null && this.mechanism.hasRelationTable();
    }

    /**
     * PUBLIC:
     * Returns RelationTableMechanism that may be owned by the mapping,
     * that allows to configure the mapping to use relation table (just like ManyToManyMapping).
     * By default its null, should be created and set into the mapping before use.
     */
    public RelationTableMechanism getRelationTableMechanism() {
        return this.mechanism;
    }

    /**
     * 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.mechanism.setRelationTable(relationTable);
    }

    /**
     * PUBLIC:
     * Set RelationTableMechanism into the mapping,
     * that allows to configure the mapping to use relation table (just like ManyToManyMapping).
     */
    public void setRelationTableMechanism(RelationTableMechanism mechanism) {
        this.mechanism = mechanism;
    }

    /**
     * PUBLIC:
     * Return RelationTable.
     */
    public DatabaseTable getRelationTable() {
        if(this.mechanism != null) {
            return this.mechanism.getRelationTable();
        } else {
            return null;
        }
    }

    /**
     * INTERNAL:
     * Delete privately owned parts
     */
    @Override
    public void preDelete(DeleteObjectQuery query) throws DatabaseException, OptimisticLockException {
        if ((this.mechanism != null) && !this.isReadOnly && !this.isCascadeOnDeleteSetOnDatabase) {
            AbstractRecord sourceRow = this.mechanism.buildRelationTableSourceRow(query.getObject(), query.getSession(), this);
            query.getSession().executeQuery(this.mechanism.deleteQuery, sourceRow);
        }
        super.preDelete(query);
    }

    /**
     * INTERNAL:
     * Insert into relation table. This follows following steps.
     * <p>- Extract primary key and its value from the source object.
     * <p>- Extract target key and its value from the target object.
     * <p>- Construct a insert statement with above fields and values for relation table.
     * <p>- execute the statement.
     */
    @Override
    public void postInsert(WriteObjectQuery query) throws DatabaseException {
        super.postInsert(query);
        if(this.mechanism != null && !isReadOnly()) {
            Object targetObject = getRealAttributeValueFromObject(query.getObject(), query.getSession());
            if (targetObject == null) {
                return;
            }

            // Batch data modification in the uow
            if (query.shouldCascadeOnlyDependentParts()) {
                // Hey I might actually want to use an inner class here... ok array for now.
                Object[] event = new Object[3];
                event[0] = setObject;
                event[1] = this.mechanism.buildRelationTableSourceRow(query.getObject(), query.getSession(), this);
                // targetObject may not have pk yet - wait to extract targetRow until the event is processed
                event[2] = targetObject;
                query.getSession().getCommitManager().addDataModificationEvent(this, event);
            } else {
                AbstractRecord sourceAndTargetRow = this.mechanism.buildRelationTableSourceAndTargetRow(query.getObject(), targetObject, query.getSession(), this);
                query.getSession().executeQuery(this.mechanism.insertQuery, sourceAndTargetRow);
            }
        }
    }

    /**
     * INTERNAL:
     * Update the relation table with the entries related to this mapping.
     * Delete entries removed, insert entries added.
     * If private also insert/delete/update target objects.
     */
    @Override
    public void postUpdate(WriteObjectQuery query) throws DatabaseException {
        if(this.mechanism == null) {
            super.postUpdate(query);
        } else {
            // If object is not instantiated then it's not changed.
            if (!isAttributeValueInstantiated(query.getObject())) {
                return;
            }

            AbstractRecord sourceRow = null;
            if(!isReadOnly()) {
                sourceRow = this.mechanism.buildRelationTableSourceRow(query.getObject(), query.getSession(), this);
                query.getSession().executeQuery(this.mechanism.deleteQuery, sourceRow);
            }

            super.postUpdate(query);

            if(sourceRow != null) {
                Object targetObject = getRealAttributeValueFromObject(query.getObject(), query.getSession());
                if (targetObject == null) {
                    return;
                }
                // Batch data modification in the uow
                if (query.shouldCascadeOnlyDependentParts()) {
                    // Hey I might actually want to use an inner class here... ok array for now.
                    Object[] event = new Object[3];
                    event[0] = setObject;
                    event[1] = sourceRow;
                    // targetObject may not have pk yet - wait to extract targetRow until the event is processed
                    event[2] = targetObject;
                    query.getSession().getCommitManager().addDataModificationEvent(this, event);
                } else {
                    AbstractRecord sourceAndTargetRow = this.mechanism.addRelationTableTargetRow(targetObject, query.getExecutionSession(), sourceRow, this);
                    query.getSession().executeQuery(this.mechanism.insertQuery, sourceAndTargetRow);
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Perform the commit event.
     * This is used in the uow to delay data modifications.
     */
    @Override
    public void performDataModificationEvent(Object[] event, AbstractSession session) throws DatabaseException, DescriptorException {
        // Hey I might actually want to use an inner class here... ok array for now.
        if (event[0] == setObject) {
            AbstractRecord sourceAndTargetRow = this.mechanism.addRelationTableTargetRow(event[2], session, (AbstractRecord)event[1], this);
            session.executeQuery(this.mechanism.insertQuery, sourceAndTargetRow);
        } else {
            throw DescriptorException.invalidDataModificationEventCode(event[0], this);
        }
    }

    /**
     * INTERNAL:
     * Return all the fields populated by this mapping, these are foreign keys only.
     */
    @Override
    protected Vector<DatabaseField> collectFields() {
        if(this.mechanism != null) {
            return new Vector(0);
        } else {
            return super.collectFields();
        }
    }

    /**
     * INTERNAL:
     * Order by foreign key fields if a foreign key mapping (avoids joins).
     */
    @Override
    public List<Expression> getOrderByNormalizedExpressions(Expression base) {
        if (this.foreignKeyFields.size() > 0) {
            List<Expression> orderBys = new ArrayList(this.foreignKeyFields.size());
            for (DatabaseField field : this.foreignKeyFields) {
                orderBys.add(((QueryKeyExpression)base).getBaseExpression().getField(field));
            }
            return orderBys;
        }
        return super.getOrderByNormalizedExpressions(base);
    }
}
