/*
 * 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
//     31/05/2010-2.1 Michael O'Brien
//         - 312503: invalidateClass(Class, recurseFlag) - when recurseFlag=false
//         (non-default) will now invalidate the implementing subtree
//           from [Class] down.  Previously only the single Class inside the tree was invalidated.
package org.eclipse.persistence.internal.sessions;

import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.descriptors.CacheIndex;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.descriptors.DescriptorIterator;
import org.eclipse.persistence.internal.helper.WriteLockManager;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.identitymaps.IdentityMap;
import org.eclipse.persistence.internal.identitymaps.IdentityMapManager;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.queries.InMemoryQueryIndirectionPolicy;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.sessions.DataRecord;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.coordination.CommandManager;
import org.eclipse.persistence.sessions.coordination.MergeChangeSetCommand;

/**
 * INTERNAL:
 * Internal subclass that provides access to identity maps through the session.
 * Implements the IdentityMapAccessor interface which provides all publicly available
 * identity map functionality to users.
 * This is the main class that should be used to access identity maps.  In general, any
 * function that accesses the identity map manager should go through this class
 * Any session specific functionality appears in subclasses
 */
public class IdentityMapAccessor implements org.eclipse.persistence.sessions.IdentityMapAccessor, java.io.Serializable {

    /** This is the identity map manager for this accessor.  It should only be accessed through the getter **/
    protected IdentityMapManager identityMapManager = null;
    protected AbstractSession session = null;

    /**
     * INTERNAL:
     */
    public IdentityMapAccessor() {
    }

    /**
     * INTERNAL:
     * An IdentityMapAccessor sits between the session and the identityMapManager
     * It needs references in both directions.
     */
    public IdentityMapAccessor(AbstractSession session) {
        this.session = session;
    }

    /**
     * INTERNAL:
     * An IdentityMapAccessor sits between the session and the identityMapManager
     * It needs references in both directions.
     */
    public IdentityMapAccessor(AbstractSession session, IdentityMapManager identityMapManager) {
        this.session = session;
        this.identityMapManager = identityMapManager;
    }

    /**
     * INTERNAL:
     * Deferred lock the identity map for the object, this is used for avoiding deadlock
     * The return cacheKey should be used to release the deferred lock.
     */
    public CacheKey acquireDeferredLock(Object primarKey, Class javaClass, ClassDescriptor descriptor, boolean isCacheCheckComplete) {
        return getIdentityMapManager().acquireDeferredLock(primarKey, javaClass, descriptor, isCacheCheckComplete);
    }

    /**
     * INTERNAL:
     * Lock the identity map for the object, this must be done when building objects.
     * The return cacheKey should be used to release the lock.
     */
    public CacheKey acquireLock(Object primarKey, Class javaClass, ClassDescriptor descriptor, boolean isCacheCheckComplete) {
        return acquireLock(primarKey, javaClass, false, descriptor, isCacheCheckComplete);
    }

    /**
     * INTERNAL:
     * Provides access for setting a concurrency lock on an object in the IdentityMap.
     * Called with true from the merge process, if true then the refresh will not refresh the object.
     */
    public CacheKey acquireLock(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor, boolean isCacheCheckComplete) {
        return getIdentityMapManager().acquireLock(primaryKey, domainClass, forMerge, descriptor, isCacheCheckComplete);
    }

    /**
     * INTERNAL:
     * Provides access for setting a concurrency lock on an object in the IdentityMap.
     * Called with true from the merge process, if true then the refresh will not refresh the object.
     */
    public CacheKey acquireLockNoWait(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor) {
        return getIdentityMapManager().acquireLockNoWait(primaryKey, domainClass, forMerge, descriptor);
    }

    /**
     * INTERNAL:
     * Provides access for setting a concurrency lock on an object in the IdentityMap.
     * Called with true from the merge process, if true then the refresh will not refresh the object.
     */
    public CacheKey acquireLockWithWait(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor, int wait) {
        return getIdentityMapManager().acquireLockWithWait(primaryKey, domainClass, forMerge, descriptor, wait);
    }

    /**
     * INTERNAL:
     * Find the cachekey for the provided primary key and place a readlock on it.
     * This will allow multiple users to read the same object but prevent writes to
     * the object while the read lock is held.
     */
    public CacheKey acquireReadLockOnCacheKey(Object primaryKey, Class domainClass, ClassDescriptor descriptor) {
        return getIdentityMapManager().acquireReadLockOnCacheKey(primaryKey, domainClass, descriptor);
    }

    /**
     * INTERNAL:
     * Find the cachekey for the provided primary key and place a readlock on it.
     * This will allow multiple users to read the same object but prevent writes to
     * the object while the read lock is held.
     * If no readlock can be acquired then do not wait but return null.
     */
    public CacheKey acquireReadLockOnCacheKeyNoWait(Object primaryKey, Class domainClass, ClassDescriptor descriptor) {
        return getIdentityMapManager().acquireReadLockOnCacheKeyNoWait(primaryKey, domainClass, descriptor);
    }

    /**
     * INTERNAL:
     * Lock the entire cache if the cache isolation requires.
     * By default concurrent reads and writes are allowed.
     * By write, unit of work merge is meant.
     */
    public boolean acquireWriteLock() {
        return getIdentityMapManager().acquireWriteLock();
    }

    /**
     * ADVANCED:
     * Clear all the query caches
     */
    @Override
    public void clearQueryCache() {
        getIdentityMapManager().clearQueryCache();
    }

    /**
     * ADVANCED:
     * Clear the query class associated with the passed-in read query
     */
    @Override
    public void clearQueryCache(ReadQuery query) {
        getIdentityMapManager().clearQueryCache(query);
    }

    /**
     * ADVANCED:
     * Clear the query cache associated with the named query on the session
     */
    @Override
    public void clearQueryCache(String sessionQueryName) {
        getIdentityMapManager().clearQueryCache((ReadQuery)session.getQuery(sessionQueryName));
    }

    /**
     * ADVANCED:
     * Clear the query cache associated with the named query on the descriptor for the given class
     */
    @Override
    public void clearQueryCache(String descriptorQueryName, Class queryClass) {
        getIdentityMapManager().clearQueryCache((ReadQuery)session.getDescriptor(queryClass).getQueryManager().getQuery(descriptorQueryName));
    }

    /**
     * ADVANCED:
     * Return if their is an object for the primary key.
     */
    @Override
    public boolean containsObjectInIdentityMap(Object object) {
        return containsObjectInIdentityMap(getSession().getId(object), object.getClass());
    }

    /**
     * ADVANCED:
     * Return if their is an object for the primary key.
     */
    @Override
    public boolean containsObjectInIdentityMap(Object primaryKey, Class theClass) {
        ClassDescriptor descriptor = getSession().getDescriptor(theClass);
        return containsObjectInIdentityMap(primaryKey, theClass, descriptor);
    }

    /**
     * INTERNAL:
     * Return if their is an object for the primary key.
     */
    public boolean containsObjectInIdentityMap(Object primaryKey, Class theClass, ClassDescriptor descriptor) {
        return getIdentityMapManager().containsKey(primaryKey, theClass, descriptor);
    }

    /**
     * ADVANCED:
     * Return if their is an object for the row containing primary key and the class.
     */
    @Override
    public boolean containsObjectInIdentityMap(DataRecord rowContainingPrimaryKey, Class theClass) {
        return containsObjectInIdentityMap(extractPrimaryKeyFromRow(rowContainingPrimaryKey, theClass), theClass);
    }

    /**
     * INTERNAL:
     * Extract primary key from a row.
     */
    protected Object extractPrimaryKeyFromRow(DataRecord rowContainingPrimaryKey, Class theClass) {
        return this.session.getDescriptor(theClass).getObjectBuilder().extractPrimaryKeyFromRow((AbstractRecord)rowContainingPrimaryKey, this.session);
    }

    /**
     * INTERNAL:
     * Retrieve the cache key for the given object from the identity maps.
     * @param object the object to get the cache key for.
     */
    public CacheKey getCacheKeyForObject(Object object, ClassDescriptor descriptor) {
        return getCacheKeyForObject(getSession().keyFromObject(object, descriptor), object.getClass(), descriptor, false);
    }

    /**
     * INTERNAL:
     * This method is used to get a list of those classes with IdentityMaps in the Session.
     */
    public Vector getClassesRegistered() {
        return getIdentityMapManager().getClassesRegistered();
    }

    /**
     * ADVANCED:
     * Query the cache in-memory.
     * If the expression is too complex an exception will be thrown.
     */
    public Vector getAllFromIdentityMap(Expression selectionCriteria, Class theClass, DataRecord translationRow) throws QueryException {
        return getAllFromIdentityMap(selectionCriteria, theClass, translationRow, InMemoryQueryIndirectionPolicy.SHOULD_THROW_INDIRECTION_EXCEPTION, true);
    }

    /**
     * ADVANCED:
     * Query the cache in-memory.
     * If the expression is too complex an exception will be thrown.
     */
    @Override
    public Vector getAllFromIdentityMap(Expression selectionCriteria, Class theClass, DataRecord translationRow, InMemoryQueryIndirectionPolicy valueHolderPolicy) throws QueryException {
        return getAllFromIdentityMap(selectionCriteria, theClass, translationRow, valueHolderPolicy, true);
    }

    /**
     * ADVANCED:
     * Query the cache in-memory.
     * If the expression is too complex an exception will be thrown.
     */
    @Override
    public Vector getAllFromIdentityMap(Expression selectionCriteria, Class theClass, DataRecord translationRow, int valueHolderPolicy) throws QueryException {
        return getAllFromIdentityMap(selectionCriteria, theClass, translationRow, valueHolderPolicy, true);
    }

    /**
     * ADVANCED:
     * Query the cache in-memory.
     * If the expression is too complex an exception will be thrown.
     * Only return objects that are invalid in the cache if specified.
     */
    @Override
    public Vector getAllFromIdentityMap(Expression selectionCriteria, Class theClass, DataRecord translationRow, InMemoryQueryIndirectionPolicy valueHolderPolicy, boolean shouldReturnInvalidatedObjects) throws QueryException {
        int policy = 0;
        if (valueHolderPolicy != null) {
            policy = valueHolderPolicy.getPolicy();
        }
        return getAllFromIdentityMap(selectionCriteria, theClass, translationRow, policy, shouldReturnInvalidatedObjects);
    }

    /**
     * ADVANCED:
     * Query the cache in-memory.
     * If the expression is too complex an exception will be thrown.
     * Only return objects that are invalid in the cache if specified.
     */
    @Override
    public Vector getAllFromIdentityMap(Expression selectionCriteria, Class theClass, DataRecord translationRow, int valueHolderPolicy, boolean shouldReturnInvalidatedObjects) throws QueryException {
        return getIdentityMapManager().getAllFromIdentityMap(selectionCriteria, theClass, translationRow, valueHolderPolicy, shouldReturnInvalidatedObjects);
    }

    /**
     * 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
     */
    public Map<Object, Object> getAllFromIdentityMapWithEntityPK(Object[] pkList, ClassDescriptor descriptor){
        return getIdentityMapManager().getAllFromIdentityMapWithEntityPK(pkList, descriptor, getSession());
    }

    /**
     * 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
     */
    public Map<Object, CacheKey> getAllCacheKeysFromIdentityMapWithEntityPK(Object[] pkList, ClassDescriptor descriptor){
        return getIdentityMapManager().getAllCacheKeysFromIdentityMapWithEntityPK(pkList, descriptor, getSession());
    }

    /**
     * ADVANCED:
     * Return the object from the identity with primary and class of the given object.
     */
    @Override
    public Object getFromIdentityMap(Object object) {
        return getFromIdentityMap(getSession().getId(object), object.getClass());
    }

    /**
     * INTERNAL:
     * Retrieve the cache key for the given object.
     * @return CacheKey
     */
    public CacheKey getCacheKeyForObject(Object object) {
        return getCacheKeyForObject(getSession().getId(object), object.getClass(), getSession().getDescriptor(object.getClass()), false);
    }

    /**
     * INTERNAL:
     * Retrieve the cache key for the given identity information.
     * @param primaryKey the primary key of the cache key to be retrieved.
     * @param myClass the class of the cache key to be retrieved.
     */
    public CacheKey getCacheKeyForObjectForLock(Object primaryKey, Class myClass, ClassDescriptor descriptor) {
        return getIdentityMapManager().getCacheKeyForObjectForLock(primaryKey, myClass, descriptor);
    }

    /**
     * INTERNAL:
     * Retrieve the cache key for the given identity information.
     * @param primaryKey the primary key of the cache key to be retrieved.
     * @param myClass the class of the cache key to be retrieved.
     */
    public CacheKey getCacheKeyForObject(Object primaryKey, Class myClass, ClassDescriptor descriptor, boolean forMerge) {
        return getIdentityMapManager().getCacheKeyForObject(primaryKey, myClass, descriptor, forMerge);
    }

    /**
     * ADVANCED:
     * Return the object from the identity with the primary and class.
     */
    @Override
    public Object getFromIdentityMap(Object primaryKey, Class theClass) {
        return getFromIdentityMap(primaryKey, theClass, true);
    }

    /**
     * ADVANCED:
     * Return the object from the identity with the primary and class.
     */
    public Object getFromIdentityMap(Object primaryKey, Class theClass, ClassDescriptor descriptor) {
        return getFromIdentityMap(primaryKey, null, theClass, true, descriptor);
    }

    /**
     * ADVANCED:
     * Return the object from the identity with the primary and class.
     * Only return invalidated objects if requested.
     */
    @Override
    public Object getFromIdentityMap(Object primaryKey, Class theClass, boolean shouldReturnInvalidatedObjects) {
        return getFromIdentityMap(primaryKey, null, theClass, shouldReturnInvalidatedObjects, getSession().getDescriptor(theClass));
    }

    /**
     * INTERNAL:
     * Return the object from the identity with the primary and class.
     * Only return invalidated objects if requested.
     */
    public Object getFromIdentityMap(Object primaryKey, Object object, Class theClass, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor) {
        return getIdentityMapManager().getFromIdentityMap(primaryKey, theClass, shouldReturnInvalidatedObjects, descriptor);
    }

    /**
     * INTERNAL:
     * Return the object from the local identity map with the primary and class.
     * This avoids checking the parent cache for the unit of work.
     */
    public Object getFromLocalIdentityMap(Object primaryKey, Class theClass, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor) {
        return getIdentityMapManager().getFromIdentityMap(primaryKey, theClass, shouldReturnInvalidatedObjects, descriptor);
    }

    /**
     * INTERNAL:
     * Return the object from the local identity map with the primary and class.
     * This avoids checking the parent cache for the unit of work.
     */
    public Object getFromLocalIdentityMapWithDeferredLock(Object primaryKey, Class theClass, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor){
        return getIdentityMapManager().getFromIdentityMapWithDeferredLock(primaryKey, theClass, shouldReturnInvalidatedObjects, descriptor);
    }

    /**
     * ADVANCED:
     * Return the object from the identity with the primary and class.
     */
    @Override
    public Object getFromIdentityMap(DataRecord rowContainingPrimaryKey, Class theClass) {
        return getFromIdentityMap(extractPrimaryKeyFromRow(rowContainingPrimaryKey, theClass), theClass);
    }

    /**
     * ADVANCED:
     * Return the object from the identity with the primary and class.
     * Only return invalidated objects if requested.
     */
    @Override
    public Object getFromIdentityMap(DataRecord rowContainingPrimaryKey, Class theClass, boolean shouldReturnInvalidatedObjects) {
        return getFromIdentityMap(extractPrimaryKeyFromRow(rowContainingPrimaryKey, theClass), theClass, shouldReturnInvalidatedObjects);
    }

    /**
     * ADVANCED:
     * Query the cache in-memory.
     * If the object is not found null is returned.
     * If the expression is too complex an exception will be thrown.
     */
    @Override
    public Object getFromIdentityMap(Expression selectionCriteria, Class theClass, DataRecord translationRow) throws QueryException {
        return getFromIdentityMap(selectionCriteria, theClass, translationRow, InMemoryQueryIndirectionPolicy.SHOULD_THROW_INDIRECTION_EXCEPTION);
    }

    /**
     * ADVANCED:
     * Query the cache in-memory.
     * If the object is not found null is returned.
     * If the expression is too complex an exception will be thrown.
     */
    @Override
    public Object getFromIdentityMap(Expression selectionCriteria, Class theClass, DataRecord translationRow, InMemoryQueryIndirectionPolicy valueHolderPolicy) throws QueryException {
        int policy = 0;
        if (valueHolderPolicy != null) {
            policy = valueHolderPolicy.getPolicy();
        }
        return getFromIdentityMap(selectionCriteria, theClass, translationRow, policy, false);
    }

    /**
     * ADVANCED:
     * Query the cache in-memory.
     * If the object is not found null is returned.
     * If the expression is too complex an exception will be thrown.
     */
    @Override
    public Object getFromIdentityMap(Expression selectionCriteria, Class theClass, DataRecord translationRow, int valueHolderPolicy) throws QueryException {
        return getFromIdentityMap(selectionCriteria, theClass, translationRow, valueHolderPolicy, false);
    }

    /**
     * INTERNAL:
     * Query the cache in-memory.
     * If the object is not found null is returned.
     * If the expression is too complex an exception will be thrown.
     */
    public Object getFromIdentityMap(Expression selectionCriteria, Class theClass, DataRecord translationRow, int valueHolderPolicy, boolean conforming) {
        return getFromIdentityMap(selectionCriteria, theClass, translationRow, valueHolderPolicy, conforming, true, getSession().getDescriptor(theClass));
    }

    /**
     * INTERNAL:
     * Query the cache in-memory.
     * If the object is not found null is returned.
     * If the expression is too complex an exception will be thrown.
     */
    public Object getFromIdentityMap(Expression selectionCriteria, Class theClass, DataRecord translationRow, int valueHolderPolicy, boolean conforming, boolean shouldReturnInvalidatedObjects) {
        return getFromIdentityMap(selectionCriteria, theClass, translationRow, valueHolderPolicy, conforming, shouldReturnInvalidatedObjects, getSession().getDescriptor(theClass));
    }

    /**
     * INTERNAL:
     * Query the cache in-memory.
     * If the object is not found null is returned.
     * If the expression is too complex an exception will be thrown.
     */
    public Object getFromIdentityMap(Expression selectionCriteria, Class theClass, DataRecord translationRow, int valueHolderPolicy, boolean conforming, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor) {
        return getIdentityMapManager().getFromIdentityMap(selectionCriteria, theClass, translationRow, valueHolderPolicy, conforming, shouldReturnInvalidatedObjects, descriptor);
    }

    /**
     * INTERNAL:
     * Return the object from the identity with the primary and class.
     */
    public Object getFromIdentityMapWithDeferredLock(Object primaryKey, Class theClass, ClassDescriptor descriptor) {
        return getFromIdentityMapWithDeferredLock(primaryKey, theClass, true, descriptor);
    }

    /**
     * INTERNAL:
     * Return the object from the identity with the primary and class.
     * Only return invalidated objects if requested
     */
    public Object getFromIdentityMapWithDeferredLock(Object primaryKey, Class theClass, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor) {
        return getIdentityMapManager().getFromIdentityMapWithDeferredLock(primaryKey, theClass, shouldReturnInvalidatedObjects, descriptor);
    }

    /**
     * INTERNAL:
     * Get the IdentityMapManager for this IdentityMapAccessor
     * This method should be used for all IdentityMapManager access since it may
     * be overridden in sub classes.
     */
    public IdentityMapManager getIdentityMapManager() {
        if (session.hasBroker()) {
            return getSession().getBroker().getIdentityMapAccessorInstance().getIdentityMapManager();
        }
        return identityMapManager;
    }

    /**
     * INTERNAL: (public to allow test cases to check)
     * Return the identity map for the class, if missing create a new one.
     */
    public IdentityMap getIdentityMap(Class theClass) {
        ClassDescriptor descriptor = getSession().getDescriptor(theClass);
        if (descriptor == null) {
            throw ValidationException.missingDescriptor(theClass.toString());
        }
        return getIdentityMap(descriptor);
    }

    /**
     * INTERNAL:
     * Get the identity map for the given class from the IdentityMapManager
     */
    public IdentityMap getIdentityMap(ClassDescriptor descriptor) {
        return getIdentityMap(descriptor, false);
    }

    /**
     * INTERNAL:
     * Get the identity map for the given class from the IdentityMapManager
     */
    public IdentityMap getIdentityMap(ClassDescriptor descriptor, boolean returnNullIfMissing) {
        return getIdentityMapManager().getIdentityMap(descriptor, returnNullIfMissing);
    }

    /**
     * INTERNAL:
     * Get the cached results associated with a query.  Results are cached by the
     * values of the parameters to the query so different parameters will have
     * different cached results.
     */
    public Object getQueryResult(ReadQuery query, List parameters, boolean checkExpiry) {
        return getIdentityMapManager().getQueryResult(query, parameters, checkExpiry);
    }

    /**
     * ADVANCED:
     * Return the remaining life of this object.  This method is associated with use of
     * cache invalidation 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 getRemainingValidTime(Object object) {
        Object primaryKey = getSession().getId(object);
        ClassDescriptor descriptor = getSession().getDescriptor(object);
        CacheKey key = getCacheKeyForObjectForLock(primaryKey, object.getClass(), descriptor);
        if (key == null) {
            throw QueryException.objectDoesNotExistInCache(object);
        }
        return descriptor.getCacheInvalidationPolicy().getRemainingValidTime(key);
    }

    /**
     * INTERNAL:
     * get the session associated with this IdentityMapAccessor
     */
    public AbstractSession getSession() {
        return session;
    }

    /**
     * INTERNAL:
     * Get the wrapper object from the cache key associated with the given primary key,
     * this is used for EJB.
     */
    public Object getWrapper(Object primaryKey, Class theClass) {
        return getIdentityMapManager().getWrapper(primaryKey, theClass);
    }

    /**
     * INTERNAL:
     * Returns the single write Lock manager for this session
     */
    public WriteLockManager getWriteLockManager() {
        return getIdentityMapManager().getWriteLockManager();
    }

    /**
    * ADVANCED:
    * Extract the write lock value from the identity map.
    */
    @Override
    public Object getWriteLockValue(Object object) {
        return getWriteLockValue(getSession().getId(object), object.getClass());
    }

    /**
     * ADVANCED:
     * Extract the write lock value from the identity map.
     */
    @Override
    public Object getWriteLockValue(Object primaryKey, Class theClass) {
        return getWriteLockValue(primaryKey, theClass, getSession().getDescriptor(theClass));
    }

    /**
     * ADVANCED:
     * Extract the write lock value from the identity map.
     */
    public Object getWriteLockValue(Object primaryKey, Class theClass, ClassDescriptor descriptor) {
        return getIdentityMapManager().getWriteLockValue(primaryKey, theClass, descriptor);
    }

    /**
     * PUBLIC:
     * Reset the entire object cache.
     * <p> NOTE: be careful using this method. This method blows away both this session's and its parents 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 object held in the cache.
     */
    @Override
    public void initializeAllIdentityMaps() {
        getSession().log(SessionLog.FINER, SessionLog.CACHE, "initialize_all_identitymaps");
        getIdentityMapManager().initializeIdentityMaps();
    }

    /**
     * PUBLIC:
     * Reset the identity map for only the instances of the class.
     * For inheritance the user must make sure that they only use the root class.
     * Caution must be used in doing this to ensure that the objects within the identity map
     * are not referenced from other objects of other classes or from the application.
     */
    @Override
    public void initializeIdentityMap(Class theClass) {
        getSession().log(SessionLog.FINER, SessionLog.CACHE, "initialize_identitymap", theClass);
        getIdentityMapManager().initializeIdentityMap(theClass);
    }

    /**
     * PUBLIC:
     * Reset the entire local object 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 object held in the cache.
     */
    @Override
    public void initializeIdentityMaps() {
        getSession().log(SessionLog.FINER, SessionLog.CACHE, "initialize_identitymaps");
        getIdentityMapManager().initializeIdentityMaps();
        if (getSession().hasCommitManager()) {
            getSession().getCommitManager().reinitialize();
        }
    }

    /**
     * ADVANCED:
     * Set an object to be invalid in the cache.
     * If the object does not exist in the cache, this method will return
     * without any action.
     */
    @Override
    public void invalidateObject(Object object) {
        invalidateObject(object, false);
    }

    /**
     * ADVANCED:
     * Set an object to be invalid in the cache.
     * @param invalidateCluster if true the invalidation will be broadcast to each server in the cluster.
     */
    @Override
    public void invalidateObject(Object object, boolean invalidateCluster) {
        invalidateObject(getSession().getId(object), object.getClass(), invalidateCluster);
    }

    /**
     * ADVANCED:
     * Set an object to be invalid in the cache.
     * If the object does not exist in the cache, this method will return
     * without any action.
     */
    @Override
    public void invalidateObject(Object primaryKey, Class theClass) {
        invalidateObject(primaryKey, theClass, false);
    }

    /**
     * ADVANCED:
     * Set an object to be invalid in the cache.
     * @param invalidateCluster if true the invalidation will be broadcast to each server in the cluster.
     */
    @Override
    public void invalidateObject(Object primaryKey, Class theClass, boolean invalidateCluster) {
        if (primaryKey == null) {
            return;
        }
        ClassDescriptor descriptor = getSession().getDescriptor(theClass);
        //forward the call to getCacheKeyForObject locally in case subclasses overload
        CacheKey key = getCacheKeyForObjectForLock(primaryKey, theClass, descriptor);
        if (key != null) {
            key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
        }
        if (invalidateCluster) {
            CommandManager rcm = getSession().getCommandManager();
            if (rcm != null) {
                UnitOfWorkChangeSet changeSet = new UnitOfWorkChangeSet(getSession());
                ObjectChangeSet objectChangeSet = new ObjectChangeSet(primaryKey, descriptor, null, changeSet, false);
                objectChangeSet.setSynchronizationType(ClassDescriptor.INVALIDATE_CHANGED_OBJECTS);
                changeSet.getAllChangeSets().put(objectChangeSet, objectChangeSet);
                MergeChangeSetCommand command = new MergeChangeSetCommand();
                command.setChangeSet(changeSet);
                rcm.propagateCommand(command);
            }
        }
        if (session.getProject().allowExtendedCacheLogging()) {
            session.log(SessionLog.FINEST, SessionLog.CACHE, "cache_item_invalidation", new Object[] {theClass, primaryKey, Thread.currentThread().getId(), Thread.currentThread().getName()});
        }
    }

    /**
     * ADVANCED:
     * Set an object to be invalid in the cache.
     * If the object does not exist in the cache, this method will return
     * without any action.
     */
    @Override
    public void invalidateObject(DataRecord rowContainingPrimaryKey, Class theClass) {
        invalidateObject(rowContainingPrimaryKey, theClass, false);
    }

    /**
     * ADVANCED:
     * Set an object to be invalid in the cache.
     * @param invalidateCluster if true the invalidation will be broadcast to each server in the cluster.
     */
    @Override
    public void invalidateObject(DataRecord rowContainingPrimaryKey, Class theClass, boolean invalidateCluster) {
        invalidateObject(extractPrimaryKeyFromRow(rowContainingPrimaryKey, theClass), theClass, invalidateCluster);
    }

    /**
     * ADVANCED:
     * Set all of the objects from the given Expression to be invalid in the cache.
     */
    @Override
    public void invalidateObjects(Expression selectionCriteria) {
        invalidateObjects(selectionCriteria, selectionCriteria.getBuilder().getQueryClass(), new DatabaseRecord(0), true);
    }

    /**
     * ADVANCED:
     * Queries the cache in-memory with the passed in criteria and invalidates matching Objects.
     * If the expression is too complex either all or none object of theClass invalidated (depending on shouldInvalidateOnException value).
     * @param selectionCriteria Expression selecting the Objects to be returned
     * @param theClass Class to be considered
     * @param translationRow Record
     * @param shouldInvalidateOnException boolean indicates weather to invalidate the object if conform threw exception.
     */
    @Override
    public void invalidateObjects(Expression selectionCriteria, Class theClass, DataRecord translationRow, boolean shouldInvalidateOnException) {
        getIdentityMapManager().invalidateObjects(selectionCriteria, theClass, translationRow, shouldInvalidateOnException);
    }

    /**
     * ADVANCED:
     * Set all of the objects in the given collection to be invalid in the cache.
     * This method will take no action for any objects in the collection that do not exist in the cache.
     */
    @Override
    public void invalidateObjects(Collection collection) {
        invalidateObjects(collection, false);
    }

    /**
     * ADVANCED:
     * Set all of the objects in the given collection to be invalid in the cache.
     * @param invalidateCluster if true the invalidation will be broadcast to each server in the cluster.
     */
    @Override
    public void invalidateObjects(Collection collection, boolean invalidateCluster) {
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()) {
            invalidateObject(iterator.next(), invalidateCluster);
        }
    }

    /**
     * ADVANCED:
     * Set all of the objects of a specific class to be invalid in the cache.
     * Will set the recurseAndInvalidateToParentRoot flag on inheritance to true.
     */
    @Override
    public void invalidateClass(Class myClass) {
        invalidateClass(myClass, true);
    }

    /**
     * ADVANCED:
     * Set all of the objects of a specific class to be invalid in the cache.
     * User can set the recurse flag to false if they do not want to invalidate
     * all the classes within an inheritance tree and instead invalidate the subtree rooted at myClass.
     * @param myClass - the class where we start invalidation
     * @param recurseAndInvalidateToParentRoot - default is true where we invalidate
     *   up the inheritance tree to the root descriptor
     */
    @Override
    public void invalidateClass(Class myClass, boolean recurseAndInvalidateToParentRoot) {
        //forward the call to getIdentityMap locally in case subclasses overload
        IdentityMap identityMap = this.getIdentityMap(myClass); // will always return the root IdentityMap

        //bug 227430: Deadlock in IdentityMapAccessor.
        //removed synchronization that would result in deadlock
        //no need to synchronize as changes to identity map will not aversely affect this code
        //bug 275724: IdentityMapAccessor.invalidateClass() should not check ReadLock when invalidating
        Enumeration<CacheKey> keys = identityMap.keys(false); // do not check readlock
        while (keys.hasMoreElements()) {
            CacheKey key = keys.nextElement();
            Object obj = key.getObject();
            // 312503: When recurse is false we also invalidate all assignable implementing subclasses of [obj]
            if (recurseAndInvalidateToParentRoot || ((obj != null) && (null != myClass) && myClass.isAssignableFrom(obj.getClass()))) {
                key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
            }
        }
        invalidateQueryCache(myClass);
        if (session.getProject().allowExtendedCacheLogging()) {
            session.log(SessionLog.FINEST, SessionLog.CACHE, "cache_class_invalidation", new Object[] {myClass, Thread.currentThread().getId(), Thread.currentThread().getName()});
        }
    }

    /**
     * Invalidate/remove any results for the class from the query cache.
     * This is used to invalidate the query cache on any change.
     */
    @Override
    public void invalidateQueryCache(Class classThatChanged) {
        getIdentityMapManager().invalidateQueryCache(classThatChanged);
    }

    /**
     * ADVANCED:
     * Set all of the objects from all identity maps to be invalid in the cache.
     */
    @Override
    public void invalidateAll() {
        Iterator identiyMapClasses = getIdentityMapManager().getIdentityMapClasses();

        while (identiyMapClasses.hasNext()) {
            invalidateClass((Class) identiyMapClasses.next());
        }
    }

    /**
     * ADVANCED:
     * Return if this object is valid in the cache.
     */
    @Override
    public boolean isValid(Object object) {
        return isValid(getSession().getId(object), object.getClass());
    }

    /**
     * ADVANCED:
     * Return if this object is valid in the cache.
     */
    @Override
    public boolean isValid(Object primaryKey, Class theClass) {
        ClassDescriptor descriptor = getSession().getDescriptor(theClass);
        //forward the call to getCacheKeyForObject locally in case subclasses overload
        CacheKey key = getCacheKeyForObjectForLock(primaryKey, theClass, descriptor);
        if (key == null) {
            throw QueryException.classPkDoesNotExistInCache(theClass, primaryKey);
        }
        return !descriptor.getCacheInvalidationPolicy().isInvalidated(key);
    }

    /**
     * ADVANCED:
     * Return if this object is valid in the cache.
     */
    @Override
    public boolean isValid(DataRecord rowContainingPrimaryKey, Class theClass) {
        return isValid(extractPrimaryKeyFromRow(rowContainingPrimaryKey, theClass), theClass);
    }

    /**
     * PUBLIC:
     * Used to print all the objects in the identity map of the passed in class.
     * The output of this method will be logged to this session's SessionLog at SEVERE level.
     */
    @Override
    public void printIdentityMap(Class businessClass) {
        if (getSession().shouldLog(SessionLog.SEVERE, SessionLog.CACHE)) {
            getIdentityMapManager().printIdentityMap(businessClass);
        }
    }

    /**
     * PUBLIC:
     * Used to print all the objects in every identity map in this session.
     * The output of this method will be logged to this session's SessionLog at SEVERE level.
     */
    @Override
    public void printIdentityMaps() {
        if (getSession().shouldLog(SessionLog.SEVERE, SessionLog.CACHE)) {
            getIdentityMapManager().printIdentityMaps();
        }
    }

    /**
     * PUBLIC:
     * Used to print all the locks in every identity map in this session.
     * The output of this method will be logged to this session's SessionLog at FINEST level.
     */
    @Override
    public void printIdentityMapLocks() {
        if (getSession().shouldLog(SessionLog.SEVERE, SessionLog.CACHE)) {
            getIdentityMapManager().printLocks();
        }
    }

    /**
     * ADVANCED:
     * Register the object with the cache.
     * The object must always be registered with its version number if optimistic locking is used.
     */
    @Override
    public Object putInIdentityMap(Object object) {
        return putInIdentityMap(object, getSession().getId(object));
    }

    /**
     * ADVANCED:
     * Register the object with the cache.
     * The object must always be registered with its version number if optimistic locking is used.
     */
    @Override
    public Object putInIdentityMap(Object object, Object key) {
        return putInIdentityMap(object, key, null);
    }

    /**
     * ADVANCED:
     * Register the object with the cache.
     * The object must always be registered with its version number if optimistic locking is used.
     */
    @Override
    public Object putInIdentityMap(Object object, Object key, Object writeLockValue) {
        return putInIdentityMap(object, key, writeLockValue, 0);
    }

    /**
     * ADVANCED:
     * Register the object with the cache.
     * The object must always be registered with its version number if optimistic locking is used.
     * The readTime may also be included in the cache key as it is constructed.
     */
    @Override
    public Object putInIdentityMap(Object object, Object key, Object writeLockValue, long readTime) {
        ClassDescriptor descriptor = getSession().getDescriptor(object);
        return putInIdentityMap(object, key, writeLockValue, readTime, descriptor);
    }

    /**
     * ADVANCED:
     * Register the object with the cache.
     * The object must always be registered with its version number if optimistic locking is used.
     * The readTime may also be included in the cache key as it is constructed.
     */
    public Object putInIdentityMap(Object object, Object key, Object writeLockValue, long readTime, ClassDescriptor descriptor) {
        CacheKey cacheKey = internalPutInIdentityMap(object, key, writeLockValue, readTime, descriptor);
        if (cacheKey == null) {
            return null;
        }
        return cacheKey.getObject();
    }

    /**
     * INTERNAL:
     * Set the results for a query.
     * Query results are cached based on the parameter values provided to the query
     * different parameter values access different caches.
     */
    public void putQueryResult(ReadQuery query, List parameters, Object results) {
        getIdentityMapManager().putQueryResult(query, parameters, results);
    }

    /**
     * Index the cache key by the index values.
     */
    public void putCacheKeyByIndex(CacheIndex index, CacheId indexValues, CacheKey cacheKey, ClassDescriptor descriptor) {
        getIdentityMapManager().putCacheKeyByIndex(index, indexValues, cacheKey, descriptor);
    }

    /**
     * Return the cache key for the cache index or null if not found.
     */
    public CacheKey getCacheKeyByIndex(CacheIndex index, CacheId indexValues, boolean shouldCheckExpiry, ClassDescriptor descriptor) {
        return getIdentityMapManager().getCacheKeyByIndex(index, indexValues, shouldCheckExpiry, descriptor);
    }

    /**
     * INTERNAL:
     * Register the object with the cache.
     * The object must always be registered with its version number if optimistic locking is used.
     * The readTime may also be included in the cache key as it is constructed.
     * Return the cache-key.
     */
    public CacheKey internalPutInIdentityMap(Object object, Object key, Object writeLockValue, long readTime, ClassDescriptor descriptor) {
        return getIdentityMapManager().putInIdentityMap(object, key, writeLockValue, readTime, descriptor);
    }

    /**
    * INTERNAL:
    * Lock the entire cache if the cache isolation requires.
    * By default concurrent reads and writes are allowed.
    * By write, unit of work merge is meant.
    */
    public void releaseWriteLock() {
        getIdentityMapManager().releaseWriteLock();
    }

    /**
     * ADVANCED:
     * Remove the object from the object cache.
     * Caution should be used when calling to avoid violating object identity.
     * The application should only call this is it knows that no references to the object exist.
     */
    @Override
    public Object removeFromIdentityMap(Object object) {
        Class<? extends Object> theClass = object.getClass();
        return removeFromIdentityMap(getSession().getId(object), theClass, getSession().getDescriptor(theClass), object);
    }

    /**
     * ADVANCED:
     * Remove the object from the object cache.
     */
    @Override
    public Object removeFromIdentityMap(Object key, Class theClass) {
        ClassDescriptor descriptor = getSession().getDescriptor(theClass);
        if (descriptor == null){
            return null;
        }
        return removeFromIdentityMap(key, theClass, descriptor, null);
    }

    /**
     * INTERNAL:
     * Remove the object from the object cache.
     */
    public Object removeFromIdentityMap(Object key, Class theClass, ClassDescriptor descriptor, Object object) {
        return getIdentityMapManager().removeFromIdentityMap(key, theClass, descriptor, object);
    }

    /**
     * INTERNAL:
     * Set the IdentityMapManager for this IdentityMapAccessor
     */
    public void setIdentityMapManager(IdentityMapManager identityMapManager) {
        this.identityMapManager = identityMapManager;
    }

    /**
     * INTERNAL:
     * Update the wrapper object the cache key associated with the given primary key,
     * this is used for EJB.
     */
    public void setWrapper(Object primaryKey, Class theClass, Object wrapper) {
        getIdentityMapManager().setWrapper(primaryKey, theClass, wrapper);
    }

    /**
     * ADVANCED:
     * Update the write lock value in the cache.
     */
    @Override
    public void updateWriteLockValue(Object object, Object writeLockValue) {
        updateWriteLockValue(getSession().getId(object), object.getClass(), writeLockValue);
    }

    /**
     * ADVANCED:
     * Update the write lock value in the cache.
     */
    @Override
    public void updateWriteLockValue(Object primaryKey, Class theClass, Object writeLockValue) {
        getIdentityMapManager().setWriteLockValue(primaryKey, theClass, writeLockValue);
    }

    /**
     * INTERNAL:
     * 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 not in the cache.
     * This method will validate that all cached objects are in a correct state.
     */
    @Override
    public void validateCache() {
        //pass certain calls to this in order to allow subclasses to implement own behavior
        getSession().log(SessionLog.FINER, SessionLog.CACHE, "validate_cache");
        // This define an inner class for process the iteration operation, don't be scared, its just an inner class.
        DescriptorIterator iterator = new DescriptorIterator() {
            @Override
            public void iterate(Object object) {
                if (!containsObjectInIdentityMap(IdentityMapAccessor.this.session.getDescriptor(object.getClass()).getObjectBuilder().extractPrimaryKeyFromObject(object, IdentityMapAccessor.this.getSession()), object.getClass())) {
                    IdentityMapAccessor.this.session.log(SessionLog.FINEST, SessionLog.CACHE, "stack_of_visited_objects_that_refer_to_the_corrupt_object", getVisitedStack());
                    IdentityMapAccessor.this.session.log(SessionLog.FINER, SessionLog.CACHE, "corrupt_object_referenced_through_mapping", getCurrentMapping());
                    IdentityMapAccessor.this.session.log(SessionLog.FINER, SessionLog.CACHE, "corrupt_object", object);
                }
            }
        };

        iterator.setSession(getSession());
        Iterator<ClassDescriptor> descriptors = getSession().getDescriptors().values().iterator();
        while (descriptors.hasNext()) {
            ClassDescriptor descriptor = descriptors.next();
            IdentityMap cache = getIdentityMap(descriptor, true);
            if (cache != null) {
                for (Enumeration mapEnum = cache.elements(); mapEnum.hasMoreElements();) {
                    iterator.startIterationOn(mapEnum.nextElement());
                }
            }
        }
    }
}
