/*
 * 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.io.IOException;
import java.sql.Date;

import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.LockModeType;
import jakarta.persistence.PersistenceException;

import org.eclipse.persistence.testing.framework.wdf.AbstractBaseTest;
import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.framework.wdf.ToBeInvestigated;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Account;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.CreditCardAccount;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Cubicle;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.CubiclePrimaryKeyClass;
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.Patent;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.PatentId;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Review;
import org.eclipse.persistence.testing.models.wdf.jpa1.node.CascadingNode;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Test;

public class TestGetReference extends JPA1Base {

    // Existing test entities
    private final Department _dep = new Department(1, "eins");
    private final Department _dep2 = new Department(2, "zwei");
    private final Employee _emp = new Employee(7, "first", "last", _dep);
    private final Cubicle _cub = new Cubicle(1, 2, "yellow", _emp);
    private final Patent _pat = new Patent("12345", 2007, "whatever", Date.valueOf("2007-01-01"));
    private final CreditCardAccount _ccacc = new CreditCardAccount();

    @Override
    public void setup() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            _ccacc.setNumber(1);
            _ccacc.setOwner("me");
            _ccacc.setCardNumber(123);
            env.beginTransaction(em);
            em.persist(_dep);
            em.persist(_dep2);
            em.persist(_emp);
            em.persist(_cub);
            em.persist(_pat);
            em.persist(_ccacc);
            em.flush();
            env.commitTransactionAndClear(em);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSimple() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Employee emp = em.getReference(Employee.class, _emp.getId());
            verify(em.contains(emp), "Object " + emp + " not managed");
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testPositivTx() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Employee emp = em.getReference(Employee.class, _emp.getId());
            verify(em.contains(emp), "Object " + emp + " not managed");
            verifyEquals(_emp.getId(), emp.getId(), "wrong id");
            verifyEquals(_dep.getName(), emp.getDepartment().getName(), "wrong department");

            emp = em.getReference(Employee.class, _emp.getId());
            verifyEquals(_emp.getId(), emp.getId(), "wrong id");

            Department dep = em.getReference(Department.class, _dep.getId());
            verify(em.contains(dep), "Object " + dep + " not managed");
            verifyEquals(_dep.getId(), dep.getId(), "wrong id");

            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testPositivNonTx() {
        final EntityManager em = getEnvironment().getEntityManager();
        try {
            Employee emp = em.getReference(Employee.class, _emp.getId());
            try {
                verifyEquals(_emp.getId(), emp.getId(), "wrong id");
                verifyEquals(_dep.getName(), emp.getDepartment().getName(), "wrong department");
                emp = em.getReference(Employee.class, _emp.getId());

                verifyEquals(_emp.getId(), emp.getId(), "wrong id");
                Department dep = em.getReference(Department.class, _dep.getId());
                verifyEquals(_dep.getId(), dep.getId(), "wrong id");
            } catch (PersistenceException e) {
                if (getEnvironment().usesExtendedPC()) {
                    throw e;
                }
                // transaction-scoped pc might throw exception while trying to
                // load hollow entity outside tx
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testPositivTxPropertyAccess() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Department dep = em.getReference(Department.class, _dep.getId());
            verify(em.contains(dep), "Object " + dep + " not managed");
            verifyEquals(_dep.getId(), dep.getId(), "wrong id");
            verifyEquals(_dep.getName(), dep.getName(), "wrong name");
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testPositivNonTxPropertyAccess() {
        final EntityManager em = getEnvironment().getEntityManager();
        try {
            Department dep = em.getReference(Department.class, _dep.getId());
            verifyEquals(_dep.getId(), dep.getId(), "wrong id");
            try {
                verifyEquals(_dep.getName(), dep.getName(), "wrong name");
            } catch (PersistenceException e) {
                if (getEnvironment().usesExtendedPC()) {
                    throw e;
                }
                // transaction-scoped pc might throw exception while trying to
                // load hollow entity outside tx
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testNegativ() {
        /*
         * If the requested instance does not exist in the database, the EntityNotFoundException is thrown when the instance
         * state is first accessed. (The persistence provider runtime is permitted to throw the EntityNotFoundException when
         * getReference is called.)
         */
        final EntityManager em = getEnvironment().getEntityManager();
        try {
            final JPAEnvironment env = getEnvironment();
            Employee employee = null;
            boolean operationFailed = false;
            env.beginTransaction(em);
            try {
                employee = em.getReference(Employee.class, 17 + 4);
            } catch (EntityNotFoundException e) {
                // $JL-EXC$ expected behavior
                operationFailed = true;
            }
            if (employee != null) {
                try {
                    employee.getFirstName();
                } catch (EntityNotFoundException e) {
                    // $JL-EXC$ expected behavior
                    operationFailed = true;
                }
            }
            env.rollbackTransactionAndClear(em);
            verify(operationFailed, "no EntityNotFoundException");
        } finally {
            closeEntityManager(em);
        }
    }

    /*
     * IllegalArgumentException, if the first argument does not denote an entity type or the second argument is not a valid type
     * for that entity's primary key.
     */
    @Test
    public void testIllegalArguments() {
        final EntityManager em = getEnvironment().getEntityManager();
        try {
            try {
                em.getReference(String.class, 17 + 4);
                flop("no IllegalArgumentException thrown");
            } catch (IllegalArgumentException ex) {
                verify(true, "");
            }
            try {
                em.getReference(Employee.class, "illegal key");
                flop("no IllegalArgumentException thrown");
            } catch (IllegalArgumentException ex) {
                verify(true, "");
            }
            try {
                em.getReference(Employee.class, null);
                flop("no IllegalArgumentException thrown");
            } catch (IllegalArgumentException ex) {
                verify(true, "");
            }
            try {
                em.getReference(null, "illegal key");
                flop("no IllegalArgumentException thrown");
            } catch (IllegalArgumentException ex) {
                verify(true, "");
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testFindWithCompositeKey() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Integer one = 1;
            Integer two = 2;
            CubiclePrimaryKeyClass cubKey = new CubiclePrimaryKeyClass(one, two);
            Cubicle cub = em.getReference(Cubicle.class, cubKey);
            verifyEquals(one, cub.getFloor(), "wrong cubicle");
            verifyEquals(two, cub.getPlace(), "wrong cubicle");
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testEmbeddedIdPropertyAccess() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            PatentId id = _pat.getId();
            Patent pat = em.getReference(Patent.class, id);
            verify(pat.getId().equals(_pat.getId()), "wrong patent");
            verify(pat.getDescription().equals(_pat.getDescription()), "wrong description");
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    /**
     * Clarification with Mike Keith on this:
     *     2) Check on flush another example
     *        On the DB: Employee(1) - Address(2);
     *        Address(3) may or may not exist
     * We perform the following operations:
     *     Employee emp = em.find(Employee.class, 1); 
     *     Address newAddress = em.getReference(Address.class, 3); // depending on the implementation, newAddress may be "hollow"
     *     emp.setAddress(newAddress);
     *     em.flush();
     * 
     * In which state is newAddress upon flush?
     * Is the entity manager required to assert the existence of newAddress upon flush?
     * Again, this would pervert the idea of lazy loading.
     * 
     * Should we specify that checks on flush should not apply to "hollow" entities?
     *
     * The getReference API comment states that the existence assertion is not expected until the state of the entity is first
     * accessed, so no assertion should be expected in this case. However, we might want to ensure it is in the spec text, not
     * just a comment, and we might also want to qualify that the assertion may only occur when accessing non-identifier state.
     */
    public void testNonExistingEntityInRelation() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Employee employee = null;
            Department nonExistingDepartment = null;
            env.beginTransaction(em);
            employee = em.find(Employee.class, _emp.getId());
            try {
                nonExistingDepartment = em.getReference(Department.class, 999); // does not exist
            } catch (EntityNotFoundException e) {
                // $JL-EXC$ expected behavior
                return; // getReference checks -> fail fast
            }
            employee.setDepartment(nonExistingDepartment);
            em.flush(); // must succeed now if getReference did not fail fast
        } finally {
            env.rollbackTransactionAndClear(em);
            closeEntityManager(em);
        }
    }

    @Test
    public void testInheritance() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            CreditCardAccount acc = em.getReference(CreditCardAccount.class, _ccacc.getNumber());
            // verify method declared by superclass
            verifyEquals(_ccacc.getOwner(), acc.getOwner(), "wrong owner");
            env.rollbackTransactionAndClear(em);

            env.beginTransaction(em);
            acc = (CreditCardAccount) em.getReference(Account.class, _ccacc.getNumber());
            // verify method declared by subclass of Account
            verifyEquals(_ccacc.getCardNumber(), acc.getCardNumber(), "wrong card number");
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testNegativInheritance() {
        /*
         * If the requested instance does not exist in the database, the EntityNotFoundException is thrown when the instance
         * state is first accessed. (The persistence provider runtime is permitted to throw the EntityNotFoundException when
         * getReference is called.)
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            CreditCardAccount account = null;
            boolean operationFailed = false;
            env.beginTransaction(em);
            try {
                account = em.getReference(CreditCardAccount.class, 999L); // does not exist
            } catch (EntityNotFoundException e) {
                // $JL-EXC$ expected behavior
                operationFailed = true;
            }
            if (account != null) {
                try {
                    account.getOwner();
                } catch (EntityNotFoundException e) {
                    // $JL-EXC$ expected behavior
                    operationFailed = true;
                }
            }
            env.rollbackTransactionAndClear(em);
            verify(operationFailed, "no EntityNotFoundException");
        } finally {
            closeEntityManager(em);
        }
    }

    /**
     * Test to validate that persisting an instance returned from `em.getReference()` will result in a PersistenceException
     */
    @Test
    public void testPersist() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Employee emp = null;
            boolean operationFailed = false;
            try {
                env.beginTransaction(em);
                // obtain existing hollow entity instance
                emp = em.getReference(Employee.class, _emp.getId());
            } catch (EntityNotFoundException e) {
                operationFailed = true;
            } finally {
                env.rollbackTransactionAndClear(em);
            }

            // emp is now detached and persist should throw a PersistenceException
            if (emp != null) {
                env.beginTransaction(em);
                try {
                    em.persist(emp);
                    em.flush();
                } catch (PersistenceException e) {
                    // $JL-EXC$ expected behavior
                    operationFailed = true;
                }
                env.rollbackTransactionAndClear(em);
                verify(operationFailed, "persisting a hollow entity succeeded (should fail)");
            }
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRemove() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Employee emp = new Employee(11, "homer", "simpson", _dep); // field access, no versioning
            em.persist(emp);
            Department dep = new Department(11, "eleven"); // property access, versioning
            em.persist(dep);
            Review rev = new Review(11, Date.valueOf("2007-01-01"), "eleven"); // field access, versioning
            em.persist(rev);
            env.commitTransactionAndClear(em);

            // update to increase version counter
            env.beginTransaction(em);
            dep = em.find(Department.class, 11);
            dep.setName("updated");
            rev = em.find(Review.class, 11);
            rev.setReviewText("updated");
            env.commitTransactionAndClear(em);

            env.beginTransaction(em);
            emp = em.getReference(Employee.class, 11);
            em.remove(emp);
            em.flush();
            env.commitTransactionAndClear(em);
            verify(em.find(Employee.class, 11) == null, "employee not removed");

            env.beginTransaction(em);
            dep = em.getReference(Department.class, 11);
            em.remove(dep);
            em.flush();
            env.commitTransactionAndClear(em);
            verify(em.find(Department.class, 11) == null, "department not removed");

            env.beginTransaction(em);
            rev = em.getReference(Review.class, 11);
            em.remove(rev);
            em.flush();
            env.commitTransactionAndClear(em);
            verify(em.find(Review.class, 11) == null, "review not removed");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRemoveNonExisting() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            try {
                Employee emp = em.getReference(Employee.class, 999); // versioning, entity does not exist
                em.remove(emp);
                em.flush();
                flop("PersistenceException not thrown as expected");
            } catch (PersistenceException e) {
                // $JL-EXC$ expected behavior
                // The persistence provider runtime is permitted to throw the EntityNotFoundException when getReference is called
            }
            env.rollbackTransactionAndClear(em);

            env.beginTransaction(em);
            try {
                Department dep = em.getReference(Department.class, 999); // versioning, entity does not exist
                em.remove(dep);
                em.flush();
                flop("PersistenceException not thrown as expected");
            } catch (PersistenceException e) {
                // $JL-EXC$ expected behavior
                // The persistence provider runtime is permitted to throw the EntityNotFoundException when getReference is called
            }
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testMerge() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Employee emp = null;

            // case 1: hollow entity is managed
            env.beginTransaction(em);
            emp = em.getReference(Employee.class, _emp.getId());
            em.merge(emp);
            em.flush();
            env.rollbackTransactionAndClear(em);

            // case 2: hollow entity is detached
            emp = em.getReference(Employee.class, _emp.getId());
            boolean shouldFail = isHollow(emp);
            env.beginTransaction(em);
            try {
                em.clear();
                verify(!em.contains(emp), "emp not detached");
                em.merge(emp);
                em.flush();
                if (shouldFail) {
                    flop("merge of a detached hollow entity succeeded (should fail)");
                }
            } catch (PersistenceException e) {
                if (!shouldFail) {
                    throw e;
                }
            } catch (IllegalArgumentException e) {
                if (!shouldFail) {
                    throw e;
                }
            }
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testMergeIntoHollow() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        int id = 20;
        try {

            env.beginTransaction(em);
            Employee emp = new Employee(id, "first", "last", _dep);
            em.persist(emp);
            env.commitTransactionAndClear(em);

            Employee empDetached = em.find(Employee.class, id);
            em.clear(); // detach entity
            empDetached.setFirstName("updated");

            env.beginTransaction(em);
            emp = em.getReference(Employee.class, id);
            em.merge(empDetached);
            em.flush();
            env.commitTransactionAndClear(em);

            emp = em.find(Employee.class, id);
            verify("updated".equals(emp.getFirstName()), "wrong first name: " + emp.getFirstName());
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testRefresh() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            Employee emp = null;
            env.beginTransaction(em);
            emp = em.getReference(Employee.class, _emp.getId());
            em.refresh(emp);
            em.flush();
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testReadLock() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Department dep = em.getReference(Department.class, _dep.getId());
            em.lock(dep, LockModeType.READ);
            em.flush();
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testWriteLock() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            Department dep = em.find(Department.class, _dep.getId());
            int version = dep.getVersion();
            env.rollbackTransactionAndClear(em);

            env.beginTransaction(em);
            dep = em.getReference(Department.class, _dep.getId());
            em.lock(dep, LockModeType.WRITE);
            em.flush();
            verify(dep.getVersion() > version, "version not incremented");
            env.rollbackTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @ToBeInvestigated
    public void testCascadeRemove() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            CascadingNode parent = new CascadingNode(1, null);
            CascadingNode child = new CascadingNode(2, parent);
            em.persist(parent);
            em.persist(child);
            env.commitTransactionAndClear(em);

            env.beginTransaction(em);
            parent = em.getReference(CascadingNode.class, 1);
            em.remove(parent);
            em.flush();
            env.commitTransactionAndClear(em);
            parent = em.find(CascadingNode.class, 1);
            verify(parent == null, "parent not removed");
            child = em.find(CascadingNode.class, 2);
            verify(child == null, "child not removed");
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @ToBeInvestigated
    public void testCascadePersistOnFlush() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            env.beginTransaction(em);
            CascadingNode parent = new CascadingNode(11, null);
            CascadingNode child = new CascadingNode(12, parent);
            em.persist(parent);
            em.persist(child);
            env.commitTransactionAndClear(em);

            env.beginTransaction(em);
            em.getReference(CascadingNode.class, 11);
            em.flush();
            env.rollbackTransactionAndClear(em);

            env.beginTransaction(em); // cleanup in order -> FK
            em.merge(child);
            em.merge(parent);
            em.remove(child);
            em.remove(parent);
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSerializeLoaded() throws IOException, ClassNotFoundException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // case 1: entity with standard serialization
            Employee emp = em.getReference(Employee.class, _emp.getId());
            // load entity
            emp.getFirstName();
            Employee resultEmp = AbstractBaseTest.serializeDeserialize(emp);
            verify(emp.getId() == resultEmp.getId(), "wrong id: " + resultEmp.getId());
            verify(emp.getFirstName().equals(resultEmp.getFirstName()), "wrong first name: " + resultEmp.getFirstName());
            em.clear();

            // case 2: entity with writeReplace
            Department dep = em.getReference(Department.class, _dep.getId());
            // load entity
            dep.getName();
            Department resultDep = AbstractBaseTest.serializeDeserialize(dep);
            verify(dep.getId() == resultDep.getId(), "wrong id: " + resultDep.getId());
            verify(Department.HUGO.equals(resultDep.getName()), "wrong name: " + resultDep.getName());
            em.clear();

            // case 3: related entities
            emp = em.getReference(Employee.class, 7);
            emp.getFirstName();
            dep = em.getReference(Department.class, 2);
            dep.getName();
            emp.setDepartment(dep);
            Cubicle cub = em.getReference(Cubicle.class, new CubiclePrimaryKeyClass(1, 2));
            cub.getColor();
            emp.setCubicle(cub);
            cub.setEmployee(emp);
            Cubicle resultCub = AbstractBaseTest.serializeDeserialize(cub);
            resultDep = resultCub.getEmployee().getDepartment();
            verify(Department.HUGO.equals(resultDep.getName()), "wrong name: " + resultDep.getName());
            em.clear();
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testSerializeHollow() throws IOException, ClassNotFoundException {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // case 1: entity with standard serialization
            Employee emp = em.getReference(Employee.class, _emp.getId());
            boolean shouldFail = isHollow(emp);
            try {
                Employee resultEmp = AbstractBaseTest.serializeDeserialize(emp);
                verify(emp.getId() == resultEmp.getId(), "wrong id: " + resultEmp.getId());
                verify(emp.getFirstName().equals(resultEmp.getFirstName()), "wrong first name: " + resultEmp.getFirstName());
            } catch (PersistenceException e) {
                if (!shouldFail) {
                    throw e;
                }
            }
            em.clear();

            // case 2: entity with writeReplace
            Department dep = em.getReference(Department.class, _dep.getId());
            shouldFail = isHollow(dep);
            try {
                Department resultDep = AbstractBaseTest.serializeDeserialize(dep);
                verify(dep.getId() == resultDep.getId(), "wrong id: " + resultDep.getId());
                verify(Department.HUGO.equals(resultDep.getName()), "wrong name: " + resultDep.getName());
            } catch (PersistenceException e) {
                if (!shouldFail) {
                    throw e;
                }
            }
            em.clear();
            em.clear();
        } finally {
            closeEntityManager(em);
        }
    }

    private boolean isHollow(Object entity) {
        return false; // TODO move to EclipseLink
        // return entity instanceof LazilyLoadable && ((LazilyLoadable)
        // entity)._isPending();
    }
}
