/*
 * 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:
//     Gordon Yorke - initial API and implementation

package org.eclipse.persistence.internal.indirection;

import java.util.Collection;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;

/**
 * <p>
 * <b>Purpose:</b> In certain cases the contents of a relationship may be
 * retrievable from a cache. This ValueHolder instance provides the mechanism to
 * store a cached relationship and to load that relationship from a cache. This
 * functionality requires that the persistent identities of the targets can be
 * collected as database type foreign key queries are unavailable.
 *
 * @author gyorke
 * @since EclipseLink 1.1
 */
public class CacheBasedValueHolder<T> extends DatabaseValueHolder<T> {

    protected transient ForeignReferenceMapping mapping;
    protected Object[] references;
    /** Setting to force the instantiation of the Collection on modification */
    protected boolean shouldAllowInstantiationDeferral = true;

    public CacheBasedValueHolder(Object[] pks, AbstractRecord foreignKeys, AbstractSession session, ForeignReferenceMapping mapping){
        super();
        this.references = pks;
        this.mapping = mapping;
        this.session = session;
        this.row = foreignKeys;
    }

    public Object[] getCachedPKs(){
        return this.references;
    }


    /**
     * Process against the UOW and attempt to load a local copy before going to the shared cache
     * If null is returned then the calling UOW will instantiate as normal.
     */
    @Override
    @SuppressWarnings({"unchecked"})
    public T getValue(UnitOfWorkImpl uow) {
        if (this.references != null && this.references.length != 0){
            if (mapping.isCollectionMapping()){
                Collection<Object> result = uow.getIdentityMapAccessorInstance().getAllFromIdentityMapWithEntityPK(this.references, this.mapping.getReferenceDescriptor()).values();
                if (result.size() == references.length){
                    ContainerPolicy cp = mapping.getContainerPolicy();
                    Object container = cp.containerInstance(result.size());
                    for (Object object : result){
                        cp.addInto(object, container, uow);
                    }
                    return (T) container;
                }
            }else{
                return (T) uow.getIdentityMapAccessorInstance().getFromIdentityMap(this.references[0], this.mapping.getReferenceClass());
            }
        }
        return null;
    }

    @Override
    protected T instantiate() throws DatabaseException {
        return instantiate(this.session);
    }

    @SuppressWarnings({"unchecked"})
    protected T instantiate(AbstractSession localSession) throws DatabaseException {
        if (session == null){
            throw ValidationException.instantiatingValueholderWithNullSession();
        }
        return (T) mapping.valueFromPKList(references, row, localSession);
    }

    /**
     * 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 synchronized manner
     */
    @Override
    public T instantiateForUnitOfWorkValueHolder(UnitOfWorkValueHolder<T> unitOfWorkValueHolder) {
        return instantiate(unitOfWorkValueHolder.getUnitOfWork());
    }

    @Override
    public boolean isPessimisticLockingValueHolder() {
        return false;
    }

    /**
     * Set if instantiation deferral on modification should be available.
     */
    public void setShouldAllowInstantiationDeferral(boolean shouldAllowInstantiationDeferral){
        this.shouldAllowInstantiationDeferral = shouldAllowInstantiationDeferral;
    }

    /**
     * INTERNAL:
     * Return if add/remove should trigger instantiation or avoid.
     * Current instantiation is avoided is using change tracking.
     */
    @Override
    public boolean shouldAllowInstantiationDeferral() {
        return this.shouldAllowInstantiationDeferral;
    }



}
