/*
 * Copyright (c) 2008, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     12/04/2008 - 2.0 Darani Yallapragada
//       - 248780: Initial contribution for JPA 2.0
//     06/02/2010 - 2.1 Michael O'Brien
//       - 248780: Refactor Cache Implementation surrounding evict()
//         http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/cache_api#Refactor_20100322
//         Fix evict() to handle non-Entity classes
//         Refactor to get IdentityMapAccessor state through EMF reference
//         Refactor dependencies to use Interfaces instead of Impl subclasses
//         Handle no CMPPolicy case for getId()
//         Handle no associated descriptor for Class parameter
//         MappedSuperclasses passed to evict() cause implementing subclasses to be evicted
//         Throw an IAE for Interfaces and Embeddable classes passed to evict()
package org.eclipse.persistence.testing.tests.jpa.advanced;

import jakarta.persistence.Cache;
import jakarta.persistence.EntityManager;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.persistence.testing.models.jpa.advanced.*;
import org.eclipse.persistence.testing.models.jpa.advanced.fetchgroup.AdvancedFetchGroupTableCreator;
import org.eclipse.persistence.testing.models.jpa.advanced.fetchgroup.ChestProtector;
import org.eclipse.persistence.testing.models.jpa.advanced.fetchgroup.Gear;
import org.eclipse.persistence.testing.models.jpa.advanced.fetchgroup.GoalieGear;
import org.eclipse.persistence.testing.models.jpa.advanced.fetchgroup.NonPersistedSubclassOfChestProtector;
import org.eclipse.persistence.testing.models.jpa.advanced.fetchgroup.Pads;
import org.eclipse.persistence.testing.models.jpa.cacheable.CacheableTableCreator;
import org.eclipse.persistence.testing.models.jpa.metamodel.Manufacturer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.jpa.CMP3Policy;
import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl;
import org.eclipse.persistence.internal.jpa.EntityManagerImpl;
import org.eclipse.persistence.jpa.JpaCache;
import org.eclipse.persistence.jpa.JpaEntityManagerFactory;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;

/**
 * @author DaraniY
 */
public class CacheImplJUnitTest extends JUnitTestCase {

    private static final String METAMODEL_PERSISTENCE_UNIT = "metamodel1";

    public CacheImplJUnitTest() {
        super();
    }

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

    @Override
    public void setUp() {
        super.setUp();
        clearCache();
    }

    /**
     * Note: These tests are setup with ID generation - but it is not used.
     * We set the Id manually so we can test cache operations like eviction properly.
     */
    public static Test suite() {
        TestSuite suite = new TestSuite();
        suite.setName("CacheImplJUnitTest");

        suite.addTest(new CacheImplJUnitTest("testSetup"));
        suite.addTest(new CacheImplJUnitTest("testContains"));
        suite.addTest(new CacheImplJUnitTest("testEvictClassObject"));
        suite.addTest(new CacheImplJUnitTest("testEvictClass"));
        suite.addTest(new CacheImplJUnitTest("testEvictAll"));
        suite.addTest(new CacheImplJUnitTest("testEvictContains"));
        suite.addTest(new CacheImplJUnitTest("testCacheAPI"));
        // 20100322: 248780: CacheImpl refactor for non-Entity classes
        // the following external test models are used [AdvancedFetchGroupTableCreator, CacheableTableCreator]
        suite.addTest(new CacheImplJUnitTest("testEvictClass_MappedSuperclass_RemovesAssignableSubclasses"));
        suite.addTest(new CacheImplJUnitTest("testEvictClassObject_MappedSuperclass_RemovesAssignableSubclasses"));
        suite.addTest(new CacheImplJUnitTest("testEvictClass_JavaLangClass_hasNoEffect"));
        suite.addTest(new CacheImplJUnitTest("testEvictClass_NonPersistableParentOfEntityMappedSuperclassChain_RemovesAssignableSubclasses"));
        suite.addTest(new CacheImplJUnitTest("testEvictClass_NonPersistableSubclassOfEntityMappedSuperclassChain_hasNoEffect"));

        suite.addTest(new CacheImplJUnitTest("testGetId_fromUnmanagedMappedSuperclass_handles_null_descriptor"));
        suite.addTest(new CacheImplJUnitTest("testGetId_fromUnsupportedJavaLangInteger_throwsIAE_on_null_descriptor"));
        // Run these tests last as they modify the state of the ClassDescriptor permanently to verify variant corner use cases
        suite.addTest(new CacheImplJUnitTest("testGetId_fromNativeMappedSuperclass_handles_null_cmp3policy_weaving_on"));
        // 315714: comment out 3 of the 10 new tests requiring setup() table creation - until the metamodel one is added to setup()
        // Tests fail to create tables when run outside of ant or before the metamodel model is created
        /*
        suite.addTest(new CacheImplJUnitTest("testGetId_fromNativeMappedSuperclass_handles_null_cmp3policy_and_null_pk_with_weaving_on"));
        suite.addTest(new CacheImplJUnitTest("testGetId_fromNativeMappedSuperclass_handles_null_cmp3policy_and_null_pk_with_weaving_off"));
        */
        // test null descriptor on closed entityManager
        return suite;
    }

    @Override
    public String getPersistenceUnitName(){
        return "default1";
    }

    /**
     * The setup is done as a test, both to record its failure, and to allow execution in the server.
     */
    public void testSetup() {
        new AdvancedTableCreator().replaceTables(JUnitTestCase.getServerSession());
        new AdvancedFetchGroupTableCreator().replaceTables(JUnitTestCase.getServerSession());
        new CacheableTableCreator().replaceTables(JUnitTestCase.getServerSession());
        // 315714: metamodel model requires a table creator now that we are persisting with it
        clearCache();
    }

    /**
     * Test of contains method, of class CacheImpl.
     */
    public void testContains() {
        EntityManager em1 = createEntityManager();
        beginTransaction(em1);
        Employee e1 = new Employee();
        e1.setFirstName("ellie1");
        e1.setId(101);
        em1.persist(e1);
        commitTransaction(em1);
        closeEntityManager(em1);
        boolean result = getEntityManagerFactory().getCache().contains(Employee.class, 101);
        assertTrue("Employee not found in cache", result);
    }

    /**
     * Test cache API.
     */
    public void testCacheAPI() {
        EntityManager em = createEntityManager();
        beginTransaction(em);
        Employee employee = new Employee();
        employee.setFirstName("testCacheAPI");
        em.persist(employee);
        commitTransaction(em);
        closeEntityManager(em);
        JpaCache cache = (JpaCache)getEntityManagerFactory().getCache();
        assertTrue("Employee not valid in cache", cache.isValid(employee));
        assertTrue("Employee not valid in cache", cache.isValid(Employee.class, employee.getId()));
        cache.timeToLive(employee);
        assertTrue("Employee not found in cache", cache.getObject(Employee.class, employee.getId()) != null);
        assertTrue("Employee not found in cache", cache.contains(employee));
        cache.evict(employee);
        cache.putObject(employee);
        cache.print();
        cache.removeObject(employee);
        cache.removeObject(Employee.class, employee.getId());
        cache.clear();
        cache.clear(Employee.class);
        cache.clearQueryCache();
        cache.clearQueryCache("findAllEmployeesByIdAndFirstName");
        assertTrue("Employee id not correct", employee.getId().equals(cache.getId(employee)));
        cache.print();
        cache.print(Employee.class);
        cache.printLocks();
        cache.validate();
    }

    /**
     * Test of evict method, of class CacheImpl.
     */
    public void testEvictClassObject() {
        String beforeCache;
        String afterCache;
        EntityManager em2 = createEntityManager();
        beginTransaction(em2);
        Employee e2 = new Employee();
        e2.setFirstName("ellie");
        e2.setId(121);
        em2.persist(e2);
        commitTransaction(em2);
        closeEntityManager(em2);
        EntityManager em3 = createEntityManager();
        EntityManager em4=createEntityManager();
        try {
            Employee emp1 = (Employee) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(e2);
            emp1.setFirstName("foo");
            beforeCache = em3.find(Employee.class, 121).getFirstName();
            getEntityManagerFactory().getCache().evict(Employee.class, 121);
            Employee e3 = em4.find(Employee.class, 121);
            afterCache = e3.getFirstName();
            assertNotSame("Assertion Error", beforeCache, afterCache);
        } finally {
            closeEntityManager(em3);
            closeEntityManager(em4);
        }
    }

    /**
     * Test of evict method, of class CacheImpl.
     */
    public void testEvictClass() {
        EntityManager em5 = createEntityManager();
        beginTransaction(em5);
        Employee e4 = new Employee();
        e4.setFirstName("ellie");
        e4.setId(131);
        em5.persist(e4);
        commitTransaction(em5);
        closeEntityManager(em5);
        EntityManager em6 = createEntityManager();
        EntityManager em7 = createEntityManager();
        try {
            Employee emp2 = (Employee) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(e4);
            emp2.setFirstName("food");
            String expected = em6.find(Employee.class, 131).getFirstName();
            getEntityManagerFactory().getCache().evict(Employee.class);
            Employee e5 = em7.find(Employee.class, 131);
            String actual = e5.getFirstName();
            assertNotSame("Assertion Error", expected, actual);
        } finally {
            closeEntityManager(em6);
            closeEntityManager(em7);
        }
    }

    /**
     * Test of evictAll method, of class CacheImpl.
     */
    public void testEvictAll() {
        EntityManager em8 = createEntityManager();
        beginTransaction(em8);
        Employee e6 = new Employee();
        e6.setFirstName("ellie");
        e6.setId(141);
        Department d1 = new Department();
        d1.setId(3);
        d1.setName("Computers");
        em8.persist(d1);
        em8.persist(e6);
        commitTransaction(em8);
        String expectedEmp = e6.getFirstName();
        String expectedDept = d1.getName();
        closeEntityManager(em8);
        EntityManager em9 = createEntityManager();
        try {
            Employee emp3 = (Employee) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(e6);
            Department dept1 = (Department) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(d1);
            emp3.setFirstName("foo");
            dept1.setName("science");
            getEntityManagerFactory().getCache().evictAll();
            Employee e4 = em9.find(Employee.class, 141);
            String actualEmp = e4.getFirstName();
            Department d2 = em9.find(Department.class, 3);
            String actualDept = d2.getName();
            assertEquals("Assertion Error", expectedEmp, actualEmp);
            assertEquals("Assertion Error", expectedDept, actualDept);
        } finally {
            closeEntityManager(em9);
        }

    }

    public void testEvictContains() {
        EntityManager em =  createEntityManager();
        beginTransaction(em);
        Employee emp = new Employee();
        emp.setFirstName("evictContains");
        em.persist(emp);
        commitTransaction(em);

        try {
            assertTrue(em.getEntityManagerFactory().getCache().contains(Employee.class, emp.getId()));

            em.clear();
            Employee findEmp = em.find(Employee.class, emp.getId());
            assertNotNull(findEmp);

            em.getEntityManagerFactory().getCache().evict(Employee.class, emp.getId());
            assertFalse(em.getEntityManagerFactory().getCache().contains(Employee.class, emp.getId()));
        } finally {
            closeEntityManager(em);
        }
    }

    // for entity1-mappedSuperclass-entity2 we only have cache entries for entity1 and entity2
    // evict lowest 3nd level subclass of entity-mappedSuperclass-entity does not evict 1st level root entity
    //evict(Pads) will evict Pads but leave Chest and HockeyGear
    //evict(GoalieGear) will evict all Pads, Chest and HockeyGear
    //evict(HockeyGear) will evict all Pads, Chest and HockeyGear
    //(evict(MappedSuperclass:GoalieGear) and evict(Entity:HockeyGear) have the same effect)
    // evict middle 2nd level mappedSuperclass evicts 3rd level implementing entities but not 1st level root entity
    // evict 1st level root entity removes both 2nd level mappedSuperclasses and 3rd level implementing entities
    /**
     * In this test we attempt to remove the MappedSuperclass (superclass) from the entity cache.
     * The resulting action removes all implementing subclasses - which has the same effect
     * as just removing the implementing Entity in the first case.
     *
     * Hierarchy:
     * HockeyGear (Abstract Entity)
     *       +----- GoalieGear (Concrete MappedSuperclass) --- (we will evict this one)
     *                  +----- Chest Protector (Concrete Entity) ---- cacheable (but this will actually be evicted)
     *                  +----- Pads (Concrete Entity) ---- cacheable (as well as this one)
     */
    public void testEvictClass_MappedSuperclass_RemovesAssignableSubclasses() {
        if (! isJPA10()) {
            int ID_PADS = ID_TEST_BASE + 2100;
            int ID_CHESTPROTECTOR = ID_PADS++;
            final EntityManager em = createEntityManager();
            // Persist both implementing subclasses of GoalieGear
            beginTransaction(em);
            // HockeyGear(Abstract Entity) << GoalieGear (Concrete MappedSuperclass) << ChestProtector (Concrete Entity)
            ChestProtector e1 = new ChestProtector();
            e1.setDescription("chest_protector");
            e1.setSerialNumber(ID_PADS);
            em.persist(e1);
            commitTransaction(em);
            // do not close the entityManager between transactions or you will get bug# 307445

            beginTransaction(em);
            // HockeyGear(Abstract Entity) << GoalieGear (Concrete MappedSuperclass) << ChestProtector (Concrete Entity)
            Pads p1 = new Pads();
            p1.setDescription("pads");
            p1.setSerialNumber(ID_CHESTPROTECTOR);
            em.persist(p1);
            commitTransaction(em);
            closeEntityManager(em);

            EntityManager em1 = createEntityManager();
            EntityManager em2 = createEntityManager();
            try {
                ChestProtector e2 = (ChestProtector) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(e1);
                Pads p2 = (Pads) ((JpaEntityManagerFactory) getEntityManagerFactory())
                    .getServerSession().getIdentityMapAccessor().getFromIdentityMap(p1);
                // change the entity in the cache (only) - later a find() will get the unmodified version in the database
                e2.setDescription("new_chest_protector");
                p2.setDescription("new_pads");

                String expected_chestProtector = em1.find(GoalieGear.class, ID_CHESTPROTECTOR).getDescription();
                String expected_pads = em1.find(GoalieGear.class, ID_PADS).getDescription();

                // evict the inheriting entities via their MappedSuperclass (without referencing their ID)
                getEntityManagerFactory().getCache().evict(GoalieGear.class);

                // read the inheriting entities directly from the database (because they are no longer in the cache - hopefully)
                GoalieGear g5 = em2.find(GoalieGear.class, ID_CHESTPROTECTOR);
                GoalieGear p5 = em2.find(GoalieGear.class, ID_PADS);

                // check that the root entity is also evicted

                // Check that we are not actually getting the supposed "to be evicted" cached version (that was modified)
                String actual_chestProtector = g5.getDescription();
                String actual_pads = p5.getDescription();
                // verify that assignable subclasses (ChestProtector and Pads) are removed from the cache
                assertNotSame("Assertion Error - There should be no modified cached entity instance in the cache - the entity read from the database should be different. "
                    , expected_chestProtector, actual_chestProtector);
                assertNotSame("Assertion Error - There should be no modified cached entity instance in the cache - the entity read from the database should be different. "
                    , expected_pads, actual_pads);
            } finally {
                closeEntityManager(em1);
                closeEntityManager(em2);
            }
        }
    }

    /**
     * In this test we attempt to remove the Entity subclasses of a root (non-persistable) plain java class
     * from the entity cache.
     * The resulting action removes all implementing subclasses - which has the same effect
     * as just removing the root implementing Entity in the first case.
     *
     * Hierarchy:
     * Gear (non-entity/non-mappedSuperclass plain java class - with non-persistable state) - (we will evict this one)
     *    +-----HockeyGear (Abstract Entity) (not cacheable)
     *                +----- GoalieGear (Concrete MappedSuperclass) --- (no cache entry)
     *                              +----- Chest Protector (Concrete Entity) ---- cacheable (but this will actually be evicted)
     *                              +----- Pads (Concrete Entity) ---- cacheable (as well as this one)
     */
    public void testEvictClass_NonPersistableParentOfEntityMappedSuperclassChain_RemovesAssignableSubclasses() {
        if (! isJPA10()) {
            int ID_PADS = ID_TEST_BASE + 800;
            int ID_CHESTPROTECTOR = ID_PADS++;
            final EntityManager em = createEntityManager();
            // Persist both implementing subclasses of GoalieGear
            beginTransaction(em);
            // HockeyGear(Abstract Entity) << GoalieGear (Concrete MappedSuperclass) << ChestProtector (Concrete Entity)
            ChestProtector e1 = new ChestProtector();
            e1.setDescription("chest_protector");
            e1.setSerialNumber(ID_PADS);
            em.persist(e1);
            commitTransaction(em);
            // do not close the entityManager between transactions or you will get bug# 307445

            beginTransaction(em);
            // HockeyGear(Abstract Entity) << GoalieGear (Concrete MappedSuperclass) << ChestProtector (Concrete Entity)
            Pads p1 = new Pads();
            p1.setDescription("pads");
            p1.setSerialNumber(ID_CHESTPROTECTOR);
            em.persist(p1);
            commitTransaction(em);
            closeEntityManager(em);

            EntityManager em1 = createEntityManager();
            EntityManager em2 = createEntityManager();
            try {
                ChestProtector e2 = (ChestProtector) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(e1);
                Pads p2 = (Pads) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(p1);
                // change the entity in the cache (only) - later a find() will get the unmodified version in the database
                e2.setDescription("new_chest_protector");
                p2.setDescription("new_pads");

                String expected_chestProtector = em1.find(GoalieGear.class, ID_CHESTPROTECTOR).getDescription();
                String expected_pads = em1.find(GoalieGear.class, ID_PADS).getDescription();

                // evict the inheriting entities via their non-persistable root (without referencing their ID)
                getEntityManagerFactory().getCache().evict(Gear.class);

                // read the inheriting entities directly from the database (because they are no longer in the cache - hopefully)
                GoalieGear g5 = em2.find(GoalieGear.class, ID_CHESTPROTECTOR);
                GoalieGear p5 = em2.find(GoalieGear.class, ID_PADS);

                // check that the root entity is also evicted

                // Check that we are not actually getting the supposed "to be evicted" cached version (that was modified)
                String actual_chestProtector = g5.getDescription();
                String actual_pads = p5.getDescription();
                // verify that assignable subclasses (ChestProtector and Pads) are removed from the cache
                assertNotSame("Assertion Error - There should be no modified cached entity instance in the cache - the entity read from the database should be different. "
                    , expected_chestProtector, actual_chestProtector);
                assertNotSame("Assertion Error - There should be no modified cached entity instance in the cache - the entity read from the database should be different. "
                    , expected_pads, actual_pads);
            } finally {
                closeEntityManager(em1);
                closeEntityManager(em2);
            }
        }
    }

    /**
     * In this test we attempt to remove the (non-persistable) plain java class subclass of an Entity inheritance tree
     * from the entity cache.
     * The resulting action removes all implementing subclasses - which has the same effect
     * as just removing the root implementing Entity in the first case.
     *
     * Hierarchy:
     * Gear (non-entity/non-mappedSuperclass plain java class - with non-persistable state) - (we will evict this one)
     *    +-----HockeyGear (Abstract Entity) (not cacheable)
     *                +----- GoalieGear (Concrete MappedSuperclass) --- (no cache entry)
     *                              +----- Chest Protector (Concrete Entity) ---- cacheable (but this will actually be evicted)
     *                              +----- Pads (Concrete Entity) ---- cacheable (as well as this one)
     */
    public void testEvictClass_NonPersistableSubclassOfEntityMappedSuperclassChain_hasNoEffect() {
        if (! isJPA10()) {
            int ID_PADS = ID_TEST_BASE + 900;
            int ID_CHESTPROTECTOR = ID_PADS++;
            final EntityManager em = createEntityManager();
            // Persist both implementing subclasses of GoalieGear
            beginTransaction(em);
            // HockeyGear(Abstract Entity) << GoalieGear (Concrete MappedSuperclass) << ChestProtector (Concrete Entity)
            ChestProtector e1 = new ChestProtector();
            e1.setDescription("chest_protector");
            e1.setSerialNumber(ID_PADS);
            em.persist(e1);
            commitTransaction(em);
            // do not close the entityManager between transactions or you will get bug# 307445

            beginTransaction(em);
            // HockeyGear(Abstract Entity) << GoalieGear (Concrete MappedSuperclass) << ChestProtector (Concrete Entity)
            Pads p1 = new Pads();
            p1.setDescription("pads");
            p1.setSerialNumber(ID_CHESTPROTECTOR);
            em.persist(p1);
            commitTransaction(em);
            closeEntityManager(em);

            EntityManager em1 = createEntityManager();
            EntityManager em2 = createEntityManager();
            try {
                ChestProtector e2 = (ChestProtector) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(e1);
                Pads p2 = (Pads) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(p1);
                // change the entity in the cache (only) - later a find() will get the unmodified version in the database
                e2.setDescription("new_chest_protector");
                p2.setDescription("new_pads");

                String expected_chestProtector = em1.find(GoalieGear.class, ID_CHESTPROTECTOR).getDescription();
                String expected_pads = em1.find(GoalieGear.class, ID_PADS).getDescription();

                // evict the inheriting entities via their non-persistable root (without referencing their ID)
                getEntityManagerFactory().getCache().evict(NonPersistedSubclassOfChestProtector.class);
                //getEntityManagerFactory().getCache().evict(Pads.class);

                // read the inheriting entities directly from the cache (because they were not evicted)
                GoalieGear g5 = em2.find(GoalieGear.class, ID_CHESTPROTECTOR);
                GoalieGear p5 = em2.find(GoalieGear.class, ID_PADS);
                String actual_chestProtector = g5.getDescription();
                String actual_pads = p5.getDescription();
                assertSame("Assertion Error - There should be a modified cached entity instance in the cache - the entity is not actually read from the database"
                    , expected_pads, actual_pads);
                assertSame("Assertion Error - There should be a modified cached entity instance in the cache - the entity is not actually read from the database"
                    , expected_chestProtector, actual_chestProtector);
            } finally {
                closeEntityManager(em1);
                closeEntityManager(em2);
            }
        }
    }

    /**
     * In this test we attempt to remove the MappedSuperclass (superclass) from the entity cache.
     * The resulting action removes all implementing subclasses - which has the same effect
     * as just removing the implementing Entity in the first case.
     *
     * Hierarchy:
     * Gear (non-entity/non-mappedSuperclass plain java class - with non-persistable state) - (we will evict this one)
     *    +-----HockeyGear (Abstract Entity) (not cacheable)
     *                +----- GoalieGear (Concrete MappedSuperclass) --- (no cache entry)
     *                              +----- Chest Protector (Concrete Entity) ---- cacheable (but this will actually be evicted)
     *                              +----- Pads (Concrete Entity) ---- cacheable (as well as this one)
     */
    public void testEvictClassObject_MappedSuperclass_RemovesAssignableSubclasses() {
        if (! isJPA10()) {
            int ID_PADS = ID_TEST_BASE + 200;
            int ID_CHESTPROTECTOR = ID_PADS++;
            EntityManager em = createEntityManager();
            // Persist both implementing subclasses of GoalieGear
            beginTransaction(em);
            // HockeyGear(Abstract Entity) << GoalieGear (Concrete MappedSuperclass) << ChestProtector (Concrete Entity)
            ChestProtector e1 = new ChestProtector();
            e1.setDescription("chest_protector");
            e1.setSerialNumber(ID_PADS);
            em.persist(e1);
            commitTransaction(em);
            // do not close the entityManager between transactions or you will get bug# 307445

            beginTransaction(em);
            Pads p1 = new Pads();
            p1.setDescription("pads");
            p1.setSerialNumber(ID_CHESTPROTECTOR);
            em.persist(p1);
            commitTransaction(em);
            closeEntityManager(em);

            EntityManager em1 = createEntityManager();
            EntityManager em2 = createEntityManager();
            try {
                GoalieGear c2 = (GoalieGear) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(e1);
                Pads p2 = (Pads) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(p1);
                // change the entity in the cache (only) - later a find() will get the unmodified version in the database
                c2.setDescription("new_chest_protector");
                p2.setDescription("new_pads");
                String expected_chestProtector = em1.find(GoalieGear.class, ID_CHESTPROTECTOR).getDescription();
                String expected_pads = em1.find(GoalieGear.class, ID_PADS).getDescription();

                // evict the inheriting entity (by Id) via its' MappedSuperclass
                    getEntityManagerFactory().getCache().evict(GoalieGear.class, c2.getSerialNumber()); // ChestProtector
                    getEntityManagerFactory().getCache().evict(GoalieGear.class, p2.getSerialNumber()); // Pad

                // read the inheriting entities directly from the database (because they are no longer in the cache - hopefully)
                GoalieGear c5 = em2.find(GoalieGear.class, ID_CHESTPROTECTOR);
                GoalieGear p5 = em2.find(GoalieGear.class, ID_PADS);

                // Check that we are not actually getting the supposed "to be evicted" cached version (that was modified)
                String actual_chestProtector = c5.getDescription();
                String actual_pads = p5.getDescription();
                // verify that assignable subclasses (ChestProtector and Pads) are removed from the cache
                assertNotSame("Assertion Error - There should be no modified cached entity instance in the cache - the entity read from the database should be different. "
                    , expected_chestProtector, actual_chestProtector);
                assertNotSame("Assertion Error - There should be no modified cached entity instance in the cache - the entity read from the database should be different. "
                    , expected_pads, actual_pads);
            } finally {
                closeEntityManager(em1);
                closeEntityManager(em2);
            }
        }
    }


    //org.eclipse.persistence.testing.models.jpa.jpaadvancedproperties.Customer

    public void testEvictClass_JavaLangClass_hasNoEffect() {
        if (! isJPA10()) {
            int ID = ID_TEST_BASE + 300;
            boolean _exceptionThrown = false;
            EntityManager em = createEntityManager();
            // Persist
            beginTransaction(em);
            // HockeyGear(Abstract Entity) << GoalieGear (Concrete MappedSuperclass) << ChestProtector (Concrete Entity)
            ChestProtector e1 = new ChestProtector();
            e1.setDescription("gear");
            e1.setSerialNumber(ID);
            em.persist(e1);
            commitTransaction(em);
            closeEntityManager(em);

            EntityManager em1 = createEntityManager();
            EntityManager em2 = createEntityManager();
            try {
                GoalieGear e2 = (GoalieGear) getDatabaseSession().getIdentityMapAccessor().getFromIdentityMap(e1);
                // change the entity in the cache (only) - later a find() will get the unmodified version in the database
                e2.setDescription("new_gear");
                String expected = em1.find(GoalieGear.class, ID).getDescription();
                // The following does not throws an IAE on a plain java (Integer) class - it will leave the cached entities as-is in the cache
                // This evict exercises the else clause in the evict when the descriptor is null on the session
                getEntityManagerFactory().getCache().evict(Integer.class);
                // read the inheriting entities directly from the cache (because they were not evicted)
                GoalieGear g5 = em2.find(GoalieGear.class, ID);
                String actual = g5.getDescription();
                assertSame("Assertion Error - There should be a modified cached entity instance in the cache - the entity is not actually read from the database"
                    , expected, actual);
            } catch (IllegalArgumentException iae) {
                _exceptionThrown = true;
            } finally {
                closeEntityManager(em1);
                closeEntityManager(em2);
                assertFalse("IllegalArgumentException was thrown.", _exceptionThrown);
            }
        }
    }

    // The xml model version is not managed
    public void testGetId_fromUnmanagedMappedSuperclass_handles_null_descriptor() {
        if (!isJPA10()) {
            int ID = ID_TEST_BASE + 400;
            boolean _exceptionThrown = false;
            EntityManager em = createEntityManager();
            beginTransaction(em);
            // CacheableTrueMappedSuperclass (MappedSuperclass with Id) << SubCacheableFalseEntity (Entity)
            org.eclipse.persistence.testing.models.jpa.xml.cacheable.SubCacheableFalseEntity anEntity
                = new org.eclipse.persistence.testing.models.jpa.xml.cacheable.SubCacheableFalseEntity();
            org.eclipse.persistence.testing.models.jpa.xml.cacheable.CacheableTrueMappedSuperclass aMappedSuperclass
                = new org.eclipse.persistence.testing.models.jpa.xml.cacheable.CacheableTrueMappedSuperclass();
            anEntity.setId(ID);
            // Can we place non-persistable objects into only the cache (non-entities)?
            // We do not need to persist this entity for this specific test
            //em.persist(anEntity);
            commitTransaction(em);
            closeEntityManager(em);

            EntityManager em1 = createEntityManager();
            EntityManager em2 = createEntityManager();
            Cache aJPACache = getEntityManagerFactory().getCache();
            JpaCache anEclipseLinkCache = (JpaCache)getEntityManagerFactory().getCache();
            Object anId = null;
            try {
                anId = anEclipseLinkCache.getId(anEntity);
            } catch (IllegalArgumentException iae) {
                _exceptionThrown = true;
            } finally {
                closeEntityManager(em1);
                closeEntityManager(em2);
                assertTrue("IllegalArgumentException should have been thrown on the unmanaged entity lacking a descriptor.", _exceptionThrown);
            }
        }
    }

    public void testGetId_fromUnsupportedJavaLangInteger_throwsIAE_on_null_descriptor() {
        if (!isJPA10()) {
            boolean _exceptionThrown = false;
            EntityManager em1 = createEntityManager();
            JpaCache anEclipseLinkCache = (JpaCache)getEntityManagerFactory().getCache();
            try {
                anEclipseLinkCache.getId(1);
            } catch (IllegalArgumentException iae) {
                _exceptionThrown = true;
            } finally {
                closeEntityManager(em1);
                assertTrue("IllegalArgumentException should have been thrown on a getId() call on an Integer which obviously has no descriptor.", _exceptionThrown);
            }
        }
    }

    /**
     * In order to test handling of a null CMP3Policy on the descriptor during a cache.getId() call,
     * we must have an Id on an abstract MappedSuperclass root that is defined via sessions.xml.
     * Or we can simulate a null CMP3Policy by clearing it - so that the alternate code handling is run
     */
    public void testGetId_fromNativeMappedSuperclass_handles_null_cmp3policy_weaving_on() {
        if (!isJPA10()) {
            int ID = ID_TEST_BASE + 500;
            Object originalId = null;
            EntityManager em = createEntityManager();//);
            // Persist both implementing subclasses of GoalieGear
            beginTransaction(em);
            // CacheableTrueMappedSuperclass (MappedSuperclass with Id) << SubCacheableFalseEntity (Entity)
            org.eclipse.persistence.testing.models.jpa.cacheable.SubCacheableFalseEntity anEntity = new org.eclipse.persistence.testing.models.jpa.cacheable.SubCacheableFalseEntity();
            org.eclipse.persistence.testing.models.jpa.cacheable.CacheableTrueMappedSuperclass aMappedSuperclass = new org.eclipse.persistence.testing.models.jpa.cacheable.CacheableTrueMappedSuperclass();
            anEntity.setId(ID);
            // Can we place non-persistable objects into only the cache (non-entities)?
            em.persist(anEntity);
            commitTransaction(em);
            closeEntityManager(em);

            EntityManager em1 = createEntityManager();
            JpaCache anEclipseLinkCache = (JpaCache)getEntityManagerFactory().getCache();
            Object anId = null;
            originalId = anEntity.getId();

            // clear the CMP3Policy to simulate a native pojo
            ClassDescriptor cdesc = ((EntityManagerImpl)em1).getSession().getClassDescriptor(anEntity.getClass());
            CMP3Policy policy = (CMP3Policy) (cdesc.getCMPPolicy());
            assertNotNull("CMP3Policy should exist", policy);
            cdesc.setCMPPolicy(null);
            try {
                // This call will test the weaving [on] section of getId()
                anId = anEclipseLinkCache.getId(anEntity);
                assertNotNull("Id instance should not be null", anId);
                assertTrue("Id instance should be of type Integer", anId instanceof Integer);
                assertEquals(((Integer)anId).intValue(), ID);
                assertEquals(anId, originalId);
            } finally {
                cdesc.setCMPPolicy(policy);
                closeEntityManager(em1);
            }
        }
    }

    public void testGetId_fromNativeMappedSuperclass_handles_null_cmp3policy_and_null_pk_with_weaving_on() {
        if (!isJPA10()) {
            //int ID = ID_TEST_BASE + 600;
            Integer ID = null; // keep object as null for unset testing
            Object originalId = null;
            EntityManager em = createEntityManager(METAMODEL_PERSISTENCE_UNIT);
            beginTransaction(em);
            // org.eclipse.persistence.testing.models.jpa.metamodel.Person(Concrete MappedSuperclass) <-- Corporation(Abstract MappedSuperclass) <-- Manufacturer (Entity)
            Manufacturer anEntity = new Manufacturer();
            //anEntity.setId(ID);
            // Can we place non-persistable objects into only the cache (non-entities)?
            em.persist(anEntity);
            commitTransaction(em);
            closeEntityManager(em);

            EntityManager em1 = createEntityManager(METAMODEL_PERSISTENCE_UNIT);
            JpaCache anEclipseLinkCache = (JpaCache)getEntityManagerFactory(METAMODEL_PERSISTENCE_UNIT).getCache();
            Object anId = null;
            // The originalId will be set by automatic sequence generation - if we require it
            originalId = anEntity.getId();

            // clear the CMP3Policy to simulate a native pojo
            ClassDescriptor cdesc = ((EntityManagerImpl)em1).getSession().getClassDescriptor(anEntity.getClass());
            CMP3Policy policy = (CMP3Policy) (cdesc.getCMPPolicy());
            assertNotNull("CMP3Policy should exist prior to having been cleared manually for this test", policy);
            cdesc.setCMPPolicy(null);
            try {
                anId = anEclipseLinkCache.getId(anEntity);
                assertNotNull("Id instance should not be null", anId);
                assertTrue("Id instance should be of type Integer", anId instanceof Integer);
                assertEquals(anId, originalId);
            } finally {
                // set the CMPPolicy back for out of order testing
                cdesc.setCMPPolicy(policy);
                closeEntityManager(em1);
            }
        }
    }

    // We need a MappedSuperclass that is defined by a persistence.xml where eclipselink.weaving="false"
    // This test requires that weaving is off in persistence.xml for METAMODEL_PERSISTENCE_UNIT
    public void testGetId_fromNativeMappedSuperclass_handles_null_cmp3policy_and_null_pk_with_weaving_off() {
        if (!isJPA10()) {
            int ID = ID_TEST_BASE + 700;
            //Integer ID = null; // keep object as null for unset testing
            Object originalId = null;
            EntityManager em = createEntityManager(METAMODEL_PERSISTENCE_UNIT);
            beginTransaction(em);
            Manufacturer anEntity = new Manufacturer();
            anEntity.setName("test");
            anEntity.setId(ID);
            // Can we place non-persistable objects into only the cache (non-entities)?
            em.persist(anEntity);
            commitTransaction(em);
            //closeEntityManager(em); // keep the EM open

            EntityManager em1 = createEntityManager(METAMODEL_PERSISTENCE_UNIT);
            JpaCache anEclipseLinkCache = (JpaCache)getEntityManagerFactory(METAMODEL_PERSISTENCE_UNIT).getCache();
            Object anId = null;
            // The originalId will be set by automatic sequence generation - if we require it
            originalId = anEntity.getId();

            // clear the CMP3Policy to simulate a native pojo
            ClassDescriptor cdesc = ((EntityManagerImpl)em).getSession().getClassDescriptor(anEntity.getClass());
            assertNotNull("ClassDescriptor for Entity must not be null", cdesc); // check that the entityManager is not null
            CMP3Policy policy = (CMP3Policy) (cdesc.getCMPPolicy());
            assertNotNull("CMP3Policy should exist prior to having been cleared manually for this test", policy);
            cdesc.setCMPPolicy(null);
            try {
                anId = anEclipseLinkCache.getId(anEntity);
                assertNotNull("Id instance should not be null", anId);
                assertTrue("Id instance should be of type Integer", anId instanceof Integer);
                assertEquals(anId, ID);
                assertEquals(anId, originalId);
            } finally {
             // set the CMPPolicy back for out of order testing
                cdesc.setCMPPolicy(policy);
                closeEntityManager(em1);
                closeEntityManager(em);
            }
        }
    }

    // 20100422: 248780: CacheImpl refactor for non-Entity classes
    public static int ID_TEST_BASE = 3710; // change this value during iterative testing
}
