/*******************************************************************************
 * Copyright (c) 2005, 2009 SAP. All rights reserved.
 * This program and the accompanying materials are made available under the 
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     SAP - initial API and implementation
 ******************************************************************************/

package org.eclipse.persistence.testing.tests.wdf.jpa1.entitymanager;

import static org.junit.Assert.fail;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.FlushModeType;
import javax.persistence.Query;
import javax.persistence.TransactionRequiredException;

import org.eclipse.persistence.testing.framework.wdf.Bugzilla;
import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Employee;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Review;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Ignore;
import org.junit.Test;

public class TestRefresh extends JPA1Base {

    @Test
    public void testRefreshNew() {
        /*
         * Refresh on an entity that is not under control of the entity manager
         * should throw an IllegalArgumentException.
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        try {
            id = 1;
            dep = new Department(id, "NEW");
            env.beginTransaction(em);
            try {
                em.refresh(dep);
                flop("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            }
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid = 309681)
    public void testRefreshManagedNew() throws SQLException {
        /*
         * Note: The specification doesn't state explicitly how to behave in
         * this case, so we test our interpretation: - If the entity doesn't
         * exist on the database, nothing is changed - If the entity exists on
         * the database, the data is loaded and the state changes from
         * FOR_INSERT to FOR_UPDATE (in order to avoid errors at flush time)
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        try {
            // case 2: state MANAGED_NEW, but exists on DB (inserted in
            // different tx)
            id = 12;
            dep = new Department(id, "MANAGED_NEW");
            Department depInserted = new Department(id, "INSERTED");
            env.beginTransaction(em);
            em.persist(dep);
            insertDepartmentIntoDatabase(depInserted);
            verifyExistenceOnDatabase(id);
            // entity is now in state MANAGED_NEW, but record exists on db
            em.refresh(dep);
            checkDepartment(dep, id, "INSERTED"); // this should now be in state
                                                  // MANAGED
            verify(em.contains(dep), "Department is not managed");
            dep.setName("UPDATED");
            env.commitTransactionAndClear(em);
            // verify that updated name present on db
            dep = em.find(Department.class, new Integer(id));
            checkDepartment(dep, id, "UPDATED");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid = 309681)
    public void testRefreshManagedNewNotOnDB() throws SQLException {
        /*
         * Note: The specification doesn't state explicitly how to behave in
         * this case, so we test our interpretation: - If the entity doesn't
         * exist on the database, nothing is changed - If the entity exists on
         * the database, the data is loaded and the state changes from
         * FOR_INSERT to FOR_UPDATE (in order to avoid errors at flush time)
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        try {
            // case 1: state MANAGED_NEW and does not exist on DB
            id = 11;
            dep = new Department(id, "MANAGED_NEW");
            env.beginTransaction(em);
            em.persist(dep); // this is now in state MANAGED_NEW, but not on db
            em.refresh(dep); // nothing should happen
            verify(em.contains(dep), "Department is not managed");
            env.commitTransactionAndClear(em);
            verifyExistenceOnDatabase(id);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRefreshManaged() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        Department updatedDep;
        try {
            // case 1: undo own changes
            id = 21;
            dep = new Department(id, "MANAGED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, new Integer(id)); // this is now in
                                                              // state MANAGED
            dep.setName("UPDATED");
            em.refresh(dep);
            checkDepartment(dep, id, "MANAGED");
            verify(em.contains(dep), "Department is not managed");
            env.commitTransactionAndClear(em);
            // verify that original name present on db
            dep = em.find(Department.class, new Integer(id));
            checkDepartment(dep, id, "MANAGED");
            // case 2: refresh with data changed on db in a different tx
            id = 22;
            dep = new Department(id, "MANAGED");
            updatedDep = new Department(id, "UPDATED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, new Integer(id)); // this is now in
                                                              // state MANAGED
            updateDepartmentOnDatabase(updatedDep);
            em.refresh(dep);
            checkDepartment(dep, id, "UPDATED");
            verify(em.contains(dep), "Department is not managed");
            dep.setName("MANAGED");
            env.commitTransactionAndClear(em);
            // verify that original name present on db
            dep = em.find(Department.class, new Integer(id));
            checkDepartment(dep, id, "MANAGED");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @Bugzilla(bugid = 309681)
    public void testRefreshManagedCheckContains() throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        try {
            // case 3: try to refresh, but record has been deleted on db in a
            // different tx
            /*
             * We expect an EntityNotFoundException. However, the specification
             * does not state explicitly in which state the managed entity
             * should be after the exception. We are going to remove the entity
             * from the persistence context, so it is detached afterwards.
             */
            id = 23;
            dep = new Department(id, "MANAGED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, new Integer(id)); // this is now in
                                                              // state MANAGED
            deleteDepartmentFromDatabase(id);
            verifyAbsenceFromDatabase(em, id);
            try {
                em.refresh(dep);
                flop("refresh did not throw EntityNotFoundException");
            } catch (EntityNotFoundException e) {
                verify(true, "");
            }
            verify(!em.contains(dep), "entity still managed after EntityNotFoundException");
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    private void doRefreshDeleted(int id, boolean flush) throws SQLException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Department dep = new Department(id, "DELETED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);

            env.beginTransaction(em);
            dep = em.find(Department.class, new Integer(id));
            em.remove(dep);
            if (flush) {
                em.flush(); // this is now in state DELETE_EXECUTED
                verifyAbsenceFromDatabase(em, id);
            }
            try {
                em.refresh(dep);
                fail("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                // expected
            }
            if (env.isTransactionActive(em)) {
                env.rollbackTransactionAndClear(em);
            }
        } finally {
            closeEntityManager(em);
        }
    }

    /*
     * Refreshing an entity in state "removed" should raise an
     * IllegalArgumentException
     */
    @Test
    public void testRefreshDeleted() throws SQLException {
        doRefreshDeleted(31, false);
        doRefreshDeleted(32, true);
    }

    @Test
    public void testRefreshDetached() {
        /*
         * Refresh on a detached entity should throw an
         * IllegalArgumentException.
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        Department detachedDep;
        try {
            // case 1: entity exists on DB, but not contained in persistence
            // context
            id = 41;
            dep = new Department(id, "DETACHED");
            // firstly, we create a department on the database
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            try {
                em.refresh(dep);
                flop("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            }
            env.rollbackTransactionAndClear(em);
            // case 2: entity is contained in persistence context, but object to
            // be merged has different object identity
            // case 2a: state of known object: MANAGED_NEW
            id = 42;
            dep = new Department(id, "MANAGED_NEW");
            detachedDep = new Department(id, "DETACHED");
            env.beginTransaction(em);
            em.persist(dep); // this is now in state new
            try {
                em.refresh(detachedDep); // this object is detached
                flop("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            }
            env.rollbackTransactionAndClear(em);
            // case 2b: state of known object: MANAGED
            id = 43;
            dep = new Department(id, "MANAGED");
            detachedDep = new Department(id, "DETACHED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, new Integer(id)); // this is now in
                                                              // state MANAGED
            try {
                em.refresh(detachedDep); // this object is detached
                flop("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            }
            env.rollbackTransactionAndClear(em);
            // case 2c: state of known object: DELETED
            id = 44;
            dep = new Department(id, "DELETED");
            detachedDep = new Department(id, "DETACHED");
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            dep = em.find(Department.class, new Integer(id));
            em.remove(dep); // this is now in state DELETED
            try {
                em.refresh(detachedDep); // this object is detached
                flop("refresh did not throw IllegalArgumentException");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            }
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testNotAnEntity() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            try {
                em.refresh("Hutzliputz");
                flop("no IllegalArgumentException ");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            } finally {
                env.rollbackTransactionAndClear(em);
            }
            env.beginTransaction(em);
            try {
                em.refresh(null);
                flop("no IllegalArgumentException ");
            } catch (IllegalArgumentException e) {
                verify(true, "");
            } finally {
                env.rollbackTransactionAndClear(em);
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Ignore
    // @TestProperties(unsupportedEnvironments = {
    // JTANonSharedPCEnvironment.class, ResourceLocalEnvironment.class })
    public void testNoTransaction() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id;
        Department dep;
        try {
            id = 61;
            dep = new Department(id, "NO_TX");
            verify(!env.isTransactionActive(em), "transaction is active, can't execute test");
            try {
                em.refresh(dep);
                flop("refresh did not throw TransactionRequiredException");
            } catch (TransactionRequiredException e) {
                verify(true, "");
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRefreshManagedWithRelationships() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // case 1: undo own changes
            Department dep = new Department(101, "Evangelists");
            Employee emp = new Employee(102, "First", "Last", dep);
            Review rev1 = new Review(103, Date.valueOf("2006-02-03"), "Code inspection");
            Review rev2 = new Review(104, Date.valueOf("2006-02-04"), "Design review");
            emp.addReview(rev1);
            emp.addReview(rev2);
            env.beginTransaction(em);
            em.persist(dep);
            em.persist(emp);
            em.persist(rev1);
            em.persist(rev2);
            env.commitTransactionAndClear(em);
            env.beginTransaction(em);
            emp = em.find(Employee.class, new Integer(emp.getId()));
            rev1 = em.find(Review.class, new Integer(rev1.getId()));
            Review rev3 = new Review(105, Date.valueOf("2006-02-05"), "Test coverage");
            Set<Review> reviews = new HashSet<Review>();
            reviews.add(rev1);
            reviews.add(rev3);
            emp.setReviews(reviews);
            rev1.setReviewText("UPDATED");
            em.refresh(emp);
            verify(em.contains(emp), "Employee is not managed");
            Set<Review> reviewsAfterRefresh = emp.getReviews();
            verify(reviewsAfterRefresh.size() == 2, "Employee contains wrong number of reviews: " + reviewsAfterRefresh.size());
            for (Review rev : reviewsAfterRefresh) {
                int id = rev.getId();
                verify(id == rev1.getId() || id == rev2.getId(), "Employee has wrong review: " + id);
                verify(em.contains(rev), "Review " + id + " is not managed");
            }
            env.commitTransactionAndClear(em);
            // verify that original name present on db
            rev1 = em.find(Review.class, new Integer(rev1.getId()));
            verify("UPDATED".equals(rev1.getReviewText()), "Rev1 has wrong text: " + rev1.getReviewText());
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testTransactionMarkedForRollback() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        Department dep = new Department(111, "dep111");
        try {
            env.beginTransaction(em);
            em.persist(dep);
            env.commitTransaction(em);
            em.clear();
            env.beginTransaction(em);
            dep = em.find(Department.class, Integer.valueOf(dep.getId()));
            dep.setName("updated");
            env.markTransactionForRollback(em);
            em.refresh(dep);
            checkDepartment(dep, dep.getId(), "dep111");
            verify(em.contains(dep), "entity not contained in persistence context");
            env.rollbackTransaction(em);
        } finally {
            closeEntityManager(em);
        }
    }

    private void verifyExistenceOnDatabase(int departmentId) throws SQLException {
        Connection conn = getEnvironment().getDataSource().getConnection();
        try {
            PreparedStatement stmt = conn.prepareStatement("select ID, NAME from TMP_DEP where ID = ?");
            try {
                stmt.setInt(1, departmentId);
                ResultSet rs = stmt.executeQuery();
                try {
                    verify(rs.next(), "no department with id " + departmentId + " found using JDBC.");
                } finally {
                    rs.close();
                }
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }

    private void verifyAbsenceFromDatabase(EntityManager em, int id) {
        Query query = em.createQuery("SELECT d.id from Department d where d.id = ?1");
        query.setFlushMode(FlushModeType.COMMIT);
        query.setParameter(1, Integer.valueOf(id));
        verify(query.getResultList().size() == 0, "wrong result list size");
    }

    private void deleteDepartmentFromDatabase(int departmentId) throws SQLException {
        Connection conn = getEnvironment().getDataSource().getConnection();
        try {
            PreparedStatement stmt = conn.prepareStatement("delete from TMP_DEP where ID = ?");
            try {
                stmt.setInt(1, departmentId);
                stmt.executeUpdate();
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }

    private void insertDepartmentIntoDatabase(Department department) throws SQLException {
        Connection conn = getEnvironment().getDataSource().getConnection();
        try {
            PreparedStatement stmt = conn.prepareStatement("insert into TMP_DEP (ID, NAME, VERSION) values (?, ?, ?)");
            try {
                stmt.setInt(1, department.getId());
                stmt.setString(2, department.getName());
                stmt.setShort(3, (short) 0);
                stmt.executeUpdate();
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }

    private void updateDepartmentOnDatabase(Department department) throws SQLException {
        Connection conn = getEnvironment().getDataSource().getConnection();
        try {
            PreparedStatement stmt = conn.prepareStatement("update TMP_DEP set NAME = ? where ID = ?");
            try {
                stmt.setString(1, department.getName());
                stmt.setInt(2, department.getId());
                stmt.executeUpdate();
            } finally {
                stmt.close();
            }
        } finally {
            conn.close();
        }
    }

    private void checkDepartment(Department department, int id, String name) {
        verify(department != null, "department is null");
        verify(id == department.getId(), "department has wrong id: " + department.getId());
        verify(name.equals(department.getName()), "department has wrong name: " + department.getName());
    }
}
