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

import jakarta.persistence.EntityManager;

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

public class TestCascadeMerge extends JPA1Base {

    @Test
    @ToBeInvestigated
    public void testCascadeNew() {
        /*
         * If X is a new entity instance, a new managed entity instance X' is created and the state of X is copied into the new
         * managed entity instance X'.
         *
         * For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL,
         * Y is merged recursively as Y'. For all such Y referenced by X, X' is set to reference Y'. (Note that if X is managed
         * then X is the same object as X'.)
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            CascadingNode parent = new CascadingNode(1, null);
            CascadingNodeDescription parentDescription = new CascadingNodeDescription(2, null, "new parent");
            parent.setDescription(parentDescription);
            CascadingNode child = new CascadingNode(3, null);
            CascadingNodeDescription childDescription = new CascadingNodeDescription(4, null, "new child");
            child.setDescription(childDescription);
            CascadingNode grandchild = new CascadingNode(5, null);
            CascadingNodeDescription grandchildDescription = new CascadingNodeDescription(6, null, "new grandchild");
            grandchild.setDescription(grandchildDescription);
            parent.addChild(child);
            child.addChild(grandchild);
            env.beginTransaction(em);
            CascadingNode mergedNode = em.merge(parent);
            verify(mergedNode.getId() == parent.getId(), "merged entity has wrong id: expected " + parent.getId() + ", got "
                    + mergedNode.getId());
            verify(mergedNode != parent, "merged entity not a copy");
            verify(em.contains(mergedNode), "merged entity not managed");
            CascadingNodeDescription mergedDescription = mergedNode.getDescription();
            verify(mergedDescription.getId() == parentDescription.getId(), "merged entity has wrong id: expected "
                    + parentDescription.getId() + ", got " + mergedDescription.getId());
            verify(mergedDescription != parentDescription, "merged entity not a copy");
            verify(em.contains(mergedDescription), "merged entity not managed");
            Set<CascadingNode> mergedChildren = mergedNode.getChildren();
            verify(mergedChildren.size() == 1, "Wrong number of children: expected 1, got " + mergedChildren.size());
            for (CascadingNode temp : mergedChildren) {
                mergedNode = temp;
                break;
            }
            verify(mergedNode.getId() == child.getId(), "merged entity has wrong id: expected " + child.getId() + ", got "
                    + mergedNode.getId());
            verify(mergedNode != child, "merged entity not a copy");
            verify(em.contains(mergedNode), "merged entity not managed");
            mergedDescription = mergedNode.getDescription();
            verify(mergedDescription.getId() == childDescription.getId(), "merged entity has wrong id: expected "
                    + childDescription.getId() + ", got " + mergedDescription.getId());
            verify(mergedDescription != childDescription, "merged entity not a copy");
            verify(em.contains(mergedDescription), "merged entity not managed");
            mergedChildren = mergedNode.getChildren();
            verify(mergedChildren.size() == 1, "Wrong number of children: expected 1, got " + mergedChildren.size());
            for (CascadingNode temp : mergedChildren) {
                mergedNode = temp;
                break;
            }
            verify(mergedNode.getId() == grandchild.getId(), "merged entity has wrong id: expected " + grandchild.getId()
                    + ", got " + mergedNode.getId());
            verify(mergedNode != grandchild, "merged entity not a copy");
            verify(em.contains(mergedNode), "merged entity not managed");
            mergedDescription = mergedNode.getDescription();
            verify(mergedDescription.getId() == grandchildDescription.getId(), "merged entity has wrong id: expected "
                    + grandchildDescription.getId() + ", got " + mergedDescription.getId());
            verify(mergedDescription != grandchildDescription, "merged entity not a copy");
            verify(em.contains(mergedDescription), "merged entity not managed");
            mergedChildren = mergedNode.getChildren();
            verify(mergedChildren == null, "merged entity has children");
            env.commitTransactionAndClear(em);
            verifyExistence(em, parent);
            verifyExistence(em, parentDescription);
            verifyExistence(em, child);
            verifyExistence(em, childDescription);
            verifyExistence(em, grandchild);
            verifyExistence(em, grandchildDescription);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    @ToBeInvestigated
    public void testCascadeDetached() {
        /*
         * If X is a detached entity, the state of X is copied onto a pre-existing managed entity instance X' of the same
         * identity or a new managed copy X' of X is created.
         *
         * For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL,
         * Y is merged recursively as Y'. For all such Y referenced by X, X' is set to reference Y'. (Note that if X is managed
         * then X is the same object as X'.)
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // types of being detached:
            // parent, parentDescription: not in persistence context but on db
            // child, childDescription: different object with same pk in persistence context, state FOR_UPDATE
            // grandchild, grandchildDescription: different object with same pk in persistence context, state FOR_INSERT
            CascadingNode parent = new CascadingNode(101, null);
            CascadingNodeDescription parentDescription = new CascadingNodeDescription(102, null, "new parent");
            parent.setDescription(parentDescription);
            CascadingNode child = new CascadingNode(103, null);
            CascadingNodeDescription childDescription = new CascadingNodeDescription(104, null, "new child");
            child.setDescription(childDescription);
            parent.addChild(child);
            env.beginTransaction(em);
            em.persist(parent);
            env.commitTransactionAndClear(em);
            verifyExistence(em, parent);
            verifyExistence(em, parentDescription);
            verifyExistence(em, child);
            verifyExistence(em, childDescription);
            env.beginTransaction(em);
            CascadingNode grandchild = new CascadingNode(105, null);
            CascadingNodeDescription grandchildDescription = new CascadingNodeDescription(106, null, "new grandchild");
            grandchild.setDescription(grandchildDescription);
            child.addChild(grandchild);
            CascadingNode managedChild = em.find(CascadingNode.class, child.getId());
            CascadingNodeDescription managedChildDescription = em.find(CascadingNodeDescription.class, childDescription.getId());
            CascadingNode managedGrandchild = new CascadingNode(grandchild.getId(), null);
            CascadingNodeDescription managedGrandchildDescription = new CascadingNodeDescription(grandchildDescription.getId(),
                    null, "new grandchild");
            managedGrandchild.setDescription(managedGrandchildDescription);
            managedChild.addChild(managedGrandchild);
            em.persist(managedGrandchild);
            verify(!em.contains(parent), "parent is managed");
            verify(!em.contains(parentDescription), "parentDescription is managed");
            verify(!em.contains(child), "child is managed");
            verify(!em.contains(childDescription), "childDescription is managed");
            verify(!em.contains(grandchild), "grandchild is managed");
            verify(!em.contains(grandchildDescription), "grandchildDescription is managed");
            verify(em.contains(managedChild), "managedChild is not managed");
            verify(em.contains(managedChildDescription), "managedChildDescription is not managed");
            verify(em.contains(managedGrandchild), "managedGrandchild is not managed");
            verify(em.contains(managedGrandchildDescription), "managedGrandchildDescription is not managed");
            // setup complete
            CascadingNode mergedNode = em.merge(parent);
            verify(mergedNode.getId() == parent.getId(), "merged entity has wrong id: expected " + parent.getId() + ", got "
                    + mergedNode.getId());
            verify(mergedNode != parent, "merged entity not a copy");
            verify(em.contains(mergedNode), "merged entity not managed");
            CascadingNodeDescription mergedDescription = mergedNode.getDescription();
            verify(mergedDescription.getId() == parentDescription.getId(), "merged entity has wrong id: expected "
                    + parentDescription.getId() + ", got " + mergedDescription.getId());
            verify(mergedDescription != parentDescription, "merged entity not a copy");
            verify(em.contains(mergedDescription), "merged entity not managed");
            Set<CascadingNode> mergedChildren = mergedNode.getChildren();
            verify(mergedChildren.size() == 1, "Wrong number of children: expected 1, got " + mergedChildren.size());
            for (CascadingNode temp : mergedChildren) {
                mergedNode = temp;
                break;
            }
            verify(mergedNode.getId() == child.getId(), "merged entity has wrong id: expected " + child.getId() + ", got "
                    + mergedNode.getId());
            verify(mergedNode != child, "merged entity not a copy");
            verify(em.contains(mergedNode), "merged entity not managed");
            mergedDescription = mergedNode.getDescription();
            verify(mergedDescription.getId() == childDescription.getId(), "merged entity has wrong id: expected "
                    + childDescription.getId() + ", got " + mergedDescription.getId());
            verify(mergedDescription != childDescription, "merged entity not a copy");
            verify(em.contains(mergedDescription), "merged entity not managed");
            mergedChildren = mergedNode.getChildren();
            verify(mergedChildren.size() == 1, "Wrong number of children: expected 1, got " + mergedChildren.size());
            for (CascadingNode temp : mergedChildren) {
                mergedNode = temp;
                break;
            }
            verify(mergedNode.getId() == grandchild.getId(), "merged entity has wrong id: expected " + grandchild.getId()
                    + ", got " + mergedNode.getId());
            verify(mergedNode != grandchild, "merged entity not a copy");
            verify(em.contains(mergedNode), "merged entity not managed");
            mergedDescription = mergedNode.getDescription();
            verify(mergedDescription.getId() == grandchildDescription.getId(), "merged entity has wrong id: expected "
                    + grandchildDescription.getId() + ", got " + mergedDescription.getId());
            verify(mergedDescription != grandchildDescription, "merged entity not a copy");
            verify(em.contains(mergedDescription), "merged entity not managed");
            mergedChildren = mergedNode.getChildren();
            verify(mergedChildren == null, "merged entity has children");
            env.commitTransactionAndClear(em);
            verifyExistence(em, parent);
            verifyExistence(em, parentDescription);
            verifyExistence(em, child);
            verifyExistence(em, childDescription);
            verifyExistence(em, grandchild);
            verifyExistence(em, grandchildDescription);
        } finally {
            closeEntityManager(em);
        }
    }

    /**
     * Scenario: Merge a detached entity in case an entity with the same primary key but different object identiy exists in the
     * persistence context <b>in state FOR_DELETE</b>. The specification does not state clearly how to behave in that case. We
     * decided to throw an IllegalArgumentException.
     */
    @Test
    public void testCascadeDetachedRemoved() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // child, childDescription: different object with same pk in persistence context, state FOR_DELETE
            // others: detached (other types)
            CascadingNode parent = new CascadingNode(201, null);
            CascadingNodeDescription parentDescription = new CascadingNodeDescription(202, null, "new parent");
            parent.setDescription(parentDescription);
            CascadingNode child = new CascadingNode(203, null);
            CascadingNodeDescription childDescription = new CascadingNodeDescription(204, null, "new child");
            child.setDescription(childDescription);
            CascadingNode grandchild = new CascadingNode(205, null);
            CascadingNodeDescription grandchildDescription = new CascadingNodeDescription(206, null, "new grandchild");
            grandchild.setDescription(grandchildDescription);
            parent.addChild(child);
            child.addChild(grandchild);
            env.beginTransaction(em);
            em.persist(parent);
            env.commitTransactionAndClear(em);
            verifyExistence(em, parent);
            verifyExistence(em, parentDescription);
            verifyExistence(em, child);
            verifyExistence(em, childDescription);
            verifyExistence(em, grandchild);
            verifyExistence(em, grandchildDescription);
            env.beginTransaction(em);
            CascadingNode managedParent = em.find(CascadingNode.class, parent.getId());
            CascadingNodeDescription managedParentDescription = em.find(CascadingNodeDescription.class, parentDescription.getId());
            CascadingNode managedChild = em.find(CascadingNode.class, child.getId());
            CascadingNodeDescription managedChildDescription = em.find(CascadingNodeDescription.class, childDescription.getId());
            CascadingNode managedGrandchild = em.find(CascadingNode.class, grandchild.getId());
            CascadingNodeDescription managedGrandchildDescription = em.find(CascadingNodeDescription.class, grandchildDescription.getId());
            managedParent.setChildren(null);
            em.remove(managedChild);
            em.persist(managedGrandchild);
            verify(!em.contains(parent), "parent is managed");
            verify(!em.contains(parentDescription), "parentDescription is managed");
            verify(!em.contains(child), "child is managed");
            verify(!em.contains(childDescription), "childDescription is managed");
            verify(!em.contains(grandchild), "grandchild is managed");
            verify(!em.contains(grandchildDescription), "grandchildDescription is managed");
            verify(em.contains(managedParent), "managedParent is not managed");
            verify(em.contains(managedParentDescription), "managedParentDescription is not managed");
            verify(!em.contains(managedChild), "managedChild is not in state FOR_DELETE");
            verify(!em.contains(managedChildDescription), "managedChildDescription is not in state FOR_DELETE");
            verify(em.contains(managedGrandchild), "managedGrandchild is not managed");
            verify(em.contains(managedGrandchildDescription), "managedGrandchildDescription is not managed");
            // setup complete
            boolean mergeFailed = false;
            try {
                em.merge(parent);
            } catch (IllegalArgumentException e) {
                // $JL-EXC$ this is expected behavior
                mergeFailed = true;
            }
            verify(mergeFailed, "Merge did not throw IllegalArgumentException");
            verify(em.contains(managedParent), "managedParent is not managed");
            verify(em.contains(managedParentDescription), "managedParentDescription is not managed");
            verify(managedParent.getDescription() == managedParentDescription, "managedParent has wrong description");
            Set<CascadingNode> children = managedParent.getChildren();
            verify(children == null || children.size() == 0, "parent has children");
            verify(!em.contains(managedChild), "managedChild is not in state FOR_DELETE");
            verify(!em.contains(managedChildDescription), "managedChildDescription is not in state FOR_DELETE");
            verify(em.contains(managedGrandchild), "managedGrandchild is not managed");
            verify(em.contains(managedGrandchildDescription), "managedGrandchildDescription is not managed");
            verify(managedGrandchild.getDescription() == managedGrandchildDescription,
                    "managedGrandchild has wrong description");
            env.rollbackTransactionAndClear(em);
            verifyExistence(em, parent);
            verifyExistence(em, parentDescription);
            verifyExistence(em, child);
            verifyExistence(em, childDescription);
            verifyExistence(em, grandchild);
            verifyExistence(em, grandchildDescription);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testCircularCascade() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            CascadingNode node1 = new CascadingNode(301, null);
            CascadingNode node2 = new CascadingNode(302, null);
            env.beginTransaction(em);
            em.persist(node1);
            em.persist(node2);
            env.commitTransactionAndClear(em);
            verifyExistence(em, node1);
            verifyExistence(em, node2);
            node1.addChild(node2);
            node2.addChild(node1);
            env.beginTransaction(em);
            CascadingNode mergedNode1 = em.merge(node1);
            verify(em.contains(mergedNode1), "mergedNode1 not managed");
            Set<CascadingNode> childrenOfNode1 = mergedNode1.getChildren();
            verify(childrenOfNode1.size() == 1, "Wrong number of children: expected 1, got " + childrenOfNode1.size());
            CascadingNode childOfNode1 = null;
            for (CascadingNode temp : childrenOfNode1) {
                childOfNode1 = temp;
                break;
            }
            verify(childOfNode1.getId() == node2.getId(), "childOfNode1 has wrong id: " + childOfNode1.getId());
            verify(em.contains(childOfNode1), "childOfNode1 not managed");
            Set<CascadingNode> childrenOfNode2 = childOfNode1.getChildren();
            verify(childrenOfNode2.size() == 1, "Wrong number of children: expected 1, got " + childrenOfNode2.size());
            CascadingNode childOfNode2 = null;
            for (CascadingNode temp : childrenOfNode2) {
                childOfNode2 = temp;
                break;
            }
            verify(childOfNode2 == mergedNode1, "mergedNode1 not child of childOfNode1");
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    /**
     * Tests a scenario where two nodes with the same primary key are related to each other, one is managed, the other detached.
     */
    @Test
    public void testCircularCascadeWithSamePks() {
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            CascadingNode managedNode = new CascadingNode(401, null);
            CascadingNode detachedNode = new CascadingNode(managedNode.getId(), null);
            env.beginTransaction(em);
            em.persist(managedNode);
            env.commitTransactionAndClear(em);
            verifyExistence(em, managedNode);
            env.beginTransaction(em);
            managedNode = em.find(CascadingNode.class, managedNode.getId());
            managedNode.addChild(detachedNode);
            detachedNode.addChild(managedNode);
            CascadingNode mergedNode = em.merge(detachedNode);
            verify(em.contains(mergedNode), "mergedNode not managed");
            verify(mergedNode == managedNode, "mergedNode not identical to managedNode");
            Set<CascadingNode> children = mergedNode.getChildren();
            verify(children.size() == 1, "Wrong number of children: expected 1, got " + children.size());
            CascadingNode child = null;
            for (CascadingNode temp : children) {
                child = temp;
                break;
            }
            verify(child == managedNode, "child is not identical to managedNode");
            env.commitTransactionAndClear(em);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testCascadeManaged() {
        /*
         * If X is a managed entity, it is ignored by the merge operation, however, the merge operation is cascaded to entities
         * referenced by relationships from X if these relationships have been annotated with the cascade element value
         * cascade=MERGE or cascade=ALL annotation.
         *
         * For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL,
         * Y is merged recursively as Y'. For all such Y referenced by X, X' is set to reference Y'. (Note that if X is managed
         * then X is the same object as X'.)
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // states:
            // parent, parentDescription: managed
            // child, childDescription: new
            CascadingNode parent = new CascadingNode(501, null);
            CascadingNodeDescription parentDescription = new CascadingNodeDescription(502, null, "managed parent");
            parent.setDescription(parentDescription);
            CascadingNode child = new CascadingNode(503, null);
            CascadingNodeDescription childDescription = new CascadingNodeDescription(504, null, "new child");
            child.setDescription(childDescription);
            env.beginTransaction(em);
            em.persist(parent);
            env.commitTransactionAndClear(em);
            verifyExistence(em, parent);
            verifyExistence(em, parentDescription);
            verifyAbsence(em, child);
            verifyAbsence(em, childDescription);
            env.beginTransaction(em);
            parent = em.find(CascadingNode.class, parent.getId());
            parent.addChild(child);
            // setup complete
            CascadingNode mergedNode = em.merge(parent);
            verify(mergedNode == parent, "merge returned a copy of the managed entity");
            verify(em.contains(mergedNode), "merged entity not managed");
            CascadingNodeDescription mergedDescription = mergedNode.getDescription();
            verify(mergedDescription.getId() == parentDescription.getId(), "merged entity has wrong id: expected "
                    + parentDescription.getId() + ", got " + mergedNode.getId());
            verify(mergedDescription != parentDescription, "merged entity not a copy");
            verify(em.contains(mergedDescription), "merged entity not managed");
            Set<CascadingNode> mergedChildren = mergedNode.getChildren();
            verify(mergedChildren.size() == 1, "Wrong number of children: expected 1, got " + mergedChildren.size());
            for (CascadingNode temp : mergedChildren) {
                mergedNode = temp;
                break;
            }
            verify(mergedNode.getId() == child.getId(), "merged entity has wrong id: expected " + child.getId() + ", got "
                    + mergedNode.getId());
            verify(mergedNode != child, "merged entity not a copy");
            verify(em.contains(mergedNode), "merged entity not managed");
            mergedDescription = mergedNode.getDescription();
            verify(mergedDescription.getId() == childDescription.getId(), "merged entity has wrong id: expected "
                    + childDescription.getId() + ", got " + mergedNode.getId());
            verify(mergedDescription != childDescription, "merged entity not a copy");
            verify(em.contains(mergedDescription), "merged entity not managed");
            mergedChildren = mergedNode.getChildren();
            verify(mergedChildren == null || mergedChildren.size() == 0, "Node has children, expected none");
            env.commitTransactionAndClear(em);
            verifyExistence(em, parent);
            verifyExistence(em, parentDescription);
            verifyExistence(em, child);
            verifyExistence(em, childDescription);
        } finally {
            closeEntityManager(em);
        }
    }

    @Test
    public void testCascadeRemoved() {
        /*
         * If X is a removed entity instance, an IllegalArgumentException will be thrown by the merge operation (or the
         * transaction commit will fail).
         */
        final JPAEnvironment env = getEnvironment();
        final EntityManager em = env.getEntityManager();
        try {
            // states:
            // parent, parentDescription: new
            // child, childDescription: removed
            CascadingNode parent = new CascadingNode(601, null);
            CascadingNodeDescription parentDescription = new CascadingNodeDescription(602, null, "new parent");
            parent.setDescription(parentDescription);
            CascadingNode child = new CascadingNode(603, null);
            CascadingNodeDescription childDescription = new CascadingNodeDescription(604, null, "removed child");
            child.setDescription(childDescription);
            env.beginTransaction(em);
            em.persist(child);
            env.commitTransactionAndClear(em);
            verifyAbsence(em, parent);
            verifyAbsence(em, parentDescription);
            verifyExistence(em, child);
            verifyExistence(em, childDescription);
            env.beginTransaction(em);
            child = em.find(CascadingNode.class, child.getId());
            em.remove(child);
            parent.addChild(child);
            verify(!em.contains(parent), "parent not new");
            verify(!em.contains(child), "child not removed");
            // setup complete
            boolean mergeFailed = false;
            boolean immediateException = false;
            try {
                em.merge(parent);
            } catch (IllegalArgumentException e) {
                mergeFailed = true;
                immediateException = true;
                verify(!em.contains(parent), "parent not new");
                verify(!em.contains(child), "child not removed");
            }
            if (!immediateException) {
                try {
                    env.commitTransactionAndClear(em);
                } catch (RuntimeException e) {
                    if (!checkForPersistenceException(e)) {
                        throw e;
                    }
                    mergeFailed = true;
                }
            } else {
                env.rollbackTransactionAndClear(em);
            }
            verify(mergeFailed, "merge succeeded on a removed entity");
            verifyAbsence(em, parent);
            verifyAbsence(em, parentDescription);
            verifyExistence(em, child);
            verifyExistence(em, childDescription);
        } finally {
            closeEntityManager(em);
        }
    }

    private void verifyExistence(EntityManager em, Object entity) {
        if (entity instanceof CascadingNode) {
            CascadingNode node = (CascadingNode) entity;
            CascadingNode found = em.find(CascadingNode.class, node.getId());
            verify(found != null, "cascading node with id " + node.getId() + " not found");
        } else if (entity instanceof CascadingNodeDescription) {
            CascadingNodeDescription desc = (CascadingNodeDescription) entity;
            CascadingNodeDescription found = em.find(CascadingNodeDescription.class, desc.getId());
            verify(found != null, "cascading node description with id " + desc.getId() + " not found");
        } else {
            throw new IllegalArgumentException("not supported");
        }
    }

    private void verifyAbsence(EntityManager em, Object entity) {
        if (entity instanceof CascadingNode) {
            CascadingNode node = (CascadingNode) entity;
            CascadingNode found = em.find(CascadingNode.class, node.getId());
            verify(found == null, "cascading node with id " + node.getId() + " found");
        } else if (entity instanceof CascadingNodeDescription) {
            CascadingNodeDescription desc = (CascadingNodeDescription) entity;
            CascadingNodeDescription found = em.find(CascadingNodeDescription.class, desc.getId());
            verify(found == null, "cascading node description with id " + desc.getId() + " found");
        } else {
            throw new IllegalArgumentException("not supported");
        }
    }
}
