/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2021 IBM Corporation. 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
//     Mark Wolochuk - Bug 321041 ConcurrentModificationException on getFromIdentityMap() fix
//     11/07/2017 - Dalia Abo Sheasha
//       - 526957: Split the logging and trace messages
//     12/14/2017-3.0 Tomas Kraus
//       - 522635: ConcurrentModificationException when triggering lazy load from conforming query
package org.eclipse.persistence.internal.identitymaps;

import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.eclipse.persistence.config.ReferenceMode;
import org.eclipse.persistence.descriptors.CacheIndex;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.invalidation.CacheInvalidationPolicy;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.EclipseLinkException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.ConcurrencyManager;
import org.eclipse.persistence.internal.helper.DeferredLockManager;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.InvalidObject;
import org.eclipse.persistence.internal.helper.WriteLockManager;
import org.eclipse.persistence.internal.localization.LoggingLocalization;
import org.eclipse.persistence.internal.localization.TraceLocalization;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.queries.InMemoryQueryIndirectionPolicy;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.sessions.DataRecord;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.sessions.interceptors.CacheInterceptor;

/**
 * <p><b>Purpose</b>: Maintain identity maps for domain classes mapped with EclipseLink.
 * <p><b>Responsibilities</b>:<ul>
 *    <li> Build new identity maps lazily using info from the descriptor
 *    <li> Insert objects into appropriate identity map
 *    <li> Get object from appropriate identity map using object or primary key with class
 *    <li> Get and Set write lock values for cached objects
 * </ul>
 * @since TOPLink/Java 1.0
 */
public class IdentityMapManager implements Serializable, Cloneable {
    protected static final String MONITOR_PREFIX = SessionProfiler.CacheSize;

    /** A table of identity maps with the key being the domain Class. */
    protected Map<Class<?>, IdentityMap> identityMaps;

    /** A table of identity maps with the key being the query */
    protected Map<Object, IdentityMap> queryResults;

    /** A map of class to list of queries that need to be invalidated when that class changes. */
    protected Map<Class<?>, Set> queryResultsInvalidationsByClass;

    /** A map of indexes on the cache. */
    protected Map<CacheIndex, IdentityMap> cacheIndexes;

    /** A reference to the session owning this manager. */
    protected AbstractSession session;

    /** Ensure mutual exclusion depending on the cache isolation.*/
    protected transient ConcurrencyManager cacheMutex;

    /** PERF: Optimize the object retrieval from the identity map. */
    protected IdentityMap lastAccessedIdentityMap = null;

    /** Used to store the write lock manager used for merging. */
    protected transient WriteLockManager writeLockManager;

    /** PERF: Used to avoid readLock and profiler checks to improve performance. */
    protected boolean isCacheAccessPreCheckRequired;

    protected IdentityMapManager() {
    }

    public IdentityMapManager(AbstractSession session) {
        this.session = session;
        this.cacheMutex = new ConcurrencyManager();
        // PERF: Avoid query cache for uow as never used.
        if (session.isUnitOfWork()) {
            this.identityMaps = new HashMap();
        } else if (session.isIsolatedClientSession()) {
            this.identityMaps = new HashMap();
            this.queryResults = new HashMap();
            this.queryResultsInvalidationsByClass = new HashMap();
            this.cacheIndexes = new HashMap();
        } else {
            this.identityMaps = new ConcurrentHashMap();
            this.queryResults = new ConcurrentHashMap();
            this.queryResultsInvalidationsByClass = new ConcurrentHashMap();
            this.cacheIndexes = new ConcurrentHashMap();
        }
        checkIsCacheAccessPreCheckRequired();
    }

    /**
     * Provides access for setting a deferred lock on an object in the IdentityMap.
     */
    public CacheKey acquireDeferredLock(Object primaryKey, Class<?> domainClass, ClassDescriptor descriptor, boolean isCacheCheckComplete) {
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            IdentityMap identityMap = getIdentityMap(descriptor, false);
            try {
                cacheKey = identityMap.acquireDeferredLock(primaryKey, isCacheCheckComplete);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
            if (!this.session.isUnitOfWork() && cacheKey.getObject() == null) {
                this.session.updateProfile(MONITOR_PREFIX + domainClass.getSimpleName(), identityMap.getSize());
            }
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireDeferredLock(primaryKey, isCacheCheckComplete);
        }

        return cacheKey;
    }

    /**
     * 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) {
        if (primaryKey == null) {
            CacheKey cacheKey = new CacheKey(null);
            cacheKey.acquire();
            return cacheKey;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            IdentityMap identityMap = getIdentityMap(descriptor, false);
            try {
                cacheKey = identityMap.acquireLock(primaryKey, forMerge, isCacheCheckComplete);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
            if (!this.session.isUnitOfWork() && (cacheKey != null) && cacheKey.getObject() == null) {
                this.session.updateProfile(MONITOR_PREFIX + domainClass.getSimpleName(), identityMap.getSize());
            }
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireLock(primaryKey, forMerge, isCacheCheckComplete);
        }

        return cacheKey;
    }

    /**
     * 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) {
        if (primaryKey == null) {
            CacheKey cacheKey = new CacheKey(null);
            cacheKey.acquire();
            return cacheKey;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            IdentityMap identityMap = getIdentityMap(descriptor, false);
            try {
                cacheKey = identityMap.acquireLockNoWait(primaryKey, forMerge);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
            if (!this.session.isUnitOfWork() && (cacheKey != null) && (cacheKey.getObject() == null)) {
                this.session.updateProfile(MONITOR_PREFIX + domainClass.getSimpleName(), identityMap.getSize());
            }
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireLockNoWait(primaryKey, forMerge);
        }

        return cacheKey;
    }

    /**
     * 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) {
        if (primaryKey == null) {
            CacheKey cacheKey = new CacheKey(null);
            cacheKey.acquire();
            return cacheKey;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            IdentityMap identityMap = getIdentityMap(descriptor, false);
            try {
                cacheKey = identityMap.acquireLockWithWait(primaryKey, forMerge, wait);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
            if (!this.session.isUnitOfWork() && (cacheKey != null) && cacheKey.getObject() == null) {
                this.session.updateProfile(MONITOR_PREFIX + domainClass.getSimpleName(), identityMap.getSize());
            }
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireLockWithWait(primaryKey, forMerge, wait);
        }

        return cacheKey;
    }

    /**
     * PERF: Used to micro optimize cache access.
     * Avoid the readLock and profile checks if not required.
     */
    public void checkIsCacheAccessPreCheckRequired() {
        if ((this.session.getProfiler() != null)
                || ((this.session.getDatasourceLogin() != null) && this.session.getDatasourceLogin().shouldSynchronizedReadOnWrite())) {
            this.isCacheAccessPreCheckRequired = true;
        } else {
            this.isCacheAccessPreCheckRequired = false;
        }
    }

    /**
     * Provides access for setting a concurrency lock on an IdentityMap.
     */
    public void acquireReadLock() {
        this.session.startOperationProfile(SessionProfiler.Caching);

        if (this.session.getDatasourceLogin().shouldSynchronizedReadOnWrite()) {
            getCacheMutex().acquireReadLock();
        }

        this.session.endOperationProfile(SessionProfiler.Caching);
    }

    /**
     * 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) {
        if (primaryKey == null) {
            CacheKey cacheKey = new CacheKey(null);
            cacheKey.acquireReadLock();
            return cacheKey;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = getIdentityMap(descriptor, false).acquireReadLockOnCacheKey(primaryKey);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireReadLockOnCacheKey(primaryKey);
        }

        return cacheKey;
    }

    /**
     * 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) {
        if (primaryKey == null) {
            CacheKey cacheKey = new CacheKey(null);
            cacheKey.acquireReadLock();
            return cacheKey;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = getIdentityMap(descriptor, false).acquireReadLockOnCacheKeyNoWait(primaryKey);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireReadLockOnCacheKeyNoWait(primaryKey);
        }

        return cacheKey;
    }

    /**
     * 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() {
        if (this.session.getDatasourceLogin().shouldSynchronizedReadOnWrite() || this.session.getDatasourceLogin().shouldSynchronizeWrites()) {
            getCacheMutex().acquire();
            return true;
        }
        return false;
    }

    /**
     * INTERNAL: (Public to allow testing to access)
     * Return a new empty identity map to cache instances of the class.
     */
    public IdentityMap buildNewIdentityMap(ClassDescriptor descriptor) {
        if (this.session.isUnitOfWork()) {
            ReferenceMode mode = ((UnitOfWorkImpl)this.session).getReferenceMode();
            if (mode == ReferenceMode.FORCE_WEAK){
                return new WeakUnitOfWorkIdentityMap(32, descriptor, this.session, true);
            } else if (mode == ReferenceMode.WEAK && descriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy()) {
                return new WeakUnitOfWorkIdentityMap(32, descriptor, this.session, true);
            } else {
                return new UnitOfWorkIdentityMap(32, descriptor, this.session, true);
            }
        }

        // Remote session has its own setting.
        if (this.session.isRemoteSession()) {
            return buildNewIdentityMap(descriptor.getRemoteIdentityMapClass(), descriptor.getRemoteIdentityMapSize(), descriptor, true);
        } else {
            return buildNewIdentityMap(descriptor.getIdentityMapClass(), descriptor.getIdentityMapSize(), descriptor, this.session.isIsolatedClientSession());
        }
    }

    /**
     * INTERNAL:
     * Return a new empty identity map of the class type.
     */
    protected <T extends IdentityMap> IdentityMap buildNewIdentityMap(
            final Class<T> identityMapClass, final int size, final ClassDescriptor descriptor, final boolean isIsolated) throws DescriptorException {
        if ((descriptor == null) || (descriptor.getCachePolicy().getCacheInterceptorClass() == null)) {
            // PERF: Avoid reflection.
            if (identityMapClass == ClassConstants.SoftCacheWeakIdentityMap_Class) {
                return new SoftCacheWeakIdentityMap(size, descriptor, this.session, isIsolated);
            } else if (identityMapClass == ClassConstants.HardCacheWeakIdentityMap_Class) {
                return new HardCacheWeakIdentityMap(size, descriptor, this.session, isIsolated);
            } else if (identityMapClass == ClassConstants.SoftIdentityMap_Class) {
                return new SoftIdentityMap(size, descriptor, this.session, isIsolated);
            } else if (identityMapClass == ClassConstants.WeakIdentityMap_Class) {
                return new WeakIdentityMap(size, descriptor, this.session, isIsolated);
            } else if (identityMapClass == ClassConstants.FullIdentityMap_Class) {
                return new FullIdentityMap(size, descriptor, this.session, isIsolated);
            } else if (identityMapClass == ClassConstants.CacheIdentityMap_Class) {
                return new CacheIdentityMap(size, descriptor, this.session, isIsolated);
            }
        }
        final Class<?>[] parameters = new Class<?>[]{ClassConstants.PINT, ClassDescriptor.class, AbstractSession.class, boolean.class};
        final Object[] values = new Object[]{size, descriptor, this.session, isIsolated};
        IdentityMap map = PrivilegedAccessHelper.callDoPrivilegedWithException(
                () -> {
                    final Constructor<T> constructor = PrivilegedAccessHelper.<T>getConstructorFor(identityMapClass, parameters, false);
                    return PrivilegedAccessHelper.<T>invokeConstructor(constructor, values);
                },
                (ex) -> DescriptorException.invalidIdentityMap(descriptor, ex)
        );
        if ((descriptor != null) && (descriptor.getCacheInterceptorClass() != null)) {
            final Object params[] = new Object[]{map, this.session};
            map = PrivilegedAccessHelper.callDoPrivilegedWithException(
                    () -> {
                        final Constructor<? extends CacheInterceptor> interceptor = PrivilegedAccessHelper.getConstructorFor(
                                descriptor.getCacheInterceptorClass(), new Class<?>[]{IdentityMap.class, AbstractSession.class}, false);
                        return PrivilegedAccessHelper.invokeConstructor(interceptor, params);
                    },
                    (ex) -> DescriptorException.invalidIdentityMap(descriptor, ex)
            );
        }
        return map;
    }

    /**
     * INTERNAL:
     * Clear the the lastAccessedIdentityMap and the lastAccessedIdentityMapClass
     */
    public void clearLastAccessedIdentityMap() {
        this.lastAccessedIdentityMap = null;
    }

    /**
     * INTERNAL:
     * Clones itself, used for uow commit and resume on failure.
     */
    @Override
    public Object clone() {
        IdentityMapManager manager = null;
        try {
            manager = (IdentityMapManager)super.clone();
            manager.setIdentityMaps(new ConcurrentHashMap());
            for (Iterator<Map.Entry<Class<?>, IdentityMap>> iterator = this.identityMaps.entrySet().iterator(); iterator.hasNext();) {
                Map.Entry<Class<?>, IdentityMap> entry = iterator.next();
                manager.identityMaps.put(entry.getKey(), (IdentityMap) entry.getValue().clone());
            }
        } catch (CloneNotSupportedException exception) {
            throw new InternalError(exception.toString());
        }
        return manager;
    }

    /**
     * Clear all the query caches.
     */
    public void clearQueryCache() {
        this.queryResults = new ConcurrentHashMap();
        this.queryResultsInvalidationsByClass = new ConcurrentHashMap();
    }

    /**
     * Clear all index caches.
     */
    public void clearCacheIndexes() {
        this.cacheIndexes = new ConcurrentHashMap();
    }

    /**
     * Remove the cache key related to a query.
     * Note this method is not synchronized and care should be taken to ensure
     * there are no other threads accessing the cache key.
     * This is used to clean up cached clones of queries.
     */
    public void clearQueryCache(ReadQuery query) {
        if (query != null) {// PERF: use query name, unless no name.
            Object queryKey = query.getName();
            if ((queryKey == null) || ((String)queryKey).length() == 0) {
                queryKey = query;
            }
            this.queryResults.remove(queryKey);
        }
    }

    /**
     * Invalidate/remove any results for the class from the query cache.
     * This is used to invalidate the query cache on any change.
     */
    public void invalidateQueryCache(Class<?> classThatChanged) {
        if (this.queryResultsInvalidationsByClass == null) {
            return;
        }
        Set invalidations = this.queryResultsInvalidationsByClass.get(classThatChanged);
        if (invalidations != null) {
            for (Object queryKey : invalidations) {
                this.queryResults.remove(queryKey);
            }
        }
        Class<?> superClass = classThatChanged.getSuperclass();
        if ((superClass != null) && (superClass != ClassConstants.OBJECT)) {
            invalidateQueryCache(superClass);
        }
    }

    /**
     * Return true if an CacheKey with the primary key is in the map.
     * User API.
     * @param key is the primary key for the object to search for.
     */
    public boolean containsKey(Object key, Class<?> theClass, ClassDescriptor descriptor) {
        if (key == null) {
            return false;
        }
        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return false;
        }
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                return map.containsKey(key);
            } finally {
                releaseReadLock();
                this.session.endOperationProfile(SessionProfiler.Caching);
            }
        } else {
            return map.containsKey(key);
        }
    }

    /**
     * Query the cache in-memory.
     */
    public Vector getAllFromIdentityMap(Expression selectionCriteria, Class<?> theClass, DataRecord translationRow, int valueHolderPolicy, boolean shouldReturnInvalidatedObjects) {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        this.session.startOperationProfile(SessionProfiler.Caching);
        Vector objects = null;
        try {
            if (selectionCriteria != null) {
                // PERF: Avoid clone of expression.
                ExpressionBuilder builder = selectionCriteria.getBuilder();
                if (builder != null && builder.getSession() == null) {
                    builder.setSession(this.session.getRootSession(null));
                    builder.setQueryClass(theClass);
                }
            }
            objects = new Vector();
            IdentityMap map = getIdentityMap(descriptor, false);

            // Bug #522635 - if policy is set to trigger indirection, then iterate over a copy of the cache keys collection
            //               to avoid a ConcurrentModificationException
            final Enumeration<CacheKey> cacheEnum = valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION ? map.cloneKeys() : map.keys();

            // bug 327900 - If don't read subclasses is set on the descriptor heed it.
            boolean readSubclassesOrNoInheritance = (!descriptor.hasInheritance() || descriptor.getInheritancePolicy().shouldReadSubclasses());

            // cache the current time to avoid calculating it every time through the loop
            long currentTimeInMillis = System.currentTimeMillis();
            while (cacheEnum.hasMoreElements()) {
                CacheKey key = cacheEnum.nextElement();
                if ((key.getObject() == null) || (!shouldReturnInvalidatedObjects && descriptor.getCacheInvalidationPolicy().isInvalidated(key, currentTimeInMillis))) {
                    continue;
                }
                Object object = key.getObject();

                // Bug # 3216337 - key.getObject() should check for null; object may be GC'd (MWN)
                if (object == null) {
                    continue;
                }

                // Must check for inheritance.
                // bug 327900
                if ((object.getClass() == theClass) || (readSubclassesOrNoInheritance && (theClass.isInstance(object)))) {
                    if (selectionCriteria == null) {
                        objects.add(object);
                    } else {
                        try {
                            if (selectionCriteria.doesConform(object, this.session, (AbstractRecord)translationRow, valueHolderPolicy)) {
                                objects.add(object);
                            }
                        } catch (QueryException queryException) {
                            if (queryException.getErrorCode() == QueryException.MUST_INSTANTIATE_VALUEHOLDERS) {
                                if (valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_CONFORMED) {
                                    objects.add(object);
                                } else if (valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_THROW_INDIRECTION_EXCEPTION) {
                                    throw queryException;
                                }
                            } else {
                                throw queryException;
                            }
                        }
                    }
                }
            }
        } finally {
            this.session.endOperationProfile(SessionProfiler.Caching);
        }
        return objects;
    }

    /**
     * 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, AbstractSession session){
        return getIdentityMap(descriptor).getAllFromIdentityMapWithEntityPK(pkList, descriptor, session);
    }

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

    /**
     * Invalidate objects meeting selectionCriteria.
     */
    public void invalidateObjects(Expression selectionCriteria, Class<?> theClass, DataRecord translationRow, boolean shouldInvalidateOnException) {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        this.session.startOperationProfile(SessionProfiler.Caching);
        try {
            IdentityMap map = getIdentityMap(descriptor, true);
            if(map == null) {
                return;
            }
            boolean isChildDescriptor = descriptor.isChildDescriptor();
            if (selectionCriteria != null) {
                // PERF: Avoid clone of expression.
                ExpressionBuilder builder = selectionCriteria.getBuilder();
                if (builder.getSession() == null) {
                    builder.setSession(this.session.getRootSession(null));
                    builder.setQueryClass(theClass);
                }
                CacheInvalidationPolicy cacheInvalidationPolicy = descriptor.getCacheInvalidationPolicy();
                int inMemoryQueryIndirectionPolicy = InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_NOT_CONFORMED;
                if (shouldInvalidateOnException) {
                    inMemoryQueryIndirectionPolicy = InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_CONFORMED;
                }

                // cache the current time to avoid calculating it every time through the loop
                long currentTimeInMillis = System.currentTimeMillis();
                //Enumeration doesn't checkReadLocks
                for (Enumeration<CacheKey> cacheEnum = map.keys(false); cacheEnum.hasMoreElements();) {
                    CacheKey key = cacheEnum.nextElement();
                    Object object = key.getObject();
                    if (object == null || cacheInvalidationPolicy.isInvalidated(key, currentTimeInMillis)) {
                        continue;
                    }

                    // Must check for inheritance.
                    if (!isChildDescriptor || (object.getClass() == theClass) || (theClass.isInstance(object))) {
                        try {
                            if (selectionCriteria.doesConform(object, this.session, (AbstractRecord)translationRow, inMemoryQueryIndirectionPolicy)) {
                                key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
                            }
                        } catch (QueryException queryException) {
                            if(queryException.getErrorCode() == QueryException.CANNOT_CONFORM_EXPRESSION) {
                                // if the expression can't be confirmed for the object it's likely the same will happen to all other objects -
                                // invalidate all objects of theClass if required, otherwise leave.
                                if (shouldInvalidateOnException) {
                                    invalidateObjects(null, theClass, null, true);
                                } else {
                                    return;
                                }
                            } else {
                                if (shouldInvalidateOnException) {
                                    key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
                                }
                            }
                        } catch (RuntimeException runtimeException) {
                            if (shouldInvalidateOnException) {
                                key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
                            }
                        }
                    }
                }
            } else {
                // selectionCriteria == null
                if(isChildDescriptor) {
                    // Must check for inheritance.
                    for (Enumeration<CacheKey> cacheEnum = map.keys(false); cacheEnum.hasMoreElements();) {
                        CacheKey key = cacheEnum.nextElement();
                        Object object = key.getObject();
                        if (object == null) {
                            continue;
                        }

                        if ((object.getClass() == theClass) || (theClass.isInstance(object))) {
                            key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
                        }
                    }
                } else {
                    // if it's either a root class or there is no inheritance just invalidate the whole identity map
                    for (Enumeration<CacheKey> cacheEnum = map.keys(false); cacheEnum.hasMoreElements();) {
                        CacheKey key = cacheEnum.nextElement();
                        key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
                    }
                }
            }
            invalidateQueryCache(theClass);
        } finally {
            this.session.endOperationProfile(SessionProfiler.Caching);
        }
    }

    /**
     * Retrieve the cache key for the given identity information.
     */
    public CacheKey getCacheKeyForObjectForLock(Object primaryKey, Class<?> theClass, ClassDescriptor descriptor) {
        if (primaryKey == null) {
            return null;
        }
        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return null;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = map.getCacheKeyForLock(primaryKey);
            } finally {
                releaseReadLock();
                this.session.endOperationProfile(SessionProfiler.Caching);
            }
        } else {
            cacheKey = map.getCacheKeyForLock(primaryKey);
        }
        return cacheKey;
    }

    /**
     * Retrieve the cache key for the given identity information.
     */
    public CacheKey getCacheKeyForObject(Object primaryKey, Class<?> theClass, ClassDescriptor descriptor, boolean forMerge) {
        if (primaryKey == null) {
            return null;
        }
        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return null;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = map.getCacheKey(primaryKey, forMerge);
            } finally {
                releaseReadLock();
                this.session.endOperationProfile(SessionProfiler.Caching);
            }
        } else {
            cacheKey = map.getCacheKey(primaryKey, forMerge);
        }
        return cacheKey;
    }
    /**
     * Return the cache mutex.
     * This allows for the entire cache to be locked.
     * This is done for transaction isolations on merges, although never locked by default.
     */
    public ConcurrencyManager getCacheMutex() {
        return cacheMutex;
    }

    /**
     * This method is used to get a list of those classes with IdentityMaps in the Session.
     */
    public Vector getClassesRegistered() {
        Iterator<Class<?>> classes = getIdentityMaps().keySet().iterator();
        Vector results = new Vector(getIdentityMaps().size());
        while (classes.hasNext()) {
            results.add(classes.next().getName());
        }
        return results;
    }

    /**
     * Get the object from the identity map which has the same identity information
     * as the given object.
     */
    public Object getFromIdentityMap(Object object) {
        ClassDescriptor descriptor = this.session.getDescriptor(object);
        Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, this.session);
        return getFromIdentityMap(primaryKey, object.getClass(), descriptor);
    }

    /**
     * Get the object from the identity map which has the given primary key and class.
     */
    public Object getFromIdentityMap(Object key, Class<?> theClass, ClassDescriptor descriptor) {
        return getFromIdentityMap(key, theClass, true, descriptor);
    }

    /**
     * Get the object from the identity map which has the given primary key and class.
     * Only return the object if it has not been invalidated.
     */
    public Object getFromIdentityMap(Object key, Class<?> theClass, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor) {
        if (key == null) {
            return null;
        }

        CacheKey cacheKey;
        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return null;
        }
        Object domainObject = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = map.getCacheKey(key, false);
            } finally {
                releaseReadLock();
            }
        } else {
            cacheKey = map.getCacheKey(key, false);
        }

        if ((cacheKey != null) && (shouldReturnInvalidatedObjects || !descriptor.getCacheInvalidationPolicy().isInvalidated(cacheKey))) {
            // BUG#4772232 - The read-lock must be checked to avoid returning a partial object,
            // PERF: Just check the read-lock to avoid acquire if not locked.
            // This is ok if you get the object first, as the object cannot gc and identity is always maintained.
            domainObject = cacheKey.getObject();
            cacheKey.checkReadLock();
            // Resolve the inheritance issues.
            domainObject = checkForInheritance(domainObject, theClass, descriptor);
        }

        if (this.isCacheAccessPreCheckRequired) {
            this.session.endOperationProfile(SessionProfiler.Caching);
        }

        return domainObject;
    }

    public Object getFromIdentityMap(Expression selectionCriteria, Class<?> theClass, DataRecord translationRow, int valueHolderPolicy, boolean conforming, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor) {
        UnitOfWorkImpl unitOfWork = (conforming) ? (UnitOfWorkImpl)this.session : null;
        this.session.startOperationProfile(SessionProfiler.Caching);
        try {
            if (selectionCriteria != null) {
                // PERF: Avoid clone of expression.
                ExpressionBuilder builder = selectionCriteria.getBuilder();
                if (builder.getSession() == null) {
                    builder.setSession(this.session.getRootSession(null));
                    builder.setQueryClass(theClass);
                }
            }
            IdentityMap map = getIdentityMap(descriptor, false);

            // Bug #321041 - if policy is set to trigger indirection, then iterate over a copy of the cache keys collection
            //               to avoid a ConcurrentModificationException
            Enumeration<CacheKey> cacheEnum = valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION ? map.cloneKeys() : map.keys();

            // cache the current time to avoid calculating it every time through the loop
            long currentTimeInMillis = System.currentTimeMillis();
            while (cacheEnum.hasMoreElements()) {
                CacheKey key = cacheEnum.nextElement();
                if (!shouldReturnInvalidatedObjects && descriptor.getCacheInvalidationPolicy().isInvalidated(key, currentTimeInMillis)) {
                    continue;
                }
                Object object = key.getObject();

                // Bug # 3216337 - key.getObject() should check for null; object may be GC'd (MWN)
                if (object == null) {
                    continue;
                }

                // Must check for inheritance.
                if ((object.getClass() == theClass) || (theClass.isInstance(object))) {
                    if (selectionCriteria == null) {
                        // bug 2782991: if first found was deleted nothing returned.
                        if (!(conforming && unitOfWork.isObjectDeleted(object))) {
                            return object;
                        }
                    }

                    //CR 3677 integration of a ValueHolderPolicy
                    try {
                        if (selectionCriteria.doesConform(object, this.session, (AbstractRecord)translationRow, valueHolderPolicy)) {
                            // bug 2782991: if first found was deleted nothing returned.
                            if (!(conforming && unitOfWork.isObjectDeleted(object))) {
                                return object;
                            }
                        }
                    } catch (QueryException queryException) {
                        if (queryException.getErrorCode() == QueryException.MUST_INSTANTIATE_VALUEHOLDERS) {
                            if (valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_CONFORMED) {
                                // bug 2782991: if first found was deleted nothing returned.
                                if (!(conforming && unitOfWork.isObjectDeleted(object))) {
                                    return object;
                                }
                            } else if (valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_NOT_CONFORMED) {
                                // For bug 2667870 just skip this item, but do not abort.
                            } else {
                                throw queryException;
                            }
                        } else {
                            throw queryException;
                        }
                    }
                }
            }
        } finally {
            this.session.endOperationProfile(SessionProfiler.Caching);
        }
        return null;
    }

    /**
     * Get the object from the cache with the given primary key and class.
     * Do not return the object if it was invalidated.
     */
    public Object getFromIdentityMapWithDeferredLock(Object key, Class<?> theClass, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor) {
        if (key == null) {
            return null;
        }

        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return null;
        }
        CacheKey cacheKey;
        Object domainObject = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = map.getCacheKey(key, false);
            } finally {
                releaseReadLock();
            }
        } else {
            cacheKey = map.getCacheKey(key, false);
        }

        if ((cacheKey != null) && (shouldReturnInvalidatedObjects || !descriptor.getCacheInvalidationPolicy().isInvalidated(cacheKey))) {
            // PERF: Just check the read-lock to avoid acquire if not locked.
            // This is ok if you get the object first, as the object cannot gc and identity is always maintained.
            domainObject = cacheKey.getObject();
            cacheKey.checkDeferredLock();
            // Reslove inheritance issues.
            domainObject = checkForInheritance(domainObject, theClass, descriptor);
        }


        if (this.isCacheAccessPreCheckRequired) {
            this.session.endOperationProfile(SessionProfiler.Caching);
        }

        return domainObject;
    }

    /**
     * INTERNAL:
     * Return the identity map for the class, if missing create a new one.
     */
    public IdentityMap getIdentityMap(ClassDescriptor descriptor) {
        return  getIdentityMap(descriptor, false);
    }

    /**
     * INTERNAL:
     * Return the identity map for the class.
     * @param returnNullIfNoMap if true return null if no map, otherwise create one.
     */
    public IdentityMap getIdentityMap(ClassDescriptor descriptor, boolean returnNullIfNoMap) {
        // Ensure that an identitymap is only used for the root descriptor for inheritance.
        // This is required to obtain proper cache hits.
        if (descriptor.hasInheritance()) {
            descriptor = descriptor.getInheritancePolicy().getRootParentDescriptor();
        }
        Class<?> descriptorClass = descriptor.getJavaClass();

        // PERF: First check if same as lastAccessedIdentityMap to avoid lookup.
        IdentityMap tempMap = this.lastAccessedIdentityMap;
        if ((tempMap != null) && (tempMap.getDescriptorClass() == descriptorClass)) {
            return tempMap;
        }

        // PERF: Avoid synchronization through get and putIfAbsent double-check.
        IdentityMap identityMap = this.identityMaps.get(descriptorClass);
        if (identityMap == null) {
            if (returnNullIfNoMap && descriptor.getCachePolicy().getCacheInterceptorClass() == null) {
                //interceptor monitors the identity map and needs to know that a request occurred.
                return null;
            }
            IdentityMap newIdentityMap = null;
            if (this.session.isUnitOfWork() || this.session.isIsolatedClientSession()) {
                newIdentityMap = buildNewIdentityMap(descriptor);
                identityMap = this.identityMaps.put(descriptorClass, newIdentityMap);
            } else {
                newIdentityMap = buildNewIdentityMap(descriptor);
                identityMap = (IdentityMap)((ConcurrentMap)this.identityMaps).putIfAbsent(descriptorClass, newIdentityMap);
            }
            if (identityMap == null) {
                identityMap = newIdentityMap;
            }
        }
        this.lastAccessedIdentityMap = identityMap;

        return identityMap;
    }

    protected Map<Class<?>, IdentityMap> getIdentityMaps() {
        return identityMaps;
    }

    /**
     * Return an iterator of the classes in the identity map.
     */
    public Iterator getIdentityMapClasses() {
        return getIdentityMaps().keySet().iterator();
    }

    /**
     * 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 shouldCheckExpiry) {
        if (query.getQueryResultsCachePolicy() == null) {
            return null;
        }
        // PERF: use query name, unless no name.
        Object queryKey = query.getName();
        if ((queryKey == null) || ((String)queryKey).length() == 0) {
            queryKey = query;
        }
        IdentityMap map = this.queryResults.get(queryKey);
        if (map == null) {
            return null;
        }

        Object lookupParameters;
        if ((parameters == null) || parameters.isEmpty()) {
            lookupParameters = CacheId.EMPTY;
        } else {
            lookupParameters = new CacheId(parameters.toArray());
        }

        CacheKey key = map.getCacheKey(lookupParameters, false);
        if ((key == null) || (shouldCheckExpiry && query.getQueryResultsCachePolicy().getCacheInvalidationPolicy().isInvalidated(key))) {
            return null;
        }
        return key.getObject();
    }

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

        CacheKey cacheKey = map.getCacheKey(indexValues, false);
        if (cacheKey == null) {
            return null;
        }
        // The cache key is nested as the object cache key is put into the cache.
        cacheKey = (CacheKey)cacheKey.getObject();
        if (cacheKey == null) {
            return null;
        }
        if (shouldCheckExpiry && descriptor.getCacheInvalidationPolicy().isInvalidated(cacheKey)) {
            return null;
        }
        return cacheKey;
    }

    /**
     * Index the cache key by the index values.
     */
    public void putCacheKeyByIndex(CacheIndex index, CacheId indexValues, CacheKey cacheKey, ClassDescriptor descriptor) {
        if (this.cacheIndexes == null) {
            return;
        }
        if (indexValues == null) {
            return;
        }
        IdentityMap map = this.cacheIndexes.get(index);
        if (map == null) {
            synchronized (this.cacheIndexes) {
                map = this.cacheIndexes.get(index);
                if (map == null) {
                    map = buildNewIdentityMap(index.getCacheType(), index.getCacheSize(), null, false);
                    this.cacheIndexes.put(index, map);
                }
            }
        }
        map.put(indexValues, cacheKey, null, 0);
    }

    protected AbstractSession getSession() {
        return session;
    }

    /**
     * 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) {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        IdentityMap map = getIdentityMap(descriptor, false);
        Object wrapper;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                wrapper = map.getWrapper(primaryKey);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            wrapper = map.getWrapper(primaryKey);
        }
        return wrapper;
    }

    /**
     * Returns the single write Lock manager for this session
     */
    public WriteLockManager getWriteLockManager() {
        // With Isolated Sessions not all Identity maps need a WriteLockManager so
        //lazy initialize
        synchronized (this) {
            if (this.writeLockManager == null) {
                this.writeLockManager = new WriteLockManager();
            }
        }
        return this.writeLockManager;
    }

    /**
     * Retrieve the write lock value of the cache key associated with the given primary key,
     */
    public Object getWriteLockValue(Object primaryKey, Class<?> domainClass, ClassDescriptor descriptor) {
        if (primaryKey == null) {
            return null;
        }
        IdentityMap map = getIdentityMap(descriptor, false);
        Object value;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                value = map.getWriteLockValue(primaryKey);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            value = map.getWriteLockValue(primaryKey);
        }
        return value;
    }

    /**
     * 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.
     */
    public void initializeIdentityMap(Class<?> theClass) throws EclipseLinkException {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);

        if (descriptor == null) {
            throw ValidationException.missingDescriptor(String.valueOf(theClass));
        }
        if (descriptor.isChildDescriptor()) {
            throw ValidationException.childDescriptorsDoNotHaveIdentityMap();
        }
        // Bug 3736313 - look up identity map by descriptor's java class
        Class<?> javaClass = descriptor.getJavaClass();
        IdentityMap identityMap = buildNewIdentityMap(descriptor);
        getIdentityMaps().put(javaClass, identityMap);
        clearLastAccessedIdentityMap();
        invalidateQueryCache(theClass);
    }

    public void initializeIdentityMaps() {
        clearLastAccessedIdentityMap();
        setIdentityMaps(new ConcurrentHashMap());
        clearQueryCache();
        clearCacheIndexes();
    }

    /**
     * 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.
     */
    public void printIdentityMap(Class<?> businessClass) {
        String cr = Helper.cr();
        ClassDescriptor descriptor = this.session.getDescriptor(businessClass);
        int cacheCounter = 0;
        StringWriter writer = new StringWriter();
        if (descriptor.isDescriptorTypeAggregate()) {
            return; //do nothing if descriptor is aggregate
        }

        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return;
        }
        writer.write(LoggingLocalization.buildMessage("identitymap_for", new Object[] { cr, Helper.getShortClassName(map.getClass()), Helper.getShortClassName(businessClass) }));
        if (descriptor.hasInheritance()) {
            if (descriptor.getInheritancePolicy().isRootParentDescriptor()) {
                writer.write(LoggingLocalization.buildMessage("includes"));
                List<ClassDescriptor> childDescriptors = descriptor.getInheritancePolicy().getChildDescriptors();
                if ((childDescriptors != null) && (childDescriptors.size() != 0)) {//Bug#2675242
                    Iterator<ClassDescriptor> iterator = childDescriptors.iterator();
                    writer.write(Helper.getShortClassName(iterator.next().getJavaClass()));
                    while (iterator.hasNext()) {
                        writer.write(", " + Helper.getShortClassName(iterator.next().getJavaClass()));
                    }
                }
                writer.write(")");
            }
        }

        for (Enumeration<CacheKey> enumtr = map.keys(); enumtr.hasMoreElements();) {
            org.eclipse.persistence.internal.identitymaps.CacheKey cacheKey = enumtr.nextElement();
            Object object = cacheKey.getObject();
            if (businessClass.isInstance(object)) {
                cacheCounter++;
                Object key = cacheKey.getKey();
                if (object == null) {
                    writer.write(LoggingLocalization.buildMessage("key_object_null", new Object[] { cr, key, "\t" }));
                } else {
                    String hashCode = String.valueOf(System.identityHashCode(object));
                    if (descriptor.usesOptimisticLocking() && descriptor.usesVersionLocking()) {
                        // Obtain writeLockValue and convert the value to String
                        Object writeLockValue = descriptor.getOptimisticLockingPolicy().getWriteLockValue(object, key, session);
                        String version = session.getPlatform().convertObject(writeLockValue, String.class);
                        writer.write(LoggingLocalization.buildMessage("key_version_identity_hash_code_object", new Object[] { cr, key, "\t", hashCode, object, version }));
                    } else {
                        writer.write(LoggingLocalization.buildMessage("key_identity_hash_code_object", new Object[] { cr, key, "\t", hashCode, object }));
                    }
                }
            }
        }
        writer.write(LoggingLocalization.buildMessage("elements", new Object[] { cr, String.valueOf(cacheCounter) }));
        this.session.log(SessionLog.SEVERE, SessionLog.CACHE, writer.toString(), null, null, false);
    }

    /**
     * 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.
     */
    public void printIdentityMaps() {
        for (Iterator<Class<?>> iterator = this.session.getDescriptors().keySet().iterator();
             iterator.hasNext();) {
            Class<?> businessClass = iterator.next();
            ClassDescriptor descriptor = this.session.getDescriptor(businessClass);
            if (descriptor.hasInheritance()) {
                if (descriptor.getInheritancePolicy().isRootParentDescriptor()) {
                    printIdentityMap(businessClass);
                }
            } else {
                printIdentityMap(businessClass);
            }
        }
    }

    /**
     * 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.
     */
    public void printLocks() {
        StringWriter writer = new StringWriter();
        HashMap threadCollection = new HashMap();
        writer.write(TraceLocalization.buildMessage("lock_writer_header", null) + Helper.cr());
        Iterator<IdentityMap> idenityMapsIterator = this.session.getIdentityMapAccessorInstance().getIdentityMapManager().getIdentityMaps().values().iterator();
        while (idenityMapsIterator.hasNext()) {
            IdentityMap idenityMap = idenityMapsIterator.next();
            idenityMap.collectLocks(threadCollection);
        }
        Object[] parameters = new Object[1];
        for (Iterator threads = threadCollection.keySet().iterator(); threads.hasNext();) {
            Thread activeThread = (Thread)threads.next();
            parameters[0] = activeThread.getName();
            writer.write(TraceLocalization.buildMessage("active_thread", parameters) + Helper.cr());
            for (Iterator cacheKeys = ((HashSet)threadCollection.get(activeThread)).iterator();
                     cacheKeys.hasNext();) {
                CacheKey cacheKey = (CacheKey)cacheKeys.next();
                if (cacheKey.isAcquired() && cacheKey.getActiveThread() == activeThread){
                    parameters[0] = cacheKey.getObject();
                    writer.write(TraceLocalization.buildMessage("locked_object", parameters) + Helper.cr());
                    writer.write("PK: " + cacheKey.getKey() + Helper.cr());
                    parameters[0] = cacheKey.getDepth();
                    writer.write(TraceLocalization.buildMessage("depth", parameters) + Helper.cr());
                    Exception stack = cacheKey.getStack();
                    if (stack != null) stack.printStackTrace(new PrintWriter(writer));
                } else{
                    writer.write(TraceLocalization.buildMessage("cachekey_released", new Object[]{}));
                    parameters[0] = cacheKey.getObject();
                    writer.write(TraceLocalization.buildMessage("locked_object", parameters) + Helper.cr());
                    writer.write("PK: " + cacheKey.getKey() + Helper.cr());
                }
            }
            DeferredLockManager deferredLockManager = ConcurrencyManager.getDeferredLockManager(activeThread);
            if (deferredLockManager != null) {
                for (Iterator deferredLocks = deferredLockManager.getDeferredLocks().iterator();
                         deferredLocks.hasNext();) {
                    ConcurrencyManager lock = (ConcurrencyManager)deferredLocks.next();
                    if (lock instanceof CacheKey){
                        parameters[0] = ((CacheKey)lock).getObject();
                        writer.write(TraceLocalization.buildMessage("deferred_locks", parameters) + Helper.cr());
                    }
                }
            }
        }
        writer.write(Helper.cr() + TraceLocalization.buildMessage("lock_writer_footer", null) + Helper.cr());
        this.session.log(SessionLog.SEVERE, SessionLog.CACHE, writer.toString(), null, null, false);
    }

    /**
     * Used to print all the Locks in the specified identity map in this session.
     * The output of this method will be logged to this session's SessionLog at FINEST level.
     */
    public void printLocks(Class<?> theClass) {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        StringWriter writer = new StringWriter();
        HashMap threadCollection = new HashMap();
        writer.write(TraceLocalization.buildMessage("lock_writer_header", null) + Helper.cr());
        IdentityMap identityMap = getIdentityMap(descriptor, false);
        identityMap.collectLocks(threadCollection);

        Object[] parameters = new Object[1];
        for (Iterator threads = threadCollection.keySet().iterator(); threads.hasNext();) {
            Thread activeThread = (Thread)threads.next();
            parameters[0] = activeThread.getName();
            writer.write(TraceLocalization.buildMessage("active_thread", parameters) + Helper.cr());
            for (Iterator cacheKeys = ((HashSet)threadCollection.get(activeThread)).iterator();
                     cacheKeys.hasNext();) {
                CacheKey cacheKey = (CacheKey)cacheKeys.next();
                parameters[0] = cacheKey.getObject();
                writer.write(TraceLocalization.buildMessage("locked_object", parameters) + Helper.cr());
                parameters[0] = cacheKey.getDepth();
                writer.write(TraceLocalization.buildMessage("depth", parameters) + Helper.cr());
            }
            DeferredLockManager deferredLockManager = ConcurrencyManager.getDeferredLockManager(activeThread);
            if (deferredLockManager != null) {
                for (Iterator deferredLocks = deferredLockManager.getDeferredLocks().iterator();
                         deferredLocks.hasNext();) {
                    ConcurrencyManager lock = (ConcurrencyManager)deferredLocks.next();
                    if (lock instanceof CacheKey){
                        parameters[0] = ((CacheKey)lock).getObject();
                        writer.write(TraceLocalization.buildMessage("deferred_locks", parameters) + Helper.cr());
                    }
                }
            }
        }
        writer.write(Helper.cr() + TraceLocalization.buildMessage("lock_writer_footer", null) + Helper.cr());
        this.session.log(SessionLog.SEVERE, SessionLog.CACHE, writer.toString(), null, null, false);
    }

    /**
     * Register the object with the identity map.
     * 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 CacheKey putInIdentityMap(Object domainObject, Object keys, Object writeLockValue, long readTime, ClassDescriptor descriptor) {
        if (keys == null) {
            return null;
        }
        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object implementation = builder.unwrapObject(domainObject, this.session);

        IdentityMap map = getIdentityMap(descriptor, false);
        CacheKey cacheKey;

        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            // This is atomic so considered a read lock.
            acquireReadLock();
            try {
                cacheKey = map.put(keys, implementation, writeLockValue, readTime);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            cacheKey = map.put(keys, implementation, writeLockValue, readTime);
        }
        return cacheKey;
    }

    /**
     * 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) {
        if ((results == null) || (results == InvalidObject.instance())) {
            if (query.getQueryResultsCachePolicy().isNullIgnored()) {
                return;
            }
        }
        // PERF: use query name, unless no name.
        Object queryKey = query.getName();
        if ((queryKey == null) || ((String)queryKey).length() == 0) {
            queryKey = query;
        }
        IdentityMap map = this.queryResults.get(queryKey);
        if (map == null) {
            synchronized (this.queryResults) {
                map = this.queryResults.get(queryKey);
                if (map == null) {
                    int size = query.getQueryResultsCachePolicy().getMaximumCachedResults();
                    // PERF: If no parameters, then there can only be one result.
                    if ((parameters == null) || parameters.isEmpty()) {
                        size = 1;
                    }
                    map = buildNewIdentityMap(query.getQueryResultsCachePolicy().getCacheType(), size, null, false);
                    this.queryResults.put(queryKey, map);
                    // Mark the query to be invalidated for the query classes.
                    if (query.getQueryResultsCachePolicy().getInvalidateOnChange()) {
                        for (Class<?> queryClass : query.getQueryResultsCachePolicy().getInvalidationClasses()) {
                            Set invalidations = this.queryResultsInvalidationsByClass.get(queryClass);
                            if (invalidations == null) {
                                invalidations = new HashSet();
                                this.queryResultsInvalidationsByClass.put(queryClass, invalidations);
                            }
                            invalidations.add(queryKey);
                        }
                    }
                }
            }
        }
        Object lookupParameters;
        if ((parameters == null) || parameters.isEmpty()) {
            lookupParameters = CacheId.EMPTY;
        } else {
            lookupParameters = new CacheId(parameters.toArray());
        }
        long queryTime = 0;
        if (query.isObjectLevelReadQuery()) {
            queryTime = ((ObjectLevelReadQuery)query).getExecutionTime();
        }
        if (queryTime == 0) {
            queryTime = System.currentTimeMillis();
        }
        // Bug 6138532 - store InvalidObject for "no results", do not store null
        if (results == null) {
            results = InvalidObject.instance();
        }
        map.put(lookupParameters, results, null, queryTime);
    }

    /**
     * Read-release the local-map and the entire cache.
     */
    protected void releaseReadLock() {
        if (this.session.getDatasourceLogin().shouldSynchronizedReadOnWrite()) {
            getCacheMutex().releaseReadLock();
        }
    }

    /**
     * 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() {
       if (this.session.getDatasourceLogin().shouldSynchronizedReadOnWrite() || this.session.getDatasourceLogin().shouldSynchronizeWrites()) {
             getCacheMutex().release();
        }
    }

    /**
     * Remove the object from the object cache.
     */
    public Object removeFromIdentityMap(Object key, Class<?> domainClass, ClassDescriptor descriptor, Object objectToRemove) {
        if (key == null) {
            return null;
        }
        IdentityMap map = getIdentityMap(descriptor, false);
        Object value;

        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            // This is atomic so considered a read lock.
            acquireReadLock();
            try {
                value = map.remove(key, objectToRemove);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            value = map.remove(key, objectToRemove);
        }
        if (session.getProject().allowExtendedCacheLogging()) {
            session.log(SessionLog.FINEST, SessionLog.CACHE, "cache_item_removal", new Object[] {domainClass, key, Thread.currentThread().getId(), Thread.currentThread().getName()});
        }
        return value;
    }

    /**
     * Set the cache mutex.
     * This allows for the entire cache to be locked.
     * This is done for transaction isolations on merges, although never locked by default.
     */
    protected void setCacheMutex(ConcurrencyManager cacheMutex) {
        this.cacheMutex = cacheMutex;
    }

    public void setIdentityMaps(ConcurrentMap identityMaps) {
        clearLastAccessedIdentityMap();
        this.identityMaps = identityMaps;
    }

    protected void setSession(AbstractSession session) {
        this.session = session;
    }

    /**
     * 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) {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        IdentityMap map = getIdentityMap(descriptor, false);

        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            // This is atomic so considered a read lock.
            acquireReadLock();
            try {
                map.setWrapper(primaryKey, wrapper);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            map.setWrapper(primaryKey, wrapper);
        }
    }

    /**
     * Update the write lock value of the cache key associated with the given primary key,
     */
    public void setWriteLockValue(Object primaryKey, Class<?> theClass, Object writeLockValue) {
        if (primaryKey == null) {
            return;
        }
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        IdentityMap map = getIdentityMap(descriptor, false);

        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            // This is atomic so considered a read lock.
            acquireReadLock();
            try {
                map.setWriteLockValue(primaryKey, writeLockValue);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            map.setWriteLockValue(primaryKey, writeLockValue);
        }
    }

    /**
     * This method is used to resolve the inheritance issues arisen when conforming from the identity map
     * 1. Avoid reading the unintended subclass during in-memory query(e.g. when querying on large project, do not want
     *    to check small project,  both are inherited from the project, and stored in the same identity map).
     * 2. EJB container-generated classes broke the inheritance hierarchy. Need to use associated descriptor to track
     *    the relationship. CR4005-2612426, King-Sept-18-2002
     */
    protected Object checkForInheritance(Object domainObject, Class<?> superClass, ClassDescriptor descriptor) {
        if ((domainObject != null) && ((domainObject.getClass() != superClass) && (!superClass.isInstance(domainObject)))) {
            // Before returning null, check if we are using EJB inheritance.
            if (descriptor.hasInheritance() && descriptor.getInheritancePolicy().getUseDescriptorsToValidateInheritedObjects()) {
                // EJB inheritance on the descriptors, not the container-generated classes/objects. We need to check the
                // identity map for the bean instance through the descriptor.
                if (descriptor.getInheritancePolicy().getSubclassDescriptor(domainObject.getClass()) == null) {
                    return null;
                }
                return domainObject;
            }
            return null;
        }
        return domainObject;
    }
}
