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

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

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.annotations.CacheKeyType;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
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.identitymaps.CacheId;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.queries.JoinedAttributeManager;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.queries.ObjectBuildingQuery;
import org.eclipse.persistence.queries.ObjectLevelModifyQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.ReadQuery;

/**
 * <p>An EIS one-to-one mapping is a reference mapping that represents the relationship between
 * a single source object and a single mapped persistent Java object.  The source object usually
 * contains a foreign key (pointer) to the target object (key on source); alternatively, the target
 * object may contain a foreign key to the source object (key on target).  Because both the source
 * and target objects use interactions, they must both be configured as root object types.
 *
 * <table border="1">
 * <caption>Record formats</caption>
 * <tr>
 * <th id="c1">Record Type</th>
 * <th id="c2">Description</th>
 * </tr>
 * <tr>
 * <td headers="c1">Indexed</td>
 * <td headers="c2">Ordered collection of record elements.  The indexed record EIS format
 * enables Java class attribute values to be retrieved by position or index.</td>
 * </tr>
 * <tr>
 * <td headers="c1">Mapped</td>
 * <td headers="c2">Key-value map based representation of record elements.  The mapped record
 * EIS format enables Java class attribute values to be retrieved by an object key.</td>
 * </tr>
 * <tr>
 * <td headers="c1">XML</td>
 * <td headers="c2">Record/Map representation of an XML DOM element.</td>
 * </tr>
 * </table>
 *
 * @see org.eclipse.persistence.eis.EISDescriptor#useIndexedRecordFormat
 * @see org.eclipse.persistence.eis.EISDescriptor#useMappedRecordFormat
 * @see org.eclipse.persistence.eis.EISDescriptor#useXMLRecordFormat
 *
 * @since Oracle TopLink 10<i>g</i> Release 2 (10.1.3)
 */
public class EISOneToOneMapping extends ObjectReferenceMapping implements EISMapping {

    /** 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;

    /** 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 EISOneToOneMapping() {
        this.selectionQuery = new ReadObjectQuery();

        this.foreignKeyFields = org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(1);

        this.sourceToTargetKeyFields = new HashMap<>(2);
        this.targetToSourceKeyFields = new HashMap<>(2);
    }

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

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

    /**
     * PUBLIC:
     * Define the source foreign key relationship in the one-to-one mapping.
     * This method is used to add foreign key relationships to the mapping.
     * Both the source foreign key field name and the corresponding
     * target primary key field name must be specified.
     */
    @Override
    public void addForeignKeyField(DatabaseField sourceForeignKeyField, DatabaseField targetKeyField) {
        getSourceToTargetKeyFields().put(sourceForeignKeyField, targetKeyField);
        getTargetToSourceKeyFields().put(targetKeyField, sourceForeignKeyField);

        getForeignKeyFields().add(sourceForeignKeyField);
        setIsForeignKeyRelationship(true);
    }

    /**
     * PUBLIC:
     * Define the source foreign key relationship in the one-to-one mapping.
     * This method is used to add foreign key relationships to the mapping.
     * Both the source foreign key field name and the corresponding
     * target primary key field name must be specified.
     */
    public void addForeignKeyFieldName(String sourceForeignKeyFieldName, String targetKeyFieldName) {
        this.addForeignKeyField(new DatabaseField(sourceForeignKeyFieldName), new DatabaseField(targetKeyFieldName));
    }

    /**
     * INTERNAL:
     * This methods clones all the fields and ensures that each collection refers to
     * the same clones.
     */
    @Override
    public Object clone() {
        EISOneToOneMapping clone = (EISOneToOneMapping)super.clone();
        clone.setForeignKeyFields(org.eclipse.persistence.internal.helper.NonSynchronizedVector.newInstance(getForeignKeyFields().size()));
        clone.setSourceToTargetKeyFields(new HashMap<>(getSourceToTargetKeyFields().size()));
        clone.setTargetToSourceKeyFields(new HashMap<>(getTargetToSourceKeyFields().size()));
        Map<DatabaseField, DatabaseField> setOfFields = new HashMap<>(getTargetToSourceKeyFields().size());

        for (Enumeration<DatabaseField> enumtr = getForeignKeyFields().elements(); enumtr.hasMoreElements();) {
            DatabaseField field = enumtr.nextElement();

            DatabaseField fieldClone = field.clone();
            setOfFields.put(field, fieldClone);
            clone.getForeignKeyFields().addElement(fieldClone);
        }

        //get clones from set for source hashtable.  If they do not exist, create a new one.
        Iterator<DatabaseField> sourceKeyIterator = getSourceToTargetKeyFields().keySet().iterator();
        while (sourceKeyIterator.hasNext()) {
            DatabaseField sourceField = sourceKeyIterator.next();
            DatabaseField targetField = getSourceToTargetKeyFields().get(sourceField);

            DatabaseField targetClone = setOfFields.get(targetField);
            if (targetClone == null) {
                targetClone = targetField.clone();
                setOfFields.put(targetField, targetClone);
            }

            DatabaseField sourceClone = sourceField.clone();
            if (sourceClone == null) {
                sourceClone = sourceField.clone();
                setOfFields.put(sourceField, sourceClone);
            }
            clone.getSourceToTargetKeyFields().put(sourceClone, targetClone);
        }

        //get clones from set for target hashtable.  If they do not exist, create a new one.
        Iterator<DatabaseField> targetKeyIterator = getTargetToSourceKeyFields().keySet().iterator();
        while (targetKeyIterator.hasNext()) {
            DatabaseField targetField = targetKeyIterator.next();
            DatabaseField sourceField = getTargetToSourceKeyFields().get(targetField);

            DatabaseField targetClone = setOfFields.get(targetField);
            if (targetClone == null) {
                targetClone = targetField.clone();
                setOfFields.put(targetField, targetClone);
            }

            DatabaseField sourceClone = setOfFields.get(sourceField);
            if (sourceClone == null) {
                sourceClone = sourceField.clone();
                setOfFields.put(sourceField, sourceClone);
            }
            clone.getTargetToSourceKeyFields().put(targetClone, sourceClone);
        }

        return clone;
    }

    /**
     * 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<DatabaseField> primaryKeyFields = getReferenceDescriptor().getPrimaryKeyFields();
        Object[] result = new  Object[primaryKeyFields.size()];
        for (int index = 0; index < primaryKeyFields.size(); index++) {
            DatabaseField targetKeyField = 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:
     * Initialize the mapping.
     */
    @Override
    public void initialize(AbstractSession session) throws DescriptorException {
        super.initialize(session);

        // Must build foreign keys fields.
        List<DatabaseField> foreignKeyFields = getForeignKeyFields();
        int size = foreignKeyFields.size();
        for (int index = 0; index < size; index++) {
            DatabaseField foreignKeyField = foreignKeyFields.get(index);
            foreignKeyField = getDescriptor().buildField(foreignKeyField);
            foreignKeyFields.set(index, foreignKeyField);
        }

        initializeForeignKeys(session);

        if (shouldInitializeSelectionCriteria()) {
            initializeSelectionCriteria(session);
        } else {
            setShouldVerifyDelete(false);
        }
        setFields(collectFields());
    }

    /**
     * INTERNAL:
     * The foreign keys primary keys are stored as database fields in the hashtable.
     */
    protected void initializeForeignKeys(AbstractSession session) {
        Map<DatabaseField, DatabaseField> newSourceToTargetKeyFields = new HashMap<>(getSourceToTargetKeyFields().size());
        Map<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();
            DatabaseField targetField = entry.getValue();

            sourceField = getDescriptor().buildField(sourceField);
            targetField = getReferenceDescriptor().buildField(targetField);
            newSourceToTargetKeyFields.put(sourceField, targetField);
            newTargetToSourceKeyFields.put(targetField, sourceField);
        }
        setSourceToTargetKeyFields(newSourceToTargetKeyFields);
        setTargetToSourceKeyFields(newTargetToSourceKeyFields);
    }

    /**
     * INTERNAL:
     * Selection criteria is created with source foreign keys and target keys.
     * This criteria is then used to read target records from the table.
     *
     * CR#3922 - This method is almost the same as buildSelectionCriteria() the difference
     * is that getSelectionCriteria() is called
     */
    protected void initializeSelectionCriteria(AbstractSession session) {
        if (this.getSourceToTargetKeyFields().isEmpty()) {
            throw DescriptorException.noForeignKeysAreSpecified(this);
        }

        Expression criteria;
        Expression builder = new ExpressionBuilder();
        Iterator<DatabaseField> keyIterator = getSourceToTargetKeyFields().keySet().iterator();
        while (keyIterator.hasNext()) {
            DatabaseField foreignKey = keyIterator.next();
            DatabaseField targetKey = getSourceToTargetKeyFields().get(foreignKey);

            Expression expression = builder.getField(targetKey).equal(builder.getParameter(foreignKey));
            criteria = expression.and(getSelectionCriteria());
            setSelectionCriteria(criteria);
        }
    }

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

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

    /**
     * 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:
     * 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 query, CacheKey cacheKey, AbstractSession session, 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);
                }
                return result;
            } else if (!this.isCacheable && !isTargetProtected && cacheKey != null) {
                return this.indirectionPolicy.buildIndirectObject(new ValueHolder<>(null));
            }
        }
        // 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 (!query.hasPartialAttributeExpressions()) {
            for (Enumeration<DatabaseField> enumeration = getFields().elements(); enumeration.hasMoreElements();) {
                DatabaseField field = enumeration.nextElement();
                if (row.get(field) == null) {
                    return getIndirectionPolicy().nullValueFromRow();
                }
            }
        }

        // Call the default which executes the selection query,
        // or wraps the query with a value holder.
        //return super.valueFromRow(row, query);
        ReadQuery targetQuery = getSelectionQuery();

        // if the source query is cascading then the target query must use the same settings
        if (targetQuery.isObjectLevelReadQuery() && (query.shouldCascadeAllParts() || (query.shouldCascadePrivateParts() && isPrivateOwned()) || (query.shouldCascadeByMapping() && this.cascadeRefresh))) {
            targetQuery = (ObjectLevelReadQuery)targetQuery.clone();
            ((ObjectLevelReadQuery)targetQuery).setShouldRefreshIdentityMapResult(query.shouldRefreshIdentityMapResult());
            targetQuery.setCascadePolicy(query.getCascadePolicy());
            //CR #4365
            targetQuery.setQueryId(query.getQueryId());
            // For queries that have turned caching off, such as aggregate collection, leave it off.
            if (targetQuery.shouldMaintainCache()) {
                targetQuery.setShouldMaintainCache(query.shouldMaintainCache());
            }
        }

        return getIndirectionPolicy().valueFromQuery(targetQuery, row, query.getSession());
    }

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

        AbstractRecord referenceRow = getIndirectionPolicy().extractReferenceRow(getAttributeValueFromObject(object));
        if (referenceRow == null) {
            // Extract from object.
            Object referenceObject = getRealAttributeValueFromObject(object, session);

            for (int i = 0; i < getForeignKeyFields().size(); i++) {
                DatabaseField sourceKey = getForeignKeyFields().get(i);
                DatabaseField targetKey = getSourceToTargetKeyFields().get(sourceKey);

                Object referenceValue = null;

                // If privately owned part is null then method cannot be invoked.
                if (referenceObject != null) {
                    referenceValue = getReferenceDescriptor().getObjectBuilder().extractValueFromObjectForField(referenceObject, targetKey, session);
                }
                Record.add(sourceKey, referenceValue);
            }
        } else {
            for (int i = 0; i < getForeignKeyFields().size(); i++) {
                DatabaseField sourceKey = getForeignKeyFields().get(i);
                Record.add(sourceKey, referenceRow.get(sourceKey));
            }
        }
    }

    /**
     * INTERNAL:
     * Return the classifiction 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);
    }

    /**
     * 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:
     * 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.
     *
     * @param shouldVerifyDelete
     *            Sets whether delete verification should be performed
     */
    public void setShouldVerifyDelete(boolean shouldVerifyDelete) {
        this.shouldVerifyDelete = shouldVerifyDelete;
    }

    /**
     * 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.
     *
     * @return TRUE if verify delete has been enabled
     */
    public boolean shouldVerifyDelete() {
        return shouldVerifyDelete;
    }

    /**
     * INTERNAL: Gets the foreign key fields.
     *
     * @return The mapping from source to target key fields
     */
    public Map<DatabaseField, DatabaseField> getSourceToTargetKeyFields() {
        return sourceToTargetKeyFields;
    }

    /**
     * INTERNAL: Gets the target foreign key fields.
     *
     * @return The mapping from target to source key fields
     */
    public Map<DatabaseField, DatabaseField> getTargetToSourceKeyFields() {
        return targetToSourceKeyFields;
    }

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

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

    /**
     * INTERNAL:
     * This method is not supported in an EIS environment.
     */
    @Override
    public void setSelectionSQLString(String sqlString) {
        throw DescriptorException.invalidMappingOperation(this, "setSelectionSQLString");
    }
}
