/*
 * Copyright (c) 2008, 2020 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;

    /**
     * @param 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
     * @param possibleSuperclass
     * @param id
     */
    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.
     * @return
     */
    protected EntityManagerFactoryDelegate getEntityManagerFactory() {
        return this.emf;
    }

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

    /**
     * INTERNAL:
     * Return the IdentityMapAccessor associated with the session on the EntityManagerFactory on this CacheImpl.
     * @return
     */
    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()}));
    }
}
