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

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     06/20/2008-1.0 Guy Pelletier
//       - 232975: Failure when attribute type is generic
//     09/23/2008-1.1 Guy Pelletier
//       - 241651: JPA 2.0 Access Type support
//     01/28/2009-2.0 Guy Pelletier
//       - 248293: JPA 2.0 Element Collections (part 1)
//     02/06/2009-2.0 Guy Pelletier
//       - 248293: JPA 2.0 Element Collections (part 2)
//     03/27/2009-2.0 Guy Pelletier
//       - 241413: JPA 2.0 Add EclipseLink support for Map type attributes
//     04/03/2009-2.0 Guy Pelletier
//       - 241413: JPA 2.0 Add EclipseLink support for Map type attributes
//     06/02/2009-2.0 Guy Pelletier
//       - 278768: JPA 2.0 Association Override Join Table
//     06/09/2009-2.0 Guy Pelletier
//       - 249037: JPA 2.0 persisting list item index
//     02/18/2010-2.0.2 Guy Pelletier
//       - 294803: @Column(updatable=false) has no effect on @Basic mappings
//     06/18/2010-2.2 Guy Pelletier
//       - 300458: EclispeLink should throw a more specific exception than NPE
//     07/16/2010-2.2 Guy Pelletier
//       - 260296: mixed access with no Transient annotation does not result in error
package org.eclipse.persistence.testing.tests.jpa.inherited;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;

import junit.framework.*;

import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.weaving.PersistenceWeaved;
import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.sessions.CopyGroup;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.models.jpa.inherited.Accredidation;
import org.eclipse.persistence.testing.models.jpa.inherited.Becks;
import org.eclipse.persistence.testing.models.jpa.inherited.BecksTag;
import org.eclipse.persistence.testing.models.jpa.inherited.BeerConsumer;
import org.eclipse.persistence.testing.models.jpa.inherited.Birthday;
import org.eclipse.persistence.testing.models.jpa.inherited.Blue;
import org.eclipse.persistence.testing.models.jpa.inherited.Alpine;
import org.eclipse.persistence.testing.models.jpa.inherited.BlueLight;
import org.eclipse.persistence.testing.models.jpa.inherited.Bluish;
import org.eclipse.persistence.testing.models.jpa.inherited.BuildingBylaw;
import org.eclipse.persistence.testing.models.jpa.inherited.Committee;
import org.eclipse.persistence.testing.models.jpa.inherited.CommitteeDates;
import org.eclipse.persistence.testing.models.jpa.inherited.Corona;
import org.eclipse.persistence.testing.models.jpa.inherited.CoronaTag;
import org.eclipse.persistence.testing.models.jpa.inherited.ExpertBeerConsumer;
import org.eclipse.persistence.testing.models.jpa.inherited.Heineken;
import org.eclipse.persistence.testing.models.jpa.inherited.InheritedTableManager;
import org.eclipse.persistence.testing.models.jpa.inherited.Location;
import org.eclipse.persistence.testing.models.jpa.inherited.NodeImpl;
import org.eclipse.persistence.testing.models.jpa.inherited.NoiseBylaw;
import org.eclipse.persistence.testing.models.jpa.inherited.NoviceBeerConsumer;
import org.eclipse.persistence.testing.models.jpa.inherited.Official;
import org.eclipse.persistence.testing.models.jpa.inherited.OfficialEntry;
import org.eclipse.persistence.testing.models.jpa.inherited.Record;
import org.eclipse.persistence.testing.models.jpa.inherited.RedStripe;
import org.eclipse.persistence.testing.models.jpa.inherited.SerialNumber;
import org.eclipse.persistence.testing.models.jpa.inherited.Venue;
import org.eclipse.persistence.testing.models.jpa.inherited.Witness;
import org.eclipse.persistence.testing.models.jpa.inherited.ServiceTime;

public class InheritedModelJunitTest extends JUnitTestCase {
    private static BigDecimal m_blueId;
    private static Integer m_beerConsumerId;
    private static Integer m_noviceBeerConsumerId;
    private static Integer m_expertBeerConsumerId;

    private static Timestamp m_quote1Stamp;
    private static final String QUOTE_ONE = "Beer is blood";
    private static Timestamp m_quote2Stamp;
    private static final String QUOTE_TWO = "My first wife was a beer";

    public InheritedModelJunitTest() {
        super();
    }

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

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

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

        suite.addTest(new InheritedModelJunitTest("testSetup"));
        suite.addTest(new InheritedModelJunitTest("testCreateBlue"));
        suite.addTest(new InheritedModelJunitTest("testReadBlue"));
        suite.addTest(new InheritedModelJunitTest("testCreateBeerConsumer"));
        suite.addTest(new InheritedModelJunitTest("testCreateNoviceBeerConsumer"));
        suite.addTest(new InheritedModelJunitTest("testReadNoviceBeerConsumer"));
        suite.addTest(new InheritedModelJunitTest("testOrderColumnNoviceBeerConsumerDesignations"));
        suite.addTest(new InheritedModelJunitTest("testCreateExpertBeerConsumer"));
        suite.addTest(new InheritedModelJunitTest("testDeleteMiddleRecordOfExpertBeerConsumer"));
        suite.addTest(new InheritedModelJunitTest("testReadExpertBeerConsumer"));
        suite.addTest(new InheritedModelJunitTest("testExpertBeerConsumerRecordsCRUD"));
        suite.addTest(new InheritedModelJunitTest("testUpdateBeerConsumer"));
        suite.addTest(new InheritedModelJunitTest("testInheritedClone"));
        suite.addTest(new InheritedModelJunitTest("testCascadeRemove"));
        // 1-M map using direct key
        suite.addTest(new InheritedModelJunitTest("testHeinekenBeerConsumer"));
        // 1-M map using entity key
        suite.addTest(new InheritedModelJunitTest("testBecksBeerConsumer"));
        // 1-M map using embeddable key
        suite.addTest(new InheritedModelJunitTest("testCoronaBeerConsumer"));
        // Element collection with generic map key type, with embeddable values.
        suite.addTest(new InheritedModelJunitTest("testRedStripeExpertConsumer"));
        // Element collection with generic map key type, with embeddable values.
        suite.addTest(new InheritedModelJunitTest("testRedStripeNoviceConsumer"));
        // OrderColumn with OrderCorrectionType.EXCEPTION
        suite.addTest(new InheritedModelJunitTest("testBreakOrder_CorrectionType_EXCEPTION"));
        // OrderColumn with OrderCorrectionType.READ_WRITE
        suite.addTest(new InheritedModelJunitTest("testBreakOrder_CorrectionType_READ_WRITE"));

        suite.addTest(new InheritedModelJunitTest("testMapOrphanRemoval"));

        suite.addTest(new InheritedModelJunitTest("testSerializedElementCollectionMap"));
        suite.addTest(new InheritedModelJunitTest("testVersionUpdateOnElementCollectionChange"));

        suite.addTest(new InheritedModelJunitTest("testAddToHeinekenBeerConsumerMap"));
        suite.addTest(new InheritedModelJunitTest("testColumnUpdatableAndInsertable"));
        suite.addTest(new InheritedModelJunitTest("testColumnUpdatableAndInsertableThroughQuery"));
        suite.addTest(new InheritedModelJunitTest("testElementCollectionMapEmbeddable"));
        suite.addTest(new InheritedModelJunitTest("testMultipleIdButNonIdClassEntity"));
        suite.addTest(new InheritedModelJunitTest("testRelatedBylawWrite"));
        suite.addTest(new InheritedModelJunitTest("testInterfaceBylawWrite"));
        suite.addTest(new InheritedModelJunitTest("testEmbeddableAggregateCollectionAndAggregate"));
        suite.addTest(new InheritedModelJunitTest("testNodeImplWeaving"));
        suite.addTest(new InheritedModelJunitTest("testEmbeddaleCollectionMapEmbeddableRead"));
        suite.addTest(new InheritedModelJunitTest("testCopyMapKeyMap"));
        if (!isJPA10()) {
            suite.addTest(new InheritedModelJunitTest("testInterfaces"));
        }

        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 InheritedTableManager().replaceTables(JUnitTestCase.getServerSession());
        clearCache();
    }

    public void  testMultipleIdButNonIdClassEntity() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        NoiseBylaw noiseBylaw = new NoiseBylaw();
        int noiseBylawId = 0;
        BuildingBylaw buildingBylaw = new BuildingBylaw();
        int buildingBylawId = 0;

        try {
            noiseBylaw.setCity("Ottawa");
            noiseBylaw.setDescription("Can't mow your grass after 9PM!");
            em.persist(noiseBylaw);

            buildingBylaw.setCity("Ottawa");
            buildingBylaw.setDescription("Can't build without a permit");
            em.persist(buildingBylaw);

            noiseBylawId = noiseBylaw.getNumber();
            buildingBylawId = buildingBylaw.getNumber();

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

            closeEntityManager(em);
            fail("An exception was caught during create operation: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);

        clearCache();
        em = createEntityManager();

        // find by object entity will not work since there is no IdClass in
        // this case so we will look it up through jpql
        String jpqlString = "SELECT n FROM NoiseBylaw n WHERE n.number =" + noiseBylawId;
        NoiseBylaw refreshedNoiseBylaw = (NoiseBylaw) em.createQuery(jpqlString).getSingleResult();
        assertTrue("The noise bylaw read back did not match the original", getServerSession().compareObjects(noiseBylaw, refreshedNoiseBylaw));

        String jpqlString2 = "SELECT n FROM BuildingBylaw n WHERE n.number =" + buildingBylawId;
        BuildingBylaw refreshedBuildingBylaw = (BuildingBylaw) em.createQuery(jpqlString2).getSingleResult();
        assertTrue("The building bylaw read back did not match the original", getServerSession().compareObjects(buildingBylaw, refreshedBuildingBylaw));

        closeEntityManager(em);
    }

    public void testBecksBeerConsumer() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        BeerConsumer initialBC = new BeerConsumer();
        int beerConsumerId = 0;

        try {
            Becks becks1  = new Becks();
            becks1.setAlcoholContent(5.1);
            BecksTag becksTag1 = new BecksTag();
            becksTag1.setCallNumber("0A.789");
            em.persist(becksTag1);

            Becks becks2  = new Becks();
            becks2.setAlcoholContent(5.1);
            BecksTag becksTag2 = new BecksTag();
            becksTag2.setCallNumber("BX.521");
            em.persist(becksTag2);

            Becks becks3  = new Becks();
            becks3.setAlcoholContent(5.1);
            BecksTag becksTag3 = new BecksTag();
            becksTag3.setCallNumber("UY.429");
            em.persist(becksTag3);

            initialBC.setName("Becks Consumer");
            initialBC.addBecksBeerToConsume(becks1, becksTag1);
            initialBC.addBecksBeerToConsume(becks2, becksTag2);
            initialBC.addBecksBeerToConsume(becks3, becksTag3);

            em.persist(initialBC);
            beerConsumerId = initialBC.getId();

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

            closeEntityManager(em);
            fail("An exception was caught during create operation: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);

        clearCache();
        em = createEntityManager();
        BeerConsumer refreshedBC = em.find(BeerConsumer.class, beerConsumerId);
        assertTrue("The beer consumer read back did not match the original", getServerSession().compareObjects(initialBC, refreshedBC));
    }

    public void testCoronaBeerConsumer() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        BeerConsumer initialBC = new BeerConsumer();
        int beerConsumerId = 0;

        try {
            Corona corona1  = new Corona();
            corona1.setAlcoholContent(5.3);
            CoronaTag coronaTag1 = new CoronaTag();
            coronaTag1.setCode("0A");
            coronaTag1.setNumber(789);

            Corona corona2  = new Corona();
            corona2.setAlcoholContent(5.3);
            CoronaTag coronaTag2 = new CoronaTag();
            coronaTag2.setCode("BX");
            coronaTag2.setNumber(521);

            Corona corona3  = new Corona();
            corona3.setAlcoholContent(5.3);
            CoronaTag coronaTag3 = new CoronaTag();
            coronaTag3.setCode("UY");
            coronaTag3.setNumber(429);

            initialBC.setName("Corona Consumer");
            initialBC.addCoronaBeerToConsume(corona1, coronaTag1);
            initialBC.addCoronaBeerToConsume(corona2, coronaTag2);
            initialBC.addCoronaBeerToConsume(corona3, coronaTag3);

            em.persist(initialBC);
            beerConsumerId = initialBC.getId();

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

            closeEntityManager(em);
            fail("An exception was caught during create operation: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);

        clearCache();
        em = createEntityManager();
        BeerConsumer refreshedBC = em.find(BeerConsumer.class, beerConsumerId);
        assertTrue("The beer consumer read back did not match the original", getServerSession().compareObjects(initialBC, refreshedBC));
    }

    public void testCreateBlue() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        try {
            Blue blue = new Blue();
            blue.setAlcoholContent(Float.valueOf(5.3f));
            em.persist(blue);
            m_blueId = blue.getId();
            blue.setUniqueKey(m_blueId.toBigInteger());
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            throw e;
        }

        closeEntityManager(em);
    }

    public void testOrderColumnNoviceBeerConsumerDesignations() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        NoviceBeerConsumer beerConsumer;

        try {
            // These are the designations we have right now ...
            // index: 0 - 1 - 2 - 3 - 4
            //  item: 5 - 4 - 2 - 3 - 1
           beerConsumer = em.find(NoviceBeerConsumer.class, m_noviceBeerConsumerId);

            //String stringFour = beerConsumer.getDesignations().remove(1);
            //String stringTwo = beerConsumer.getDesignations().remove(1);
           //beerConsumer.getDesignations().add(stringTwo);

            // This is what we have done
            // index: 0 - 1 - 2 - 3
            //  item: 5 - 3 - 1 - 2

            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            throw e;
        }

        closeEntityManager(em);

        clearCache();
        em = createEntityManager();
        BeerConsumer refreshedBC = em.find(BeerConsumer.class, m_noviceBeerConsumerId);
        assertTrue("The novice beer consumer read back did not match the original", getServerSession().compareObjects(beerConsumer, refreshedBC));
    }

    public void testReadBlue() {
        Blue blue = createEntityManager().find(Blue.class, m_blueId);
        assertTrue("Error on reading back a Blue beer", blue != null);
    }

    public void testCreateBeerConsumer() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        try {
            BeerConsumer beerConsumer = new BeerConsumer();
            beerConsumer.setName("Blue Consumer");
            em.persist(beerConsumer);
            m_beerConsumerId = beerConsumer.getId();
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }

            closeEntityManager(em);
            fail("An exception was caught during create operation: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);
    }

    public void testCreateNoviceBeerConsumer() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        NoviceBeerConsumer beerConsumer = new NoviceBeerConsumer();

        try {
            beerConsumer.setName("Novice Beer Consumer");
            beerConsumer.setIQ(100);

            beerConsumer.getAcclaims().add(1);
            beerConsumer.getAcclaims().add(2);
            beerConsumer.getAcclaims().add(3);

            beerConsumer.getAwards().put(1, 1);
            beerConsumer.getAwards().put(2, 2);
            beerConsumer.getAwards().put(3, 3);

            beerConsumer.getDesignations().add("5");
            beerConsumer.getDesignations().add("4");
            beerConsumer.getDesignations().add("2");
            beerConsumer.getDesignations().add("3");
            beerConsumer.getDesignations().add("1");

            Record record1 = new Record();
            record1.setDescription("Slowest beer ever consumed - 10 hours");
            record1.setDate(Helper.dateFromYearMonthDate(2008, 1, 1));
            record1.setLocation(new Location("Paris", "France"));
            Venue venue1 = new Venue();
            venue1.setAttendance(10);
            venue1.setName("Champs-Elysees");
            record1.setVenue(venue1);
            beerConsumer.getRecords().add(record1);

            Accredidation accredidation = new Accredidation();
            accredidation.setDetails("Superb, just superb!");
            Witness witness1 = new Witness();
            witness1.setName("Mickey Blue Eyes");
            accredidation.addWitness(witness1);
            Witness witness2 = new Witness();
            witness2.setName("Donny Trafalgo");
            accredidation.addWitness(witness2);
            beerConsumer.setAccredidation(accredidation);

            Committee committee1 = new Committee();
            committee1.setDescription("Moral labelling");
            beerConsumer.addCommittee(committee1);

            Committee committee2 = new Committee();
            committee2.setDescription("Crimes against beer");
            beerConsumer.addCommittee(committee2);

            Committee committee3 = new Committee();
            committee3.setDescription("BADD - Beers against drunk dorks");
            beerConsumer.addCommittee(committee3);

            em.persist(beerConsumer);
            m_noviceBeerConsumerId = beerConsumer.getId();
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }

            closeEntityManager(em);
            fail("An exception was caught during create operation for a novice beer consumer: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);

        clearCache();
        em = createEntityManager();
        BeerConsumer refreshedBC = em.find(BeerConsumer.class, m_noviceBeerConsumerId);
        assertTrue("The novice beer consumer read back did not match the original", getServerSession().compareObjects(beerConsumer, refreshedBC));
    }

    public void testCreateExpertBeerConsumer() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        ExpertBeerConsumer beerConsumer = new ExpertBeerConsumer();

        try {
            beerConsumer.setName("Expert Beer Consumer");
            beerConsumer.setIQ(110);

            beerConsumer.getAcclaims().add("A");
            beerConsumer.getAcclaims().add("B");
            beerConsumer.getAcclaims().add("C");

            // Commenting out this mapping until bug 272298 is resolved.
            // The compareObjects check below would fail in some configurations
            // as a result of this.
            //beerConsumer.getAudio().add(new byte[]{1});
            //beerConsumer.getAudio().add(new byte[]{2});
            //beerConsumer.getAudio().add(new byte[]{3});

            beerConsumer.getAwards().put("A", "A");
            beerConsumer.getAwards().put("B", "B");
            beerConsumer.getAwards().put("C", "C");

            beerConsumer.getDesignations().add("A");
            beerConsumer.getDesignations().add("B");

            m_quote1Stamp = Helper.timestampFromDate(Helper.dateFromYearMonthDate(2009, 1, 1));
            beerConsumer.getQuotes().put(m_quote1Stamp, QUOTE_ONE);
            m_quote2Stamp = Helper.timestampFromDate(Helper.dateFromYearMonthDate(2005, 7, 9));
            beerConsumer.getQuotes().put(m_quote2Stamp, QUOTE_TWO);

            Record record1 = new Record();
            record1.setDescription("Fastest beer ever consumed - 10 ms");
            record1.setDate(Helper.dateFromYearMonthDate(2009, 10, 10));
            record1.setLocation(new Location("Ottawa", "Canada"));
            Venue venue1 = new Venue();
            venue1.setAttendance(10000);
            venue1.setName("Scotiabank PLace");
            record1.setVenue(venue1);
            beerConsumer.getRecords().add(record1);

            Record record2 = new Record();
            record2.setDescription("Most beers consumed upside down - 12");
            record2.setDate(Helper.dateFromYearMonthDate(2007, 11, 11));
            record2.setLocation(new Location("Sydney", "Australia"));
            Venue venue2 = new Venue();
            venue2.setAttendance(2678);
            venue2.setName("Opera House");
            record2.setVenue(venue2);
            beerConsumer.getRecords().add(record2);

            Record record3 = new Record();
            record3.setDescription("Most beers consumed in a second - 5");
            record3.setDate(Helper.dateFromYearMonthDate(2005, 12, 12));
            record3.setLocation(new Location("Miami", "USA"));
            Venue venue3 = new Venue();
            venue3.setAttendance(63000);
            venue3.setName("Dolphin Stadium");
            record3.setVenue(venue3);
            beerConsumer.getRecords().add(record3);

            Accredidation accredidation = new Accredidation();
            accredidation.setDetails("Elite, absolutely elite!");
            Witness witness1 = new Witness();
            witness1.setName("Big Bobby");
            accredidation.addWitness(witness1);
            Witness witness2 = new Witness();
            witness2.setName("Little Bobby");
            accredidation.addWitness(witness2);
            Official official = new Official();
            official.setName("Authority Joe");
            accredidation.addOfficial(official);
            beerConsumer.setAccredidation(accredidation);

            Birthday birthday1 = new Birthday();
            birthday1.setDay(9);
            birthday1.setMonth(7);
            birthday1.setYear(2005);
            beerConsumer.addCelebration(birthday1, "Drank a 24 of Heineken");

            Birthday birthday2 = new Birthday();
            birthday2.setDay(10);
            birthday2.setMonth(7);
            birthday2.setYear(2006);
            beerConsumer.addCelebration(birthday2, "Drank a 24 of Becks");

            Committee committee1 = new Committee();
            committee1.setDescription("New beer committee");
            CommitteeDates committee1Dates = new CommitteeDates();
            committee1Dates.setStartDate("Jan 1, 2010");
            committee1.setCommitteeDates(committee1Dates);
            beerConsumer.addCommittee(committee1);

            Committee committee2 = new Committee();
            committee2.setDescription("Alcohol content regulation");
            CommitteeDates committee2Dates = new CommitteeDates();
            committee2Dates.setStartDate("Jan 1, 1970");
            committee2Dates.setEndDate("Jan 1, 2001");
            committee2.setCommitteeDates(committee2Dates);
            beerConsumer.addCommittee(committee2);

            em.persist(beerConsumer);
            m_expertBeerConsumerId = beerConsumer.getId();
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }

            closeEntityManager(em);
            fail("An exception was caught during create operation for an expert beer consumer: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);

        clearCache();
        em = createEntityManager();
        BeerConsumer refreshedBC = em.find(BeerConsumer.class, m_expertBeerConsumerId);
        assertTrue("The expert beer consumer read back did not match the original", getServerSession().compareObjects(beerConsumer, refreshedBC));
    }

    public void testDeleteMiddleRecordOfExpertBeerConsumer() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        try {
            ExpertBeerConsumer beerConsumer = em.find(ExpertBeerConsumer.class, m_expertBeerConsumerId);
            beerConsumer.getRecords().remove(1);
            commitTransaction(em);
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            clearCache();
        }
    }

    public void testHeinekenBeerConsumer() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        BeerConsumer initialBC = new BeerConsumer();
        int beerConsumerId = 0;

        try {
            Heineken heineken1  = new Heineken();
            heineken1.setAlcoholContent(5.0);

            Heineken heineken2  = new Heineken();
            heineken2.setAlcoholContent(5.0);

            Heineken heineken3  = new Heineken();
            heineken3.setAlcoholContent(5.0);

            initialBC.setName("Heineken Consumer");
            Calendar cal = Calendar.getInstance();
            cal.set(2008, 12, 12);
            initialBC.addHeinekenBeerToConsume(heineken1, cal.getTime());
            cal.set(2009, 1, 1);
            initialBC.addHeinekenBeerToConsume(heineken2, cal.getTime());
            cal.set(2009, 2, 2);
            initialBC.addHeinekenBeerToConsume(heineken3, cal.getTime());

            em.persist(initialBC);
            beerConsumerId = initialBC.getId();

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

            closeEntityManager(em);
            fail("An exception was caught during create operation: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);

        clearCache();
        em = createEntityManager();
        BeerConsumer refreshedBC = em.find(BeerConsumer.class, beerConsumerId);
        assertTrue("The beer consumer read back did not match the original", getServerSession().compareObjects(initialBC, refreshedBC));
    }

    public void testReadNoviceBeerConsumer() {
        NoviceBeerConsumer consumer = createEntityManager().find(NoviceBeerConsumer.class, m_noviceBeerConsumerId);

        assertTrue("Error on reading back a NoviceBeerConsumer", consumer != null);

        assertTrue("IQ Level was not persisted.", consumer.getIQ() == 100);

        assertTrue("Incorrect number of acclaims returned.", consumer.getAcclaims().size() == 3);
        assertTrue("Missing acclaim - 1", consumer.getAcclaims().contains(1));
        assertTrue("Missing acclaim - 2", consumer.getAcclaims().contains(2));
        assertTrue("Missing acclaim - 3", consumer.getAcclaims().contains(3));

        assertTrue("Incorrect number of awards returned.", consumer.getAwards().size() == 3);
        Integer awardCode = consumer.getAwards().get(1);
        assertFalse("Missing award code - 1", awardCode == null);
        assertTrue("Award code 1 is incorrect", awardCode.equals(1));

        awardCode = consumer.getAwards().get(2);
        assertFalse("Missing award code - 2", awardCode == null);
        assertTrue("Award code 2 is incorrect", awardCode.equals(2));

        awardCode = consumer.getAwards().get(3);
        assertFalse("Missing award code - 3", awardCode == null);
        assertTrue("Award code 3 is incorrect", awardCode.equals(3));

        assertTrue("Incorrect number of designations returned.", consumer.getDesignations().size() == 5);
        assertTrue("Missing designation - 5 at index 0", consumer.getDesignations().get(0).equals("5"));
        assertTrue("Missing designation - 4 at index 1", consumer.getDesignations().get(1).equals("4"));
        assertTrue("Missing designation - 2 at index 2", consumer.getDesignations().get(2).equals("2"));
        assertTrue("Missing designation - 3 at index 3", consumer.getDesignations().get(3).equals("3"));
        assertTrue("Missing designation - 1 at index 4", consumer.getDesignations().get(4).equals("1"));

        assertTrue("Incorrect number of records returned.", consumer.getRecords().size() == 1);
    }

    public void testReadExpertBeerConsumer() {
        ExpertBeerConsumer consumer = createEntityManager().find(ExpertBeerConsumer.class, m_expertBeerConsumerId);

        assertTrue("Error on reading back an ExpertBeerConsumer", consumer != null);

        assertTrue("IQ Level was not persisted.", consumer.getIQ() == 110);

        assertTrue("Incorrect number of acclaims returned.", consumer.getAcclaims().size() == 3);
        assertTrue("Missing acclaim - A", consumer.getAcclaims().contains("A"));
        assertTrue("Missing acclaim - B", consumer.getAcclaims().contains("B"));
        assertTrue("Missing acclaim - C", consumer.getAcclaims().contains("C"));

        //assertTrue("Incorrect number of audio returned.", consumer.getAudio().size() == 3);
        // don't individually check them, assume they are correct.

        assertTrue("Incorrect number of awards returned.", consumer.getAwards().size() == 3);
        String awardCode = consumer.getAwards().get("A");
        assertFalse("Missing award code - A", awardCode == null);
        assertTrue("Award code A is incorrect", awardCode.equals("A"));

        awardCode = consumer.getAwards().get("B");
        assertFalse("Missing award code - B", awardCode == null);
        assertTrue("Award code B is incorrect", awardCode.equals("B"));

        awardCode = consumer.getAwards().get("C");
        assertFalse("Missing award code - C", awardCode == null);
        assertTrue("Award code C is incorrect", awardCode.equals("C"));

        assertTrue("Incorrect number of designations returned.", consumer.getDesignations().size() == 2);
        assertTrue("Missing designation - A", consumer.getDesignations().contains("A"));
        assertTrue("Missing designation - B", consumer.getDesignations().contains("B"));

        assertTrue("Incorrect number of quotes returned.", consumer.getQuotes().size() == 2);
        String quote = consumer.getQuotes().get(m_quote1Stamp);
        assertFalse("Missing quote from Jan 1, 2009", quote == null);
        assertTrue("Quote from Jan 1, 2009 was incorrect", quote.equals(QUOTE_ONE));

        quote = consumer.getQuotes().get(m_quote2Stamp);
        assertFalse("Missing quote from Jul 9, 2005", quote == null);
        assertTrue("Quote from Jul 9, 2005 was incorrect", quote.equals(QUOTE_TWO));

        assertTrue("Incorrect number of records returned.", consumer.getRecords().size() == 2);
        assertTrue("Incorrect first record", consumer.getRecords().get(0).getDescription().equals("Fastest beer ever consumed - 10 ms"));
        assertTrue("Incorrect last record", consumer.getRecords().get(1).getDescription().equals("Most beers consumed in a second - 5"));
    }

    // Bug 296606 - issues with ElementCollections
    // This test should be run after testCreateExpertBearConsumer
    // This test makes changes, so testReadExpertBeerConsumer will fail after this test.
    public void testExpertBeerConsumerRecordsCRUD() {
        String errorMsg = "";

        int nRecords;
        int nRecordsExpected = 2;

        clearCache();
        EntityManager em = createEntityManager();
        try {
            // read all Records inside transaction
            beginTransaction(em);
            ExpertBeerConsumer consumer = em.find(ExpertBeerConsumer.class, m_expertBeerConsumerId);
            // trigger indirection
            nRecords = consumer.getRecords().size();
            // Bug 296606 - issues with ElementCollections cause commit to fail with NPE
            // Before the bug was fixed, the workaround was to annotate Record with @ChangeTracking(ChangeTrackingType.DEFERRED)
            commitTransaction(em);
            closeEntityManager(em);
            if(nRecords != nRecordsExpected) {
                errorMsg += "wrong number of records after read; ";
            }

            // remove Record
            em = createEntityManager();
            beginTransaction(em);
            consumer = em.find(ExpertBeerConsumer.class, m_expertBeerConsumerId);
            Record recordToRemove = consumer.getRecords().iterator().next();
            consumer.getRecords().remove(recordToRemove);
            commitTransaction(em);
            closeEntityManager(em);
            nRecordsExpected--;
            // verify in cache
            em = createEntityManager();
            consumer = em.find(ExpertBeerConsumer.class, m_expertBeerConsumerId);
            closeEntityManager(em);
            nRecords = consumer.getRecords().size();
            if(nRecords != nRecordsExpected) {
                errorMsg += "cache: wrong number of records after remove; ";
            }
            // verify in db
            clearCache();
            em = createEntityManager();
            consumer = em.find(ExpertBeerConsumer.class, m_expertBeerConsumerId);
            closeEntityManager(em);
            nRecords = consumer.getRecords().size();
            if(nRecords != nRecordsExpected) {
                errorMsg += "db: wrong number of records after remove; ";
            }

            // add Record
            Record record1 = new Record();
            record1.setDescription("Original");
            record1.setDate(Helper.dateFromYearMonthDate(2009, 1, 1));
            record1.setLocation(new Location("Ottawa", "Canada"));
            Venue venue1 = new Venue();
            venue1.setAttendance(10);
            venue1.setName("Original");
            record1.setVenue(venue1);
            em = createEntityManager();
            beginTransaction(em);
            consumer = em.find(ExpertBeerConsumer.class, m_expertBeerConsumerId);
            consumer.getRecords().add(record1);
            commitTransaction(em);
            closeEntityManager(em);
            nRecordsExpected++;
            // verify in cache
            em = createEntityManager();
            consumer = em.find(ExpertBeerConsumer.class, m_expertBeerConsumerId);
            closeEntityManager(em);
            nRecords = consumer.getRecords().size();
            if(nRecords != nRecordsExpected) {
                errorMsg += "cache: wrong number of records after add; ";
            }
            // verify in db
            clearCache();
            em = createEntityManager();
            consumer = em.find(ExpertBeerConsumer.class, m_expertBeerConsumerId);
            closeEntityManager(em);
            nRecords = consumer.getRecords().size();
            if(nRecords != nRecordsExpected) {
                errorMsg += "db: wrong number of records after add; ";
            }

            // update all Records one by one.
            String newDescription = "New Description ";
            String newName = "New Name ";
            em = createEntityManager();
            beginTransaction(em);
            consumer = em.find(ExpertBeerConsumer.class, m_expertBeerConsumerId);
            int i=0;
            Iterator<Record> it = consumer.getRecords().iterator();
            while(it.hasNext()) {
                Record record = it.next();
                String index = Integer.toString(i++);
                record.setDescription(newDescription + index);
                record.getVenue().setName(newName + index );
            }
            // Bug 296606 - issues with ElementCollections cause commit to fail with NPE
            // Before the bug was fixed, the workaround was to annotate both Record and Venue with @ChangeTracking(ChangeTrackingType.DEFERRED).
            // With that workaround the test still used to fail - Record and Venue were not updated in the data base.
            // Before the bug was fixed, the workaround for that was to set property "eclipselink.weaving.internal" to "false" in persistence.xml.
            commitTransaction(em);
            // verify in cache
            em = createEntityManager();
            consumer = em.find(ExpertBeerConsumer.class, m_expertBeerConsumerId);
            closeEntityManager(em);
            nRecords = consumer.getRecords().size();
            if(nRecords != nRecordsExpected) {
                errorMsg += "cache: wrong number of records after update; ";
            }
            HashSet<String> usedDescriptions = new HashSet(nRecords);
            HashSet<String> usedNames = new HashSet(nRecords);
            it = consumer.getRecords().iterator();
            while(it.hasNext()) {
                Record record = it.next();
                String description = record.getDescription();
                if(!description.startsWith(newDescription)) {
                    errorMsg += "cache: wrong record description after update; ";
                }
                usedDescriptions.add(description);
                String name = record.getVenue().getName();
                if(!name.startsWith(newName)) {
                    errorMsg += "cache: wrong venue name after update; ";
                }
                usedNames.add(name);
            }
            if(usedDescriptions.size() != nRecords) {
                errorMsg += "cache: records with same description; ";
            }
            if(usedNames.size() != nRecords) {
                errorMsg += "cache: venues with same name; ";
            }
            // verify in db
            clearCache();
            em = createEntityManager();
            consumer = em.find(ExpertBeerConsumer.class, m_expertBeerConsumerId);
            closeEntityManager(em);
            nRecords = consumer.getRecords().size();
            if(nRecords != nRecordsExpected) {
                errorMsg += "db: wrong number of records after update; ";
            }
            usedDescriptions.clear();
            usedNames.clear();
            it = consumer.getRecords().iterator();
            while(it.hasNext()) {
                Record record = it.next();
                String description = record.getDescription();
                if(!description.startsWith(newDescription)) {
                    errorMsg += "db: wrong record description after update; ";
                }
                usedDescriptions.add(description);
                String name = record.getVenue().getName();
                if(!name.startsWith(newName)) {
                    errorMsg += "db: wrong venue name after update; ";
                }
                usedNames.add(name);
            }
            if(usedDescriptions.size() != nRecords) {
                errorMsg += "db: records with same description; ";
            }
            if(usedNames.size() != nRecords) {
                errorMsg += "db: venues with same name; ";
            }

            if(errorMsg.length() > 0) {
                fail(errorMsg);
            }
        } finally {
            if(em != null) {
                if (isTransactionActive(em)){
                    rollbackTransaction(em);
                }
                if(isOnServer()) {
                    closeEntityManager(em);
                } else if(em.isOpen()) {
                    closeEntityManager(em);
                }
            }
        }
    }

    public void testRedStripeExpertConsumer() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        ExpertBeerConsumer initialEBC = new ExpertBeerConsumer();
        initialEBC.setAccredidation(new Accredidation());
        int beerConsumerId = 0;

        try {
            RedStripe redStripe1 = new RedStripe();
            redStripe1.setAlcoholContent(5.0);
            initialEBC.addRedStripeBeersToConsume(redStripe1, "1");

            RedStripe redStripe2 = new RedStripe();
            redStripe2.setAlcoholContent(5.0);
            initialEBC.addRedStripeBeersToConsume(redStripe2, "2");

            initialEBC.setName("Expert Red Stripe Consumer");
            em.persist(initialEBC);
            beerConsumerId = initialEBC.getId();

            commitTransaction(em);
        } catch (RuntimeException e) {
            e.printStackTrace();

            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }

            closeEntityManager(em);
            fail("An exception was caught during create operation: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);

        clearCache();
        em = createEntityManager();
        ExpertBeerConsumer refreshedEBC = em.find(ExpertBeerConsumer.class, beerConsumerId);
        assertTrue("The expert beer consumer read back did not match the original", getServerSession().compareObjects(initialEBC, refreshedEBC));
    }

    public void testRedStripeNoviceConsumer() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        NoviceBeerConsumer initialNBC = new NoviceBeerConsumer();
        initialNBC.setAccredidation(new Accredidation());
        int beerConsumerId = 0;

        try {
            RedStripe redStripe1 = new RedStripe();
            redStripe1.setAlcoholContent(5.0);
            initialNBC.addRedStripeBeersToConsume(redStripe1, "3");

            RedStripe redStripe2 = new RedStripe();
            redStripe2.setAlcoholContent(5.0);
            initialNBC.addRedStripeBeersToConsume(redStripe2, "4");

            initialNBC.setName("Novice Red Stripe Consumer");
            em.persist(initialNBC);
            beerConsumerId = initialNBC.getId();

            commitTransaction(em);
        } catch (RuntimeException e) {
            e.printStackTrace();

            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }

            closeEntityManager(em);
            fail("An exception was caught during create operation: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);

        clearCache();
        em = createEntityManager();
        NoviceBeerConsumer refreshedNBC = em.find(NoviceBeerConsumer.class, beerConsumerId);
        assertTrue("The novice beer consumer read back did not match the original", getServerSession().compareObjects(initialNBC, refreshedNBC));
    }

    public void testUpdateBeerConsumer() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        try {
            BeerConsumer beerConsumer = em.find(BeerConsumer.class, m_beerConsumerId);

            // Create a detached object that mirrors the beer consumer from
            // testCreateBeerConsumer.
            BeerConsumer beerConsumerDetached = new BeerConsumer();
            beerConsumerDetached.setName(beerConsumer.getName());
            beerConsumerDetached.setId(beerConsumer.getId());
            beerConsumerDetached.setVersion(beerConsumer.getVersion());

            Blue blue = em.find(Blue.class, m_blueId);
            beerConsumerDetached.addBlueBeerToConsume(blue);

            em.merge(beerConsumerDetached);
            commitTransaction(em);
        } catch (RuntimeException e) {
            e.printStackTrace();
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }

            closeEntityManager(em);
            fail("An exception was caught during the merge of the detached beer consumer: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);
    }

    public void testVersionUpdateOnElementCollectionChange() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        try {
            BeerConsumer beerConsumer = (BeerConsumer) em.createQuery("select b from BeerConsumer b join b.redStripes r").getResultList().get(0);
            int currentVersion = beerConsumer.getVersion();
            beerConsumer.getRedStripes().put("version", new RedStripe(Double.valueOf("343")));
            commitTransaction(em);
            assertTrue("Did not increment version for change to element collection", beerConsumer.getVersion() == ++currentVersion);


        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }

            closeEntityManager(em);
            // Re-throw exception to ensure stacktrace appears in test result.
            throw e;
        }

        closeEntityManager(em);

    }

    // Test the clone method works with LAZY attributes at multiple levels of an inheritance hierarchy
    public void testInheritedClone() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        SerialNumber serialNumber = new SerialNumber();
        em.persist(serialNumber);
        Alpine alpine = new Alpine(serialNumber);
        alpine.setBestBeforeDate(Helper.dateFromYearMonthDate(2005, 8, 21));
        alpine.setAlcoholContent(5.0);
        alpine.setClassification(Alpine.Classification.BITTER);
        alpine.addInspectionDate(new Date(System.currentTimeMillis()));
        alpine.getBeerConsumer();
        Alpine clone = null;
        try{
            clone = alpine.clone();
        } catch (CloneNotSupportedException ex){
            fail("Caught CloneNotSupportedException " + ex);
        }

        BeerConsumer consumer = new BeerConsumer();
        consumer.setName("Keith Alexander");

        BlueLight blueLight = new BlueLight();
        blueLight.setAlcoholContent(Float.valueOf(4.0f));
        blueLight.setUniqueKey(new BigInteger((Long.valueOf(System.currentTimeMillis()).toString())));
        em.persist(blueLight);
        consumer.addBlueLightBeerToConsume(blueLight);
        clone.setBeerConsumer(consumer);
        consumer.addAlpineBeerToConsume(clone);
        em.persist(clone);
        em.persist(consumer);
        if (alpine.getBeerConsumer() == clone.getBeerConsumer()) {
            fail("Changing clone beerConsumer changed original.");
        }
        commitTransaction(em);
        Integer alpineId = clone.getId();
        Integer consumerId = consumer.getId();
        BigDecimal blueLightId = blueLight.getId();
        clearCache();
        closeEntityManager(em);
        em = createEntityManager();
        beginTransaction(em);
        alpine = em.find(Alpine.class, alpineId);
        try{
            clone = alpine.clone();
        } catch (CloneNotSupportedException ex){
            fail("Caught CloneNotSupportedException " + ex);
        }

        consumer = new BeerConsumer();
        consumer.setName("Frank Keith");
        clone.setBeerConsumer(consumer);
        consumer.addAlpineBeerToConsume(clone);
        clone.getBeerConsumer();
        if (alpine.getBeerConsumer() == clone.getBeerConsumer()) {
            fail("Changing clone beerConsumer changed original.");
        }
        if (alpine.getBeerConsumer() == null) {
            fail("Changing clone address reset original to null.");
        }
        if (clone.getBeerConsumer() != consumer) {
            fail("Changing clone did not work.");
        }

        try{
            consumer = em.find(BeerConsumer.class, consumerId);
            BeerConsumer consumerClone = (BeerConsumer)consumer.clone();

            Iterator<Alpine> alpineIterator = consumer.getAlpineBeersToConsume().iterator();
            while (alpineIterator.hasNext()){
                alpine = alpineIterator.next();
                assertTrue("The original beerConsumer has an alpine beer with an incorrect back pointer.", consumer == alpine.getBeerConsumer());
            }

            alpineIterator = consumerClone.getAlpineBeersToConsume().iterator();
            while (alpineIterator.hasNext()){
                alpine = alpineIterator.next();
                assertTrue("The cloned beerConsumer has an alpine beer with an incorrect back pointer.", consumerClone == alpine.getBeerConsumer());
            }

            Iterator<BlueLight> blueLightIterator = consumer.getBlueLightBeersToConsume().iterator();
            while (blueLightIterator.hasNext()){
                blueLight = blueLightIterator.next();
                assertTrue("The original beerConsumer has an BlueLight beer with an incorrect back pointer.", consumer == blueLight.getBeerConsumer());
            }

            blueLightIterator = consumerClone.getBlueLightBeersToConsume().iterator();
            while (blueLightIterator.hasNext()){
                blueLight = blueLightIterator.next();
                assertTrue("The cloned beerConsumer has an BlueLight beer with an incorrect back pointer.", consumerClone == blueLight.getBeerConsumer());
            }
        } catch (CloneNotSupportedException e){
            fail("Call to clone threw CloneNotSupportedException");
        }

        alpine = em.find(Alpine.class, clone.getId());
        em.remove(alpine);
        blueLight = em.find(BlueLight.class, blueLightId);
        em.remove(blueLight);
        consumer = em.find(BeerConsumer.class, consumerId);
        em.remove(consumer);
        commitTransaction(em);
        closeEntityManager(em);
    }

    // BUG 227345
    public void testCascadeRemove() {
        BeerConsumer beerConsumer = null;
        BlueLight blueLightPersisted = null;
        BlueLight blueLightDetached = null;
        EntityManager em = createEntityManager();

        // Create and persist the beerConsumer
        try {
            beginTransaction(em);
            beerConsumer = new BeerConsumer();
            beerConsumer.setName("Beer Man");

            blueLightPersisted = new BlueLight();
            beerConsumer.getBlueLightBeersToConsume().add(blueLightPersisted);
            blueLightPersisted.setBeerConsumer(beerConsumer);

            em.persist(beerConsumer);

            // Unique key must be set before commit.
            blueLightPersisted.setUniqueKey(blueLightPersisted.getId().toBigInteger());

            // They should be known by the EM
            assertTrue(em.contains(beerConsumer));
            assertTrue(em.contains(blueLightPersisted));
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            throw e;
        }

        // Create BlueLightDetached and manage the relations
        try {
            beginTransaction(em);
            blueLightDetached = new BlueLight();
            blueLightDetached.setUniqueKey(new BigDecimal(blueLightPersisted.getUniqueKey().intValue() + 1).toBigInteger());

            // Set the pointers
            beerConsumer.getBlueLightBeersToConsume().add(blueLightDetached);
            blueLightDetached.setBeerConsumer(beerConsumer);

            // And now remove the beer consumer. The remove-operation should cascade
            if (isOnServer()){
                beerConsumer = em.find(BeerConsumer.class, m_beerConsumerId);
            }
            em.remove(beerConsumer);

            // It's o.k. should be detached
            assertFalse(em.contains(blueLightDetached));
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            throw e;
        }

        try {
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }

            closeEntityManager(em);
            fail("An exception was caught during the remove of the BeerConsumer: [" + e.getMessage() + "]");
        }

        // Ensure neither the beer consumer nor the blue light
        // persisted/detached are available.
        assertFalse("The beer consumer was not removed", em.contains(beerConsumer));
        assertFalse("The blue light persisted was not removed even though the its owning beer comsumer was removed", em.contains(blueLightPersisted));
        assertFalse("The blue light detached was persisted even though the its owning beer comsumer was removed", em.contains(blueLightDetached));

        closeEntityManager(em);
    }

    public void testBreakOrder_CorrectionType_EXCEPTION() {
        // create BeerConsumer with designations
        EntityManager em = createEntityManager();
        beginTransaction(em);
        NoviceBeerConsumer beerConsumer = new NoviceBeerConsumer();
        beerConsumer.setAccredidation(new Accredidation());
        beerConsumer.setName("Broken order");
        beerConsumer.getDesignations().add("0");
        beerConsumer.getDesignations().add("1");
        beerConsumer.getDesignations().add("2");
        try {
            em.persist(beerConsumer);
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            fail("failed to create beerConsumer");
        }
        Integer id = beerConsumer.getId();

        try {

            // break the order of designations
            beginTransaction(em);
            try {
                em.createNativeQuery("UPDATE NOVICE_CONSUMER_DESIGNATIONS SET ORDER_COLUMN = null WHERE NOVICE_CONSUMER_ID = " + id +" AND ORDER_COLUMN = 0").executeUpdate();
                commitTransaction(em);
            } catch (RuntimeException e) {
                if (isTransactionActive(em)) {
                    rollbackTransaction(em);
                }
                fail("failed to break order of designations");
            } finally {
                closeEntityManager(em);
            }

            // remove beerConsumer from the cache
            clearCache();

            // read back the beer consumer, reading of the list of designations with the broken order should trigger exception
            em = createEntityManager();
            try {
                beerConsumer = em.find(NoviceBeerConsumer.class, id);
                // trigger indirection
                beerConsumer.getDesignations().size();
                fail("Exception was expected - but not thrown");
            } catch (RuntimeException e) {
                boolean isCorrectException = false;
                if(e instanceof QueryException) {
                    QueryException queryException = (QueryException)e;
                    if(((QueryException) e).getErrorCode() == QueryException.LIST_ORDER_FIELD_WRONG_VALUE) {
                        isCorrectException = true;
                    }
                }
                if(!isCorrectException) {
                    throw e;
                }
            } finally {
                closeEntityManager(em);
            }
        } finally {
            // clean up
            em = createEntityManager();
            beginTransaction(em);
            try {
                beerConsumer = em.find(NoviceBeerConsumer.class, id);
                em.remove(beerConsumer);
                commitTransaction(em);
            } catch (RuntimeException e) {
                if (isTransactionActive(em)) {
                    rollbackTransaction(em);
                }
            } finally {
                closeEntityManager(em);
            }
        }
    }

    public void testBreakOrder_CorrectionType_READ_WRITE() {
        // create BeerConsumer with committees
        EntityManager em = createEntityManager();
        beginTransaction(em);
        ExpertBeerConsumer beerConsumer = new ExpertBeerConsumer();
        beerConsumer.setName("Beer order");
        beerConsumer.setAccredidation(new Accredidation());

        Committee committee0 = new Committee();
        committee0.setDescription("Broken Order 0");
        beerConsumer.addCommittee(committee0);

        Committee committee1 = new Committee();
        committee1.setDescription("Broken Order 1");
        beerConsumer.addCommittee(committee1);

        Committee committee2 = new Committee();
        committee2.setDescription("Broken Order 2");
        beerConsumer.addCommittee(committee2);
        try {
            em.persist(beerConsumer);
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            closeEntityManager(em);
            fail("failed to create beerConsumer");
        }
        Integer id = beerConsumer.getId();

        try {

            // break the order of committees
            beginTransaction(em);
            try {
                em.createNativeQuery("UPDATE JPA_CONSUMER_COMMITTEE SET ORDER_COLUMN = null WHERE CONSUMER_ID = " + id +" AND ORDER_COLUMN = 0").executeUpdate();
                commitTransaction(em);
            } catch (RuntimeException e) {
                if (isTransactionActive(em)) {
                    rollbackTransaction(em);
                }
                fail("failed to break order of committees");
            } finally {
                closeEntityManager(em);
            }

            // remove beerConsumer from the cache
            clearCache();

            // read back the beer consumer, reading of the list of committees with the broken should fix the order "on the fly":
            // the default correction performed on the list substitutes null in the first element back to 0;
            // then alter order of committees - that would cause the list order to be updated in the db (and become valid).
            em = createEntityManager();
            beginTransaction(em);
            try {
                beerConsumer = em.find(ExpertBeerConsumer.class, id);
                // committees #1 and #2 switch their positions in the list.
                Committee committee = beerConsumer.getCommittees().remove(2);
                beerConsumer.getCommittees().add(1, committee);
                commitTransaction(em);
            } catch (RuntimeException e) {
                if (isTransactionActive(em)) {
                    rollbackTransaction(em);
                }
                closeEntityManager(em);
                fail("failed to change committees order");
            }

            // now verify that the order in the db has been corrected
            List<Number> results = em.createNativeQuery("SELECT ORDER_COLUMN FROM JPA_CONSUMER_COMMITTEE WHERE CONSUMER_ID = " +id+ " ORDER BY ORDER_COLUMN").getResultList();
            int expectedSize = beerConsumer.getCommittees().size();
            if(expectedSize != results.size()) {
                closeEntityManager(em);
                fail("read in "+ results.size() + " committees; expected " + expectedSize);
            }
            for(int i=0; i < expectedSize; i++) {
                if(results.get(i) == null || results.get(i).intValue() != i) {
                    closeEntityManager(em);
                    fail("read in list in wrong order: " + results + "; expected: 0, 1, 2");
                }
            }
            closeEntityManager(em);

        } finally {
            // clean up
            em = createEntityManager();
            beginTransaction(em);
            try {
                beerConsumer = em.find(ExpertBeerConsumer.class, id);
                em.remove(beerConsumer);
                commitTransaction(em);
            } catch (RuntimeException e) {
                if (isTransactionActive(em)) {
                    rollbackTransaction(em);
                }
            } finally {
                closeEntityManager(em);
            }
        }
    }

    public void testMapOrphanRemoval(){
        EntityManager em = createEntityManager();
        beginTransaction(em);

        BeerConsumer initialBC = new BeerConsumer();

        int beerConsumerId = 0;
        try {
            Becks becks1  = new Becks();
            becks1.setAlcoholContent(5.1);
            BecksTag becksTag1 = new BecksTag();
            becksTag1.setCallNumber("0A.789");
            em.persist(becksTag1);

            initialBC.setName("Becks Consumer");
            initialBC.addBecksBeerToConsume(becks1, becksTag1);

            em.persist(initialBC);
            beerConsumerId = initialBC.getId();

            em.flush();

            clearCache();

            BeerConsumer refreshedBC = em.find(BeerConsumer.class, beerConsumerId);
            refreshedBC.getBecksBeersToConsume().remove(becksTag1);

            em.flush();

            clearCache();
            becksTag1 = (BecksTag)em.find(BecksTag.class, becksTag1.getId());
            assertTrue("Key was deleted when it should not be.", becksTag1 != null);
            becks1 = (Becks)em.find(Becks.class, becks1.getId());
            assertTrue("Orphan removal did not remove the orphan", becks1 == null);

            rollbackTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }

            closeEntityManager(em);
            fail("An exception was caught during create operation: [" + e.getMessage() + "]");
        }

    }

    public void testSerializedElementCollectionMap(){
        EntityManager em = createEntityManager();
        beginTransaction(em);

        try{
            BeerConsumer initialBC = new BeerConsumer();
            em.persist(initialBC);

            SerialNumber serialNumber = new SerialNumber();
            em.persist(serialNumber);

            initialBC.addCommentLookup(serialNumber, "A test comment");

            em.flush();
            em.clear();

            initialBC = em.find(BeerConsumer.class, initialBC.getId());
            serialNumber = em.find(SerialNumber.class, serialNumber.getNumber());

            assertTrue("The serialized map was not properly retrieved after persist.", initialBC.getCommentLookup().size() == 1);
            assertTrue("The serialized map did not contain the proper entry.", initialBC.getCommentLookup().get(serialNumber) != null);
        } finally {
            rollbackTransaction(em);
            closeEntityManager(em);
        }
    }

    // this method is a test for the fix for bug 299847, prior to the fix, it fails when
    // weaving is disabled
    public void testAddToHeinekenBeerConsumerMap() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        int beerConsumerId = 0;
        int heinekenId = 0;
        Calendar cal = Calendar.getInstance();
        cal.set(2008, 12, 12);
        try {
            BeerConsumer initialBC = new BeerConsumer();
            initialBC.setName("Heineken Consumer");
            em.persist(initialBC);
            Heineken heineken1  = new Heineken();
            heineken1.setAlcoholContent(5.0);
            em.persist(heineken1);
            commitTransaction(em);

            beerConsumerId = initialBC.getId();
            heinekenId = heineken1.getId();

            clearCache();

            beginTransaction(em);

            initialBC = em.find(BeerConsumer.class, initialBC.getId());
            heineken1 = em.find(Heineken.class, heineken1.getId());
            initialBC.addHeinekenBeerToConsume(heineken1, cal.getTime());
            commitTransaction(em);

            clearCache();

            initialBC = em.find(BeerConsumer.class, initialBC.getId());
            heineken1 = em.find(Heineken.class, heineken1.getId());
            assertTrue("The beer consumer is not appropriately associated with the heineken.", heineken1.getBeerConsumer() != null);
            assertTrue("The heineken is not appropriately associated with the beer consumer.", initialBC.getHeinekenBeersToConsume().size() == 1);
        } catch (RuntimeException e) {
            fail("An exception was caught during create operation: [" + e.getMessage() + "]");
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            beginTransaction(em);
            BeerConsumer consumer = em.find(BeerConsumer.class, beerConsumerId);
            Heineken heineken = em.find(Heineken.class, heinekenId);
            if (consumer != null){
                em.remove(consumer);
            }
            if (heineken != null){
                em.remove(heineken);
            }

            commitTransaction(em);
            closeEntityManager(em);
        }
    }

    public void testColumnUpdatableAndInsertable() {
        EntityManager em = createEntityManager();

        try {
            // Create an official
            beginTransaction(em);

            OfficialEntry officialEntry = new OfficialEntry();
            em.persist(officialEntry);

            Official initialOfficial = new Official();
            initialOfficial.setName("Gui Pelletier"); // insertable=true, updatable=false
            initialOfficial.setAge(25); // insertable=false, updatable=true
            initialOfficial.setSalary(50000); // insertable=true, updatable=false
            initialOfficial.setBonus(10000); // insertable=false, updatable=true

            // Tests multiple mappings to the same column. The M-1 is read only
            // and the basic is the writable mapping.
            initialOfficial.setOfficialEntry(officialEntry); // insertable=false, updatable=false
            initialOfficial.setOfficialEntryId(officialEntry.getId()); // insertable=true, updatable=true

            ServiceTime service = new ServiceTime();
            service.setStartDate("Jan 1, 2008"); // insertable=true, updatable=false
            service.setEndDate("Jul 1, 2010"); // insertable=false, updatable=true
            initialOfficial.setServiceTime(service);

            em.persist(initialOfficial);

            commitTransaction(em);

            // Close the EM, clear cache and get new EM.
            closeEntityManager(em);
            clearCache();
            em = createEntityManager();

            // Read the official and verify its content
            beginTransaction(em);
            Official official = em.find(Official.class, initialOfficial.getId());
            assertTrue("The name was not inserted", official.getName().equals("Gui Pelletier"));
            assertTrue("The age was inserted", official.getAge() == null);
            assertTrue("The salary was not inserted", official.getSalary() == 50000);
            assertTrue("The bonus was inserted", official.getBonus() == null);
            assertTrue("The official entry was not inserted", official.getOfficialEntryId() == officialEntry.getId());
            assertTrue("The embeddable start date was not inserted", official.getServiceTime().getStartDate().equals("Jan 1, 2008"));
            assertTrue("The embeddable end date was inserted", official.getServiceTime().getEndDate() == null);

            // Change the updatable=false fields:
            official.setName("Guy Pelletier");
            official.setSalary(100000);
            official.getServiceTime().setStartDate("Jan 30, 2008");

            // Update the insertable=false fields:
            official.setAge(25);
            official.setBonus(10000);
            official.getServiceTime().setEndDate("Jul 1, 2010");

            commitTransaction(em);

            // Close the EM, clear cache and get new EM.
            closeEntityManager(em);
            clearCache();
            em = createEntityManager();

            // The refreshed official at this point should not have had any
            // update changes to name but age should now be updated.
            Official refreshedOfficial = em.find(Official.class, initialOfficial.getId());
            assertTrue("The refreshedOfficial did not match the original", getServerSession().compareObjects(initialOfficial, refreshedOfficial));

        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }

            fail("An exception was caught during create operation: [" + e.getMessage() + "]");
        } finally {
            closeEntityManager(em);
        }
    }

    public void testColumnUpdatableAndInsertableThroughQuery() {
        if ((JUnitTestCase.getServerSession()).getPlatform().isSymfoware()) {
            getServerSession().logMessage("Test testColumnUpdatableAndInsertableThroughQuery skipped for this platform, "
                    + "Symfoware doesn't support UpdateAll/DeleteAll on multi-table objects (see rfe 298193).");
            return;
        }

        EntityManager em = createEntityManager();

        try {
            // Create an official
            beginTransaction(em);
            Official initialOfficial = new Official();
            initialOfficial.setName("Gui Pelletier");
            em.persist(initialOfficial);
            commitTransaction(em);

            // Close the EM, clear cache and get new EM.
            closeEntityManager(em);
            clearCache();
            em = createEntityManager();

            // Update the official using a named query.
            beginTransaction(em);
            Query query = em.createNamedQuery("UpdateOfficalName");
            query.setParameter("name", "Guy");
            query.setParameter("id", initialOfficial.getId());
            query.executeUpdate();
            Official modifiedOfficial = em.find(Official.class, initialOfficial.getId());
            assertTrue("The name was not updated after executing the named query", modifiedOfficial.getName().equals("Guy"));
            commitTransaction(em);

            // Close the EM, clear cache and get new EM.
            closeEntityManager(em);
            clearCache();
            em = createEntityManager();

            Official refreshedOfficial = em.find(Official.class, modifiedOfficial.getId());
            assertTrue("The refreshedOfficial did not match the modified", getServerSession().compareObjects(modifiedOfficial, refreshedOfficial));

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

            fail("Update query failed: " + e.getMessage());
        } finally {
            closeEntityManager(em);
        }
    }

    public void testElementCollectionMapEmbeddable(){
        EntityManager em = createEntityManager();

        try {
            // Create an official
            beginTransaction(em);
            BeerConsumer consumer = new BeerConsumer();
            consumer.setName("Lionel");
            RedStripe rs = new RedStripe();
            rs.setAlcoholContent(4.5);
            consumer.addRedStripeByAlcoholContent(rs);
            em.persist(consumer);
            em.flush();

            rs = new RedStripe();
            rs.setAlcoholContent(3.5);
            consumer.addRedStripeByAlcoholContent(rs);
            em.flush();
        } finally {
            rollbackTransaction(em);
        }
    }

    // Bug 282523
    public void testRelatedBylawWrite(){
        EntityManager em = createEntityManager();

        try {
            beginTransaction(em);
            BuildingBylaw law = new BuildingBylaw();
            law.setCity("EastTown");
            law.setDescription("No west facing property.");

            BuildingBylaw relatedLaw = new BuildingBylaw();
            relatedLaw.setCity("EastTown");
            relatedLaw.setDescription("No square houses");

            law.setRelatedByLaw(relatedLaw);

            em.persist(law);
            em.persist(relatedLaw);

            em.flush();
            em.clear();

            String jpqlString = "SELECT b FROM BuildingBylaw b WHERE b.number =" + law.getNumber();
            law = (BuildingBylaw) em.createQuery(jpqlString).getSingleResult();

            assertNotNull("BuildingBylaw not properly written.", law);
            assertNotNull("ManyToOne with target type != actual type not properly written.", law.getRelatedByLaw());
        } finally {
            rollbackTransaction(em);
        }
    }

    // Bug 282523
    public void testInterfaceBylawWrite(){
        EntityManager em = createEntityManager();

        try {
            beginTransaction(em);
            BuildingBylaw law = new BuildingBylaw();
            law.setCity("EastTown");
            law.setDescription("No west facing property.");

            BuildingBylaw relatedLaw = new BuildingBylaw();
            relatedLaw.setCity("EastTown");
            relatedLaw.setDescription("No square houses");

            law.setReference(relatedLaw);

            em.persist(law);
            em.persist(relatedLaw);

            em.flush();
            em.clear();

            String jpqlString = "SELECT b FROM BuildingBylaw b WHERE b.number =" + law.getNumber();
            law = (BuildingBylaw) em.createQuery(jpqlString).getSingleResult();

            assertNotNull("BuildingBylaw not properly written.", law);
            assertNotNull("ManyToOne with target type != actual type not properly written.", law.getReference());
        } finally {
            rollbackTransaction(em);
        }
    }

    // Bug 334175
    public void testEmbeddableAggregateCollectionAndAggregate(){
        EntityManager em = createEntityManager();
        beginTransaction(em);
        BeerConsumer consumer = new BeerConsumer();
        consumer.setName("Lionel");
        RedStripe rs = new RedStripe();
        rs.setAlcoholContent(4.5);
        consumer.addRedStripeByAlcoholContent(rs);
        em.persist(consumer);

        Official official = new Official();
        official.setName("George");
        rs = new RedStripe();
        rs.setAlcoholContent(4.6);
        official.setLastRedStripeConsumed(rs);
        em.persist(official);

        em.flush();
        em.clear();
        clearCache();

        consumer = em.find(BeerConsumer.class, consumer.getId());
        assertNotNull("BeerConsumer had null red stripes.", consumer.getRedStripes());
        assertTrue("BeerConsumer had wrong number of red stripes.", consumer.getRedStripesByAlcoholContent().size() == 1);
        assertTrue("BeerConsumer had wrong red stripe.", consumer.getRedStripesByAlcoholContent().get(4.5) != null);

        official = em.find(Official.class, official.getId());
        assertNotNull("Official had null red stripe.", official.getLastRedStripeConsumed());
        assertTrue("Official had the wrong red stripe", official.getLastRedStripeConsumed().getAlcoholContent() == 4.6);

        rollbackTransaction(em);

    }


    // Bug 370975
    public void testNodeImplWeaving(){
        if (isWeavingEnabled()) {
            Class[] interfaces = NodeImpl.class.getInterfaces();
            boolean found = false;
            for (Class c : interfaces){
                if (c == PersistenceWeaved.class){
                    found = true;
                }
            }
            assertTrue("NodeImpl was not weaved.", found);
        }
    }

    // Bug 384527
    public void testEmbeddaleCollectionMapEmbeddableRead(){
        EntityManager em = createEntityManager();

        try {
            beginTransaction(em);
            BeerConsumer consumer = new BeerConsumer();
            consumer.setName("Lionel");
            RedStripe rs = new RedStripe();
            rs.setAlcoholContent(4.5);
            consumer.addRedStripeByAlcoholContent(rs);
            rs = new RedStripe();
            rs.setAlcoholContent(5.0);
            consumer.addRedStripeByAlcoholContent(rs);
            em.persist(consumer);
            em.flush();

            clearCache();
            em.clear();
            consumer = em.find(BeerConsumer.class, consumer.getId());
            Integer version = consumer.getVersion();
            consumer.getRedStripesByAlcoholContent().get(4.5);
            em.flush();

            clearCache();
            em.clear();

            consumer = em.find(BeerConsumer.class, consumer.getId());
            assertTrue("The version was updated on a read.", consumer.getVersion().equals(version));
        } finally {
            rollbackTransaction(em);
        }
    }

    public void testInterfaces(){
        // ensure weaving has occured
        EntityManager em = createEntityManager();
        em.getCriteriaBuilder();
        Class[] testClasses = new Class[]{BeerConsumer.class, Alpine.class, NoviceBeerConsumer.class, Bluish.class, Blue.class, Corona.class, ExpertBeerConsumer.class, Heineken.class};

        for (int index = 0;index<testClasses.length;index++){
            Class[] interfaces = testClasses[index].getInterfaces();
            Type[] genericInterfaces = testClasses[index].getGenericInterfaces();

            if (interfaces.length != genericInterfaces.length){
                fail("Weaving failed to correctly update interfaces for " + testClasses[index]);
            }

            for (int i=0;i<interfaces.length;i++){
                String comparisonString = null;
                if (genericInterfaces[i] instanceof Class<?>){
                    comparisonString = ((Class<?>)genericInterfaces[i]).getCanonicalName();
                } else if (genericInterfaces[i] instanceof ParameterizedType){
                    comparisonString = ((Class<?>)((ParameterizedType)genericInterfaces[i]).getRawType()).getCanonicalName();
                }

                assertEquals("Mismatched interface on " + testClasses[index] + ": " + interfaces[i].getCanonicalName() + " != " + comparisonString, interfaces[i].getCanonicalName(), comparisonString);
            }
        }
    }

    // Bug 406957 - Copy fails on AggregateCollectionMapping and on map with @MapKeyColumn
    public void testCopyMapKeyMap() {
        Calendar cal = Calendar.getInstance();
        BeerConsumer consumer = new BeerConsumer();
        consumer.setId(1);
        consumer.setName("A");
        Heineken heineken  = new Heineken();
        heineken.setAlcoholContent(5.0);
        heineken.setId(11);
        Date date = cal.getTime();
        consumer.addHeinekenBeerToConsume(heineken, date);
        EntityManager em = createEntityManager();
        CopyGroup copyAll = new CopyGroup();
        copyAll.cascadeAllParts();
        BeerConsumer consumerCopy = (BeerConsumer)JpaHelper.getEntityManager(em).copy(consumer, copyAll);
        if (consumerCopy.getHeinekenBeersToConsume().size() != consumer.getHeinekenBeersToConsume().size()) {
            fail("consumerCopy.getHeinekenBeersToConsume().size() = " + consumerCopy.getHeinekenBeersToConsume().size() + "; "+consumer.getHeinekenBeersToConsume().size()+" was expected");
        }
        if (consumerCopy.getHeinekenBeersToConsume() == consumer.getHeinekenBeersToConsume()) {
            fail("consumerCopy.getHeinekenBeersToConsume() == consumer.getHeinekenBeersToConsume()");
        }
        Map.Entry<Date, Heineken> entry = (Map.Entry<Date, Heineken>)consumerCopy.getHeinekenBeersToConsume().entrySet().iterator().next();
        Date dateCopy = entry.getKey();
        Heineken heinekenCopy = entry.getValue();
        if (!date.equals(dateCopy)) {
            fail("!date.equals(dateCopy)");
        }
        if (heineken == heinekenCopy) {
            fail("heineken == heinekenCopy");
        }
        if (heineken.getAlcoholContent() != heinekenCopy.getAlcoholContent()) {
            fail("heineken.getAlcoholContent() != heinekenCopy.getAlcoholContent()");
        }
    }
}
