/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2018 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:
//     06/16/2009-2.0 Guy Pelletier
//       - 277039: JPA 2.0 Cache Usage Settings
//     07/16/2009-2.0 Guy Pelletier
//       - 277039: JPA 2.0 Cache Usage Settings
//     06/09/2010-2.0.3 Guy Pelletier
//       - 313401: shared-cache-mode defaults to NONE when the element value is unrecognized
//     06/19/2014-2.6: - Tomas Kraus (Oracle)
//       - 437578: Tests to verify @Cacheable inheritance in JPA 2.1
//     12/03/2015-2.6 Dalia Abo Sheasha
//       - 483582: Add the jakarta.persistence.sharedCache.mode property
package org.eclipse.persistence.testing.tests.jpa.cacheable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jakarta.persistence.Cache;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.Cacheable;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.Query;

import junit.framework.*;

import org.eclipse.persistence.config.CacheUsage;
import org.eclipse.persistence.config.EntityManagerProperties;
import org.eclipse.persistence.config.HintValues;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.config.QueryHints;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.indirection.IndirectList;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.eclipse.persistence.testing.framework.QuerySQLTracker;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCaseHelper;
import org.eclipse.persistence.testing.models.jpa.cacheable.CacheableFalseDetail;
import org.eclipse.persistence.testing.models.jpa.cacheable.CacheableFalseDetailWithBackPointer;
import org.eclipse.persistence.testing.models.jpa.cacheable.CacheableFalseEntity;
import org.eclipse.persistence.testing.models.jpa.cacheable.CacheableForceProtectedEntity;
import org.eclipse.persistence.testing.models.jpa.cacheable.CacheableProtectedEntity;
import org.eclipse.persistence.testing.models.jpa.cacheable.CacheableTableCreator;
import org.eclipse.persistence.testing.models.jpa.cacheable.CacheableTrueDerivedIDEntity;
import org.eclipse.persistence.testing.models.jpa.cacheable.CacheableTrueDerivedIDPK;
import org.eclipse.persistence.testing.models.jpa.cacheable.CacheableTrueEntity;
import org.eclipse.persistence.testing.models.jpa.cacheable.ChildCacheableFalseEntity;
import org.eclipse.persistence.testing.models.jpa.cacheable.ForceProtectedEntityWithComposite;
import org.eclipse.persistence.testing.models.jpa.cacheable.ProductFalse;
import org.eclipse.persistence.testing.models.jpa.cacheable.ProductHardwareFalse;
import org.eclipse.persistence.testing.models.jpa.cacheable.ProductHardwareTrue;
import org.eclipse.persistence.testing.models.jpa.cacheable.ProductSoftwareFalse;
import org.eclipse.persistence.testing.models.jpa.cacheable.ProductSoftwareTrue;
import org.eclipse.persistence.testing.models.jpa.cacheable.ProductTrue;
import org.eclipse.persistence.testing.models.jpa.cacheable.ProtectedEmbeddable;
import org.eclipse.persistence.testing.models.jpa.cacheable.ProtectedRelationshipsEntity;
import org.eclipse.persistence.testing.models.jpa.cacheable.SharedEmbeddable;
import org.eclipse.persistence.testing.models.jpa.cacheable.CacheableRelationshipsEntity;

/*
 * By default the tests in this suite assume the "DISABLE_SELECTIVE" persistence
 * unit.
 *
 * If you want to test against a different PU be sure to ask for it accordingly.
 *
 * The list of Cacheable PU's available are:
 * "NONE"
 * "ALL"
 * "ENABLE_SELECTIVE"
 * "DISABLE_SELECTIVE"
 * "UNSPECIFIED"
 */
public class CacheableModelJunitTest extends JUnitTestCase {
    protected static int m_cacheableTrueEntity1Id;
    protected static int m_cacheableForceProtectedEntity1Id;
    protected static int m_cacheableTrueEntity2Id;
    protected static int m_childCacheableFalseEntityId;
    protected static int m_cacheableProtectedEntityId;
    protected static int m_forcedProtectedEntityCompositId;
    protected static int m_cacheableRelationshipsEntityId;

    public CacheableModelJunitTest() {
        super();
    }

    public CacheableModelJunitTest(String name) {
        super(name);
    }

    /**
     * Convenience method. Default PU is DISABLE_SELETIVE
     */
    public void clearDSCache() {
        clearCache("DISABLE_SELECTIVE");
    }

    /**
     * Convenience method.
     */
    public void closeEM(EntityManager em) {
        if (em.isOpen()) {
            closeEntityManager(em);
        }
    }

    /**
     * Convenience method.
     */
    public EntityManager createDSEntityManager() {
        return createEntityManager("DISABLE_SELECTIVE");
    }

    /**
     * Convenience method - Executes a straight up find on the EM provided or
     * a new one.
     */
    protected CacheableTrueEntity findCacheableTrueEntity(EntityManager em, int id) {
        if (em == null) {
            EntityManager myEm = createDSEntityManager();
            CacheableTrueEntity entity = myEm.find(CacheableTrueEntity.class, id);
            closeEM(myEm);
            return entity;
        } else {
            return em.find(CacheableTrueEntity.class, id);
        }
    }

    /**
     * Convenience method - Executes the select query using retrieve BYPASS
     * and store BYPASS on a new entity manager or the one provided.
     */
    protected CacheableTrueEntity findCacheableTrueEntity_BYPASS_BYPASS(EntityManager em, int id) {
        return findCacheableTrueEntityUsingQuery(em, "findCacheableTrueEntityByPK_BYPASS_BYPASS", id);
    }

    /**
     * Convenience method - Executes the select query using retrieve BYPASS
     * and store USE on a new entity manager or the one provided.
     */
    protected CacheableTrueEntity findCacheableTrueEntity_BYPASS_USE(EntityManager em, int id) {
        return findCacheableTrueEntityUsingQuery(em, "findCacheableTrueEntityByPK_RETRIEVE_BYPASS_STORE_USE", id);
    }

    /**
     * Convenience method - Executes the select query using retrieve USE
     * and store BYPASS on a new entity manager or the one provided.
     */
    protected CacheableTrueEntity findCacheableTrueEntity_USE_BYPASS(EntityManager em, int id) {
        return findCacheableTrueEntityUsingQuery(em, "findCacheableTrueEntityByPK_RETRIEVE_USE_STORE_BYPASS", id);
    }

    /**
     * Convenience method - Executes the select query on a new entity manager
     * or the one provided.
     */
    protected CacheableTrueEntity findCacheableTrueEntityUsingQuery(EntityManager em, String query, int id) {
        CacheableTrueEntity entity = null;

        EntityManager emToUse;
        if (em == null) {
            // Create a new EM ...
            emToUse = createDSEntityManager();
        } else {
            // Use the em provided but do not close it.
            emToUse = em;
        }

        try {
            boolean commit = false;
            if (!isTransactionActive(emToUse)) {
                beginTransaction(emToUse);
                commit = true;
            }
            entity = (CacheableTrueEntity) emToUse.createNamedQuery(query).setParameter("id", id).getSingleResult();
            if (commit) {
                commitTransaction(emToUse);
            }
        }  catch (Exception e) {
            fail("Error executing query: " + e);
        } finally {
            if (em == null) {
                closeEM(emToUse);
            }
        }

        return entity;
    }

    /**
     * Convenience method.
     */
    public ServerSession getDSServerSession() {
        return getPUServerSession("DISABLE_SELECTIVE");
    }

    /**
     * Convenience method.
     */
    public ServerSession getPUServerSession(String puName) {
        return JUnitTestCase.getServerSession(puName);
    }

    /**
     * Convenience method.
     */
    public ServerSession getPUServerSession(String puName, Map properties) {
        return JUnitTestCase.getServerSession(puName, properties);
    }

    @Override
    public void setUp() {
        clearDSCache();
    }

    public static Test suite() {
        TestSuite suite = new TestSuite();
        suite.setName("CacheableModelJunitTest");

        if (! JUnitTestCase.isJPA10()) {
            suite.addTest(new CacheableModelJunitTest("testSetup"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnALL"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnALLProperty"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnNONE"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnNONEProperty"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnNONEPropertyEMF"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnNONEPropertyConflict"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnENABLE_SELECTIVE"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnENABLE_SELECTIVEProperty"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnDISABLE_SELECTIVE"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnDISABLE_SELECTIVEProperty"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnUNSPECIFIED"));
            suite.addTest(new CacheableModelJunitTest("testCachingOnUNSPECIFIEDProperty"));

            // Test cache retrieve mode of BYPASS and USE through the EM.
            suite.addTest(new CacheableModelJunitTest("testCreateEntities"));

            suite.addTest(new CacheableModelJunitTest("testFindWithEMProperties"));
            suite.addTest(new CacheableModelJunitTest("testFindWithFindProperties"));

            suite.addTest(new CacheableModelJunitTest("testRefreshWithEMProperties"));
            suite.addTest(new CacheableModelJunitTest("testRefreshWithRefreshProperties"));

            // Test various usage scenarios ..
            suite.addTest(new CacheableModelJunitTest("testRetrieveBYPASSStoreUSE1"));
            suite.addTest(new CacheableModelJunitTest("testRetrieveBYPASSStoreUSE2"));
            suite.addTest(new CacheableModelJunitTest("testRetrieveUSEStoreBYPASS1"));
            suite.addTest(new CacheableModelJunitTest("testRetrieveUSEStoreBYPASS2"));
            suite.addTest(new CacheableModelJunitTest("testRetrieveBYPASSStoreBYPASS1"));
            suite.addTest(new CacheableModelJunitTest("testRetrieveBYPASSStoreBYPASS2"));
            suite.addTest(new CacheableModelJunitTest("testMultipleEMQueries"));
            suite.addTest(new CacheableModelJunitTest("testEMPropertiesOnCommit1"));
            suite.addTest(new CacheableModelJunitTest("testEMPropertiesOnCommit2"));
            suite.addTest(new CacheableModelJunitTest("testInheritanceCacheable"));

            suite.addTest(new CacheableModelJunitTest("testDetailsOrder_Isolated"));
            suite.addTest(new CacheableModelJunitTest("testDetailsOrder_Isolated_BeginEarlyTransaction"));
            suite.addTest(new CacheableModelJunitTest("testDetailsOrder_Shared"));
            suite.addTest(new CacheableModelJunitTest("testDetailsOrder_Shared_BeginEarlyTransaction"));
            suite.addTest(new CacheableModelJunitTest("testLoadMixedCacheTree"));
            suite.addTest(new CacheableModelJunitTest("testIsolatedIsolation"));
            suite.addTest(new CacheableModelJunitTest("testProtectedIsolation"));
            suite.addTest(new CacheableModelJunitTest("testProtectedCaching"));
            suite.addTest(new CacheableModelJunitTest("testProtectedIsolationWithLockOnCloneFalse"));
            suite.addTest(new CacheableModelJunitTest("testReadOnlyTree"));

            suite.addTest(new CacheableModelJunitTest("testUpdateForceProtectedBasic"));
            suite.addTest(new CacheableModelJunitTest("testUpdateForceProtectedOneToOne"));
            suite.addTest(new CacheableModelJunitTest("testUpdateProtectedBasic"));
            suite.addTest(new CacheableModelJunitTest("testUpdateProtectedOneToMany"));

            suite.addTest(new CacheableModelJunitTest("testProtectedRelationshipsMetadata"));
            suite.addTest(new CacheableModelJunitTest("testForceProtectedFromEmbeddable"));
            suite.addTest(new CacheableModelJunitTest("testEmbeddableProtectedCaching"));
            suite.addTest(new CacheableModelJunitTest("testEmbeddableProtectedReadOnly"));
            suite.addTest(new CacheableModelJunitTest("testUpdateProtectedManyToOne"));
            suite.addTest(new CacheableModelJunitTest("testUpdateProtectedManyToMany"));
            suite.addTest(new CacheableModelJunitTest("testUpdateProtectedElementCollection"));
            suite.addTest(new CacheableModelJunitTest("testIsolationBeforeEarlyTxBegin"));
            suite.addTest(new CacheableModelJunitTest("testForeignKeyUpdateInNonCachedOnMergeNewObject"));

            // Bug 340074
            suite.addTest(new CacheableModelJunitTest("testFindWithLegacyFindProperties"));
            suite.addTest(new CacheableModelJunitTest("testFindWithEMLegacyProperties"));
            suite.addTest(new CacheableModelJunitTest("testMergeNonCachedWithRelationship"));
            suite.addTest(new CacheableModelJunitTest("testIndirectCollectionRefreshBehavior"));
            suite.addTest(new CacheableModelJunitTest("testDerivedIDProtectedRead"));

            // Bug 408262
            suite.addTest(new CacheableModelJunitTest("testRefreshProtectedEntityInEarlyTransaction"));

            // Bug 530680
            suite.addTest(new CacheableModelJunitTest("testUpdateSharedElementCollection"));
        }
        return suite;
    }

    /**
     * The setup is done as a test, both to record its failure, and to allow execution in the server.
     */
    public void testSetup() {
        new CacheableTableCreator().replaceTables(JUnitTestCase.getServerSession());
        clearDSCache();
    }

    /**
     * Test EM properties on commit.
     */
    public void testEMPropertiesOnCommit1() {
        EntityManager em1 = createDSEntityManager();

        // Find the entity and put it in the cache ..
        CacheableTrueEntity cachedEntity = findCacheableTrueEntity(em1, m_cacheableTrueEntity1Id);
        String staleName = cachedEntity.getName();

        // Create  a new Entity to delete
        beginTransaction(em1);
        CacheableTrueEntity entityToDelete = new CacheableTrueEntity();
        entityToDelete.setName("entityToDelete");
        em1.persist(entityToDelete);
        int entityToDeleteId = entityToDelete.getId();
        commitTransaction(em1);

        beginTransaction(em1);
        // No need to clear the EM, just set the new property to BYPASS.
        em1.setProperty(QueryHints.CACHE_STORE_MODE, CacheStoreMode.BYPASS);
        CacheableTrueEntity entity = findCacheableTrueEntity(em1, m_cacheableTrueEntity1Id);
        String updatedName = "testEMPropertiesOnCommit1";
        entity.setName(updatedName);

        CacheableTrueEntity deletedEntity1 = findCacheableTrueEntity(em1, entityToDeleteId);
        em1.remove(deletedEntity1);
        commitTransaction(em1);
        closeEM(em1);

        EntityManager em2 = createDSEntityManager();
        beginTransaction(em2);
        try {
            CacheableTrueEntity entity2 = findCacheableTrueEntity_USE_BYPASS(em2, m_cacheableTrueEntity1Id);
            assertTrue("The shared cache was updated when the EM property CacheStoreMode = BYPASS", entity2.getName().equals(staleName));

            em2.refresh(entity2);
            assertTrue("The entity was not refreshed with the updated name.", entity2.getName().equals(updatedName));

            HashMap props = new HashMap();
            props.put(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.USE);
            props.put(QueryHints.CACHE_STORE_MODE, CacheStoreMode.BYPASS);
            CacheableTrueEntity deletedEntity2 = em2.find(CacheableTrueEntity.class, entityToDeleteId, props);
            assertTrue("The deleted entity was removed from the cache", deletedEntity2 == null);

            deletedEntity2 = em2.find(CacheableTrueEntity.class, entityToDeleteId);
            assertTrue("The deleted entity was removed from the database", deletedEntity2 == null);
        } finally {
            closeEntityManagerAndTransaction(em2);
        }
    }

    /**
     * Test EM properties on commit.
     */
    public void testEMPropertiesOnCommit2() {
        EntityManager em1 = createDSEntityManager();

        // Find the entities and put them in the shared cache ...
        CacheableTrueEntity cachedEntity1 = findCacheableTrueEntity(em1, m_cacheableTrueEntity1Id);
        CacheableTrueEntity cachedEntity2 = findCacheableTrueEntity(em1, m_cacheableTrueEntity2Id);
        String staleName = cachedEntity2.getName();

        String updatedName = "testEMPropertiesOnCommit2";

        beginTransaction(em1);
        // No need to clear the EM, just set the new property to BYPASS.
        em1.setProperty(QueryHints.CACHE_STORE_MODE, CacheStoreMode.BYPASS);
        // Update entity1 through a query that uses cache store mode USE.
        Query query = em1.createQuery("UPDATE JPA_CACHEABLE_TRUE e SET e.name = :name " + "WHERE e.id = :id ").setParameter("name", updatedName).setParameter("id", m_cacheableTrueEntity1Id);
        query.setHint(QueryHints.CACHE_STORE_MODE, CacheStoreMode.USE);
        query.executeUpdate();

        // Update entity2 manually.
        CacheableTrueEntity entity2 = findCacheableTrueEntity(em1, m_cacheableTrueEntity2Id);
        entity2.setName(updatedName);
        commitTransaction(em1);
        closeEM(em1);

        // Verify the cache in a separate entity manager.
        EntityManager em2 = createDSEntityManager();
        beginTransaction(em2);
        try {
            CacheableTrueEntity entity21 = findCacheableTrueEntity_USE_BYPASS(em2, m_cacheableTrueEntity1Id);
            assertTrue("The shared cache should have been updated", entity21.getName().equals(updatedName));

            CacheableTrueEntity entity22 = findCacheableTrueEntity_USE_BYPASS(em2, m_cacheableTrueEntity2Id);
            assertTrue("The shared cache should NOT have been updated", entity22.getName().equals(staleName));

            em2.refresh(entity22);
            assertTrue("The entity was not refreshed with the updated name.", entity22.getName().equals(updatedName));
        } finally {
            closeEntityManagerAndTransaction(em2);
        }
    }

    /**
     * Test find using entity manager properties
     */
    public void testFindWithEMProperties() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            EntityManager em = createDSEntityManager();

            // Put the entity in the UOW and shared cache.
            CacheableTrueEntity cachedEntity = findCacheableTrueEntity(em, m_cacheableTrueEntity1Id);

            // Update the entity name in the shared cash through a different EM.
            updateCacheableTrueEntityNameInSharedCache("testCacheRetrieveModeBypassOnFindThroughEMProperties");

            // This should pick up the entity from the shared cache
            EntityManager em2 = createDSEntityManager();
            CacheableTrueEntity cachedEntity2 = em2.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);
            assertTrue("The shared cache was not updated.", cachedEntity2.getName().equals("testCacheRetrieveModeBypassOnFindThroughEMProperties"));
            closeEM(em2);

            // This setting should be ignored on a refresh operation ...
            em.setProperty(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.USE);

            // Set the refresh property.
            em.setProperty(QueryHints.CACHE_STORE_MODE, CacheStoreMode.REFRESH);

            // Re-issue the find on the original EM.
            CacheableTrueEntity entity = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);
            assertTrue("CacheableTrueEntity should have been refreshed.", entity.getName().equals("testCacheRetrieveModeBypassOnFindThroughEMProperties"));
            assertTrue("CacheableTrueEntity from UOW should have been refreshed.", cachedEntity.getName().equals(entity.getName()));
            assertTrue("Entity returned should be the same instance from the UOW cache", cachedEntity == entity);

            closeEM(em);
        }
    }

    /**
     * Test find using entity manager properties (legacy)
     */
    public void testFindWithEMLegacyProperties() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            EntityManager em = createDSEntityManager();

            // Put the entity in the UOW and shared cache.
            CacheableTrueEntity cachedEntity = findCacheableTrueEntity(em, m_cacheableTrueEntity1Id);

            // Update the entity name in the shared cash through a different EM.
            updateCacheableTrueEntityNameInSharedCache("testCacheRetrieveModeBypassOnFindThroughEMProperties");

            // This should pick up the entity from the shared cache
            EntityManager em2 = createDSEntityManager();
            CacheableTrueEntity cachedEntity2 = em2.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);
            assertTrue("The shared cache was not updated.", cachedEntity2.getName().equals("testCacheRetrieveModeBypassOnFindThroughEMProperties"));
            closeEM(em2);

            // This setting should be ignored on a refresh operation ...
            em.setProperty("jakarta.persistence.cacheRetrieveMode", CacheRetrieveMode.USE); // legacy property

            // Set the refresh property.
            em.setProperty("jakarta.persistence.cacheStoreMode", CacheStoreMode.REFRESH); // legacy property

            // Re-issue the find on the original EM.
            CacheableTrueEntity entity = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);
            assertTrue("CacheableTrueEntity should have been refreshed.", entity.getName().equals("testCacheRetrieveModeBypassOnFindThroughEMProperties"));
            assertTrue("CacheableTrueEntity from UOW should have been refreshed.", cachedEntity.getName().equals(entity.getName()));
            assertTrue("Entity returned should be the same instance from the UOW cache", cachedEntity == entity);

            closeEM(em);
        }
    }

    /**
     * Test find using find properties
     */
    public void testFindWithFindProperties() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            EntityManager em = createDSEntityManager();

            // Put the entity in the UOW and shared cache.
            CacheableTrueEntity cachedEntity = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);

            // Update the entity name, but BYPASS updating the shared cache through a different EM.
            updateCacheableTrueEntityNameAndBypassStore("testCacheRetrieveModeBypassOnFindThroughFindProperties");

            // This should pick up the entity from the shared cache (which should not of been updated
            EntityManager em2 = createDSEntityManager();
            CacheableTrueEntity cachedEntity2 = em2.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);
            assertFalse("The shared cache was updated.", cachedEntity2.getName().equals("testCacheRetrieveModeBypassOnFindThroughFindProperties"));
            closeEM(em2);

            // This setting should be ignored on a refresh operation ...
            em.setProperty(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.USE);

            // Set the refresh property.
            HashMap properties = new HashMap();
            properties.put(QueryHints.CACHE_STORE_MODE, CacheStoreMode.REFRESH);

            // Re-issue the find on the original EM.
            CacheableTrueEntity entity = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id, properties);
            assertTrue("CacheableTrueEntity should have been refreshed.", entity.getName().equals("testCacheRetrieveModeBypassOnFindThroughFindProperties"));
            assertTrue("CacheableTrueEntity from UOW should have been refreshed.", cachedEntity.getName().equals(entity.getName()));
            assertTrue("Entity returned should be the same instance from the UOW cache", cachedEntity == entity);

            closeEM(em);
        }
    }

    /**
     * Test find using find properties (legacy)
     */
    public void testFindWithLegacyFindProperties() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            EntityManager em = createDSEntityManager();

            // Put the entity in the UOW and shared cache.
            CacheableTrueEntity cachedEntity = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);

            // Update the entity name, but BYPASS updating the shared cache through a different EM.
            updateCacheableTrueEntityNameAndBypassStore("testCacheRetrieveModeBypassOnFindThroughFindProperties");

            // This should pick up the entity from the shared cache (which should not of been updated
            EntityManager em2 = createDSEntityManager();
            CacheableTrueEntity cachedEntity2 = em2.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);
            assertFalse("The shared cache was updated.", cachedEntity2.getName().equals("testCacheRetrieveModeBypassOnFindThroughFindProperties"));
            closeEM(em2);

            // This setting should be ignored on a refresh operation ...
            em.setProperty("jakarta.persistence.cacheRetrieveMode", CacheRetrieveMode.USE);

            // Set the refresh property.
            HashMap properties = new HashMap();
            properties.put("jakarta.persistence.cacheStoreMode", CacheStoreMode.REFRESH);

            // Re-issue the find on the original EM.
            CacheableTrueEntity entity = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id, properties);
            assertTrue("CacheableTrueEntity should have been refreshed.", entity.getName().equals("testCacheRetrieveModeBypassOnFindThroughFindProperties"));
            assertTrue("CacheableTrueEntity from UOW should have been refreshed.", cachedEntity.getName().equals(entity.getName()));
            assertTrue("Entity returned should be the same instance from the UOW cache", cachedEntity == entity);

            closeEM(em);
        }
    }

    /**
     * Test refresh using EM properties
     */
    public void testRefreshWithEMProperties() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            // This will put the entity in the cache.
            EntityManager em = createDSEntityManager();
            CacheableTrueEntity cachedEntity = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);
            // Update the database manually through a different EM
            String updatedName = "testRefreshWithEMProperties";
            updateCacheableTrueEntityNameInSharedCache(updatedName);

            // This setting should be ignored on a refresh operation ...
            em.setProperty(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.USE);
            beginTransaction(em);
            try{
                cachedEntity = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);
                em.refresh(cachedEntity);
                commitTransaction(em);
            }catch(Exception ex){
                ex.printStackTrace();
                if (isTransactionActive(em)) {
                    rollbackTransaction(em);
                }
            }finally{
                closeEM(em);
            }
            assertTrue("CacheableTrueEntity should have been refreshed.", cachedEntity.getName().equals(updatedName));
        }

    }

    /**
     * Test refresh using refresh properties.
     */
    public void testRefreshWithRefreshProperties() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            // This will put the entity in the cache.
            EntityManager em = createDSEntityManager();
            CacheableTrueEntity cachedEntity = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);

            // Update the database manually through a different EM
            String updatedName = "testRefreshWithRefreshProperties";
            updateCacheableTrueEntityNameInSharedCache(updatedName);

            HashMap properties = new HashMap();
            // This setting should be ignored on a refresh operation ...
            properties.put(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.USE);
            beginTransaction(em);
            try{
                cachedEntity = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);
                em.refresh(cachedEntity, properties);
                commitTransaction(em);
            }catch(Exception ex){
                if (isTransactionActive(em)) {
                    rollbackTransaction(em);
                }
            }finally{
                closeEM(em);
            }
            assertTrue("CacheableTrueEntity should have been refreshed.", cachedEntity.getName().equals(updatedName));
        }
    }

    /**
     * Test: Using named query (when updated object in shared cache)
     * CacheRetrieveMode = BYPASS
     * CacheStoreMode = BYPASS
     */
    public void testRetrieveBYPASSStoreBYPASS1() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            // Put the entity in the EM UOW and shared cache.
            EntityManager em = createDSEntityManager();
            CacheableTrueEntity cachedEntity = findCacheableTrueEntity(em, m_cacheableTrueEntity1Id);

            // Update the entity name in the shared cache through a different EM.
            String updatedName = "testRetrieveBYPASSStoreBYPASS1";
            updateCacheableTrueEntityNameInSharedCache(updatedName);

            // Execute find by pk query using Retrieve BYPASS, Store BYPASS on EM.
            // It should return the same entity.
            CacheableTrueEntity entity1 = findCacheableTrueEntity_BYPASS_BYPASS(em, m_cacheableTrueEntity1Id);
            assertTrue("The entity instances must be the same", entity1 == cachedEntity);
            assertTrue("The name should not of been refreshed", entity1.getName().equals(cachedEntity.getName()));

            // Issue a find using refresh on EM, should pick up the updated name.
            HashMap properties = new HashMap();
            properties.put(QueryHints.CACHE_STORE_MODE, CacheStoreMode.REFRESH);
            CacheableTrueEntity entity1b = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id, properties);
            assertTrue("CacheableTrueEntity should of been refreshed.", entity1b.getName().equals(updatedName));
            closeEM(em);

            // On a different EM execute a find by pk using Retrieve BYPASS,
            // Store BYPASS, we should get the updated name.
            CacheableTrueEntity entity2 = findCacheableTrueEntity_BYPASS_BYPASS(null, m_cacheableTrueEntity1Id);
            assertTrue("CacheableTrueEntity should have been refreshed.", entity2.getName().equals(updatedName));
        }
    }

    /**
     * Test: Using named query  (when updated object NOT in shared cache)
     * CacheRetrieveMode = BYPASS
     * CacheStoreMode = BYPASS
     */
    public void testRetrieveBYPASSStoreBYPASS2() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            // Put the entity in the EM UOW and shared cache.
            EntityManager em = createDSEntityManager();
            CacheableTrueEntity cachedEntity = findCacheableTrueEntity(em, m_cacheableTrueEntity1Id);

            // Update the entity name in the shared cache through a different EM.
            String updatedName = "testRetrieveBYPASSStoreBYPASS2";
            updateCacheableTrueEntityNameAndBypassStore(updatedName);

            // Execute find by pk query using Retrieve BYPASS, Store BYPASS on EM.
            // It should return the same entity.
            CacheableTrueEntity entity1a = findCacheableTrueEntity_BYPASS_BYPASS(em, m_cacheableTrueEntity1Id);
            assertTrue("The entity returned should match the cached instance", entity1a == cachedEntity);
            assertTrue("CacheableTrueEntity should have been refreshed.", entity1a.getName().equals(cachedEntity.getName()));

            // On a different EM issue a find (using internal EclipseLink defaults)
            CacheableTrueEntity entity2 = findCacheableTrueEntity(null, m_cacheableTrueEntity1Id);
            assertTrue("CacheableTrueEntity should not of been refreshed.", entity2.getName().equals(entity1a.getName()));

            // Issue a find on EM1 using REFRESH.
            HashMap properties = new HashMap();
            properties.put(QueryHints.CACHE_STORE_MODE, CacheStoreMode.REFRESH);
            CacheableTrueEntity entity1b = em.find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id, properties);
            assertTrue("CacheableTrueEntity should be from the shared cache.", entity1b.getName().equals(updatedName));

            closeEM(em);
        }
    }

    /**
     * Test: Named query using retrieve BYPASS and store USE (when updated object in shared cache).
     */
    public void testRetrieveBYPASSStoreUSE1() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            // Put the entity in the EM UOW and shared cache.
            EntityManager em = createDSEntityManager();
            CacheableTrueEntity cachedEntity = findCacheableTrueEntity(em, m_cacheableTrueEntity1Id);

            // Update the entity name in the shared cache through a different EM.
            String updatedName = "testRetrieveBYPASSStoreUSE1";
            updateCacheableTrueEntityNameInSharedCache(updatedName);

            // Execute find by pk query using Retrieve BYPASS, Store USE on EM.
            // It should return the same entity.
            CacheableTrueEntity entity1 = findCacheableTrueEntity_BYPASS_USE(em, m_cacheableTrueEntity1Id);
            assertTrue("The entity instances must be the same", entity1 == cachedEntity);
            assertTrue("The name should not of been refreshed", entity1.getName().equals(cachedEntity.getName()));

            // Execute find by pk query using Retrieve USE, Store BYPASS on a
            // different EM. The entity returned should have been read from the
            // shared cache with the updated name.
            CacheableTrueEntity entity2 = findCacheableTrueEntity_USE_BYPASS(null, m_cacheableTrueEntity1Id);
            assertTrue("CacheableTrueEntity should have the name from the shared cache.", entity2.getName().equals(updatedName));

            closeEM(em);
        }
    }

    /**
     * Test: Using a named query with BYPASS and USE (when updated object not in shared cache)
     */
    public void testRetrieveBYPASSStoreUSE2() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            // Put the entity in the EM UOW and shared cache.
            EntityManager em = createDSEntityManager();
            CacheableTrueEntity cachedEntity = findCacheableTrueEntity(em, m_cacheableTrueEntity1Id);

            // Update the database manually through a different EM and bypass
            // updating the shared cache.
            String updatedName = "testRetrieveBYPASSStoreUSE2";
            updateCacheableTrueEntityNameAndBypassStore(updatedName);

            // Execute find by pk query using Retrieve BYPASS, Store USE on EM.
            // It should return the same entity. As an optimization in this case,
            // the Store USE will update the shared cache.
            CacheableTrueEntity entity1 = findCacheableTrueEntity_BYPASS_USE(em, m_cacheableTrueEntity1Id);
            assertTrue("The entity instances must be the same", entity1 == cachedEntity);
            assertTrue("The name should not of been refreshed", entity1.getName().equals(cachedEntity.getName()));
            closeEM(em);

            // A find on a new EM should return the value from the shared cache
            // which should have been updated with the Store USE value above
            CacheableTrueEntity entity2 = findCacheableTrueEntity(null, m_cacheableTrueEntity1Id);
            assertTrue("CacheableTrueEntity should have the name from the shared cache.", entity2.getName().equals(updatedName));
        }
    }

    /**
     * Test: Named query using retrieve USE and store BYPASS (when updated object in shared cache).
     */
    public void testRetrieveUSEStoreBYPASS1() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            // Put the entity in the UOW and shared cache for EM1
            EntityManager em = createDSEntityManager();
            CacheableTrueEntity cachedEntity = findCacheableTrueEntity(em, m_cacheableTrueEntity1Id);

            // Update the entity name in the shared cash through a different EM.
            String updatedName = "testRetrieveUSEStoreBYPASS1";
            updateCacheableTrueEntityNameInSharedCache(updatedName);

            // Execute find by pk query using Retrieve USE, Store BYPASS on EM.
            // It should return the same entity.
            CacheableTrueEntity entity1 = findCacheableTrueEntity_USE_BYPASS(em, m_cacheableTrueEntity1Id);
            assertTrue("The entity returned should match the cached instance", entity1 == cachedEntity);
            assertTrue("CacheableTrueEntity should not have been refreshed.", entity1.getName().equals(cachedEntity.getName()));
            closeEM(em);

            // Execute a find by pk query using Retrieve USE, Store BYPASS on a
            // different EM. The entity returned should have been read from the
            // shared cache with the updated name.
            CacheableTrueEntity entity2 = findCacheableTrueEntity_USE_BYPASS(null, m_cacheableTrueEntity1Id);
            assertTrue("CacheableTrueEntity should have the name from the shared cache.", entity2.getName().equals(updatedName));
        }
    }

    /**
     * Test: Named query using retrieve USE and store BYPASS (when updated object NOT in shared cache).
     */
    public void testRetrieveUSEStoreBYPASS2() {
        // Cannot create parallel entity managers in the server.
        if (! isOnServer()) {
            // Put the entity in the UOW and shared cache for EM1
            EntityManager em1 = createDSEntityManager();
            CacheableTrueEntity cachedEntity = findCacheableTrueEntity(em1, m_cacheableTrueEntity1Id);

            // Update the database manually through a different EM and bypass
            // updating the shared cache.
            String updatedName = "testRetrieveUSEStoreBYPASS2";
            updateCacheableTrueEntityNameAndBypassStore(updatedName);

            // Execute find by pk query using Retrieve USE, Store BYPASS on EM.
            // It should return the same entity.
            CacheableTrueEntity entity1 = findCacheableTrueEntity_USE_BYPASS(em1, m_cacheableTrueEntity1Id);
            assertTrue("The entity returned should match the cached instance", entity1 == cachedEntity);
            assertTrue("CacheableTrueEntity should not have been refreshed.", entity1.getName().equals(cachedEntity.getName()));
            closeEM(em1);

            // Issue a find on a different EM. The entity should come from the
            // shared cache and have a stale name.
            EntityManager em2 = createDSEntityManager();
            CacheableTrueEntity entity2 = findCacheableTrueEntity(em2, m_cacheableTrueEntity1Id);
            assertTrue("CacheableTrueEntity should have the name from the shared cache.", entity2.getName().equals(entity1.getName()));

            // Now refresh the entity, should get the updated name.
            em2.refresh(entity2);
            assertTrue("CacheableTrueEntity should have the name from database.", entity2.getName().equals(updatedName));
            closeEM(em2);
        }
    }

    /**
     * Test EM properties on commit.
     */
    public void testInheritanceCacheable() {
        EntityManager em1 = createDSEntityManager();

        beginTransaction(em1);
        CacheableTrueEntity cacheableEntity1 = new CacheableTrueEntity();
        cacheableEntity1.setName("cacheableEntity");
        em1.persist(cacheableEntity1);
        ChildCacheableFalseEntity nonCacheableEntity1 = new ChildCacheableFalseEntity();
        nonCacheableEntity1.setName("nonCacheableEntity");
        em1.persist(nonCacheableEntity1);
        commitTransaction(em1);

        closeEM(em1);

        EntityManager em2 = createDSEntityManager();
        HashMap props = new HashMap();
        props.put(QueryHints.CACHE_USAGE, CacheUsage.CheckCacheOnly);

        CacheableTrueEntity cacheableEntity2 = em2.find(CacheableTrueEntity.class, cacheableEntity1.getId(), props);
        CacheableTrueEntity nonCacheableEntity2a = em2.find(CacheableTrueEntity.class, nonCacheableEntity1.getId(), props);
        ChildCacheableFalseEntity nonCacheableEntity2b = em2.find(ChildCacheableFalseEntity.class, nonCacheableEntity1.getId(), props);

        assertFalse("CacheableTrueEntity was not in the cache", cacheableEntity2 == null);
        assertTrue("ChildCacheableFalseEntity was in the cache", nonCacheableEntity2a == null);
        assertTrue("ChildCacheableFalseEntity was in the cache", nonCacheableEntity2b == null);

        closeEM(em2);
    }

    public void testMultipleEMQueries() {
        // Get the object in the shared cache.
        CacheableTrueEntity cachedEntity = createDSEntityManager().find(CacheableTrueEntity.class, m_cacheableTrueEntity1Id);

        // Update the database manually through a different EM and bypass
        // updating the shared cache.
        String updatedName = "testMultipleEMQueries";
        updateCacheableTrueEntityNameAndBypassStore(updatedName);

        // Execute find by pk query using Retrieve USE, Store BYPASS. The entity
        // returned should have been read from the shared cache with the stale name.
        CacheableTrueEntity entity1 = findCacheableTrueEntity_USE_BYPASS(null, m_cacheableTrueEntity1Id);
        assertFalse("CacheableTrueEntity should not have the updated name.", entity1.getName().equals(updatedName));

        // Execute find by pk query using Retrieve BYPASS, Store USE. The entity
        // returned should have been read from the database and the shared cache
        // should have been updated.
        CacheableTrueEntity entity2 = findCacheableTrueEntity_BYPASS_USE(null, m_cacheableTrueEntity1Id);
        assertTrue("CacheableTrueEntity should have the updated name.", entity2.getName().equals(updatedName));

        // Execute find by pk query using Retrieve USE, Store BYPASS. The entity
        // returned should have been read from the shared cache with the updated name.
        CacheableTrueEntity entity3 = findCacheableTrueEntity_USE_BYPASS(null, m_cacheableTrueEntity1Id);
        assertTrue("CacheableTrueEntity should have the updated name.", entity3.getName().equals(updatedName));
    }

    /**
     * Verifies the cacheable settings when caching (from persistence.xml) is set to ALL using {@code <shared-cache-mode>}.
     */
    public void testCachingOnALL() {
        assertCachingOnALL(getPUServerSession("ALL"));
    }
    
    /**
     * Verifies the cacheable settings when caching (from persistence.xml) is set to ALL using jakarta.persistence.sharedCache.mode property.
     */
    public void testCachingOnALLProperty() {
        assertCachingOnALL(getPUServerSession("ALL-Property"));
    }
    
    public void assertCachingOnALL(ServerSession session) {
        ClassDescriptor falseEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_FALSE");
        assertFalse("CacheableFalseEntity (ALL) from annotations has caching turned off", usesNoCache(falseEntityDescriptor));

        ClassDescriptor trueEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_TRUE");
        assertFalse("CacheableTrueEntity (ALL) from annotations has caching turned off", usesNoCache(trueEntityDescriptor));

        ClassDescriptor protectedEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_PROTECTED");
        assertFalse("CacheableProtectedEntity (ALL) from annotations has caching turned off", usesNoCache(protectedEntityDescriptor));

        ClassDescriptor childFalseEntityDescriptor = session.getDescriptorForAlias("JPA_CHILD_CACHEABLE_FALSE");
        assertFalse("ChildCacheableFalseEntity (ALL) from annotations has caching turned off", usesNoCache(childFalseEntityDescriptor));

        ClassDescriptor falseSubEntityDescriptor = session.getDescriptorForAlias("JPA_SUB_CACHEABLE_FALSE");
        assertFalse("SubCacheableFalseEntity (ALL) from annotations has caching turned off", usesNoCache(falseSubEntityDescriptor));

        // Should pick up true from the mapped superclass.
        ClassDescriptor noneSubEntityDescriptor = session.getDescriptorForAlias("JPA_SUB_CACHEABLE_NONE");
        assertFalse("SubCacheableNoneEntity (ALL) from annotations has caching turned off", usesNoCache(noneSubEntityDescriptor));

        ClassDescriptor xmlFalseEntityDescriptor = session.getDescriptorForAlias("XML_CACHEABLE_FALSE");
        assertFalse("CacheableFalseEntity (ALL) from XML has caching turned off", usesNoCache(xmlFalseEntityDescriptor));

        ClassDescriptor xmlTrueEntityDescriptor = session.getDescriptorForAlias("XML_CACHEABLE_TRUE");
        assertFalse("CacheableTrueEntity (ALL) from XML has caching turned ff", usesNoCache(xmlTrueEntityDescriptor));

        ClassDescriptor xmlFalseSubEntityDescriptor = session.getDescriptorForAlias("XML_SUB_CACHEABLE_FALSE");
        assertFalse("SubCacheableFalseEntity (ALL) from XML has caching turned off", usesNoCache(xmlFalseSubEntityDescriptor));

        // Should pick up true from the mapped superclass.
        ClassDescriptor xmlNoneSubEntityDescriptor = session.getDescriptorForAlias("XML_SUB_CACHEABLE_NONE");
        assertFalse("SubCacheableTrueEntity (ALL) from XML has caching turned off", usesNoCache(xmlNoneSubEntityDescriptor));
    }

    /**
     * Verifies the cacheable settings when caching (from persistence.xml) is set to NONE using {@code <shared-cache-mode>}.
     */
    public void testCachingOnNONE() {
        assertCachingOnNONE(getPUServerSession("NONE"));
    }
    
    /**
     * Verifies the cacheable settings when caching (from persistence.xml) is set to NONE using jakarta.persistence.sharedCache.mode property.
     */
    public void testCachingOnNONEProperty() {
        assertCachingOnNONE(getPUServerSession("NONE-Property"));
    }
    
    /**
     * Verifies the cacheable settings when passing the jakarta.persistence.sharedCache.mode property
     * as NONE when creating an EntityManagerFactory.
     */
    public void testCachingOnNONEPropertyEMF() {
        Map<String, String> properties = new HashMap<String, String>();
        properties.putAll(JUnitTestCaseHelper.getDatabaseProperties());
        properties.put(PersistenceUnitProperties.SHARED_CACHE_MODE, "NONE");
        assertCachingOnNONE(getPUServerSession("CacheUnlisted", properties));
    }
    
    /**
     * Verifies that when the {@code <shared-cache-mode>} and jakarta.persistence.sharedCache.mode property
     * are set, the jakarta.persistence.sharedCache.mode property will win. In the persistence.xml,
     * jakarta.persistence.sharedCache.mode property is set to NONE while {@code <shared-cache-mode>} is set to
     * ALL.
     */
    public void testCachingOnNONEPropertyConflict() {
        assertCachingOnNONE(getPUServerSession("NONE-Property-Conflict"));
    }
    
    public void assertCachingOnNONE(ServerSession session) {
        ClassDescriptor falseEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_FALSE");
        assertTrue("CacheableFalseEntity (NONE) from annotations has caching turned on", usesNoCache(falseEntityDescriptor));

        ClassDescriptor trueEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_TRUE");
        assertTrue("CacheableTrueEntity (NONE) from annotations has caching turned on", usesNoCache(trueEntityDescriptor));

        ClassDescriptor protectedEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_PROTECTED");
        assertTrue("CacheableProtectedEntity (ALL) from annotations has caching turned off", usesNoCache(protectedEntityDescriptor));

        ClassDescriptor childFalseEntityDescriptor = session.getDescriptorForAlias("JPA_CHILD_CACHEABLE_FALSE");
        assertTrue("ChildCacheableFalseEntity (NONE) from annotations has caching turned on", usesNoCache(childFalseEntityDescriptor));

        ClassDescriptor falseSubEntityDescriptor = session.getDescriptorForAlias("JPA_SUB_CACHEABLE_FALSE");
        assertTrue("SubCacheableFalseEntity (NONE) from annotations has caching turned on", usesNoCache(falseSubEntityDescriptor));

        // Should pick up true from the mapped superclass.
        ClassDescriptor noneSubEntityDescriptor = session.getDescriptorForAlias("JPA_SUB_CACHEABLE_NONE");
        assertTrue("SubCacheableNoneEntity (NONE) from annotations has caching turned on", usesNoCache(noneSubEntityDescriptor));

        ClassDescriptor xmlFalseEntityDescriptor = session.getDescriptorForAlias("XML_CACHEABLE_FALSE");
        assertTrue("CacheableFalseEntity (NONE) from XML has caching turned on", usesNoCache(xmlFalseEntityDescriptor));

        ClassDescriptor xmlTrueEntityDescriptor = session.getDescriptorForAlias("XML_CACHEABLE_TRUE");
        assertTrue("CacheableTrueEntity (NONE) from XML has caching turned on", usesNoCache(xmlTrueEntityDescriptor));

        ClassDescriptor xmlFalseSubEntityDescriptor = session.getDescriptorForAlias("XML_SUB_CACHEABLE_FALSE");
        assertTrue("SubCacheableFalseEntity (NONE) from XML has caching turned on", usesNoCache(xmlFalseSubEntityDescriptor));

        // Should pick up true from the mapped superclass.
        ClassDescriptor xmlNoneSubEntityDescriptor = session.getDescriptorForAlias("XML_SUB_CACHEABLE_NONE");
        assertTrue("SubCacheableTrueEntity (NONE) from XML has caching turned on", usesNoCache(xmlNoneSubEntityDescriptor));
    }

    /**
     * Verifies the cacheable settings when caching (from persistence.xml) is set to ENABLE_SELECTIVE using {@code <shared-cache-mode>}.
     */
    public void testCachingOnENABLE_SELECTIVE() {
        assertCachingOnENABLE_SELECTIVE(getPUServerSession("ENABLE_SELECTIVE"));
    }
    
    /**
     * Verifies the cacheable settings when caching (from persistence.xml) is set to ENABLE_SELECTIVE using jakarta.persistence.sharedCache.mode property.
     */
    public void testCachingOnENABLE_SELECTIVEProperty() {
        assertCachingOnENABLE_SELECTIVE(getPUServerSession("ENABLE_SELECTIVE-Property"));
    }
    
    public void assertCachingOnENABLE_SELECTIVE(ServerSession session) {
        ClassDescriptor falseEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_FALSE");
        assertTrue("CacheableFalseEntity (ENABLE_SELECTIVE) from annotations has caching turned on", usesNoCache(falseEntityDescriptor));

        ClassDescriptor trueEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_TRUE");
        assertFalse("CacheableTrueEntity (ENABLE_SELECTIVE) from annotations has caching turned off", usesNoCache(trueEntityDescriptor));

        ClassDescriptor childFalseEntityDescriptor = session.getDescriptorForAlias("JPA_CHILD_CACHEABLE_FALSE");
        assertTrue("ChildCacheableFalseEntity (ENABLE_SELECTIVE) from annotations has caching turned on", usesNoCache(childFalseEntityDescriptor));

        ClassDescriptor falseSubEntityDescriptor = session.getDescriptorForAlias("JPA_SUB_CACHEABLE_FALSE");
        assertTrue("SubCacheableFalseEntity (ENABLE_SELECTIVE) from annotations has caching turned on", usesNoCache(falseSubEntityDescriptor));

        // Should pick up true from the mapped superclass.
        ClassDescriptor noneSubEntityDescriptor = session.getDescriptorForAlias("JPA_SUB_CACHEABLE_NONE");
        assertFalse("SubCacheableNoneEntity (ENABLE_SELECTIVE) from annotations has caching turned off", usesNoCache(noneSubEntityDescriptor));

        ClassDescriptor xmlFalseEntityDescriptor = session.getDescriptorForAlias("XML_CACHEABLE_FALSE");
        assertTrue("CacheableFalseEntity (ENABLE_SELECTIVE) from XML has caching turned on", usesNoCache(xmlFalseEntityDescriptor));

        ClassDescriptor xmlTrueEntityDescriptor = session.getDescriptorForAlias("XML_CACHEABLE_TRUE");
        assertFalse("CacheableTrueEntity (ENABLE_SELECTIVE) from XML has caching turned off", usesNoCache(xmlTrueEntityDescriptor));

        ClassDescriptor xmlFalseSubEntityDescriptor = session.getDescriptorForAlias("XML_SUB_CACHEABLE_FALSE");
        assertTrue("SubCacheableFalseEntity (ENABLE_SELECTIVE) from XML has caching turned on", usesNoCache(xmlFalseSubEntityDescriptor));

        // Should pick up true from the mapped superclass.
        ClassDescriptor xmlNoneSubEntityDescriptor = session.getDescriptorForAlias("XML_SUB_CACHEABLE_NONE");
        assertFalse("SubCacheableNoneEntity (ENABLE_SELECTIVE) from XML has caching turned off", usesNoCache(xmlNoneSubEntityDescriptor));
    }

    /**
     * Verifies the cacheable settings when caching (from persistence.xml) is set to DISABLE_SELECTIVE using {@code <shared-cache-mode>}.
     */
    public void testCachingOnDISABLE_SELECTIVE() {
        assertCachingOnDISABLE_SELECTIVE(getPUServerSession("DISABLE_SELECTIVE"));
    }
    
    /**
     * Verifies the cacheable settings when caching (from persistence.xml) is set to DISABLE_SELECTIVE using jakarta.persistence.sharedCache.mode property.
     */
    public void testCachingOnDISABLE_SELECTIVEProperty() {
        assertCachingOnDISABLE_SELECTIVE(getPUServerSession("DISABLE_SELECTIVE-Property"));
    }
    
    public void assertCachingOnDISABLE_SELECTIVE(ServerSession session) {
        ClassDescriptor falseEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_FALSE");
        assertTrue("CacheableFalseEntity (DISABLE_SELECTIVE) from annotations has caching turned on", usesNoCache(falseEntityDescriptor));

        ClassDescriptor trueEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_TRUE");
        assertFalse("CacheableTrueEntity (DISABLE_SELECTIVE) from annotations has caching turned off", usesNoCache(trueEntityDescriptor));

        ClassDescriptor childFalseEntityDescriptor = session.getDescriptorForAlias("JPA_CHILD_CACHEABLE_FALSE");
        assertTrue("ChildCacheableFalseEntity (DISABLE_SELECTIVE) from annotations has caching turned on", usesNoCache(childFalseEntityDescriptor));

        ClassDescriptor falseSubEntityDescriptor = session.getDescriptorForAlias("JPA_SUB_CACHEABLE_FALSE");
        assertTrue("SubCacheableFalseEntity (DISABLE_SELECTIVE) from annotations has caching turned on", usesNoCache(falseSubEntityDescriptor));

        // Should pick up true from the mapped superclass.
        ClassDescriptor noneSubEntityDescriptor = session.getDescriptorForAlias("JPA_SUB_CACHEABLE_NONE");
        assertFalse("SubCacheableNoneEntity (DISABLE_SELECTIVE) from annotations has caching turned off", usesNoCache(noneSubEntityDescriptor));

        ClassDescriptor xmlFalseEntityDescriptor = session.getDescriptorForAlias("XML_CACHEABLE_FALSE");
        assertTrue("CacheableFalseEntity (DISABLE_SELECTIVE) from XML has caching turned on", usesNoCache(xmlFalseEntityDescriptor));

        ClassDescriptor xmlTrueEntityDescriptor = session.getDescriptorForAlias("XML_CACHEABLE_TRUE");
        assertFalse("CacheableTrueEntity (DISABLE_SELECTIVE) from XML has caching turned off", usesNoCache(xmlTrueEntityDescriptor));

        ClassDescriptor xmlFalseSubEntityDescriptor = session.getDescriptorForAlias("XML_SUB_CACHEABLE_FALSE");
        assertTrue("SubCacheableFalseEntity (DISABLE_SELECTIVE) from XML has caching turned on", usesNoCache(xmlFalseSubEntityDescriptor));

        // Should pick up true from the mapped superclass.
        ClassDescriptor xmlNoneSubEntityDescriptor = session.getDescriptorForAlias("XML_SUB_CACHEABLE_NONE");
        assertFalse("SubCacheableNoneEntity (DISABLE_SELECTIVE) from XML has caching turned off", usesNoCache(xmlNoneSubEntityDescriptor));
    }

    /**
     * Verifies the cacheable settings when caching (from persistence.xml) is set to UNSPECIFIED using {@code <shared-cache-mode>}.
     */
    public void testCachingOnUNSPECIFIED() {
        assertCachingOnUNSPECIFIED(getPUServerSession("UNSPECIFIED"));
    }
    
    /**
     * Verifies the cacheable settings when caching (from persistence.xml) is set to UNSPECIFIED using jakarta.persistence.sharedCache.mode property.
     */
    public void testCachingOnUNSPECIFIEDProperty() {
        assertCachingOnUNSPECIFIED(getPUServerSession("UNSPECIFIED-Property"));
    }
    
    public void assertCachingOnUNSPECIFIED(ServerSession session) {
        ClassDescriptor falseEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_FALSE");
        assertTrue("CacheableFalseEntity (UNSPECIFIED) from annotations has caching turned on", usesNoCache(falseEntityDescriptor));

        ClassDescriptor trueEntityDescriptor = session.getDescriptorForAlias("JPA_CACHEABLE_TRUE");
        assertFalse("CacheableTrueEntity (UNSPECIFIED) from annotations has caching turned off", usesNoCache(trueEntityDescriptor));

        ClassDescriptor childFalseEntityDescriptor = session.getDescriptorForAlias("JPA_CHILD_CACHEABLE_FALSE");
        assertTrue("ChildCacheableFalseEntity (UNSPECIFIED) from annotations has caching turned on", usesNoCache(childFalseEntityDescriptor));

        ClassDescriptor falseSubEntityDescriptor = session.getDescriptorForAlias("JPA_SUB_CACHEABLE_FALSE");
        assertTrue("SubCacheableFalseEntity (UNSPECIFIED) from annotations has caching turned on", usesNoCache(falseSubEntityDescriptor));

        // Should pick up true from the mapped superclass.
        ClassDescriptor noneSubEntityDescriptor = session.getDescriptorForAlias("JPA_SUB_CACHEABLE_NONE");
        assertFalse("SubCacheableNoneEntity (UNSPECIFIED) from annotations has caching turned off", usesNoCache(noneSubEntityDescriptor));

        ClassDescriptor xmlFalseEntityDescriptor = session.getDescriptorForAlias("XML_CACHEABLE_FALSE");
        assertTrue("CacheableFalseEntity (UNSPECIFIED) from XML has caching turned on", usesNoCache(xmlFalseEntityDescriptor));

        ClassDescriptor xmlTrueEntityDescriptor = session.getDescriptorForAlias("XML_CACHEABLE_TRUE");
        assertFalse("CacheableTrueEntity (UNSPECIFIED) from XML has caching turned off", usesNoCache(xmlTrueEntityDescriptor));

        ClassDescriptor xmlFalseSubEntityDescriptor = session.getDescriptorForAlias("XML_SUB_CACHEABLE_FALSE");
        assertTrue("SubCacheableFalseEntity (UNSPECIFIED) from XML has caching turned on", usesNoCache(xmlFalseSubEntityDescriptor));

        // Should pick up true from the mapped superclass.
        ClassDescriptor xmlNoneSubEntityDescriptor = session.getDescriptorForAlias("XML_SUB_CACHEABLE_NONE");
        assertFalse("SubCacheableNoneEntity (UNSPECIFIED) from XML has caching turned off", usesNoCache(xmlNoneSubEntityDescriptor));
    }

    public void testCreateEntities() {
        EntityManager em = null;

        try {
            if (!isOnServer()) {
                em = createEntityManager("DISABLE_SELECTIVE");
            } else {
                em = createEntityManager("MulitPU-4");
            }
            beginTransaction(em);

            CacheableTrueEntity cacheableTrueEntity = new CacheableTrueEntity();
            cacheableTrueEntity.setName("testCreateEntities");
            em.persist(cacheableTrueEntity);
            m_cacheableTrueEntity1Id = cacheableTrueEntity.getId();

            CacheableForceProtectedEntity cacheableForceProtectedEntity = new CacheableForceProtectedEntity();
            cacheableForceProtectedEntity.setName("testCreateEntities");
            em.persist(cacheableForceProtectedEntity);
            m_cacheableForceProtectedEntity1Id = cacheableForceProtectedEntity.getId();

            CacheableFalseEntity cacheableFalseEntity = new CacheableFalseEntity();
            em.persist(cacheableFalseEntity);

            cacheableForceProtectedEntity.setCacheableFalse(cacheableFalseEntity);

            CacheableProtectedEntity cacheableProtectedEntity = new CacheableProtectedEntity();
            em.persist(cacheableProtectedEntity);
            m_cacheableProtectedEntityId = cacheableProtectedEntity.getId();
            cacheableFalseEntity.setProtectedEntity(cacheableProtectedEntity);

            CacheableTrueEntity cacheableTrueEntity2 = new CacheableTrueEntity();
            cacheableTrueEntity2.setName("testCreateEntities");
            em.persist(cacheableTrueEntity2);
            m_cacheableTrueEntity2Id = cacheableTrueEntity2.getId();

            ChildCacheableFalseEntity childCacheableFalseEntity = new ChildCacheableFalseEntity();
            childCacheableFalseEntity.setName("testCreateEntities");
            em.persist(childCacheableFalseEntity);
            m_childCacheableFalseEntityId = childCacheableFalseEntity.getId();

            ForceProtectedEntityWithComposite fpewc = new ForceProtectedEntityWithComposite();
            fpewc.setName("testCreateEntities");
            ProtectedEmbeddable pe = new ProtectedEmbeddable();
            fpewc.setProtectedEmbeddable(pe);
            CacheableFalseEntity cfe = new CacheableFalseEntity();
            pe.setCacheableFalseEntity(cfe);
            SharedEmbeddable se = new SharedEmbeddable();
            fpewc.setSharedEmbeddable(se);
            em.persist(fpewc);
            m_forcedProtectedEntityCompositId = fpewc.getId();
            em.persist(cfe);
            CacheableFalseDetail cacheableFalseDetailEntity = new CacheableFalseDetail();
            em.persist(cacheableFalseDetailEntity);

            CacheableRelationshipsEntity prse = new CacheableRelationshipsEntity();
            prse.setName("Test OneToMany");
            prse.addCacheableFalse(cacheableFalseEntity);
            prse.addCacheableProtected(cacheableProtectedEntity);
            prse.setCacheableFPE(cacheableForceProtectedEntity);
            prse.addCacheableFalseDetail(cacheableFalseDetailEntity);
            prse.addProtectedEmbeddable(pe);
            em.persist(prse);
            m_cacheableRelationshipsEntityId = prse.getId();
            commitTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    public void testDetailsOrder_Isolated() {
        testDetailsOrder(false, false);
    }

    public void testDetailsOrder_Isolated_BeginEarlyTransaction() {
        testDetailsOrder(false, true);
    }

    public void testDetailsOrder_Shared() {
        testDetailsOrder(true, false);
    }

    public void testDetailsOrder_Shared_BeginEarlyTransaction() {
        testDetailsOrder(true, true);
    }

    /*
     * @param useSharedCache if true both Entity and Detail use shared cache (otherwise both use isolated cache)
     * @param beginEarlyTransaction if true both EntityManagers that read back objects to verify order will beginEarlyTransaction
     */
    void testDetailsOrder(boolean useSharedCache, boolean beginEarlyTransaction) {
        String puName = useSharedCache ? "ALL" : "NONE";
        if (isOnServer()) {
            puName = useSharedCache ? "MulitPU-1" : "MulitPU-2";
        }
        int entityId;
        int nDetails = 2;

        // create entity and details, persist them
        EntityManager em = createEntityManager(puName);
        try {
            beginTransaction(em);
            CacheableFalseEntity entity = new CacheableFalseEntity();
            for(int i=0; i < nDetails; i++) {
                CacheableFalseDetail detail = new CacheableFalseDetail();
                detail.setDescription(Integer.toString(i));
                entity.getDetails().add(detail);
            }
            em.persist(entity);
            commitTransaction(em);
            entityId = entity.getId();
        } finally {
            if(isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }

        try {
            // verify that the order is correct, then reverse the order
            clearCache(puName);
            em = createEntityManager(puName);
            try {
                beginTransaction(em);
                if(beginEarlyTransaction) {
                    em.setProperty(EntityManagerProperties.JOIN_EXISTING_TRANSACTION, "true");
                }
                // verify that the order is correct
                CacheableFalseEntity entity = em.find(CacheableFalseEntity.class, entityId);
                assertTrue("Read back wrong number of details", nDetails == entity.getDetails().size());
                for(int i=0; i < nDetails; i++) {
                    CacheableFalseDetail detail = entity.getDetails().get(i);
                    int iExpected = Integer.parseInt(detail.getDescription());
                    assertTrue("Wrong index " + i + "; was expected " + iExpected, i == iExpected);
                }

                // reverse the order
                List<CacheableFalseDetail> copyDetails = new ArrayList(entity.getDetails());
                entity.getDetails().clear();
                for(int i=nDetails-1; i >= 0; i--) {
                    entity.getDetails().add(copyDetails.get(i));
                }
                commitTransaction(em);
            } finally {
                if(isTransactionActive(em)) {
                    rollbackTransaction(em);
                }
                closeEntityManager(em);
            }

            // verify that the order is still correct
            clearCache(puName);
            em = createEntityManager(puName);
            try {
                beginTransaction(em);
                if(beginEarlyTransaction) {
                    em.setProperty(EntityManagerProperties.JOIN_EXISTING_TRANSACTION, "true");
                }
                CacheableFalseEntity entity = em.find(CacheableFalseEntity.class, entityId);
                assertTrue("After reverse read back wrong number of details", nDetails == entity.getDetails().size());
                for(int i=0; i < nDetails; i++) {
                    CacheableFalseDetail detail = entity.getDetails().get(i);
                    // the order has been reversed
                    int iExpected = nDetails - Integer.parseInt(detail.getDescription()) - 1;
                    assertTrue("After reverse wrong index " + i + "; was expected " + iExpected, i == iExpected);
                }
            } finally {
                if(isTransactionActive(em)) {
                    rollbackTransaction(em);
                }
                closeEntityManager(em);
            }
        } finally {
            // clean up
            em = createEntityManager(puName);
            try {
                beginTransaction(em);
                CacheableFalseEntity entity = em.find(CacheableFalseEntity.class, entityId);
                em.remove(entity);
                commitTransaction(em);
            } finally {
                if(isTransactionActive(em)) {
                    rollbackTransaction(em);
                }
                closeEntityManager(em);
            }
        }
    }

    public void testLoadMixedCacheTree(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        try{
            CacheableForceProtectedEntity cte = em.find(CacheableForceProtectedEntity.class, m_cacheableForceProtectedEntity1Id);
            assertNotNull("Did not load the CacheableTrue Entity", cte);
            CacheableFalseEntity cfe = cte.getCacheableFalse();
            assertNotNull("Did not load the CacheableFalse related Entity", cfe);
            CacheableProtectedEntity cpe = cfe.getProtectedEntity();
            assertNotNull("Did not load the Cacheable Protected related Entity", cpe);
            CacheableRelationshipsEntity cre = em.find(CacheableRelationshipsEntity.class, m_cacheableRelationshipsEntityId);
            assertNotNull("Did not load the CacheableRelationshipsEntity", cre);
            List<CacheableFalseEntity> cacheableFalses = cre.getCacheableFalses();
            assertNotNull("Did not load collections of CacheableRelationshipsEntity related(OneToMany) CacheableFalseEntity", cacheableFalses);
            List<CacheableProtectedEntity> cacheableProtects = cre.getCacheableProtecteds();
            assertNotNull("Did not load collections of CacheableRelationshipsEntity related(OneToMany) CacheableProtectedEntity", cacheableProtects);
            CacheableForceProtectedEntity cfpe = cre.getCacheableFPE();
            assertNotNull("Did not load the CacheableRelationshipsEntity related(ManyToOne) CacheableForceProtectedEntity", cfpe);
            List<CacheableFalseDetail> cacheableFalseDetails = cre.getCacheableFalseDetails();
            assertNotNull("Did not load collections of CacheableRelationshipsEntity related(ManyToMany) CacheableFalseDetail", cacheableFalseDetails);
            List<ProtectedEmbeddable> protectedEmbed = cre.getProtectedEmbeddables();
            assertNotNull("Did not load collections of CacheableRelationshipsEntity related(ElementCollection) ProtectedEmbeddable", protectedEmbed);
    }finally{
        rollbackTransaction(em);
        closeEM(em);
        }
    }

    public void testIsolatedIsolation(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        try{
            CacheableForceProtectedEntity cte = em.find(CacheableForceProtectedEntity.class, m_cacheableForceProtectedEntity1Id);
            CacheableFalseEntity cfe = cte.getCacheableFalse();
            assertNull("An isolated Entity was found in the shared cache", em.unwrap(ServerSession.class).getIdentityMapAccessor().getFromIdentityMap(cfe));
            CacheableRelationshipsEntity cre = em.find(CacheableRelationshipsEntity.class, m_cacheableRelationshipsEntityId);
            for (CacheableFalseEntity cfe1 : cre.getCacheableFalses()){
                assertNull("An isolated Entity in many side of OneToMany relationship was found in the shared cache", em.unwrap(ServerSession.class).getIdentityMapAccessor().getFromIdentityMap(cfe1));
            }
            for (CacheableFalseDetail cfde1 : cre.getCacheableFalseDetails()){
                assertNull("An isolated Entity in many side of ManyToMany relationship was found in the shared cache", em.unwrap(ServerSession.class).getIdentityMapAccessor().getFromIdentityMap(cfde1));
            }
    }finally{
        rollbackTransaction(em);
        closeEM(em);
        }
    }

    public void testProtectedIsolationWithLockOnCloneFalse(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        ClassDescriptor descriptor = null;
        try{
            ServerSession session = em.unwrap(ServerSession.class);
            descriptor = session.getDescriptor(CacheableForceProtectedEntity.class);
            descriptor.setShouldLockForClone(false);
            session.readObject(CacheableForceProtectedEntity.class, new ExpressionBuilder().get("id").equal(m_cacheableForceProtectedEntity1Id));
            CacheableForceProtectedEntity cte = em.find(CacheableForceProtectedEntity.class, m_cacheableForceProtectedEntity1Id);
            CacheableFalseEntity cfe = cte.getCacheableFalse();
            assertNotNull("Failed to load protected relationship when setShouldLockForClone is set to false", cfe);
            CacheableProtectedEntity cpe = cfe.getProtectedEntity();
            assertNotNull("Failed to load protected relationship when setShouldLockForClone is set to false", cpe);
        }finally{
            if (descriptor != null){
                descriptor.setShouldLockForClone(true);
            }
        rollbackTransaction(em);

        closeEM(em);
        }

    }

    public void testProtectedIsolation(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        try{
            CacheableForceProtectedEntity cte = em.find(CacheableForceProtectedEntity.class, m_cacheableForceProtectedEntity1Id);
            CacheableFalseEntity cfe = cte.getCacheableFalse();
            CacheableProtectedEntity cpe = cfe.getProtectedEntity();
            ServerSession session = em.unwrap(ServerSession.class);
            assertNull("An protected relationshipwas found in the shared cache", ((CacheableForceProtectedEntity)session.getIdentityMapAccessor().getFromIdentityMap(cte)).getCacheableFalse());
            CacheableRelationshipsEntity cre = em.find(CacheableRelationshipsEntity.class, m_cacheableRelationshipsEntityId);
            for (CacheableProtectedEntity cpe1 : ((CacheableRelationshipsEntity)session.getIdentityMapAccessor().getFromIdentityMap(cre)).getCacheableProtecteds()){
                assertNotNull("An protected relationship in OneToMany was not found in the shared cache", cpe1);
            }
            assertNotNull("An protected relationship in ManyToOne was found in the shared cache", ((CacheableRelationshipsEntity)session.getIdentityMapAccessor().getFromIdentityMap(cre)).getCacheableFPE());
            for (ProtectedEmbeddable cpe2 : ((CacheableRelationshipsEntity)session.getIdentityMapAccessor().getFromIdentityMap(cre)).getProtectedEmbeddables()){
                assertNull("An protected relationship in ElementCollection was found in the shared cache", cpe2);
            }
        }finally{
        rollbackTransaction(em);
        closeEM(em);
        }

    }

    public void testForceProtectedFromEmbeddable(){
        EntityManager em = createDSEntityManager();
        ClassDescriptor forcedProtectedDescriptor = em.unwrap(ServerSession.class).getDescriptor(ForceProtectedEntityWithComposite.class);
        ClassDescriptor protectedEmbeddableDesc = forcedProtectedDescriptor.getMappingForAttributeName("protectedEmbeddable").getReferenceDescriptor();
        ClassDescriptor sharedEmbeddableDesc = forcedProtectedDescriptor.getMappingForAttributeName("sharedEmbeddable").getReferenceDescriptor();
        assertFalse("Isolation of Entity not altered when embeddable has noncacheable relationship", forcedProtectedDescriptor.isSharedIsolation());
        assertFalse("Isolation of Embeddable not altered when embeddable has noncacheable relationship", protectedEmbeddableDesc.isSharedIsolation());
        assertFalse("Isolation of Embeddable not altered when Parent Entity is Protected", sharedEmbeddableDesc.isSharedIsolation());
    }

    public void testEmbeddableProtectedCaching(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        try{
            ForceProtectedEntityWithComposite cte = em.find(ForceProtectedEntityWithComposite.class, m_forcedProtectedEntityCompositId);
            CacheableRelationshipsEntity cre = em.find(CacheableRelationshipsEntity.class, m_cacheableRelationshipsEntityId);
            ProtectedEmbeddable pe = cte.getProtectedEmbeddable();

            ServerSession session = em.unwrap(ServerSession.class);
            commitTransaction(em);
            closeEM(em);
            ForceProtectedEntityWithComposite cachedCPE = (ForceProtectedEntityWithComposite) session.getIdentityMapAccessor().getFromIdentityMap(cte);
            CacheableRelationshipsEntity cachedCRE = (CacheableRelationshipsEntity) session.getIdentityMapAccessor().getFromIdentityMap(cre);
            assertNotNull("ForceProtectedEntityWithComposite was not found in the cache", cachedCPE);
            assertNotNull("CacheableRelationshipsEntity was not found in the cache", cachedCRE);
            cachedCPE.getProtectedEmbeddable().setName("NewName"+System.currentTimeMillis());
            //following code is commented out due to bug 336651
            //cachedCRE.getProtectedEmbeddables().get(0).setName("NewName"+System.currentTimeMillis());
            em = createDSEntityManager();
            beginTransaction(em);
            ForceProtectedEntityWithComposite managedCPE = em.find(ForceProtectedEntityWithComposite.class, cte.getId());
            CacheableRelationshipsEntity managedCRE = em.find(CacheableRelationshipsEntity.class, cre.getId());
            assertEquals("Cache was not used for Protected Isolation", cachedCPE.getProtectedEmbeddable().getName(),managedCPE.getProtectedEmbeddable().getName());
            //follwoing code is commented out due to bug 336651
            //assertEquals("Cache was not used for Protected Isolation", cachedCRE.getProtectedEmbeddables().get(0).getName(),managedCRE.getProtectedEmbeddables().get(0).getName());
        } finally {
            rollbackTransaction(em);
            closeEM(em);
        }
    }

    // Bug 347168
    public void testEmbeddableProtectedReadOnly(){
        EntityManager em = createDSEntityManager();
        Map properties = new HashMap();
        properties.put(QueryHints.READ_ONLY, "true");
        ForceProtectedEntityWithComposite cte = null;
        try{
            cte = em.find(ForceProtectedEntityWithComposite.class, m_forcedProtectedEntityCompositId, properties);
        } catch (Exception e){
            fail("Exception while trying to do a read-only find to an protected entity with an embeddable: " + e.getMessage());
        }
        assertNotNull("Protected entity did not have aggregate when read back.", cte.getProtectedEmbeddable());
    }

    public void testProtectedCaching(){
        //Nested transaction not supported
        if (! isOnServer()) {
            EntityManager em = createDSEntityManager();
            beginTransaction(em);
            try{
                CacheableForceProtectedEntity cte = em.find(CacheableForceProtectedEntity.class, m_cacheableForceProtectedEntity1Id);
                CacheableFalseEntity cfe = cte.getCacheableFalse();
                CacheableProtectedEntity cpe = cfe.getProtectedEntity();
                CacheableRelationshipsEntity cre = em.find(CacheableRelationshipsEntity.class, m_cacheableRelationshipsEntityId);
                List<CacheableProtectedEntity> cacheableProtects = cre.getCacheableProtecteds();
                CacheableForceProtectedEntity cfpe = cre.getCacheableFPE();
                ServerSession session = em.unwrap(ServerSession.class);
                closeEM(em);
                CacheableProtectedEntity cachedCPE = (CacheableProtectedEntity) session.getIdentityMapAccessor().getFromIdentityMap(cpe);
                assertNotNull("CacheableProtectedEntity was not found in the cache", cachedCPE);
                CacheableForceProtectedEntity cachedCFPE = (CacheableForceProtectedEntity) session.getIdentityMapAccessor().getFromIdentityMap(cfpe);
                assertNotNull("CacheableForceProtectedEntity from ManyToOne relationship was not found in the cache", cachedCFPE);
                for (CacheableProtectedEntity cpe1 : cacheableProtects){
                    CacheableProtectedEntity cachedCPE1 = (CacheableProtectedEntity) session.getIdentityMapAccessor().getFromIdentityMap(cpe1);
                    assertNotNull("CacheableProtectedEntity from OneToMany relationship was not found in the cache", cachedCPE1);
                }
                cachedCPE.setName("NewName"+System.currentTimeMillis());
                cachedCFPE.setName("NewName"+System.currentTimeMillis());
                em = createDSEntityManager();
                beginTransaction(em);
                CacheableProtectedEntity managedCPE = em.find(CacheableProtectedEntity.class, cpe.getId());
                CacheableForceProtectedEntity managedCFPE = em.find(CacheableForceProtectedEntity.class, cfpe.getId());
                assertEquals("Cache was not used for Protected Isolation", cachedCPE.getName(),managedCPE.getName());
                assertEquals("Cache was not used for Protected Isolation", cachedCFPE.getName(),managedCFPE.getName());
            }finally{
            rollbackTransaction(em);
            closeEM(em);
            }
        }
    }

    public void testProtectedRelationshipsMetadata(){
        EntityManager em = createDSEntityManager();
        ServerSession session = em.unwrap(ServerSession.class);
        ClassDescriptor descriptor = session.getDescriptor(ProtectedRelationshipsEntity.class);
        for (DatabaseMapping mapping : descriptor.getMappings()){
            if (!mapping.isDirectToFieldMapping()){
                assertTrue("Relationship NONCacheable metadata was not processed correctly", !mapping.isCacheable());
            }
        }
        descriptor = session.getDescriptorForAlias("XML_ROTECTED_RELATIONSHIPS");
        for (DatabaseMapping mapping : descriptor.getMappings()){
            if (!mapping.isDirectToFieldMapping()){
                assertTrue("Relationship NONCacheable metadata was not processed correctly", !mapping.isCacheable());
            }
        }
        closeEM(em);

    }

    public void testReadOnlyTree(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        try{
            Query q = em.createQuery("Select c from JPA_CACHEABLE_FORCE_PROTECTED c");
            q.setHint(QueryHints.READ_ONLY, "true");
            CacheableForceProtectedEntity cte = (CacheableForceProtectedEntity) q.getResultList().get(0);
            assertNotNull("Did not load the CacheableTrue Entity", cte);
            CacheableFalseEntity cfe = cte.getCacheableFalse();
            assertNotNull("Did not load the CacheableFalse related Entity", cfe);
            CacheableProtectedEntity cpe = cfe.getProtectedEntity();
            assertNotNull("Did not load the Cacheable Protected related Entity", cpe);
            Query q1 = em.createQuery("Select c from JPA_CACHEABLE_RELATIONSHIPS c");
            q1.setHint(QueryHints.READ_ONLY, "true");
            CacheableRelationshipsEntity cre = (CacheableRelationshipsEntity) q1.getResultList().get(0);
            for (CacheableFalseEntity cfe1 : cre.getCacheableFalses()){
                assertNotNull("Did not load the CacheableFalse related Entity in OneToMany relationship", cfe1);
            }
            for (CacheableProtectedEntity cpe1 : cre.getCacheableProtecteds()){
                assertNotNull("Did not load the CacheableProtected related Entity in OneToMany relationship", cpe1);
            }
            CacheableForceProtectedEntity cfpe = cre.getCacheableFPE();
            assertNotNull("Did not load the Cacheable Force Protected related Entity in ManyToOne relationship", cfpe);
            for (CacheableFalseDetail cfde : cre.getCacheableFalseDetails()){
                assertNotNull("Did not load the CacheableFalse Details related Entity in ManyToMany relationship", cfde);
            }
        }finally{
            rollbackTransaction(em);
            closeEM(em);
        }
    }

    public void testUpdateForceProtectedOneToOne(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        int cfeID = 0;
        try{
            CacheableForceProtectedEntity cte = em.find(CacheableForceProtectedEntity.class, m_cacheableForceProtectedEntity1Id);
            CacheableFalseEntity oldcfe = cte.getCacheableFalse();
            ServerSession session = em.unwrap(ServerSession.class);
            CacheableFalseEntity cfe = new CacheableFalseEntity();
            em.persist(cfe);
            cfeID = cfe.getId();
            cte.setCacheableFalse(cfe);
            commitTransaction(em);
            CacheableForceProtectedEntity cachedCPE = (CacheableForceProtectedEntity) session.getIdentityMapAccessor().getFromIdentityMap(cte);
            assertNull("A protected OneToOne relationship was merged into the shared cache", cachedCPE.getCacheableFalse());
            ObjectReferenceMapping orm = (ObjectReferenceMapping) session.getDescriptor(CacheableForceProtectedEntity.class).getMappingForAttributeName("cacheableFalse");
            Object cacheableFalsefk = session.getIdentityMapAccessorInstance().getCacheKeyForObject(cte).getProtectedForeignKeys().get(orm.getSelectFields().get(0));
            assertEquals("FK update not cached", cfe.getId(), cacheableFalsefk);
            beginTransaction(em);
            cte.setCacheableFalse(oldcfe);
            cfe = em.find(CacheableFalseEntity.class, cfeID);
            em.remove(cfe);
            commitTransaction(em);
        }finally{
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEM(em);
        }
    }

    public void testUpdateForceProtectedBasic(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        try{
            CacheableForceProtectedEntity cte = em.find(CacheableForceProtectedEntity.class, m_cacheableForceProtectedEntity1Id);
            String newName = "SomeNewName" + System.currentTimeMillis();
            cte.setName(newName);
            commitTransaction(em);
            ServerSession session = em.unwrap(ServerSession.class);
            CacheableForceProtectedEntity cachedCPE = (CacheableForceProtectedEntity) session.getIdentityMapAccessor().getFromIdentityMap(cte);
            assertEquals("A Basic mapping in a Protected class was not merged into the shared cache.  Expected: "+ newName + " found: "+ cachedCPE.getName(), cachedCPE.getName(), newName);
        }finally{
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEM(em);
        }
    }

    public void testUpdateProtectedBasic(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        try{
            CacheableProtectedEntity cte = em.find(CacheableProtectedEntity.class, m_cacheableProtectedEntityId);
            ServerSession session = em.unwrap(ServerSession.class);
            String newName = "SomeNewName" + System.currentTimeMillis();
            cte.setName(newName);
            commitTransaction(em);
            CacheableProtectedEntity cachedCPE = (CacheableProtectedEntity) session.getIdentityMapAccessor().getFromIdentityMap(cte);
            assertEquals("A Basic mapping in a Protected class was not merged into the shared cache", newName, cachedCPE.getName());
        }finally{
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEM(em);
        }
    }

    public void testUpdateProtectedOneToMany(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        int cfeID = 0;
        try{
            CacheableForceProtectedEntity cte = em.find(CacheableForceProtectedEntity.class, m_cacheableForceProtectedEntity1Id);
            ServerSession session = em.unwrap(ServerSession.class);
            CacheableProtectedEntity cfe = new CacheableProtectedEntity();
            em.persist(cfe);
            cfeID = cfe.getId();
            cfe.setForcedProtected(cte);
            cte.getCacheableProtecteds().add(cfe);
            commitTransaction(em);

            CacheableForceProtectedEntity cachedCPE = (CacheableForceProtectedEntity) session.getIdentityMapAccessor().getFromIdentityMap(cte);
            assertFalse("A protected OneToMany relationship was not merged into the shared cache", cachedCPE.getCacheableProtecteds() == null || cachedCPE.getCacheableProtecteds().isEmpty());
            beginTransaction(em);
            cte.getCacheableProtecteds().clear();
            cfe.setForcedProtected(null);
            cfe = em.find(CacheableProtectedEntity.class, cfeID);
            em.remove(cfe);
            commitTransaction(em);
        }finally{
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEM(em);
        }
    }

    public void testUpdateProtectedManyToOne(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        int creID = 0;
        try{
            CacheableForceProtectedEntity cfpe = em.find(CacheableForceProtectedEntity.class, m_cacheableForceProtectedEntity1Id);
            ServerSession session = em.unwrap(ServerSession.class);
            CacheableRelationshipsEntity cre = new CacheableRelationshipsEntity();
            em.persist(cre);
            creID = cre.getId();
            cre.setCacheableFPE(cfpe);
            commitTransaction(em);

            CacheableRelationshipsEntity cachedCRE = (CacheableRelationshipsEntity) session.getIdentityMapAccessor().getFromIdentityMap(cre);
            assertFalse("A protected ManyToOne relationship was not merged into the shared cache", cachedCRE.getCacheableFPE() == null);
            beginTransaction(em);
            cre = em.find(CacheableRelationshipsEntity.class, creID);
            em.remove(cre);
            commitTransaction(em);
        }finally{
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEM(em);
        }
    }

    public void testUpdateProtectedManyToMany(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        int cfdID1 = 0, cfdID2 = 0;
        try{
            CacheableRelationshipsEntity cre = em.find(CacheableRelationshipsEntity.class, m_cacheableRelationshipsEntityId);
            ServerSession session = em.unwrap(ServerSession.class);
            CacheableFalseDetail cfd1 = new CacheableFalseDetail();
            CacheableFalseDetail cfd2 = new CacheableFalseDetail();
            em.persist(cfd1);
            em.persist(cfd2);
            cfdID1 = cfd1.getId();
            cfdID2 = cfd2.getId();
            cre.addCacheableFalseDetail(cfd1);
            cre.addCacheableFalseDetail(cfd2);
            commitTransaction(em);

            CacheableRelationshipsEntity cachedCRE = (CacheableRelationshipsEntity) session.getIdentityMapAccessor().getFromIdentityMap(cre);
            assertTrue("A protected ManyToMany relationship was merged into the shared cache", cachedCRE.getCacheableFalseDetails() == null || cachedCRE.getCacheableFalseDetails().isEmpty());
            beginTransaction(em);
            cre.getCacheableFalseDetails().clear();
            cre = em.find(CacheableRelationshipsEntity.class, m_cacheableRelationshipsEntityId);
            cfd1 = em.find(CacheableFalseDetail.class, cfdID1);
            cfd2 = em.find(CacheableFalseDetail.class, cfdID2);
            cre.removeCacheableFalseDetail(cfd1);
            cre.removeCacheableFalseDetail(cfd2);
            em.remove(cfd1);
            em.remove(cfd2);
            commitTransaction(em);
        }finally{
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEM(em);
        }
    }

    public void testUpdateProtectedElementCollection(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        try{
            CacheableRelationshipsEntity cre = em.find(CacheableRelationshipsEntity.class, m_cacheableRelationshipsEntityId);
            ServerSession session = em.unwrap(ServerSession.class);
            ProtectedEmbeddable cem1 = new ProtectedEmbeddable();
            ProtectedEmbeddable cem2 = new ProtectedEmbeddable();
            cre.addProtectedEmbeddable(cem1);
            cre.addProtectedEmbeddable(cem2);
            commitTransaction(em);

            CacheableRelationshipsEntity cachedCRE = (CacheableRelationshipsEntity) session.getIdentityMapAccessor().getFromIdentityMap(cre);
            assertTrue("A protected ElementCollection relationship was merged into the shared cache", cachedCRE.getProtectedEmbeddables() == null || cachedCRE.getProtectedEmbeddables().isEmpty());
            beginTransaction(em);
            cre.getProtectedEmbeddables().clear();
            commitTransaction(em);
        }finally{
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEM(em);
        }
    }

    //Bug #530680
    public void testUpdateSharedElementCollection() {
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        try{
            CacheableRelationshipsEntity cre = em.find(CacheableRelationshipsEntity.class, m_cacheableRelationshipsEntityId);
            ServerSession session = em.unwrap(ServerSession.class);
            SharedEmbeddable cem1 = new SharedEmbeddable();
            cem1.setName("origName1");
            SharedEmbeddable cem2 = new SharedEmbeddable();
            cem2.setName("origName2");
            cre.addSharedEmbeddable(cem1);
            cre.addSharedEmbeddable(cem2);
            commitTransaction(em);

            CacheableRelationshipsEntity cachedCRE = (CacheableRelationshipsEntity) session.getIdentityMapAccessor().getFromIdentityMap(cre);
            assertTrue("A shared ElementCollection relationship was not merged into the shared cache", cachedCRE.getSharedEmbeddables() != null && !cachedCRE.getSharedEmbeddables().isEmpty());

            CacheableRelationshipsEntity cre2 = em.find(CacheableRelationshipsEntity.class, m_cacheableRelationshipsEntityId);
            beginTransaction(em);
            em.detach(cre2);
            cre2.getSharedEmbeddables().remove(0);
            em.merge(cre2);
            commitTransaction(em);

            session = em.unwrap(ServerSession.class);
            CacheableRelationshipsEntity cachedCRE2 = (CacheableRelationshipsEntity) session.getIdentityMapAccessor().getFromIdentityMap(cre2);
            assertEquals("Changes in shared ElementCollection relationship were not merged into the shared cache", 1, cachedCRE2.getSharedEmbeddables().size());

            beginTransaction(em);
            cre.getSharedEmbeddables().clear();
            commitTransaction(em);
        }finally{
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEM(em);
        }
    }

    public void testIsolationBeforeEarlyTxBegin(){
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        int cfeID = 0;
        try {
            CacheableForceProtectedEntity cte = em.find(CacheableForceProtectedEntity.class, m_cacheableForceProtectedEntity1Id);
            ServerSession session = em.unwrap(ServerSession.class);
            CacheableProtectedEntity cfe = new CacheableProtectedEntity();
            em.persist(cfe);
            cfeID = cfe.getId();
            cfe.setForcedProtected(cte);
            cte.getCacheableProtecteds().add(cfe);
            commitTransaction(em);

            CacheableRelationshipsEntity cre = em.find(CacheableRelationshipsEntity.class, m_cacheableRelationshipsEntityId);
            assertNotNull("CacheableRelationshipsEntity from find should not be null", cre);
            CacheableRelationshipsEntity cachedCRE = (CacheableRelationshipsEntity) session.getIdentityMapAccessor().getFromIdentityMap(cre);
            assertNotNull("CacheableRelationshipsEntity from cache should not be null", cachedCRE);
            assertTrue("A protected OneToMany relationship was merged into the shared cache", cachedCRE.getCacheableFalses() == null || cachedCRE.getCacheableFalses().isEmpty());
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            try {
                beginTransaction(em);

                CacheableForceProtectedEntity cte = em.find(CacheableForceProtectedEntity.class, m_cacheableForceProtectedEntity1Id);
                CacheableProtectedEntity cfe = em.find(CacheableProtectedEntity.class, cfeID);
                cte.getCacheableProtecteds().clear();
                cfe.setForcedProtected(null);
                em.remove(cfe);

                commitTransaction(em);
            } catch (Exception e) {
                if (isTransactionActive(em)){
                    rollbackTransaction(em);
                }
            }
            closeEM(em);
        }
    }

    /**
     * Convenience method. This will not update the entity in the shared cache.
     */
    protected void updateCacheableTrueEntityNameAndBypassStore(String name) {
        EntityManager em = createDSEntityManager();

        try {
            beginTransaction(em);
            Query query = em.createQuery("UPDATE JPA_CACHEABLE_TRUE e SET e.name = :name " + "WHERE e.id = :id ").setParameter("name", name).setParameter("id", m_cacheableTrueEntity1Id);
            query.setHint(QueryHints.CACHE_STORE_MODE, CacheStoreMode.BYPASS);
            query.executeUpdate();
            commitTransaction(em);
        } catch (Exception e) {
            fail("Error updating the entity through JPQL: " + e);
        } finally {
            closeEM(em);
        }
    }

    /**
     * Convenience method. This will update the entity in the shared cache.
     */
    protected void updateCacheableTrueEntityNameInSharedCache(String name) {
        updateCacheableTrueEntityNameInSharedCache(name, null);
    }

    /**
     * Convenience method. This will update the entity in the shared cache.
     */
    protected void updateCacheableTrueEntityNameInSharedCache(String name, EntityManager em) {
        EntityManager emToUse;

        if (em == null) {
            emToUse = createDSEntityManager();
        } else {
            emToUse = em;
        }

        try {
            beginTransaction(emToUse);
            emToUse.createQuery("UPDATE JPA_CACHEABLE_TRUE e SET e.name = :name " + "WHERE e.id = :id ").setParameter("name", name).setParameter("id", m_cacheableTrueEntity1Id).executeUpdate();
            commitTransaction(emToUse);
        } catch (Exception e) {
            fail("Error updating the entity through JPQL: " + e);
        } finally {
            if (em == null) {
                closeEM(emToUse);
            }
        }
    }

    // Bug 345478 - Incorrect foreign key parameter set when retrieving an eager @OneToMany
    public void testMergeNonCachedWithRelationship(){
        // create entity and details, persist them
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        CacheableFalseEntity entity = new CacheableFalseEntity();
        em.persist(entity);
        commitTransaction(em);
        em.clear();
        CacheableFalseDetailWithBackPointer detail = null;
        try{
            detail = new CacheableFalseDetailWithBackPointer();
            detail.setEntity(entity);
            List<CacheableFalseDetailWithBackPointer> details = new ArrayList<CacheableFalseDetailWithBackPointer>();
            details.add(detail);
            entity.setDetailsBackPointer(details);
            detail.setDescription("test");
            beginTransaction(em);
            detail = em.merge(detail);
            commitTransaction(em);

            beginTransaction(em);
            detail = em.find(detail.getClass(), detail.getId());
            em.refresh(detail);
            commitTransaction(em);

            assertTrue("detail does not have it's entity.", detail.getEntity() != null);
            assertTrue("detail's entity does not have the backpointer.", detail.getEntity().getDetailsBackPointer().size() == 1);
        } finally {
            beginTransaction(em);
            detail = em.merge(detail);
            em.remove(detail.getEntity());
            em.remove(detail);
            commitTransaction(em);
            closeEM(em);
        }

    }

    // Bug392542 - Test Foreign Key update of detached while merging new object with
    // reference to a detatched object with cascade merge.
    public void testForeignKeyUpdateInNonCachedOnMergeNewObject(){
        // create entity and details, persist them
        EntityManager em = createDSEntityManager();
        beginTransaction(em);
        try{
            CacheableFalseDetailWithBackPointer detail = new CacheableFalseDetailWithBackPointer();
            detail.setDescription("test");
            detail = em.merge(detail);
            em.flush();

            em.clear();

            CacheableFalseEntity entity = new CacheableFalseEntity();
            List<CacheableFalseDetailWithBackPointer> details = new ArrayList<CacheableFalseDetailWithBackPointer>();
            details.add(detail);
            entity.setDetailsBackPointer(details);
            detail.setEntity(entity);
            entity = em.merge(entity);
            em.flush();

            em.clear();

            // Verify Foreign Key Update.
            CacheableFalseDetailWithBackPointer falseDetail = em.find(detail.getClass(), detail.getId());

            assertTrue("Foreign Key is not updated in detail.", falseDetail.getEntity() != null);
            assertTrue("Foreign Key updated, but doesn't match.", falseDetail.getEntity().getId() == entity.getId());
        } finally {
            rollbackTransaction(em);
            closeEM(em);

        }
    }

     // Bug 347190
    public void testIndirectCollectionRefreshBehavior(){
        QuerySQLTracker counter = new QuerySQLTracker(getServerSession());
        EntityManager em = createEntityManager();
        try{
            beginTransaction(em);

            CacheableFalseEntity entity = new CacheableFalseEntity();
            CacheableFalseDetailWithBackPointer detail = new CacheableFalseDetailWithBackPointer();

            List<CacheableFalseDetailWithBackPointer> details = new ArrayList<CacheableFalseDetailWithBackPointer>();
            details.add(detail);
            entity.setDetailsBackPointer(details);
            detail.setEntity(entity);

            em.persist(entity);

            em.flush();
            em.clear();
            counter.getSqlStatements().clear();
            Query query = em.createQuery("SELECT e from JPA_CACHEABLE_FALSE e where e.id = :id").setParameter("id", entity.getId());
            query.setHint(QueryHints.REFRESH, HintValues.TRUE);
            entity = (CacheableFalseEntity)query.getResultList().get(0);
            IndirectList list = (IndirectList)entity.getDetailsBackPointer();
            assertFalse(list.isInstantiated());
            assertEquals(2, counter.getSqlStatements().size());
        } finally{
            rollbackTransaction(em);
            counter.remove();
            closeEntityManager(em);
        }
      }

    // Bug 352533
    public void testDerivedIDProtectedRead(){
        EntityManager em = createEntityManager();
        CacheableFalseEntity cf = null;
        CacheableTrueDerivedIDEntity ctdid  = null;
        try{
            beginTransaction(em);
            cf = new CacheableFalseEntity();
            em.persist(cf);
            em.flush();

            ctdid = new CacheableTrueDerivedIDEntity("desc1", cf);
            em.persist(ctdid);
            commitTransaction(em);
            em.clear();

            ctdid = em.find(CacheableTrueDerivedIDEntity.class, new CacheableTrueDerivedIDPK(ctdid.getPk().getDescription(), cf.getId()));
            assertNotNull("The protected cached relationship was not properly retrieved", ctdid.getCacheableFalse());
        } finally {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            beginTransaction(em);
            cf = em.find(CacheableFalseEntity.class, cf.getId());
            ctdid = em.find(ctdid.getClass(), ctdid.getPk());
            em.remove(cf);
            em.remove(ctdid);
            commitTransaction(em);
        }

    }

    //Bug 408262 - Refresh of Protected Entity in early transaction refreshes Entity in shared cache
    public void testRefreshProtectedEntityInEarlyTransaction() {
        CacheableForceProtectedEntity entity = null;
        try {
            EntityManager em = createDSEntityManager();
            beginTransaction(em);

            entity = new CacheableForceProtectedEntity();
            entity.setName("original");

            em.persist(entity);
            assertEquals("original", entity.getName());

            commitTransaction(em);
            assertEquals("original", entity.getName());

            em = createDSEntityManager();
            beginTransaction(em);

            entity = em.find(CacheableForceProtectedEntity.class, entity.getId());
            entity.setName("modified");

            em.flush();

            em.refresh(entity); // problem occurs in refresh
            assertNotNull(entity);
            assertEquals("modified", entity.getName());

            rollbackTransaction(em);

            em = createDSEntityManager();

            entity = em.find(CacheableForceProtectedEntity.class, entity.getId());

            closeEM(em);

            assertNotNull(entity);
            assertEquals("Entity found should have an unmodified name post-rollback", "original", entity.getName());
        } finally {
            if (entity != null) {
                EntityManager em = createDSEntityManager();
                beginTransaction(em);
                entity = em.find(CacheableForceProtectedEntity.class, entity.getId());
                if (entity != null) {
                    em.remove(entity);
                }
                commitTransaction(em);
                closeEM(em);
            }
        }
    }

    /**
     * Test caching with <code>@Cacheable(false)</code> in parent class, <code>@Cacheable(true)</code> in child class
     * and another child class which just inherits <code>@Cacheable</code> value from parent class.
     * There is following class structure with <code>@Cacheable</code> settings:<ul>
     * <li><code>ProductFalse</code> with <code>@Cacheable(false)</code></li>
     * <li><code>ProductHardwareTrue</code> with <code>@Cacheable(false)</code> extends <code>ProductFalse</code></li>
     * <li><code>ProductSoftwareFalse</code> with <code>@Cacheable</code> value inherited from parent extends <code>ProductFalse</code></li></ul>
     * Abstract code to be reused in child test classes to verify caching for ENABLE_SELECTIVE
     * and DISABLE_SELECTIVE shared cache mode.
     */
    protected void runTestCacheableInheritanceBasedOnFalse(EntityManagerFactory emf, EntityManager em) {
        try {
            assertNotNull("Could not create EntityManager", em);
            EntityTransaction tx = em.getTransaction();
            assertNotNull("Could not get transaction", tx);
            tx.begin();
            ProductFalse pf = new ProductFalse(1, 2);
            em.persist(pf);
            ProductHardwareTrue pht = new ProductHardwareTrue(2, 3, 1);
            em.persist(pht);
            ProductSoftwareFalse psf = new ProductSoftwareFalse(3, 2, 1);
            em.persist(psf);
            em.flush();
            tx.commit();
            int pfId = pf.getId();
            int phtId = pht.getId();
            int psfId = psf.getId();
            Cache cache = emf.getCache();
            assertNotNull("Could not get cache", cache);
            boolean isPf = cache.contains(ProductFalse.class, pfId);
            boolean isPht = cache.contains(ProductHardwareTrue.class, phtId);
            boolean isPsf = cache.contains(ProductSoftwareFalse.class, psfId);
            assertFalse("ProductFalse with @Cacheable(false) shall not be in the cache.", isPf);
            assertTrue("ProductHardwareTrue with @Cacheable(false) shall be in the cache.", isPht);
            assertFalse("ProductSoftwareFalse with @Cacheable inherited as false shall not be in the cache.", isPsf);
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    /**
     * Test caching with <code>@Cacheable(true)</code> in parent class, <code>@Cacheable(false)</code> in child class
     * and another child class which just inherits <code>@Cacheable</code> value from parent class.
     * There is following class structure with <code>@Cacheable</code> settings:<ul>
     * <li><code>ProductTrue</code> with <code>@Cacheable(true)</code></li>
     * <li><code>ProductHardwareTrue</code> with <code>@Cacheable(false)</code> extends <code>ProductTrue</code></li>
     * <li><code>ProductSoftwareFalse</code> with <code>@Cacheable</code> value inherited from parent extends <code>ProductTrue</code></li></ul>
     * Abstract code to be reused in child test classes to verify caching for ENABLE_SELECTIVE
     * and DISABLE_SELECTIVE shared cache mode.
     */
    protected void runTestCacheableInheritanceBasedOnTrue(EntityManagerFactory emf, EntityManager em) {
        try {
            assertNotNull("Could not create EntityManager", em);
            EntityTransaction tx = em.getTransaction();
            assertNotNull("Could not get transaction", tx);
            tx.begin();
            ProductTrue pt = new ProductTrue(1, 2);
            em.persist(pt);
            ProductHardwareFalse phf = new ProductHardwareFalse(2, 3, 1);
            em.persist(phf);
            ProductSoftwareTrue pst = new ProductSoftwareTrue(3, 2, 1);
            em.persist(pst);
            em.flush();
            tx.commit();
            int ptId = pt.getId();
            int phfId = phf.getId();
            int pstId = pst.getId();
            Cache cache = emf.getCache();
            assertNotNull("Could not get cache", cache);
            boolean isPt = cache.contains(ProductTrue.class, ptId);
            boolean isPhf = cache.contains(ProductHardwareFalse.class, phfId);
            boolean isPst = cache.contains(ProductSoftwareTrue.class, pstId);
            assertTrue("ProductTrue with @Cacheable(true) shall be in the cache.", isPt);
            assertFalse("ProductHardwareFalse with @Cacheable(true) shall not be in the cache.", isPhf);
            assertTrue("ProductSoftwareTrue with @Cacheable inherited as false shall be in the cache.", isPst);
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    /**
     * Convenience method.
     */
    protected boolean usesNoCache(ClassDescriptor descriptor) {
        return descriptor.isIsolated();
    }
}
