JOHNZON-103 implemented JsonPatchDiff for JsonArray

still more tests needed


Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo
Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/e2905f9e
Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/e2905f9e
Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/e2905f9e

Branch: refs/heads/master
Commit: e2905f9ec8313627ccd5bb6896511b57fe7aa2c5
Parents: bcd4533
Author: Reinhard Sandtner <[email protected]>
Authored: Tue Mar 7 20:38:28 2017 +0100
Committer: Reinhard Sandtner <[email protected]>
Committed: Tue Mar 7 20:38:28 2017 +0100

----------------------------------------------------------------------
 .../org/apache/johnzon/core/JsonPatchDiff.java  |  59 ++++--
 .../apache/johnzon/core/JsonPatchDiffTest.java  | 200 +++++++++++++------
 2 files changed, 182 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/johnzon/blob/e2905f9e/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java
----------------------------------------------------------------------
diff --git 
a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java 
b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java
index a326f94..bab7bd1 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java
@@ -42,40 +42,54 @@ class JsonPatchDiff {
     JsonPatch calculateDiff() {
         JsonPatchBuilder patchBuilder = new JsonPatchBuilderImpl();
 
-        diff(patchBuilder, "/", source, target);
+        diff(patchBuilder, "", source, target);
 
         return patchBuilder.build();
     }
 
-    private void diff(JsonPatchBuilder patchBuilder, String basePath, 
JsonStructure source, JsonStructure target) {
+    private void diff(JsonPatchBuilder patchBuilder, String basePath, 
JsonValue source, JsonValue target) {
+
         if (isJsonObject(source) && isJsonObject(target)) {
-            // handle JsonObjects
-            diffJsonObjects(patchBuilder, basePath, (JsonObject) source, 
(JsonObject) target);
-
-        } else if (source instanceof JsonArray && target instanceof JsonArray) 
{
-            // handle JsonArray
-            //X TODO
-            throw new UnsupportedOperationException("not yet implemented.");
-        } else {
-            throw new UnsupportedOperationException("not yet implemented.");
+            diffJsonObjects(patchBuilder, basePath + "/", (JsonObject) source, 
(JsonObject) target);
+        } else if (isJsonArray(source) && isJsonArray(target)) {
+            diffJsonArray(patchBuilder, basePath + "/", (JsonArray) source, 
(JsonArray) target);
+        } else if (!source.equals(target)){
+            patchBuilder.replace(basePath, target);
         }
     }
 
+    private void diffJsonArray(JsonPatchBuilder patchBuilder, String basePath, 
JsonArray source, JsonArray target) {
+
+        for (int i = 0; i < source.size(); i++) {
+
+            JsonValue sourceValue = source.get(i);
+
+            if (target.size() <= i) {
+                patchBuilder.remove(basePath + i);
+                continue;
+            }
+
+            diff(patchBuilder, basePath + i, sourceValue, target.get(i));
+        }
+
+        if (target.size() > source.size()) {
+
+            for (int i = target.size() - source.size(); i < target.size(); 
i++) {
+                patchBuilder.add(basePath + i, target.get(i));
+            }
+        }
+
+    }
+
     private void diffJsonObjects(JsonPatchBuilder patchBuilder, String 
basePath, JsonObject source, JsonObject target) {
         Set<Map.Entry<String, JsonValue>> sourceEntries = source.entrySet();
 
         for (Map.Entry<String, JsonValue> sourceEntry : sourceEntries) {
+
             String attributeName = sourceEntry.getKey();
+
             if (target.containsKey(attributeName)) {
-                JsonValue targetValue = target.get(attributeName);
-
-                if (isJsonObject(targetValue) && isJsonObject(targetValue)) {
-                    diffJsonObjects(patchBuilder, basePath + 
JsonPointerUtil.encode(attributeName) + "/",
-                            (JsonObject) sourceEntry.getValue(), (JsonObject) 
targetValue);
-                } else if (!sourceEntry.getValue().equals(targetValue)) {
-                    // replace the original value
-                    patchBuilder.replace(basePath + 
JsonPointerUtil.encode(attributeName), targetValue);
-                }
+                diff(patchBuilder, basePath + 
JsonPointerUtil.encode(attributeName), sourceEntry.getValue(), 
target.get(attributeName));
             } else {
                 // the value got removed
                 patchBuilder.remove(basePath + 
JsonPointerUtil.encode(attributeName));
@@ -95,4 +109,9 @@ class JsonPatchDiff {
     private static boolean isJsonObject(JsonValue jsonValue) {
         return jsonValue instanceof JsonObject;
     }
+
+    private static boolean isJsonArray(JsonValue targetValue) {
+        return targetValue instanceof JsonArray;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/e2905f9e/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java 
b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java
index a85c1cf..51bada2 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java
@@ -44,7 +44,7 @@ public class JsonPatchDiffTest {
         // this results in 1 diff operations:
         // adding "b"
         JsonPatch jsonPatch = Json.createDiff(Json.createReader(new 
StringReader(jsonA)).readObject(),
-                Json.createReader(new StringReader(jsonB)).readObject());
+                                              Json.createReader(new 
StringReader(jsonB)).readObject());
         assertNotNull(jsonPatch);
         JsonArray patchOperations = jsonPatch.toJsonArray();
         assertNotNull(patchOperations);
@@ -56,10 +56,10 @@ public class JsonPatchDiffTest {
     public void testAddDiffNewObject() {
 
         JsonObject target = Json.createObjectBuilder()
-                .add("a", Json.createObjectBuilder()
-                        .add("aa", "value")
-                        .add("ab", "another"))
-                .build();
+                                .add("a", Json.createObjectBuilder()
+                                              .add("aa", "value")
+                                              .add("ab", "another"))
+                                .build();
 
         JsonPatch patch = Json.createDiff(JsonValue.EMPTY_JSON_OBJECT, target);
         assertNotNull(patch);
@@ -78,10 +78,10 @@ public class JsonPatchDiffTest {
     public void testAddDiffNewObjectWithEscaping() {
 
         JsonObject target = Json.createObjectBuilder()
-                .add("a~/", Json.createObjectBuilder()
-                        .add("esc/aped", "value")
-                        .add("tilde", "another"))
-                .build();
+                                .add("a~/", Json.createObjectBuilder()
+                                                .add("esc/aped", "value")
+                                                .add("tilde", "another"))
+                                .build();
 
         JsonPatch patch = Json.createDiff(JsonValue.EMPTY_JSON_OBJECT, target);
         assertNotNull(patch);
@@ -100,15 +100,15 @@ public class JsonPatchDiffTest {
     public void testAddDiffInNestedObject() {
 
         JsonObject source = Json.createObjectBuilder()
-                .add("a", Json.createObjectBuilder()
-                        .add("aa", "value"))
-                .build();
+                                .add("a", Json.createObjectBuilder()
+                                              .add("aa", "value"))
+                                .build();
 
         JsonObject target = Json.createObjectBuilder()
-                .add("a", Json.createObjectBuilder()
-                        .add("aa", "value")
-                        .add("bb", "another value"))
-                .build();
+                                .add("a", Json.createObjectBuilder()
+                                              .add("aa", "value")
+                                              .add("bb", "another value"))
+                                .build();
 
         JsonPatch patch = Json.createDiff(source, target);
         assertNotNull(patch);
@@ -123,8 +123,8 @@ public class JsonPatchDiffTest {
     public void testRemoveDiffObject() {
 
         JsonObject source = Json.createObjectBuilder()
-                .add("a", "value")
-                .build();
+                                .add("a", "value")
+                                .build();
 
         JsonPatch patch = Json.createDiff(source, JsonValue.EMPTY_JSON_OBJECT);
         assertNotNull(patch);
@@ -139,11 +139,11 @@ public class JsonPatchDiffTest {
     public void testRemoveDiffNestedObject() {
 
         JsonObject source = Json.createObjectBuilder()
-                .add("a", "value")
-                .add("nested", Json.createObjectBuilder()
-                        .add("1", 1)
-                        .add("2", 2))
-                .build();
+                                .add("a", "value")
+                                .add("nested", Json.createObjectBuilder()
+                                                   .add("1", 1)
+                                                   .add("2", 2))
+                                .build();
 
         {
             JsonPatch patch = Json.createDiff(source, 
JsonValue.EMPTY_JSON_OBJECT);
@@ -158,10 +158,10 @@ public class JsonPatchDiffTest {
 
         {
             JsonObject target = Json.createObjectBuilder()
-                    .add("a", "value")
-                    .add("nested", Json.createObjectBuilder()
-                            .add("1", 1))
-                    .build();
+                                    .add("a", "value")
+                                    .add("nested", Json.createObjectBuilder()
+                                                       .add("1", 1))
+                                    .build();
 
             JsonPatch patch = Json.createDiff(source, target);
             assertNotNull(patch);
@@ -177,12 +177,12 @@ public class JsonPatchDiffTest {
     public void testDiffEqualObjects() {
 
         JsonObject source = Json.createObjectBuilder()
-                .add("a", "value")
-                .build();
+                                .add("a", "value")
+                                .build();
 
         JsonObject target = Json.createObjectBuilder()
-                .add("a", "value")
-                .build();
+                                .add("a", "value")
+                                .build();
 
         JsonPatch patch = Json.createDiff(source, target);
         assertNotNull(patch);
@@ -193,12 +193,12 @@ public class JsonPatchDiffTest {
     public void testDiffReplaceObject() {
 
         JsonObject source = Json.createObjectBuilder()
-                .add("a", "value")
-                .build();
+                                .add("a", "value")
+                                .build();
 
         JsonObject target = Json.createObjectBuilder()
-                .add("a", "replaced")
-                .build();
+                                .add("a", "replaced")
+                                .build();
 
         JsonPatch patch = Json.createDiff(source, target);
         assertNotNull(patch);
@@ -213,14 +213,14 @@ public class JsonPatchDiffTest {
     public void testDiffReplaceFromNestedObject() {
 
         JsonObject source = Json.createObjectBuilder()
-                .add("a", Json.createObjectBuilder()
-                        .add("aa", "value"))
-                .build();
+                                .add("a", Json.createObjectBuilder()
+                                              .add("aa", "value"))
+                                .build();
 
         JsonObject target = Json.createObjectBuilder()
-                .add("a", Json.createObjectBuilder()
-                        .add("aa", "replaced"))
-                .build();
+                                .add("a", Json.createObjectBuilder()
+                                              .add("aa", "replaced"))
+                                .build();
 
         JsonPatch patch = Json.createDiff(source, target);
         assertNotNull(patch);
@@ -237,16 +237,16 @@ public class JsonPatchDiffTest {
     public void testDiffMoveValue() {
 
         JsonObject source = Json.createObjectBuilder()
-                .add("a", Json.createObjectBuilder()
-                        .add("aa", "valueToMove"))
-                .add("b", JsonValue.EMPTY_JSON_OBJECT)
-                .build();
+                                .add("a", Json.createObjectBuilder()
+                                              .add("aa", "valueToMove"))
+                                .add("b", JsonValue.EMPTY_JSON_OBJECT)
+                                .build();
 
         JsonObject target = Json.createObjectBuilder()
-                .add("a", JsonValue.EMPTY_JSON_OBJECT)
-                .add("b", Json.createObjectBuilder()
-                        .add("aa", "valueToMove"))
-                .build();
+                                .add("a", JsonValue.EMPTY_JSON_OBJECT)
+                                .add("b", Json.createObjectBuilder()
+                                              .add("aa", "valueToMove"))
+                                .build();
 
         JsonPatch patch = Json.createDiff(source, target);
         assertNotNull(patch);
@@ -261,16 +261,101 @@ public class JsonPatchDiffTest {
     }
 
 
+    @Test
+    public void testAddValueToArray() {
+
+        JsonArray source = Json.createArrayBuilder()
+                               .add("first")
+                               .build();
+
+        JsonArray target = Json.createArrayBuilder()
+                               .add("first")
+                               .add("second")
+                               .build();
+
+        JsonPatch patch = Json.createDiff(source, target);
+        assertNotNull(patch);
+
+        JsonArray operations = patch.toJsonArray();
+        assertEquals(1, operations.size());
+
+        containsOperation(operations, JsonPatch.Operation.ADD, "/1", 
Json.createValue("second"));
+    }
+
+    @Test
+    public void testAddObjectToArray() {
+
+        JsonArray source = Json.createArrayBuilder()
+                .add(Json.createObjectBuilder()
+                        .add("a", "a"))
+                .build();
+
+        JsonArray target = Json.createArrayBuilder()
+                               .add(Json.createObjectBuilder()
+                                        .add("a", "a"))
+                               .add(Json.createObjectBuilder()
+                                        .add("a", "b"))
+                               .build();
+
+
+        JsonPatch patch = Json.createDiff(source, target);
+        assertNotNull(patch);
+
+        JsonArray operations = patch.toJsonArray();
+        assertEquals(1, operations.size());
+
+        containsOperation(operations, JsonPatch.Operation.ADD, "/1", 
Json.createObjectBuilder()
+                                                                         
.add("a", "b")
+                                                                         
.build());
+    }
+
+    @Test
+    public void testRemoveValueFromArray() {
+
+        JsonArray source = Json.createArrayBuilder()
+                               .add("a")
+                               .add("b")
+                               .build();
+
+        JsonArray target = Json.createArrayBuilder()
+                               .add("b")
+                               .build();
+
+        JsonPatch patch = Json.createDiff(source, target);
+        assertNotNull(patch);
+
+        JsonArray operations = patch.toJsonArray();
+        assertEquals(2, operations.size());
+
+        containsOperation(operations, JsonPatch.Operation.REPLACE, "/0", 
Json.createValue("b"));
+        containsOperation(operations, JsonPatch.Operation.REMOVE, "/1");
+    }
+
+    @Test
+    public void testRemoveObjectFromArray() {
+
+        JsonArray source = Json.createArrayBuilder()
+                               .add(Json.createObjectBuilder()
+                                        .add("a", "a")
+                                        .add("b", "b"))
+                               .build();
+
+        JsonPatch patch = Json.createDiff(source, JsonValue.EMPTY_JSON_ARRAY);
+        assertNotNull(patch);
 
-    //X TODO arrays...
-    //X TODO test add/remove JsonArray
-    //X TODO test add object to JsonArray
-    //X TODO test remove object to JsonArray
+        JsonArray operations = patch.toJsonArray();
+        assertEquals(1, operations.size());
+
+        containsOperation(operations, JsonPatch.Operation.REMOVE, "/0");
+    }
 
+    //X TODO replaceValueInArray
+    //X TODO replaceObjectInArray
+    //X TODO Object in Array
+    //X TODO Array in Object
 
 
     @Test
-    @Ignore //X TODO reinhard take over ;)
     public void testComplexDiff() {
         // {"a":"xa","b":2,"c":{"d":"xd"},"e":[1,2,3]}
         String jsonA = 
"{\"a\":\"xa\",\"b\":2,\"c\":{\"d\":\"xd\"},\"e\":[1,2,3]}";
@@ -278,16 +363,17 @@ public class JsonPatchDiffTest {
         // {"a":"xa","c":{"d":"xd", "d2":"xd2"},"e":[1,3],"f":"xe"}
         String jsonB = "{\"a\":\"xa\",\"c\":{\"d\":\"xd\", 
\"d2\":\"xd2\"},\"e\":[1,3],\"f\":\"xe\"}";
 
-        // this results in 4 diff operations:
-        // removing b, adding d2, removing 2 from e, adding f
+        // this results in 5 diff operations:
+        // removing b, adding d2, replacing 2 with 3 from e, removing 3 from 
3, adding f
         JsonPatch jsonPatch = Json.createDiff(Json.createReader(new 
StringReader(jsonA)).readObject(),
                 Json.createReader(new StringReader(jsonB)).readObject());
         assertNotNull(jsonPatch);
         JsonArray patchOperations = jsonPatch.toJsonArray();
         assertNotNull(patchOperations);
-        assertEquals(4, patchOperations.size());
+        assertEquals(5, patchOperations.size());
         containsOperation(patchOperations, JsonPatch.Operation.REMOVE, "/b");
         containsOperation(patchOperations, JsonPatch.Operation.ADD, "/c/d2", 
Json.createValue("xd2"));
+        containsOperation(patchOperations, JsonPatch.Operation.REPLACE, 
"/e/1", Json.createValue(3));
         containsOperation(patchOperations, JsonPatch.Operation.REMOVE, "/e/2");
         containsOperation(patchOperations, JsonPatch.Operation.ADD, "/f", 
Json.createValue("xe"));
     }

Reply via email to