EntityPrunerHibernateJpaSetTest.java :  » JPA » entity-pruner » com » saliman » entitypruner » Java Open Source

Java Open Source » JPA » entity pruner 
entity pruner » com » saliman » entitypruner » EntityPrunerHibernateJpaSetTest.java
package com.saliman.entitypruner;

import static com.saliman.entitypruner.testhelper.junit.JunitUtil.assertEjbThrows;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.math.BigInteger;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.EntityExistsException;
import javax.persistence.PersistenceException;

import org.hibernate.collection.PersistentSet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.saliman.entitypruner.testhelper.BaseDaoJpa;
import com.saliman.entitypruner.testhelper.junit.AbstractEjb3ContainerTest;
import com.saliman.entitypruner.testhelper.junit.Transactable;
import com.saliman.entitypruner.testhelper.set.TestSetChildDao;
import com.saliman.entitypruner.testhelper.set.TestSetChildEntity;
import com.saliman.entitypruner.testhelper.set.TestSetParentDao;
import com.saliman.entitypruner.testhelper.set.TestSetParentEntity;
import com.saliman.entitypruner.testhelper.set.TestSetUniChildDao;
import com.saliman.entitypruner.testhelper.set.TestSetUniChildEntity;

/**
 * The test class for the BaseDaoJpa class was getting ridiculously
 * long, so it has been split into 3 separate test classes.  This class tests
 * how the BaseDao operates when dealing with pruning and un-pruning.
 * <p>
 * This class uses the TestParentDaoJpa, TestChildDaoJpa, and
 * TestUniChildDaoJpa helper DAOs to test the methods in {@link BaseDaoJpa}
 * and {@link Persistable} classes.
 * <p>
 * It isn't generally a good idea to have a unit test that tests 2 things, 
 * but we really can't test the prune/unprune methods of the 
 * EntityPruner class without seeing how they save to the database.  This 
 * class has basically the same tests as the BaseDaoJpaTest class, but with
 * pruning and un-pruning.  Where possible, pruning and un-pruning happens
 * outside a transaction, because that is where pruning code needs to be in
 * a deployed Java EE application.
 * <p>
 * From time to time, you may want to see results of this test in the database.
 * To do this, you will need to do 2 things:<br>
 * 1: call <code>setDefaultRollback(false)</code>.
 * 2: Isolate the test you want to see by adding the <code>@Ignore </code> 
 * annotation to the rest of the tests. <b>Do not forget to remove them when
 * you are done!</b><br>
 * If you do choose to commit transactions, you will need to restore the 
 * database to its original state.
 * 
 * @author Steven C. Saliman
 */
public class EntityPrunerHibernateJpaSetTest extends AbstractEjb3ContainerTest  {
    // These constant names reflect OpenEjb naming conventions. We'll need to
    // change these to reflect embedded GlassFish when we switch.
    private static final String PARENT_DAO_NAME = "TestSetParentDaoLocal";
    private static final String CHILD_DAO_NAME = "TestSetChildDaoLocal";
    private static final String UNI_CHILD_DAO_NAME = "TestSetUniChildDaoLocal";
    private static final String PRUNER_NAME = "EntityPrunerLocal";
    private static final String PARENT_TABLE = "TEST_PARENT";
    private static final String CHILD_TABLE = "TEST_CHILD";
    private static final String UNI_CHILD_TABLE = "TEST_UNI_CHILD";
    private static final BigInteger TEST_ID = new BigInteger("-1");
    private static final BigInteger TEST_UNICHILDLESS_ID = new BigInteger("-2");
    private static final BigInteger TEST_CHILDLESS_ID = new BigInteger("-3");
    private static final String USER = "JUNIT";
    private static final String PARENT_SQL = 
        "insert into test_parent(id, code, int_value, description, " +
        "                        create_user, update_user) " +
        "values (?, ?, ?, ?, ?, ?)";
    private static final String CHILD_SQL =
        "insert into test_child(id, test_parent_id, code, description, " +
        "                       create_user, update_user) " +
        "values(?, ?, ?, ?, ?, ?)";
    private static final String UNI_CHILD_SQL =
        "insert into test_uni_child(id, test_parent_id, code, description, " +
        "                       create_user, update_user) " +
        "values(?, ?, ?, ?, ?, ?)";


    private TestSetParentDao parentDao;
    private TestSetChildDao childDao;
    private TestSetUniChildDao uniChildDao;
    private EntityPruner pruner;
    private TestSetParentEntity parent;
    private Set<TestSetChildEntity> children;
    private Set<TestSetUniChildEntity> uniChildren;
    private Set<TestSetChildEntity> transChildren;
    private TestSetChildEntity child;
    private List<TestSetChildEntity> childList;
    private int parentRows = -1;
    private int childRows = -1;
    private int uniChildRows = -1;
    private int numTransChild = -1;

    /**
     * Default Constructor, initializes logging.
     */
    public EntityPrunerHibernateJpaSetTest() {
        super();
    }

    /**
     * Helper method to create the common data needed for each test.
     * Remember, the int_value column in the parent maps to a primitive, which
     * can't be null.
     */
    @SuppressWarnings("boxing")
    private void createData() throws Exception {
        // The first data set is a parent with both types of children.
        executeUpdate(PARENT_SQL, -1, "PARENT1", 0,
                "Test parent with children", USER, USER);
        executeUpdate(CHILD_SQL, -1, -1, "CHILD1", 
                "Test child 1", USER, USER);
        executeUpdate(CHILD_SQL, -2, -1, "CHILD2", 
                "Test child 2", USER, USER);
        executeUpdate(CHILD_SQL, -3, -1, "CHILD3",
                "Test child 3", USER, USER);
        executeUpdate(UNI_CHILD_SQL, -1, -1, "UNICHILD1",
                "Test uni_child 1", USER, USER);
        executeUpdate(UNI_CHILD_SQL, -2, -1, "UNICHILD2",
                "Test uni_child 2", USER, USER);
        executeUpdate(UNI_CHILD_SQL, -3, -1, "UNICHILD3",
                "Test uni_child 3", USER, USER);

        // Insert a parent with no uni-children
        executeUpdate(PARENT_SQL, -2, "PARENT2", 0,
                "Test parent with no uniChildren", USER, USER);
        executeUpdate(CHILD_SQL, -21, -2, "CHILD21",
                "Test child 2-1", USER, USER);
        executeUpdate(CHILD_SQL, -22, -2, "CHILD22",
                "Test child 2-2", USER, USER);
        executeUpdate(CHILD_SQL, -23, -2, "CHILD23",
                "Test child 2-3", USER, USER);

        // Insert a parent with no children at all.
        executeUpdate(PARENT_SQL, -3, "PARENT3", 0,
                "Test parent with no Children", USER, USER);
    }

    /**
     * Helper method to delete old data before and after each test.
     * @throws Exception if anything goes badly.
     */
    private void deleteData() throws Exception {
        // Make sure the DAOs aren't holding on to anything.
//        purgeDaos();
        String sql = "delete from test_child where create_user = '" + USER + "'";
        executeUpdate(sql);
        sql = "delete from test_uni_child where create_user = '" + USER + "'";
        executeUpdate(sql);
        sql = "delete from test_parent where create_user = '" + USER + "'";
        executeUpdate(sql);
    }

    /**
     * Lists up the test by getting what we need from the container.
     * @throws Exception 
     */
    @Before
    public void setUp() throws Exception {
        parentDao = (TestSetParentDao)getBean(PARENT_DAO_NAME);
        assertNotNull("Can't load parent Dao", parentDao);
        childDao = (TestSetChildDao)getBean(CHILD_DAO_NAME);
        assertNotNull("Can't load child Dao", childDao);
        uniChildDao = (TestSetUniChildDao)getBean(UNI_CHILD_DAO_NAME);
        assertNotNull("Can't load uniChildDao", uniChildDao);
        pruner = (EntityPruner)getBean(PRUNER_NAME);
        assertNotNull("Can't load entityPruner", pruner);
        parent = new TestSetParentEntity();
        children = new HashSet<TestSetChildEntity>(2);
        uniChildren = new HashSet<TestSetUniChildEntity>(2);
        parent.setCode("JPARENT1");
        parent.setDescription("Parent 1");
        parent.setAffirmative(Boolean.TRUE); // can't be null;
        parent.setCreateUser(USER);
        parent.setUpdateUser(USER);
        child = new TestSetChildEntity();
        child.setParent(parent);
        child.setCode("JCHILD1");
        child.setDescription("Child 1");
        child.setCreateUser(USER);
        child.setUpdateUser(USER);
        children.add(child);
        parent.setChildren(children);
        TestSetUniChildEntity uniChild = new TestSetUniChildEntity();
        uniChild.setCode("JCHILD1");
        uniChild.setDescription("Child 1");
        uniChild.setCreateUser(USER);
        uniChild.setUpdateUser(USER);
        uniChildren.add(uniChild);
        parent.setUniChildren(uniChildren);
    }

    /**
     * Cleans up after a test by releasing memory used by the test.  We can't 
     * really clear collections, because we may have un-pruned children.
     * @throws Exception if anything goes wrong
     */
    @After
    public void tearDown() throws Exception {
        uniChildren = null;
        children = null;
        parent = null;
        parentDao = null;
        pruner = null;
    }

    /** 
     * Try the following sequence of events:
     * Create a new parent object with null children and uni-children.
     * Un-prune the object.  Do we get an empty PersistentSet?
     * Save the object.  It should succeed. This simulates a new record 
     * coming in from a Web Service.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void insertUnprunedParentNullChildren() throws Exception {
        parent.setChildren(null);
        parent.setUniChildren(null);
        parent.setPruned(true);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        assertNull("unpruning should not have created a child set",
                parent.getChildren());
        assertNull("unpruning should not have created a uniChild set",
                parent.getUniChildren());
        assertNull("unpruning should not have created a transChild set",
                parent.getTransChildren());
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                parent = parentDao.save(parent);
                assertEquals("Failed to insert parent", 
                        parentRows+1, countRowsInTable(PARENT_TABLE));
                assertEquals("Shouldn't have changed children", 
                        childRows, countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed the uniChild table.",
                        uniChildRows,
                        countRowsInTable(UNI_CHILD_TABLE));
            }
        });
    }

    /**
     * Try inserting a new parent with new bidirectional children after
     * un-pruning.  The save should succeed.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void insertUnprunedParentAndChildren() throws Exception {
        parent.setUniChildren(null);
        parent.setPruned(true);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        assertNotNull("unpruning should have kept the a child set",
                parent.getChildren());
        assertNull("unpruning should not have created a uniChild set",
                parent.getUniChildren());
        assertNull("unpruning should not have created a transChild set",
                parent.getTransChildren());
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                parent = parentDao.save(parent);
                assertEquals("Failed to insert parent", 
                        parentRows+1, countRowsInTable(PARENT_TABLE));
                assertEquals("Failed to insert children", 
                        childRows+parent.getChildren().size(),
                        countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed the uniChild table.",
                        uniChildRows,
                        countRowsInTable(UNI_CHILD_TABLE));
            }
        });
    }

    /** 
     * Try inserting a new parent with new unidirectional children after
     * re-hydrating.  This should fail because Hibernate won't resolve the ID
     * in the child records, but the unpruning should work.
     * <p>
     * The actual exception is misleading, but as we discovered in the 
     * BaseDaoJpaTest, this is just something JPA does.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void insertUnprunedParentAndUniChildren() throws Exception {
        parent.setChildren(null);
        parent.setPruned(true);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                assertNull("unpruning should not have created  a child set",
                        parent.getChildren());
                assertNotNull("unpruning should have kept a uniChild set",
                        parent.getUniChildren());
                assertNull("unpruning should not have created a transChild set",
                        parent.getTransChildren());
                assertEjbThrows(EntityExistsException.class, parentDao, "save", parent);
            }
        });
    }

    /** 
     * Try inserting a new parent with new transient children after 
     * un-pruning. This should have no problems.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void insertRehydratedParentAndTransChildren() throws Exception {
        // put the children in the transient collection.
        parent.setTransChildren(parent.getChildren());
        parent.setChildren(null);
        parent.setUniChildren(null);
        parent.setPruned(true);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        assertNull("unpruning should not have created the a child set",
                parent.getChildren());
        assertNull("unpruning should not have created a uniChild set",
                parent.getUniChildren());
        assertNotNull("unpruning should have kept a transChild set",
                parent.getTransChildren());
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                parent = parentDao.save(parent);
                assertEquals("Failed to insert parent", 
                        parentRows+1, countRowsInTable(PARENT_TABLE));
                assertEquals("Shouldn't have changed children", 
                        childRows, countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed the uniChild table.",
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
            }
        });
    }

    /**
     * Try fetching a parent with lazy children (both-types).  Add Transient
     * children and prune the object. Make sure the collections come back
     * null. Make a change to the parent and make sure we can still save the
     * un-pruned object.  This tests the savability of pruned/un-pruned
     * objects, and also tests the collection types of children.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void updateParentWithoutFetchingChildren() throws Exception {
        // This test spans transactions, so we need to commit in this test.
        setDefaultRollback(false);
        // Get children BEFORE fetching the object. Then fetch the parent
        // then set the transient children in the parent. Mess this up
        // And you'll wind up fetching the children from the DB. We 
        // do this inside a transaction because of Java scoping 
        transChildren = new HashSet<TestSetChildEntity>(parent.getChildren().size());
        transChildren.addAll(parent.getChildren());
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parent = parentDao.findById(TEST_ID);
                parent.setTransChildren(transChildren);
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                numTransChild = parent.getTransChildren().size();
            }
        });
        // prune the object outside the transaction.  Change description and
        // un-prune.
        pruner.prune(parent);
        assertNull("Prune should have nulled out the unitialized child set",
                parent.getChildren());
        assertNull("Prune should have nulled out the unitialized uniChild set",
                parent.getUniChildren());
        assertNotNull("Prune should not have nulled out the transChildren",
                parent.getTransChildren());
        parent.setDescription("Updated by updateParentWithoutFetchingChildren");
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        // This time, our null sets should be replaced with PersistentSets.
        children = parent.getChildren();
        assertNotNull("Unprune should have created a PersistentSet for children",
                children);
        assertTrue("The child set is the wrong type",
                PersistentSet.class.isAssignableFrom(children.getClass()));
        uniChildren = parent.getUniChildren();
        assertNotNull("Unprune should have created a PersistentSet for uniChildren",
                uniChildren);
        assertTrue("The uniChild set is the wrong type",
                PersistentSet.class.isAssignableFrom(uniChildren.getClass()));
        // Save the changed object in a new transaction.
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                parent = parentDao.save(parent);
                assertEquals("Shouldn't have changed parent count", 
                        parentRows, countRowsInTable(PARENT_TABLE));
                assertEquals("Shouldn't have changed child count", 
                        childRows, countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed uniChild count", 
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
                assertEquals("Shouldn't have changed the transient child count",
                        numTransChild, parent.getTransChildren().size());
                // Don't forget to clean up.
                deleteData();
            }
        });
    }

    /**
     * Try fetching a parent with lazy children (both-types), and fetch the
     * children. Add Transient children and Prune the object. Make sure
     * the collections come back non-null. Make a change to the parent and make
     * sure we can still save the un-pruned object.  This tests the savability 
     * of pruned/un-pruned objects, and also tests the collection types of 
     * children. This test also makes a change to a child record.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void updateParentFetchingChildren() throws Exception {
        // This test spans transactions, so set rollback to false.
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parent = parentDao.findById(TEST_ID);
                assertTrue("Failed to fetch Children", parent.getChildren().size() > 0);
                assertTrue("Failed to fetch uniChildren", parent.getUniChildren().size() > 0);
                transChildren = new HashSet<TestSetChildEntity>(parent.getChildren().size());
                transChildren.addAll(parent.getChildren());
                parent.setTransChildren(transChildren);
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                numTransChild = parent.getTransChildren().size();
            }
        });
        // prune the parent outside a transaction and make sure we get what 
        // we were expecting.
        pruner.prune(parent);
        children = parent.getChildren();
        assertNotNull("Prune should not null fetched children",
                children);
        assertFalse("The Pruned child set shouldn't be a PersistentSet",
                PersistentSet.class.isAssignableFrom(children.getClass()));
        uniChildren = parent.getUniChildren();
        assertNotNull("Prune should not null fetched uniChildren",
                uniChildren);
        assertFalse("The pruned uniChild set shouldn't be a PersistentSet",
                PersistentSet.class.isAssignableFrom(uniChildren.getClass()));
        String newDesc = "Updated by updateParentFetchingChildren";
        parent.setDescription(newDesc);
        for ( TestSetChildEntity c : parent.getChildren() ) {
            c.setDescription(newDesc);
        }
        for ( TestSetUniChildEntity u : parent.getUniChildren() ) {
            u.setDescription(newDesc);
        }
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        // This time, our null sets should be replaced with PersistentSets.
        children = parent.getChildren();
        assertNotNull("Unprune should have created a Set for children",
                children);
        uniChildren = parent.getUniChildren();
        assertNotNull("Unprune should have created a Set for uniChildren",
                uniChildren);
        
        // Save the updated object in a new transaction
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                parent = parentDao.save(parent);
                assertEquals("Shouldn't have changed parent count", 
                        parentRows, countRowsInTable(PARENT_TABLE));
                assertEquals("Shouldn't have changed child count", 
                        childRows, countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed uniChild count", 
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
                assertEquals("Shouldn't have changed the transient child count",
                        numTransChild, parent.getTransChildren().size());
                // don't forget to clean up
                deleteData();
            }
        });
    }

    /**
     * Try loading a childless parent, pruning, un-pruning, then saving the
     * parent.  This makes sure the un-pruner correctly recreates the proxy
     * collection.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void updateChildlessParent() throws Exception {
        // This test spans transactions, so set rollback to false.
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parent = parentDao.findById(TEST_CHILDLESS_ID);
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
            }
        });
        
        // prune the parent outside a transaction and make sure we get what 
        // we were expecting.
        pruner.prune(parent);
        children = parent.getChildren();
        assertNull("Prune should have pruned unfetched children",
                   children);
        uniChildren = parent.getUniChildren();
        assertNull("Prune should have pruned unfetched uniChildren",
                      uniChildren);
        String newDesc = "Updated by updateChildlessParent";
        parent.setDescription(newDesc);
        runInTransaction(new Transactable() {
          public void run() throws Exception {
            pruner.unprune(parent);
            // This time, our null sets should be replaced with PersistentLists.
            children = parent.getChildren();
            assertNotNull("Unprune should have created a List for children",
                children);
            uniChildren = parent.getUniChildren();
            assertNotNull("Unprune should have created a List for uniChildren",
                uniChildren);
        
                parent = parentDao.save(parent);
                assertEquals("Shouldn't have changed parent count", 
                        parentRows, countRowsInTable(PARENT_TABLE));
                assertEquals("Shouldn't have changed child count", 
                        childRows, countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed uniChild count", 
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
                // don't forget to clean up
                deleteData();
            }
        });
    }

    /**
     * Try loading the childless parent and pruning.  Un-prune it and copy
     * the un-pruned child collections in to a new copy of the childless 
     * parent fetch from the database.  This will test whether or not the 
     * un-prune method is creating the uninitialized proxy collections 
     * properly.  This simulates an actual application scenario where only a
     * part of an incoming entity was copied into a persistent entity for 
     * security purposes.  The observed behavior was an exception due to an 
     * uninitialized transient collection.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void updateCopyOfChildlessParent() throws Exception {
        // This test spans transactions, so set rollback to false.
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parent = parentDao.findById(TEST_CHILDLESS_ID);
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
            }
        });
        
        // prune the parent outside a transaction and make sure we get what 
        // we were expecting.
        pruner.prune(parent);
        children = parent.getChildren();
        assertNull("Prune should have pruned unfetched children",
                   children);
        uniChildren = parent.getUniChildren();
        assertNull("Prune should have pruned unfetched uniChildren",
                      uniChildren);
        runInTransaction(new Transactable() {
          public void run() throws Exception {
            pruner.unprune(parent);
            // This time, our null sets should be replaced with PersistentLists.
            children = parent.getChildren();
            assertNotNull("Unprune should have created a List for children",
                children);
            uniChildren = parent.getUniChildren();
            assertNotNull("Unprune should have created a List for uniChildren",
                uniChildren);
        
            // Load the copy
            TestSetParentEntity copy = parentDao.findById(TEST_CHILDLESS_ID);
            copy.setChildren(parent.getChildren());
            copy.setUniChildren(parent.getUniChildren());
                String newDesc = "Updated by updateChildlessParent";
                copy.setDescription(newDesc);
                copy = parentDao.save(copy);
                assertEquals("Shouldn't have changed parent count", 
                        parentRows, countRowsInTable(PARENT_TABLE));
                assertEquals("Shouldn't have changed child count", 
                        childRows, countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed uniChild count", 
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
                // don't forget to clean up
                deleteData();
            }
        });
    }

    /**
     * Try loading a parent with children.  Make sure the children load 
     * from the database and prune to a depth of 1.  Make sure the children
     * are now null.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void pruneToDepth() throws Exception {
        // we want to do a count between transactions, so we need to 
        // disable rollback.
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parent = parentDao.findById(TEST_ID);
                assertTrue("Failed to fetch Children", parent.getChildren().size() > 0);
                assertTrue("Failed to fetch uniChildren", parent.getUniChildren().size() > 0);
                transChildren = new HashSet<TestSetChildEntity>(parent.getChildren().size());
                transChildren.addAll(parent.getChildren());
                parent.setTransChildren(transChildren);
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                numTransChild = parent.getTransChildren().size();
            }
        });
        // Remember, pruning must happen outside a transaction.  First, 
        // make sure the children are still loaded.
        assertTrue("Failed to fetch Children", parent.getChildren().size() > 0);
        assertTrue("Failed to fetch uniChildren", parent.getUniChildren().size() > 0);
        pruner.prune(parent, 1);
        assertNull("We shouldn't have children anymore", parent.getChildren());
        assertNull("We shouldn't have uniChildren anymore", parent.getUniChildren());
        assertNull("We shouldn't have transient children anymore", parent.getTransChildren());
        // Make sure the counts aren't affected.
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                assertEquals("Shouldn't have changed parent count", 
                        parentRows, countRowsInTable(PARENT_TABLE));
                assertEquals("Shouldn't have changed child count", 
                        childRows, countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed uniChild count", 
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
                // don't forget to clean up
                deleteData();
            }
        });
    }

    /**
     * Try loading a parent with no children.  Access the collections then 
     * prune.  Do we get an empty collection? This should not return null
     * because we actually tried to do a fetch on the children. Try on both 
     * collections.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void pruneChildlessParent() throws Exception {
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parent = parentDao.findById(TEST_CHILDLESS_ID);
                assertTrue("Shouldn't have Children", parent.getChildren().size() == 0);
                assertTrue("Shouldn't have uniChildren", parent.getUniChildren().size() ==0);
            }
        });
        // prune the entity outside a transaction.
        pruner.prune(parent);
        assertNotNull("Should still have child set", parent.getChildren());
        assertEquals("Should have empty child set",
                0, parent.getChildren().size());
        assertNotNull("Should still have uniChild set", parent.getUniChildren());
        assertEquals("Should have empty uniChild set",
                0, parent.getUniChildren().size());
    }

    /**
     * Try creating a child object with a valid (but pruned) parent (from
     * the db). Un-prune the child and try a child save. This simulates
     * creating a child from a web service client.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void insertUnprunedChild() throws Exception {
        // This test spans transactions, so set rollback to false.
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                parent = parentDao.findById(TEST_ID);
            }
        });
        // prune and add the child outside a transaction.  Then un-prune.
        pruner.prune(parent); // simulate giving to client
        child = new TestSetChildEntity();
        child.setParent(parent);
        child.setCode("TESTINS");
        child.setDescription("Inserted by insertUnprunedChild");
        child.setCreateUser(USER);
        child.setUpdateUser(USER);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(child);
            };
        });
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                child = childDao.save(child);
                assertNotNull("Child should now have an ID", child.getId());
                assertEquals("Shouldn't have changed parent table", 
                        parentRows, countRowsInTable(PARENT_TABLE));
                assertEquals("Failed to insert child", 
                        childRows+1, countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed uniChild table", 
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
                // Don't forget to clean up
                deleteData();
            }
        });
    }

    /**
     * Try creating a new child pointing to a new parent and un-prune the 
     * child.  We expect the save to fail because Hibernate wants the parent
     * to be saved first, but the un-prune should work. 
     * @throws Exception if anything goes badly.
     */
    @Test
    public void insertUnprunedChildNewParent() throws Exception {
        parent.setId(null);
        child = new TestSetChildEntity();
        child.setParent(parent);
        child.setCode("TESTINS");
        child.setDescription("Inserted by insertUnprunedChildNewParent");
        child.setCreateUser(USER);
        child.setUpdateUser(USER);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(child);
            };
        });
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                assertEjbThrows(IllegalStateException.class, childDao, "save", child);
            }
        });
    }

    /**
     * Try adding a child to a parent while it's pruned, and saving it
     * when it is un-pruned. For this test the child points to its parent.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void addChildPointingToParent() throws Exception {
        // We need to span transactions
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                parent = parentDao.findById(TEST_ID);
                assertTrue("Need a parent that has children", parent.getChildren().size()>0);
            }
        });
        // prune and add child outside transaction.
        pruner.prune(parent);
        child = new TestSetChildEntity();
        child.setParent(parent);
        child.setCode("TESTINS");
        child.setDescription("Inserted by addChildPointingToParent");
        child.setCreateUser(USER);
        child.setUpdateUser(USER);
        parent.getChildren().add(child);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });

        // Save in new transaction.
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                parent = parentDao.save(parent);
                assertEquals("Shouldn't have changed parent table", 
                        parentRows, countRowsInTable(PARENT_TABLE));
                assertEquals("Failed to insert child", 
                        childRows+1, countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed uniChild table", 
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
                // don't forget to clean up
                deleteData();
            }
        });
    }

    /**
     * Try adding a child to a parent while it's pruned, and saving it
     * when it is un-pruned. For this test the child does not point to its
     * parent, but un-pruned the parent should fix that.  If it doesn't,
     * we'll know because the child won't save with a null parent.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void addChildNotPointingToParent() throws Exception {
        // We need to span transactions
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                parent = parentDao.findById(TEST_ID);
                assertTrue("Need a parent that has children", parent.getChildren().size()>0);
            }
        });
        
        // prune and add child outside transaction.
        pruner.prune(parent);
        child = new TestSetChildEntity();
        child.setCode("TESTINS");
        child.setDescription("Inserted by addChildNotPointingToParent");
        child.setCreateUser(USER);
        child.setUpdateUser(USER);
        parent.getChildren().add(child);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                parent = parentDao.save(parent);
                assertEquals("Shouldn't have changed parent table", 
                        parentRows, countRowsInTable(PARENT_TABLE));
                assertEquals("Failed to insert child", 
                        childRows+1, countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed uniChild table", 
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
                // Don't forget to clean up
                deleteData();
            }
        });
    }

    /**
     * Try adding a uniChild to a parent while it's pruned, and saving it
     * when it is un-pruned. For this test the child points to its parent.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void addUniChildPointingToParent() throws Exception {
        // We need to span transactions
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                parent = parentDao.findById(TEST_ID);
                assertTrue("Need a parent that has uniChildren", parent.getUniChildren().size()>0);
            }
        });

        // prune, change entity, unprune outside transaction.
        pruner.prune(parent);
        TestSetUniChildEntity uniChild = new TestSetUniChildEntity();
        uniChild.setParentId(parent.getId());
        uniChild.setCode("TESTINS");
        uniChild.setDescription("Inserted by addUniChildPointingToParent");
        uniChild.setCreateUser(USER);
        uniChild.setUpdateUser(USER);
        parent.getUniChildren().add(uniChild);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });

        // save in new transaction
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                parent = parentDao.save(parent);
                assertEquals("Shouldn't have changed parent table", 
                        parentRows, countRowsInTable(PARENT_TABLE));
                assertEquals("Shouldn't have changed child table", 
                        childRows, countRowsInTable(CHILD_TABLE));
                assertEquals("Failed to insert uniChild", 
                        uniChildRows+1, countRowsInTable(UNI_CHILD_TABLE));
                // clean up.
                deleteData();
            }
        });
    }

    /**
     * Try adding a child to a parent while it's pruned, and saving it
     * when it is un-pruned. For this test the child does not point to its
     * parent. This save should fail because the child was not set up 
     * correctly, and the de-pruner doesn't have any way to know how to 
     * get the ID.
     * <p>
     * The actual exception is misleading, but as we discovered in the 
     * BaseDaoJpaTest, this is just something JPA does.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void addUniChildNotPointingToParent() throws Exception {
        // we need to span transactions
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parent = parentDao.findById(TEST_ID);
                assertTrue("Need a parent that has uniChildren", parent.getUniChildren().size()>0);
            }
        });
        pruner.prune(parent);
        TestSetUniChildEntity uniChild = new TestSetUniChildEntity();
        uniChild.setCode("TESTINS");
        uniChild.setDescription("Inserted by addChildNotPointingToParent");
        uniChild.setCreateUser(USER);
        uniChild.setUpdateUser(USER);
        parent.getUniChildren().add(uniChild);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                assertEjbThrows(EntityExistsException.class, parentDao, "save", parent);
            }
        });
        // Clean up in a new transaction because the exception above kills
        // the transaction.
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData();
            }
        });
    }

    /**
     * Try adding a child to a parent that never fetched children.  We expect
     * hibernate to keep this sane by only inserting the new item without
     * deleting the old ones.  This only works without the delete-orphan option,
     * which is one of the reasons we don't use that option.<br>
     * If this works, there really isn't a need to test the other collections.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void addChildPointingToParentUnfetched() throws Exception {
        // we need to span transactions
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                parent = parentDao.findById(TEST_ID);
            }
        });
        pruner.prune(parent);
        assertNull("We should have a null child set in the pruned parent",
                parent.getChildren());
        child = new TestSetChildEntity();
        child.setParent(parent);
        child.setCode("TESTINS");
        child.setDescription("Inserted by addChildPointingToParent");
        child.setCreateUser(USER);
        child.setUpdateUser(USER);
        children = new HashSet<TestSetChildEntity>();
        children.add(child);
        parent.setChildren(children);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                parent = parentDao.save(parent);
                assertEquals("Shouldn't have changed parent table", 
                        parentRows, countRowsInTable(PARENT_TABLE));
                assertEquals("Failed to insert child", 
                        childRows+1, countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed uniChild table", 
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
                // don't forget to clean up
                deleteData();
            }
        });
    }

    /**
     * Try loading a parent that only has bidirectional children.  Don't fetch
     * the collection and try a delete. 
     * <p>
     * Note that this test requires multiple sessions.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void deleteParentWithUnfetchedChildren() throws Exception {
        // we need to span transactions
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                parent = parentDao.findById(TEST_UNICHILDLESS_ID);
            }
        });
        // prune and un-prune outside the transaction.
        pruner.prune(parent);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                parentDao.delete(parent);
                assertEquals("Failed to delete parent", 
                        parentRows-1, countRowsInTable(PARENT_TABLE));
                assertTrue("Failed to delete children", 
                        childRows > countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed uniChild table", 
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
                // don't forget to clean up
                deleteData();
            }
        });
    }

    /**
     * Try loading a parent that has unidirectional children.  Don't fetch
     * the collection and try a delete.  We expect the delete fail because we
     * can't disassociate  the uniChildren from it's parent.  This is a 
     * feature of how Hibernate deals with unidirectional joins.
     * <p>
     * Note that this test requires multiple sessions.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void deleteParentWithUnfetchedUniChildren() throws Exception {
        // we need to span transactions
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parent = parentDao.findById(TEST_ID);
            }
        });
        pruner.prune(parent);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                assertEjbThrows(PersistenceException.class, parentDao, "delete", parent);
            }
        });
        // Clean up in a new transaction because the exception above kills
        // the transaction.
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData();
            }
        });
    }

    /**
     * Try loading a parent that only has bidirectional children.  Fetch
     * the collection and try a delete.  We expect the delete to cascade.
     * <p>
     * Note that this test requires multiple sessions.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void deleteParentWithFetchedChildren() throws Exception {
        // We need to span transactions
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parentRows = countRowsInTable(PARENT_TABLE);
                childRows = countRowsInTable(CHILD_TABLE);
                uniChildRows = countRowsInTable(UNI_CHILD_TABLE);
                parent = parentDao.findById(TEST_UNICHILDLESS_ID);
                assertTrue("This test needs child records", parent.getChildren().size()>0);
            }
        });
        // prune and un-prune outside transaction.
        pruner.prune(parent);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        // delete in new transaction.
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                parentDao.delete(parent);
                assertEquals("Failed to delete parent", 
                        parentRows-1, countRowsInTable(PARENT_TABLE));
                assertTrue("Failed to delete children", 
                        childRows > countRowsInTable(CHILD_TABLE));
                assertEquals("Shouldn't have changed uniChild table", 
                        uniChildRows, countRowsInTable(UNI_CHILD_TABLE));
                // clean up
                deleteData();
            }
        });
    }

    /**
     * Try loading a parent that has unidirectional children.  Fetch
     * the collection and try a delete.  We expect the delete fail because we
     * can't disassociate  the uniChildren from it's parent.  This is a 
     * feature of how Hibernate deals with unidirectional joins.
     * <p>
     * Note that this test requires multiple sessions.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void deleteParentWithFetchedUniChildren() throws Exception {
        // We need to span transactions
        setDefaultRollback(false);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                parent = parentDao.findById(TEST_ID);
                assertTrue("This test needs uniChild records", parent.getUniChildren().size()>0);
            }
        });
        pruner.prune(parent);
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                pruner.unprune(parent);
            };
        });
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                assertEjbThrows(PersistenceException.class, parentDao, "delete", parent);
            }
        });
        // Clean up in a new transaction because the exception above kills
        // the transaction.
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData();
            }
        });
    }

    /**
     * This test was designed to test observed behavior in hibernate.
     * In Hibernate, if 2 children refer to the same parent, the parent
     * will only be fetched once, and the same reference will be in both
     * children.  Whatever code we put in to prevent circular reference
     * issues cannot interfere with multiple children trying to prune
     * the same parent.  We'll test this by fetching more than one child, 
     * then making sure the parents don't have Hibernate data types for
     * their child collections.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void fetchChildrenSingleParent() throws Exception {
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                childList = childDao.findByParentId(TEST_ID);
                // This test doesn't work without at least 2 items.
                assertNotNull("Couldn't load any children", childList);
                assertTrue("Need at least 2 children", childList.size() > 1 );
            }
        });
        for ( TestSetChildEntity c : childList ) {
            pruner.prune(c);
            parent = c.getParent();
            // we the parent's children are lazy loaded, so we should not get
            // children
            assertNull("A parent's children should be lazy-loaded, therefore null. Parent NOT pruned",
                    parent.getChildren());
        }
    }

    /**
     * Try fetching a child by it's id.  We want to have an uninitialized
     * proxy for a parent.  Then try pruning.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void fetchChildAndPrune() throws Exception {
        runInTransaction(new Transactable() {
            public void run() throws Exception {
                deleteData(); // in case some other test did a commit.
                createData();
                child = childDao.findById(new BigInteger("-1"));
                // This test doesn't work without at least 2 items.
                assertNotNull("Couldn't load child", child);
                assertEquals("Got wrong child", new BigInteger("-1"), child.getId());
            }
        });
        pruner.prune(child);
        parent = child.getParent();
        // we the parent's children are lazy loaded, so we should not get
        // children
        assertNull("A parent's children should be lazy-loaded, therefore null. Parent NOT pruned",
                parent.getChildren());
    }

    /**
   * Test fetching all children, then pruning with no args.  We should keep
   * all children.
   * @throws Exception if anything goes badly.
   */
  @Test
  public void fetchAllPruneUnlimited() throws Exception {
      runInTransaction(new Transactable() {
          public void run() throws Exception {
                  deleteData(); // in case some other test did a commit.
                  createData();
                  parent = parentDao.findById(TEST_ID);
                  parent.getChildren().size();
                  parent.getUniChildren().size();
          };
      });
      assertNotNull("Test should start with a child set",
              parent.getChildren());
      assertNotNull("Test  should start with a uniChild set",
              parent.getUniChildren());
      pruner.prune(parent);
      assertNotNull("pruner should NOT have pruned the child set",
              parent.getChildren());
      assertNotNull("pruner should NOT have pruned the uniChild set",
              parent.getUniChildren());
  }

  /** 
     * Try fetching all children, then pruning to a level of 1. We should 
     * lose all children.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void fetchAllPruneToDepth() throws Exception {
      runInTransaction(new Transactable() {
          public void run() throws Exception {
                  deleteData(); // in case some other test did a commit.
                  createData();
                  parent = parentDao.findById(TEST_ID);
                  parent.getChildren().size();
                  parent.getUniChildren().size();
          };
      });
      assertNotNull("Test should start with a child set",
              parent.getChildren());
      assertNotNull("Test  should start with a uniChild set",
              parent.getUniChildren());
      pruner.prune(parent, 1);
      assertNull("pruner should have pruned the child set",
              parent.getChildren());
      assertNull("pruner should have pruned the uniChild set",
              parent.getUniChildren());
    }

  /** 
     * Try fetching all children, then pruning to a level of 1. We should 
     * lose all children.  Tests an exclude list of one.
     * @throws Exception if anything goes badly.
     */
    @Test
    public void fetchAllPruneExcludeChild() throws Exception {
      runInTransaction(new Transactable() {
          public void run() throws Exception {
                  deleteData(); // in case some other test did a commit.
                  createData();
                  parent = parentDao.findById(TEST_ID);
                  parent.getChildren().size();
                  parent.getUniChildren().size();
          };
      });
      assertNotNull("Test should start with a child set",
              parent.getChildren());
      assertNotNull("Test  should start with a uniChild set",
              parent.getUniChildren());
      pruner.prune(parent, 10, "children");
      assertNull("pruner should have pruned the child set",
              parent.getChildren());
      assertNotNull("pruner should NOT have pruned the uniChild set",
              parent.getUniChildren());
    }

  /** 
     * Try fetching all children, then pruning, excluding all children. Tests
     * the ability to parse the exclude list. 
     * @throws Exception if anything goes badly.
     */
    @Test
    public void fetchAllPruneExcludeAll() throws Exception {
      runInTransaction(new Transactable() {
          public void run() throws Exception {
                  deleteData(); // in case some other test did a commit.
                  createData();
                  parent = parentDao.findById(TEST_ID);
                  parent.getChildren().size();
                  parent.getUniChildren().size();
          };
      });
      assertNotNull("Test should start with a child set",
              parent.getChildren());
      assertNotNull("Test  should start with a uniChild set",
              parent.getUniChildren());
      pruner.prune(parent, 10, "children, uniChildren");
      assertNull("pruner should have pruned the child set",
              parent.getChildren());
      assertNull("pruner should have pruned the uniChild set",
              parent.getUniChildren());
    }

  /** 
     * Try fetching all children, then pruning, excluding one child and an 
     * invalid attribute. Tests  to make sure an invalid attribute doesn't 
     * prevent the pruner from pruning the valid ones. 
     * @throws Exception if anything goes badly.
     */
    @Test
    public void fetchAllPruneExcludeOneWithInvalud() throws Exception {
      runInTransaction(new Transactable() {
          public void run() throws Exception {
                  deleteData(); // in case some other test did a commit.
                  createData();
                  parent = parentDao.findById(TEST_ID);
                  parent.getChildren().size();
                  parent.getUniChildren().size();
          };
      });
      assertNotNull("Test should start with a child set",
              parent.getChildren());
      assertNotNull("Test  should start with a uniChild set",
              parent.getUniChildren());
      pruner.prune(parent, 10, "asdf,children ");
      assertNull("pruner should have pruned the child set",
              parent.getChildren());
      assertNotNull("pruner should have NOT pruned the uniChild set",
              parent.getUniChildren());
    }

    /**
   * Test fetching all children, then pruning with invalid excludes.  We 
   * should keep all children.
   * @throws Exception if anything goes badly.
   */
  @Test
  public void fetchAllPruneInvalidExclude() throws Exception {
      runInTransaction(new Transactable() {
          public void run() throws Exception {
                  deleteData(); // in case some other test did a commit.
                  createData();
                  parent = parentDao.findById(TEST_ID);
                  parent.getChildren().size();
                  parent.getUniChildren().size();
          };
      });
      assertNotNull("Test should start with a child set",
              parent.getChildren());
      assertNotNull("Test  should start with a uniChild set",
              parent.getUniChildren());
      pruner.prune(parent, 10, "blahblahblah");
      assertNotNull("pruner should NOT have pruned the child set",
              parent.getChildren());
      assertNotNull("pruner should NOT have pruned the uniChild set",
              parent.getUniChildren());
  }

    /**
   * Test fetching no children, then pruning.  We shouldn't have any 
   * collections.
   * @throws Exception if anything goes badly.
   */
  @Test
  public void fetchNonePrune() throws Exception {
      runInTransaction(new Transactable() {
          public void run() throws Exception {
                  deleteData(); // in case some other test did a commit.
                  createData();
                  parent = parentDao.findById(TEST_ID);
          };
      });
      pruner.prune(parent, 10);
      assertNull("pruner should have pruned the child set",
              parent.getChildren());
      assertNull("pruner should have pruned the uniChild set",
              parent.getUniChildren());
  }

    /**
   * Test fetching no children, then pruning, excluding children.  We 
   * shouldn't have any collections.
   * @throws Exception if anything goes badly.
   */
  @Test
  public void fetchNonePruneExclude() throws Exception {
      runInTransaction(new Transactable() {
          public void run() throws Exception {
                  deleteData(); // in case some other test did a commit.
                  createData();
                  parent = parentDao.findById(TEST_ID);
          };
      });
      pruner.prune(parent, 10, "children");
      assertNull("pruner should have pruned the child set",
              parent.getChildren());
      assertNull("pruner should have pruned the uniChild set",
              parent.getUniChildren());
  }

  /**
   * Try fetching all children, then excluding a valid, non-child attribute.
   * This shouldn't change anything.
   * @throws Exception if anything goes badly.
   */
  @Test
  public void fetchAllPruneNonCollection() throws Exception {
      runInTransaction(new Transactable() {
          public void run() throws Exception {
                  deleteData(); // in case some other test did a commit.
                  createData();
                  parent = parentDao.findById(TEST_ID);
                  parent.getChildren().size();
                  parent.getUniChildren().size();
          };
      });
      assertNotNull("Test should start with a code", parent.getCode());
      assertNotNull("Test should start with a child list",
              parent.getChildren());
      assertNotNull("Test  should start with a uniChild list",
              parent.getUniChildren());
      pruner.prune(parent, 10, "code");
      assertNotNull("Test should start with a code", parent.getCode());
      assertNotNull("pruner should NOT have pruned the child list",
              parent.getChildren());
      assertNotNull("pruner should NOT have pruned the uniChild list",
              parent.getUniChildren());
  }
  
  /**
   * Try finding a child, then prune the parent.  This should not do 
   * do anything.
   * @throws Exception if anything goes badly.
   */
  @Test
  public void loadChildPrune() throws Exception {
      runInTransaction(new Transactable() {
          public void run() throws Exception {
                  deleteData(); // in case some other test did a commit.
                  createData();
                  child = childDao.findById(TEST_ID);
                  parent.getChildren().size();
                  parent.getUniChildren().size();
          };
      });
      assertNotNull("Test should start with a parent");
      pruner.prune(child, 10, "parent");
      assertNotNull("Test should not have pruned parent");
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.