/*
 * Copyright (c) 2011, 2019 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
//     05/19/2014-2.6 Tomas Kraus
//       - 437578: Added cacheable field and updated setting isolation from parent.
package org.eclipse.persistence.descriptors;

import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.persistence.annotations.CacheCoordinationType;
import org.eclipse.persistence.annotations.CacheKeyType;
import org.eclipse.persistence.annotations.DatabaseChangeNotificationType;
import org.eclipse.persistence.config.CacheIsolationType;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.identitymaps.CacheId;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.sessions.DatabaseSession;

/**
 * <p><b>Purpose</b>:
 * CachePolicy defines the cache configuration.
 * EclipseLink supports an integrated shared (L2) object cache.
 * Caching is enabled by default.<br>
 * To disable caching use:<br>
 * <code>setCacheIsolation(CacheIsolationType.ISOLATED)</code>
 *
 * @see ClassDescriptor
 */
public class CachePolicy implements Cloneable, Serializable {
    protected Class identityMapClass;
    protected int identityMapSize;
    protected boolean shouldAlwaysRefreshCache;
    protected boolean shouldOnlyRefreshCacheIfNewerVersion;
    protected boolean shouldDisableCacheHits;

    protected Class remoteIdentityMapClass;
    protected int remoteIdentityMapSize;
    protected boolean shouldAlwaysRefreshCacheOnRemote;
    protected boolean shouldDisableCacheHitsOnRemote;

    // Used only to evaluate cache isolation type in this class methods.
    /**
     * Entity @Cacheable annotation value.
     * This value contains Boolean value equal to annotation value or null when
     * no annotation was set for entity. Parent values are ignored, value refers
     * to current class only.
     * This value is set only when SharedCacheMode allows to override caching
     * on entity level (DISABLE_SELECTIVE  or ENABLE_SELECTIVE). Default value
     * is <code>null</code> what means no annotation is present in current class.
     */
    private Boolean cacheable = null;
    // this attribute is used to determine what classes should be isolated from the shared cache
    // and the severity of their isolation.
    protected CacheIsolationType cacheIsolation;

    /** Configures how objects will be sent via cache synchronization, if synchronization is enabled. */
    protected int cacheSynchronizationType = UNDEFINED_OBJECT_CHANGE_BEHAVIOR;
    public static final int UNDEFINED_OBJECT_CHANGE_BEHAVIOR = 0;
    public static final int SEND_OBJECT_CHANGES = 1;
    public static final int INVALIDATE_CHANGED_OBJECTS = 2;
    public static final int SEND_NEW_OBJECTS_WITH_CHANGES = 3;
    public static final int DO_NOT_SEND_CHANGES = 4;

    /** Configures how the unit of work uses the session cache. */
    protected int unitOfWorkCacheIsolationLevel = UNDEFINED_ISOLATATION;
    /* Required to resolve initialization. */
    protected boolean wasDefaultUnitOfWorkCacheIsolationLevel;
    public static final int UNDEFINED_ISOLATATION = -1;
    public static final int USE_SESSION_CACHE_AFTER_TRANSACTION = 0;
    public static final int ISOLATE_NEW_DATA_AFTER_TRANSACTION = 1; // this is the default behaviour even when undefined.
    public static final int ISOLATE_CACHE_AFTER_TRANSACTION = 2;
    public static final int ISOLATE_FROM_CLIENT_SESSION = 3;  // Entity Instances only exist in UOW and shared cache.
    public static final int ISOLATE_CACHE_ALWAYS = 4;

    /** Allow cache key type to be configured. */
    protected CacheKeyType cacheKeyType;

    //Added for interceptor support.
    protected Class cacheInterceptorClass;
    //Added for interceptor support.
    protected String cacheInterceptorClassName;

    /** This flag controls how the MergeManager should merge an Entity when merging into the shared cache.*/
    protected boolean fullyMergeEntity;

    /**
     * In certain cases and cache types it is more efficient to preFetch the cache keys from the cache when
     * building the results of the query.  Set this flag to true to prefetch the results.
     */
    protected boolean prefetchCacheKeys;

    protected Map<List<DatabaseField>, CacheIndex> cacheIndexes;

    /** Allows configuration of database change event notification. */
    protected DatabaseChangeNotificationType databaseChangeNotificationType;

    /**
     * PUBLIC:
     * Return a new descriptor.
     */
    public CachePolicy() {
        this.identityMapSize = -1;
        this.remoteIdentityMapSize = -1;
    }

    /**
     * Returns what type of database change notification an entity/descriptor should use.
     * This is only relevant if the persistence unit/session has been configured with a DatabaseEventListener,
     * such as the OracleChangeNotificationListener that receives database change events.
     * This allows for the EclipseLink cache to be invalidated or updated from database changes.
     */
    public DatabaseChangeNotificationType getDatabaseChangeNotificationType() {
        return databaseChangeNotificationType;
    }

    /**
     * Configures what type of database change notification an entity/descriptor should use.
     * This is only relevant if the persistence unit/session has been configured with a DatabaseEventListener,
     * such as the OracleChangeNotificationListener that receives database change events.
     * This allows for the EclipseLink cache to be invalidated or updated from database changes.
     */
    public void setDatabaseChangeNotificationType(DatabaseChangeNotificationType databaseChangeNotificationType) {
        this.databaseChangeNotificationType = databaseChangeNotificationType;
    }

    /**
     * INTERNAL:
     * Allow the inheritance properties of the descriptor to be initialized.
     * The descriptor's parent must first be initialized.
     */
    public void initializeFromParent(CachePolicy parentPolicy, ClassDescriptor descriptor, ClassDescriptor descriptorDescriptor, AbstractSession session) throws DescriptorException {
        // If the parent is isolated, then the child must also be isolated.
        if (!parentPolicy.isSharedIsolation()) {
            // Do not override cache isolation when explicitly enabled by @Cacheable(true) annotation in current class.
            boolean copyParrent = cacheable == null || cacheable == false;
            if (!isIsolated() && (getCacheIsolation() != parentPolicy.getCacheIsolation()) && copyParrent) {
                session.log(SessionLog.WARNING, SessionLog.METADATA, "overriding_cache_isolation",
                        new Object[]{descriptorDescriptor.getAlias(),
                                parentPolicy.getCacheIsolation(), descriptor.getAlias(),
                                getCacheIsolation()});
                setCacheIsolation(parentPolicy.getCacheIsolation());
            }
        }
        // Child must maintain the same indexes as the parent.
        for (CacheIndex index : parentPolicy.getCacheIndexes().values()) {
            addCacheIndex(index);
        }
        if ((getDatabaseChangeNotificationType() == null) && (parentPolicy.getDatabaseChangeNotificationType() != null)) {
            setDatabaseChangeNotificationType(parentPolicy.getDatabaseChangeNotificationType());
        }
        if ((getCacheSynchronizationType() == UNDEFINED_OBJECT_CHANGE_BEHAVIOR)
                && (parentPolicy.getCacheSynchronizationType() != UNDEFINED_OBJECT_CHANGE_BEHAVIOR)) {
            setCacheSynchronizationType(parentPolicy.getCacheSynchronizationType());
        }
    }

    /**
     * INTERNAL:
     * Initialize the cache isolation setting.
     * This may need to be called multiple times as notifyReferencingDescriptorsOfIsolation() can change the cache isolation.
     */
    public void postInitialize(ClassDescriptor descriptor, AbstractSession session) throws DescriptorException {
        if (!isSharedIsolation()) {
            descriptor.notifyReferencingDescriptorsOfIsolation(session);
        }

        // PERF: If using isolated cache, then default uow isolation to always (avoids merge/double build).
        if ((getUnitOfWorkCacheIsolationLevel() == UNDEFINED_ISOLATATION) || this.wasDefaultUnitOfWorkCacheIsolationLevel) {
            this.wasDefaultUnitOfWorkCacheIsolationLevel = true;
            if (isIsolated()) {
                setUnitOfWorkCacheIsolationLevel(ISOLATE_CACHE_ALWAYS);
            } else if (isProtectedIsolation()) {
                setUnitOfWorkCacheIsolationLevel(ISOLATE_FROM_CLIENT_SESSION);
            } else {
                setUnitOfWorkCacheIsolationLevel(ISOLATE_NEW_DATA_AFTER_TRANSACTION);
            }
        }

        // Record that there is an isolated class in the project.
        if (!isSharedIsolation()) {
            session.getProject().setHasIsolatedClasses(true);
        }
        if (!shouldIsolateObjectsInUnitOfWork() && !descriptor.shouldBeReadOnly()) {
            session.getProject().setHasNonIsolatedUOWClasses(true);
        }
    }

    /**
     * INTERNAL:
     * Allow the inheritance properties of the descriptor to be initialized.
     * The descriptor's parent must first be initialized.
     */
    public void initialize(ClassDescriptor descriptor, AbstractSession session) throws DescriptorException {
        if (hasCacheIndexes()) {
            for (CacheIndex index : getCacheIndexes().values()) {
                for (int count = 0; count < index.getFields().size(); count++) {
                    index.getFields().set(count, descriptor.buildField(index.getFields().get(count)));
                }
            }
        }
        for (DatabaseMapping mapping : descriptor.getMappings()) {
            if (!mapping.isCacheable()) {
                if (isSharedIsolation()) {
                    setCacheIsolation(CacheIsolationType.PROTECTED);
                }
            }

            if (mapping.isForeignReferenceMapping()) {
                ClassDescriptor referencedDescriptor = mapping.getReferenceDescriptor();
                if (referencedDescriptor!= null) {
                    if (isSharedIsolation() && !referencedDescriptor.getCachePolicy().isSharedIsolation()) {
                        setCacheIsolation(CacheIsolationType.PROTECTED);
                    }
                }
            }

            if (mapping.isAggregateObjectMapping()) {
                ClassDescriptor referencedDescriptor = mapping.getReferenceDescriptor();
                if (referencedDescriptor != null) {
                    if (isSharedIsolation() && !referencedDescriptor.getCachePolicy().isSharedIsolation()) {
                        setCacheIsolation(CacheIsolationType.PROTECTED);
                    }
                }
            }
        }

        if (this.databaseChangeNotificationType == null) {
            this.databaseChangeNotificationType = DatabaseChangeNotificationType.INVALIDATE;
        }
        if (this.cacheSynchronizationType == UNDEFINED_OBJECT_CHANGE_BEHAVIOR) {
            this.cacheSynchronizationType = SEND_OBJECT_CHANGES;
        }
        if ((this.databaseChangeNotificationType != DatabaseChangeNotificationType.NONE)
                && session.isDatabaseSession() && ((DatabaseSession)session).getDatabaseEventListener() != null) {
            ((DatabaseSession)session).getDatabaseEventListener().initialize(descriptor, session);
        }
    }

    /**
     * PUBLIC:
     * Return the cache index for the field names.
     */
    public CacheIndex getCacheIndex(List<DatabaseField> fields) {
        return getCacheIndexes().get(fields);
    }

    /**
     * PUBLIC:
     * Add the cache index to the descriptor's cache settings.
     * This allows for cache hits to be obtained on non-primary key fields.
     * The primary key is always indexed in the cache.
     * Cache indexes are defined by their database column names.
     */
    public void addCacheIndex(CacheIndex index) {
        getCacheIndexes().put(index.getFields(), index);
    }

    /**
     * PUBLIC:
     * Add the cache index to the descriptor's cache settings.
     * This allows for cache hits to be obtained on non-primary key fields.
     * The primary key is always indexed in the cache.
     * Cache indexes are defined by their database column names.
     */
    public void addCacheIndex(String... fields) {
        addCacheIndex(new CacheIndex(fields));
    }

    /**
     * PUBLIC:
     * Add the cache index to the descriptor's cache settings.
     * This allows for cache hits to be obtained on non-primary key fields.
     * The primary key is always indexed in the cache.
     * Cache indexes are defined by their database column names.
     */
    public void addCacheIndex(DatabaseField fields[]) {
        addCacheIndex(new CacheIndex(fields));
    }

    public boolean hasCacheIndexes() {
        return (this.cacheIndexes != null) && (!this.cacheIndexes.isEmpty());
    }

    public Map<List<DatabaseField>, CacheIndex> getCacheIndexes() {
        if (this.cacheIndexes == null) {
            this.cacheIndexes = new HashMap<>();
        }
        return this.cacheIndexes;
    }

    public void setCacheIndexes(Map<List<DatabaseField>, CacheIndex> cacheIndexes) {
        this.cacheIndexes = cacheIndexes;
    }

    @Override
    public CachePolicy clone() {
        try {
            return (CachePolicy)super.clone();
        } catch (CloneNotSupportedException ignore) {
            throw new InternalError(ignore.getMessage());
        }
    }

    /**
     * INTERNAL:
     * Some attributes have default values defined in Project.
     * If such the value for the attribute hasn't been set then the default value is assigned.
     */
    public void assignDefaultValues(AbstractSession session) {
        if(this.identityMapSize == -1) {
            this.identityMapSize = session.getProject().getDefaultIdentityMapSize();
        }
        if(this.identityMapClass == null) {
            this.identityMapClass = session.getProject().getDefaultIdentityMapClass();
        }
        if(this.cacheIsolation == null) {
            this.cacheIsolation = session.getProject().getDefaultCacheIsolation();
        }
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this Descriptor to actual class-based
     * settings. This method is used when converting a project that has been built
     * with class names to a project with classes.
     * @param classLoader
     */
    public void convertClassNamesToClasses(ClassLoader classLoader) {
        try {
            if (this.cacheInterceptorClass == null && this.cacheInterceptorClassName != null){
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                    try {
                        this.cacheInterceptorClass = AccessController.doPrivileged(new PrivilegedClassForName(this.cacheInterceptorClassName, true, classLoader));
                    } catch (PrivilegedActionException exception) {
                        throw ValidationException.classNotFoundWhileConvertingClassNames(this.cacheInterceptorClassName, exception.getException());
                   }
                } else {
                    this.cacheInterceptorClass = PrivilegedAccessHelper.getClassForName(this.cacheInterceptorClassName, true, classLoader);
                }
            }
        } catch (ClassNotFoundException exc){
            throw ValidationException.classNotFoundWhileConvertingClassNames(this.cacheInterceptorClassName, exc);
        }
    }

    /**
     * @return the fullyMergeEntity
     */
    public boolean getFullyMergeEntity() {
        return fullyMergeEntity;
    }

    /**
     * ADVANCED:
     * Set what cache key type to use to store the object in the cache.
     */
    public void setCacheKeyType(CacheKeyType cacheKeyType) {
        this.cacheKeyType = cacheKeyType;
    }

    /**
     * ADVANCED:
     * Return what cache key type to use to store the object in the cache.
     */
    public CacheKeyType getCacheKeyType() {
        return cacheKeyType;
    }

    /**
     * A CacheInterceptor is an adaptor that when overridden and assigned to a Descriptor all interaction
     * between EclipseLink and the internal cache for that class will pass through the Interceptor.
     * Advanced users could use this interceptor to audit, profile or log cache access.  This Interceptor
     * could also be used to redirect or augment the TopLink cache with an alternate cache mechanism.
     * EclipseLink's configurated IdentityMaps will be passed to the Interceptor constructor.
     *
     * As with IdentityMaps an entire class inheritance hierarchy will share the same interceptor.
     * @see org.eclipse.persistence.sessions.interceptors.CacheInterceptor
     */
    public Class getCacheInterceptorClass(){
        return this.cacheInterceptorClass;
    }

    /**
     * A CacheInterceptor is an adaptor that when overridden and assigned to a Descriptor all interaction
     * between EclipseLink and the internal cache for that class will pass through the Interceptor.
     * Advanced users could use this interceptor to audit, profile or log cache access.  This Interceptor
     * could also be used to redirect or augment the TopLink cache with an alternate cache mechanism.
     * EclipseLink's configurated IdentityMaps will be passed to the Interceptor constructor.
     *
     * As with IdentityMaps an entire class inheritance hierarchy will share the same interceptor.
     * @see org.eclipse.persistence.sessions.interceptors.CacheInterceptor
     */
    public String getCacheInterceptorClassName(){
        return this.cacheInterceptorClassName;
    }

    /**
     * PUBLIC:
     * Get a value indicating the type of cache synchronization that will be used on objects of
     * this type. Possible values are:
     * SEND_OBJECT_CHANGES
     * INVALIDATE_CHANGED_OBJECTS
     * SEND_NEW_OBJECTS+WITH_CHANGES
     * DO_NOT_SEND_CHANGES
     * @return int
     *
     */
    public int getCacheSynchronizationType() {
        return cacheSynchronizationType;
    }

    /**
     * INTERNAL:
     * Return the class of identity map to be used by this descriptor.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public Class getIdentityMapClass() {
        return identityMapClass;
    }

    /**
     * PUBLIC:
     * Return the size of the identity map.
     */
    public int getIdentityMapSize() {
        return identityMapSize;
    }

    /**
     * INTERNAL:
     * Return the class of identity map to be used by this descriptor.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public Class getRemoteIdentityMapClass() {
        if (remoteIdentityMapClass == null) {
            remoteIdentityMapClass = getIdentityMapClass();
        }

        return remoteIdentityMapClass;
    }

    /**
     * PUBLIC:
     * Return the size of the remote identity map.
     */
    public int getRemoteIdentityMapSize() {
        if (remoteIdentityMapSize == -1) {
            remoteIdentityMapSize = getIdentityMapSize();
        }
        return remoteIdentityMapSize;
    }

    /**
     * PUBLIC:
     * Return if for cache hits on primary key read object queries to be disabled.
     *
     * @see ClassDescriptor#disableCacheHits()
     */
    public boolean shouldDisableCacheHits() {
        return shouldDisableCacheHits;
    }

    /**
     * PUBLIC:
     * Return if the remote server session cache hits on primary key read object queries is aloowed or not.
     *
     * @see ClassDescriptor#disableCacheHitsOnRemote()
     */
    public boolean shouldDisableCacheHitsOnRemote() {
        return shouldDisableCacheHitsOnRemote;
    }

    /**
     * PUBLIC:
     * This method returns <CODE>true</CODE> if the <CODE>ClassDescriptor</CODE> is configured to only refresh the cache
     * if the data received from the database by a query is newer than the data in the cache (as determined by the
     * optimistic locking field). Otherwise, it returns <CODE>false</CODE>.
     *
     * @see #setShouldOnlyRefreshCacheIfNewerVersion
     */
    public boolean shouldOnlyRefreshCacheIfNewerVersion() {
        return shouldOnlyRefreshCacheIfNewerVersion;
    }

    /**
     * PUBLIC:
     * This method returns <CODE>true</CODE> if the <CODE>ClassDescriptor</CODE> is configured to always refresh
     * the cache if data is received from the database by any query. Otherwise, it returns <CODE>false</CODE>.
     *
     * @see #setShouldAlwaysRefreshCache
     */
    public boolean shouldAlwaysRefreshCache() {
        return shouldAlwaysRefreshCache;
    }

    /**
     * PUBLIC:
     * This method returns <CODE>true</CODE> if the <CODE>ClassDescriptor</CODE> is configured to always remotely
     * refresh the cache if data is received from the database by any query in a {@link org.eclipse.persistence.sessions.remote.RemoteSession}.
     * Otherwise, it returns <CODE>false</CODE>.
     *
     * @see #setShouldAlwaysRefreshCacheOnRemote
     */
    public boolean shouldAlwaysRefreshCacheOnRemote() {
        return shouldAlwaysRefreshCacheOnRemote;
    }

    /**
     * PUBLIC:
     * Set if cache hits on primary key read object queries should be disabled.
     *
     * @see ClassDescriptor#alwaysRefreshCache()
     */
    public void setShouldDisableCacheHits(boolean shouldDisableCacheHits) {
        this.shouldDisableCacheHits = shouldDisableCacheHits;
    }

    /**
     * PUBLIC:
     * Set if the remote session cache hits on primary key read object queries is allowed or not.
     *
     * @see ClassDescriptor#disableCacheHitsOnRemote()
     */
    public void setShouldDisableCacheHitsOnRemote(boolean shouldDisableCacheHitsOnRemote) {
        this.shouldDisableCacheHitsOnRemote = shouldDisableCacheHitsOnRemote;
    }

    /**
     * PUBLIC:
     * When the <CODE>shouldOnlyRefreshCacheIfNewerVersion</CODE> argument passed into this method is <CODE>true</CODE>,
     * this method configures a <CODE>ClassDescriptor</CODE> to only refresh the cache if the data received from the database
     * by a query is newer than the data in the cache (as determined by the optimistic locking field) and as long as one of the following is true:
     *
     * <UL>
     * <LI>the <CODE>ClassDescriptor</CODE> was configured by calling {@link ClassDescriptor#alwaysRefreshCache} or {@link ClassDescriptor#alwaysRefreshCacheOnRemote},</LI>
     * <LI>the query was configured by calling {@link org.eclipse.persistence.queries.ObjectLevelReadQuery#refreshIdentityMapResult}, or</LI>
     * <LI>the query was a call to {@link org.eclipse.persistence.sessions.Session#refreshObject}</LI>
     * </UL>
     * <P>
     *
     * However, if a query hits the cache, data is not refreshed regardless of how this setting is configured. For example, by default,
     * when a query for a single object based on its primary key is executed, OracleAS TopLink will first look in the cache for the object.
     * If the object is in the cache, the cached object is returned and data is not refreshed. To avoid cache hits, use
     * the {@link ClassDescriptor#disableCacheHits} method.<P>
     *
     * Also note that the {@link org.eclipse.persistence.sessions.UnitOfWork} will not refresh its registered objects.<P>
     *
     * When the <CODE>shouldOnlyRefreshCacheIfNewerVersion</CODE> argument passed into this method is <CODE>false</CODE>, this method
     * ensures that a <CODE>ClassDescriptor</CODE> is not configured to only refresh the cache if the data received from the database by a
     * query is newer than the data in the cache (as determined by the optimistic locking field).
     *
     * @see ClassDescriptor#onlyRefreshCacheIfNewerVersion
     * @see ClassDescriptor#dontOnlyRefreshCacheIfNewerVersion
     */
    public void setShouldOnlyRefreshCacheIfNewerVersion(boolean shouldOnlyRefreshCacheIfNewerVersion) {
        this.shouldOnlyRefreshCacheIfNewerVersion = shouldOnlyRefreshCacheIfNewerVersion;
    }

    /**
     * PUBLIC:
     * When the <CODE>shouldAlwaysRefreshCache</CODE> argument passed into this method is <CODE>true</CODE>,
     * this method configures a <CODE>ClassDescriptor</CODE> to always refresh the cache if data is received from
     * the database by any query.<P>
     *
     * However, if a query hits the cache, data is not refreshed regardless of how this setting is configured.
     * For example, by default, when a query for a single object based on its primary key is executed, OracleAS TopLink
     * will first look in the cache for the object. If the object is in the cache, the cached object is returned and
     * data is not refreshed. To avoid cache hits, use the {@link ClassDescriptor#disableCacheHits} method.<P>
     *
     * Also note that the {@link org.eclipse.persistence.sessions.UnitOfWork} will not refresh its registered objects.<P>
     *
     * Use this property with caution because it can lead to poor performance and may refresh on queries when it is not desired.
     * Normally, if you require fresh data, it is better to configure a query with {@link org.eclipse.persistence.queries.ObjectLevelReadQuery#refreshIdentityMapResult}.
     * To ensure that refreshes are only done when required, use this method in conjunction with {@link ClassDescriptor#onlyRefreshCacheIfNewerVersion}.<P>
     *
     * When the <CODE>shouldAlwaysRefreshCache</CODE> argument passed into this method is <CODE>false</CODE>, this method
     * ensures that a <CODE>ClassDescriptor</CODE> is not configured to always refresh the cache if data is received from the database by any query.
     *
     * @see ClassDescriptor#alwaysRefreshCache
     * @see ClassDescriptor#dontAlwaysRefreshCache
     */
    public void setShouldAlwaysRefreshCache(boolean shouldAlwaysRefreshCache) {
        this.shouldAlwaysRefreshCache = shouldAlwaysRefreshCache;
    }

    /**
     * PUBLIC:
     * When the <CODE>shouldAlwaysRefreshCacheOnRemote</CODE> argument passed into this method is <CODE>true</CODE>,
     * this method configures a <CODE>ClassDescriptor</CODE> to always remotely refresh the cache if data is received from
     * the database by any query in a {@link org.eclipse.persistence.sessions.remote.RemoteSession}.
     *
     * However, if a query hits the cache, data is not refreshed regardless of how this setting is configured. For
     * example, by default, when a query for a single object based on its primary key is executed, OracleAS TopLink
     * will first look in the cache for the object. If the object is in the cache, the cached object is returned and
     * data is not refreshed. To avoid cache hits, use the {@link ClassDescriptor#disableCacheHitsOnRemote} method.<P>
     *
     * Also note that the {@link org.eclipse.persistence.sessions.UnitOfWork} will not refresh its registered objects.<P>
     *
     * Use this property with caution because it can lead to poor performance and may refresh on queries when it is
     * not desired. Normally, if you require fresh data, it is better to configure a query with {@link org.eclipse.persistence.queries.ObjectLevelReadQuery#refreshIdentityMapResult}.
     * To ensure that refreshes are only done when required, use this method in conjunction with {@link ClassDescriptor#onlyRefreshCacheIfNewerVersion}.<P>
     *
     * When the <CODE>shouldAlwaysRefreshCacheOnRemote</CODE> argument passed into this method is <CODE>false</CODE>,
     * this method ensures that a <CODE>ClassDescriptor</CODE> is not configured to always remotely refresh the cache if data
     * is received from the database by any query in a {@link org.eclipse.persistence.sessions.remote.RemoteSession}.
     *
     * @see ClassDescriptor#alwaysRefreshCacheOnRemote
     * @see ClassDescriptor#dontAlwaysRefreshCacheOnRemote
     */
    public void setShouldAlwaysRefreshCacheOnRemote(boolean shouldAlwaysRefreshCacheOnRemote) {
        this.shouldAlwaysRefreshCacheOnRemote = shouldAlwaysRefreshCacheOnRemote;
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be used by this descriptor.
     * The default is the "FullIdentityMap".
     */
    public void setRemoteIdentityMapClass(Class theIdentityMapClass) {
        remoteIdentityMapClass = theIdentityMapClass;
    }

    /**
     * PUBLIC:
     * Set the size of the identity map to be used by this descriptor.
     * The default is the 100.
     */
    public void setRemoteIdentityMapSize(int identityMapSize) {
        remoteIdentityMapSize = identityMapSize;
    }

    /**
     * INTERNAL:
     * Set entity @Cacheable annotation value.
     * @param cacheable Entity @Cacheable annotation value for current class
     *        or <code>null</code> if @Cacheable annotation is not set. Parent
     *        values are ignored, value shall refer to current class only.
     */
    public void setCacheable(Boolean cacheable) {
        this.cacheable = cacheable;
    }

    /**
     * PUBLIC:
     * Controls how the Entity instances will be cached.  See the CacheIsolationType for details on the options.
     * @return the isolationType
     */
    public CacheIsolationType getCacheIsolation() {
        return cacheIsolation;
    }

    /**
     * PUBLIC:
     * Controls how the Entity instances and data will be cached.  See the CacheIsolationType for details on the options.
     * To disable all second level caching simply set CacheIsolationType.ISOLATED.  Note that setting the isolation
     * will automatically set the corresponding cacheSynchronizationType.
     * ISOLATED = DO_NOT_SEND_CHANGES, PROTECTED and SHARED = SEND_OBJECT_CHANGES
     */
    public void setCacheIsolation(CacheIsolationType isolationType) {
        this.cacheIsolation = isolationType;
        if (CacheIsolationType.ISOLATED == isolationType) {
            // bug 3587273 - set the cache synchronization type so isolated objects are not sent
            // do not call the setter method because it does not allow changing the cache synchronization
            // type of isolated objects
            cacheSynchronizationType = DO_NOT_SEND_CHANGES;
        }
    }

    /**
     * INTERNAL:
     * Return if the unit of work should by-pass the session cache.
     * Objects will be built in the unit of work, and never merged into the session cache.
     */
    public boolean shouldIsolateObjectsInUnitOfWork() {
        return this.unitOfWorkCacheIsolationLevel == ISOLATE_CACHE_ALWAYS;
    }

    /**
     * INTERNAL:
     * Return if the unit of work should by-pass the IsolatedSession cache.
     * Objects will be built/merged into the unit of work and into the session cache.
     * but not built/merge into the IsolatedClientSession cache.
     */
    public boolean shouldIsolateProtectedObjectsInUnitOfWork() {
        return this.unitOfWorkCacheIsolationLevel == ISOLATE_FROM_CLIENT_SESSION;
    }

    /**
     * INTERNAL:
     * Return if the unit of work should by-pass the session cache after an early transaction.
     */
    public boolean shouldIsolateObjectsInUnitOfWorkEarlyTransaction() {
        return this.unitOfWorkCacheIsolationLevel == ISOLATE_CACHE_AFTER_TRANSACTION;
    }

    /**
     * INTERNAL:
     * Return if the unit of work should use the session cache after an early transaction.
     */
    public boolean shouldUseSessionCacheInUnitOfWorkEarlyTransaction() {
        return this.unitOfWorkCacheIsolationLevel == USE_SESSION_CACHE_AFTER_TRANSACTION;
    }

    /**
     * ADVANCED:
     * Return the unit of work cache isolation setting.
     * This setting configures how the session cache will be used in a unit of work.
     * @see #setUnitOfWorkCacheIsolationLevel(int)
     */
    public int getUnitOfWorkCacheIsolationLevel() {
        return unitOfWorkCacheIsolationLevel;
    }

    /**
     * ADVANCED:
     * This setting configures how the session cache will be used in a unit of work.
     * Most of the options only apply to a unit of work in an early transaction,
     * such as a unit of work that was flushed (writeChanges), issued a modify query, or acquired a pessimistic lock.
     * <p> USE_SESSION_CACHE_AFTER_TRANSACTION - Objects built from new data accessed after a unit of work early transaction are stored in the session cache.
     * This options is the most efficient as it allows the cache to be used after an early transaction.
     * This should only be used if it is known that this class is not modified in the transaction,
     * otherwise this could cause uncommitted data to be loaded into the session cache.
     * ISOLATE_NEW_DATA_AFTER_TRANSACTION - Default (when using caching): Objects built from new data accessed after a unit of work early transaction are only stored in the unit of work.
     * This still allows previously cached objects to be accessed in the unit of work after an early transaction,
     * but ensures uncommitted data will never be put in the session cache by storing any object built from new data only in the unit of work.
     * ISOLATE_CACHE_AFTER_TRANSACTION - After a unit of work early transaction the session cache is no longer used for this class.
     * Objects will be directly built from the database data and only stored in the unit of work, even if previously cached.
     * Note that this may lead to poor performance as the session cache is bypassed after an early transaction.
     * ISOLATE_CACHE_ALWAYS - Default (when using isolated cache): The session cache will never be used for this class.
     * Objects will be directly built from the database data and only stored in the unit of work.
     * New objects and changes will also never be merged into the session cache.
     * Note that this may lead to poor performance as the session cache is bypassed,
     * however if this class is isolated or pessimistic locked and always accessed in a transaction, this can avoid having to build two copies of the object.
     */
    public void setUnitOfWorkCacheIsolationLevel(int unitOfWorkCacheIsolationLevel) {
        this.unitOfWorkCacheIsolationLevel = unitOfWorkCacheIsolationLevel;
    }

    /**
     * @param fullyMergeEntity the fullyMergeEntity to set
     */
    public void setFullyMergeEntity(boolean fullyMergeEntity) {
        this.fullyMergeEntity = fullyMergeEntity;
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be used by this descriptor.
     * The default is the "FullIdentityMap".
     */
    public void setIdentityMapClass(Class theIdentityMapClass) {
        identityMapClass = theIdentityMapClass;
    }

    /**
     * PUBLIC:
     * Set the size of the identity map to be used by this descriptor.
     * The default is the 100.
     */
    public void setIdentityMapSize(int identityMapSize) {
        this.identityMapSize = identityMapSize;
    }

    /**
     * OBSOLETE:
     * Set the type of cache coordination that will be used on objects of this type.  Possible values
     * are:<ul>
     * <li>SEND_OBJECT_CHANGES
     * <li>INVALIDATE_CHANGED_OBJECTS
     * <li>SEND_NEW_OBJECTS_WITH_CHANGES
     * <li>DO_NOT_SEND_CHANGES</ul>
     * Note: Cache Synchronization type cannot be altered for descriptors that are set as isolated using
     * the setIsIsolated method.<p>
     * This has been replaced by setCacheCoordinationType().
     * @see #setCacheCoordinationType(CacheCoordinationType)
     * @param type int  The synchronization type for this descriptor
     */
    public void setCacheSynchronizationType(int type) {
        // bug 3587273
        if (!isIsolated()) {
            cacheSynchronizationType = type;
        }
    }

    /**
     * PUBLIC:
     * Set the type of cache coordination that will be used on objects of this type.
     * Valid values defined in CacheCoordinationType.
     */
    public void setCacheCoordinationType(CacheCoordinationType type) {
        if (type == null) {
            setCacheSynchronizationType(UNDEFINED_OBJECT_CHANGE_BEHAVIOR);
        } else if (type == CacheCoordinationType.SEND_OBJECT_CHANGES) {
            setCacheSynchronizationType(SEND_OBJECT_CHANGES);
        } else if (type == CacheCoordinationType.INVALIDATE_CHANGED_OBJECTS) {
            setCacheSynchronizationType(INVALIDATE_CHANGED_OBJECTS);
        } else if (type == CacheCoordinationType.SEND_NEW_OBJECTS_WITH_CHANGES) {
            setCacheSynchronizationType(SEND_NEW_OBJECTS_WITH_CHANGES);
        } else if (type == CacheCoordinationType.NONE) {
            setCacheSynchronizationType(DO_NOT_SEND_CHANGES);
        }
    }

    /**
     * PUBLIC:
     * A CacheInterceptor is an adaptor that when overridden and assigned to a Descriptor all interaction
     * between EclipseLink and the internal cache for that class will pass through the Interceptor.
     * Advanced users could use this interceptor to audit, profile or log cache access.  This Interceptor
     * could also be used to redirect or augment the TopLink cache with an alternate cache mechanism.
     * EclipseLink's configurated IdentityMaps will be passed to the Interceptor constructor.

     * As with IdentityMaps an entire class inheritance hierarchy will share the same interceptor.
     * @see org.eclipse.persistence.sessions.interceptors.CacheInterceptor
     */
    public void setCacheInterceptorClass(Class cacheInterceptorClass){
        this.cacheInterceptorClass = cacheInterceptorClass;
    }

    /**
     * PUBLIC:
     * A CacheInterceptor is an adaptor that when overridden and assigned to a Descriptor all interaction
     * between EclipseLink and the internal cache for that class will pass through the Interceptor.
     * Advanced users could use this interceptor to audit, profile or log cache access.  This Interceptor
     * could also be used to redirect or augment the TopLink cache with an alternate cache mechanism.
     * EclipseLink's configurated IdentityMaps will be passed to the Interceptor constructor.

     * As with IdentityMaps an entire class inheritance hierarchy will share the same interceptor.
     * @see org.eclipse.persistence.sessions.interceptors.CacheInterceptor
     */
    public void setCacheInterceptorClassName(String cacheInterceptorClassName){
        this.cacheInterceptorClassName = cacheInterceptorClassName;
    }

    /**
     * PUBLIC:
     * Returns true if the descriptor represents an isolated class
     */
    public boolean isIsolated() {
        return CacheIsolationType.ISOLATED == this.cacheIsolation;
    }

    /**
     * PUBLIC:
     * Returns true if the descriptor represents a protected class.
     */
    public boolean isProtectedIsolation() {
        return CacheIsolationType.PROTECTED ==this.cacheIsolation;
    }

    /**
     * PUBLIC:
     * Returns true if the descriptor represents a shared class.
     */
    public boolean isSharedIsolation() {
        return this.cacheIsolation == null || CacheIsolationType.SHARED == this.cacheIsolation;
    }

    /**
     * INTERNAL:
     * Index the object by index in the cache using its row.
     */
    public void indexObjectInCache(CacheKey cacheKey, AbstractRecord databaseRow, Object domainObject, ClassDescriptor descriptor, AbstractSession session, boolean refresh) {
        if (!hasCacheIndexes()) {
            return;
        }
        for (CacheIndex index : this.cacheIndexes.values()) {
            if (!refresh || index.isUpdateable()) {
                List<DatabaseField> fields = index.getFields();
                int size = fields.size();
                Object[] values = new Object[size];
                for (int count = 0; count < size; count++) {
                    values[count] = databaseRow.get(fields.get(count));
                }
                CacheId indexValues = new CacheId(values);
                session.getIdentityMapAccessorInstance().putCacheKeyByIndex(index, indexValues, cacheKey, descriptor);
            }
        }
    }

    /**
     * INTERNAL:
     * Index the object by index in the cache using the object.
     */
    public void indexObjectInCache(CacheKey cacheKey, Object object, ClassDescriptor descriptor, AbstractSession session, boolean refresh) {
        if (!hasCacheIndexes()) {
            return;
        }
        for (CacheIndex index : this.cacheIndexes.values()) {
            if (!refresh || index.isUpdateable()) {
                List<DatabaseField> fields = index.getFields();
                int size = fields.size();
                Object[] values = new Object[size];
                for (int count = 0; count < size; count++) {
                    values[count] = descriptor.getObjectBuilder().extractValueFromObjectForField(object, fields.get(count), session);
                }
                CacheId indexValues = new CacheId(values);
                session.getIdentityMapAccessorInstance().putCacheKeyByIndex(index, indexValues, cacheKey, descriptor);
            }
        }
    }

    /**
     * INTERNAL:
     * Index the object by index in the cache using its changeSet.
     */
    public void indexObjectInCache(ObjectChangeSet changeSet, Object object, ClassDescriptor descriptor, AbstractSession session) {
        if (!hasCacheIndexes()) {
            return;
        }
        for (CacheIndex index : this.cacheIndexes.values()) {
            if ((changeSet == null) || (changeSet.isNew() && index.isInsertable()) || (!changeSet.isNew() && index.isUpdateable())) {
                List<DatabaseField> fields = index.getFields();
                int size = fields.size();
                Object[] values = new Object[size];
                for (int count = 0; count < size; count++) {
                    values[count] = descriptor.getObjectBuilder().extractValueFromObjectForField(object, fields.get(count), session);
                }
                CacheId indexValues = new CacheId(values);
                CacheKey cacheKey = null;
                Object id = null;
                if (changeSet != null) {
                    cacheKey = changeSet.getActiveCacheKey();
                    if (cacheKey == null) {
                        id = changeSet.getId();
                    }
                } else {
                    id = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, session);
                }
                if (cacheKey == null) {
                    cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyForObject(id, descriptor.getJavaClass(), descriptor, true);
                }
                session.getIdentityMapAccessorInstance().putCacheKeyByIndex(index, indexValues, cacheKey, descriptor);
            }
        }
    }

    /**
     * INTERNAL:
     * Lookup the expression in the cache if it contains any indexes.
     */
    public CacheKey checkCacheByIndex(Expression expression, AbstractRecord translationRow, ClassDescriptor descriptor, AbstractSession session) {
        if (!hasCacheIndexes()) {
            return null;
        }
        AbstractRecord record = descriptor.getObjectBuilder().extractRowFromExpression(expression, translationRow, session);
        if (record == null) {
            return null;
        }
        for (CacheIndex index : this.cacheIndexes.values()) {
            List<DatabaseField> fields = index.getFields();
            int size = fields.size();
            Object[] values = new Object[size];
            for (int count = 0; count < size; count++) {
                Object value = record.get(fields.get(count));
                if (value == null) {
                    break;
                }
                values[count] = value;
            }
            CacheId indexValues = new CacheId(values);
            CacheKey cacheKey = session.getIdentityMapAccessorInstance().getCacheKeyByIndex(index, indexValues, true, descriptor);
            if (cacheKey != null) {
                return cacheKey;
            }
        }
        return null;
    }

    /**
     * INTERNAL:
     * Lookup the expression in the cache if it contains any indexes.
     */
    public boolean isIndexableExpression(Expression expression, ClassDescriptor descriptor, AbstractSession session) {
        if (!hasCacheIndexes()) {
            return false;
        }
        for (CacheIndex index : this.cacheIndexes.values()) {
            List<DatabaseField> searchFields = index.getFields();
            int size = searchFields.size();
            Set<DatabaseField> foundFields = new HashSet(size);
            boolean isValid = expression.extractFields(true, false, descriptor, searchFields, foundFields);
            if (isValid && (foundFields.size() == size)) {
                return true;
            }
        }
        return false;
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the full identity map.
     * This map caches all instances read and grows to accomodate them.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useFullIdentityMap() {
        setIdentityMapClass(ClassConstants.FullIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the hard cache weak identity map.
     * This map uses weak references to only cache object in-memory.
     * It also includes a secondary fixed sized hard cache to improve caching performance.
     * This is provided because some Java VM's implement soft references differently.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useHardCacheWeakIdentityMap() {
        setIdentityMapClass(ClassConstants.HardCacheWeakIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the soft identity map.
     * This map uses soft references to only cache all object in-memory, until memory is low.
     * Note that "low" is interpreted differently by different JVM's.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useSoftIdentityMap() {
        setIdentityMapClass(ClassConstants.SoftIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the no identity map.
     * This map does no caching.
     * Note: This map does not maintain object identity.
     * In general if caching is not desired a WeakIdentityMap should be used with an isolated descriptor.
     * The default is the "SoftCacheWeakIdentityMap".
     * @see ClassDescriptor#setCacheIsolation(CacheIsolationType)
     */
    public void useNoIdentityMap() {
        setIdentityMapClass(ClassConstants.NoIdentityMap_Class);
    }

    /**
     * PUBLIC:
     * Set the class of identity map to be the weak identity map.
     * The default is the "SoftCacheWeakIdentityMap".
     */
    public void useWeakIdentityMap() {
        setIdentityMapClass(ClassConstants.WeakIdentityMap_Class);
    }

    public void setPrefetchCacheKeys(boolean prefetchCacheKeys) {
        this.prefetchCacheKeys = prefetchCacheKeys;
    }

    public boolean shouldPrefetchCacheKeys() {
        return this.prefetchCacheKeys ;
    }
}
