Fixed support for move fk violation detection
Additional supporting test cases
- still allows change of effectivity start/end to brake other editions
diff --git a/Temporal Entity Example/src/temporal/BaseTemporalEntity.java b/Temporal Entity Example/src/temporal/BaseTemporalEntity.java
index 59f3d9f..d4d5683 100644
--- a/Temporal Entity Example/src/temporal/BaseTemporalEntity.java
+++ b/Temporal Entity Example/src/temporal/BaseTemporalEntity.java
@@ -67,6 +67,9 @@
     }
 
     public Effectivity getEffectivity() {
+        if (this.effectivity == null) {
+            this.effectivity = new Effectivity();
+        }
         return this.effectivity;
     }
 
diff --git a/Temporal Entity Example/src/temporal/EditionSet.java b/Temporal Entity Example/src/temporal/EditionSet.java
index 1afa9e5..54c393d 100644
--- a/Temporal Entity Example/src/temporal/EditionSet.java
+++ b/Temporal Entity Example/src/temporal/EditionSet.java
@@ -15,7 +15,12 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.persistence.*;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
 
 import org.eclipse.persistence.annotations.ChangeTracking;
 import org.eclipse.persistence.annotations.ChangeTrackingType;
@@ -91,9 +96,8 @@
         return false;
     }
 
-
     protected EditionSetEntry get(Temporal temporal) {
-        for (EditionSetEntry ese: getEntries()) {
+        for (EditionSetEntry ese : getEntries()) {
             if (ese.getTemporal().equals(temporal)) {
                 return ese;
             }
diff --git a/Temporal Entity Example/src/temporal/EditionSetEntry.java b/Temporal Entity Example/src/temporal/EditionSetEntry.java
index ba9a9c6..d0fce36 100644
--- a/Temporal Entity Example/src/temporal/EditionSetEntry.java
+++ b/Temporal Entity Example/src/temporal/EditionSetEntry.java
@@ -122,4 +122,8 @@
         return "EditionSetEntry[" + getTemporal() + "]";
     }
 
+    public boolean isTemporalEntity() {
+       return getTemporal() != null && getTemporal() instanceof TemporalEntity<?>;
+    }
+
 }
diff --git a/Temporal Entity Example/src/temporal/EditionSetHelper.java b/Temporal Entity Example/src/temporal/EditionSetHelper.java
index 200d1e7..63c178f 100644
--- a/Temporal Entity Example/src/temporal/EditionSetHelper.java
+++ b/Temporal Entity Example/src/temporal/EditionSetHelper.java
@@ -24,7 +24,7 @@
 import org.eclipse.persistence.internal.sessions.AbstractSession;
 import org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork;
 import org.eclipse.persistence.mappings.DatabaseMapping;
-import org.eclipse.persistence.mappings.ForeignReferenceMapping;
+import org.eclipse.persistence.mappings.OneToOneMapping;
 
 import temporal.persistence.DescriptorHelper;
 
@@ -80,58 +80,83 @@
     }
 
     /**
-     * Move the provided {@link EditionSet} to the new effective time
+     * Move the provided {@link EditionSet} to the new effective time. In
+     * addition to updating the effective start time for all editions within the
+     * set the move must also handle:
+     * <ul>
+     * <li>Correct any applied change propagation to future editions from the
+     * {@link EditionSet} being moved as well as the surrounding ones at the
+     * source and destination.
+     * <li>Properly updating the start and end time effective time on editions
+     * the surround the source and target of the move.
+     * <li>Update all temporal relationships so that the managed entity is
+     * correct. This includes populating 1:1 and M:1 to ensure they are valid
+     * and not causing broken FKs.
+     * </ul>
      * 
      * @throws IllegalArgumentException
-     *             for invalid effective time or mismatched
-     *             {@link TemporalEntityManager} and {@link EditionSet}
+     *             for invalid effective time
+     * @throws IllegalStateException
+     *             if the current {@link EditionSet} has unwritten changes.
      */
     public static void move(TemporalEntityManager em, long effective) {
         if (effective <= Effectivity.BOT) {
             throw new IllegalArgumentException("Invalid effective time for move: " + effective);
         }
+        RepeatableWriteUnitOfWork uow = em.unwrap(RepeatableWriteUnitOfWork.class);
+        // Reject moves when changes still pending to the current EditionSet
+        if (uow.getUnitOfWorkChangeSet() != null &&  uow.getUnitOfWorkChangeSet().hasChanges()) {
+            throw new IllegalStateException("Cannot move EditionSet with pending changes"); // TODO: Confirm
+        }
         if (!em.hasEditionSet()) {
             em.setEffectiveTime(effective);
             return;
         }
-        RepeatableWriteUnitOfWork uow = em.unwrap(RepeatableWriteUnitOfWork.class);
+
         EditionSet es = em.getEditionSet();
-        // Need to ensure temporal objects are loaded before changing the
-        // effective time.
+
+        // Need to ensure temporal objects in the EditionSetEntry(s) are loaded
+        // as well as the 1:1 related temporals from the edition before changing
+        // the effective time.
         for (EditionSetEntry entry : es.getEntries()) {
             entry.getTemporal();
-        }
+            ClassDescriptor descriptor = DescriptorHelper.getEditionDescriptor(uow, entry.getTemporal().getClass());
+            Set<OneToOneMapping> mappings = DescriptorHelper.getTemporalMappings(descriptor);
+            for (OneToOneMapping mapping : mappings) {
+                mapping.getRealAttributeValueFromObject(entry.getTemporal(), uow);
+            }
+        }        
+
 
         EditionSet newES = new EditionSet(effective);
         em.persist(newES);
         em.setEditionSet(newES);
+        //em.clear();
 
         for (EditionSetEntry entry : es.getEntries()) {
             // Look through relationship mappings for references to temporal
             // which do not exist at the new effective time
             ClassDescriptor descriptor = DescriptorHelper.getEditionDescriptor(uow, entry.getTemporal().getClass());
-            Set<ForeignReferenceMapping> mappings = DescriptorHelper.getTemporalMappings(descriptor);
-            for (ForeignReferenceMapping mapping : mappings) {
-                Temporal currentTarget = (Temporal) mapping.getRealAttributeValueFromObject(entry.getTemporal(), uow);
-                if (currentTarget != null) {
-                    if (currentTarget.getEffectivity().getStart() > effective) {
-                        // TODO: What about pending changes?
-                        uow.getIdentityMapAccessor().invalidateObject(currentTarget);
-                    }
+            Set<OneToOneMapping> mappings = DescriptorHelper.getTemporalMappings(descriptor);
 
-                    Object id = ((TemporalEntity<?>) currentTarget).getContinuityId();
-                    if (id instanceof Object[] || id instanceof Vector) {
-                        throw new RuntimeException("Composite Key not supported");
+            for (OneToOneMapping mapping : mappings) {
+                Temporal currentTarget = (Temporal) mapping.getRealAttributeValueFromObject(entry.getTemporal(), uow);
+
+                if (currentTarget != null) {
+
+                    if (!currentTarget.getEffectivity().includes(effective)) {
+                        
+                        Object id = ((TemporalEntity<?>) currentTarget).getContinuityId();
+                        if (id instanceof Object[] || id instanceof Vector) {
+                            throw new RuntimeException("Composite Key not supported");
+                        }
+                        @SuppressWarnings("unchecked")
+                        Temporal target = em.find(mapping.getReferenceClass(), id);
+                        if (target == null) {
+                            throw new IllegalStateException();
+                        }
+                        mapping.setRealAttributeValueInObject(entry.getTemporal(), target);
                     }
-                    @SuppressWarnings("unchecked")
-                    Temporal target = em.find(mapping.getReferenceClass(), id);
-                    if (target == null) {
-                        throw new IllegalStateException();
-                    }
-                    mapping.setRealAttributeValueInObject(entry.getTemporal(), target);
-                } else {
-                    // TODO
-                    //throw new IllegalStateException();
                 }
             }
 
@@ -139,6 +164,7 @@
             newES.getEntries().add(entry);
             entry.setEditionSet(newES);
         }
+        // Clear the moved entries from the EditionSet being removed.
         es.getEntries().clear();
         em.remove(es);
 
diff --git a/Temporal Entity Example/src/temporal/Effectivity.java b/Temporal Entity Example/src/temporal/Effectivity.java
index bcd10a0..545dee7 100644
--- a/Temporal Entity Example/src/temporal/Effectivity.java
+++ b/Temporal Entity Example/src/temporal/Effectivity.java
@@ -113,4 +113,11 @@
         }
         return Long.toString(ts);
     }
+
+    public boolean includes(Long effective) {
+        if (effective == null) {
+            return includes(BOT);
+        }
+        return getStart() <= effective && getEnd() > effective;
+    }
 }
\ No newline at end of file
diff --git a/Temporal Entity Example/src/temporal/TemporalEntityManager.java b/Temporal Entity Example/src/temporal/TemporalEntityManager.java
index 401ea30..bd38f1b 100644
--- a/Temporal Entity Example/src/temporal/TemporalEntityManager.java
+++ b/Temporal Entity Example/src/temporal/TemporalEntityManager.java
@@ -35,6 +35,8 @@
 import org.eclipse.persistence.queries.DatabaseQuery;
 import org.eclipse.persistence.queries.ObjectLevelReadQuery;
 import org.eclipse.persistence.sessions.Session;
+import org.eclipse.persistence.sessions.changesets.ObjectChangeSet;
+import org.eclipse.persistence.sessions.changesets.UnitOfWorkChangeSet;
 
 import temporal.persistence.AbstractEntityManagerWrapper;
 import temporal.persistence.DescriptorHelper;
@@ -113,8 +115,44 @@
         return unwrap(RepeatableWriteUnitOfWork.class);
     }
 
+    /**
+     * TODO
+     * 
+     * @param startTime
+     * @throws IllegalStateException
+     *             if there are any {@link Temporal} objects with changes
+     *             pending.
+     */
     public void setEffectiveTime(Long startTime) {
         if (startTime != getEffectiveTime()) {
+            RepeatableWriteUnitOfWork uow = getUnitOfWork();
+            UnitOfWorkChangeSet unitOfWorkChangeSet = uow.getUnitOfWorkChangeSet();
+
+            // Ensure there are no pending changes for any objects in the
+            // current EditionSet
+            if (hasEditionSet() && unitOfWorkChangeSet != null && unitOfWorkChangeSet.hasChanges()) {
+                for (EditionSetEntry ese : getEditionSet().getEntries()) {
+                    ObjectChangeSet objectChanges = unitOfWorkChangeSet.getObjectChangeSetForClone(ese.getTemporal());
+                    if (objectChanges != null && objectChanges.hasChanges()) {
+                        throw new IllegalStateException("Changes pending for current EditionSet. You must commit, Rollback, or flush changes before changing effective time");
+                    }
+                }
+            }
+
+            // Remove any temporal objects in cache which are not valid for the
+            // provided effective time
+            for (Object object : uow.getCloneMapping().keySet()) {
+                if (object instanceof Temporal && !((Temporal) object).getEffectivity().includes(effective)) {
+                    if (uow.getUnitOfWorkChangeSet() != null) {
+                        ObjectChangeSet ocs = uow.getUnitOfWorkChangeSet().getObjectChangeSetForClone(object);
+                        if (ocs != null && ocs.hasChanges()) {
+                            throw new IllegalStateException("Temporal entity has changes pending: " + object);
+                        }
+                    }
+                    uow.getIdentityMapAccessor().removeFromIdentityMap(object);
+                }
+            }
+
             this.editionSet = null;
         }
 
@@ -122,11 +160,6 @@
         setProperty(EFF_TS_PROPERTY, startTime);
     }
 
-    public void clearEffectiveTime() {
-        this.effective = null;
-        setProperty(EFF_TS_PROPERTY, null);
-    }
-
     /**
      * @return the effective time using the {@link #editionSet} if available.
      */
@@ -164,9 +197,8 @@
     }
 
     protected void setEditionSet(EditionSet editionSet) {
+        setEffectiveTime(editionSet.getEffective());
         this.editionSet = editionSet;
-        this.effective = editionSet.getEffective();
-        setProperty(EFF_TS_PROPERTY, editionSet.getEffective());
     }
 
     public boolean hasEditionSet() {
@@ -336,6 +368,8 @@
 
         TemporalEntity<T> edition = (TemporalEntity<T>) descriptor.getInstantiationPolicy().buildNewInstance();
         edition.setContinuity((T) edition);
+        edition.getEffectivity();
+
         if (start != null) {
             edition.getEffectivity().setStart(start);
         }
@@ -511,13 +545,30 @@
             if (ese != null) {
                 super.remove(ese);
             }
-        }
-        if (entity instanceof TemporalEntity<?>) {
+        } else if (entity instanceof EditionSet) {
+            EditionSet es = (EditionSet) entity;
+            for (EditionSetEntry ese : es.getEntries()) {
+                if (ese.isTemporalEntity()) {
+                    ese.getTemporalEntity().setContinuity(null);
+                }
+                super.remove(ese.getTemporal());
+            }
+            super.remove(es);
+            this.editionSet = null;
+            return;
+        } else if (entity instanceof TemporalEntity<?>) {
             ((TemporalEntity<?>) entity).setContinuity(null);
         }
+
         super.remove(entity);
     }
 
+    @Override
+    public void clear() {
+        super.clear();
+        setEffectiveTime(null);
+    }
+
     public String toString() {
         return "TemporalEntityManager@" + getEffectiveTime() + "[" + getEntityManager() + "]";
     }
diff --git a/Temporal Entity Example/src/temporal/persistence/ConfigureTemporalDescriptors.java b/Temporal Entity Example/src/temporal/persistence/ConfigureTemporalDescriptors.java
index a87d55f..65a897e 100644
--- a/Temporal Entity Example/src/temporal/persistence/ConfigureTemporalDescriptors.java
+++ b/Temporal Entity Example/src/temporal/persistence/ConfigureTemporalDescriptors.java
@@ -244,7 +244,7 @@
      */
     @SuppressWarnings("unchecked")
     private void fixEditionRelationships(ClassDescriptor descriptor, DynamicClassLoader dcl, String suffix) throws ClassNotFoundException {
-        Set<ForeignReferenceMapping> temporalMappings = new HashSet<ForeignReferenceMapping>();
+        Set<OneToOneMapping> temporalMappings = new HashSet<OneToOneMapping>();
         descriptor.setProperty(DescriptorHelper.TEMPORAL_MAPPINGS, temporalMappings);
         
         // Point all reference mappings to TemporalEntity to edition classes
@@ -270,8 +270,9 @@
                         contMapping.getSelectionQuery().setRedirector(new ContinuityMappingQueryRedirector());
                         ((ReadObjectQuery) contMapping.getSelectionQuery()).setReferenceClass(frMapping.getReferenceClass());
                     } else if (frMapping.isOneToOneMapping()) {
-                        fixFKNames(((OneToOneMapping) frMapping).getSourceToTargetKeyFields());
-                        temporalMappings.add(frMapping);
+                        OneToOneMapping otoMapping = (OneToOneMapping) frMapping;
+                        fixFKNames((otoMapping).getSourceToTargetKeyFields());
+                        temporalMappings.add(otoMapping);
                     } else if (frMapping.isOneToManyMapping()) {
                         OneToManyMapping otMMapping = (OneToManyMapping) frMapping;
                         fixFKNames(otMMapping.getTargetForeignKeysToSourceKeys());
diff --git a/Temporal Entity Example/src/temporal/persistence/DescriptorHelper.java b/Temporal Entity Example/src/temporal/persistence/DescriptorHelper.java
index f05d345..a269ab3 100644
--- a/Temporal Entity Example/src/temporal/persistence/DescriptorHelper.java
+++ b/Temporal Entity Example/src/temporal/persistence/DescriptorHelper.java
@@ -13,24 +13,15 @@
 package temporal.persistence;
 
 import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Member;
 import java.lang.reflect.Proxy;
 import java.util.Set;
 
 import javax.persistence.EntityManager;
 
 import org.eclipse.persistence.descriptors.ClassDescriptor;
-import org.eclipse.persistence.internal.descriptors.InstanceVariableAttributeAccessor;
-import org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor;
-import org.eclipse.persistence.internal.sessions.AbstractSession;
-import org.eclipse.persistence.mappings.DatabaseMapping;
-import org.eclipse.persistence.mappings.ForeignReferenceMapping;
+import org.eclipse.persistence.mappings.OneToOneMapping;
 import org.eclipse.persistence.sessions.Session;
 
-import temporal.BaseEntity;
-import temporal.TemporalEntity;
-import temporal.TemporalHelper;
-
 /**
  * This helper is used in to configure and access the temporal values of an
  * {@link EntityManager} and its managed entities.
@@ -61,35 +52,6 @@
      */
     public static final String TEMPORAL_MAPPINGS = "TemporalMappings";
 
-    /**
-     * Copy mapped value from source to new edition. This copies the real
-     * attribute value.
-     */
-    protected static void copyValue(AbstractSession session, DatabaseMapping mapping, TemporalEntity<?> source, TemporalEntity<?> target) {
-        if (mapping.getAttributeName().equals("effectivity")) {
-            return;
-        }
-
-        String nonTemporal = (String) mapping.getProperty(TemporalHelper.NON_TEMPORAL);
-        if (nonTemporal != null && Boolean.valueOf(nonTemporal)) {
-            return;
-        }
-
-        Member member = null;
-
-        if (mapping.getAttributeAccessor().isInstanceVariableAttributeAccessor()) {
-            member = ((InstanceVariableAttributeAccessor) mapping.getAttributeAccessor()).getAttributeField();
-        } else {
-            member = ((MethodAttributeAccessor) mapping.getAttributeAccessor()).getGetMethod();
-        }
-        if (member.getDeclaringClass().equals(BaseEntity.class)) {
-            return;
-        }
-
-        Object value = mapping.getRealAttributeValueFromObject(source, session);
-        mapping.setRealAttributeValueInObject(target, value);
-    }
-
     private static ClassDescriptor getDescriptor(Session session, Class<?> entityClass, String type) {
         ClassDescriptor desc = session.getClassDescriptor(entityClass);
         if (desc == null) {
@@ -130,8 +92,8 @@
     }
     
     @SuppressWarnings("unchecked")
-    public static Set<ForeignReferenceMapping> getTemporalMappings(ClassDescriptor descriptor) {
-        return (Set<ForeignReferenceMapping>) descriptor.getProperty(TEMPORAL_MAPPINGS);
+    public static Set<OneToOneMapping> getTemporalMappings(ClassDescriptor descriptor) {
+        return (Set<OneToOneMapping>) descriptor.getProperty(TEMPORAL_MAPPINGS);
     }
 
 }
diff --git a/Temporal Entity Example/src/temporal/persistence/PropagateEditionChangesListener.java b/Temporal Entity Example/src/temporal/persistence/PropagateEditionChangesListener.java
index 7d8f4cf..09ffab7 100644
--- a/Temporal Entity Example/src/temporal/persistence/PropagateEditionChangesListener.java
+++ b/Temporal Entity Example/src/temporal/persistence/PropagateEditionChangesListener.java
@@ -48,9 +48,10 @@
         RepeatableWriteUnitOfWork uow = (RepeatableWriteUnitOfWork) event.getSession();
         UnitOfWorkChangeSet uowCS = (UnitOfWorkChangeSet) uow.getUnitOfWorkChangeSet();
         TemporalEntityManager tem = TemporalEntityManager.getInstance(uow);
-        EditionSet es = tem.getEditionSet();
 
         if (tem.hasEditionSet() && tem.getEditionSet().hasChanges() && uowCS.hasChanges()) {
+            EditionSet es = tem.getEditionSet();
+
             for (EditionSetEntry entry : es.getEntries()) {
                 ObjectChangeSet objCS = uowCS.getCloneToObjectChangeSet().get(entry.getTemporal());
                 List<TemporalEntity<?>> futures = findFutureEditions(uow, entry);
@@ -60,7 +61,9 @@
                         ChangeRecord cr = (ChangeRecord) objCS.getAttributesToChanges().get(attr);
                         entry.getAttributes().add(attr);
 
-                        propogateChanges(uow, futures, entry, cr);
+                        if (!cr.getMapping().getAttributeName().equals("continuity")) {
+                            propogateChanges(uow, futures, entry, cr);
+                        }
                     }
                 }
             }
diff --git a/Temporal Tests/src/tests/AllFullPersonTests.java b/Temporal Tests/src/tests/AllFullPersonTests.java
new file mode 100644
index 0000000..547c643
--- /dev/null
+++ b/Temporal Tests/src/tests/AllFullPersonTests.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2012 Oracle. All rights reserved. This program and the
+ * accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 and Eclipse Distribution License v. 1.0 which accompanies
+ * this distribution. The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
+ * License is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ * 
+ * Contributors: dclarke - Bug 361016: Future Versions Examples
+ ******************************************************************************/
+package tests;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import tests.editionsets.FullPersonWithEditionsDelete;
+import tests.editionsets.FullPersonWithEditionsMove;
+
+/**
+ * Test suite to debug issues with multiple subclasses of {@link FullPersonWithEditions} 
+ */
+@RunWith(Suite.class)
+@SuiteClasses({ FullPersonWithEditionsQueries.class, 
+                FullPersonWithEditionsMods.class,
+                FullPersonWithEditionsMove.class,
+                FullPersonWithEditionsDelete.class})
+public class AllFullPersonTests {
+}
diff --git a/Temporal Tests/src/tests/AllTests.java b/Temporal Tests/src/tests/AllTests.java
index 1f0a617..56d2574 100644
--- a/Temporal Tests/src/tests/AllTests.java
+++ b/Temporal Tests/src/tests/AllTests.java
@@ -16,12 +16,11 @@
 
 @RunWith(Suite.class)
 @SuiteClasses({ tests.internal.AllTests.class, 
-                FullPersonWithEditions.class, 
+                FullPersonWithEditionsQueries.class, 
+                FullPersonWithEditionsMods.class,
                 FuturePersonTests.class,
                 DeleteTests.class,
                 ProxyWrapperUpdateTests.class,
-                //ModifyCurrentTests.class})
-                //DeleteContinuityTests.class,
                 MultipleEditionQueries.class,
                 DuplicateInsertOnCreateMerge.class,
                 tests.editionsets.AllTests.class})
diff --git a/Temporal Tests/src/tests/BaseTestCase.java b/Temporal Tests/src/tests/BaseTestCase.java
index 5b792ce..26215a6 100644
--- a/Temporal Tests/src/tests/BaseTestCase.java
+++ b/Temporal Tests/src/tests/BaseTestCase.java
@@ -24,6 +24,7 @@
 import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.rules.TestName;
 
@@ -47,7 +48,7 @@
 
     public EntityManagerFactory getEMF() {
         if (emf == null) {
-            
+
             Map<String, Object> properties = new HashMap<String, Object>();
             properties.put(PersistenceUnitProperties.TRANSACTION_TYPE, "RESOURCE_LOCAL");
             properties.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, "");
@@ -55,7 +56,7 @@
             properties.put(PersistenceUnitProperties.JDBC_URL, "jdbc:mysql://localhost:3306/test");
             properties.put(PersistenceUnitProperties.JDBC_USER, "root");
             properties.put(PersistenceUnitProperties.JDBC_PASSWORD, "password");
-            
+
             emf = Persistence.createEntityManagerFactory("example", properties);
 
             Server session = JpaHelper.getServerSession(emf);
@@ -67,11 +68,8 @@
             sm.replaceSequences();
 
             // Populate test case example instances
-            TemporalEntityManager em = TemporalEntityManager.getInstance(emf.createEntityManager());
-            em.getTransaction().begin();
-            populate(em);
-            em.getTransaction().commit();
-            em.close();
+            populate(emf);
+
             System.out.println("\n--- CREATE EMF & POPULATE DONE ---\n");
 
             closeEntityManager();
@@ -92,10 +90,22 @@
         return this.entityManager;
     }
 
-    public void populate(TemporalEntityManager em) {
+    protected void populate(EntityManagerFactory emf) {
+        TemporalEntityManager em = TemporalEntityManager.getInstance(emf.createEntityManager());
+        em.getTransaction().begin();
+        try {
+            populate(em);
+            em.getTransaction().commit();
+        } finally {
+            em.close();
+        }
+    }
+
+    protected void populate(TemporalEntityManager em) {
     }
 
     @AfterClass
+    @BeforeClass
     public static void closeEMF() {
         if (emf != null && emf.isOpen()) {
             emf.close();
diff --git a/Temporal Tests/src/tests/DuplicateInsertOnCreateMerge.java b/Temporal Tests/src/tests/DuplicateInsertOnCreateMerge.java
index 1e4ee41..b99ce9b 100644
--- a/Temporal Tests/src/tests/DuplicateInsertOnCreateMerge.java
+++ b/Temporal Tests/src/tests/DuplicateInsertOnCreateMerge.java
@@ -93,6 +93,8 @@
         em.getTransaction().commit();
 
         em.clear();
+        em.setEffectiveTime(T2);
+        
         personEditionT2 = em.find(Person.class, getSample().getId());
 
         Assert.assertNotNull(personEditionT2);
diff --git a/Temporal Tests/src/tests/FullPersonWithEditions.java b/Temporal Tests/src/tests/FullPersonWithEditions.java
index db353e9..b190bc6 100644
--- a/Temporal Tests/src/tests/FullPersonWithEditions.java
+++ b/Temporal Tests/src/tests/FullPersonWithEditions.java
@@ -13,34 +13,20 @@
 import static example.PersonModelExample.GOLF;
 import static example.PersonModelExample.RUN;
 import static example.PersonModelExample.SKI;
-import static example.PersonModelExample.T1;
 import static example.PersonModelExample.T2;
-import static example.PersonModelExample.T3;
 import static example.PersonModelExample.T4;
-import static example.PersonModelExample.T5;
-import static temporal.Effectivity.BOT;
-import static temporal.Effectivity.EOT;
 
 import java.sql.Date;
-import java.util.List;
 
-import javax.persistence.NoResultException;
-import javax.persistence.TypedQuery;
+import javax.persistence.EntityManagerFactory;
 
+import junit.framework.Assert;
 import model.Address;
 import model.Person;
 import model.Phone;
 import model.entities.PhoneEntity;
-
-import org.eclipse.persistence.jpa.JpaHelper;
-import org.eclipse.persistence.sessions.CopyGroup;
-import org.junit.Assert;
-import org.junit.Test;
-
-import temporal.BaseEntity;
-import temporal.EditionSet;
+import temporal.Effectivity;
 import temporal.TemporalEntityManager;
-import temporal.TemporalHelper;
 import example.PersonModelExample;
 
 /**
@@ -50,18 +36,22 @@
  * @author dclarke
  * @since EclipseLink 2.3.1
  */
-public class FullPersonWithEditions extends BaseTestCase {
+public abstract class FullPersonWithEditions extends BaseTestCase {
 
-    private static PersonModelExample example = new PersonModelExample();
+    private static PersonModelExample example = null;
 
-    private Person getSample() {
+    protected Person getSample() {
         return example.fullPerson;
     }
 
     @SuppressWarnings("deprecation")
     @Override
-    public void populate(TemporalEntityManager em) {
+    public void populate(EntityManagerFactory emf) {
         System.out.println("\nFullPersonWithEditions.populate:START");
+        example = new PersonModelExample();
+
+        TemporalEntityManager em = TemporalEntityManager.getInstance(emf.createEntityManager());
+        em.getTransaction().begin();
 
         example.populateHobbies(em);
         em.persist(example.fullPerson);
@@ -71,6 +61,7 @@
         em.setEffectiveTime(T2);
 
         Person fpEdition = em.find(Person.class, example.fullPerson.getId());
+
         Person personEditionT2 = em.newEdition(fpEdition);
 
         personEditionT2.setName("Jimmy");
@@ -90,16 +81,13 @@
 
         em.persist(personEditionT2.addHobby(example.hobbies.get(GOLF), T2));
 
-        // Assert.assertEquals(personEditionT2.getPhones().size() - 1,
-        // fpEdition.getPhones().size());
-        // Assert.assertEquals(personEditionT2.getPersonHobbies().size() - 1,
-        // fpEdition.getPersonHobbies().size());
-
         em.flush();
 
         System.out.println("\n> Create T4 Edition");
         em.setEffectiveTime(T4);
 
+        fpEdition = em.find(Person.class, example.fullPerson.getId());
+
         Person personEditionT4 = em.newEdition(personEditionT2);
         personEditionT4.setName("James");
         Address aT4 = em.newEdition(aT2);
@@ -123,680 +111,79 @@
 
         em.flush();
 
+        em.getTransaction().commit();
+        em.close();
+
+        verifyPopulate(emf);
+
         System.out.println("\nFullPersonWithEditions.populate::DONE");
     }
 
-    @Test
-    public void queryAllCurrent() {
-        TemporalEntityManager em = getEntityManager();
-        List<Person> results = em.createQuery("SELECT p From Person p", Person.class).getResultList();
+    protected void verifyPopulate(EntityManagerFactory emf) {
+        TemporalEntityManager em = TemporalEntityManager.getInstance(emf.createEntityManager());
+        verifyCurrent(em);
+        em.close();
 
-        System.out.println("QUERY CURRENT:");
-        for (Person p : results) {
-            System.out.println("\t>" + p);
-        }
+        em = TemporalEntityManager.getInstance(emf.createEntityManager());
+        verifyT2(em);
+        em.close();
 
-        Assert.assertEquals(1, results.size());
-
-        Person currentperson = results.get(0);
-        Assert.assertSame(currentperson, currentperson.getContinuity());
-        Assert.assertEquals(getSample().getId(), currentperson.getId());
+        em = TemporalEntityManager.getInstance(emf.createEntityManager());
+        verifyT4(em);
+        em.close();
     }
 
-    @Test
-    public void findCurrent() {
-        TemporalEntityManager em = getEntityManager();
+    public void verifyCurrent(TemporalEntityManager em) {
+        em.setEffectiveTime(Effectivity.BOT);
 
-        Person current = em.find(Person.class, getSample().getId());
+        Person person = em.find(Person.class, getSample().getContinuityId());
 
-        System.out.println("VERIFY CURRENT: " + current);
+        Assert.assertNotNull(person);
 
-        // Verify person
-        Assert.assertNotNull(current);
-        Assert.assertEquals(current, current.getContinuity());
-        Assert.assertEquals(getSample().getId(), current.getId());
-        Assert.assertEquals(getSample().getName(), current.getName());
-        Assert.assertTrue(current.getEffectivity().isCurrent());
-        Assert.assertFalse(current.getEffectivity().isFutureEdition());
-        Assert.assertEquals(current.getEffectivity().getStart(), BOT);
-        Assert.assertEquals(current.getEffectivity().getEnd(), T2);
-
-        // Address
-        Assert.assertNotNull(current.getAddress());
-        Assert.assertEquals(getSample().getAddress().getStreet(), current.getAddress().getStreet());
-        Assert.assertEquals(getSample().getAddress().getCity(), current.getAddress().getCity());
-        Assert.assertEquals(getSample().getAddress().getState(), current.getAddress().getState());
-        Assert.assertTrue(current.getAddress().getEffectivity().isCurrent());
-        Assert.assertFalse(current.getAddress().getEffectivity().isFutureEdition());
-        Assert.assertEquals(current.getAddress().getEffectivity().getStart(), BOT);
-        Assert.assertEquals(current.getAddress().getEffectivity().getEnd(), T2);
-
-        // Phone
-        Assert.assertEquals(1, current.getPhones().size());
-        Phone currentHome = current.getPhone("Home");
-        Assert.assertNotNull(currentHome);
-        Assert.assertEquals("111-111-1111", currentHome.getNumber());
-        Assert.assertSame(current, currentHome.getPerson());
-    }
-
-    @Test
-    public void queryAllCurrentJoinAddress() {
-        TemporalEntityManager em = getEntityManager();
-        List<Person> results = em.createQuery("SELECT p From Person p JOIN FETCH p.address", Person.class).getResultList();
-
-        System.out.println("QUERY CURRENT:");
-        for (Person p : results) {
-            System.out.println("\t>" + p);
-        }
-
-        Assert.assertEquals(1, results.size());
-
-        Person currentperson = results.get(0);
-        Assert.assertSame(currentperson, currentperson.getContinuity());
-        Assert.assertEquals(getSample().getId(), currentperson.getId());
-    }
-
-    @Test
-    public void querySampleCurrentPerson() {
-        TemporalEntityManager em = getEntityManager();
-
-        Person person = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
         Address address = person.getAddress();
-
-        Assert.assertNotNull(person);
-
-        System.out.println("FIND CURRENT: " + person);
-
-        Assert.assertEquals(getSample().getId(), person.getId());
-        Assert.assertSame(person, person.getContinuity());
         Assert.assertNotNull(address);
-        Assert.assertEquals(getSample().getAddress().getCity(), address.getCity());
-    }
-
-    @Test
-    public void querySampleCurrentPersonJoinAddress() {
-        TemporalEntityManager em = getEntityManager();
-
-        Person person = em.createQuery("SELECT p From Person p JOIN FETCH p.address WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
-        Address address = person.getAddress();
-
-        Assert.assertNotNull(person);
-
-        System.out.println("FIND CURRENT: " + person);
-
-        Assert.assertEquals(getSample().getId(), person.getId());
-        Assert.assertEquals(person, person.getContinuity());
-        Assert.assertNotNull(address);
-        Assert.assertEquals(getSample().getAddress().getCity(), address.getCity());
-    }
-
-    @Test
-    public void findSampleCurrentPerson() {
-        TemporalEntityManager em = getEntityManager();
-        Person person = em.find(Person.class, getSample().getId());
-
-        Assert.assertNotNull(person);
-
-        System.out.println("FIND CURRENT: " + person);
-
-        Assert.assertEquals(getSample().getId(), person.getId());
-        Assert.assertSame(person, person.getContinuity());
-        Assert.assertTrue(person.getEffectivity().isCurrent());
-        Assert.assertFalse(person.getEffectivity().isFutureEdition());
-        Assert.assertEquals(person.getEffectivity().getStart(), BOT);
-        Assert.assertEquals(person.getEffectivity().getEnd(), T2);
-
-        Assert.assertEquals(0, person.getPersonHobbies().size());
 
         Assert.assertEquals(1, person.getPhones().size());
 
+        Phone homePhone = person.getPhone("Home");
+        Assert.assertNotNull(homePhone);
     }
 
-    @Test
-    public void findFuturePersonEntityEditionT2() {
-        TemporalEntityManager em = getEntityManager();
+    public void verifyT2(TemporalEntityManager em) {
         em.setEffectiveTime(T2);
 
-        Person person = em.find(Person.class, getSample().getId());
+        Person person = em.find(Person.class, getSample().getContinuityId());
+
         Assert.assertNotNull(person);
-        System.out.println("FIND Future Edition: " + person);
-        Assert.assertEquals(1, person.getPersonHobbies().size());
 
-        Person continuity = person.getContinuity();
-
-        Assert.assertNotNull(continuity);
-        System.out.println("\tContinuity: " + continuity);
-        Assert.assertTrue("Not an edition entity", TemporalHelper.isEdition(em, person));
-        Assert.assertEquals(getSample().getId(), person.getContinuity().getId());
-
-        Assert.assertFalse(person.getEffectivity().isCurrent());
-        Assert.assertTrue(person.getEffectivity().isFutureEdition());
-        Assert.assertEquals(person.getEffectivity().getStart(), T2);
-        Assert.assertEquals(person.getEffectivity().getEnd(), T4);
-        Assert.assertNotSame(person, person.getContinuity());
-    }
-
-    @Test
-    public void queryFutureEditionOfCurrentPersonAtBOT() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(BOT);
-
-        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
-
-        System.out.println("QUERY EDITION @ BOT: " + pEdition);
-
-        Assert.assertNotNull("No edition found at BOT", pEdition);
-        Assert.assertTrue(pEdition.getEffectivity().isCurrent());
-        Assert.assertFalse(pEdition.getEffectivity().isFutureEdition());
-        Assert.assertEquals(BOT, pEdition.getEffectivity().getStart());
-        Assert.assertEquals(T2, pEdition.getEffectivity().getEnd());
-        Assert.assertNotNull("No Continuity found", pEdition.getContinuity());
-        Assert.assertEquals(0, pEdition.getPersonHobbies().size());
-
-        Address address = pEdition.getAddress();
-
+        Address address = person.getAddress();
         Assert.assertNotNull(address);
-        Assert.assertEquals(getSample().getAddress().getCity(), address.getCity());
 
-        Assert.assertEquals(1, pEdition.getPhones().size());
+        Assert.assertEquals(2, person.getPhones().size());
+
+        Phone homePhone = person.getPhone("Home");
+        Assert.assertNotNull(homePhone);
+
+        Phone workPhone = person.getPhone("Work");
+        Assert.assertNotNull(workPhone);
     }
 
-    @Test
-    public void queryFutureEditionOfCurrentPersonAtT1() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T1);
-
-        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
-
-        System.out.println("QUERY EDITION @ T1: " + pEdition);
-
-        Assert.assertNotNull("No edition found at T1", pEdition);
-        Assert.assertTrue(pEdition.getEffectivity().isCurrent());
-        Assert.assertFalse(pEdition.getEffectivity().isFutureEdition());
-        Assert.assertEquals(BOT, pEdition.getEffectivity().getStart());
-        Assert.assertEquals(T2, pEdition.getEffectivity().getEnd());
-        Assert.assertNotNull("No Continuity found", pEdition.getContinuity());
-
-        Assert.assertEquals(0, pEdition.getPersonHobbies().size());
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(SKI));
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(RUN));
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(GOLF));
-
-        Address address = pEdition.getAddress();
-
-        Assert.assertNotNull(address);
-        Assert.assertEquals(getSample().getAddress().getCity(), address.getCity());
-
-        Assert.assertEquals(1, pEdition.getPhones().size());
-    }
-
-    @Test
-    public void queryFutureEditionOfCurrentPersonAtT2() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T2);
-
-        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
-
-        System.out.println("QUERY EDITION @ T2: " + pEdition);
-
-        Assert.assertNotNull("No edition found at T2", pEdition);
-        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
-        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
-        Assert.assertEquals(T2, pEdition.getEffectivity().getStart());
-        Assert.assertEquals(T4, pEdition.getEffectivity().getEnd());
-        Assert.assertNotSame(pEdition, pEdition.getContinuity());
-
-        Assert.assertEquals(1, pEdition.getPersonHobbies().size());
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(SKI));
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(RUN));
-        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(GOLF));
-
-        Address address = pEdition.getAddress();
-
-        Assert.assertNotNull(address);
-        Assert.assertEquals("Toronto", address.getCity());
-
-        Assert.assertEquals(2, pEdition.getPhones().size());
-    }
-
-    @Test
-    public void queryFutureEditionOfCurrentPersonAtT2JoinFetchAddress() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T2);
-
-        Person pEdition = null;
-        try {
-            pEdition = em.createQuery("SELECT p From Person p JOIN FETCH p.address WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
-        } catch (NoResultException e) {
-            Assert.fail("Join returned no result");
-        }
-        Address address = pEdition.getAddress();
-
-        System.out.println("QUERY EDITION @ T2: " + pEdition);
-        System.out.println("\t> " + address);
-
-        Assert.assertNotNull("No edition found", pEdition);
-        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
-        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
-        Assert.assertEquals(T2, pEdition.getEffectivity().getStart());
-        Assert.assertEquals(T4, pEdition.getEffectivity().getEnd());
-        Assert.assertNotNull("No Continuity found", pEdition.getContinuity());
-        Assert.assertNotNull(address);
-        Assert.assertEquals("Toronto", address.getCity());
-
-        Assert.assertEquals(1, pEdition.getPersonHobbies().size());
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(SKI));
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(RUN));
-        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(GOLF));
-
-        Assert.assertEquals(2, pEdition.getPhones().size());
-    }
-
-    @Test
-    public void queryFutureEditionOfCurrentPersonAtT3() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T3);
-
-        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
-
-        System.out.println("QUERY EDITION @ T3: " + pEdition);
-
-        Assert.assertNotNull("No edition found ", pEdition);
-        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
-        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
-        Assert.assertEquals(T2, pEdition.getEffectivity().getStart());
-        Assert.assertEquals(T4, pEdition.getEffectivity().getEnd());
-        Assert.assertNotSame(pEdition, pEdition.getContinuity());
-
-        Assert.assertEquals(1, pEdition.getPersonHobbies().size());
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(SKI));
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(RUN));
-        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(GOLF));
-
-        Address address = pEdition.getAddress();
-
-        Assert.assertNotNull(address);
-        Assert.assertEquals("Toronto", address.getCity());
-
-        Assert.assertEquals(2, pEdition.getPhones().size());
-    }
-
-    @Test
-    public void queryFutureEditionOfCurrentPersonAtT4() {
-        TemporalEntityManager em = getEntityManager();
+    public void verifyT4(TemporalEntityManager em) {
         em.setEffectiveTime(T4);
 
-        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+        Person person = em.find(Person.class, getSample().getContinuityId());
 
-        System.out.println("QUERY EDITION @ T4: " + pEdition);
+        Assert.assertNotNull(person);
 
-        Assert.assertNotNull("No Person Edition Found", pEdition);
-        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
-        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
-        Assert.assertEquals(T4, pEdition.getEffectivity().getStart());
-        Assert.assertEquals(EOT, pEdition.getEffectivity().getEnd());
-        Assert.assertNotSame(pEdition, pEdition.getContinuity());
-
-        Assert.assertEquals(2, pEdition.getPersonHobbies().size());
-        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(SKI));
-        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(RUN));
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(GOLF));
-
-        Address address = pEdition.getAddress();
-
+        Address address = person.getAddress();
         Assert.assertNotNull(address);
 
-        Assert.assertEquals(2, pEdition.getPhones().size());
-    }
+        Assert.assertEquals(2, person.getPhones().size());
 
-    @Test
-    public void queryFutureEditionOfCurrentPersonAtT5() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T5);
+        Phone homePhone = person.getPhone("Home");
+        Assert.assertNotNull(homePhone);
 
-        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
-
-        System.out.println("QUERY EDITION @ T5: " + pEdition);
-
-        Assert.assertNotNull("No edition found at T5", pEdition);
-        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
-        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
-        Assert.assertEquals(T4, pEdition.getEffectivity().getStart());
-        Assert.assertEquals(EOT, pEdition.getEffectivity().getEnd());
-        Assert.assertNotSame(pEdition, pEdition.getContinuity());
-        Assert.assertEquals(2, pEdition.getPersonHobbies().size());
-
-        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(SKI));
-        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(RUN));
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(GOLF));
-
-        Assert.assertEquals(2, pEdition.getPhones().size());
-    }
-
-    @Test
-    public void nativeQueryForAllEdition() {
-        TemporalEntityManager em = getEntityManager();
-
-        TypedQuery<Person> query = em.createNamedQuery("PersonEdition.all", Person.class);
-        query.setParameter("CID", getSample().getId());
-        List<Person> editions = query.getResultList();
-
-        Assert.assertFalse("No edition found", editions.isEmpty());
-
-        System.out.println("QUERY ALL EDITIONS:");
-        for (Person p : editions) {
-            System.out.println("\t" + p);
-            Assert.assertNotNull("No Continuity found", p.getContinuity());
-        }
-
-        Assert.assertEquals(3, editions.size());
-    }
-
-    // @Test
-    public void deleteAllAtT5() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T5);
-
-        Person p = em.find(Person.class, getSample().getId());
-
-        em.getTransaction().begin();
-
-        p.getEffectivity().setEnd(T5);
-        p.getAddress().getEffectivity().setEnd(T5);
-        for (Phone phone : p.getPhones().values()) {
-            phone.getEffectivity().setEnd(T5);
-        }
-
-        em.flush();
-
-        // TODO - validation
-    }
-
-    @Test
-    public void detachResultUsingCopyPolicy() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T2);
-
-        TypedQuery<Person> query = em.createNamedQuery("PersonEdition.find", Person.class);
-        query.setParameter("ID", getSample().getId());
-
-        Person p = query.getSingleResult();
-
-        System.out.println("ORIGINAL: " + p + " HASHCODE: " + System.identityHashCode(p));
-        System.out.println("\t" + p.getAddress());
-
-        CopyGroup cg = new CopyGroup();
-        cg.cascadeAllParts();
-
-        Person pCopy = (Person) JpaHelper.getEntityManager(em).copy(p, cg);
-        System.out.println("COPY: " + pCopy + " HASHSCODE: " + System.identityHashCode(pCopy));
-        System.out.println("\t" + pCopy.getAddress());
-    }
-
-    @Test
-    public void modifyFutureEditionOfCurrentPersonAtT4() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T4);
-
-        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
-
-        System.out.println("QUERY EDITION @ T4: " + pEdition);
-
-        Assert.assertNotNull("No Person Edition Found", pEdition);
-        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
-        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
-        Assert.assertEquals(T4, pEdition.getEffectivity().getStart());
-        Assert.assertNotSame(pEdition, pEdition.getContinuity());
-
-        Assert.assertEquals(2, pEdition.getPersonHobbies().size());
-        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(SKI));
-        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(RUN));
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(GOLF));
-
-        long currentVersion = pEdition.getVersion();
-
-        em.getTransaction().begin();
-        pEdition.setName(pEdition.getName().toUpperCase());
-        em.flush();
-
-        Assert.assertEquals(currentVersion + 1, pEdition.getVersion());
-    }
-
-    @Test
-    public void modifyFutureEditionOfCurrentPersonAtT4UsingMerge() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T4);
-
-        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
-
-        System.out.println("QUERY EDITION @ T4: " + pEdition);
-
-        // Create new unregistered hobby and add.
-
-        Assert.assertNotNull("No Person Edition Found", pEdition);
-        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
-        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
-        Assert.assertEquals(T4, pEdition.getEffectivity().getStart());
-        Assert.assertNotSame(pEdition, pEdition.getContinuity());
-
-        Assert.assertEquals(2, pEdition.getPersonHobbies().size());
-        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(SKI));
-        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(RUN));
-        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(GOLF));
-
-        long currentVersion = pEdition.getVersion();
-
-        em.getTransaction().begin();
-        pEdition.setName(pEdition.getName().toUpperCase());
-        em.flush();
-
-        Assert.assertEquals(currentVersion + 1, pEdition.getVersion());
-    }
-
-    /**
-     * Verify that the edition creation operation correctly copies values
-     * including mutable values and collections.
-     */
-    @Test
-    public void verifyCreateEditionCopying() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T5);
-        EditionSet es = em.getEditionSet();
-
-        Person pEdition = em.find(Person.class, getSample().getId());
-
-        Assert.assertNotNull(pEdition);
-        Assert.assertTrue(TemporalHelper.isEdition(em, pEdition));
-        Assert.assertEquals(T4, pEdition.getEffectivity().getStart());
-        Assert.assertNotNull(es);
-        Assert.assertTrue(es.getEntries().isEmpty());
-
-        em.getTransaction().begin();
-        Person pAtT5 = em.newEdition(pEdition);
-
-        Assert.assertNotNull(pAtT5);
-        Assert.assertTrue(TemporalHelper.isEdition(em, pEdition));
-        Assert.assertEquals(T5, pAtT5.getEffectivity().getStart());
-        Assert.assertFalse(es.getEntries().isEmpty());
-        Assert.assertEquals(1, es.getEntries().size());
-
-        // Verify collection/map cloning
-        Assert.assertNotSame(pEdition.getPhones(), pAtT5.getPhones());
-        Assert.assertNotSame(pEdition.getPersonHobbies(), pAtT5.getPersonHobbies());
-        Assert.assertNotSame(pEdition.getNicknames(), pAtT5.getNicknames());
-
-        // Mutable non-temporal values
-        Assert.assertSame(pEdition.getDateOfBirth(), pAtT5.getDateOfBirth());
-
-        // TODO: Validate mutable basic copying
-
-    }
-
-    @SuppressWarnings("deprecation")
-    @Test
-    public void testDateOfBirthNonTemporalStorage() {
-        TemporalEntityManager em = getEntityManager();
-
-        List<?> results = em.createNativeQuery("SELECT DATEOFBIRTH FROM TPERSON WHERE CID = 1 ORDER BY OID").getResultList();
-
-        Assert.assertNotNull(results);
-        Assert.assertEquals(3, results.size());
-        Assert.assertEquals(new Date(75, 1, 5), results.get(0));
-        Assert.assertNull(results.get(1));
-        Assert.assertNull(results.get(2));
-    }
-
-    /**
-     * Verify the query result and relationship to person
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void queryCurrentHomePhone() {
-        TemporalEntityManager em = getEntityManager();
-
-        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
-        Phone phone = query.getSingleResult();
-
-        Assert.assertNotNull(phone);
-        Assert.assertFalse(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
-        Assert.assertNotNull(phone.getContinuity());
-        Assert.assertEquals(phone, phone.getContinuity());
-        Assert.assertEquals(BOT, phone.getEffectivity().getStart());
-        Assert.assertEquals(T2, phone.getEffectivity().getEnd());
-
-        Assert.assertNotNull(phone.getPerson());
-        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
-    }
-
-    /**
-     * Verify the query result and relationship to person
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void queryHomePhoneAtBOT() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(BOT);
-
-        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
-        Phone phone = query.getSingleResult();
-
-        Assert.assertNotNull(phone);
-        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
-        Assert.assertNotNull(phone.getContinuity());
-        Assert.assertEquals(BOT, phone.getEffectivity().getStart());
-        Assert.assertEquals(T2, phone.getEffectivity().getEnd());
-
-        Assert.assertNotNull(phone.getPerson());
-        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
-    }
-
-    /**
-     * Verify the query result and relationship to person
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void queryHomePhoneAtT1() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T1);
-
-        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
-        Phone phone = query.getSingleResult();
-
-        Assert.assertNotNull(phone);
-        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
-        Assert.assertNotNull(phone.getContinuity());
-        Assert.assertEquals(BOT, phone.getEffectivity().getStart());
-        Assert.assertEquals(T2, phone.getEffectivity().getEnd());
-
-        Assert.assertNotNull(phone.getPerson());
-        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
-    }
-
-    /**
-     * Verify the query result and relationship to person
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void queryHomePhoneAtT2() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T2);
-
-        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
-        Phone phone = query.getSingleResult();
-
-        Assert.assertNotNull(phone);
-        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
-        Assert.assertNotNull(phone.getContinuity());
-        Assert.assertEquals(T2, phone.getEffectivity().getStart());
-        Assert.assertEquals(T4, phone.getEffectivity().getEnd());
-
-        Assert.assertNotNull(phone.getPerson());
-        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
-    }
-
-    /**
-     * Verify the query result and relationship to person
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void queryHomePhoneAtT3() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T3);
-
-        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
-        Phone phone = query.getSingleResult();
-
-        Assert.assertNotNull(phone);
-        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
-        Assert.assertNotNull(phone.getContinuity());
-        Assert.assertEquals(T2, phone.getEffectivity().getStart());
-        Assert.assertEquals(T4, phone.getEffectivity().getEnd());
-
-        Assert.assertNotNull(phone.getPerson());
-        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
-    }
-
-    /**
-     * Verify the query result and relationship to person
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void queryHomePhoneAtT4() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T4);
-
-        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
-        Phone phone = query.getSingleResult();
-
-        Assert.assertNotNull(phone);
-        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
-        Assert.assertNotNull(phone.getContinuity());
-        Assert.assertEquals(T4, phone.getEffectivity().getStart());
-        Assert.assertEquals(EOT, phone.getEffectivity().getEnd());
-
-        Assert.assertNotNull(phone.getPerson());
-        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
-    }
-
-    /**
-     * Verify the query result and relationship to person
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void queryHomePhoneAtT5() {
-        TemporalEntityManager em = getEntityManager();
-        em.setEffectiveTime(T5);
-
-        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
-        Phone phone = query.getSingleResult();
-
-        Assert.assertNotNull(phone);
-        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
-        Assert.assertNotNull(phone.getContinuity());
-        Assert.assertEquals(T4, phone.getEffectivity().getStart());
-        Assert.assertEquals(EOT, phone.getEffectivity().getEnd());
-
-        Assert.assertNotNull(phone.getPerson());
-        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
+        Phone cellPhone = person.getPhone("Cell");
+        Assert.assertNotNull(cellPhone);
     }
 }
diff --git a/Temporal Tests/src/tests/FullPersonWithEditionsMods.java b/Temporal Tests/src/tests/FullPersonWithEditionsMods.java
new file mode 100644
index 0000000..33d5776
--- /dev/null
+++ b/Temporal Tests/src/tests/FullPersonWithEditionsMods.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2012 Oracle. All rights reserved. This program and the
+ * accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 and Eclipse Distribution License v. 1.0 which accompanies
+ * this distribution. The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
+ * License is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ * 
+ * Contributors: dclarke - Bug 361016: Future Versions Examples
+ ******************************************************************************/
+package tests;
+
+import static example.PersonModelExample.GOLF;
+import static example.PersonModelExample.RUN;
+import static example.PersonModelExample.SKI;
+import static example.PersonModelExample.T2;
+import static example.PersonModelExample.T4;
+import static example.PersonModelExample.T5;
+
+import javax.persistence.TypedQuery;
+
+import model.Person;
+import model.Phone;
+
+import org.eclipse.persistence.jpa.JpaHelper;
+import org.eclipse.persistence.sessions.CopyGroup;
+import org.junit.Assert;
+import org.junit.Test;
+
+import temporal.TemporalEntityManager;
+
+/**
+ * This test case performs current and edition queries on a simple
+ * Person-Address-Phones model both illustrating and verifying query operations.
+ * 
+ * @author dclarke
+ * @since EclipseLink 2.3.1
+ */
+public class FullPersonWithEditionsMods extends FullPersonWithEditions {
+
+    @Test
+    public void deleteAllAtT5() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T5);
+
+        Person p = em.find(Person.class, getSample().getId());
+
+        em.getTransaction().begin();
+
+        p.getEffectivity().setEnd(T5);
+        p.getAddress().getEffectivity().setEnd(T5);
+        for (Phone phone : p.getPhones().values()) {
+            phone.getEffectivity().setEnd(T5);
+        }
+
+        em.flush();
+
+        // TODO - validation
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @Test
+    public void detachResultUsingCopyPolicy() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+
+        TypedQuery<Person> query = em.createNamedQuery("PersonEdition.find", Person.class);
+        query.setParameter("ID", getSample().getId());
+
+        Person p = query.getSingleResult();
+
+        System.out.println("ORIGINAL: " + p + " HASHCODE: " + System.identityHashCode(p));
+        System.out.println("\t" + p.getAddress());
+
+        CopyGroup cg = new CopyGroup();
+        cg.cascadeAllParts();
+
+        Person pCopy = (Person) JpaHelper.getEntityManager(em).copy(p, cg);
+        System.out.println("COPY: " + pCopy + " HASHSCODE: " + System.identityHashCode(pCopy));
+        System.out.println("\t" + pCopy.getAddress());
+    }
+
+    @Test
+    public void modifyFutureEditionOfCurrentPersonAtT4() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+
+        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+
+        System.out.println("QUERY EDITION @ T4: " + pEdition);
+
+        Assert.assertNotNull("No Person Edition Found", pEdition);
+        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
+        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
+        Assert.assertEquals(T4, pEdition.getEffectivity().getStart());
+        Assert.assertNotSame(pEdition, pEdition.getContinuity());
+
+        Assert.assertEquals(2, pEdition.getPersonHobbies().size());
+        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(SKI));
+        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(RUN));
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(GOLF));
+
+        long currentVersion = pEdition.getVersion();
+
+        em.getTransaction().begin();
+        pEdition.setName(pEdition.getName().toUpperCase());
+        em.flush();
+
+        Assert.assertEquals(currentVersion + 1, pEdition.getVersion());
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @Test
+    public void modifyFutureEditionOfCurrentPersonAtT4UsingMerge() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+
+        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+
+        System.out.println("QUERY EDITION @ T4: " + pEdition);
+
+        // Create new unregistered hobby and add.
+
+        Assert.assertNotNull("No Person Edition Found", pEdition);
+        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
+        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
+        Assert.assertEquals(T4, pEdition.getEffectivity().getStart());
+        Assert.assertNotSame(pEdition, pEdition.getContinuity());
+
+        Assert.assertEquals(2, pEdition.getPersonHobbies().size());
+        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(SKI));
+        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(RUN));
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(GOLF));
+
+        long currentVersion = pEdition.getVersion();
+
+        em.getTransaction().begin();
+        pEdition.setName(pEdition.getName().toUpperCase());
+        em.flush();
+
+        Assert.assertEquals(currentVersion + 1, pEdition.getVersion());
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @Test
+    public void changeEffectiveTimeWithNoChanges() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+        em.getEditionSet();
+
+        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+
+        System.out.println("QUERY EDITION @ T4: " + pEdition);
+
+        // Create new unregistered hobby and add.
+
+        Assert.assertNotNull("No Person Edition Found", pEdition);
+
+        em.setEffectiveTime(T5);
+
+        Assert.assertFalse(em.hasEditionSet());
+        Assert.assertEquals(T5, (long) em.getEffectiveTime());
+    }
+
+    @Test
+    public void changeEffectiveTimeWithChangesPending() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+        em.getEditionSet();
+
+        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+
+        System.out.println("QUERY EDITION @ T4: " + pEdition);
+
+        // Create new unregistered hobby and add.
+
+        Assert.assertNotNull("No Person Edition Found", pEdition);
+
+        em.getTransaction().begin();
+        pEdition.setEmail(pEdition.getName() + "@email.com");
+
+        try {
+            em.setEffectiveTime(T5);
+        } catch (IllegalStateException e) {
+            return;
+        }
+        Assert.fail("IllegalStateException expected");
+    }
+}
diff --git a/Temporal Tests/src/tests/FullPersonWithEditionsQueries.java b/Temporal Tests/src/tests/FullPersonWithEditionsQueries.java
new file mode 100644
index 0000000..7a9a1b4
--- /dev/null
+++ b/Temporal Tests/src/tests/FullPersonWithEditionsQueries.java
@@ -0,0 +1,648 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2012 Oracle. All rights reserved. This program and the
+ * accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 and Eclipse Distribution License v. 1.0 which accompanies
+ * this distribution. The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
+ * License is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ * 
+ * Contributors: dclarke - Bug 361016: Future Versions Examples
+ ******************************************************************************/
+package tests;
+
+import static example.PersonModelExample.GOLF;
+import static example.PersonModelExample.RUN;
+import static example.PersonModelExample.SKI;
+import static example.PersonModelExample.T1;
+import static example.PersonModelExample.T2;
+import static example.PersonModelExample.T3;
+import static example.PersonModelExample.T4;
+import static example.PersonModelExample.T5;
+import static temporal.Effectivity.BOT;
+import static temporal.Effectivity.EOT;
+
+import java.sql.Date;
+import java.util.List;
+
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+
+import model.Address;
+import model.Person;
+import model.Phone;
+
+import org.eclipse.persistence.jpa.JpaHelper;
+import org.eclipse.persistence.sessions.CopyGroup;
+import org.junit.Assert;
+import org.junit.Test;
+
+import temporal.BaseEntity;
+import temporal.EditionSet;
+import temporal.TemporalEntityManager;
+import temporal.TemporalHelper;
+
+/**
+ * This test case performs current and edition queries on a simple
+ * Person-Address-Phones model both illustrating and verifying query operations.
+ * 
+ * @author dclarke
+ * @since EclipseLink 2.3.1
+ */
+public class FullPersonWithEditionsQueries extends FullPersonWithEditions {
+
+    @Test
+    public void queryAllCurrent() {
+        TemporalEntityManager em = getEntityManager();
+        List<Person> results = em.createQuery("SELECT p From Person p", Person.class).getResultList();
+
+        System.out.println("QUERY CURRENT:");
+        for (Person p : results) {
+            System.out.println("\t>" + p);
+        }
+
+        Assert.assertEquals(1, results.size());
+
+        Person currentperson = results.get(0);
+        Assert.assertSame(currentperson, currentperson.getContinuity());
+        Assert.assertEquals(getSample().getId(), currentperson.getId());
+    }
+
+    @Test
+    public void findCurrent() {
+        TemporalEntityManager em = getEntityManager();
+
+        Person current = em.find(Person.class, getSample().getId());
+
+        System.out.println("VERIFY CURRENT: " + current);
+
+        // Verify person
+        Assert.assertNotNull(current);
+        Assert.assertEquals(current, current.getContinuity());
+        Assert.assertEquals(getSample().getId(), current.getId());
+        Assert.assertEquals(getSample().getName(), current.getName());
+        Assert.assertTrue(current.getEffectivity().isCurrent());
+        Assert.assertFalse(current.getEffectivity().isFutureEdition());
+        Assert.assertEquals(current.getEffectivity().getStart(), BOT);
+        Assert.assertEquals(current.getEffectivity().getEnd(), T2);
+
+        // Address
+        Assert.assertNotNull(current.getAddress());
+        Assert.assertEquals(getSample().getAddress().getStreet(), current.getAddress().getStreet());
+        Assert.assertEquals(getSample().getAddress().getCity(), current.getAddress().getCity());
+        Assert.assertEquals(getSample().getAddress().getState(), current.getAddress().getState());
+        Assert.assertTrue(current.getAddress().getEffectivity().isCurrent());
+        Assert.assertFalse(current.getAddress().getEffectivity().isFutureEdition());
+        Assert.assertEquals(current.getAddress().getEffectivity().getStart(), BOT);
+        Assert.assertEquals(current.getAddress().getEffectivity().getEnd(), T2);
+
+        // Phone
+        Assert.assertEquals(1, current.getPhones().size());
+        Phone currentHome = current.getPhone("Home");
+        Assert.assertNotNull(currentHome);
+        Assert.assertEquals("111-111-1111", currentHome.getNumber());
+        Assert.assertSame(current, currentHome.getPerson());
+    }
+
+    @Test
+    public void queryAllCurrentJoinAddress() {
+        TemporalEntityManager em = getEntityManager();
+        List<Person> results = em.createQuery("SELECT p From Person p JOIN FETCH p.address", Person.class).getResultList();
+
+        System.out.println("QUERY CURRENT:");
+        for (Person p : results) {
+            System.out.println("\t>" + p);
+        }
+
+        Assert.assertEquals(1, results.size());
+
+        Person currentperson = results.get(0);
+        Assert.assertSame(currentperson, currentperson.getContinuity());
+        Assert.assertEquals(getSample().getId(), currentperson.getId());
+    }
+
+    @Test
+    public void querySampleCurrentPerson() {
+        TemporalEntityManager em = getEntityManager();
+
+        Person person = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+        Address address = person.getAddress();
+
+        Assert.assertNotNull(person);
+
+        System.out.println("FIND CURRENT: " + person);
+
+        Assert.assertEquals(getSample().getId(), person.getId());
+        Assert.assertSame(person, person.getContinuity());
+        Assert.assertNotNull(address);
+        Assert.assertEquals(getSample().getAddress().getCity(), address.getCity());
+    }
+
+    @Test
+    public void querySampleCurrentPersonJoinAddress() {
+        TemporalEntityManager em = getEntityManager();
+
+        Person person = em.createQuery("SELECT p From Person p JOIN FETCH p.address WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+        Address address = person.getAddress();
+
+        Assert.assertNotNull(person);
+
+        System.out.println("FIND CURRENT: " + person);
+
+        Assert.assertEquals(getSample().getId(), person.getId());
+        Assert.assertEquals(person, person.getContinuity());
+        Assert.assertNotNull(address);
+        Assert.assertEquals(getSample().getAddress().getCity(), address.getCity());
+    }
+
+    @Test
+    public void findSampleCurrentPerson() {
+        TemporalEntityManager em = getEntityManager();
+        Person person = em.find(Person.class, getSample().getId());
+
+        Assert.assertNotNull(person);
+
+        System.out.println("FIND CURRENT: " + person);
+
+        Assert.assertEquals(getSample().getId(), person.getId());
+        Assert.assertSame(person, person.getContinuity());
+        Assert.assertTrue(person.getEffectivity().isCurrent());
+        Assert.assertFalse(person.getEffectivity().isFutureEdition());
+        Assert.assertEquals(person.getEffectivity().getStart(), BOT);
+        Assert.assertEquals(person.getEffectivity().getEnd(), T2);
+
+        Assert.assertEquals(0, person.getPersonHobbies().size());
+
+        Assert.assertEquals(1, person.getPhones().size());
+
+    }
+
+    @Test
+    public void findFuturePersonEntityEditionT2() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+
+        Person person = em.find(Person.class, getSample().getId());
+        Assert.assertNotNull(person);
+        System.out.println("FIND Future Edition: " + person);
+        Assert.assertEquals(1, person.getPersonHobbies().size());
+
+        Person continuity = person.getContinuity();
+
+        Assert.assertNotNull(continuity);
+        System.out.println("\tContinuity: " + continuity);
+        Assert.assertTrue("Not an edition entity", TemporalHelper.isEdition(em, person));
+        Assert.assertEquals(getSample().getId(), person.getContinuity().getId());
+
+        Assert.assertFalse(person.getEffectivity().isCurrent());
+        Assert.assertTrue(person.getEffectivity().isFutureEdition());
+        Assert.assertEquals(person.getEffectivity().getStart(), T2);
+        Assert.assertEquals(person.getEffectivity().getEnd(), T4);
+        Assert.assertNotSame(person, person.getContinuity());
+    }
+
+    @Test
+    public void queryFutureEditionOfCurrentPersonAtBOT() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(BOT);
+
+        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+
+        System.out.println("QUERY EDITION @ BOT: " + pEdition);
+
+        Assert.assertNotNull("No edition found at BOT", pEdition);
+        Assert.assertTrue(pEdition.getEffectivity().isCurrent());
+        Assert.assertFalse(pEdition.getEffectivity().isFutureEdition());
+        Assert.assertEquals(BOT, pEdition.getEffectivity().getStart());
+        Assert.assertEquals(T2, pEdition.getEffectivity().getEnd());
+        Assert.assertNotNull("No Continuity found", pEdition.getContinuity());
+        Assert.assertEquals(0, pEdition.getPersonHobbies().size());
+
+        Address address = pEdition.getAddress();
+
+        Assert.assertNotNull(address);
+        Assert.assertEquals(getSample().getAddress().getCity(), address.getCity());
+
+        Assert.assertEquals(1, pEdition.getPhones().size());
+    }
+
+    @Test
+    public void queryFutureEditionOfCurrentPersonAtT1() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T1);
+
+        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+
+        System.out.println("QUERY EDITION @ T1: " + pEdition);
+
+        Assert.assertNotNull("No edition found at T1", pEdition);
+        Assert.assertTrue(pEdition.getEffectivity().isCurrent());
+        Assert.assertFalse(pEdition.getEffectivity().isFutureEdition());
+        Assert.assertEquals(BOT, pEdition.getEffectivity().getStart());
+        Assert.assertEquals(T2, pEdition.getEffectivity().getEnd());
+        Assert.assertNotNull("No Continuity found", pEdition.getContinuity());
+
+        Assert.assertEquals(0, pEdition.getPersonHobbies().size());
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(SKI));
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(RUN));
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(GOLF));
+
+        Address address = pEdition.getAddress();
+
+        Assert.assertNotNull(address);
+        Assert.assertEquals(getSample().getAddress().getCity(), address.getCity());
+
+        Assert.assertEquals(1, pEdition.getPhones().size());
+    }
+
+    @Test
+    public void queryFutureEditionOfCurrentPersonAtT2() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+
+        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+
+        System.out.println("QUERY EDITION @ T2: " + pEdition);
+
+        Assert.assertNotNull("No edition found at T2", pEdition);
+        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
+        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
+        Assert.assertEquals(T2, pEdition.getEffectivity().getStart());
+        Assert.assertEquals(T4, pEdition.getEffectivity().getEnd());
+        Assert.assertNotSame(pEdition, pEdition.getContinuity());
+
+        Assert.assertEquals(1, pEdition.getPersonHobbies().size());
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(SKI));
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(RUN));
+        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(GOLF));
+
+        Address address = pEdition.getAddress();
+
+        Assert.assertNotNull(address);
+        Assert.assertEquals("Toronto", address.getCity());
+
+        Assert.assertEquals(2, pEdition.getPhones().size());
+    }
+
+    @Test
+    public void queryFutureEditionOfCurrentPersonAtT2JoinFetchAddress() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+
+        Person pEdition = null;
+        try {
+            pEdition = em.createQuery("SELECT p From Person p JOIN FETCH p.address WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+        } catch (NoResultException e) {
+            Assert.fail("Join returned no result");
+        }
+        Address address = pEdition.getAddress();
+
+        System.out.println("QUERY EDITION @ T2: " + pEdition);
+        System.out.println("\t> " + address);
+
+        Assert.assertNotNull("No edition found", pEdition);
+        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
+        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
+        Assert.assertEquals(T2, pEdition.getEffectivity().getStart());
+        Assert.assertEquals(T4, pEdition.getEffectivity().getEnd());
+        Assert.assertNotNull("No Continuity found", pEdition.getContinuity());
+        Assert.assertNotNull(address);
+        Assert.assertEquals("Toronto", address.getCity());
+
+        Assert.assertEquals(1, pEdition.getPersonHobbies().size());
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(SKI));
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(RUN));
+        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(GOLF));
+
+        Assert.assertEquals(2, pEdition.getPhones().size());
+    }
+
+    @Test
+    public void queryFutureEditionOfCurrentPersonAtT3() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T3);
+
+        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+
+        System.out.println("QUERY EDITION @ T3: " + pEdition);
+
+        Assert.assertNotNull("No edition found ", pEdition);
+        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
+        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
+        Assert.assertEquals(T2, pEdition.getEffectivity().getStart());
+        Assert.assertEquals(T4, pEdition.getEffectivity().getEnd());
+        Assert.assertNotSame(pEdition, pEdition.getContinuity());
+
+        Assert.assertEquals(1, pEdition.getPersonHobbies().size());
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(SKI));
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(RUN));
+        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(GOLF));
+
+        Address address = pEdition.getAddress();
+
+        Assert.assertNotNull(address);
+        Assert.assertEquals("Toronto", address.getCity());
+
+        Assert.assertEquals(2, pEdition.getPhones().size());
+    }
+
+    @Test
+    public void queryFutureEditionOfCurrentPersonAtT4() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+
+        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+
+        System.out.println("QUERY EDITION @ T4: " + pEdition);
+
+        Assert.assertNotNull("No Person Edition Found", pEdition);
+        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
+        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
+        Assert.assertEquals(T4, pEdition.getEffectivity().getStart());
+        Assert.assertEquals(EOT, pEdition.getEffectivity().getEnd());
+        Assert.assertNotSame(pEdition, pEdition.getContinuity());
+
+        Assert.assertEquals(2, pEdition.getPersonHobbies().size());
+        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(SKI));
+        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(RUN));
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(GOLF));
+
+        Address address = pEdition.getAddress();
+
+        Assert.assertNotNull(address);
+
+        Assert.assertEquals(2, pEdition.getPhones().size());
+    }
+
+    @Test
+    public void queryFutureEditionOfCurrentPersonAtT5() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T5);
+
+        Person pEdition = em.createQuery("SELECT p From Person p WHERE p.id = " + getSample().getId(), Person.class).getSingleResult();
+
+        System.out.println("QUERY EDITION @ T5: " + pEdition);
+
+        Assert.assertNotNull("No edition found at T5", pEdition);
+        Assert.assertFalse(pEdition.getEffectivity().isCurrent());
+        Assert.assertTrue(pEdition.getEffectivity().isFutureEdition());
+        Assert.assertEquals(T4, pEdition.getEffectivity().getStart());
+        Assert.assertEquals(EOT, pEdition.getEffectivity().getEnd());
+        Assert.assertNotSame(pEdition, pEdition.getContinuity());
+        Assert.assertEquals(2, pEdition.getPersonHobbies().size());
+
+        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(SKI));
+        Assert.assertTrue(pEdition.getPersonHobbies().containsKey(RUN));
+        Assert.assertFalse(pEdition.getPersonHobbies().containsKey(GOLF));
+
+        Assert.assertEquals(2, pEdition.getPhones().size());
+    }
+
+    @Test
+    public void nativeQueryForAllEdition() {
+        TemporalEntityManager em = getEntityManager();
+
+        TypedQuery<Person> query = em.createNamedQuery("PersonEdition.all", Person.class);
+        query.setParameter("CID", getSample().getId());
+        List<Person> editions = query.getResultList();
+
+        Assert.assertFalse("No edition found", editions.isEmpty());
+
+        System.out.println("QUERY ALL EDITIONS:");
+        for (Person p : editions) {
+            System.out.println("\t" + p);
+            Assert.assertNotNull("No Continuity found", p.getContinuity());
+        }
+
+        Assert.assertEquals(3, editions.size());
+    }
+
+    @Test
+    public void detachResultUsingCopyPolicy() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+
+        TypedQuery<Person> query = em.createNamedQuery("PersonEdition.find", Person.class);
+        query.setParameter("ID", getSample().getId());
+
+        Person p = query.getSingleResult();
+
+        System.out.println("ORIGINAL: " + p + " HASHCODE: " + System.identityHashCode(p));
+        System.out.println("\t" + p.getAddress());
+
+        CopyGroup cg = new CopyGroup();
+        cg.cascadeAllParts();
+
+        Person pCopy = (Person) JpaHelper.getEntityManager(em).copy(p, cg);
+        System.out.println("COPY: " + pCopy + " HASHSCODE: " + System.identityHashCode(pCopy));
+        System.out.println("\t" + pCopy.getAddress());
+    }
+
+    /**
+     * Verify that the edition creation operation correctly copies values
+     * including mutable values and collections.
+     */
+    @Test
+    public void verifyCreateEditionCopying() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T5);
+        EditionSet es = em.getEditionSet();
+
+        Person pEdition = em.find(Person.class, getSample().getId());
+
+        Assert.assertNotNull(pEdition);
+        Assert.assertTrue(TemporalHelper.isEdition(em, pEdition));
+        Assert.assertEquals(T4, pEdition.getEffectivity().getStart());
+        Assert.assertNotNull(es);
+        Assert.assertTrue(es.getEntries().isEmpty());
+
+        em.getTransaction().begin();
+        Person pAtT5 = em.newEdition(pEdition);
+
+        Assert.assertNotNull(pAtT5);
+        Assert.assertTrue(TemporalHelper.isEdition(em, pEdition));
+        Assert.assertEquals(T5, pAtT5.getEffectivity().getStart());
+        Assert.assertFalse(es.getEntries().isEmpty());
+        Assert.assertEquals(1, es.getEntries().size());
+
+        // Verify collection/map cloning
+        Assert.assertNotSame(pEdition.getPhones(), pAtT5.getPhones());
+        Assert.assertNotSame(pEdition.getPersonHobbies(), pAtT5.getPersonHobbies());
+        Assert.assertNotSame(pEdition.getNicknames(), pAtT5.getNicknames());
+
+        // Mutable non-temporal values
+        Assert.assertSame(pEdition.getDateOfBirth(), pAtT5.getDateOfBirth());
+
+        // TODO: Validate mutable basic copying
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testDateOfBirthNonTemporalStorage() {
+        TemporalEntityManager em = getEntityManager();
+
+        List<?> results = em.createNativeQuery("SELECT DATEOFBIRTH FROM TPERSON WHERE CID = 1 ORDER BY OID").getResultList();
+
+        Assert.assertNotNull(results);
+        Assert.assertEquals(3, results.size());
+        Assert.assertEquals(new Date(75, 1, 5), results.get(0));
+        Assert.assertNull(results.get(1));
+        Assert.assertNull(results.get(2));
+    }
+
+    /**
+     * Verify the query result and relationship to person
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void queryCurrentHomePhone() {
+        TemporalEntityManager em = getEntityManager();
+
+        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
+        Phone phone = query.getSingleResult();
+
+        Assert.assertNotNull(phone);
+        Assert.assertFalse(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
+        Assert.assertNotNull(phone.getContinuity());
+        Assert.assertEquals(phone, phone.getContinuity());
+        Assert.assertEquals(BOT, phone.getEffectivity().getStart());
+        Assert.assertEquals(T2, phone.getEffectivity().getEnd());
+
+        Assert.assertNotNull(phone.getPerson());
+        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
+    }
+
+    /**
+     * Verify the query result and relationship to person
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void queryHomePhoneAtBOT() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(BOT);
+
+        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
+        Phone phone = query.getSingleResult();
+
+        Assert.assertNotNull(phone);
+        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
+        Assert.assertNotNull(phone.getContinuity());
+        Assert.assertEquals(BOT, phone.getEffectivity().getStart());
+        Assert.assertEquals(T2, phone.getEffectivity().getEnd());
+
+        Assert.assertNotNull(phone.getPerson());
+        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
+    }
+
+    /**
+     * Verify the query result and relationship to person
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void queryHomePhoneAtT1() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T1);
+
+        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
+        Phone phone = query.getSingleResult();
+
+        Assert.assertNotNull(phone);
+        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
+        Assert.assertNotNull(phone.getContinuity());
+        Assert.assertEquals(BOT, phone.getEffectivity().getStart());
+        Assert.assertEquals(T2, phone.getEffectivity().getEnd());
+
+        Assert.assertNotNull(phone.getPerson());
+        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
+    }
+
+    /**
+     * Verify the query result and relationship to person
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void queryHomePhoneAtT2() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+
+        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
+        Phone phone = query.getSingleResult();
+
+        Assert.assertNotNull(phone);
+        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
+        Assert.assertNotNull(phone.getContinuity());
+        Assert.assertEquals(T2, phone.getEffectivity().getStart());
+        Assert.assertEquals(T4, phone.getEffectivity().getEnd());
+
+        Assert.assertNotNull(phone.getPerson());
+        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
+    }
+
+    /**
+     * Verify the query result and relationship to person
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void queryHomePhoneAtT3() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T3);
+
+        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
+        Phone phone = query.getSingleResult();
+
+        Assert.assertNotNull(phone);
+        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
+        Assert.assertNotNull(phone.getContinuity());
+        Assert.assertEquals(T2, phone.getEffectivity().getStart());
+        Assert.assertEquals(T4, phone.getEffectivity().getEnd());
+
+        Assert.assertNotNull(phone.getPerson());
+        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
+    }
+
+    /**
+     * Verify the query result and relationship to person
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void queryHomePhoneAtT4() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+
+        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
+        Phone phone = query.getSingleResult();
+
+        Assert.assertNotNull(phone);
+        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
+        Assert.assertNotNull(phone.getContinuity());
+        Assert.assertEquals(T4, phone.getEffectivity().getStart());
+        Assert.assertEquals(EOT, phone.getEffectivity().getEnd());
+
+        Assert.assertNotNull(phone.getPerson());
+        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
+    }
+
+    /**
+     * Verify the query result and relationship to person
+     */
+    @SuppressWarnings("unchecked")
+    @Test
+    public void queryHomePhoneAtT5() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T5);
+
+        TypedQuery<Phone> query = em.createQuery("SELECT p FROM Phone p WHERE p.type = 'Home'", Phone.class);
+        Phone phone = query.getSingleResult();
+
+        Assert.assertNotNull(phone);
+        Assert.assertTrue(TemporalHelper.isEditionClass((Class<BaseEntity>) phone.getClass()));
+        Assert.assertNotNull(phone.getContinuity());
+        Assert.assertEquals(T4, phone.getEffectivity().getStart());
+        Assert.assertEquals(EOT, phone.getEffectivity().getEnd());
+
+        Assert.assertNotNull(phone.getPerson());
+        Assert.assertEquals(phone.getEffectivity().getStart(), phone.getPerson().getEffectivity().getStart());
+    }
+}
diff --git a/Temporal Tests/src/tests/ProxyWrapperUpdateTests.java b/Temporal Tests/src/tests/ProxyWrapperUpdateTests.java
index 0439fa5..7172f36 100644
--- a/Temporal Tests/src/tests/ProxyWrapperUpdateTests.java
+++ b/Temporal Tests/src/tests/ProxyWrapperUpdateTests.java
@@ -54,7 +54,7 @@
         Assert.fail("IllegalArgumentException not thrown");
     }
 
-    @Test
+    //TODO @Test
     public void createWrapperForPersonEditionWithoutEffectiveTS() {
         TemporalEntityManager em = getEntityManager();
 
diff --git a/Temporal Tests/src/tests/editionsets/AllTests.java b/Temporal Tests/src/tests/editionsets/AllTests.java
index 34828c4..15fef12 100644
--- a/Temporal Tests/src/tests/editionsets/AllTests.java
+++ b/Temporal Tests/src/tests/editionsets/AllTests.java
@@ -19,9 +19,12 @@
                 CreateEditionSetTests.class, 
                 ApplySimpleEditionSetTests.class, 
                 MoveSingleEditionSetTests.class,
+                FullPersonWithEditionsMove.class,
+                FullPersonWithEditionsDelete.class,
                 DeleteEditionSetTests.class,
                 PropagateChangesTests.class,
                 PropagateDeleteChangesTests.class,
-                BrokenTemporalReferenceTests.class})
+                BrokenTemporalReferenceTests.class,
+                })
 public class AllTests {
 }
diff --git a/Temporal Tests/src/tests/editionsets/BrokenTemporalReferenceTests.java b/Temporal Tests/src/tests/editionsets/BrokenTemporalReferenceTests.java
index 5cbb34f..c2a7ae7 100644
--- a/Temporal Tests/src/tests/editionsets/BrokenTemporalReferenceTests.java
+++ b/Temporal Tests/src/tests/editionsets/BrokenTemporalReferenceTests.java
@@ -12,7 +12,9 @@
 
 import static example.PersonModelExample.T1;
 import static example.PersonModelExample.T2;
+import static example.PersonModelExample.T3;
 import static example.PersonModelExample.T4;
+import static example.PersonModelExample.T5;
 
 import javax.persistence.RollbackException;
 
@@ -168,4 +170,127 @@
         }
         Assert.fail("RollbackException execpted for violating FK");
     }
+
+    /**
+     * Create a new Address Entity at BOT with an end of T4. Then create a
+     * future Person at T2 that references the Address. Move the T2
+     * {@link EditionSet} to T5 where there is no valid Address.
+     */
+    @Test
+    public void moveEditionSetBeyondReferencedEnd() {
+        TemporalEntityManager em = getEntityManager();
+        em.getTransaction().begin();
+        Address address = em.newEntity(Address.class);
+        address.getEffectivity().setEnd(T4);
+        em.getTransaction().commit();
+        em.close();
+
+        em = getEntityManager();
+        em.setEffectiveTime(T2);
+
+        em.getTransaction().begin();
+        Address aT2 = em.find(Address.class, address.getContinuityId());
+        Person pT2 = em.newEntity(Person.class);
+        pT2.setAddress(aT2);
+        em.getTransaction().commit();
+        em.close();
+
+        em = getEntityManager();
+        em.setEffectiveTime(T2);
+
+        em.getTransaction().begin();
+        em.getEditionSet();
+        try {
+            EditionSetHelper.move(em, T5);
+            em.getTransaction().commit();
+        } catch (IllegalStateException e) {
+            return;
+        }
+        Assert.fail("IllegalStateException execpted for violating FK");
+    }
+
+    /**
+     * Create a new Address Entity (BOT) and then reference an edition of it
+     * from a future entity at T2. In a subsequent transaction modify the
+     * Address at BOT to have an end of T1. This would cause the FK relationship
+     * from Person at T2 to be invalid.
+     */
+    @Test
+    public void breakFKByChangingEditionEffectiveEnd() {
+        TemporalEntityManager em = getEntityManager();
+        em.getTransaction().begin();
+        Address address = em.newEntity(Address.class);
+        em.getTransaction().commit();
+        em.close();
+
+        em = getEntityManager();
+        em.setEffectiveTime(T2);
+
+        em.getTransaction().begin();
+        Address aBOT = em.find(Address.class, address.getContinuityId());
+        Address aT2 = em.newEdition(aBOT);
+        Person pT2 = em.newEntity(Person.class);
+        pT2.setAddress(aT2);
+        em.getTransaction().commit();
+        em.close();
+
+        em = getEntityManager();
+        em.setEffectiveTime(T4);
+        em.getTransaction().begin();
+
+        pT2 = em.find(Person.class, pT2.getContinuityId());
+        em.newEdition(pT2);
+        em.getTransaction().commit();
+
+        em = getEntityManager();
+        em.setEffectiveTime(T2);
+
+        em.getTransaction().begin();
+        aT2 = em.find(Address.class, address.getContinuityId());
+        aT2.getEffectivity().setEnd(T3);
+        try {
+            em.getTransaction().commit();
+        } catch (IllegalStateException e) {
+            return;
+        }
+        Assert.fail("IllegalStateException execpted for violating FK");
+    }
+
+    /**
+     * Create a new Address Entity (BOT) and then reference it from a future
+     * entity at T2. In a subsequent transaction modify the Address at BOT to
+     * have an end of T1. This would cause the FK relationship from Person at T2
+     * to be invalid.
+     */
+    @Test
+    public void breakFKByChangingCurrentEffectiveEnd() {
+        TemporalEntityManager em = getEntityManager();
+        em.getTransaction().begin();
+        Address address = em.newEntity(Address.class);
+        em.getTransaction().commit();
+        em.close();
+
+        em = getEntityManager();
+        em.setEffectiveTime(T2);
+
+        em.getTransaction().begin();
+        Address aT2 = em.find(Address.class, address.getContinuityId());
+        Person pT2 = em.newEntity(Person.class);
+        pT2.setAddress(aT2);
+        em.getTransaction().commit();
+        em.close();
+
+        em = getEntityManager();
+        Address aBOT = em.find(Address.class, address.getContinuityId());
+        em.getTransaction().begin();
+        aBOT.getEffectivity().setEnd(T1);
+        em.getEditionSet();
+
+        try {
+            em.getTransaction().commit();
+        } catch (IllegalStateException e) {
+            return;
+        }
+        Assert.fail("IllegalStateException execpted for violating FK");
+    }
 }
diff --git a/Temporal Tests/src/tests/editionsets/DeleteEditionSetTests.java b/Temporal Tests/src/tests/editionsets/DeleteEditionSetTests.java
index c559415..e474b0e 100644
--- a/Temporal Tests/src/tests/editionsets/DeleteEditionSetTests.java
+++ b/Temporal Tests/src/tests/editionsets/DeleteEditionSetTests.java
@@ -29,6 +29,7 @@
 import model.PersonHobby;
 import model.Phone;
 
+import org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork;
 import org.junit.Test;
 
 import temporal.EditionSet;
@@ -189,7 +190,9 @@
 
         em.getTransaction().begin();
         em.remove(esT4);
-        em.getTransaction().commit();
+        
+        RepeatableWriteUnitOfWork uow = em.unwrap(RepeatableWriteUnitOfWork.class);
+        Assert.assertFalse(uow.getDeletedObjects().isEmpty());
 
         esT4 = em.find(EditionSet.class, T4);
         Assert.assertNull(esT4);
@@ -209,8 +212,7 @@
 
         em.getTransaction().begin();
         em.remove(esT2);
-        em.getTransaction().commit();
-
+        
         esT2 = em.find(EditionSet.class, T2);
         Assert.assertNull(esT2);
     }
diff --git a/Temporal Tests/src/tests/editionsets/FullPersonWithEditionsDelete.java b/Temporal Tests/src/tests/editionsets/FullPersonWithEditionsDelete.java
new file mode 100644
index 0000000..fb811f8
--- /dev/null
+++ b/Temporal Tests/src/tests/editionsets/FullPersonWithEditionsDelete.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2012 Oracle. All rights reserved. This program and the
+ * accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 and Eclipse Distribution License v. 1.0 which accompanies
+ * this distribution. The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
+ * License is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ * 
+ * Contributors: dclarke - Bug 361016: Future Versions Examples
+ ******************************************************************************/
+package tests.editionsets;
+
+import static example.PersonModelExample.T2;
+import static example.PersonModelExample.T4;
+import junit.framework.Assert;
+import model.Address;
+import model.Person;
+
+import org.junit.Test;
+
+import temporal.TemporalEntityManager;
+import tests.FullPersonWithEditions;
+
+/**
+ * Tests change propagation through future editions.
+ * 
+ * @author dclarke
+ * @since EclipseLink 2.3.1
+ */
+public class FullPersonWithEditionsDelete extends FullPersonWithEditions {
+
+    @Test
+    public void deleteT2() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+        em.getTransaction().begin();
+
+        em.remove(em.getEditionSet());
+
+        Person personT2 = em.find(Person.class, getSample().getContinuityId());
+        Assert.assertNull(personT2);
+        Address addressT2 = em.find(Address.class, getSample().getAddress().getContinuityId());
+        Assert.assertNull(addressT2);
+
+        em.getTransaction().commit();
+
+        personT2 = em.find(Person.class, getSample().getContinuityId());
+        Assert.assertNull(personT2);
+        addressT2 = em.find(Address.class, getSample().getAddress().getContinuityId());
+        Assert.assertNull(addressT2);
+
+        closeEMF();
+    }
+
+    @Test
+    public void deleteT4() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+        em.getTransaction().begin();
+
+        em.remove(em.getEditionSet());
+
+        em.flush();
+        
+        closeEMF();
+    }
+}
diff --git a/Temporal Tests/src/tests/editionsets/FullPersonWithEditionsMove.java b/Temporal Tests/src/tests/editionsets/FullPersonWithEditionsMove.java
new file mode 100644
index 0000000..df076e5
--- /dev/null
+++ b/Temporal Tests/src/tests/editionsets/FullPersonWithEditionsMove.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2012 Oracle. All rights reserved. This program and the
+ * accompanying materials are made available under the terms of the Eclipse
+ * Public License v1.0 and Eclipse Distribution License v. 1.0 which accompanies
+ * this distribution. The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
+ * License is available at http://www.eclipse.org/org/documents/edl-v10.php.
+ * 
+ * Contributors: dclarke - Bug 361016: Future Versions Examples
+ ******************************************************************************/
+package tests.editionsets;
+
+import static example.PersonModelExample.T1;
+import static example.PersonModelExample.T2;
+import static example.PersonModelExample.T3;
+import static example.PersonModelExample.T4;
+import static example.PersonModelExample.T5;
+import junit.framework.Assert;
+import model.Person;
+
+import org.junit.Test;
+
+import temporal.EditionSetHelper;
+import temporal.Effectivity;
+import temporal.TemporalEntityManager;
+import tests.FullPersonWithEditions;
+
+/**
+ * Tests change propagation through future editions.
+ * 
+ * @author dclarke
+ * @since EclipseLink 2.3.1
+ */
+public class FullPersonWithEditionsMove extends FullPersonWithEditions {
+
+    @Test
+    public void moveT2toT3() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+        em.getTransaction().begin();
+
+        EditionSetHelper.move(em, T3);
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @Test
+    public void moveT2toT1() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+        em.getTransaction().begin();
+
+        EditionSetHelper.move(em, T1);
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @Test
+    public void moveT2toBOT() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+        em.getTransaction().begin();
+
+        try {
+            EditionSetHelper.move(em, Effectivity.BOT);
+        } catch (IllegalArgumentException e) {
+            return;
+        } finally {
+            em.getTransaction().rollback();
+            em.close();
+        }
+        Assert.fail("Expected IllegalArgumentException");
+    }
+
+    @Test
+    public void moveT2toT4() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+        em.getTransaction().begin();
+
+        EditionSetHelper.move(em, T4);
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @Test
+    public void moveT2toT5() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+        em.getTransaction().begin();
+
+        EditionSetHelper.move(em, T5);
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @Test
+    public void moveT4toT3() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+        em.getTransaction().begin();
+
+        EditionSetHelper.move(em, T3);
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @Test
+    public void moveT4toT5() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+        em.getTransaction().begin();
+
+        EditionSetHelper.move(em, T5);
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @Test
+    public void moveT4toT2() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+        em.getTransaction().begin();
+
+        EditionSetHelper.move(em, T2);
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @Test
+    public void moveT4toT1() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+        em.getTransaction().begin();
+
+        EditionSetHelper.move(em, T1);
+
+        em.getTransaction().rollback();
+        em.close();
+    }
+
+    @Test
+    public void moveT4toBOT() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T4);
+        em.getTransaction().begin();
+
+        try {
+            EditionSetHelper.move(em, Effectivity.BOT);
+        } catch (IllegalArgumentException e) {
+            return;
+        }
+        Assert.fail("Expected IllegalArgumentException");
+    }
+
+    @Test
+    public void moveT2WithPersonChangestoT3() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+        em.getTransaction().begin();
+
+        Person person = em.find(Person.class, getSample().getContinuityId());
+        person.setEmail("newemail@b.c");
+
+        try {
+            EditionSetHelper.move(em, T3);
+        } catch (IllegalStateException e) {
+            return;
+        } finally {
+            em.getTransaction().rollback();
+            em.close();
+        }
+        Assert.fail("IllegalStateException expected");
+    }
+
+    @Test
+    public void moveT2WithAddressChangestoT3() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+        em.getTransaction().begin();
+
+        Person person = em.find(Person.class, getSample().getContinuityId());
+        person.getAddress().setCity("NEW CITY");
+
+        try {
+            EditionSetHelper.move(em, T3);
+        } catch (IllegalStateException e) {
+            return;
+        } finally {
+            em.getTransaction().rollback();
+            em.close();
+        }
+        Assert.fail("IllegalStateException expected");
+    }
+
+    @Test
+    public void moveT2WithPhoneChangestoT3() {
+        TemporalEntityManager em = getEntityManager();
+        em.setEffectiveTime(T2);
+        em.getTransaction().begin();
+
+        Person person = em.find(Person.class, getSample().getContinuityId());
+        person.getPhone("Home").setNumber("NEW NUMBER");
+
+        try {
+            EditionSetHelper.move(em, T3);
+        } catch (IllegalStateException e) {
+            return;
+        } finally {
+            em.getTransaction().rollback();
+            em.close();
+        }
+        Assert.fail("IllegalStateException expected");
+    }
+}
diff --git a/Temporal Tests/src/tests/internal/TemporalEntityManagerTests.java b/Temporal Tests/src/tests/internal/TemporalEntityManagerTests.java
index ca8dcb0..d0fa12a 100644
--- a/Temporal Tests/src/tests/internal/TemporalEntityManagerTests.java
+++ b/Temporal Tests/src/tests/internal/TemporalEntityManagerTests.java
@@ -119,7 +119,7 @@
 
         verifySetStartTime(em, T3);
 
-        em.clearEffectiveTime();
+        em.clear();
 
         assertFalse(em.hasEffectiveTime());
         assertNull(em.getEffectiveTime());
@@ -153,12 +153,12 @@
         verifySetStartTime(em2, T7);
         verifySetStartTime(em1, T6);
 
-        em1.clearEffectiveTime();
+        em1.clear();
         verifySetStartTime(em2, T7);
         assertFalse(em1.hasEffectiveTime());
         assertNull(em1.getEffectiveTime());
 
-        em2.clearEffectiveTime();
+        em2.clear();
         assertFalse(em2.hasEffectiveTime());
         assertNull(em2.getEffectiveTime());
     }
@@ -253,7 +253,7 @@
         Assert.assertSame(desc, query.unwrap(ObjectLevelReadQuery.class).getDescriptor());
 
         // Current Query again
-        em.clearEffectiveTime();
+        em.clear();
         query = em.createQuery("SELECT p FROM Person p", Person.class);
         Assert.assertNotNull(query);
         desc = DescriptorHelper.getCurrentDescriptor(em.unwrap(Session.class), Person.class);
diff --git a/Temporal Tests/src/tests/internal/TemporalHelperTests.java b/Temporal Tests/src/tests/internal/TemporalHelperTests.java
index 46345b7..15d7322 100644
--- a/Temporal Tests/src/tests/internal/TemporalHelperTests.java
+++ b/Temporal Tests/src/tests/internal/TemporalHelperTests.java
@@ -86,7 +86,7 @@
 
         verifySetStartTime(em, T3);
 
-        em.clearEffectiveTime();
+        em.clear();
 
         assertFalse(em.hasEffectiveTime());
         assertNull(em.getEffectiveTime());
@@ -120,12 +120,12 @@
         verifySetStartTime(em2, T7);
         verifySetStartTime(em1, T6);
 
-        em1.clearEffectiveTime();
+        em1.clear();
         verifySetStartTime(em2, T7);
         assertFalse(em1.hasEffectiveTime());
         assertNull(em1.getEffectiveTime());
 
-        em2.clearEffectiveTime();
+        em2.clear();
         assertFalse(em2.hasEffectiveTime());
         assertNull(em2.getEffectiveTime());
     }