/*
 * Copyright (c) 2005, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2005, 2015 SAP. 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:
//     SAP - initial API and implementation

package org.eclipse.persistence.testing.tests.wdf.jpa1.entitymanager;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import jakarta.persistence.EntityManager;

import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.models.wdf.jpa1.node.CascadingNode;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Test;

/*
 * The semantics of the flush operation, applied to an entity X are as follows:
 * <p>
 * If X is a managed entity, it is synchronized to the database. For all entities Y referenced by a relationship from X, if the
 * relationship to Y has been annotated with the cascade element value cascade=PERSIST or cascade=ALL, the persist operation is
 * applied to Y.
 * <p>
 * If X is a removed entity, it is removed from the database. No cascade options are relevant. </ul>
 */
public class TestCascadeFlush extends JPA1Base {

    /*
     * The semantics of the persist operation, applied to an entity X are as follows: If X is a new entity, it becomes managed.
     * The entity X will be entered into the database at or before transaction commit or as a result of the flush operation.
     */
    @Test
    public void testSimpleCascadeToNew() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            CascadingNode parent = new CascadingNode(1, null);
            env.beginTransaction(em);
            em.persist(parent);
            CascadingNode child = new CascadingNode(2, parent);
            child.setParent(null); // to avoid circular cascade
            verify(!em.contains(child), "Child is already managed");
            em.flush();
            env.commitTransactionAndClear(em);
            // verify existence after commit
            verifyExistenceOnDatabase(parent.getId());
            verifyExistenceOnDatabase(child.getId());
        } finally {
            closeEntityManager(em);
        }
    }

    /*
     * The semantics of the persist operation, applied to an entity X are as follows: If X is a preexisting managed entity, it
     * is ignored by the persist operation. However, the persist operation is cascaded to entities referenced by X, if the
     * relationships from X to these other entities is annotated with the cascade=PERSIST or cascade=ALL annotation element
     * value or specified with the equivalent XML descriptor element.
     */
    @Test
    public void testSimpleCascadeToManaged() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            CascadingNode parent = new CascadingNode(11, null);
            CascadingNode child = new CascadingNode(12, parent);
            child.setParent(null); // to avoid circular cascade
            env.beginTransaction(em);
            em.persist(parent);
            verify(em.contains(parent), "Parent not contained in persistence context after persist");
            verify(em.contains(child), "Child not contained in persistence context after persist");
            CascadingNode grandchild = new CascadingNode(13, child);
            grandchild.setParent(null); // to avoid circular cascade
            verify(!em.contains(grandchild), "Grandchild is already managed");
            em.flush();
            env.commitTransactionAndClear(em);
            // verify existence after commit
            verifyExistenceOnDatabase(parent.getId());
            verifyExistenceOnDatabase(child.getId());
            verifyExistenceOnDatabase(grandchild.getId());
        } finally {
            closeEntityManager(em);
        }
    }

    /*
     * The semantics of the persist operation, applied to an entity X are as follows: If X is a detached object,
     * the EntityExistsException may be thrown when the persist operation is invoked,
     * or the EntityExistsException or another PersistenceException may be thrown at flush or commit time.
     */
    @Test
    public void testSimpleCascadeToDetached1() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // case 1: detached because entity exists on db but is not known by persistence context
            CascadingNode child = new CascadingNode(21, null);
            env.beginTransaction(em);
            em.persist(child);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            CascadingNode parent = new CascadingNode(22, null);
            em.persist(parent);
            parent.addChild(child); // child is detached
            verify(em.contains(parent), "Parent not contained in persistence context after persist");
            verify(!em.contains(child), "Child is already managed");
            boolean exceptionThrown = false;
            try {
                env.commitTransactionAndClear(em);
            } catch (RuntimeException e) {
                if (!checkForPersistenceException(e)) {
                    throw e;
                }
                exceptionThrown = true;
            }
            verify(exceptionThrown, "commit did not fail as expected");
            // can't verify anything on the database as state is undefined after rollback
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSimpleCascadeToDetached2a() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // case 2: detached because an object with same pk but different object identity is known by persistence context
            // case 2a: state of known object: new
            CascadingNode existing = new CascadingNode(23, null);
            CascadingNode parent = new CascadingNode(24, null);
            env.beginTransaction(em);
            em.persist(existing); // known object in state new
            em.persist(parent);
            CascadingNode child = new CascadingNode(existing.getId(), parent);
            child.setParent(null); // to avoid circular cascade
            verify(em.contains(existing), "Existing not contained in persistence context after persist");
            verify(em.contains(parent), "Parent not contained in persistence context after persist");
            verify(!em.contains(child), "Child is already managed");
            boolean exceptionThrown = false;
            try {
                env.commitTransactionAndClear(em);
            } catch (RuntimeException e) {
                if (!checkForPersistenceException(e)) {
                    throw e;
                }
                exceptionThrown = true;
            }
            verify(exceptionThrown, "commit did not fail as expected");
            // can't verify anything on the database as state is undefined after rollback
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSimpleCascadeToDetached2b() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // case 2b: state of known object: managed
            CascadingNode existing = new CascadingNode(25, null);
            CascadingNode parent = new CascadingNode(26, null);
            env.beginTransaction(em);
            em.persist(existing);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            existing = em.find(CascadingNode.class, Integer.valueOf(existing.getId())); // known object in state managed
            em.persist(parent);
            CascadingNode child = new CascadingNode(existing.getId(), parent);
            child.setParent(null); // to avoid circular cascade
            verify(em.contains(existing), "Existing not contained in persistence context after find");
            verify(em.contains(parent), "Parent not contained in persistence context after persist");
            verify(!em.contains(child), "Child is already managed");
            boolean exceptionThrown = false;
            try {
                env.commitTransactionAndClear(em);
            } catch (RuntimeException e) {
                if (!checkForPersistenceException(e)) {
                    throw e;
                }
                exceptionThrown = true;
            }
            verify(exceptionThrown, "commit did not fail as expected");
            // can't verify anything on the database as state is undefined after rollback
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSimpleCascadeToDetached2c() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // case 2c: state of known object: deleted
            CascadingNode existing = new CascadingNode(27, null);
            CascadingNode parent = new CascadingNode(28, null);
            env.beginTransaction(em);
            em.persist(existing);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            existing = em.find(CascadingNode.class, Integer.valueOf(existing.getId()));
            em.remove(existing); // known object in state deleted
            em.persist(parent);
            CascadingNode child = new CascadingNode(existing.getId(), parent);
            child.setParent(null); // to avoid circular cascade
            verify(!em.contains(existing), "Existing contained in persistence context after remove");
            verify(em.contains(parent), "Parent not contained in persistence context after persist");
            verify(!em.contains(child), "Child is already managed");
            boolean exceptionThrown = false;
            try {
                env.commitTransactionAndClear(em);
            } catch (RuntimeException e) {
                if (!checkForPersistenceException(e)) {
                    throw e;
                }
                exceptionThrown = true;
            }
            verify(exceptionThrown, "commit did not fail as expected");
            // can't verify anything on the database as state is undefined after rollback
        } finally {
            closeEntityManager(em);
        }
    }

    /*
     * The semantics of the persist operation, applied to an entity X are as follows: If X is a removed entity, it becomes
     * managed.
     */
    @Test
    public void testSimpleCascadeToRemoved() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            CascadingNode child = new CascadingNode(31, null);
            env.beginTransaction(em);
            em.persist(child);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            CascadingNode parent = new CascadingNode(32, null);
            em.persist(parent);
            child = em.find(CascadingNode.class, Integer.valueOf(child.getId()));
            em.remove(child);
            parent.addChild(child);
            verify(em.contains(parent), "Parent not contained in persistence context after persist");
            verify(!em.contains(child), "Child is contained in persistence context after remove");
            em.flush();
            verify(em.contains(child), "Child is not managed after cascading persist operation");
            env.commitTransactionAndClear(em);
            verifyExistenceOnDatabase(parent.getId());
            verifyExistenceOnDatabase(child.getId());
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testCircularCascade() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // cascade from parent to child
            CascadingNode parent = new CascadingNode(41, null);
            env.beginTransaction(em);
            em.persist(parent);
            CascadingNode child = new CascadingNode(42, parent);
            env.commitTransactionAndClear(em);
            verifyExistenceOnDatabase(parent.getId());
            verifyExistenceOnDatabase(child.getId());
            // cascade from child to parent
            child = new CascadingNode(43, null);
            env.beginTransaction(em);
            em.persist(child);
            parent = new CascadingNode(44, null);
            child.setParent(parent);
            parent.addChild(child);
            env.commitTransactionAndClear(em);
            verifyExistenceOnDatabase(parent.getId());
            verifyExistenceOnDatabase(child.getId());
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testFlushLazyCollectionWithCascadePersist() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // cascade from parent to child
            final int rootId = 50;
            env.beginTransaction(em);
            CascadingNode root = new CascadingNode(rootId, null);
            root.addChild(new CascadingNode(51, root));
            em.persist(root);
            env.commitTransaction(em);
            em.clear();
            env.beginTransaction(em);
            em.find(CascadingNode.class, Integer.valueOf(rootId));
            env.commitTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    private void verifyExistenceOnDatabase(int nodeId) throws SQLException {
        verify(checkForExistenceOnDatabase(nodeId), "no node with id " + nodeId + " found using JDBC.");
    }

    private boolean checkForExistenceOnDatabase(int nodeId) throws SQLException {
        Connection conn = getEnvironment().getDataSource().getConnection();
        try {
            PreparedStatement stmt = conn.prepareStatement("select ID, PARENT from TMP_CASC_NODE where ID = ?");
            try {
                stmt.setInt(1, nodeId);
                ResultSet rs = stmt.executeQuery();
                try {
                    return rs.next();
                } finally {
                    rs.close();
                }
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }

}
