From 1430c9217b215a64a70cae4c2e5f4f86ec532d68 Mon Sep 17 00:00:00 2001 From: Robert von Burg Date: Mon, 12 Aug 2013 11:54:57 +0200 Subject: [PATCH] Fixed remaining failing tests by implementing the replacing of objects in the filter as required --- .../utils/objectfilter/ObjectFilter.java | 44 +++- .../utils/objectfilter/ObjectFilterTest.java | 204 +++++++++++++++++- 2 files changed, 231 insertions(+), 17 deletions(-) diff --git a/src/main/java/ch/eitchnet/utils/objectfilter/ObjectFilter.java b/src/main/java/ch/eitchnet/utils/objectfilter/ObjectFilter.java index 7ee255595..def9671a8 100644 --- a/src/main/java/ch/eitchnet/utils/objectfilter/ObjectFilter.java +++ b/src/main/java/ch/eitchnet/utils/objectfilter/ObjectFilter.java @@ -118,9 +118,6 @@ public class ObjectFilter { if (ObjectFilter.logger.isDebugEnabled()) ObjectFilter.logger.debug("add object " + objectToAdd + " with key " + key); - // add the key to the set - this.keySet.add(key); - // BEWARE: you fix a bug here, be sure to update BOTH tables on the logic. ObjectCache cached = this.cache.get(objectToAdd); if (cached == null) { @@ -148,11 +145,30 @@ public class ObjectFilter { case MODIFY: throw new IllegalStateException("Stale State exception: Invalid + after +="); case REMOVE: + // replace key if necessary + replaceKey(cached.getObject(), objectToAdd); + + // update operation's object cached.setObject(objectToAdd); cached.setOperation(Operation.MODIFY); break; } // switch }// else of object not in cache + + // register the key + this.keySet.add(key); + } + + private void replaceKey(Object oldObject, Object newObject) { + if (oldObject != newObject) { + if (ObjectFilter.logger.isDebugEnabled()) { + String msg = "Replacing key for object as they are not the same reference: old: {0} / new: {1}"; + msg = MessageFormat.format(msg, oldObject, newObject); + ObjectFilter.logger.warn(msg); + } + ObjectCache objectCache = this.cache.remove(oldObject); + this.cache.put(newObject, objectCache); + } } /** @@ -184,9 +200,6 @@ public class ObjectFilter { if (ObjectFilter.logger.isDebugEnabled()) ObjectFilter.logger.debug("update object " + objectToUpdate + " with key " + key); - // add the key to the keyset - this.keySet.add(key); - // BEWARE: you fix a bug here, be sure to update BOTH tables on the logic. ObjectCache cached = this.cache.get(objectToUpdate); if (cached == null) { @@ -209,15 +222,20 @@ public class ObjectFilter { Operation op = cached.getOperation(); switch (op) { case ADD: - cached.setObject(objectToUpdate); - break; case MODIFY: + // replace key if necessary + replaceKey(cached.getObject(), objectToUpdate); + + // update operation's object cached.setObject(objectToUpdate); break; case REMOVE: throw new IllegalStateException("Stale State exception: Invalid += after -"); } // switch }// else of object not in cache + + // register the key + this.keySet.add(key); } /** @@ -249,9 +267,6 @@ public class ObjectFilter { if (ObjectFilter.logger.isDebugEnabled()) ObjectFilter.logger.debug("remove object " + objectToRemove + " with key " + key); - // add the key to the keyset - this.keySet.add(key); - // BEWARE: you fix a bug here, be sure to update BOTH tables on the logic. ObjectCache cached = this.cache.get(objectToRemove); if (cached == null) { @@ -277,6 +292,10 @@ public class ObjectFilter { this.cache.remove(objectToRemove); break; case MODIFY: + // replace key if necessary + replaceKey(cached.getObject(), objectToRemove); + + // update operation's object cached.setObject(objectToRemove); cached.setOperation(Operation.REMOVE); break; @@ -284,6 +303,9 @@ public class ObjectFilter { throw new IllegalStateException("Stale State exception: Invalid - after -"); } // switch } + + // register the key + this.keySet.add(key); } /** diff --git a/src/test/java/ch/eitchnet/utils/objectfilter/ObjectFilterTest.java b/src/test/java/ch/eitchnet/utils/objectfilter/ObjectFilterTest.java index 5ae6b64b4..ef30ddee4 100644 --- a/src/test/java/ch/eitchnet/utils/objectfilter/ObjectFilterTest.java +++ b/src/test/java/ch/eitchnet/utils/objectfilter/ObjectFilterTest.java @@ -19,13 +19,14 @@ */ package ch.eitchnet.utils.objectfilter; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.*; - import java.util.List; import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + /** * @author Robert von Burg * @@ -208,7 +209,7 @@ public class ObjectFilterTest { filter.update("different_key", myObj); fail("Should have failed because of different key for already registered object"); } catch (RuntimeException e) { - String msg = "Invalid key provided for object with transaction ID -1 and operation MODIFY: existing key is java.lang.Object, new key is different_key. Object may be present in the same filter instance only once, registered using one key only. Object"; + String msg = "Object may be present in the same filter instance only once, registered using one key only"; assertTrue("Encountered exception: " + e.getMessage(), e.getMessage().contains(msg)); } @@ -216,8 +217,79 @@ public class ObjectFilterTest { } @Test - public void shouldReplaceInstanceIfObjectIsEqual() { - fail("Not yet implemented"); + public void shouldReplaceOnAddAfterRemove() { + + TestObject obj1 = new TestObject(1); + TestObject obj2 = new TestObject(1); + assertEquals("Test objects are not equal!", obj1, obj2); + + ObjectFilter filter = new ObjectFilter(); + filter.remove(Object.class.getName(), obj1); + filter.add(Object.class.getName(), obj2); + + testAssertions(filter, 1, 1, 0, 1, 0); + + List updated = filter.getUpdated(Object.class.getName()); + Object updatedObj = updated.get(0); + String msg = "registered object is not the last operation's object"; + assertTrue(msg, obj2 == updatedObj); + } + + @Test + public void shouldReplaceOnUpdateAfterAdd() { + + TestObject obj1 = new TestObject(1); + TestObject obj2 = new TestObject(1); + assertEquals("Test objects are not equal!", obj1, obj2); + + ObjectFilter filter = new ObjectFilter(); + filter.add(Object.class.getName(), obj1); + filter.update(Object.class.getName(), obj2); + + testAssertions(filter, 1, 1, 1, 0, 0); + + List added = filter.getAdded(Object.class.getName()); + Object addedObj = added.get(0); + String msg = "registered object is not the last operation's object"; + assertTrue(msg, obj2 == addedObj); + } + + @Test + public void shouldReplaceOnUpdateAfterUpdate() { + + TestObject obj1 = new TestObject(1); + TestObject obj2 = new TestObject(1); + assertEquals("Test objects are not equal!", obj1, obj2); + + ObjectFilter filter = new ObjectFilter(); + filter.update(Object.class.getName(), obj1); + filter.update(Object.class.getName(), obj2); + + testAssertions(filter, 1, 1, 0, 1, 0); + + List updated = filter.getUpdated(Object.class.getName()); + Object updatedObj = updated.get(0); + String msg = "registered object is not the last operation's object"; + assertTrue(msg, obj2 == updatedObj); + } + + @Test + public void shouldReplaceOnRemoveAfterModify() { + + TestObject obj1 = new TestObject(1); + TestObject obj2 = new TestObject(1); + assertEquals("Test objects are not equal!", obj1, obj2); + + ObjectFilter filter = new ObjectFilter(); + filter.update(Object.class.getName(), obj1); + filter.remove(Object.class.getName(), obj2); + + testAssertions(filter, 1, 1, 0, 0, 1); + + List removed = filter.getRemoved(Object.class.getName()); + Object removedObj = removed.get(0); + String msg = "registered object is not the last operation's object"; + assertTrue(msg, obj2 == removedObj); } @Test @@ -231,6 +303,89 @@ public class ObjectFilterTest { testAssertions(filter, 0, 1, 0, 0, 0); } + @Test + public void shouldClear() { + + Object myObj1 = new Object(); + Object myObj2 = new Object(); + Object myObj3 = new Object(); + + ObjectFilter filter = new ObjectFilter(); + filter.add(myObj1); + filter.update(myObj2); + filter.remove(myObj3); + + filter.clearCache(); + + testAssertions(filter, 0, 0, 0, 0, 0); + } + + @Test + public void shouldGetAll() { + + Object myObj1 = new Object(); + Object myObj2 = new Object(); + Object myObj3 = new Object(); + + ObjectFilter filter = new ObjectFilter(); + filter.add(myObj1); + filter.update(myObj2); + filter.remove(myObj3); + + testAssertions(filter, 3, 1, 1, 1, 1); + + List all = filter.getAll(Object.class.getName()); + assertEquals(3, all.size()); + assertTrue(all.contains(myObj1)); + assertTrue(all.contains(myObj2)); + assertTrue(all.contains(myObj3)); + } + + @Test + public void shouldGetAdded() { + + Object myObj1 = new Object(); + + ObjectFilter filter = new ObjectFilter(); + filter.add(myObj1); + + testAssertions(filter, 1, 1, 1, 0, 0); + + List list = filter.getAdded(Object.class.getName()); + assertEquals(1, list.size()); + assertTrue(list.contains(myObj1)); + } + + @Test + public void shouldGetUpdated() { + + Object myObj1 = new Object(); + + ObjectFilter filter = new ObjectFilter(); + filter.update(myObj1); + + testAssertions(filter, 1, 1, 0, 1, 0); + + List list = filter.getUpdated(Object.class.getName()); + assertEquals(1, list.size()); + assertTrue(list.contains(myObj1)); + } + + @Test + public void shouldGetRemoved() { + + Object myObj1 = new Object(); + + ObjectFilter filter = new ObjectFilter(); + filter.remove(myObj1); + + testAssertions(filter, 1, 1, 0, 0, 1); + + List list = filter.getRemoved(Object.class.getName()); + assertEquals(1, list.size()); + assertTrue(list.contains(myObj1)); + } + private void testAssertions(ObjectFilter filter, int size, int sizeKeySet, int added, int updated, int removed) { assertEquals(size, filter.sizeCache()); assertEquals(sizeKeySet, filter.sizeKeySet()); @@ -244,4 +399,41 @@ public class ObjectFilterTest { List removedList = filter.getRemoved(Object.class.getName()); assertEquals(removed, removedList.size()); } + + private class TestObject { + private int id; + + public TestObject(int id) { + this.id = id; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + getOuterType().hashCode(); + result = prime * result + id; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TestObject other = (TestObject) obj; + if (!getOuterType().equals(other.getOuterType())) + return false; + if (id != other.id) + return false; + return true; + } + + private ObjectFilterTest getOuterType() { + return ObjectFilterTest.this; + } + } }