/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.mappings;

import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.indirection.ValueHolder;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.NonSynchronizedVector;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.ChangeRecord;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.internal.sessions.ObjectReferenceChangeRecord;
import org.eclipse.persistence.mappings.querykeys.DirectQueryKey;
import org.eclipse.persistence.mappings.querykeys.QueryKey;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ObjectLevelModifyQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;

/**
 * <p><b>Purpose</b>: Variable one to one mappings are used to represent a pointer references
 * between a java object and an implementer of an interface. This mapping 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 a foreign key and a type code.
 *
 * @author Sati
 * @since TOPLink/Java 2.0
 */
public class VariableOneToOneMapping extends ObjectReferenceMapping implements RelationalMapping {
    protected DatabaseField typeField;
    protected Map sourceToTargetQueryKeyNames;
    protected Map typeIndicatorTranslation;

    /** parallel table typeIndicatorTranslation used prior to initialization to avoid type indicators on Mapping Workbench */
    protected Map typeIndicatorNameTranslation;

    /**
     * PUBLIC:
     * Default constructor.
     */
    public VariableOneToOneMapping() {
        this.selectionQuery = new ReadObjectQuery();
        this.sourceToTargetQueryKeyNames = new HashMap(2);
        this.typeIndicatorTranslation = new HashMap(5);
        this.typeIndicatorNameTranslation = new HashMap(5);
        this.foreignKeyFields = NonSynchronizedVector.newInstance(1);

        //right now only ForeignKeyRelationships are supported
        this.isForeignKeyRelationship = false;
    }

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

    /**
     * PUBLIC:
     * Add a type indicator conversion to this mapping.
     */
    public void addClassIndicator(Class implementer, Object typeIndicator) {
        if (typeIndicator == null) {
            typeIndicator = Helper.NULL_VALUE;
        }

        getTypeIndicatorTranslation().put(implementer, typeIndicator);
        getTypeIndicatorTranslation().put(typeIndicator, implementer);
    }

    /**
     * INTERNAL:
     * Add indicators by classname.  For use by the Mapping Workbench to avoid classpath dependencies
     */
    public void addClassNameIndicator(String className, Object typeIndicator) {
        if (typeIndicator == null) {
            typeIndicator = Helper.NULL_VALUE;
        }
        getTypeIndicatorNameTranslation().put(className, typeIndicator);
    }

    /**
     * PUBLIC:
     * A foreign key from the source table and abstract query key from the interface descriptor are added to the
     * mapping. This method is used if there are multiple foreign keys.
     */
    public void addForeignQueryKeyName(DatabaseField sourceForeignKeyField, String targetQueryKeyName) {
        getSourceToTargetQueryKeyNames().put(sourceForeignKeyField, targetQueryKeyName);
        getForeignKeyFields().addElement(sourceForeignKeyField);
        this.setIsForeignKeyRelationship(true);
    }

    /**
     * PUBLIC:
     * A foreign key from the source table and abstract query key from the interface descriptor are added to the
     * mapping. This method is used if there are multiple foreign keys.
     */
    public void addForeignQueryKeyName(String sourceForeignKeyFieldName, String targetQueryKeyName) {
        addForeignQueryKeyName(new DatabaseField(sourceForeignKeyFieldName), targetQueryKeyName);
    }

    /**
     * PUBLIC:
     * Define the target foreign key relationship in the Variable 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 query name and the source primary key field name
     * must be specified.
     * The distinction between a foreign key and target foreign key is that the variable 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 addTargetForeignQueryKeyName(String targetForeignQueryKeyName, String sourcePrimaryKeyFieldName) {
        DatabaseField sourceField = new DatabaseField(sourcePrimaryKeyFieldName);

        getSourceToTargetQueryKeyNames().put(sourceField, targetForeignQueryKeyName);
    }

    /**
     * INTERNAL:
     * Possible for future development, not currently supported.
     *
     * Retrieve the value through using batch reading.
     * This executes a single query to read the target for all of the objects and stores the
     * result of the batch query in the original query to allow the other objects to share the results.
     */
    @Override
    protected Object batchedValueFromRow(AbstractRecord row, ObjectLevelReadQuery query, CacheKey parentCacheKey) {
        throw QueryException.batchReadingNotSupported(this, query);
    }

    /**
     * INTERNAL:
     * This methods clones all the fields and ensures that each collection refers to
     * the same clones.
     */
    @Override
    public Object clone() {
        VariableOneToOneMapping clone = (VariableOneToOneMapping)super.clone();
        Map setOfKeys = new HashMap(getSourceToTargetQueryKeyNames().size());
        Map sourceToTarget = new HashMap(getSourceToTargetQueryKeyNames().size());
        Vector foreignKeys = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(getForeignKeyFields().size());

        if (getTypeField() != null) {
            clone.setTypeField(this.getTypeField().clone());
        }

        for (Iterator enumtr = getSourceToTargetQueryKeyNames().keySet().iterator(); enumtr.hasNext();) {
            // Clone the SourceKeyFields
            DatabaseField field = (DatabaseField)enumtr.next();
            DatabaseField clonedField = field.clone();
            setOfKeys.put(field, clonedField);
            // on the next line I'm cloning the query key names
            sourceToTarget.put(clonedField, getSourceToTargetQueryKeyNames().get(field));
        }

        for (Enumeration<DatabaseField> enumtr = getForeignKeyFields().elements(); enumtr.hasMoreElements();) {
            DatabaseField field = enumtr.nextElement();
            foreignKeys.addElement(setOfKeys.get(field));
        }
        clone.setSourceToTargetQueryKeyFields(sourceToTarget);
        clone.setForeignKeyFields(foreignKeys);
        clone.setTypeIndicatorTranslation(new HashMap(this.getTypeIndicatorTranslation()));
        return clone;
    }

    /**
     * INTERNAL:
     * Return all the fields populated by this mapping.
     */
    @Override
    protected Vector collectFields() {
        DatabaseField type = getTypeField();

        //Get a shallow copy of the Vector
        if (type != null) {
            Vector sourceFields = (Vector)getForeignKeyFields().clone();
            sourceFields.addElement(type);
            return sourceFields;
        } else {
            return getForeignKeyFields();
        }
    }

    /**
     * INTERNAL:
     * Compare the references of the two objects are the same, not the objects themselves.
     * Used for independent relationships.
     * This is used for testing and validation purposes.
     *
     * Must get separate fields for the objects because we may be adding a different class to the
     * attribute because of the interface
     */
    @Override
    protected boolean compareObjectsWithoutPrivateOwned(Object firstObject, Object secondObject, AbstractSession session) {
        Object firstPrivateObject = getRealAttributeValueFromObject(firstObject, session);
        Object secondPrivateObject = getRealAttributeValueFromObject(secondObject, session);

        if ((firstPrivateObject == null) && (secondPrivateObject == null)) {
            return true;
        }

        if ((firstPrivateObject == null) || (secondPrivateObject == null)) {
            return false;
        }
        if (firstPrivateObject.getClass() != secondPrivateObject.getClass()) {
            return false;
        }
        Iterator targetKeys = getSourceToTargetQueryKeyNames().values().iterator();
        ClassDescriptor descriptor = session.getDescriptor(firstPrivateObject.getClass());
        ClassDescriptor descriptor2 = session.getDescriptor(secondPrivateObject.getClass());

        while (targetKeys.hasNext()) {
            String queryKey = (String)targetKeys.next();
            DatabaseField field = descriptor.getObjectBuilder().getFieldForQueryKeyName(queryKey);
            Object firstObjectField = descriptor.getObjectBuilder().extractValueFromObjectForField(firstPrivateObject, field, session);
            DatabaseField field2 = descriptor2.getObjectBuilder().getFieldForQueryKeyName(queryKey);
            Object secondObjectField = descriptor2.getObjectBuilder().extractValueFromObjectForField(secondPrivateObject, field2, session);

            if (!((firstObjectField == null) && (secondObjectField == null))) {
                if ((firstObjectField == null) || (secondObjectField == null)) {
                    return false;
                }
                if (!firstObjectField.equals(secondObjectField)) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * INTERNAL:
     * Return the class indicator associations for XML.
     * List of class-name/value associations.
     */
    public Vector getClassIndicatorAssociations() {
        Vector associations = new Vector();
        Iterator classesEnum = getTypeIndicatorNameTranslation().keySet().iterator();
        Iterator valuesEnum = getTypeIndicatorNameTranslation().values().iterator();
        while (classesEnum.hasNext()) {
            Object className = classesEnum.next();

            // If the project was built in runtime is a class, MW is a string.
            if (className instanceof Class) {
                className = ((Class)className).getName();
            }
            Object value = valuesEnum.next();
            associations.addElement(new TypedAssociation(className, value));
        }

        return associations;
    }

    /**
     * INTERNAL:
     * Return a descriptor for the target of this mapping
     * For normal ObjectReferenceMappings, we return the reference descriptor.  For
     * a VariableOneToOneMapping, the reference descriptor is often a descriptor for an
     * interface and does not contain adequate information.  As a result, we look up
     * the descriptor for the specific class we are looking for
     * Bug 2612571
     */
    @Override
    public ClassDescriptor getDescriptorForTarget(Object targetObject, AbstractSession session) {
        return session.getDescriptor(targetObject);
    }

    /**
     * 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) {
        if ((getTypeField() != null) && (fieldToClassify.equals(getTypeField()))) {
            return getTypeField().getType();
        }

        String queryKey = (String)getSourceToTargetQueryKeyNames().get(fieldToClassify);
        if (queryKey == null) {
            return null;
        }
        // Search any of the implementor descriptors for a mapping for the query-key.
        Iterator<ClassDescriptor> iterator = getReferenceDescriptor().getInterfacePolicy().getChildDescriptors().iterator();
        if (iterator.hasNext()) {
            ClassDescriptor firstChild = iterator.next();
            DatabaseMapping mapping = firstChild.getObjectBuilder().getMappingForAttributeName(queryKey);
            if ((mapping != null) && (mapping.isDirectToFieldMapping())) {
                return mapping.getAttributeClassification();
            }
            QueryKey targetQueryKey = firstChild.getQueryKeyNamed(queryKey);
            if ((targetQueryKey != null) && (targetQueryKey.isDirectQueryKey())) {
                return firstChild.getObjectBuilder().getFieldClassification(((DirectQueryKey)targetQueryKey).getField());
            }
        }
        return null;
    }

    /**
     * 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<DatabaseField> fieldsEnum = getForeignKeyFields().elements();
             fieldsEnum.hasMoreElements();) {
            fieldNames.addElement(fieldsEnum.nextElement().getQualifiedName());
        }

        return fieldNames;
    }

    /**
     * INTERNAL:
     * Return the implementor for a specified type
     */
    protected Object getImplementorForType(Object type, AbstractSession session) {
        if (type == null) {
            return getTypeIndicatorTranslation().get(Helper.NULL_VALUE);
        }

        // Must ensure the type is the same, i.e. Integer != BigDecimal.
        try {
            type = session.getDatasourcePlatform().convertObject(type, getTypeField().getType());
        } catch (ConversionException e) {
            throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
        }

        return getTypeIndicatorTranslation().get(type);
    }

    /**
     * PUBLIC:
     * Return a collection of the field to query key associations.
     */
    public Vector getSourceToTargetQueryKeyFieldAssociations() {
        Vector associations = new Vector(getSourceToTargetQueryKeyNames().size());
        Iterator sourceFieldEnum = getSourceToTargetQueryKeyNames().keySet().iterator();
        Iterator targetQueryKeyEnum = getSourceToTargetQueryKeyNames().values().iterator();
        while (sourceFieldEnum.hasNext()) {
            Object fieldValue = ((DatabaseField)sourceFieldEnum.next()).getQualifiedName();
            Object attributeValue = targetQueryKeyEnum.next();
            associations.addElement(new Association(fieldValue, attributeValue));
        }

        return associations;
    }

    /**
     * INTERNAL:
     * Returns the source keys to target keys fields association.
     */
    public Map getSourceToTargetQueryKeyNames() {
        return sourceToTargetQueryKeyNames;
    }

    public DatabaseField getTypeField() {
        return typeField;
    }

    /**
     * PUBLIC:
     * This method returns the name of the typeField of the mapping.
     * The type field is used to store the type of object the relationship is referencing.
     */
    public String getTypeFieldName() {
        if (getTypeField() == null) {
            return null;
        }
        return getTypeField().getQualifiedName();
    }

    /**
     * INTERNAL:
     * Return the type for a specified implementor
     */
    protected Object getTypeForImplementor(Class implementor) {
        Object type = getTypeIndicatorTranslation().get(implementor);
        if (type == Helper.NULL_VALUE) {
            type = null;
        }

        return type;
    }

    /**
     * INTERNAL:
     * Return the type indicators.
     */
    public Map getTypeIndicatorTranslation() {
        return typeIndicatorTranslation;
    }

    /**
     * INTERNAL:
     * Return the typeIndicatorName translation
     * Used by the Mapping Workbench to avoid classpath dependencies
     */
    public Map getTypeIndicatorNameTranslation() {
        if (typeIndicatorNameTranslation.isEmpty() && !typeIndicatorTranslation.isEmpty()) {
            Iterator keysEnum = typeIndicatorTranslation.keySet().iterator();
            Iterator valuesEnum = typeIndicatorTranslation.values().iterator();
            while (keysEnum.hasNext()) {
                Object key = keysEnum.next();
                Object value = valuesEnum.next();
                if (key instanceof Class) {
                    String className = ((Class)key).getName();
                    typeIndicatorNameTranslation.put(className, value);
                }
            }
        }

        return typeIndicatorNameTranslation;
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this mapping to actual class-based
     * settings. This method is used when converting a project that has been built
     * with class names to a project with classes.
     */
    @Override
    public void convertClassNamesToClasses(ClassLoader classLoader){
        super.convertClassNamesToClasses(classLoader);
        Iterator iterator = getTypeIndicatorNameTranslation().entrySet().iterator();
        this.typeIndicatorTranslation = new HashMap();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry)iterator.next();
            String referenceClassName = (String)entry.getKey();
            Object indicator = entry.getValue();
            Class referenceClass = null;
            try{
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                    try {
                        referenceClass = AccessController.doPrivileged(new PrivilegedClassForName<>(referenceClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(referenceClassName, exception.getException());
                    }
                } else {
                    referenceClass = PrivilegedAccessHelper.getClassForName(referenceClassName, true, classLoader);
                }
            } catch (ClassNotFoundException exception) {
                throw ValidationException.classNotFoundWhileConvertingClassNames(referenceClassName, exception);
            }
            addClassIndicator(referenceClass, indicator);
        }
    }

    /**
     * INTERNAL:
     * Initialize the mapping.
     */
    @Override
    public void initialize(AbstractSession session) {
        super.initialize(session);
        initializeForeignKeys(session);
        setFields(collectFields());
        if (usesIndirection()) {
            for (DatabaseField field : this.fields) {
                field.setKeepInRow(true);
            }
        }
        if (getTypeField() != null) {
            setTypeField(getDescriptor().buildField(getTypeField()));
        }
        if (shouldInitializeSelectionCriteria()) {
            initializeSelectionCriteria(session);
        }
    }

    /**
     * INTERNAL:
     * The foreign key names and their primary keys are converted to DatabaseField and stored.
     */
    protected void initializeForeignKeys(AbstractSession session) {
        HashMap newSourceToTargetQueryKeyNames = new HashMap(getSourceToTargetQueryKeyNames().size());
        Iterator iterator = getSourceToTargetQueryKeyNames().entrySet().iterator();
        while(iterator.hasNext()) {
            Map.Entry entry = (Map.Entry)iterator.next();
            DatabaseField field = getDescriptor().buildField((DatabaseField)entry.getKey());
            newSourceToTargetQueryKeyNames.put(field, entry.getValue());
        }
        this.sourceToTargetQueryKeyNames = newSourceToTargetQueryKeyNames;
    }

    /**
     * INTERNAL:
     * Selection criteria is created with source foreign keys and target keys.
     * This criteria is then used to read target records from the table.
     */
    public void initializeSelectionCriteria(AbstractSession session) {
        Expression selectionCriteria = null;
        Expression expression;

        ExpressionBuilder expBuilder = new ExpressionBuilder();

        Iterator sourceKeysEnum = getSourceToTargetQueryKeyNames().keySet().iterator();

        while (sourceKeysEnum.hasNext()) {
            DatabaseField sourceKey = (DatabaseField)sourceKeysEnum.next();
            String target = (String)this.getSourceToTargetQueryKeyNames().get(sourceKey);
            expression = expBuilder.getParameter(sourceKey).equal(expBuilder.get(target));

            if (selectionCriteria == null) {
                selectionCriteria = expression;
            } else {
                selectionCriteria = expression.and(selectionCriteria);
            }
        }

        setSelectionCriteria(selectionCriteria);
    }

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

    /**
     * INTERNAL:
     */
    @Override
    protected Object getPrimaryKeyForObject(Object object, AbstractSession session) {
        return session.getId(object);
    }

    /**
     * INTERNAL:
     * Set the type field classification through searching the indicators hashtable.
     */
    @Override
    public void preInitialize(AbstractSession session) throws DescriptorException {
        super.preInitialize(session);
        if (getTypeIndicatorTranslation().isEmpty()) {
            return;
        }
        Class type = null;
        for (Iterator typeValuesEnum = getTypeIndicatorTranslation().values().iterator();
                 typeValuesEnum.hasNext() && (type == null);) {
            Object value = typeValuesEnum.next();
            if ((value != Helper.NULL_VALUE) && (!(value instanceof Class))) {
                type = value.getClass();
            }
        }

        getTypeField().setType(type);
    }

    /**
     * INTERNAL:
     * Rehash any maps based on fields.
     * This is used to clone descriptors for aggregates, which hammer field names.
     */
    @Override
    public void rehashFieldDependancies(AbstractSession session) {
        setSourceToTargetQueryKeyFields(Helper.rehashMap(getSourceToTargetQueryKeyNames()));
    }

    /**
     * PUBLIC:
     * Set the class indicator associations.
     */
    public void setClassIndicatorAssociations(Vector classIndicatorAssociations) {
        setTypeIndicatorNameTranslation(new HashMap(classIndicatorAssociations.size() + 1));
        setTypeIndicatorTranslation(new HashMap((classIndicatorAssociations.size() * 2) + 1));
        for (Enumeration associationsEnum = classIndicatorAssociations.elements();
                 associationsEnum.hasMoreElements();) {
            Association association = (Association)associationsEnum.nextElement();
            Object classValue = association.getKey();
            if (classValue instanceof Class) {
                // 904 projects will be a class type.
                addClassIndicator((Class)association.getKey(), association.getValue());
            } else {
                addClassNameIndicator((String)association.getKey(), association.getValue());
            }
        }
    }

    /**
     * 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);
        if (!fields.isEmpty()) {
            setIsForeignKeyRelationship(true);
        }
    }

    /**
     * PUBLIC:
     * A foreign key from the source table and abstract query key from the interface descriptor are added to the
     * mapping. This method is used if foreign key is not composite.
     */
    public void setForeignQueryKeyName(String sourceForeignKeyFieldName, String targetQueryKeyName) {
        addForeignQueryKeyName(sourceForeignKeyFieldName, targetQueryKeyName);
    }

    /**
     * PUBLIC:
     * Set a collection of the source to target query key/field associations.
     */
    public void setSourceToTargetQueryKeyFieldAssociations(Vector sourceToTargetQueryKeyFieldAssociations) {
        setSourceToTargetQueryKeyFields(new HashMap(sourceToTargetQueryKeyFieldAssociations.size() + 1));
        for (Enumeration associationsEnum = sourceToTargetQueryKeyFieldAssociations.elements();
                 associationsEnum.hasMoreElements();) {
            Association association = (Association)associationsEnum.nextElement();
            Object sourceField = new DatabaseField((String)association.getKey());
            String targetQueryKey = (String)association.getValue();
            getSourceToTargetQueryKeyNames().put(sourceField, targetQueryKey);
        }
    }

    /**
     * INTERNAL:
     * Set the source keys to target keys fields association.
     */
    protected void setSourceToTargetQueryKeyFields(Map sourceToTargetQueryKeyNames) {
        this.sourceToTargetQueryKeyNames = sourceToTargetQueryKeyNames;
    }

    /**
     * INTERNAL:
     * This method set the typeField of the mapping to the parameter field
     */
    public void setTypeField(DatabaseField typeField) {
        this.typeField = typeField;
    }

    /**
     * PUBLIC:
     * This method sets the name of the typeField of the mapping.
     * The type field is used to store the type of object the relationship is referencing.
     */
    public void setTypeFieldName(String typeFieldName) {
        setTypeField(new DatabaseField(typeFieldName));
    }

    /**
     * INTERNAL:
     * Set the typeIndicatorTranslations hashtable to the new Hashtable translations
     */
    protected void setTypeIndicatorTranslation(Map translations) {
        this.typeIndicatorTranslation = translations;
    }

    /**
     * INTERNAL:
     * For avoiding classpath dependencies on the Mapping Workbench
     */
    protected void setTypeIndicatorNameTranslation(Map translations) {
        this.typeIndicatorNameTranslation = translations;
    }

    /**
     * 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.
        AbstractRecord referenceRow = getIndirectionPolicy().extractReferenceRow(getAttributeValueFromObject(object));
        if (referenceRow != null) {
            Object value = referenceRow.get(field);

            // Must ensure the classification to get a cache hit.
            try {
                value = session.getDatasourcePlatform().convertObject(value, getFieldClassification(field));
            } catch (ConversionException e) {
                throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
            }

            return value;
        }

        //2.5.1.6 PWK.  added to support batch reading on variable one to ones
        Object referenceObject = getRealAttributeValueFromObject(object, session);
        String queryKeyName = (String)getSourceToTargetQueryKeyNames().get(field);
        ClassDescriptor objectDescriptor = session.getDescriptor(referenceObject.getClass());
        DatabaseField targetField = objectDescriptor.getObjectBuilder().getTargetFieldForQueryKeyName(queryKeyName);

        if (targetField == null) {
            // Bug 326091 - return the type value if the field passed is the type indicator field
            if (referenceObject != null && this.typeField != null && field.equals(this.typeField)) {
                return getTypeForImplementor(referenceObject.getClass());
            } else {
                return null;
            }
        }

        return objectDescriptor.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
    public Object valueFromRow(AbstractRecord row, JoinedAttributeManager joinManager, ObjectBuildingQuery sourceQuery, CacheKey cacheKey, AbstractSession executionSession, boolean isTargetProtected, Boolean[] wasCacheUsed) throws DatabaseException {
        if (this.descriptor.getCachePolicy().isProtectedIsolation()) {
            if (this.isCacheable && isTargetProtected && cacheKey != null) {
                //cachekey will be null when isolating to uow
                //used cached collection
                Object result = null;
                Object cached = cacheKey.getObject();
                if (cached != null) {
                    if (wasCacheUsed != null){
                        wasCacheUsed[0] = Boolean.TRUE;
                    }
                    return this.getAttributeValueFromObject(cached);
                }
            } else if (!this.isCacheable && !isTargetProtected && cacheKey != null) {
                return this.indirectionPolicy.buildIndirectObject(new ValueHolder(null));
            }
        }
        if (row.hasSopObject()) {
            return getAttributeValueFromObject(row.getSopObject());
        }
        // If any field in the foreign key is null then it means there are no referenced objects
        for (DatabaseField field : getFields()) {
            if (row.get(field) == null) {
                return getIndirectionPolicy().nullValueFromRow();
            }
        }

        if (getTypeField() != null) {
            // If the query used batched reading, return a special value holder,
            // or retrieve the object from the query property.
            if (sourceQuery.isObjectLevelReadQuery() && (((ObjectLevelReadQuery)sourceQuery).isAttributeBatchRead(this.descriptor, getAttributeName())
                    || (sourceQuery.isReadAllQuery() && shouldUseBatchReading()))) {
                return batchedValueFromRow(row, ((ObjectLevelReadQuery)sourceQuery), cacheKey);
            }

            //If the field is empty we cannot load the object because we do not know what class it will be
            if (row.get(getTypeField()) == null) {
                return getIndirectionPolicy().nullValueFromRow();
            }
            Class implementerClass = (Class)getImplementorForType(row.get(getTypeField()), executionSession);
            ReadObjectQuery query = (ReadObjectQuery)getSelectionQuery().clone();
            query.setReferenceClass(implementerClass);
            query.setSelectionCriteria(getSelectionCriteria());
            query.setDescriptor(null);// Must set to null so the right descriptor is used

            if (sourceQuery.isObjectLevelReadQuery() && (sourceQuery.shouldCascadeAllParts() || (sourceQuery.shouldCascadePrivateParts() && isPrivateOwned()) || (sourceQuery.shouldCascadeByMapping() && this.cascadeRefresh)) ) {
                query.setShouldRefreshIdentityMapResult(sourceQuery.shouldRefreshIdentityMapResult());
                query.setCascadePolicy(sourceQuery.getCascadePolicy());
                query.setShouldMaintainCache(sourceQuery.shouldMaintainCache());
                // For flashback.
                if (((ObjectLevelReadQuery)sourceQuery).hasAsOfClause()) {
                    query.setAsOfClause(((ObjectLevelReadQuery)sourceQuery).getAsOfClause());
                }

                //CR #4365 - used to prevent infinit recursion on refresh object cascade all
                query.setQueryId(sourceQuery.getQueryId());
            }

            return getIndirectionPolicy().valueFromQuery(query, row, executionSession);
        } else {
            return super.valueFromRow(row, joinManager, sourceQuery, cacheKey, executionSession, isTargetProtected, wasCacheUsed);
        }
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     */
    protected void writeFromNullObjectIntoRow(AbstractRecord record) {
        if (isReadOnly()) {
            return;
        }
        if (isForeignKeyRelationship()) {
            Enumeration<DatabaseField> foreignKeys = getForeignKeyFields().elements();
            while (foreignKeys.hasMoreElements()) {
                record.put(foreignKeys.nextElement(), null);
                // EL Bug 319759 - if a field is null, then the update call cache should not be used
                record.setNullValueInFields(true);
            }
        }
        if (getTypeField() != null) {
            record.put(getTypeField(), null);
            record.setNullValueInFields(true);
        }
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     * If the mapping id target foreign key, you must only write the type into the roe, the rest will be updated
     * when the object itself is written
     */
    @Override
    public void writeFromObjectIntoRow(Object object, AbstractRecord record, AbstractSession session, WriteType writeType) {
        if (isReadOnly()) {
            return;
        }

        Object referenceObject = getRealAttributeValueFromObject(object, session);

        if (referenceObject == null) {
            writeFromNullObjectIntoRow(record);
        } else {
            if (isForeignKeyRelationship()) {
                Enumeration<DatabaseField> sourceFields = getForeignKeyFields().elements();
                ClassDescriptor descriptor = session.getDescriptor(referenceObject.getClass());
                while (sourceFields.hasMoreElements()) {
                    DatabaseField sourceKey = sourceFields.nextElement();
                    String targetQueryKey = (String)getSourceToTargetQueryKeyNames().get(sourceKey);
                    DatabaseField targetKeyField = descriptor.getObjectBuilder().getFieldForQueryKeyName(targetQueryKey);
                    if (targetKeyField == null) {
                        throw DescriptorException.variableOneToOneMappingIsNotDefinedProperly(this, descriptor, targetQueryKey);
                    }
                    Object referenceValue = descriptor.getObjectBuilder().extractValueFromObjectForField(referenceObject, targetKeyField, session);
                    // EL Bug 319759 - if a field is null, then the update call cache should not be used
                    if (referenceValue == null) {
                        record.setNullValueInFields(true);
                    }
                    record.put(sourceKey, referenceValue);
                }
            }
            if (getTypeField() != null) {
                record.put(getTypeField(), getTypeForImplementor(referenceObject.getClass()));
            }
        }
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     * If the mapping id target foreign key, you must only write the type into the roe, the rest will be updated
     * when the object itself is written
     */
    @Override
    public void writeFromObjectIntoRowWithChangeRecord(ChangeRecord changeRecord, AbstractRecord record, AbstractSession session, WriteType writeType) {
        if (isReadOnly()) {
            return;
        }

        ObjectChangeSet changeSet = (ObjectChangeSet)((ObjectReferenceChangeRecord)changeRecord).getNewValue();
        if (changeSet == null) {
            writeFromNullObjectIntoRow(record);
        } else {
            Object referenceObject = changeSet.getUnitOfWorkClone();
            if (isForeignKeyRelationship()) {
                Enumeration<DatabaseField> sourceFields = getForeignKeyFields().elements();
                ClassDescriptor descriptor = session.getDescriptor(referenceObject.getClass());
                while (sourceFields.hasMoreElements()) {
                    DatabaseField sourceKey = sourceFields.nextElement();
                    String targetQueryKey = (String)getSourceToTargetQueryKeyNames().get(sourceKey);
                    DatabaseField targetKeyField = descriptor.getObjectBuilder().getFieldForQueryKeyName(targetQueryKey);
                    if (targetKeyField == null) {
                        throw DescriptorException.variableOneToOneMappingIsNotDefinedProperly(this, descriptor, targetQueryKey);
                    }
                    Object referenceValue = descriptor.getObjectBuilder().extractValueFromObjectForField(referenceObject, targetKeyField, session);
                    // EL Bug 319759 - if a field is null, then the update call cache should not be used
                    if (referenceValue == null) {
                        record.setNullValueInFields(true);
                    }
                    record.put(sourceKey, referenceValue);
                }
            }
            if (getTypeField() != null) {
                record.put(getTypeField(), getTypeForImplementor(referenceObject.getClass()));
            }
        }
    }

    /**
     * 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 record, AbstractSession session) {
        writeFromNullObjectIntoRow(record);
    }

    /**
     * INTERNAL:
     * This row is built for update after shallow insert which happens in case of bidirectional inserts.
     * It contains the foreign keys with non null values that were set to null for shallow insert.
     * If mapping overrides writeFromObjectIntoRowForShallowInsert method it must override this one, too.
     */
    @Override
    public void writeFromObjectIntoRowForUpdateAfterShallowInsert(Object object, AbstractRecord row, AbstractSession session, DatabaseTable table) {
        if (!getFields().get(0).getTable().equals(table)) {
            return;
        }
        writeFromObjectIntoRow(object, row, session, WriteType.UPDATE);
    }

    /**
     * INTERNAL:
     * This row is built for shallow insert which happens in case of bidirectional inserts.
     * The foreign keys must be set to null to avoid constraints.
     */
    @Override
    public void writeFromObjectIntoRowForShallowInsertWithChangeRecord(ChangeRecord changeRecord, AbstractRecord record, AbstractSession session) {
        writeFromNullObjectIntoRow(record);
    }

    /**
     * INTERNAL:
     * Get a value from the object and set that in the respective field of the row.
     */
    @Override
    public void writeFromObjectIntoRowForWhereClause(ObjectLevelModifyQuery query, AbstractRecord record) {
        if (isReadOnly()) {
            return;
        }
        Object object;
        if (query.isDeleteObjectQuery()) {
            object = query.getObject();
        } else {
            object = query.getBackupClone();
        }
        Object referenceObject = getRealAttributeValueFromObject(object, query.getSession());

        if (referenceObject == null) {
            writeFromNullObjectIntoRow(record);
        } else {
            if (isForeignKeyRelationship()) {
                Enumeration<DatabaseField> sourceFields = getForeignKeyFields().elements();
                ClassDescriptor descriptor = query.getSession().getDescriptor(referenceObject.getClass());
                while (sourceFields.hasMoreElements()) {
                    DatabaseField sourceKey = sourceFields.nextElement();
                    String targetQueryKey = (String)getSourceToTargetQueryKeyNames().get(sourceKey);
                    DatabaseField targetKeyField = descriptor.getObjectBuilder().getFieldForQueryKeyName(targetQueryKey);
                    if (targetKeyField == null) {
                        throw DescriptorException.variableOneToOneMappingIsNotDefinedProperly(this, descriptor, targetQueryKey);
                    }
                    Object referenceValue = descriptor.getObjectBuilder().extractValueFromObjectForField(referenceObject, targetKeyField, query.getSession());
                    if (referenceValue == null) {
                        // EL Bug 319759 - if a field is null, then the update call cache should not be used
                        record.setNullValueInFields(true);
                    }
                    record.put(sourceKey, referenceValue);
                }
            }
            if (getTypeField() != null) {
                Object typeForImplementor = getTypeForImplementor(referenceObject.getClass());
                record.put(getTypeField(), typeForImplementor);
            }
        }
    }

    /**
     * INTERNAL:
     * Write fields needed for insert into the template for with null values.
     */
    @Override
    public void writeInsertFieldsIntoRow(AbstractRecord record, AbstractSession session) {
        writeFromNullObjectIntoRow(record);
    }
}
