Enhancer { public T enhance(T t) { if (!needsEnhancement(t)) { return t; } try { return getEnhancedClass().getConstructor(baseClass).newInstance(t); } catch (Exception e) { throw new RuntimeException(String.format("Could not enhance object %s (%s)", t, t.getClass()), e); } } protected  Enhancer(Class<T> baseClass); abstract boolean needsEnhancement(Object object); void validateClassIsEnhanceable(Class<T> baseClass); final Class<T> getBaseClass(); Class<? extends T> getEnhancedClass(); T newInstance(); T enhance(T t);  }
@Test public void enhancedSubclassIsDirtyWorks() { SampleClass2 testObject2 = new SampleClass2(); testObject2.setFoo(toString()); long bar = System.nanoTime(); testObject2.setBar(bar); assertEquals(toString(), testObject2.getFoo()); assertEquals(bar, testObject2.getBar()); SampleClass2 enhanced = enhancer2.enhance(testObject2); ((Snapshot) enhanced).snapshot(); assertNotSame(testObject2, enhanced); assertNotNull(enhanced); assertDirty(enhanced, false); assertEquals(toString(), enhanced.getFoo()); assertEquals(bar, enhanced.getBar()); enhanced.setFoo(null); assertNull(enhanced.getFoo()); assertDirty(enhanced, true); enhanced.setFoo(toString()); assertDirty(enhanced, false); enhanced.setBar(0L); assertEquals(0L, enhanced.getBar()); assertDirty(enhanced, true); enhanced.setFoo("something else"); ((Snapshot) enhanced).snapshot(); assertDirty(enhanced, false); }
@Test public void detectsMutationOfOriginal() { SampleClass testObject = new SampleClass(); testObject.setFoo("bar"); SampleClass enhanced = enhancer.enhance(testObject); ((Snapshot) enhanced).snapshot(); assertDirty(enhanced, false); assertEquals("bar", enhanced.getFoo()); testObject.setFoo(null); assertNull(enhanced.getFoo()); assertDirty(enhanced, true); ((Snapshot) enhanced).snapshot(); assertDirty(enhanced, false); testObject.setNumberObject(1234L); assertDirty(enhanced, true); assertEquals(1234L, enhanced.getNumberObject().longValue()); ((Snapshot) enhanced).snapshot(); assertDirty(enhanced, false); }
@Test public void enhanceClassThatDoesntNeedIt() { SampleClass sampleClass = new SampleClassThatImplementsSnapshot(); SampleClass enhanced = enhancer.enhance(sampleClass); assertNotNull(enhanced); assertTrue(enhanced instanceof Persistent); assertTrue(enhanced instanceof Snapshot); assertSame(sampleClass, enhanced); }
@Test public void ifYouEnhancedNullYouGetNull() { assertNull(enhancer.enhance(null)); }
@Test public void implementsGetsDirty() { SampleClass enhanced = enhancer.enhance(new SampleClass()); assertNotNull(enhanced); assertTrue(enhanced instanceof Persistent); }
@Test public void enhancedIsDirtyWorks() { SampleClass testObject = new SampleClass(); testObject.setFoo("bar"); SampleClass enhanced = enhancer.enhance(testObject); ((Snapshot) enhanced).snapshot(); assertDirty(enhanced, false); assertEquals("bar", enhanced.getFoo()); enhanced.setFoo(null); assertNull(enhanced.getFoo()); assertDirty(enhanced, true); ((Snapshot) enhanced).snapshot(); assertDirty(enhanced, false); }
@Test public void enhancedAnonymousSubclassWorks() { SampleClass testObject = new SampleClass() {{ setFoo("bar"); }}; SampleClass enhanced = enhancer.enhance(testObject); ((Snapshot) enhanced).snapshot(); assertDirty(enhanced, false); assertEquals("bar", enhanced.getFoo()); enhanced.setFoo(null); assertNull(enhanced.getFoo()); assertDirty(enhanced, true); ((Snapshot) enhanced).snapshot(); assertDirty(enhanced, false); }