/*
 * 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.sessions.remote;

import java.rmi.server.ObjID;
import java.io.*;
import org.eclipse.persistence.sessions.remote.*;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.indirection.*;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.indirection.*;
import org.eclipse.persistence.mappings.*;

/**
 * Remote value holders can be invoked locally and remotely.
 * In both situations the associated indirect object is invoked.
 */
public class RemoteValueHolder<T> extends DatabaseValueHolder<T> implements Externalizable {
    // This is a unique id for remote value holder.
    protected ObjID id;

    // Primary key row for target object.
    protected Object targetObjectPrimaryKeys;
    protected transient DatabaseMapping mapping;
    protected transient ObjectLevelReadQuery query;

    // The server side original value holder.
    protected transient ValueHolderInterface<T> wrappedServerValueHolder;

    // point back to the object holding the remote value holder;
    // for the moment, used only by TransparentIndirection
    protected transient Object serverIndirectionObject;

    public RemoteValueHolder() {
        // This assigns unique id to the remote value holder when it is created.
        this.id = new ObjID();
    }

    public RemoteValueHolder(ObjID id) {
        this.id = id;
    }

    /**
     * If the reference object is mapped thru one to one mapping and the object derives its primary key value
     * from this relationship then remote value holder has a primary key row for.
     */
    protected boolean canDoCacheCheck() {
        if ((getMapping() == null) || (getQuery() == null)) {
            return false;
        }

        return (getTargetObjectPrimaryKeys() != null) && getMapping().isOneToOneMapping() && (!getQuery().shouldRefreshIdentityMapResult()) && (!getQuery().shouldRefreshRemoteIdentityMapResult()) && (getQuery().shouldMaintainCache());
    }

    /**
     * Only the id is checked for equality check.
     */
    @Override
    public boolean equals(Object object) {
        if (!(object instanceof RemoteValueHolder)) {
            return false;
        }

        return getID().equals(((RemoteValueHolder<?>)object).getID());
    }

    /**
     * This method is used to remove the RemoteValueHolder from the dispatcher on Garbage
     * collection from the client
     */
    @Override
    public void finalize() {
        if ((this.session != null) && (this.session instanceof RemoteSession) && ((RemoteSession)this.session).shouldEnableDistributedIndirectionGarbageCollection()) {
            // This must be on the client
            RemoveServerSideRemoteValueHolderCommand command = new RemoveServerSideRemoteValueHolderCommand(getID());
            ((DistributedSession)getSession()).getRemoteConnection().processCommand(command);
            //remove this value holder from the session dispatcher as it will no longer be needed
        }
    }

    /**
     * Return the unique id.
     */
    public ObjID getID() {
        return id;
    }

    /**
     * Return the associated mapping.
     */
    public DatabaseMapping getMapping() {
        return mapping;
    }

    /**
     * Get object from the cache if there is one.
     */
    protected Object getObjectFromCache() {
        Object cachedObject = null;

        if (getMapping().isOneToOneMapping()) {
            ClassDescriptor descriptor = getMapping().getReferenceDescriptor();
            cachedObject = getSession().getIdentityMapAccessorInstance().getFromIdentityMap(getTargetObjectPrimaryKeys(), descriptor.getJavaClass(), descriptor);
        }

        return cachedObject;
    }

    /**
     * Return the associated query.
     */
    public ObjectLevelReadQuery getQuery() {
        return query;
    }

    /**
     * Return the object on the server that holds on
     * to the remote value holder.
     * Currently used only by TransparentIndirection so we
     * can get back to the original IndirectContainer.
     */
    public Object getServerIndirectionObject() {
        return serverIndirectionObject;
    }

    /**
     * Get target object primary key row.
     */
    protected Object getTargetObjectPrimaryKeys() {
        return targetObjectPrimaryKeys;
    }

    /**
     * Return the original value holder.
     * This is null on the client side because it is tagged transient.
     * This is how we know whether the remote value holder is
     * being invoked on the client or on the server.
     */
    public ValueHolderInterface<T> getWrappedServerValueHolder() {
        return wrappedServerValueHolder;
    }

    /**
     * Return the hashcode for id, because it is unqiue.
     */
    @Override
    public int hashCode() {
        return getID().hashCode();
    }

    /**
     * Return the object.
     */
    @Override
    @SuppressWarnings({"unchecked"})
    public synchronized T instantiate() {
        T valueOfServerValueHolder = null;

        if (getWrappedServerValueHolder() != null) {// server invocation
            valueOfServerValueHolder = getWrappedServerValueHolder().getValue();
        } else {// client invocation
            // check whether object exists on the client
            if (canDoCacheCheck()) {
                valueOfServerValueHolder = (T) getObjectFromCache();
            }

            // does not exist on the client - so invoke the value holder on the server
            if (valueOfServerValueHolder == null) {
                valueOfServerValueHolder = (T) ((DistributedSession)getSession()).instantiateRemoteValueHolderOnServer(this);
            }
        }
        return valueOfServerValueHolder;
    }

    /**
     * INTERNAL:
     * Answers if this valueholder is easy to instantiate.
     * @return true if getValue() won't trigger a database read.
     */
    @Override
    public boolean isEasilyInstantiated() {
        // Nothing is easily instantiated when on the client side.
        return this.isInstantiated || ((this.wrappedServerValueHolder != null)
                && (!(this.wrappedServerValueHolder instanceof DatabaseValueHolder) || ((DatabaseValueHolder<T>)this.wrappedServerValueHolder).isEasilyInstantiated()));
    }

    /**
     * INTERNAL:
     * Answers if this valueholder is a pessimistic locking one.  Such valueholders
     * are special in that they can be triggered multiple times by different
     * UnitsOfWork.  Each time a lock query will be issued.  Hence even if
     * instantiated it may have to be instantiated again, and once instantatiated
     * all fields can not be reset.
     * Note: This method is not thread-safe.  It must be used in a synchronizaed manner
     */
    @Override
    public boolean isPessimisticLockingValueHolder() {
        // This abstract method needs to be implemented but is not meaningfull for
        // this subclass.
        if (getWrappedServerValueHolder() != null) {
            return ((getWrappedServerValueHolder() instanceof DatabaseValueHolder) && ((DatabaseValueHolder<T>)getWrappedServerValueHolder()).isPessimisticLockingValueHolder());
        } else {
            // Pessimistic locking may not be supported on remote sessions, but if
            // it is make every attempt to do the right thing.
            return ((getQuery() != null) && getQuery().isLockQuery(getSession()));
        }
    }

    /**
     * Triggers UnitOfWork valueholders directly without triggering the wrapped
     * valueholder (this).
     * <p>
     * When in transaction and/or for pessimistic locking the UnitOfWorkValueHolder
     * needs to be triggered directly without triggering the wrapped valueholder.
     * However only the wrapped valueholder knows how to trigger the indirection,
     * i.e. it may be a batchValueHolder, and it stores all the info like the row
     * and the query.
     * Note: This method is not thread-safe.  It must be used in a synchronizaed manner
     */
    @Override
    public T instantiateForUnitOfWorkValueHolder(UnitOfWorkValueHolder<T> unitOfWorkValueHolder) {
        if ((getWrappedServerValueHolder() != null) && (getWrappedServerValueHolder() instanceof DatabaseValueHolder)) {
            DatabaseValueHolder<T> wrapped = (DatabaseValueHolder<T>)getWrappedServerValueHolder();
            return wrapped.instantiateForUnitOfWorkValueHolder(unitOfWorkValueHolder);
        }

        // The scenario of triggering a valueholder in transaction when
        // the RemoteUnitOfWork is on the client side may be impossible.
        return unitOfWorkValueHolder.buildCloneFor(getValue());
    }

    /**
     *  Override the default serialization for a remote valueholder so as not to serialize the value
     *  Note: Changed for bug 3145211.  We used to use the java.io.Serializable interface, but need to convert
     *  to Externalizable interface to avoid sending extra data through the superclass's serialization
     */
    @Override
    public void readExternal(ObjectInput in) throws IOException, java.lang.ClassNotFoundException {
        this.id = (ObjID)in.readObject();
        this.targetObjectPrimaryKeys = in.readObject();
        this.row = (AbstractRecord)in.readObject();
        this.isInstantiated = in.readBoolean();
    }

    /**
     * Set the unique id.
     */
    protected void setID(ObjID anID) {
        this.id = anID;
    }

    /**
     * Set mapping
     */
    public void setMapping(DatabaseMapping mapping) {
        this.mapping = mapping;
    }

    /**
     * Set the query.
     */
    public void setQuery(ObjectLevelReadQuery query) {
        this.query = query;
    }

    /**
     * Set the object on the server that holds on
     * to the remote value holder.
     * Currently used only by TransparentIndirection so we
     * can get back to the original IndirectContainer.
     */
    public void setServerIndirectionObject(Object serverIndirectionObject) {
        this.serverIndirectionObject = serverIndirectionObject;
    }

    /**
     * Set target object primary keys.
     */
    public void setTargetObjectPrimaryKeys(Object primaryKeys) {
        this.targetObjectPrimaryKeys = primaryKeys;
    }

    /**
     * Set the object.
     */
    @Override
    public void setValue(T theValue) {
        super.setValue(theValue);
        if (getWrappedServerValueHolder() != null) {
            // This is a local setting of remote value holder
            // and will only happen with basic indirection
            getWrappedServerValueHolder().setValue(theValue);
        }
    }

    /**
     * Set the original value holder.
     */
    public void setWrappedServerValueHolder(ValueHolderInterface<T> wrappedServerValueHolder) {
        this.wrappedServerValueHolder = wrappedServerValueHolder;
    }

    /**
     *  Override the default serialization for a remote valueholder so as not to serialize the value
     *  Note: Changed for bug 3145211.  We used to use the java.io.Serializable interface, but need to convert
     *  to Externalizable interface to avoid sending extra data through the superclass's serialization
     */
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(id);
        out.writeObject(targetObjectPrimaryKeys);
        out.writeObject(row);
        out.writeBoolean(false);
    }
}
