/*
 * 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 Feature development
//     12/14/2017-3.0 Tomas Kraus
//       - 522635: ConcurrentModificationException when triggering lazy load from conforming query
package org.eclipse.persistence.sessions.interceptors;

import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.identitymaps.IdentityMap;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;


/**
 * <p>
 * <b>Purpose</b>: Define a class through which Cache access can be
 * intercepted.
 * <p>
 * <b>Description</b>: EclipseLink makes extensive use of caching
 * functionality. This class provides the mechanism for intercepting the cache
 * access. Once intercepted applications can allow the process to continue by
 * calling the method on the class attribute targetIdentityMap as described in
 * the API javadocs or redirect the process entirely. * As with IdentityMaps an
 * entire class inheritance hierarchy will share the same interceptor.
 * <p>
 * To implement a CacheInterceptor users should subclass this class implementing
 * those methods they wish to intercept.
 * <p>
 * <b>Configuration</b>: Interceptors may be added to a session by using a
 * Session or Descriptor customizer to set the class name of the interceptor on
 * the target ClassDescriptor through the method
 * setCacheInterceptorClass(Class).
 */
public abstract class CacheInterceptor implements IdentityMap {
    /**
     * This attribute stores the actual IdentityMap as configured by the user.
     */
    protected IdentityMap targetIdentityMap;

    protected AbstractSession interceptedSession;

    protected CacheInterceptor(IdentityMap targetIdentityMap, AbstractSession interceptedSession){
        this.targetIdentityMap = targetIdentityMap;
        this.interceptedSession = interceptedSession;
    }
    /**
     * Acquire a deferred lock on the object.
     * This is used while reading if the object has relationships without indirection.
     * This first thread will get an active lock.
     * Other threads will get deferred locks, all threads will wait until all other threads are complete before releasing their locks.
     */
    @Override
    public CacheKey acquireDeferredLock(Object primaryKey, boolean isCacheCheckComplete){
        return createCacheKeyInterceptor(this.targetIdentityMap.acquireDeferredLock(primaryKey, isCacheCheckComplete));
    }

    /**
     * Acquire an active lock on the object.
     * This is used by reading (when using indirection or no relationships) and by merge.
     */
    @Override
    public CacheKey acquireLock(Object primaryKey, boolean forMerge, boolean isCacheCheckComplete){
        return createCacheKeyInterceptor(this.targetIdentityMap.acquireLock(primaryKey, forMerge, isCacheCheckComplete));
    }

    /**
     * Acquire an active lock on the object, if not already locked.
     * This is used by merge for missing existing objects.
     */
    @Override
    public CacheKey acquireLockNoWait(Object primaryKey, boolean forMerge){
        CacheKey cacheKeyToBeWrapped = this.targetIdentityMap.acquireLockNoWait(primaryKey, forMerge);
        if (cacheKeyToBeWrapped != null){
            return createCacheKeyInterceptor(cacheKeyToBeWrapped);
        }
        return null;
    }

    /**
     * Acquire an active lock on the object, if not already locked.
     * This is used by merge for missing existing objects.
     */
    @Override
    public CacheKey acquireLockWithWait(Object primaryKey, boolean forMerge, int wait) {
        CacheKey cacheKeyToBeWrapped = this.targetIdentityMap.acquireLockWithWait(primaryKey, forMerge, wait);
        if (cacheKeyToBeWrapped != null) {
            return createCacheKeyInterceptor(cacheKeyToBeWrapped);
        }
        return null;
    }

    /**
     * Acquire a read lock on the object.
     * This is used by UnitOfWork cloning.
     * This will allow multiple users to read the same object but prevent writes to the object while the read lock is held.
     */
    @Override
    public CacheKey acquireReadLockOnCacheKey(Object primaryKey) {
        return createCacheKeyInterceptor(this.targetIdentityMap.acquireReadLockOnCacheKey(primaryKey));
    }

    /**
     * Acquire a read lock on the object, if not already locked.
     * This is used by UnitOfWork cloning.
     * This will allow multiple users to read the same object but prevent writes to the object while the read lock is held.
     */
    @Override
    public CacheKey acquireReadLockOnCacheKeyNoWait(Object primaryKey) {
        CacheKey cacheKeyToBeWrapped = this.targetIdentityMap.acquireReadLockOnCacheKeyNoWait(primaryKey);
        if (cacheKeyToBeWrapped != null){
            return createCacheKeyInterceptor(cacheKeyToBeWrapped);
        }
        return null;
    }

    /**
     * Add all locked CacheKeys to the map grouped by thread.
     * Used to print all the locks in the identity map.
     */
    @Override
    public void collectLocks(HashMap threadList) {
        this.targetIdentityMap.collectLocks(threadList);
    }

    /**
     * Clone the map and all of the CacheKeys.
     * This is used by UnitOfWork commitAndResumeOnFailure to avoid corrupting the cache during a failed commit.
     */
    @Override
    public abstract Object clone();

    /**
     * Return true if an CacheKey with the primary key is in the map.
     * User API.
     * @param primaryKey is the primary key for the object to search for.
     */
    @Override
    public boolean containsKey(Object primaryKey) {
        return this.targetIdentityMap.containsKey(primaryKey);
    }


    protected abstract CacheKeyInterceptor createCacheKeyInterceptor(CacheKey wrappedCacheKey);

    /**
     * Allow for the cache to be iterated on.  This method is only used during debugging when
     * validateCache() has been called to print out the contents of the cache.
     */
    @Override
    public Enumeration elements() {
        return this.targetIdentityMap.elements();
    }

    /**
     * Return the object cached in the identity map or null if it could not be found.
     * User API.
     */
    @Override
    public Object get(Object primaryKey){
        return this.targetIdentityMap.get(primaryKey);
    }

    /**
     * ADVANCED:
     * Using a list of Entity PK this method will attempt to bulk load the entire list from the cache.
     * In certain circumstances this can have large performance improvements over loading each item individually.
     * @param pkList List of Entity PKs to extract from the cache
     * @param descriptor Descriptor type to be retrieved.
     * @return Map of Entity PKs associated to the Entities that were retrieved
     */
    @Override
    public abstract Map<Object, Object> getAllFromIdentityMapWithEntityPK(Object[] pkList, ClassDescriptor descriptor, AbstractSession session);

    /**
     * ADVANCED:
     * Using a list of Entity PK this method will attempt to bulk load the entire list from the cache.
     * In certain circumstances this can have large performance improvements over loading each item individually.
     * @param pkList List of Entity PKs to extract from the cache
     * @param descriptor Descriptor type to be retrieved.
     * @return Map of Entity PKs associated to the Entities that were retrieved
     */
    @Override
    public abstract Map<Object, CacheKey> getAllCacheKeysFromIdentityMapWithEntityPK(Object[] pkList, ClassDescriptor descriptor, AbstractSession session);

    /**
     * Get the cache key (with object) for the primary key.
     */
    @Override
    public CacheKey getCacheKey(Object primaryKey, boolean forMerge) {
        return this.targetIdentityMap.getCacheKey(primaryKey, forMerge);
    }

    /**
     * Get the cache key (with object) for the primary key.
     */
    @Override
    public CacheKey getCacheKeyForLock(Object primaryKey) {
        return this.targetIdentityMap.getCacheKeyForLock(primaryKey);
    }

    /**
     * Return the descriptor that this is the map for.
     */
    @Override
    public ClassDescriptor getDescriptor() {
        return this.targetIdentityMap.getDescriptor();
    }

    /**
     * Return the class that this is the map for.
     */
    @Override
    public Class getDescriptorClass() {
        return this.targetIdentityMap.getDescriptorClass();
    }

    /**
     * @return The maxSize for the IdentityMap (NOTE: some subclasses may use this differently).
     */
    @Override
    public int getMaxSize() {
        return this.targetIdentityMap.getMaxSize();
    }

    /**
     * Return the number of CacheKeys in the IdentityMap.
     * This may contain weak referenced objects that have been garbage collected.
     */
    @Override
    public int getSize() {
        return this.targetIdentityMap.getSize();
    }

    /**
     * Return the number of actual objects of type myClass in the IdentityMap.
     * Recurse = true will include subclasses of myClass in the count.
     */
    @Override
    public int getSize(Class myClass, boolean recurse) {
        return this.targetIdentityMap.getSize(myClass, recurse);
    }

    /**
     * Return the instance of the IdentityMap that this intercpetor is wrapping.  Any call that
     * is to be passed on to the underlying EclipseLink cache should be passed to this IdentityMap.
     */
    public IdentityMap getTargetIdenttyMap() {
        return this.targetIdentityMap;
    }

    /**
     * Get the wrapper object from the cache key associated with the given primary key,
     * this is used for EJB2.
     */
    @Override
    public Object getWrapper(Object primaryKey) {
        return this.targetIdentityMap.getWrapper(primaryKey);
    }

    /**
     * Get the write lock value from the cache key associated to the primarykey.
     * User API.
     */
    @Override
    public Object getWriteLockValue(Object primaryKey) {
        return this.targetIdentityMap.getWriteLockValue(primaryKey);
    }

    /**
     * Allow for the {@link CacheKey} elements to be iterated.
     * {@link CacheKey} {@link Collection} is reused so this iteration may not be thread safe.
     *
     * @return {@link Enumeration} of {@link CacheKey} instances.
     */
    @Override
    public Enumeration<CacheKey> keys() {
        return this.targetIdentityMap.keys();
    }

    /**
     * Allow for the {@link CacheKey} elements to be iterated.
     * Clone of {@link CacheKey} {@link Collection} is returned so this iteration should
     * be thread safe.
     *
     * @return {@link Enumeration} with clone of the {@link CacheKey} {@link Collection}
     */
    @Override
    public Enumeration<CacheKey> cloneKeys() {
        return this.targetIdentityMap.cloneKeys();
    }

    /**
     * Allow for the {@link CacheKey} elements to be iterated.
     * {@link CacheKey} {@link Collection} is reused so this iteration may not be thread safe.
     *
     * @param checkReadLocks value of {@code true} if read lock on the {@link CacheKey}
     *        instances should be checked or {@code false} otherwise
     * @return {@link Enumeration} of {@link CacheKey} instances.
     */
    @Override
    public Enumeration<CacheKey> keys(boolean checkReadLocks) {
        return this.targetIdentityMap.keys(checkReadLocks);
    }

    /**
     * Notify the cache that a lazy relationship has been triggered in the object
     * and the cache may need to be updated
     */
    @Override
    public void lazyRelationshipLoaded(Object rootEntity, ValueHolderInterface valueHolder, ForeignReferenceMapping mapping){
        this.targetIdentityMap.lazyRelationshipLoaded(rootEntity, valueHolder, mapping);
    }

    /**
     * Store the object in the cache at its primary key.
     * This is used by InsertObjectQuery, typically into the UnitOfWork identity map.
     * Merge and reads do not use put, but acquireLock.
     * Also an advanced (very) user API.
     * @param primaryKey is the primary key for the object.
     * @param object is the domain object to cache.
     * @param writeLockValue is the current write lock value of object, if null the version is ignored.
     */
    @Override
    public CacheKey put(Object primaryKey, Object object, Object writeLockValue, long readTime) {
        return this.targetIdentityMap.put(primaryKey, object, writeLockValue, readTime);
    }

    /**
     * Remove the CacheKey with the primaryKey from the map.
     * This is used by DeleteObjectQuery and merge.
     * This is also an advanced (very) user API.
     */
    @Override
    public Object remove(Object primaryKey, Object object) {
        return this.targetIdentityMap.remove(primaryKey, object);
    }

    /**
     * Remove the CacheKey from the map.
     */
    @Override
    public Object remove(CacheKey cacheKey) {
        if (cacheKey.isWrapper()){
            return this.targetIdentityMap.remove(cacheKey.getWrappedCacheKey());
        }
        return this.targetIdentityMap.remove(cacheKey);
    }

    /**
     * This method will be used to update the max cache size, any objects exceeding the max cache size will
     * be remove from the cache. Please note that this does not remove the object from the identityMap, except in
     * the case of the CacheIdentityMap.
     */
    @Override
    public void updateMaxSize(int maxSize){
        this.targetIdentityMap.updateMaxSize(maxSize);
    }

    /**
     * Set the descriptor that this is the map for.
     */
    @Override
    public void setDescriptor(ClassDescriptor descriptor) {
        this.targetIdentityMap.setDescriptor(descriptor);
    }

    /**
     * Update the wrapper object in the CacheKey associated with the given primaryKey,
     * this is used for EJB2.
     */
    @Override
    public void setWrapper(Object primaryKey, Object wrapper) {
        this.targetIdentityMap.setWrapper(primaryKey, wrapper);
    }

    /**
     * Update the write lock value of the CacheKey associated with the given primaryKey.
     * This is used by UpdateObjectQuery, and is also an advanced (very) user API.
     */
    @Override
    public void setWriteLockValue(Object primaryKey, Object writeLockValue) {
        this.targetIdentityMap.setWriteLockValue(primaryKey, writeLockValue);
    }

    @Override
    public String toString() {
        return Helper.getShortClassName("Intercepted " + this.targetIdentityMap.getClass()) + "[" + getSize() + "]";
    }
}
