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

import java.util.*;

import org.eclipse.persistence.config.ReferenceMode;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.history.AsOfClause;
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
import org.eclipse.persistence.internal.sessions.*;
import org.eclipse.persistence.internal.sessions.remote.*;
import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.internal.queries.*;
import org.eclipse.persistence.sessions.Login;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.internal.sequencing.Sequencing;
import org.eclipse.persistence.internal.sequencing.SequencingFactory;
import org.eclipse.persistence.logging.SessionLog;

/**
 * <b>Purpose</b>: Provide transparent remote three-tiered replacation support.
 * The remote session allows for complex three-tiered applications to be easily built.
 * It gives the remote client the fully functionality of the TopLink api including,
 * <ul>
 * <li>Client side caching and object-identity maintainence.
 * <li>Complex query support
 * <li>Unit of work support
 * <li>Indirection support through remote value holders.
 * </ul>
 *
 * This session is a primary interface which resides on the client side. Users would interact
 * with session just the same way as if it was a normal session.
 */
public class RemoteSession extends DistributedSession {
    protected Sequencing sequencing;
    protected boolean shouldEnableDistributedIndirectionGarbageCollection = false;

    public RemoteSession() {
        super(0);
    }

    /**
     * PUBLIC:
     * Creates a RemoteSession.
     * @param remoteConnection remote session requires a remote connection. This must be accessed remotely from the client through RMI or CORBA.
     */
    public RemoteSession(RemoteConnection remoteConnection) {
        super(remoteConnection);
        initializeSequencing();
    }

    /**
     * ADVANCED:
     * Allow the server-side value holders to be cleaned-up when the client-side value holder finalize.
     */
    public void setShouldEnableDistributedIndirectionGarbageCollection(boolean shouldEnableDistributedIndirectionGarbageCollection) {
        this.shouldEnableDistributedIndirectionGarbageCollection = shouldEnableDistributedIndirectionGarbageCollection;
    }

    /**
     * ADVANCED:
     * Allow the server-side value holders to be cleaned-up when the client-side value holder finalize.
     */
    public boolean shouldEnableDistributedIndirectionGarbageCollection() {
        return shouldEnableDistributedIndirectionGarbageCollection;
    }

    /**
     * INTERNAL:
     * Acquires a special historical session for reading objects as of a past time.
     */
    @Override
    public Session acquireHistoricalSession(AsOfClause clause) throws ValidationException {
        throw ValidationException.cannotAcquireHistoricalSession();
    }

    /**
     * PUBLIC:
     * Return a unit of work for this session.
     * The unit of work is an object level transaction that allows
     * a group of changes to be applied as a unit.
     *
     * @see UnitOfWorkImpl
     */
    @Override
    public UnitOfWorkImpl acquireUnitOfWork() {
        return acquireUnitOfWork(null);
    }

    /**
     * PUBLIC:
     * Return a unit of work for this session.
     * The unit of work is an object level transaction that allows
     * a group of changes to be applied as a unit.
     *
     * @see UnitOfWorkImpl
     * @param referenceMode The reference type the UOW should use internally when
     * referencing Working clones.  Setting this to WEAK means the UOW will use
     * weak references to reference clones and if the application no longer
     * references the clone the clone may be garbage collected.  If the clone
     * has uncommitted changes then those changes will be lost.
     */
    @Override
    public UnitOfWorkImpl acquireUnitOfWork(ReferenceMode referenceMode) {
        log(SessionLog.FINER, SessionLog.TRANSACTION, "acquire_unit_of_work");
        setNumberOfActiveUnitsOfWork(getNumberOfActiveUnitsOfWork() + 1);
        return new RemoteUnitOfWork(this, referenceMode);
    }

    /**
     * PUBLIC:
     * Return a repeatable write unit of work for this session.
     * A repeatable write unit of work allows multiple writeChanges (flushes).
     *
     * @see RepeatableWriteUnitOfWork
     */
    @Override
    public RepeatableWriteUnitOfWork acquireRepeatableWriteUnitOfWork(ReferenceMode referenceMode) {
        return new RemoteUnitOfWork(this, referenceMode);
    }

    /**
     * PUBLIC:
     * Execute the database query.
     */
    @Override
    public Object executeQuery(DatabaseQuery query) {
        return query.remoteExecute(this);
    }


    /**
     * PUBLIC:
     * Return the login.
     * This must retrieve the login information from the server this first time called.
     * This is useful to be able to do things differently depending on the database platform.
     */
    @Override
    public Login getDatasourceLogin() {
        Login login = super.getDatasourceLogin();
        if ((login == null) && (getRemoteConnection() != null)) {
            startOperationProfile(SessionProfiler.RemoteMetadata, null, SessionProfiler.ALL);
            login = getRemoteConnection().getLogin();
            endOperationProfile(SessionProfiler.RemoteMetadata, null, SessionProfiler.ALL);
            setDatasourceLogin(login);
        }

        return login;
    }

    /**
     * INTERNAL:
     * Return the corresponding objects from the remote session for the objects read from the server.
     */
    @Override
    public Object getObjectCorrespondingTo(Object serverSideDomainObject, Map<Object, ObjectDescriptor> objectDescriptors, Map<Object, Object> processedObjects, ObjectLevelReadQuery query) {
        if (serverSideDomainObject == null) {
            return null;
        }

        ClassDescriptor descriptor = getDescriptor(serverSideDomainObject);

        // CR... fix to descriptor iterator exposed the bug that we were putting aggregate-collections in the cache.
        if (descriptor.isAggregateCollectionDescriptor() || ((query != null) && (!query.shouldMaintainCache()))) {
            if ((query != null) && (!query.hasPartialAttributeExpressions())) {
                descriptor.getObjectBuilder().fixObjectReferences(serverSideDomainObject, objectDescriptors, processedObjects, query, this);
            }
            return serverSideDomainObject;
        }

        // Extract the object primary key and check if it exist on the remote session or not. If we find an object
        // with this primary key then that's the corresponding object. Other wise its a new object for the remote
        // session which needs to be registered in the remote sessions identity map and this is also a corresponding
        // object.
        ObjectDescriptor objectDescriptor = objectDescriptors.get(serverSideDomainObject);
        if (objectDescriptor == null){
            //the object must have been added concurrently before serialize generate a new ObjectDescriptor on this side
            objectDescriptor = new ObjectDescriptor();
            objectDescriptor.setKey(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(serverSideDomainObject, this));
            objectDescriptor.setObject(serverSideDomainObject);
            OptimisticLockingPolicy policy = descriptor.getOptimisticLockingPolicy();
            if (policy == null){
                objectDescriptor.setWriteLockValue(null);
            }else{
                objectDescriptor.setWriteLockValue(policy.getBaseValue());
            }
            objectDescriptors.put(serverSideDomainObject, objectDescriptor);
        }
        Object primaryKey = objectDescriptor.getKey();
        Object clientSideDomainObject = getIdentityMapAccessorInstance().getFromIdentityMap(primaryKey, serverSideDomainObject.getClass(), descriptor);

        // If object is already processed the return back, this check must be done after the cliet-side object is found.
        if (processedObjects.containsKey(serverSideDomainObject)) {
            if (clientSideDomainObject == null) {
                return serverSideDomainObject;
            } else {
                return clientSideDomainObject;
            }
        }

        processedObjects.put(serverSideDomainObject, serverSideDomainObject);

        if (clientSideDomainObject == null) {
            getIdentityMapAccessorInstance().putInIdentityMap(serverSideDomainObject, primaryKey, objectDescriptor.getWriteLockValue(), objectDescriptor.getReadTime(), descriptor);
            descriptor.getObjectBuilder().fixObjectReferences(serverSideDomainObject, objectDescriptors, processedObjects, query, this);
            clientSideDomainObject = serverSideDomainObject;
        } else {
            // if the query is null, that means we refreshed a newly-created client object at some point
            // and we should refresh the identity map and cascade private parts
            if ((query == null) || (query.shouldRefreshRemoteIdentityMapResult()) || getDescriptor(clientSideDomainObject).shouldAlwaysRefreshCacheOnRemote()) {
                MergeManager mergeManager = new MergeManager(this);
                mergeManager.refreshRemoteObject();
                mergeManager.setObjectDescriptors(objectDescriptors);
                if (query == null) {
                    mergeManager.cascadePrivateParts();
                } else {
                    mergeManager.setCascadePolicy(query.getCascadePolicy());
                }
                clientSideDomainObject = mergeManager.mergeChanges(serverSideDomainObject, null, this);
            }
        }

        return clientSideDomainObject;
    }

    /**
     * INTERNAL:
     * Return the corresponding objects from the remote session for the objects read from the server.
     */
    @Override
    public Object getObjectsCorrespondingToAll(Object serverSideDomainObjects, Map<Object, ObjectDescriptor> objectDescriptors, Map<Object, Object> processedObjects, ObjectLevelReadQuery query, ContainerPolicy containerPolicy) {
        Object clientSideDomainObjects = containerPolicy.containerInstance(containerPolicy.sizeFor(serverSideDomainObjects));

        for (Object iter = containerPolicy.iteratorFor(serverSideDomainObjects);
                 containerPolicy.hasNext(iter);) {
            Object serverSideDomainObject = containerPolicy.next(iter, this);
            containerPolicy.addInto(getObjectCorrespondingTo(serverSideDomainObject, objectDescriptors, processedObjects, query), clientSideDomainObjects, this);
        }

        return clientSideDomainObjects;
    }

    /**
     * INTERNAL:
     * This will instantiate value holder on the server.
     */
    @Override
    public Object instantiateRemoteValueHolderOnServer(RemoteValueHolder remoteValueHolder) {
        startOperationProfile(SessionProfiler.RemoteLazy, null, SessionProfiler.ALL);
        Transporter transporter = getRemoteConnection().instantiateRemoteValueHolderOnServer(remoteValueHolder);
        endOperationProfile(SessionProfiler.RemoteLazy, null, SessionProfiler.ALL);
        return remoteValueHolder.getMapping().getObjectCorrespondingTo(transporter.getObject(), this, transporter.getObjectDescriptors(), new IdentityHashMap<>(), remoteValueHolder.getQuery());
    }

    /**
     * INTERNAL:
     * Return if this session is remote.
     */
    @Override
    public boolean isRemoteSession() {
        return true;
    }

    /**
     * INTERNAL:
     * Return the Sequencing object used by the session.
     * Sequences may be provided locally, or remotely.
     */
    @Override
    public Sequencing getSequencing() {
        if (this.isMetadataRemote) {
            return this.sequencing;
        } else {
            return super.getSequencing();
        }
    }

    /**
     * ADVANCED:
     * Creates sequencing object for the session.
     * Sequences may be provided locally, or remotely.
     */
    @Override
    public void initializeSequencing() {
        if (this.isMetadataRemote) {
            this.sequencing = SequencingFactory.createSequencing(this);
        } else {
            super.initializeSequencing();
        }
    }
}
