You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by st...@apache.org on 2017/02/27 20:35:10 UTC

johnzon git commit: JOHNZON-103 add tests and basic impl for JsonPatch Diff handling

Repository: johnzon
Updated Branches:
  refs/heads/master 61a130e3e -> 2940f6e13


JOHNZON-103 add tests and basic impl for JsonPatch Diff handling


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

Branch: refs/heads/master
Commit: 2940f6e1309080f37a70ac538275d80b9d5abe19
Parents: 61a130e
Author: Mark Struberg <st...@apache.org>
Authored: Mon Feb 27 21:34:34 2017 +0100
Committer: Mark Struberg <st...@apache.org>
Committed: Mon Feb 27 21:34:34 2017 +0100

----------------------------------------------------------------------
 .../org/apache/johnzon/core/JsonPatchDiff.java  | 88 ++++++++++++++++++
 .../apache/johnzon/core/JsonProviderImpl.java   |  5 ++
 .../johnzon/core/JsonMergeBatchBuilderTest.java | 20 ++---
 .../apache/johnzon/core/JsonPatchDiffTest.java  | 93 ++++++++++++++++++++
 .../org/apache/johnzon/core/JsonPatchTest.java  | 39 --------
 5 files changed, 196 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/johnzon/blob/2940f6e1/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
new file mode 100644
index 0000000..81a7bf2
--- /dev/null
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchDiff.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.johnzon.core;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonPatch;
+import javax.json.JsonPatchBuilder;
+import javax.json.JsonStructure;
+import javax.json.JsonValue;
+
+/**
+ * Create a diff from a source and target JsonStructure
+ */
+public class JsonPatchDiff {
+
+    private final JsonStructure source;
+    private final JsonStructure target;
+
+    public JsonPatchDiff(JsonStructure source, JsonStructure target) {
+        this.source = source;
+        this.target = target;
+    }
+
+    public JsonPatch calculateDiff() {
+        JsonPatchBuilder patchBuilder = new JsonPatchBuilderImpl();
+
+        diff(patchBuilder, "/", source, target);
+
+        return patchBuilder.build();
+    }
+
+    private void diff(JsonPatchBuilder patchBuilder, String basePath, JsonStructure source, JsonStructure target) {
+        if (source instanceof JsonObject && target instanceof JsonObject) {
+            // 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.");
+        }
+    }
+
+    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 = ((JsonObject) target).get(attributeName);
+                if (!sourceEntry.getValue().equals(targetValue)) {
+                    // replace the original value
+                    patchBuilder.replace(basePath + attributeName, targetValue);
+                }
+            } else {
+                // the value got removed
+                patchBuilder.remove(basePath + attributeName);
+            }
+        }
+
+        Set<Map.Entry<String, JsonValue>> targetEntries = target.entrySet();
+        for (Map.Entry<String, JsonValue> targetEntry : targetEntries) {
+            if (!source.containsKey(targetEntry.getKey())) {
+                patchBuilder.add(basePath + targetEntry.getKey(), targetEntry.getValue());
+            }
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/2940f6e1/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
index 354158a..9df37da 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonProviderImpl.java
@@ -364,6 +364,11 @@ public class JsonProviderImpl extends JsonProvider implements Serializable {
             return createPatchBuilder(array).build();
         }
 
+        @Override
+        public JsonPatch createDiff(JsonStructure source, JsonStructure target) {
+            return new JsonPatchDiff(source, target).calculateDiff();
+        }
+
         //X TODO add missing methods
 
     }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/2940f6e1/johnzon-core/src/test/java/org/apache/johnzon/core/JsonMergeBatchBuilderTest.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonMergeBatchBuilderTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonMergeBatchBuilderTest.java
index 141ed9d..b5be087 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonMergeBatchBuilderTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonMergeBatchBuilderTest.java
@@ -16,20 +16,20 @@
  */
 package org.apache.johnzon.core;
 
-import javax.json.spi.JsonProvider;
 
-public class JsonMergeBatchBuilderTest {
+import org.junit.Test;
 
-    private static final String[][] TEST_CASES = new String[][]{
-            {
-                "{\"a\":\"b\"}",
-                "{\"a\":\"c\"}",
-                "{\"a\":\"c\"}"
-            }
-    };
+public class JsonMergeBatchBuilderTest {
 
+    @Test
     public void testSimpleMergePatch() {
-        JsonProvider provider = JsonProvider.provider();
+        // {"a":"xa","b","xb"}
+        String source = "{\"a\":\"xa\",\"b\",\"xb\"}";
+
+        // {"b":"bNew","c":"xc"}
+        String patch = "{\"b\":\"bNew\",\"c\":\"xc\"}";
+
+        //X TODO Json.createMergePatch();
 
 
     }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/2940f6e1/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
new file mode 100644
index 0000000..3462a19
--- /dev/null
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchDiffTest.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.johnzon.core;
+
+import java.io.StringReader;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonPatch;
+import javax.json.JsonValue;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class JsonPatchDiffTest {
+
+    @Test
+    public void testAddDiff() {
+        // {"a":"xa"}
+        String jsonA = "{\"a\":\"xa\"}";
+
+        // {"a":"xa","b":"xb"}
+        String jsonB = "{\"a\":\"xa\",\"b\":\"xb\"}";
+
+        // this results in 1 diff operations:
+        // adding "b"
+        JsonPatch jsonPatch = Json.createDiff(Json.createReader(new StringReader(jsonA)).readObject(),
+                Json.createReader(new StringReader(jsonB)).readObject());
+        Assert.assertNotNull(jsonPatch);
+        JsonArray patchOperations = jsonPatch.toJsonArray();
+        Assert.assertNotNull(patchOperations);
+        Assert.assertEquals(1, patchOperations.size());
+        containsOperation(patchOperations, JsonPatch.Operation.ADD, "/b", "xb");
+    }
+
+    @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]}";
+
+        // {"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
+        JsonPatch jsonPatch = Json.createDiff(Json.createReader(new StringReader(jsonA)).readObject(),
+                Json.createReader(new StringReader(jsonB)).readObject());
+        Assert.assertNotNull(jsonPatch);
+        JsonArray patchOperations = jsonPatch.toJsonArray();
+        Assert.assertNotNull(patchOperations);
+        Assert.assertEquals(4, patchOperations.size());
+        containsOperation(patchOperations, JsonPatch.Operation.REMOVE, "/b", null);
+        containsOperation(patchOperations, JsonPatch.Operation.ADD, "/c/d2", "xd2");
+        containsOperation(patchOperations, JsonPatch.Operation.REMOVE, "/e/2", null);
+        containsOperation(patchOperations, JsonPatch.Operation.ADD, "/f", "xe");
+    }
+
+    private void containsOperation(JsonArray patchOperations, JsonPatch.Operation patchOperation,
+                                   String jsonPointer, String value) {
+        for (JsonValue operation : patchOperations) {
+            if (operation instanceof JsonObject &&
+                    patchOperation.operationName().equalsIgnoreCase(((JsonObject) operation).getString("op"))) {
+                Assert.assertEquals(jsonPointer, ((JsonObject) operation).getString("path"));
+
+                if (value != null) {
+                    Assert.assertEquals(value, ((JsonObject) operation).getString("value"));
+                }
+
+                return;
+            }
+        }
+        Assert.fail("patchOperations does not contain " + patchOperation + " " + jsonPointer);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/2940f6e1/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java
index dc54c0c..6c96329 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java
@@ -969,45 +969,6 @@ public class JsonPatchTest {
     }
 
 
-    //X @Test disabled for now
-    //X TODO implement the diff logic!
-    public void testDiff() {
-        // {"a":"xa","b":2,"c":{"d":"xd"},"e":[1,2,3]}
-        String jsonA = "{\"a\":\"xa\",\"b\":2,\"c\":{\"d\":\"xd\"},\"e\":[1,2,3]}";
-
-        // {"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
-        JsonPatch jsonPatch = Json.createDiff(Json.createReader(new StringReader(jsonA)).readObject(),
-                                              Json.createReader(new StringReader(jsonB)).readObject());
-        Assert.assertNotNull(jsonPatch);
-        JsonArray patchOperations = jsonPatch.toJsonArray();
-        Assert.assertNotNull(patchOperations);
-        Assert.assertEquals(4, patchOperations.size());
-        containsOperation(patchOperations, JsonPatch.Operation.REMOVE, "/b", null);
-        containsOperation(patchOperations, JsonPatch.Operation.ADD, "/c/d2", "xd2");
-        containsOperation(patchOperations, JsonPatch.Operation.REMOVE, "/e/2", null);
-        containsOperation(patchOperations, JsonPatch.Operation.ADD, "/f", "xe");
-    }
-
-    private void containsOperation(JsonArray patchOperations, JsonPatch.Operation patchOperation,
-                                   String jsonPointer, String value) {
-        for (JsonValue operation : patchOperations) {
-            if (operation instanceof JsonObject &&
-                patchOperation.operationName().equalsIgnoreCase(((JsonObject) operation).getString("op"))) {
-                Assert.assertEquals(jsonPointer, ((JsonObject) operation).getString("path"));
-
-                if (value != null) {
-                    Assert.assertEquals(value, ((JsonObject) operation).getString("value"));
-                }
-            }
-        }
-        Assert.fail("patchOperations does not contain " + patchOperation + " " + jsonPointer);
-    }
-
-
     private static String toJsonString(JsonStructure value) {
         StringWriter writer = new StringWriter();
         Json.createWriter(writer).write(value);