Additional move functionality and supporting tests
diff --git a/Temporal Entity Example/src/temporal/EditionSetHelper.java b/Temporal Entity Example/src/temporal/EditionSetHelper.java
index 4166eac..200d1e7 100644
--- a/Temporal Entity Example/src/temporal/EditionSetHelper.java
+++ b/Temporal Entity Example/src/temporal/EditionSetHelper.java
@@ -14,6 +14,8 @@
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
+import java.util.Set;
+import java.util.Vector;
import javax.persistence.EntityManager;
@@ -22,6 +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 temporal.persistence.DescriptorHelper;
@@ -83,29 +86,62 @@
* for invalid effective time or mismatched
* {@link TemporalEntityManager} and {@link EditionSet}
*/
- public static EditionSet move(TemporalEntityManager em, EditionSet es, long effective) {
+ public static void move(TemporalEntityManager em, long effective) {
if (effective <= Effectivity.BOT) {
throw new IllegalArgumentException("Invalid effective time for move: " + effective);
}
- if (es == null || !es.equals(em.getEditionSet())) {
- throw new IllegalArgumentException("Invalid TemporalEntitymanager or EditionSet: " + em + "::" + es);
+ 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.
+ for (EditionSetEntry entry : es.getEntries()) {
+ entry.getTemporal();
+ }
+
EditionSet newES = new EditionSet(effective);
em.persist(newES);
-
+ em.setEditionSet(newES);
+
for (EditionSetEntry entry : es.getEntries()) {
- // TODO: Look for conflicts
+ // 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);
+ }
+
+ 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);
+ } else {
+ // TODO
+ //throw new IllegalStateException();
+ }
+ }
+
entry.getTemporal().getEffectivity().setStart(effective);
newES.getEntries().add(entry);
entry.setEditionSet(newES);
}
es.getEntries().clear();
em.remove(es);
-
- em.setEditionSet(newES);
-
- return newES;
+
}
}
diff --git a/Temporal Entity Example/src/temporal/TemporalEntityManager.java b/Temporal Entity Example/src/temporal/TemporalEntityManager.java
index d3cfbe6..401ea30 100644
--- a/Temporal Entity Example/src/temporal/TemporalEntityManager.java
+++ b/Temporal Entity Example/src/temporal/TemporalEntityManager.java
@@ -166,6 +166,7 @@
protected void setEditionSet(EditionSet editionSet) {
this.editionSet = editionSet;
this.effective = editionSet.getEffective();
+ setProperty(EFF_TS_PROPERTY, editionSet.getEffective());
}
public boolean hasEditionSet() {
diff --git a/Temporal Entity Example/src/temporal/persistence/ConfigureTemporalDescriptors.java b/Temporal Entity Example/src/temporal/persistence/ConfigureTemporalDescriptors.java
index e94d92b..a87d55f 100644
--- a/Temporal Entity Example/src/temporal/persistence/ConfigureTemporalDescriptors.java
+++ b/Temporal Entity Example/src/temporal/persistence/ConfigureTemporalDescriptors.java
@@ -19,9 +19,11 @@
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import java.util.Vector;
import org.eclipse.persistence.config.CacheIsolationType;
@@ -242,7 +244,9 @@
*/
@SuppressWarnings("unchecked")
private void fixEditionRelationships(ClassDescriptor descriptor, DynamicClassLoader dcl, String suffix) throws ClassNotFoundException {
-
+ Set<ForeignReferenceMapping> temporalMappings = new HashSet<ForeignReferenceMapping>();
+ descriptor.setProperty(DescriptorHelper.TEMPORAL_MAPPINGS, temporalMappings);
+
// Point all reference mappings to TemporalEntity to edition classes
for (DatabaseMapping mapping : descriptor.getMappings()) {
if (mapping.isForeignReferenceMapping()) {
@@ -267,6 +271,7 @@
((ReadObjectQuery) contMapping.getSelectionQuery()).setReferenceClass(frMapping.getReferenceClass());
} else if (frMapping.isOneToOneMapping()) {
fixFKNames(((OneToOneMapping) frMapping).getSourceToTargetKeyFields());
+ temporalMappings.add(frMapping);
} else if (frMapping.isOneToManyMapping()) {
OneToManyMapping otMMapping = (OneToManyMapping) frMapping;
fixFKNames(otMMapping.getTargetForeignKeysToSourceKeys());
@@ -284,7 +289,6 @@
}
otMMapping.addTargetForeignKeyFieldName(sourceField.getQualifiedName(), targetField.getQualifiedName());
}
-
} else {
throw new RuntimeException("Unsupported temporal entity mapping: " + frMapping);
}
diff --git a/Temporal Entity Example/src/temporal/persistence/DescriptorHelper.java b/Temporal Entity Example/src/temporal/persistence/DescriptorHelper.java
index c61b60b..f05d345 100644
--- a/Temporal Entity Example/src/temporal/persistence/DescriptorHelper.java
+++ b/Temporal Entity Example/src/temporal/persistence/DescriptorHelper.java
@@ -15,6 +15,7 @@
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Member;
import java.lang.reflect.Proxy;
+import java.util.Set;
import javax.persistence.EntityManager;
@@ -23,6 +24,7 @@
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.sessions.Session;
import temporal.BaseEntity;
@@ -55,6 +57,11 @@
public static final String EDITION_VIEW = "EditionView";
/**
+ * TODO
+ */
+ public static final String TEMPORAL_MAPPINGS = "TemporalMappings";
+
+ /**
* Copy mapped value from source to new edition. This copies the real
* attribute value.
*/
@@ -121,5 +128,10 @@
}
return session.getClassDescriptor(domainObject);
}
+
+ @SuppressWarnings("unchecked")
+ public static Set<ForeignReferenceMapping> getTemporalMappings(ClassDescriptor descriptor) {
+ return (Set<ForeignReferenceMapping>) descriptor.getProperty(TEMPORAL_MAPPINGS);
+ }
}
diff --git a/Temporal Tests/src/tests/editionsets/BrokenTemporalReferenceTests.java b/Temporal Tests/src/tests/editionsets/BrokenTemporalReferenceTests.java
index f29f92b..5cbb34f 100644
--- a/Temporal Tests/src/tests/editionsets/BrokenTemporalReferenceTests.java
+++ b/Temporal Tests/src/tests/editionsets/BrokenTemporalReferenceTests.java
@@ -10,7 +10,9 @@
******************************************************************************/
package tests.editionsets;
-import static example.PersonModelExample.*;
+import static example.PersonModelExample.T1;
+import static example.PersonModelExample.T2;
+import static example.PersonModelExample.T4;
import javax.persistence.RollbackException;
@@ -20,6 +22,8 @@
import org.junit.Test;
+import temporal.EditionSet;
+import temporal.EditionSetHelper;
import temporal.TemporalEntityManager;
import tests.BaseTestCase;
@@ -37,40 +41,128 @@
* EditionSet@T2 including new
*/
@Test
- public void breakFKDeletingEarliedEntity() {
+ public void breakFKFromEntityByDelete() {
TemporalEntityManager em = getEntityManager();
em.setEffectiveTime(T2);
-
+
em.getTransaction().begin();
Address aT2 = em.newEntity(Address.class);
em.getTransaction().commit();
-
+
Assert.assertTrue(aT2.getContinuityId() > 0);
em.close();
-
+
em = getEntityManager();
em.setEffectiveTime(T4);
-
+
em.getTransaction().begin();
Person pT4 = em.newEntity(Person.class);
Address aT4 = em.find(Address.class, aT2.getContinuityId());
-
+
Assert.assertNotNull(aT4);
Assert.assertEquals(T2, aT4.getEffectivity().getStart());
-
+
pT4.setAddress(aT4);
em.getTransaction().commit();
em.close();
-
+
em = getEntityManager();
em.setEffectiveTime(T2);
aT2 = em.find(Address.class, aT2.getContinuityId());
-
+
em.getTransaction().begin();
em.remove(aT2);
-
+
try {
+ em.getTransaction().commit();
+ } catch (RollbackException e) {
+ return;
+ }
+ Assert.fail("RollbackException execpted for violating FK");
+ }
+
+ @Test
+ public void breakFKFromEntityByMove() {
+ TemporalEntityManager em = getEntityManager();
+ em.setEffectiveTime(T2);
+
+ em.getTransaction().begin();
+ Address aT2 = em.newEntity(Address.class);
em.getTransaction().commit();
+
+ Assert.assertTrue(aT2.getContinuityId() > 0);
+ em.close();
+
+ em = getEntityManager();
+ em.setEffectiveTime(T4);
+
+ em.getTransaction().begin();
+ Person pT4 = em.newEntity(Person.class);
+ Address aT4 = em.find(Address.class, aT2.getContinuityId());
+
+ Assert.assertNotNull(aT4);
+ Assert.assertEquals(T2, aT4.getEffectivity().getStart());
+
+ pT4.setAddress(aT4);
+ em.getTransaction().commit();
+ em.close();
+
+ em = getEntityManager();
+ em.setEffectiveTime(T4);
+ EditionSet es = em.getEditionSet();
+
+ Assert.assertNotNull(es);
+ try {
+ EditionSetHelper.move(em, T1);
+ } catch (IllegalStateException e) {
+ return;
+ }
+ Assert.fail("IllegalStateException execpted for violating FK");
+ }
+
+ /**
+ * SETUP 1. Create new AddressEntity to exist at T2 2. Create new
+ * PersonEdition at T4 3. Reference Address@T2 from Person@T4 TEST Delete
+ * EditionSet@T2 including new
+ */
+ @Test
+ public void breakFKFromEdition() {
+ TemporalEntityManager em = getEntityManager();
+ em.setEffectiveTime(T2);
+
+ em.getTransaction().begin();
+ Address aT2 = em.newEntity(Address.class);
+ Person pT2 = em.newEntity(Person.class);
+ pT2.setAddress(aT2);
+ em.getTransaction().commit();
+
+ Assert.assertTrue(aT2.getContinuityId() > 0);
+ em.close();
+
+ em = getEntityManager();
+ em.setEffectiveTime(T4);
+
+ em.getTransaction().begin();
+ Person pT4 = em.find(Person.class, pT2.getContinuityId());
+ pT4 = em.newEdition(pT4);
+ Address aT4 = em.find(Address.class, aT2.getContinuityId());
+
+ Assert.assertNotNull(aT4);
+ Assert.assertEquals(T2, aT4.getEffectivity().getStart());
+
+ pT4.setAddress(aT4);
+ em.getTransaction().commit();
+ em.close();
+
+ em = getEntityManager();
+ em.setEffectiveTime(T2);
+ aT2 = em.find(Address.class, aT2.getContinuityId());
+
+ em.getTransaction().begin();
+ em.remove(aT2);
+
+ try {
+ em.getTransaction().commit();
} catch (RollbackException e) {
return;
}
diff --git a/Temporal Tests/src/tests/editionsets/MoveSingleEditionSetTests.java b/Temporal Tests/src/tests/editionsets/MoveSingleEditionSetTests.java
index 9b0f446..0f00426 100644
--- a/Temporal Tests/src/tests/editionsets/MoveSingleEditionSetTests.java
+++ b/Temporal Tests/src/tests/editionsets/MoveSingleEditionSetTests.java
@@ -61,12 +61,13 @@
// Make the move
em.getTransaction().begin();
- EditionSet newES = EditionSetHelper.move(em, es, T3);
+ EditionSetHelper.move(em, T3);
+ EditionSet newES = em.getEditionSet();
Assert.assertEquals(T2, es.getEffective());
Assert.assertEquals(0, es.getEntries().size());
Assert.assertFalse(es.hasChanges());
-
+
Assert.assertNotNull(newES);
Assert.assertSame(newES, em.getEditionSet());
Assert.assertEquals(T3, (long) em.getEffectiveTime());
@@ -100,7 +101,8 @@
// Make the move
em.getTransaction().begin();
- EditionSet newES = EditionSetHelper.move(em, es, T1);
+ EditionSetHelper.move(em, T1);
+ EditionSet newES = em.getEditionSet();
Assert.assertEquals(T2, es.getEffective());
Assert.assertEquals(0, es.getEntries().size());
@@ -140,7 +142,7 @@
em.getTransaction().begin();
try {
- EditionSetHelper.move(em, es, BOT);
+ EditionSetHelper.move(em, BOT);
} catch (IllegalArgumentException iae) {
return;
}