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

// Contributors:
//     06/25/2014-2.5.2 Rick Curtis
//       - 438177: Test M2M map
package org.eclipse.persistence.testing.tests.jpa.relationships;

import java.util.HashMap;

import jakarta.persistence.EntityManager;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.eclipse.persistence.internal.jpa.EntityManagerImpl;
import org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.models.jpa.relationships.MtoMEntityA;
import org.eclipse.persistence.testing.models.jpa.relationships.MtoMEntityB;
import org.eclipse.persistence.testing.models.jpa.relationships.RelationshipsTableManager;

public class TestKeyTypeToManyRelationship extends JUnitTestCase{

    public TestKeyTypeToManyRelationship() {

    }

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

    public void testSetup () {
        new RelationshipsTableManager().replaceTables(JUnitTestCase.getServerSession());
    }

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

        suite.addTest(new TestKeyTypeToManyRelationship("testSetup"));
        suite.addTest(new TestKeyTypeToManyRelationship("testManyToManyMapTypeWithDefaultKey"));
        suite.addTest(new TestKeyTypeToManyRelationship("testManyToManyMapTypeWithDefaultJointTable"));

        return suite;
    }

    public void testManyToManyMapTypeWithDefaultJointTable() throws Exception {
        HashMap<String, String> emProps = new HashMap<String, String>();
        emProps.put("eclipselink.cache.shared.default", "false");

        EntityManager em = createEntityManager(emProps);

        beginTransaction(em);
        try {
            MtoMEntityA entityA = new MtoMEntityA();
            entityA.setId(2);
            entityA.setName("Entity A");
            em.persist(entityA);

            MtoMEntityB entityB = new MtoMEntityB();
            entityB.setId(2);
            entityB.setName("Entity B");
            em.persist(entityB);

            entityA.getEntityBDefault().put(2, entityB);

            commitTransaction(em);

            beginTransaction(em);

            em.clear();

            MtoMEntityA entityA_find = em.find(MtoMEntityA.class, 2);
            assertNotSame(entityA, entityA_find);
            assertNotNull(entityA_find);
            assertNotNull(entityA_find.getEntityBDefault());
            assertEquals(1, entityA_find.getEntityBDefault().size());

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

    public void testManyToManyMapTypeWithDefaultKey() throws Exception {
        HashMap<String, String> emProps = new HashMap<String, String>();
        emProps.put("eclipselink.cache.shared.default", "false");

        EntityManager em = createEntityManager(emProps);

        beginTransaction(em);
        try {
            MtoMEntityA entityA = new MtoMEntityA();
            entityA.setId(1);
            entityA.setName("Entity A");
            em.persist(entityA);

            MtoMEntityB entityB = new MtoMEntityB();
            entityB.setId(1);
            entityB.setName("Entity B");
            em.persist(entityB);

            entityA.getEntityB().put(1, entityB);

            commitTransaction(em);

            beginTransaction(em);

            em.clear();

            MtoMEntityA entityA_find = em.find(MtoMEntityA.class, 1);
            assertNotSame(entityA, entityA_find);
            assertNotNull(entityA_find);
            assertNotNull(entityA_find.getEntityB());
            assertEquals(1, entityA_find.getEntityB().size());

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