/*
 * Copyright (c) 2008, 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:
//     12/04/2008 - 2.0 Darani Yallapragada
//       - 248780: Initial contribution for JPA 2.0
//     06/03/2010 - 2.1 Michael O'Brien
//       - 248780: Refactor Cache Implementation surrounding evict()
//         Fix evict() to handle non-Entity classes
//         Refactor to get IdentityMapAccessor state through EMF reference
//         Refactor dependencies to use Interfaces instead of Impl subclasses
//         Handle no CMPPolicy case for getId()
//         Handle no associated descriptor for Class parameter
//         MappedSuperclasses passed to evict() cause implementing subclasses to be evicted
//         Throw an IAE for Interfaces and Embeddable classes passed to evict()
//
package org.eclipse.persistence.internal.jpa;

import jakarta.persistence.Cache;
import jakarta.persistence.PersistenceException;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.JpaCache;
import org.eclipse.persistence.sessions.IdentityMapAccessor;
import org.eclipse.persistence.sessions.Session;

/**
 * Implements the JPA Cache interface using the EclipseLink cache API through IdentityMapAccessor.
 * @author DaraniY
 */
public class CacheImpl implements JpaCache {

    /** The EntityManagerFactory associated with this Cache */
    private EntityManagerFactoryDelegate emf;

    /**
     */
    public CacheImpl(EntityManagerFactoryDelegate emf) {
        this.emf = emf;
    }

    /**
     * Returns true if the cache contains an Object with the id and Class type, and is valid.
     * @see Cache#contains(Class, Object)
     */
    @Override
    public boolean contains(Class cls, Object id) {
        getEntityManagerFactory().verifyOpen();
        Object pk =  createPrimaryKeyFromId(cls, id);
        if(null == pk) {
            return false;
        }
        ClassDescriptor descriptor = getSession().getClassDescriptor(cls); // getDescriptor() is the same call
        /**
         * Check for no descriptor associated with the class parameter.
         * This will occur if the class represents a MappedSuperclass (concrete or abstract class),
         * an interface or Embeddable class.
         */
        if(null == descriptor) {
            // do not throw an IAException: cache_impl_class_has_no_descriptor_is_not_a_persistent_type - just return false
            return false;
        }

        // we can assume that all implementors of IdentityMapAccessor implement getCacheKeyforObject
        CacheKey key = ((org.eclipse.persistence.internal.sessions.IdentityMapAccessor)getAccessor())
            .getCacheKeyForObject(pk, cls, descriptor, false);
        return key != null && key.getObject() != null &&
            !descriptor.getCacheInvalidationPolicy().isInvalidated(key);
    }

    /**
     * INTERNAL:
     * This private method searches the map of descriptors for possible superclasses to the
     * passed in class parameter and invalidates only entities found in the cache.
     * If the class is not an Entity or MappedSuperclass (such as an Embeddable or plain java class)
     *  - nothing will be evicted
     */
    private void evictAssignableEntitySuperclass(Class possibleSuperclass, Object id) {
        // just remove the parent entity
        for(ClassDescriptor candidateAssignableDescriptor : getSession().getDescriptors().values()) {
            // In EclipseLink we need only remove the root descriptor that is assignable from this possibleSubclass because the recurse flag defaults to true in invalidateClass()
            // what if we have 2 roots (don't check for !candidateAssignableDescriptor.isChildDescriptor())
            if(!candidateAssignableDescriptor.isDescriptorTypeAggregate() && // a !Embeddable check and !EmbeddableCollection check
               possibleSuperclass.isAssignableFrom(candidateAssignableDescriptor.getJavaClass())) {
                // id will be null if this private function was called from evict(class)
                if(null == id) {
                    // set the invalidationState to -1 in the cache of a type that can be assigned to the class parameter
                    // this call will invalidate all assignable subclasses from the level of possibleSubclass] in the subtree
                    // we could either loop through each aDescriptor.getJavaClass()
                    // or
                    // let invalidateClass loop for us by passing in the higher [possibleSubclass] - all subclasses of the first parent entity descriptor will be invalidated in this first call
                    getAccessor().invalidateClass(candidateAssignableDescriptor.getJavaClass());
                } else {
                    // evict the class instance that corresponds to the id
                    // initialize the cache of a type that can be assigned to the class parameter
                    getAccessor().invalidateObject(createPrimaryKeyFromId(possibleSuperclass, id), candidateAssignableDescriptor.getJavaClass());
                }
            }
        }
    }

    /**
     * Sets an Object with the id and Class type to be invalid in the cache.
     * Remove the data for entities of the specified class (and its
     * subclasses) from the cache.<p>
     * If the class is a MappedSuperclass then the first entity above in the inheritance hierarchy will be evicted
     *   along with all implementing subclasses
     * If the class is not an Entity or MappedSuperclass but is the root of an entity inheritance tree then
     *   evict the subtree
     * If the class is not an Entity or MappedSuperclass but inherits from one then
     *   evict up to root descriptor
     * @see Cache#evict(Class, Object)
     * @param classToEvict - class to evict - usually representing an Entity or MappedSuperclass
     * @param id - Primary key of the Entity or MappedSuperclass Class
     *    A null id means invalidate the class - possibly the entire tree or subtree
     */
    @Override
    public void evict(Class classToEvict, Object id) {
        evict(classToEvict, id, false);
    }

    /**
     * Sets an Object with the id and Class type to be invalid in the cache.
     * Remove the data for entities of the specified class (and its
     * subclasses) from the cache.<p>
     * If the class is a MappedSuperclass then the first entity above in the inheritance hierarchy will be evicted
     *   along with all implementing subclasses
     * If the class is not an Entity or MappedSuperclass but is the root of an entity inheritance tree then
     *   evict the subtree
     * If the class is not an Entity or MappedSuperclass but inherits from one then
     *   evict up to root descriptor
     * @see Cache#evict(Class, Object)
     * @param classToEvict - class to evict - usually representing an Entity or MappedSuperclass
     * @param id - Primary key of the Entity or MappedSuperclass Class
     *    A null id means invalidate the class - possibly the entire tree or subtree
     * @param invalidateInCluster - Invalidate the object id in the cluster, this only applies to a non-null id.
     */
    @Override
    public void evict(Class classToEvict, Object id, boolean invalidateInCluster) {
        getEntityManagerFactory().verifyOpen();
        /**
         * The following descriptor lookup will return the Entity representing the classToEvict parameter,
         * or it will return the first Entity superclass of a MappedSuperclass in the hierarchy
         * - in this case all subclasses of the parent Entity will be evicted.
         * The descriptor will be null if the classToEvict represents a non-Entity or non-MappedSuperclass like an Embeddable or plain java class
         * - in this case nothing will be evicted.
         */
        ClassDescriptor aPossibleSuperclassDescriptor = getSession().getClassDescriptor(classToEvict);
        // Do not recurse if the class to evict is below its' descriptor in the inheritance tree
        if(null != aPossibleSuperclassDescriptor) {
            // Evict all Entity or MappedSuperclass classes
            if(null != id) {
                Object cacheKey = createPrimaryKeyFromId(classToEvict, id);
                if(null != cacheKey) {
                    getAccessor().invalidateObject(cacheKey, classToEvict, invalidateInCluster);
                }
            } else {
                // 312503: always evict all implementing entity subclasses of an entity or mappedSuperclass
                boolean invalidateRecursively = aPossibleSuperclassDescriptor.getJavaClass().equals(classToEvict);
                getAccessor().invalidateClass(classToEvict, invalidateRecursively);
            }
        } else {
            // Evict the first possible parent Entity superclass of a non-Entity and non-MappedSuperclass class
            evictAssignableEntitySuperclass(classToEvict, id);
        }
    }

    /**
     * Sets all instances of the class to be invalid.
     * Remove the data for entities of the specified class (and its
     * subclasses) from the cache.<p>
     * If the class is a MappedSuperclass then the first entity above in the inheritance hierarchy will be evicted
     *   along with all implementing subclasses
     * If the class is not an Entity or MappedSuperclass (such as an Embeddable or plain java class)
     *  - nothing will be evicted
     * @see Cache#evict(Class)
     * @param entityOrMappedSuperclassToEvict - Entity or MappedSuperclass Class
     */
    @Override
    public void evict(Class entityOrMappedSuperclassToEvict) {
        // A null id means invalidate the class - possibly the entire tree or subtree
        evict(entityOrMappedSuperclassToEvict, null);
    }

    /**
     * Sets all instances in the cache to be invalid.
     * @see Cache#evictAll()
     */
    @Override
    public void evictAll() {
        getEntityManagerFactory().verifyOpen();
        getEntityManagerFactory().getDatabaseSession().getIdentityMapAccessor().invalidateAll();
    }

    /**
     * Return the EclipseLink cache key object from the JPA Id object.
     */
    private Object createPrimaryKeyFromId(Class cls, Object id) {
        Object cacheKey = null;
        ClassDescriptor aDescriptor = getSession().getDescriptor(cls);
        // Check that we have a descriptor associated with the class (Entity or MappedSuperclass)
        if(null == aDescriptor) {
            // No descriptor found, throw exception for Embeddable or non-persistable java class
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "cache_impl_class_has_no_descriptor_is_not_a_persistent_type",
                    new Object[] {cls}));
        }
        // The policy is not set if the mapping is natively defined outside of JPA
        if(aDescriptor.hasCMPPolicy()) {
            // we assume that the PK id parameter is correct and do not throw a cache_descriptor_has_no_cmppolicy_set_cannot_create_primary_key exception
            // The primaryKey may be the same object as the id parameter
            cacheKey = aDescriptor.getCMPPolicy().createPrimaryKeyFromId(id, getEntityManagerFactory().getDatabaseSession());
        }
        return cacheKey;
    }

    /**
     * ADVANCED:
     * Resets the entire Object cache, and the Query cache.
     * <p> NOTE: Be careful using this method. This method blows away both this session's and its parent's caches.
     * This includes the server cache or any other cache. This throws away any Objects that have been read in.
     * Extreme caution should be used before doing this because Object identity will no longer
     * be maintained for any Objects currently read in.  This should only be called
     * if the application knows that it no longer has references to Objects held in the cache.
     */
    @Override
    public void clear() {
        getEntityManagerFactory().verifyOpen();
        getAccessor().initializeAllIdentityMaps();
    }

    /**
     * ADVANCED:
     * Resets the cache for only the instances of the given Class type.
     * For inheritance the user must make sure that they only use the root class,
     * clearing a subclass cache is not allowed (as they share their parents cache).
     * <p> NOTE: Caution must be used in doing this to ensure that the Objects within the cache
     * are not referenced from other Objects of other classes or from the application.
     */
    @Override
    public void clear(Class cls) {
        getEntityManagerFactory().verifyOpen();
        getAccessor().initializeIdentityMap(cls);
    }

    /**
     * Clear all the query results caches.
     */
    @Override
    public void clearQueryCache() {
        getEntityManagerFactory().verifyOpen();
        getAccessor().clearQueryCache();
    }

    /**
     * Clear the named query results cache associated with the query name.
     */
    @Override
    public void clearQueryCache(String queryName) {
        getEntityManagerFactory().verifyOpen();
        getAccessor().clearQueryCache(queryName);
    }

    /**
     * Clear all named query results cache associated with entity class.
     */
    @Override
    public void clearQueryCache(Class entityClass) {
        getEntityManagerFactory().verifyOpen();
        getAccessor().invalidateQueryCache(entityClass);
    }

    /**
     * Returns the remaining life of the given Object (in milliseconds).  This method is associated with use of
     * cache invalidation feature and returns the difference between the next expiry
     * time of the Object and its read time.  The method will return 0 for invalidated Objects.
     */
    @Override
    public long timeToLive(Object object) {
        getEntityManagerFactory().verifyOpen();
        return getAccessor().getRemainingValidTime(object);
    }

    /**
     * Returns true if the Object with the same id and Class type of the
     * the given Object is valid in the cache.
     */
    @Override
    public boolean isValid(Object object) {
        getEntityManagerFactory().verifyOpen();
        return getAccessor().isValid(object);
    }

    /**
     * Returns true if the Object with the id and Class type is valid in the cache.
     */
    @Override
    public boolean isValid(Class cls, Object id) {
        getEntityManagerFactory().verifyOpen();
        Object cacheKey = createPrimaryKeyFromId(cls, id);
        if(null != cacheKey) {
            return getAccessor().isValid(cacheKey, cls);
        } else {
            return false;
        }
    }

    /**
     * Used to print all the Objects in the cache.
     * The output of this method will be logged to this persistence unit's SessionLog at SEVERE level.
     */
    @Override
    public void print() {
        getEntityManagerFactory().verifyOpen();
        getAccessor().printIdentityMaps();
    }

    /**
     * Used to print all the Objects in the cache of the Class type.
     * The output of this method will be logged to this persistence unit's SessionLog at SEVERE level.
     */
    @Override
    public void print(Class cls) {
        getEntityManagerFactory().verifyOpen();
        getAccessor().printIdentityMap(cls);
    }

    /**
     * Used to print all the currently locked cache keys in the cache.
     * The output of this method will be logged to this persistence unit's SessionLog at SEVERE level.
     */
    @Override
    public void printLocks() {
        getEntityManagerFactory().verifyOpen();
        getAccessor().printIdentityMapLocks();
    }

    /**
     * This can be used to help debugging an Object identity problem.
     * An Object identity problem is when an Object in the cache references an
     * Object that is not in the cache. This method will validate that all cached
     * Objects are in a correct state.
     */
    @Override
    public void validate() {
        getEntityManagerFactory().verifyOpen();
        getAccessor().validateCache();
    }

    /**
     * Returns the Object from the cache map with the id
     * and Class type.
     */
    @Override
    public Object getObject(Class cls, Object id) {
        getEntityManagerFactory().verifyOpen();
        Object cacheKey = createPrimaryKeyFromId(cls, id);
        return getAccessor().getFromIdentityMap(cacheKey, cls);
    }

    /**
     * ADVANCED:
     * Puts the given Object into the cache.
     * This is a very advanced method, and caution should be used in adding objects to the cache
     * as other objects may have relationships to previous object, or this object may have
     * relationships to other objects.
     */
    @Override
    public Object putObject(Object object) {
        getEntityManagerFactory().verifyOpen();
        return getAccessor().putInIdentityMap(object);
    }

    /**
     * ADVANCED:
     * Removes the Object from the cache.
     * <p> NOTE: Caution should be used when calling to avoid violating Object identity.
     * The application should only call this if its known that no references to the Object exist.
     */
    @Override
    public Object removeObject(Object object) {
        getEntityManagerFactory().verifyOpen();
        return getAccessor().removeFromIdentityMap(object);
    }

    /**
     * ADVANCED:
     * Removes the Object with the id and Class type from the cache.
     * <p> NOTE: Caution should be used when calling to avoid violating Object identity.
     * The application should only call this if its known that no references to the Object exist.
     */
    @Override
    public Object removeObject(Class cls, Object id) {
        getEntityManagerFactory().verifyOpen();
        Object cacheKey = createPrimaryKeyFromId(cls, id);
        return getAccessor().removeFromIdentityMap(cacheKey, cls);
    }

    /**
     * Returns true if the cache contains an Object with the same id and Class type of the given object.
     */
    @Override
    public boolean contains(Object object) {
        return contains(object.getClass(), getId(object));
    }

    /**
     * Sets the object to be invalid in the cache.
     * @see JpaCache#evict(Object)
     */
    @Override
    public void evict(Object object) {
        getEntityManagerFactory().verifyOpen();
        getAccessor().invalidateObject(object);
    }


    /**
     * Sets an Object to be invalid in the cache.
     * If true is passed, the object is also invalidated across cache coordination.
     * Cache coordination must be enabled for this to have an affect.
     */
    @Override
    public void evict(Object object, boolean invalidateInCluster) {
        getEntityManagerFactory().verifyOpen();
        getAccessor().invalidateObject(object, invalidateInCluster);
    }

    /**
     * INTERNAL:
     * Return the EntityManagerFactory associated with this CacheImpl.
     */
    protected EntityManagerFactoryDelegate getEntityManagerFactory() {
        return this.emf;
    }

    /**
     * INTERNAL:
     * Return the Session associated with the EntityManagerFactory.
     */
    protected Session getSession() {
        return getEntityManagerFactory().getDatabaseSession();
    }

    /**
     * INTERNAL:
     * Return the IdentityMapAccessor associated with the session on the EntityManagerFactory on this CacheImpl.
     */
    protected IdentityMapAccessor getAccessor() {
        return getSession().getIdentityMapAccessor();
    }

    /**
     * This method will return the objects's Id.
     * If the descriptor associated with the domain object is null - an IllegalArgumentException is thrown.
     * If the CMPPolicy associated with the domain object's descriptor is null
     * the Id will be determined using the ObjectBuilder on the descriptor - which may return
     * the Id stored in the weaved _persistence_primaryKey field.
     * @see JpaCache#getId(Object)
     */
    @Override
    public Object getId(Object object) {
        getEntityManagerFactory().verifyOpen();
        ClassDescriptor aDescriptor = getSession().getDescriptor(object.getClass());
        // Handle a null descriptor from a detached entity (closed EntityManager), or the entity exists in another session
        if(null == aDescriptor) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage(
                    "cache_impl_object_has_no_descriptor_is_not_a_persistent_type",
                    new Object[] {object}));
        }

        // Handle a null CMPPolicy from a MappedSuperclass
        if(!aDescriptor.hasCMPPolicy()) {
            // the following code gets the key either from the weaved _persistence_primaryKey field or using valueFromObject() if not bytecode enhanced
            return aDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, (AbstractSession)getSession());
        } else {
            // Get identifier via EMF
            return getEntityManagerFactory().getIdentifier(object);
        }
    }

    @Override
    public <T> T unwrap(Class<T> cls) {
        if (cls.equals(JpaCache.class)){
            return (T) this;
        }
        if (cls.equals(IdentityMapAccessor.class)){
            return (T) getAccessor();
        }
        throw new PersistenceException(ExceptionLocalization.buildMessage("unable_to_unwrap_jpa", new String[]{Cache.class.getName(),cls.getName()}));
    }
}
