/*
 * 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
package org.eclipse.persistence.testing.tests.jpa.advanced;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

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

import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.persistence.config.EntityManagerProperties;
import org.eclipse.persistence.config.ExclusiveConnectionMode;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork;
import org.eclipse.persistence.sessions.SessionEventAdapter;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.models.jpa.advanced.AdvancedTableCreator;

import org.eclipse.persistence.testing.models.jpa.advanced.Address;
import org.eclipse.persistence.testing.models.jpa.advanced.Employee;
import org.eclipse.persistence.testing.models.jpa.advanced.Man;
import org.eclipse.persistence.testing.models.jpa.advanced.PartnerLinkPK;
import org.eclipse.persistence.testing.models.jpa.advanced.Woman;
import org.eclipse.persistence.testing.models.jpa.advanced.Golfer;
import org.eclipse.persistence.testing.models.jpa.advanced.GolferPK;
import org.eclipse.persistence.testing.models.jpa.advanced.Vegetable;
import org.eclipse.persistence.testing.models.jpa.advanced.VegetablePK;
import org.eclipse.persistence.testing.models.jpa.advanced.WorldRank;
import org.eclipse.persistence.testing.models.jpa.advanced.PartnerLink;
import org.eclipse.persistence.testing.models.jpa.advanced.LargeProject;
import org.eclipse.persistence.testing.models.jpa.advanced.entities.SimpleEntity;
import org.eclipse.persistence.testing.models.jpa.advanced.entities.SimpleNature;
import org.eclipse.persistence.testing.models.jpa.advanced.entities.SimpleLanguage;
import org.junit.Assert;

public class AdvancedJunitTest extends JUnitTestCase {
    public AdvancedJunitTest() {
        super();
    }

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


    public static Test suite() {
        TestSuite suite = new TestSuite("AdvancedJunitTest");

        suite.addTest(new AdvancedJunitTest("testSetup"));
        suite.addTest(new AdvancedJunitTest("testGF1818"));
        suite.addTest(new AdvancedJunitTest("testEL254937"));
        suite.addTest(new AdvancedJunitTest("testGF1894"));
        suite.addTest(new AdvancedJunitTest("testGF894"));
        suite.addTest(new AdvancedJunitTest("testManAndWoman"));
        suite.addTest(new AdvancedJunitTest("testStringArrayField"));
        suite.addTest(new AdvancedJunitTest("testCreateDerivedPKFromPKValues"));
        suite.addTest(new AdvancedJunitTest("testElementCollectionClear"));
        suite.addTest(new AdvancedJunitTest("testElementCollectionEntityMapKeyRemove"));
        suite.addTest(new AdvancedJunitTest("testSwitchBatchDuringSessionEvent"));
        suite.addTest(new AdvancedJunitTest("testCoalesceJPQLQueryWithNullParameterValue"));

        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 AdvancedTableCreator().replaceTables(JUnitTestCase.getServerSession());

        clearCache();
    }

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

        try {
            Vegetable vegetable = new Vegetable();
            vegetable.setId(new VegetablePK("Carrot", "Orange"));
            vegetable.setCost(2.09);

            em.persist(vegetable);
            commitTransaction(em);

        } catch (Exception e) {
            fail("An exception was caught: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);
    }

    public void testEL254937(){
        // Should not run in the server - bug 264589
        if (! isOnServer()) {
            EntityManager em = createEntityManager();
            beginTransaction(em);
            LargeProject lp1 = new LargeProject();
            lp1.setName("one");
            em.persist(lp1);
            commitTransaction(em);
            em = createEntityManager();
            beginTransaction(em);
            em.remove(em.find(LargeProject.class, lp1.getId()));
            em.flush();
            JpaEntityManager eclipselinkEm = (JpaEntityManager)em.getDelegate();
            RepeatableWriteUnitOfWork uow = (RepeatableWriteUnitOfWork)eclipselinkEm.getActiveSession();
            //duplicate the beforeCompletion call
            uow.issueSQLbeforeCompletion();
            //commit the transaction
            uow.setShouldTerminateTransaction(true);
            uow.commitTransaction();
            //duplicate the AfterCompletion call.  This should merge, removing the LargeProject from the shared cache
            uow.mergeClonesAfterCompletion();
            em = createEntityManager();
            LargeProject cachedLargeProject = em.find(LargeProject.class, lp1.getId());
            closeEntityManager(em);
            assertTrue("Entity removed during flush was not removed from the shared cache on commit", cachedLargeProject==null);
        }
    }

    public void testGF1894() {
        EntityManager em = createEntityManager();
        beginTransaction(em);
        Employee emp = new Employee();
        emp.setFirstName("Guy");
        emp.setLastName("Pelletier");

        Address address = new Address();
        address.setCity("College Town");

        emp.setAddress(address);

        try {
            Employee empClone = em.merge(emp);
            assertNotNull("The id field for the merged new employee object was not generated.", empClone.getId());
            commitTransaction(em);

            Employee empFromDB = em.find(Employee.class, empClone.getId());
            assertNotNull("The version locking field for the merged new employee object was not updated after commit.", empFromDB.getVersion());

            beginTransaction(em);
            Employee empClone2 = em.merge(empFromDB);
            assertTrue("The id field on a existing merged employee object was modified on a subsequent merge.", empFromDB.getId().equals(empClone2.getId()));
            commitTransaction(em);
        } catch (jakarta.persistence.OptimisticLockException e) {
            fail("An optimistic locking exception was caught on the merge of a new object. An insert should of occurred instead.");
        }

        closeEntityManager(em);
    }

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

        try {
            for (int i = 0; ; i++) {
                GolferPK golferPK = new GolferPK(i);
                Golfer golfer = em.find(Golfer.class, golferPK);

                if (golfer == null) {
                    golfer = new Golfer();
                    golfer.setGolferPK(golferPK);

                    WorldRank worldRank = new WorldRank();
                    worldRank.setId(i);
                    golfer.setWorldRank(worldRank);

                    em.persist(worldRank);
                    em.persist(golfer);
                    commitTransaction(em);

                    break;
                }
            }
        } catch (Exception e) {
            fail("An exception was caught: [" + e.getMessage() + "]");
        }

        closeEntityManager(em);
    }

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

        try {
            PartnerLink pLink1 = new PartnerLink();
            pLink1.setMan(new Man());
            em.persist(pLink1);

            PartnerLink pLink2 = new PartnerLink();
            pLink2.setWoman(new Woman());
            em.persist(pLink2);

            PartnerLink pLink3 = new PartnerLink();
            pLink3.setMan(new Man());
            pLink3.setWoman(new Woman());
            em.persist(pLink3);

            commitTransaction(em);

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

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

        closeEntityManager(em);
    }


    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=279634
    public void testCreateDerivedPKFromPKValues() {

        EntityManager em = createEntityManager();
        beginTransaction(em);
        try {
            PartnerLink pLink3 = new PartnerLink();
            pLink3.setMan(new Man());
            pLink3.setWoman(new Woman());
            em.persist(pLink3);
            commitTransaction(em);
            ClassDescriptor descriptor = getServerSession().getClassDescriptor(PartnerLink.class);
            Object pks = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(pLink3, getServerSession());
            PartnerLinkPK createdPK = (PartnerLinkPK) descriptor.getCMPPolicy().createPrimaryKeyInstanceFromId(pks, getServerSession());
            PartnerLinkPK usedPk = new PartnerLinkPK(pLink3.getManId(), pLink3.getWomanId());
            assertTrue("PK's do not match.", usedPk.equals(createdPK));

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

    // GF1673, 2674 Java SE 6 classloading error for String[] field
    public void testStringArrayField() {
        EntityManager em = createEntityManager();
        beginTransaction(em);

        VegetablePK pk = new VegetablePK("Tomato", "Red");
        String[] tags = {"California", "XE"};
        try {
            Vegetable vegetable = new Vegetable();
            vegetable.setId(pk);
            vegetable.setCost(2.09);
            vegetable.setTags(tags);

            em.persist(vegetable);
            commitTransaction(em);

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

        em = createEntityManager();
        beginTransaction(em);
        Vegetable vegetable;
        try {
            vegetable = em.find(Vegetable.class, pk);
            commitTransaction(em);
            assertNotNull(vegetable);
            assertTrue(Arrays.equals(tags, vegetable.getTags()));

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

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

        try {
            SimpleEntity se = new SimpleEntity();
            se.setId(101L);
            se.setDescription("Element Collection Clear Test Record");
            Collection<String> nature = new ArrayList<String>();
            nature.add(SimpleNature.PERSONALITY[0]);
            nature.add(SimpleNature.PERSONALITY[1]);
            nature.add(SimpleNature.PERSONALITY[2]);
            nature.add(SimpleNature.PERSONALITY[3]);
            nature.add(SimpleNature.PERSONALITY[4]);
            nature.add(SimpleNature.PERSONALITY[5]);
            se.setSimpleNature(nature);

            em.persist(se);
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            throw e;
        } finally {
            closeEntityManager(em);
        }

        // Clear Cache.
        clearCache();
        em = createEntityManager();
        SimpleEntity se;
        try {
            se = em.find(SimpleEntity.class, 101L);
            // Detach all entities.
            em.clear();
            closeEntityManager(em);

            // Clear lazily loaded ElementCollection.
            se.getSimpleNature().clear();

            em = createEntityManager();
            beginTransaction(em);
            em.merge(se);
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            throw e;
        } finally {
            closeEntityManager(em);
        }

        // Clear Cache
        clearCache();
        em = createEntityManager();
        beginTransaction(em);
        try {
            se = em.find(SimpleEntity.class, 101L);
            Collection<String> natureList = se.getSimpleNature();
            int count = 0;
            for(String nature : natureList) {
                // Iterate to load the collection.
                count++;
            }
            Assert.assertEquals("All entries of collection have not been removed from database for ElementCollection Test.", 0, count);
        } catch (RuntimeException e) {
           throw e;
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

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

        try {
            SimpleEntity se = new SimpleEntity();
            se.setId(102L);
            se.setDescription("Element Collection Entity MapKey Remove Test Record");

            SimpleLanguage slen = new SimpleLanguage();
            slen.setCode("EN");
            slen.setDescription("English");

            SimpleLanguage slfr = new SimpleLanguage();
            slfr.setCode("FR");
            slfr.setDescription("French");

            se.getSimpleLanguage().put(slen, "Modest");
            se.getSimpleLanguage().put(slfr, "Modeste");

            em.persist(slen);
            em.persist(slfr);
            em.persist(se);
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            throw e;
        } finally {
            closeEntityManager(em);
        }

        // Clear Cache.
        clearCache();
        em = createEntityManager();

        SimpleEntity se = null;
        SimpleLanguage slfr = null;
        try {
            beginTransaction(em);
            se = em.find(SimpleEntity.class, 102L);
            slfr = em.find(SimpleLanguage.class, "FR");
            // Remove French Language from ElementCollection.
            se.getSimpleLanguage().remove(slfr);
            commitTransaction(em);
        } catch (RuntimeException e) {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            throw e;
        } finally {
            closeEntityManager(em);
        }

        // Clear Cache
        clearCache();
        em = createEntityManager();
        beginTransaction(em);
        try {
            slfr = em.find(SimpleLanguage.class, "FR");
            Assert.assertNotSame("Entity used as key in Collection Map has been deleted along with data in collection table on remove.", null, slfr);
        } catch (RuntimeException e) {
           throw e;
        } finally {
            if (isTransactionActive(em)){
                rollbackTransaction(em);
            }
            closeEntityManager(em);
        }
    }

    public void testSwitchBatchDuringSessionEvent() {
        //Test for bug#419326
        EntityManager em = createEntityManager();
        try {
            beginTransaction(em);
            Vegetable vegetable = em.find(Vegetable.class, new VegetablePK("Potato", "Yellow"));
            if (null != vegetable) {
                //cleanup old data
                em.remove(vegetable);
                em.flush();
                commitTransaction(em);
            }
        } catch (RuntimeException e) {
            throw e;
        } finally {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            clearCache();
            closeEntityManager(em);
        }

        em = createEntityManager();
        DatabasePlatform platform = getServerSession().getPlatform();
        boolean usesBatchWriting = platform.usesBatchWriting();
        boolean usesJDBCBatchWriting = platform.usesJDBCBatchWriting();
        boolean usesExternalConnectionPooling = getServerSession().getLogin().shouldUseExternalConnectionPooling();
        boolean usesExternalTransactionController = getServerSession().getLogin().shouldUseExternalTransactionController();
        final SessionEventAdapter listener = new PostAcquireExclusiveConnectionSqlExecutorListener();
        Vegetable vegetable;

        try {
            //Simulate JDBC batching with external connection pooling
            getServerSession().getLogin().useExternalConnectionPooling();
            getServerSession().getLogin().useExternalTransactionController();
            platform.setUsesBatchWriting(true);
            platform.setUsesJDBCBatchWriting(true);
            em.setProperty(EntityManagerProperties.EXCLUSIVE_CONNECTION_MODE, ExclusiveConnectionMode.Always);
            getServerSession().getEventManager().addListener(listener);

            beginTransaction(em);
            em.setFlushMode(FlushModeType.COMMIT);

            vegetable = em.find(Vegetable.class, new VegetablePK("Potato", "Yellow"));
            if (vegetable == null) {
                vegetable = new Vegetable();
            }
            vegetable.setId(new VegetablePK("Potato", "Yellow"));
            vegetable.setCost(1.10);

            em.persist(vegetable);
            // Here the transaction will be lazily opened, old connection handles released and new
            // connection obtained, triggering postAcquireExclusiveConnection event.
            // The postAcquireExclusiveConnection() invokes a non-batchable statement, due to which
            // current batch is cleared.  This should not cause a duplicate execution of insert.
            commitTransaction(em);

        } catch (jakarta.persistence.RollbackException r) {
            fail("RollbackException exception occurred : " + r.getMessage());
        } finally {
            //Cleanup and revert back to original conditions
            getServerSession().getEventManager().removeListener(listener);

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

            platform.setUsesBatchWriting(usesBatchWriting);
            platform.setUsesJDBCBatchWriting(usesJDBCBatchWriting);

            if (!usesExternalConnectionPooling) {
                getServerSession().getLogin().dontUseExternalConnectionPooling();
            }
            if (!usesExternalTransactionController) {
                getServerSession().getLogin().dontUseExternalTransactionController();
            }
            clearCache();
            closeEntityManager(em);
        }
    }

    /*
     * Implemented for bug 469182
     * Test setting a null parameter in the JPQL coalesce query, so that the jdbc type 
     * can be configured correctly when setting a null parameter on the JDBC statement. 
     */
    public void testCoalesceJPQLQueryWithNullParameterValue() {
        // create test data, Employee.salary values are different
        EntityManager em = createEntityManager();
        Employee emp1, emp2 = null;
        try {
            beginTransaction(em);
            
            emp1 = new Employee();
            emp1.setFirstName("Per");
            emp1.setLastName("Johanssen");
            emp1.setSalary(100000);
            em.persist(emp1);
            
            emp2 = new Employee();
            emp2.setFirstName("Kalle");
            emp2.setLastName("Johanssen");
            emp2.setSalary(999999);
            em.persist(emp2);
            
            commitTransaction(em);
        } catch (RuntimeException e) {
            throw e;
        } finally {
            if (isTransactionActive(em)) {
                rollbackTransaction(em);
            }
            clearCache();
            closeEntityManager(em);
        }
        
        // test setting a null parameter on a coalesce jpql query and executing it
        em = createEntityManager();
        try {
            String jpql = "select count(1) from Employee e where e.lastName = 'Johanssen' and e.salary = coalesce(e.salary, :sal)";
            Query query = em.createQuery(jpql);
            query = query.setParameter("sal", null); // deliberate null parameter value
            Long result = (Long)query.getSingleResult(); // query should still function
            assertNotNull("Query result should be non-null", result);
            assertEquals("Incorrect query results", Long.valueOf(2), result); // result value from db
        } catch (RuntimeException e) {
            throw e;
        } finally {
            // cleanup test data
            beginTransaction(em);
            emp1 = em.find(Employee.class, emp1.getId());
            if (emp1 != null) {
                em.remove(emp1);
            }
            emp2 = em.find(Employee.class, emp2.getId());
            if (emp2 != null) {
                em.remove(emp2);
            }
            commitTransaction(em);
            clearCache();
            closeEntityManager(em);
        }
    }
    
}
