/*
 * 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.internal.indirection;

import java.rmi.server.ObjID;
import java.util.Map;

import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.IntegrityChecker;
import org.eclipse.persistence.indirection.ValueHolder;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.internal.descriptors.DescriptorIterator;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.MergeManager;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.internal.sessions.remote.ObjectDescriptor;
import org.eclipse.persistence.internal.sessions.remote.RemoteSessionController;
import org.eclipse.persistence.internal.sessions.remote.RemoteUnitOfWork;
import org.eclipse.persistence.internal.sessions.remote.RemoteValueHolder;
import org.eclipse.persistence.mappings.DatabaseMapping.WriteType;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.sessions.remote.DistributedSession;

/**
 * <h2>Purpose</h2>:
 * BasicIndirectionPolicy implements the behavior necessary for a
 * a <code>org.eclipse.persistence.mappings.ForeignReferenceMapping</code> (or TransformationMapping) to
 * use ValueHolders to delay the reading of objects from the database
 * until they are actually needed.
 *
 * @author Mike Norman
 * @since TOPLink/Java 2.5
 */
public class BasicIndirectionPolicy extends IndirectionPolicy {

    /**
     * INTERNAL:
     * Construct a new indirection policy.
     */
    public BasicIndirectionPolicy() {
        super();
    }

    /**
     * INTERNAL:
     *    Return a backup clone of the attribute.
     */
    @Override
    public Object backupCloneAttribute(Object attributeValue, Object clone, Object backup, UnitOfWorkImpl unitOfWork) {
        //no need to check if the attribute is a valueholder because closeAttribute
        // should always be called first
        @SuppressWarnings({"unchecked"})
        ValueHolderInterface<Object> valueHolder = (ValueHolderInterface<Object>)attributeValue;// cast the value
        ValueHolderInterface<Object> result = null;
        // delay instantiation until absolutely necessary
        if ((!(valueHolder instanceof UnitOfWorkValueHolder)) || valueHolder.isInstantiated()) {
            result = new ValueHolder<>();
            result.setValue(super.backupCloneAttribute(valueHolder.getValue(), clone, backup, unitOfWork));
        } else {
            // Backup value holder will be instantiated when uow vh is, to get original value,
            // backup must also know about the uow vh, in case it needs to get its value.
            result = new BackupValueHolder<>(valueHolder);
            ((UnitOfWorkValueHolder<Object>)valueHolder).setBackupValueHolder(result);
        }

        return result;
    }

    /**
     * INTERNAL: This method can be used when an Indirection Object is required
     * to be built from a provided ValueHolderInterface object. This may be used
     * for custom value holder types. Certain policies like the
     * TransparentIndirectionPolicy may wrap the valueholder in another object.
     */

    @Override
    public Object buildIndirectObject(ValueHolderInterface valueHolder){
        return valueHolder;
    }

    /**
     * INTERNAL:
     *    Return a clone of the attribute.
     *  @param buildDirectlyFromRow indicates that we are building the clone
     *  directly from a row as opposed to building the original from the
     *  row, putting it in the shared cache, and then cloning the original.
     */
    @Override
    public Object cloneAttribute(Object attributeValue, Object original, CacheKey cacheKey, Object clone, Integer refreshCascade, AbstractSession cloningSession, boolean buildDirectlyFromRow) {
        @SuppressWarnings({"unchecked"})
        ValueHolderInterface<Object> valueHolder = (ValueHolderInterface<Object>) attributeValue;
        ValueHolderInterface<Object> result;

        if (!buildDirectlyFromRow && cloningSession.isUnitOfWork() && ((UnitOfWorkImpl)cloningSession).isOriginalNewObject(original)) {
            // CR#3156435 Throw a meaningful exception if a serialized/dead value holder is detected.
            // This can occur if an existing serialized object is attempt to be registered as new.
            if ((valueHolder instanceof DatabaseValueHolder)
                    && (! valueHolder.isInstantiated())
                    && (((DatabaseValueHolder<?>) valueHolder).getSession() == null)
                    && (! ((DatabaseValueHolder<?>) valueHolder).isSerializedRemoteUnitOfWorkValueHolder())) {
                throw DescriptorException.attemptToRegisterDeadIndirection(original, this.mapping);
            }
            if (this.mapping.getRelationshipPartner() == null) {
                result = new ValueHolder<>();
                result.setValue(this.mapping.buildCloneForPartObject(valueHolder.getValue(), original, null, clone, cloningSession, refreshCascade, false, false));
            } else {
                //if I have a relationship partner trigger the indirection so that the value will be inserted
                // because of this call the entire tree should be recursively cloned
                AbstractRecord row = null;
                if (valueHolder instanceof DatabaseValueHolder) {
                    row = ((DatabaseValueHolder<?>)valueHolder).getRow();
                }
                result = this.mapping.createCloneValueHolder(valueHolder, original, clone, row, cloningSession, buildDirectlyFromRow);

                Object newObject = this.mapping.buildCloneForPartObject(valueHolder.getValue(), original, cacheKey, clone, cloningSession, refreshCascade, false, false);
                ((UnitOfWorkValueHolder<Object>)result).privilegedSetValue(newObject);
                ((UnitOfWorkValueHolder<?>)result).setInstantiated();
            }
        } else {
            AbstractRecord row = null;
            if (valueHolder instanceof DatabaseValueHolder) {
                row = ((DatabaseValueHolder<?>)valueHolder).getRow();
            }
            result = this.mapping.createCloneValueHolder(valueHolder, original, clone, row, cloningSession, buildDirectlyFromRow);
        }
        return result;
    }

    /**
     * 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 extractPrimaryKeyForReferenceObject(Object referenceObject, AbstractSession session) {
        if (objectIsEasilyInstantiated(referenceObject)) {
            return super.extractPrimaryKeyForReferenceObject(((ValueHolderInterface<?>)referenceObject).getValue(), session);
        } else {
            return getOneToOneMapping().extractPrimaryKeysForReferenceObjectFromRow(extractReferenceRow(referenceObject));
        }
    }

    /**
     * INTERNAL:
     *    Return the reference row for the reference object.
     * This allows the new row to be built without instantiating
     * the reference object.
     * Return null if the object has already been instantiated.
     */
    @Override
    public AbstractRecord extractReferenceRow(Object referenceObject) {
        if (this.objectIsInstantiated(referenceObject)) {
            return null;
        } else {
            return ((DatabaseValueHolder<?>)referenceObject).getRow();
        }
    }

    /**
     * INTERNAL:
     * An object has been serialized from the server to the client.
     * Replace the transient attributes of the remote value holders
     * with client-side objects.
     */
    @Override
    public void fixObjectReferences(Object object, Map<Object, ObjectDescriptor> objectDescriptors, Map<Object, Object> processedObjects, ObjectLevelReadQuery query, DistributedSession session) {
        Object attributeValue = this.mapping.getAttributeValueFromObject(object);
        //bug 4147755 if it is not a Remote Valueholder then treat as if there was no VH...
        if (attributeValue instanceof RemoteValueHolder){
            RemoteValueHolder<?> rvh = (RemoteValueHolder<?>)this.mapping.getAttributeValueFromObject(object);
            rvh.setSession(session);
            rvh.setMapping(this.mapping);

            if ((!query.shouldMaintainCache()) && ((!query.shouldCascadeParts()) || (query.shouldCascadePrivateParts() && (!this.mapping.isPrivateOwned())))) {
                rvh.setQuery(null);
            } else {
                rvh.setQuery(query);
            }

            // set to uninstantiated since no objects are serialized past remote value holders
            rvh.setUninstantiated();
        }else{
            this.mapping.fixRealObjectReferences(object, objectDescriptors, processedObjects, query, session);
        }
    }

    /**
     * INTERNAL:
     * Return the original indirection object for a unit of work indirection object.
     * This is used when building a new object from the unit of work when the original fell out of the cache.
     */
    @Override
    public Object getOriginalIndirectionObject(Object unitOfWorkIndirectionObject, AbstractSession session) {
        return this.getOriginalValueHolder(unitOfWorkIndirectionObject, session);
    }

    /**
     * INTERNAL:
     *    Return the original indirection object for a unit of work indirection object.
     */
    @Override
    public Object getOriginalIndirectionObjectForMerge(Object unitOfWorkIndirectionObject, AbstractSession session) {
        DatabaseValueHolder<?> holder = (DatabaseValueHolder<?>)getOriginalIndirectionObject(unitOfWorkIndirectionObject, session);
        if (holder != null && holder.getSession()!= null){
            holder.setSession(session);
        }
        return holder;
    }

    /**
     * INTERNAL: Return the original valueHolder object. Access to the
     * underlying valueholder may be required when serializing the valueholder
     * or converting the valueHolder to another type.
     */
    @Override
    public Object getOriginalValueHolder(Object unitOfWorkIndirectionObject, AbstractSession session) {
        if ((unitOfWorkIndirectionObject instanceof UnitOfWorkValueHolder)
                && (((UnitOfWorkValueHolder<?>)unitOfWorkIndirectionObject).getRemoteUnitOfWork() != null)) {
            ValueHolderInterface<?> valueHolder = ((UnitOfWorkValueHolder<?>) unitOfWorkIndirectionObject).getWrappedValueHolder();
            if (valueHolder == null) {
                // For remote session the original value holder is transient,
                // so the value must be found in the registry or created.
                RemoteUnitOfWork remoteUnitOfWork = (RemoteUnitOfWork)((UnitOfWorkValueHolder<?>)unitOfWorkIndirectionObject).getRemoteUnitOfWork();
                RemoteSessionController controller = remoteUnitOfWork.getParentSessionController();
                ObjID id = ((UnitOfWorkValueHolder<?>) unitOfWorkIndirectionObject).getWrappedValueHolderRemoteID();
                if (id != null) {
                    // This value holder may be on the server, or the client,
                    // on the server, the controller should exists, so can lock up in it,
                    // on the client, the id should be enough to create a new remote value holder.
                    if (controller != null) {
                        valueHolder = controller.getRemoteValueHolders().get(id);
                    } else if (session.isRemoteSession()) {
                        valueHolder = new RemoteValueHolder<>(id);
                        ((RemoteValueHolder<?>)valueHolder).setSession(session);
                    }
                }
                if (valueHolder == null) {
                    // Must build a new value holder.
                    Object object = ((UnitOfWorkValueHolder<?>) unitOfWorkIndirectionObject).getSourceObject();
                    AbstractRecord row = this.mapping.getDescriptor().getObjectBuilder().buildRow(object, session, WriteType.UNDEFINED);
                    ReadObjectQuery query = new ReadObjectQuery();
                    query.setSession(session);
                    valueHolder = (ValueHolderInterface<?>) this.mapping.valueFromRow(row, null, query, true);
                }
                return valueHolder;
            }
        }
        if (unitOfWorkIndirectionObject instanceof WrappingValueHolder) {
            ValueHolderInterface<?> valueHolder =  ((WrappingValueHolder<?>)unitOfWorkIndirectionObject).getWrappedValueHolder();
            if (!session.isProtectedSession()){
                while (valueHolder instanceof WrappingValueHolder && ((WrappingValueHolder<?>)valueHolder).getWrappedValueHolder() != null){
                    valueHolder = ((WrappingValueHolder<?>)valueHolder).getWrappedValueHolder();
                }
            }
            if (valueHolder instanceof DatabaseValueHolder) {
                ((DatabaseValueHolder<?>) valueHolder).releaseWrappedValueHolder(session);
            }
            return valueHolder;
        } else {
            return unitOfWorkIndirectionObject;
        }
    }

    /**
     * Reset the wrapper used to store the value.
     */
    @Override
    public void reset(Object target) {
        this.mapping.setAttributeValueInObject(target, new ValueHolder<>());
    }

    /**
     * INTERNAL:
     * Return the "real" attribute value, as opposed to any wrapper.
     * This will trigger the wrapper to instantiate the value.
     */
    @Override
    public Object getRealAttributeValueFromObject(Object object, Object attribute) {
        if (attribute instanceof ValueHolderInterface) {
            return ((ValueHolderInterface<?>)attribute).getValue();
        } else {
            return attribute;
        }
    }

    /**
     * INTERNAL:
     * Extract and return the appropriate value from the
     * specified remote value holder.
     */
    @Override
    public Object getValueFromRemoteValueHolder(RemoteValueHolder<?> remoteValueHolder) {
        return remoteValueHolder.getValue();
    }

    /**
     * INTERNAL:
     * The method validateAttributeOfInstantiatedObject(Object attributeValue) fixes the value of the attributeValue
     * in cases where it is null and indirection requires that it contain some specific data structure.  Return whether this will happen.
     * This method is used to help determine if indirection has been triggered
     * @see #validateAttributeOfInstantiatedObject(Object attributeValue)
     */
    @Override
    public boolean isAttributeValueFullyBuilt(Object attributeValue){
        //Bug#413833 : If attributeValue is an instance of ValueHolder,
        //it has not been built into the clone previously
        return attributeValue != null && !(attributeValue instanceof ValueHolder && ((ValueHolder<?>)attributeValue).isNewlyWeavedValueHolder());
    }

    /**
     * INTERNAL:
     *    Iterate over the specified attribute value,
     */
    @Override
    public void iterateOnAttributeValue(DescriptorIterator iterator, Object attributeValue) {
        iterator.iterateValueHolderForMapping((ValueHolderInterface<?>)attributeValue, this.mapping);
    }

    /**
     * INTERNAL
     * Replace the client value holder with the server value holder,
     * after copying some of the settings from the client value holder.
     */
    @Override
    public void mergeRemoteValueHolder(Object clientSideDomainObject, Object serverSideDomainObject, MergeManager mergeManager) {
        // This will always be a remote value holder coming from the server,
        RemoteValueHolder<?> serverValueHolder = (RemoteValueHolder<?>)this.mapping.getAttributeValueFromObject(serverSideDomainObject);
        mergeClientIntoServerValueHolder(serverValueHolder, mergeManager);

        this.mapping.setAttributeValueInObject(clientSideDomainObject, serverValueHolder);
    }

    /**
     * INTERNAL:
     *    Return the null value of the appropriate attribute. That is, the
     * field from the database is NULL, return what should be
     * placed in the object's attribute as a result.
     * In this case, return an empty ValueHolder.
     */
    @Override
    public Object nullValueFromRow() {
        return new ValueHolder<>();
    }

    /**
     * INTERNAL:
     * Return whether the specified object is instantiated.
     */
    @Override
    public boolean objectIsInstantiated(Object object) {
        return ((ValueHolderInterface<?>)object).isInstantiated();
    }

    /**
     * INTERNAL:
     * Return whether the specified object can be instantiated without database access.
     */
    @Override
    public boolean objectIsEasilyInstantiated(Object object) {
        if (object instanceof DatabaseValueHolder) {
            return ((DatabaseValueHolder<?>)object).isEasilyInstantiated();
        } else {
            return true;
        }
    }

    /**
     * INTERNAL:
     * Set the value of the appropriate attribute of target to attributeValue.
     * In this case, place the value inside the target's ValueHolder.
     */
    @Override
    @SuppressWarnings({"unchecked"})
    public void setRealAttributeValueInObject(Object target, Object attributeValue) {
        ValueHolderInterface<Object> holder = (ValueHolderInterface<Object>)this.mapping.getAttributeValueFromObject(target);
        if (holder == null) {
            holder = new ValueHolder<>(attributeValue);
        } else {
            holder.setValue(attributeValue);
        }
        super.setRealAttributeValueInObject(target, holder);
    }

    /**
     * INTERNAL:
     * set the source object into QueryBasedValueHolder.
     * Used only by transparent indirection.
     */
    @Override
    @SuppressWarnings({"unchecked"})
    public void setSourceObject(Object sourceObject, Object attributeValue) {
        if (attributeValue instanceof QueryBasedValueHolder) {
            ((QueryBasedValueHolder<Object>)attributeValue).setSourceObject(sourceObject);
        }
    }

    /**
     * INTERNAL:
     *    Return whether the type is appropriate for the indirection policy.
     * In this case, the attribute type MUST be ValueHolderInterface.
     */
    protected boolean typeIsValid(Class<?> attributeType) {
        return attributeType == ClassConstants.ValueHolderInterface_Class ||
            attributeType == ClassConstants.WeavedAttributeValueHolderInterface_Class;
    }

    /**
     * INTERNAL:
     * Verify that the value of the attribute within an instantiated object
     * is of the appropriate type for the indirection policy.
     * In this case, the attribute must be non-null and it must be a
     * ValueHolderInterface.
     * If the value is null return a new indirection object to be used for the attribute.
     */
    @Override
    public Object validateAttributeOfInstantiatedObject(Object attributeValue) {
        // PERF: If the value is null, create a new value holder instance for the attribute value,
        // this allows for indirection attributes to not be instantiated in the constructor as they
        // are typically replaced when reading or cloning so is very inefficient to initialize.
        if (attributeValue == null) {
            return new ValueHolder<>();
        }
        if (!(attributeValue instanceof ValueHolderInterface)) {
            throw DescriptorException.valueHolderInstantiationMismatch(attributeValue, this.mapping);
        }
        return attributeValue;
    }

    /**
     * INTERNAL:
     *    Verify that attributeType is correct for the
     * indirection policy. If it is incorrect, add an exception to the
     * integrity checker.
     * In this case, the attribute type MUST be ValueHolderInterface.
     */
    @Override
    public void validateDeclaredAttributeType(Class<?> attributeType, IntegrityChecker checker) throws DescriptorException {
        super.validateDeclaredAttributeType(attributeType, checker);
        if (!this.typeIsValid(attributeType)) {
            checker.handleError(DescriptorException.attributeAndMappingWithIndirectionMismatch(this.mapping));
        }
    }

    /**
     * INTERNAL:
     *    Verify that getter returnType is correct for the
     * indirection policy. If it is incorrect, add an exception
     * to the integrity checker.
     * In this case, the return type MUST be ValueHolderInterface.
     */
    @Override
    public void validateGetMethodReturnType(Class<?> returnType, IntegrityChecker checker) throws DescriptorException {
        super.validateGetMethodReturnType(returnType, checker);
        if (!this.typeIsValid(returnType)) {
            checker.handleError(DescriptorException.returnAndMappingWithIndirectionMismatch(this.mapping));
        }
    }

    /**
     * INTERNAL:
     *    Verify that setter parameterType is correct for the
     * indirection policy. If it is incorrect, add an exception
     * to the integrity checker.
     * In this case, the parameter type MUST be ValueHolderInterface.
     */
    @Override
    public void validateSetMethodParameterType(Class<?> parameterType, IntegrityChecker checker) throws DescriptorException {
        super.validateSetMethodParameterType(parameterType, checker);
        if (!this.typeIsValid(parameterType)) {
            checker.handleError(DescriptorException.parameterAndMappingWithIndirectionMismatch(this.mapping));
        }
    }

    /**
     * INTERNAL:
     * Return the value to be stored in the object's attribute.
     *    This value is determined by the batchQuery.
     * In this case, wrap the query in a ValueHolder for later invocation.
     */
    @Override
    public Object valueFromBatchQuery(ReadQuery batchQuery, AbstractRecord row, ObjectLevelReadQuery originalQuery, CacheKey parentCacheKey) {
        return new BatchValueHolder<>(batchQuery, row, this.getForeignReferenceMapping(), originalQuery, parentCacheKey);
    }

    /**
     * INTERNAL:
     * Return the value to be stored in the object's attribute.
     * This value is determined by invoking the appropriate
     * method on the object and passing it the row and session.
     * In this case, wrap the row in a ValueHolder for later use.
     */
    @Override
    public Object valueFromMethod(Object object, AbstractRecord row, AbstractSession session) {
        return new TransformerBasedValueHolder<>(this.getTransformationMapping().getAttributeTransformer(), object, row, session);
    }

    /**
     * INTERNAL:
     * Return the value to be stored in the object's attribute.
     *    This value is determined by the query.
     * In this case, wrap the query in a ValueHolder for later invocation.
     */
    @Override
    public Object valueFromQuery(ReadQuery query, AbstractRecord row, Object sourceObject, AbstractSession session) {
        return new QueryBasedValueHolder<>(query, sourceObject, row, session);
    }

    /**
     * INTERNAL:
     * Return the value to be stored in the object's attribute.
     *    This value is determined by the query.
     * In this case, wrap the query in a ValueHolder for later invocation.
     */
    @Override
    public Object valueFromQuery(ReadQuery query, AbstractRecord row, AbstractSession session) {
        return new QueryBasedValueHolder<>(query, row, session);
    }

    /**
     * INTERNAL:
     * Return the value to be stored in the object's attribute.
     *    This value is determined by the row.
     * In this case, simply wrap the object in a ValueHolder.
     */
    @Override
    public Object valueFromRow(Object object) {
        return new ValueHolder<>(object);
    }
}
