changeset 15:e60d38aa42fe

generate differences for missing keys either in the original document or in the conflicting document.
author dirk
date Fri, 16 Sep 2011 17:03:57 +0200
parents f2daf738299f
children 47f6cbd38de3
files conflict-editor/src/main/java/de/codedo/conflicteditor/DocumentMatcher.java conflict-editor/src/test/java/de/codedo/conflicteditor/DocumentMatcherTestCase.java conflict-editor/src/test/java/de/codedo/conflicteditor/matchers/ObjectEqualityMatcher.java
diffstat 3 files changed, 114 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/conflict-editor/src/main/java/de/codedo/conflicteditor/DocumentMatcher.java	Fri Sep 16 11:38:15 2011 +0200
+++ b/conflict-editor/src/main/java/de/codedo/conflicteditor/DocumentMatcher.java	Fri Sep 16 17:03:57 2011 +0200
@@ -21,6 +21,7 @@
 
     private JsonNode _original;
     private JsonNode _other;
+    private List<Difference> _differences;
 
     public DocumentMatcher(JsonNode original, JsonNode other)
     {
@@ -31,22 +32,92 @@
 
     public List<Difference> compare()
     {
-        List<Difference> differences = new ArrayList<Difference>();
+        if (_differences == null)
+        {
+            _differences = new ArrayList<Difference>();
+            createDifferencesFromFieldsOnlyAvailableInOriginal();
+            createDifferencesFromFieldsOnlyAvailableInConflict();
+            createDifferencesFromFieldValues();
+        }
+        return _differences;
+    }
 
+    private void createDifferencesFromFieldsOnlyAvailableInOriginal()
+    {
         Set<String> originalFieldNames = getFieldNames(_original);
+        Set<String> otherFieldNames = getFieldNames(_other);
+        originalFieldNames.removeAll(otherFieldNames);
+
         for (String name : originalFieldNames)
         {
-            // TODO better handling of values - could be of non-string type really
-            Object originalValue = _original.findValue(name).getValueAsText();
-            Object otherValue = _other.findValue(name).getValueAsText();
-            if (originalValue.equals(otherValue) == false)
+            // TODO value may not be text
+            String value = _original.findValue(name).getTextValue();
+            Difference diff = new Difference(name, value, null);
+            _differences.add(diff);
+        }
+    }
+
+    private void createDifferencesFromFieldsOnlyAvailableInConflict()
+    {
+        Set<String> originalFieldNames = getFieldNames(_original);
+        Set<String> otherFieldNames = getFieldNames(_other);
+        otherFieldNames.removeAll(originalFieldNames);
+
+        for (String name : otherFieldNames)
+        {
+            // TODO value may not be text
+            String value = _other.findValue(name).getTextValue();
+            Difference diff = new Difference(name, null, value);
+            _differences.add(diff);
+        }
+    }
+
+    private void createDifferencesFromFieldValues()
+    {
+        Set<String> originalFieldNames = getFieldNames(_original);
+        Set<String> otherFieldNames = getFieldNames(_other);
+        originalFieldNames.retainAll(otherFieldNames);
+
+        for (String name : originalFieldNames)
+        {
+            Difference difference = compareValuesForKey(name);
+            if (difference != null)
             {
-                Difference diff = new Difference(name, originalValue, otherValue);
-                differences.add(diff);
+                _differences.add(difference);
             }
         }
+    }
 
-        return differences;
+    private Difference compareValuesForKey(String key)
+    {
+        JsonNode original = _original.findValue(key);
+        JsonNode other = _other.findValue(key);
+
+        if ((original != null) && (other == null))
+        {
+            // TODO this may be something different than plain text, e.g. some structured object
+            return new Difference(key, original.getValueAsText(), null);
+        }
+        else if ((original == null) && (other != null))
+        {
+            // TODO this may be something different than plain text, e.g. some structured object
+            return new Difference(key, null, other.getValueAsText());
+        }
+        else
+        {
+            return compareValues(key, original, other);
+        }
+    }
+
+    private Difference compareValues(String key, JsonNode original, JsonNode other)
+    {
+        Object originalValue = original.getValueAsText();
+        Object otherValue = other.getValueAsText();
+        if (originalValue.equals(otherValue) == false)
+        {
+            return new Difference(key, originalValue, otherValue);
+        }
+        return null;
     }
 
     private Set<String> getFieldNames(JsonNode node)
--- a/conflict-editor/src/test/java/de/codedo/conflicteditor/DocumentMatcherTestCase.java	Fri Sep 16 11:38:15 2011 +0200
+++ b/conflict-editor/src/test/java/de/codedo/conflicteditor/DocumentMatcherTestCase.java	Fri Sep 16 17:03:57 2011 +0200
@@ -1,6 +1,10 @@
 
 package de.codedo.conflicteditor;
 
+import static de.codedo.conflicteditor.matchers.ObjectEqualityMatcher.isEqualTo;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.hasSize;
 import static org.junit.Assert.assertEquals;
@@ -10,7 +14,6 @@
 
 import org.codehaus.jackson.JsonNode;
 import org.codehaus.jackson.map.ObjectMapper;
-import org.junit.Ignore;
 import org.junit.Test;
 
 public class DocumentMatcherTestCase extends Object
@@ -39,20 +42,27 @@
         assertEquals("other-value", diff.otherValue);
     }
 
-    @Ignore("does not work yet")
     @Test
     public void valuePresentOnlyInOriginalShouldProduceDifference() throws Exception
     {
-        JsonNode original = parse("{ 'key' : 'value', 'only-here' : 'test' }");
+        JsonNode original = parse("{ 'key' : 'value', 'only-here' : 'value' }");
         JsonNode conflict = parse("{ 'key' : 'value' }");
         List<Difference> diffs = new DocumentMatcher(original, conflict).compare();
         assertThat(diffs, hasSize(1));
+
+        Difference diff = diffs.get(0);
+        assertThat(diff.key, is("only-here"));
+        assertThat(diff.currentValue, isEqualTo("value"));
+        assertThat(diff.otherValue, is(nullValue()));
     }
 
-    @Ignore("not yet implemented")
     @Test
-    public void valueOnlyInConflict() throws Exception
+    public void valuePresentOnlyInConflictShouldProduceDifference() throws Exception
     {
+        JsonNode original = parse("{ 'key' : 'value' }");
+        JsonNode conflict = parse("{ 'key' : 'value', 'only-here' : 'test' }");
+        List<Difference> diffs = new DocumentMatcher(original, conflict).compare();
+        assertThat(diffs, hasSize(1));
     }
 
     private JsonNode parse(String input) throws IOException
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conflict-editor/src/test/java/de/codedo/conflicteditor/matchers/ObjectEqualityMatcher.java	Fri Sep 16 17:03:57 2011 +0200
@@ -0,0 +1,20 @@
+
+package de.codedo.conflicteditor.matchers;
+
+import org.hamcrest.Factory;
+import org.hamcrest.Matcher;
+import org.hamcrest.core.IsEqual;
+
+public class ObjectEqualityMatcher extends IsEqual<Object>
+{
+    public ObjectEqualityMatcher(Object equalArg)
+    {
+        super(equalArg);
+    }
+
+    @Factory
+    public static Matcher<Object> isEqualTo(Object operand)
+    {
+        return new ObjectEqualityMatcher(operand);
+    }
+}