/*
 * 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.EntityExistsException;
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;

/**
 * A new entity instance becomes both managed and persistent by invoking the persist method on it or by cascading the persist
 * operation. The semantics of the persist operation, applied to an entity X are as follows:
 * <ul>
 * <li>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.</li>
 * <li>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.</li>
 * <li>If X is a removed entity, it becomes managed.</li>
 * <li>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.</li>
 * <li>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.</li>
 * </ul>
 */
public class TestCascadePersist extends JPA1Base {

    @Test
    public void testSimpleCascadeNew() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            CascadingNode parent = new CascadingNode(1, null);
            CascadingNode child = new CascadingNode(2, parent);
            child.setParent(null); // to avoid circular cascade
            // cascade from parent to child
            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");
            env.commitTransactionAndClear(em);
            // verify existence after commit
            verifyExistenceOnDatabase(parent.getId());
            verifyExistenceOnDatabase(child.getId());
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSimpleCascadeManaged() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            CascadingNode parent = new CascadingNode(11, null);
            env.beginTransaction(em);
            em.persist(parent);
            env.commitTransactionAndClear(em);
            // cascade from parent to child
            env.beginTransaction(em);
            parent = em.find(CascadingNode.class, parent.getId()); // parent is now managed
            CascadingNode child = new CascadingNode(12, parent);
            child.setParent(null); // to avoid circular cascade
            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");
            env.commitTransactionAndClear(em);
            // verify existence after commit
            verifyExistenceOnDatabase(parent.getId());
            verifyExistenceOnDatabase(child.getId());
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSimpleCascadeDetached() 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 parent = new CascadingNode(21, null);
            env.beginTransaction(em);
            em.persist(parent);
            env.commitTransactionAndClear(em);
            // parent is now detached

            CascadingNode child = new CascadingNode(22, parent);
            child.setParent(null); // to avoid circular cascade
            // cascade from parent to child
            env.beginTransaction(em);
            boolean persistFailed = false;
            boolean immediateException = false;
            try {
                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");
            } catch (EntityExistsException e) {
                persistFailed = true;
                immediateException = true;
            }
            if (!immediateException) {
                try {
                    env.commitTransactionAndClear(em);
                } catch (RuntimeException e) {
                    if (!checkForPersistenceException(e)) {
                        throw e;
                    }
                    persistFailed = true;
                }
            } else {
                env.rollbackTransactionAndClear(em);
            }
            verify(persistFailed, "persist succeeded on a detached instance");
            // can't verify anything on the database as state is undefined after rollback


            // 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);
            parent = new CascadingNode(existing.getId(), null);
            child = new CascadingNode(24, parent);
            child.setParent(null); // to avoid circular cascade
            env.beginTransaction(em);
            em.persist(existing); // known object in state new
            persistFailed = false;
            immediateException = false;
            try {
                // cascade from parent to child
                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");
            } catch (EntityExistsException e) {
                persistFailed = true;
                immediateException = true;
            }
            verify(em.contains(existing), "Previously managed entity not contained in persistence context any more");
            if (!immediateException) {
                try {
                    env.commitTransactionAndClear(em);
                } catch (RuntimeException e) {
                    if (!checkForPersistenceException(e)) {
                        throw e;
                    }
                    persistFailed = true;
                }
            } else {
                env.rollbackTransactionAndClear(em);
            }
            verify(persistFailed, "persist succeeded on a detached instance");
            // can't verify anything on the database as state is undefined after rollback


            // case 2b: state of known object: managed
            existing = new CascadingNode(25, null);
            parent = new CascadingNode(existing.getId(), null);
            child = new CascadingNode(26, parent);
            child.setParent(null); // to avoid circular cascade
            env.beginTransaction(em);
            em.persist(existing);
            env.commitTransactionAndClear(em);

            env.beginTransaction(em);
            existing = em.find(CascadingNode.class, existing.getId()); // known object in state managed
            persistFailed = false;
            immediateException = false;
            try {
                // cascade from parent to child
                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");
            } catch (EntityExistsException e) {
                persistFailed = true;
                immediateException = true;
            }
            verify(em.contains(existing), "Previously managed entity not contained in persistence context any more");
            if (!immediateException) {
                try {
                    env.commitTransactionAndClear(em);
                } catch (RuntimeException e) {
                    if (!checkForPersistenceException(e)) {
                        throw e;
                    }
                    persistFailed = true;
                }
            } else {
                env.rollbackTransactionAndClear(em);
            }
            verify(persistFailed, "persist did succeed on a detached instance");
            // can't verify anything on the database as state is undefined after rollback

            // case 2c: state of known object: deleted
            existing = new CascadingNode(27, null);
            parent = new CascadingNode(existing.getId(), null);
            child = new CascadingNode(28, parent);
            child.setParent(null); // to avoid circular cascade
            env.beginTransaction(em);
            em.persist(existing);
            env.commitTransactionAndClear(em);

            env.beginTransaction(em);
            existing = em.find(CascadingNode.class, existing.getId());
            em.remove(existing); // known object in state deleted
            persistFailed = false;
            immediateException = false;
            try {
                // cascade from parent to child
                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");
            } catch (EntityExistsException e) {
                persistFailed = true;
                immediateException = true;
            }
            if (!immediateException) {
                try {
                    env.commitTransactionAndClear(em);
                } catch (RuntimeException e) {
                    if (!checkForPersistenceException(e)) {
                        throw e;
                    }
                    persistFailed = true;
                }
            } else {
                env.rollbackTransactionAndClear(em);
            }
            verify(persistFailed, "persist did succeed on a detached instance");
            // can't verify anything on the database as state is undefined after rollback
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testCircularCascade() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            CascadingNode parent = new CascadingNode(31, null);
            CascadingNode child = new CascadingNode(32, parent);
            // cascade from parent to child
            env.beginTransaction(em);
            em.persist(parent);
            env.commitTransactionAndClear(em);
            // verify existence after commit
            verifyExistenceOnDatabase(parent.getId());
            verifyExistenceOnDatabase(child.getId());
            emptyDatabaseTable(new int[] { 32, 31 });
            // cascade from child to parent
            env.beginTransaction(em);
            em.persist(child);
            env.commitTransactionAndClear(em);
            // verify existence after commit
            verifyExistenceOnDatabase(parent.getId());
            verifyExistenceOnDatabase(child.getId());
        } 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();
        }
    }

    private void emptyDatabaseTable(int[] keys) throws SQLException {
        Connection conn = getEnvironment().getDataSource().getConnection();
        try {
            PreparedStatement stmt = conn.prepareStatement("delete from TMP_CASC_NODE where ID = ?");
            try {
                for (int i = 0; i < keys.length; i++) {
                    stmt.setInt(1, keys[i]);
                    stmt.executeUpdate();
                }
                if (conn.getAutoCommit() != true) {
                    conn.commit();
                }
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }
}
