Change implements Serializable { public static <C extends Identified<?>> Change<C> update(C oldObject, C newObject) { Preconditions.checkArgument(oldObject != null, "Attempted to create an update from a null oldObject"); Preconditions.checkArgument(newObject != null, "Attempted to create an update to a null newObject"); Preconditions.checkArgument(newObject.getId().equals(oldObject.getId()), "Attempted to create an update with non-matching ids."); return new Change<>(oldObject, newObject); } private  Change(@Nullable C originalObject, @Nullable C newObject); static Change<C> add(C newObject); static Change<C> update(C oldObject, C newObject); static Change<C> delete(C oldObject); static Change<C> identity(C object); Change<C> map(UnaryOperator<C> mapper); Optional<C> getNewObject(); Optional<C> getOriginalObject(); Identity<?> getId(); @Override boolean equals(Object o); @Override int hashCode(); @Override String toString(); @CheckForNull final C originalObject; @CheckForNull final C newObject; }
@Test void update_withNonNullMatched_returnsExpected() { Change<TestState> update = Change.update(OBJECT1_V1, OBJECT1_V2); Assertions.assertEquals(OBJECT1_V1, update.originalObject, "Original object not set as expected"); Assertions.assertEquals(OBJECT1_V2, update.newObject, "New object not set as expected"); }
@Test void update_withOldNull_throwsException() { Assertions.assertThrows(IllegalArgumentException.class, () -> Change.update(null, OBJECT1_V1), "Expected exception on updating from a null state"); }
@Test void update_withNewNull_throwsException() { Assertions.assertThrows(IllegalArgumentException.class, () -> Change.update(OBJECT1_V1, null), "Expected exception on updating to a null state"); }
@Test void update_withMismatchedIds_throwsException() { Assertions.assertThrows(IllegalArgumentException.class, () -> Change.update(OBJECT1_V1, OBJECT2), "Expected exception on updating with mismatched Ids"); }