/*
 * 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);
    }

    @Override
    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(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(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 = em.find(BecksTag.class, becksTag1.getId());
            assertTrue("Key was deleted when it should not be.", becksTag1 != null);
            becks1 = 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()");
        }
    }
}
