JOHNZON-97 implemented JsonPatch

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

Branch: refs/heads/JSONP-1.1
Commit: 74cb90884b51861361929cb6f5bcb32ca154a96c
Parents: 24fe453
Author: Reinhard Sandtner <[email protected]>
Authored: Thu Nov 24 00:11:42 2016 +0100
Committer: Reinhard Sandtner <[email protected]>
Committed: Fri Nov 25 14:35:56 2016 +0100

----------------------------------------------------------------------
 .../org/apache/johnzon/core/JsonPatchImpl.java  |  23 +
 .../org/apache/johnzon/core/JsonPatchTest.java  | 920 ++++++++++++++++++-
 2 files changed, 931 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/johnzon/blob/74cb9088/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java
----------------------------------------------------------------------
diff --git 
a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java 
b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java
index 352af88..0aaedf9 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPatchImpl.java
@@ -22,6 +22,7 @@ package org.apache.johnzon.core;
 import java.util.Arrays;
 import java.util.List;
 
+import javax.json.JsonException;
 import javax.json.JsonPatch;
 import javax.json.JsonPointer;
 import javax.json.JsonStructure;
@@ -42,12 +43,34 @@ class JsonPatchImpl implements JsonPatch {
 
         //X TODO JsonPointer should use generics like JsonPatch
         JsonStructure patched = target;
+
         for (PatchValue patch : patches) {
 
             switch (patch.operation) {
                 case ADD:
                     patched = patch.path.add(patched, patch.value);
                     break;
+                case REMOVE:
+                    patched = patch.path.remove(patched);
+                    break;
+                case REPLACE:
+                    // first remove the existing element and then add the new 
value
+                    patched = patch.path.add(patch.path.remove(patched), 
patch.value);
+                    break;
+                case MOVE:
+                    JsonValue valueToMove = patch.from.getValue(patched);
+                    patched = patch.path.add(patch.from.remove(patched), 
valueToMove);
+                    break;
+                case COPY:
+                    JsonValue toCopy = patch.from.getValue(patched);
+                    patched = patch.path.add(patched, toCopy);
+                    break;
+                case TEST:
+                    JsonValue toTest = patch.path.getValue(patched);
+                    if (!toTest.equals(patch.value)) {
+                        throw new JsonException("JsonPatchOperation.TEST 
fails! Values are not equal");
+                    }
+                    break;
                 default:
                     throw new IllegalStateException("unsupported operation: " 
+ patch.operation);
             }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/74cb9088/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 a303893..b4665ed 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
@@ -18,16 +18,22 @@
  */
 package org.apache.johnzon.core;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.io.StringReader;
-import java.io.StringWriter;
+import org.junit.Test;
 
 import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonException;
 import javax.json.JsonObject;
+import javax.json.JsonStructure;
+import javax.json.JsonValue;
+import java.io.StringReader;
+import java.io.StringWriter;
 
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
 
 public class JsonPatchTest {
 
@@ -37,21 +43,911 @@ public class JsonPatchTest {
         JsonObject object = Json.createReader(new StringReader("{ \"foo\": 
\"bar\" }"))
                                 .readObject();
 
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.ADD,
+                                                                             
Json.createJsonPointer("/baz"),
+                                                                             
null, // no from
+                                                                             
new JsonStringImpl("qux")));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertEquals("bar", patched.getString("foo"));
+        assertEquals("qux", patched.getString("baz"));
+
+        assertEquals("{\"foo\":\"bar\",\"baz\":\"qux\"}", 
toJsonString(patched));
+    }
+
+    @Test
+    public void testAddArrayElementWithIndex() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", Json.createArrayBuilder()
+                                                .add("bar")
+                                                .add("baz"))
+                                .build();
 
         JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.ADD,
-                                                                           
Json.createJsonPointer("/baz"),
-                                                                           
null, // no from
-                                                                           new 
JsonStringImpl("qux")));
+                                                                             
Json.createJsonPointer("/foo/1"),
+                                                                             
null, // no from
+                                                                             
new JsonStringImpl("qux")));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+
+        JsonArray array = patched.getJsonArray("foo");
+        assertNotNull(array);
+        assertEquals("bar", array.getString(0));
+        assertEquals("qux", array.getString(1));
+        assertEquals("baz", array.getString(2));
+
+        assertEquals("{\"foo\":[\"bar\",\"qux\",\"baz\"]}", 
toJsonString(patched));
+    }
+
+    @Test
+    public void testAddArrayElementAppend() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", Json.createArrayBuilder()
+                                                .add("bar")
+                                                .add("baz"))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.ADD,
+                                                                             
Json.createJsonPointer("/foo/-"),
+                                                                             
null, // no from
+                                                                             
new JsonStringImpl("qux")));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+
+        JsonArray array = patched.getJsonArray("foo");
+        assertNotNull(array);
+        assertEquals("bar", array.getString(0));
+        assertEquals("baz", array.getString(1));
+        assertEquals("qux", array.getString(2));
+
+        assertEquals("{\"foo\":[\"bar\",\"baz\",\"qux\"]}", 
toJsonString(patched));
+    }
+
+    @Test
+    public void testAddArrayElementPlainArray() {
+        JsonArray array = Json.createArrayBuilder()
+                              .add("bar")
+                              .add("baz")
+                              .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.ADD,
+                                                                             
Json.createJsonPointer("/-"),
+                                                                             
null, // no from
+                                                                             
new JsonStringImpl("qux")));
+
+        JsonArray patched = patch.apply(array);
+        assertNotNull(patched);
+        assertNotSame(array, patched);
+        assertEquals("bar", patched.getString(0));
+        assertEquals("baz", patched.getString(1));
+        assertEquals("qux", patched.getString(2));
+
+        assertEquals("[\"bar\",\"baz\",\"qux\"]", toJsonString(patched));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testAddNonexistentTarget() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", "bar")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.ADD,
+                                                                             
Json.createJsonPointer("/baz/bat"),
+                                                                             
null, // no from
+                                                                             
new JsonStringImpl("qux")));
+
+        patch.apply(object);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testAddArrayIndexOutOfBounds() {
+
+        JsonArray array = Json.createArrayBuilder()
+                              .add("bar")
+                              .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.ADD,
+                                                                             
Json.createJsonPointer("/5"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("baz")));
+
+        patch.apply(array);
+    }
+
+
+    @Test
+    public void testRemoveObjectMember() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("baz", "qux")
+                                .add("foo", "bar")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.REMOVE,
+                                                                             
Json.createJsonPointer("/baz"),
+                                                                             
null,
+                                                                             
null));
 
         JsonObject patched = patch.apply(object);
         assertNotNull(patched);
         assertEquals("bar", patched.getString("foo"));
+        assertFalse("patched JsonObject must no contain \"baz\"", 
patched.containsKey("baz"));
+
+        assertEquals("{\"foo\":\"bar\"}", toJsonString(patched));
+    }
+
+    @Test
+    public void testRemoveArrayElement() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", Json.createArrayBuilder()
+                                                .add("bar")
+                                                .add("qux")
+                                                .add("baz"))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.REMOVE,
+                                                                             
Json.createJsonPointer("/foo/1"),
+                                                                             
null,
+                                                                             
null));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+
+        JsonArray array = patched.getJsonArray("foo");
+        assertNotNull(array);
+        assertEquals(2, array.size());
+        assertEquals("bar", array.getString(0));
+        assertEquals("baz", array.getString(1));
+
+        assertEquals("{\"foo\":[\"bar\",\"baz\"]}", toJsonString(patched));
+    }
+
+    @Test
+    public void testRemoveArrayElementPlainArray() {
+
+        JsonArray array = Json.createArrayBuilder()
+                              .add("bar")
+                              .add("qux")
+                              .add("baz")
+                              .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.REMOVE,
+                                                                             
Json.createJsonPointer("/1"),
+                                                                             
null,
+                                                                             
null));
+
+        JsonArray patched = patch.apply(array);
+        assertNotNull(patched);
+        assertEquals(2, patched.size());
+        assertEquals("bar", patched.getString(0));
+        assertEquals("baz", patched.getString(1));
+
+        assertEquals("[\"bar\",\"baz\"]", toJsonString(patched));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testRemoveObjectElementNonexistentTarget() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", "bar")
+                                .add("baz", "qux")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.REMOVE,
+                                                                             
Json.createJsonPointer("/nomatch"),
+                                                                             
null,
+                                                                             
null));
+
+        patch.apply(object);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testRemoveArrayElementIndexOutOfBounds() {
+
+        JsonArray array = Json.createArrayBuilder()
+                              .add("bar")
+                              .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.REMOVE,
+                                                                             
Json.createJsonPointer("/5"),
+                                                                             
null,
+                                                                             
null));
+
+        patch.apply(array);
+    }
+
+
+    @Test
+    public void testReplacingObjectMember() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("baz", "qux")
+                                .add("foo", "bar")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.REPLACE,
+                                                                             
Json.createJsonPointer("/baz"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("boo")));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertNotSame(object, patched);
+        assertEquals("boo", patched.getString("baz"));
+        assertEquals("bar", patched.getString("foo"));
+
+        assertEquals("{\"foo\":\"bar\",\"baz\":\"boo\"}", 
toJsonString(patched));
+    }
+
+    @Test
+    public void testReplacingArrayElement() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", Json.createArrayBuilder()
+                                                .add("bar")
+                                                .add("qux"))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.REPLACE,
+                                                                             
Json.createJsonPointer("/foo/1"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("boo")));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertNotSame(object, patched);
+
+        JsonArray array = patched.getJsonArray("foo");
+        assertNotNull(array);
+        assertNotSame(object.getJsonArray("foo"), array);
+        assertEquals(2, array.size());
+        assertEquals("bar", array.getString(0));
+        assertEquals("boo", array.getString(1));
+
+        assertEquals("{\"foo\":[\"bar\",\"boo\"]}", toJsonString(patched));
+    }
+
+    @Test
+    public void testReplacingArrayElementPlainArray() {
+
+        JsonArray array = Json.createArrayBuilder()
+                              .add("bar")
+                              .add("qux")
+                              .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.REPLACE,
+                                                                             
Json.createJsonPointer("/0"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("boo")));
+
+        JsonArray patched = patch.apply(array);
+        assertNotNull(patched);
+        assertNotSame(array, patched);
+        assertEquals(2, patched.size());
+        assertEquals("boo", patched.getString(0));
+        assertEquals("qux", patched.getString(1));
+
+        assertEquals("[\"boo\",\"qux\"]", toJsonString(patched));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testReplacingObjectMemberNonexistingTarget() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", "bar")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.REPLACE,
+                                                                             
Json.createJsonPointer("/nomatch"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("notneeded")));
+
+        patch.apply(object);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testReplacingArrayElementIndexOutOfBounds() {
+
+        JsonArray array = Json.createArrayBuilder()
+                              .add("foo")
+                              .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.REPLACE,
+                                                                             
Json.createJsonPointer("/1"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("notneeded")));
+
+        patch.apply(array);
+    }
+
+
+    @Test
+    public void testMovingObjectMember() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", Json.createObjectBuilder()
+                                                .add("bar", "baz")
+                                                .add("waldo", "fred"))
+                                .add("qux", Json.createObjectBuilder()
+                                                .add("corge", "grault"))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.MOVE,
+                                                                             
Json.createJsonPointer("/qux/thud"),
+                                                                             
Json.createJsonPointer("/foo/waldo"),
+                                                                             
null));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertNotSame(object, patched);
+
+        JsonObject foo = patched.getJsonObject("foo");
+        assertNotNull(foo);
+        assertEquals("baz", foo.getString("bar"));
+        assertFalse("JsonObject with key 'foo' must not contain 'waldo'", 
foo.containsKey("waldo"));
+
+        JsonObject qux = patched.getJsonObject("qux");
+        assertNotNull(qux);
+        assertEquals("grault", qux.getString("corge"));
+        assertEquals("fred", qux.getString("thud"));
+
+        
assertEquals("{\"foo\":{\"bar\":\"baz\"},\"qux\":{\"corge\":\"grault\",\"thud\":\"fred\"}}",
 toJsonString(patched));
+    }
+
+    @Test
+    public void testMovingArrayElement() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", Json.createArrayBuilder()
+                                                .add("all")
+                                                .add("grass")
+                                                .add("cows")
+                                                .add("eat"))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.MOVE,
+                                                                             
Json.createJsonPointer("/foo/3"),
+                                                                             
Json.createJsonPointer("/foo/1"),
+                                                                             
null));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertNotSame(object, patched);
+
+        JsonArray array = patched.getJsonArray("foo");
+        assertNotNull(array);
+        assertEquals("all", array.getString(0));
+        assertEquals("cows", array.getString(1));
+        assertEquals("eat", array.getString(2));
+        assertEquals("grass", array.getString(3));
+
+        assertEquals("{\"foo\":[\"all\",\"cows\",\"eat\",\"grass\"]}", 
toJsonString(patched));
+    }
+
+    @Test
+    public void testMovingArrayElementPlainArray() {
+
+        JsonArray array = Json.createArrayBuilder()
+                              .add("two")
+                              .add("three")
+                              .add("four")
+                              .add("one")
+                              .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.MOVE,
+                                                                             
Json.createJsonPointer("/0"),
+                                                                             
Json.createJsonPointer("/3"),
+                                                                             
null));
+
+        JsonArray patched = patch.apply(array);
+        assertNotNull(patched);
+        assertNotSame(array, patched);
+        assertEquals("one", patched.getString(0));
+        assertEquals("two", patched.getString(1));
+        assertEquals("three", patched.getString(2));
+        assertEquals("four", patched.getString(3));
+    }
+
+    @Test
+    public void testMovingArrayElementToObjectMember() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", Json.createArrayBuilder()
+                                                .add("one")
+                                                .add("two")
+                                                .add("dog"))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.MOVE,
+                                                                             
Json.createJsonPointer("/bar"),
+                                                                             
Json.createJsonPointer("/foo/2"),
+                                                                             
null));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertEquals(2, patched.size());
+
+        JsonArray array = patched.getJsonArray("foo");
+        assertEquals(2, array.size());
+        assertEquals("one", array.getString(0));
+        assertEquals("two", array.getString(1));
+
+        assertEquals("dog", patched.getString("bar"));
+
+        assertEquals("{\"foo\":[\"one\",\"two\"],\"bar\":\"dog\"}", 
toJsonString(patched));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testMovingObjectMemberNonexistingFrom() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", "bar")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.MOVE,
+                                                                             
Json.createJsonPointer("/baz"),
+                                                                             
Json.createJsonPointer("/nomatch"),
+                                                                             
null));
+
+        patch.apply(object);
+
+    }
+
+    @Test(expected = JsonException.class)
+    public void testMovingObjectMemberNonexistingTarget() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", "bar")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.MOVE,
+                                                                             
Json.createJsonPointer("/nomatch/child"),
+                                                                             
Json.createJsonPointer("/foo"),
+                                                                             
null));
+
+        patch.apply(object);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testMovingObjectMemberMoveToSubFrom() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("object", Json.createObjectBuilder()
+                                                   .add("key", "value"))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.MOVE,
+                                                                             
Json.createJsonPointer("/object/key"),
+                                                                             
Json.createJsonPointer("/object"),
+                                                                             
null));
+
+        patch.apply(object);
+    }
+
+
+    @Test
+    public void testCopyObjectMember() {
+
+        JsonObject object = Json.createObjectBuilder()
+                               .add("foo", "bar")
+                               .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.COPY,
+                                                                             
Json.createJsonPointer("/baz"),
+                                                                             
Json.createJsonPointer("/foo"),
+                                                                             
null));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertEquals(2, patched.size());
+        assertEquals("bar", patched.getString("foo"));
+        assertEquals("bar", patched.getString("baz"));
+
+        assertEquals("{\"foo\":\"bar\",\"baz\":\"bar\"}", 
toJsonString(patched));
+    }
+
+    @Test
+    public void testCopyArrayMember() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", Json.createArrayBuilder()
+                                                .add("bar")
+                                                .add("baz"))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.COPY,
+                                                                               
  Json.createJsonPointer("/foo/-"),
+                                                                               
  Json.createJsonPointer("/foo/0"),
+                                                                               
  null));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+
+        JsonArray array = patched.getJsonArray("foo");
+        assertEquals(3, array.size());
+        assertEquals("bar", array.getString(0));
+        assertEquals("baz", array.getString(1));
+        assertEquals("bar", array.getString(2));
+
+        assertEquals("{\"foo\":[\"bar\",\"baz\",\"bar\"]}", 
toJsonString(patched));
+    }
+
+    @Test
+    public void testCopyArrayMemberPlainArray() {
+
+        JsonArray array = Json.createArrayBuilder()
+                              .add("foo")
+                              .add("bar")
+                              .build();
+
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.COPY,
+                                                                             
Json.createJsonPointer("/0"),
+                                                                             
Json.createJsonPointer("/1"),
+                                                                             
null));
+
+        JsonArray patched = patch.apply(array);
+        assertNotNull(patched);
+        assertNotSame(array, patched);
+        assertEquals(3, patched.size());
+        assertEquals("bar", patched.getString(0));
+        assertEquals("foo", patched.getString(1));
+        assertEquals("bar", patched.getString(2));
+
+        assertEquals("[\"bar\",\"foo\",\"bar\"]", toJsonString(patched));
+    }
+
+    @Test
+    public void testCopyObjectMemberToObjectMember() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("name", "Hugo")
+                                .add("partner", Json.createObjectBuilder()
+                                                    .add("name", "Leia")
+                                                    .add("partner", 
JsonValue.EMPTY_JSON_OBJECT))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.COPY,
+                                                                             
Json.createJsonPointer("/partner/partner/name"),
+                                                                             
Json.createJsonPointer("/name"),
+                                                                             
null));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertNotSame(object, patched);
+        assertEquals("Hugo", patched.getString("name"));
+
+        JsonObject partner = patched.getJsonObject("partner");
+        assertEquals("Leia", partner.getString("name"));
+
+        JsonObject parent = partner.getJsonObject("partner");
+        assertEquals(patched.getString("name"), parent.getString("name"));
+
+        
assertEquals("{\"name\":\"Hugo\",\"partner\":{\"name\":\"Leia\",\"partner\":{\"name\":\"Hugo\"}}}",
 toJsonString(patched));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testCopyObjectMemberFromNonexistentTarget() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", "bar")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.COPY,
+                                                                             
Json.createJsonPointer("/notneeded"),
+                                                                             
Json.createJsonPointer("/nomatch"),
+                                                                             
null));
+
+        patch.apply(object);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testCopyObjectMemberToNonexistingTarget() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", "bar")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.COPY,
+                                                                             
Json.createJsonPointer("/path/nomatch"),
+                                                                             
Json.createJsonPointer("/foo"),
+                                                                             
null));
+
+        patch.apply(object);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testCopyArrayMemberFromIndexOutOfBounds() {
+
+        JsonArray array = Json.createArrayBuilder()
+                              .add("foo")
+                              .add("bar")
+                              .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.COPY,
+                                                                             
Json.createJsonPointer("/-"),
+                                                                             
Json.createJsonPointer("/2"),
+                                                                             
null));
+
+        patch.apply(array);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testCopyArrayMemberToIndexOutOfBounds() {
+
+        JsonArray array = Json.createArrayBuilder()
+                              .add("foo")
+                              .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.COPY,
+                                                                             
Json.createJsonPointer("/1"),
+                                                                             
Json.createJsonPointer("/-"),
+                                                                             
null));
+
+        patch.apply(array);
+    }
+
+
+    @Test
+    public void testTestingObjectMemberValueSuccess() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", "qux")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.TEST,
+                                                                             
Json.createJsonPointer("/foo"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("qux")));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertSame(object, patched);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testTestingObjectMemberValueFailed() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", "qux")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.TEST,
+                                                                             
Json.createJsonPointer("/foo"),
+                                                                             
null,
+                                                                             
Json.createArrayBuilder().build()));
+
+        patch.apply(object);
+    }
+
+    @Test
+    public void testTestingArrayAsObjectMemberSuccess() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("name", "Thor")
+                                .add("parents", Json.createArrayBuilder()
+                                                    .add("Odin")
+                                                    .add("Forjgyn"))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.TEST,
+                                                                             
Json.createJsonPointer("/parents"),
+                                                                             
null,
+                                                                             
Json.createArrayBuilder() // yessss, we really want to create a new JsonArray ;)
+                                                                               
  .add("Odin")
+                                                                               
  .add("Forjgyn")
+                                                                               
  .build()));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertSame(object, patched);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testTestingArrayAsObjectMemberFailed() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("magic", "array")
+                                .add("numbers", Json.createArrayBuilder()
+                                                    .add(1)
+                                                    .add(2))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.TEST,
+                                                                             
Json.createJsonPointer("/numbers"),
+                                                                             
null,
+                                                                             
Json.createArrayBuilder() // different ordering
+                                                                               
  .add(2)
+                                                                               
  .add(1)
+                                                                               
  .build()));
+
+        patch.apply(object);
+    }
+
+    @Test
+    public void testTestingArrayElementSuccess() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", Json.createArrayBuilder()
+                                                .add("bar")
+                                                .add("baz"))
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.TEST,
+                                                                             
Json.createJsonPointer("/foo/1"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("baz")));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertSame(object, patched);
+    }
+
+    @Test
+    public void testTestingArrayElementPlainArraySuccess() {
+
+        JsonArray array = Json.createArrayBuilder()
+                              .add("foo")
+                              .add("bar")
+                              .add("qux")
+                              .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.TEST,
+                                                                             
Json.createJsonPointer("/2"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("qux")));
+
+        JsonArray patched = patch.apply(array);
+        assertNotNull(patched);
+        assertSame(array, patched);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testTestingArrayElementPlainArrayFailed() {
+
+        JsonArray array = Json.createArrayBuilder()
+                              .add(1)
+                              .add("2")
+                              .add("qux")
+                              .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.TEST,
+                                                                             
Json.createJsonPointer("/0"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("bar")));
+
+        patch.apply(array);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testTestingObjectMemeberNonexistentTarget() {
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.TEST,
+                                                                             
Json.createJsonPointer("/nomatch"),
+                                                                             
null,
+                                                                             
JsonValue.EMPTY_JSON_OBJECT));
+
+        patch.apply(JsonValue.EMPTY_JSON_OBJECT);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testTestingArrayElementIndexOutOfBounds() {
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.TEST,
+                                                                             
Json.createJsonPointer("/3"),
+                                                                             
null,
+                                                                             
JsonValue.EMPTY_JSON_OBJECT));
+
+        patch.apply(JsonValue.EMPTY_JSON_ARRAY);
+    }
+
+
+    @Test
+    public void testAddObjectMemberAlreadyExists() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("foo", "bar")
+                                .add("baz", "qux")
+                                .build();
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.ADD,
+                                                                             
Json.createJsonPointer("/foo"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("abcd")));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertNotSame(object, patched);
+        assertEquals("abcd", patched.getString("foo"));
         assertEquals("qux", patched.getString("baz"));
 
-        StringWriter writer = new StringWriter();
-        Json.createWriter(writer).write(patched);
+        assertEquals("{\"foo\":\"abcd\",\"baz\":\"qux\"}", 
toJsonString(patched));
+    }
 
-        assertEquals("{\"foo\":\"bar\",\"baz\":\"qux\"}", writer.toString());
+    @Test
+    public void testAddArrayElementToEmptyArray() {
+
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.ADD,
+                                                                             
Json.createJsonPointer("/-"),
+                                                                             
null,
+                                                                             
new JsonStringImpl("foo")));
+
+        JsonArray patched = patch.apply(JsonValue.EMPTY_JSON_ARRAY);
+        assertNotNull(patched);
+        assertEquals(1, patched.size());
+        assertEquals("foo", patched.getString(0));
+    }
+
+    @Test
+    public void testPatchWithMoreOperations() {
+
+        JsonObject object = Json.createObjectBuilder()
+                                .add("family", Json.createObjectBuilder()
+                                                   .add("children", 
JsonValue.EMPTY_JSON_ARRAY))
+                                .build();
+
+        // i know this can be done with PatchBuilder but
+        // currently it's not implemented and its fun ;)
+        JsonPatchImpl patch = new JsonPatchImpl(new 
JsonPatchImpl.PatchValue(JsonPatchOperation.ADD,
+                                                                             
Json.createJsonPointer("/family/father"),
+                                                                             
null,
+                                                                             
Json.createObjectBuilder()
+                                                                               
  .add("name", "Gaio Modry Effect")
+                                                                               
  .build()),
+                                                new 
JsonPatchImpl.PatchValue(JsonPatchOperation.ADD,
+                                                                             
Json.createJsonPointer("/family/mother"),
+                                                                             
null,
+                                                                             
Json.createObjectBuilder()
+                                                                               
  .add("name", "Cassius vom Hause Clarabella")
+                                                                               
  .build()),
+                                                new 
JsonPatchImpl.PatchValue(JsonPatchOperation.MOVE,
+                                                                             
Json.createJsonPointer("/family/children/0"),
+                                                                             
Json.createJsonPointer("/family/mother"),
+                                                                             
null),
+                                                new 
JsonPatchImpl.PatchValue(JsonPatchOperation.ADD,
+                                                                             
Json.createJsonPointer("/family/mother"),
+                                                                             
null,
+                                                                             
Json.createObjectBuilder()
+                                                                               
  .add("name", "Aimee vom Hause Clarabella")
+                                                                               
  .build()),
+                                                new 
JsonPatchImpl.PatchValue(JsonPatchOperation.COPY,
+                                                                             
Json.createJsonPointer("/pedigree"),
+                                                                             
Json.createJsonPointer("/family"),
+                                                                             
null),
+                                                new 
JsonPatchImpl.PatchValue(JsonPatchOperation.REMOVE,
+                                                                             
Json.createJsonPointer("/family"),
+                                                                             
null,
+                                                                             
null));
+
+        JsonObject patched = patch.apply(object);
+        assertNotNull(patched);
+        assertNotSame(object, patched);
+
+        JsonObject pedigree = patched.getJsonObject("pedigree");
+        assertEquals("Gaio Modry Effect", 
pedigree.getJsonObject("father").getString("name"));
+        assertEquals("Aimee vom Hause Clarabella", 
pedigree.getJsonObject("mother").getString("name"));
+        assertEquals("Cassius vom Hause Clarabella", 
pedigree.getJsonArray("children").getJsonObject(0).getString("name"));
+
+        assertEquals("{\"pedigree\":{" +
+                     "\"children\":[" +
+                     "{\"name\":\"Cassius vom Hause Clarabella\"}]," +
+                     "\"mother\":{\"name\":\"Aimee vom Hause Clarabella\"}," +
+                     "\"father\":{\"name\":\"Gaio Modry Effect\"}}}", 
toJsonString(patched));
+    }
+
+
+
+    private static String toJsonString(JsonStructure value) {
+        StringWriter writer = new StringWriter();
+        Json.createWriter(writer).write(value);
+        return writer.toString();
     }
 
 }

Reply via email to