Implemented JsonPointer add, replace and remove methods

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

Branch: refs/heads/JSONP-1.1
Commit: cc830c64a4e6a175a02d13ad2ccf5140401530df
Parents: 45faea0
Author: Armin Hasler <[email protected]>
Authored: Mon Nov 14 10:09:22 2016 +0100
Committer: Mark Struberg <[email protected]>
Committed: Tue Nov 22 21:28:49 2016 +0100

----------------------------------------------------------------------
 .../org/apache/johnzon/core/JsonPointer.java    | 310 ++++++++++----
 .../apache/johnzon/core/JsonPointerTest.java    | 419 ++++++++++++++++++-
 2 files changed, 647 insertions(+), 82 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/johnzon/blob/cc830c64/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointer.java
----------------------------------------------------------------------
diff --git 
a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointer.java 
b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointer.java
index af228be..ca942ef 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointer.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointer.java
@@ -18,11 +18,17 @@
  */
 package org.apache.johnzon.core;
 
+import javax.json.Json;
 import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
 import javax.json.JsonException;
 import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
 import javax.json.JsonStructure;
 import javax.json.JsonValue;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * <p>This class is an immutable representation of a JSON Pointer as specified 
in
@@ -49,7 +55,8 @@ import javax.json.JsonValue;
 public class JsonPointer {
 
     private final String jsonPointer;
-    private final String[] referenceTokens;
+    private final List<String> referenceTokens = new ArrayList<String>();
+    private final String lastReferenceToken;
 
     /**
      * Constructs and initializes a JsonPointer.
@@ -63,11 +70,16 @@ public class JsonPointer {
             throw new NullPointerException("jsonPointer must not be null");
         }
         if (!jsonPointer.equals("") && !jsonPointer.startsWith("/")) {
-            throw new JsonException("A non-empty JSON pointer must begin with 
a '/'");
+            throw new JsonException("A non-empty JsonPointer string must begin 
with a '/'");
         }
 
         this.jsonPointer = jsonPointer;
-        referenceTokens = jsonPointer.split("/", -1);
+        String[] encodedReferenceTokens = jsonPointer.split("/", -1);
+
+        for (String encodedReferenceToken : encodedReferenceTokens) {
+            referenceTokens.add(JsonPointerUtil.decode(encodedReferenceToken));
+        }
+        lastReferenceToken = referenceTokens.get(referenceTokens.size() - 1);
     }
 
     /**
@@ -113,43 +125,14 @@ public class JsonPointer {
         if (target == null) {
             throw new NullPointerException("target must not be null");
         }
-
-        if (jsonPointer.equals("")) {
+        if (isEmptyJsonPointer()) {
             return target;
         }
 
         JsonValue jsonValue = target;
-
-        for (int i = 1; i < referenceTokens.length; i++) {
-            String decodedReferenceToken = 
JsonPointerUtil.decode(referenceTokens[i]);
-
-            if (jsonValue instanceof JsonObject) {
-                JsonObject jsonObject = (JsonObject) jsonValue;
-                jsonValue = jsonObject.get(decodedReferenceToken);
-
-                if (jsonValue == null) {
-                    throw new JsonException("The JsonObject " + jsonObject + " 
contains no value for token " + decodedReferenceToken);
-                }
-            } else if (jsonValue instanceof JsonArray) {
-                JsonArray jsonArray = (JsonArray) jsonValue;
-
-                try {
-                    int index = Integer.parseInt(decodedReferenceToken);
-                    if (index >= jsonArray.size()) {
-                        throw new JsonException("The JsonArray " + jsonArray + 
" contains no element for index " + index);
-                    }
-                    if (decodedReferenceToken.startsWith("0") && 
decodedReferenceToken.length() > 1) {
-                        throw new JsonException("The token " + 
decodedReferenceToken + " with leading zeros is not allowed to reference an 
element of a JsonArray");
-                    }
-
-                    jsonValue = jsonArray.get(index);
-                } catch (NumberFormatException e) {
-                    throw new JsonException("The token " + 
decodedReferenceToken + " for the JsonArray " + jsonArray + " is not a number", 
e);
-                }
-            }
-
+        for (int i = 1; i < referenceTokens.size(); i++) {
+            jsonValue = getValue(jsonValue, referenceTokens.get(i), i, 
referenceTokens.size() - 1);
         }
-
         return jsonValue;
     }
 
@@ -179,35 +162,19 @@ public class JsonPointer {
      *                              or if the pointer contains references to 
non-existing objects or arrays.
      */
     public JsonStructure add(JsonStructure target, JsonValue value) {
-        return null;
-    }
-
-    /**
-     * Replaces the value at the referenced location in the specified
-     * {@code target} with the specified {@code value}.
-     *
-     * @param target the target referenced by this {@code JsonPointer}
-     * @param value  the value to be stored at the referenced location
-     * @return the transformed {@code target} after the value is replaced.
-     * @throws NullPointerException if {@code target} is {@code null}
-     * @throws JsonException        if the referenced value does not exist,
-     *                              or if the reference is the target.
-     */
-    public JsonStructure replace(JsonStructure target, JsonValue value) {
-        return null;
-    }
+        validateAdd(target);
+        if (isEmptyJsonPointer()) {
+            if (value.getClass() != target.getClass()) {
+                throw new JsonException("The value must have the same type as 
the target");
+            }
+            return (JsonStructure) value;
+        }
 
-    /**
-     * Removes the value at the reference location in the specified {@code 
target}
-     *
-     * @param target the target referenced by this {@code JsonPointer}
-     * @return the transformed {@code target} after the value is removed.
-     * @throws NullPointerException if {@code target} is {@code null}
-     * @throws JsonException        if the referenced value does not exist,
-     *                              or if the reference is the target.
-     */
-    public JsonStructure remove(JsonStructure target) {
-        return null;
+        if (target instanceof JsonObject) {
+            return add((JsonObject) target, value);
+        } else {
+            return add((JsonArray) target, value);
+        }
     }
 
     /**
@@ -224,7 +191,9 @@ public class JsonPointer {
      * @see #add(JsonStructure, JsonValue)
      */
     public JsonObject add(JsonObject target, JsonValue value) {
-        return (JsonObject) this.add((JsonStructure) target, value);
+        validateAdd(target);
+
+        return (JsonObject) add(target, 1, referenceTokens.size() - 1, value);
     }
 
     /**
@@ -241,7 +210,28 @@ public class JsonPointer {
      * @see #add(JsonStructure, JsonValue)
      */
     public JsonArray add(JsonArray target, JsonValue value) {
-        return (JsonArray) this.add((JsonStructure) target, value);
+        validateAdd(target);
+
+        return (JsonArray) add(target, 1, referenceTokens.size() - 1, value);
+    }
+
+    /**
+     * Replaces the value at the referenced location in the specified
+     * {@code target} with the specified {@code value}.
+     *
+     * @param target the target referenced by this {@code JsonPointer}
+     * @param value  the value to be stored at the referenced location
+     * @return the transformed {@code target} after the value is replaced.
+     * @throws NullPointerException if {@code target} is {@code null}
+     * @throws JsonException        if the referenced value does not exist,
+     *                              or if the reference is the target.
+     */
+    public JsonStructure replace(JsonStructure target, JsonValue value) {
+        if (target instanceof JsonObject) {
+            return replace((JsonObject) target, value);
+        } else {
+            return replace((JsonArray) target, value);
+        }
     }
 
     /**
@@ -253,11 +243,10 @@ public class JsonPointer {
      * @throws NullPointerException if {@code target} is {@code null}
      * @throws JsonException        if the referenced value does not exist,
      *                              or if the reference is the target.
-     *                              {@code target} with the specified {@code 
value}.
      * @see #replace(JsonStructure, JsonValue)
      */
     public JsonObject replace(JsonObject target, JsonValue value) {
-        return (JsonObject) this.replace((JsonStructure) target, value);
+        return add(remove(target), value);
     }
 
     /**
@@ -269,11 +258,27 @@ public class JsonPointer {
      * @throws NullPointerException if {@code target} is {@code null}
      * @throws JsonException        if the referenced value does not exist,
      *                              or if the reference is the target.
-     *                              {@code target} with the specified {@code 
value}.
      * @see #replace(JsonStructure, JsonValue)
      */
     public JsonArray replace(JsonArray target, JsonValue value) {
-        return (JsonArray) this.replace((JsonStructure) target, value);
+        return add(remove(target), value);
+    }
+
+    /**
+     * Removes the value at the reference location in the specified {@code 
target}
+     *
+     * @param target the target referenced by this {@code JsonPointer}
+     * @return the transformed {@code target} after the value is removed.
+     * @throws NullPointerException if {@code target} is {@code null}
+     * @throws JsonException        if the referenced value does not exist,
+     *                              or if the reference is the target.
+     */
+    public JsonStructure remove(JsonStructure target) {
+        if (target instanceof JsonObject) {
+            return remove((JsonObject) target);
+        } else {
+            return remove((JsonArray) target);
+        }
     }
 
     /**
@@ -287,7 +292,9 @@ public class JsonPointer {
      * @see #remove(JsonStructure)
      */
     public JsonObject remove(JsonObject target) {
-        return (JsonObject) this.remove((JsonStructure) target);
+        validateRemove(target);
+
+        return (JsonObject) remove(target, 1, referenceTokens.size() - 1);
     }
 
     /**
@@ -301,8 +308,169 @@ public class JsonPointer {
      * @see #remove(JsonStructure)
      */
     public JsonArray remove(JsonArray target) {
-        return (JsonArray) this.remove((JsonStructure) target);
+        validateRemove(target);
+
+        return (JsonArray) remove(target, 1, referenceTokens.size() - 1);
+    }
+
+    private void validateAdd(JsonValue target) {
+        validateJsonPointer(target, referenceTokens.size() - 1);
     }
 
+    private void validateRemove(JsonValue target) {
+        validateJsonPointer(target, referenceTokens.size());
+        if (isEmptyJsonPointer()) {
+            throw new JsonException("The reference must not be the target");
+        }
+    }
+
+    private boolean isEmptyJsonPointer() {
+        return jsonPointer.equals("");
+    }
+
+    private JsonValue getValue(JsonValue jsonValue, String referenceToken, int 
currentPosition, int referencePosition) {
+        if (jsonValue instanceof JsonObject) {
+            JsonObject jsonObject = (JsonObject) jsonValue;
+            jsonValue = jsonObject.get(referenceToken);
+
+            if (jsonValue != null) {
+                return jsonValue;
+            }
+            throw new JsonException("'" + jsonObject + "' contains no value 
for name '" + referenceToken + "'");
+        } else if (jsonValue instanceof JsonArray) {
+            validateArrayIndex(referenceToken);
+
+            try {
+                JsonArray jsonArray = (JsonArray) jsonValue;
+                int arrayIndex = Integer.parseInt(referenceToken);
+                validateArraySize(jsonArray, arrayIndex, jsonArray.size());
+                return jsonArray.get(arrayIndex);
+            } catch (NumberFormatException e) {
+                throw new JsonException("'" + referenceToken + "' is no valid 
array index", e);
+            }
+        } else {
+            if (currentPosition != referencePosition) {
+                return jsonValue;
+            }
+            throw new JsonException("'" + jsonValue + "' contains no element 
for '" + referenceToken + "'");
+        }
+    }
+
+    private JsonValue add(JsonValue jsonValue, int currentPosition, int 
referencePosition, JsonValue newValue) {
+        if (jsonValue instanceof JsonObject) {
+            JsonObject jsonObject = (JsonObject) jsonValue;
+            JsonObjectBuilder objectBuilder = Json.createObjectBuilder();
+
+            if (jsonObject.isEmpty()) {
+                objectBuilder.add(lastReferenceToken, newValue);
+            } else {
+                for (Map.Entry<String, JsonValue> entry : 
jsonObject.entrySet()) {
+                    objectBuilder.add(entry.getKey(), add(entry.getValue(), 
currentPosition + 1, referencePosition, newValue));
+                    if (currentPosition == referencePosition) {
+                        objectBuilder.add(lastReferenceToken, newValue);
+                    }
+                }
+            }
+            return objectBuilder.build();
+        } else if (jsonValue instanceof JsonArray) {
+            JsonArray jsonArray = (JsonArray) jsonValue;
+            JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+
+            int arrayIndex = -1;
+            if (currentPosition == referencePosition) {
+                arrayIndex = getArrayIndex(lastReferenceToken, jsonArray, 
true);
+            }
+
+            int jsonArraySize = jsonArray.size();
+            for (int i = 0; i <= jsonArraySize; i++) {
+                if (i == arrayIndex) {
+                    arrayBuilder.add(newValue);
+                }
+                if (i == jsonArraySize) {
+                    break;
+                }
+                arrayBuilder.add(add(jsonArray.get(i), currentPosition + 1, 
referencePosition, newValue));
+            }
+            return arrayBuilder.build();
+        }
+        return jsonValue;
+    }
+
+    private JsonValue remove(JsonValue jsonValue, int currentPosition, int 
referencePosition) {
+        if (jsonValue instanceof JsonObject) {
+            JsonObject jsonObject = (JsonObject) jsonValue;
+            JsonObjectBuilder objectBuilder = Json.createObjectBuilder();
+
+            for (Map.Entry<String, JsonValue> entry : jsonObject.entrySet()) {
+                if (currentPosition == referencePosition
+                        && lastReferenceToken.equals(entry.getKey())) {
+                    continue;
+                }
+                objectBuilder.add(entry.getKey(), remove(entry.getValue(), 
currentPosition + 1, referencePosition));
+            }
+            return objectBuilder.build();
+        } else if (jsonValue instanceof JsonArray) {
+            JsonArray jsonArray = (JsonArray) jsonValue;
+            JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+
+            int arrayIndex = -1;
+            if (currentPosition == referencePosition) {
+                arrayIndex = getArrayIndex(lastReferenceToken, jsonArray, 
false);
+            }
+
+            int jsonArraySize = jsonArray.size();
+            for (int i = 0; i < jsonArraySize; i++) {
+                if (i == arrayIndex) {
+                    continue;
+                }
+                arrayBuilder.add(remove(jsonArray.get(i), currentPosition + 1, 
referencePosition));
+            }
+            return arrayBuilder.build();
+        }
+        return jsonValue;
+    }
+
+    private int getArrayIndex(String referenceToken, JsonArray jsonArray, 
boolean addOperation) {
+        if (addOperation && referenceToken.equals("-")) {
+            return jsonArray.size();
+        }
+
+        validateArrayIndex(referenceToken);
+
+        try {
+            int arrayIndex = Integer.parseInt(referenceToken);
+            int arraySize = addOperation ? jsonArray.size() + 1 : 
jsonArray.size();
+            validateArraySize(jsonArray, arrayIndex, arraySize);
+            return arrayIndex;
+        } catch (NumberFormatException e) {
+            throw new JsonException("'" + referenceToken + "' is no valid 
array index", e);
+        }
+    }
+
+    private void validateJsonPointer(JsonValue target, int size) throws 
NullPointerException, JsonException {
+        if (target == null) {
+            throw new NullPointerException("target must not be null");
+        }
+
+        JsonValue jsonValue = target;
+        for (int i = 1; i < size; i++) {
+            jsonValue = getValue(jsonValue, referenceTokens.get(i), i, 
referenceTokens.size() - 1);
+        }
+    }
+
+    private void validateArrayIndex(String referenceToken) throws 
JsonException {
+        if (referenceToken.startsWith("+") || referenceToken.startsWith("-")) {
+            throw new JsonException("An array index must not start with '" + 
referenceToken.charAt(0) + "'");
+        }
+        if (referenceToken.startsWith("0") && referenceToken.length() > 1) {
+            throw new JsonException("An array index must not start with a 
leading '0'");
+        }
+    }
+
+    private void validateArraySize(JsonArray jsonArray, int arrayIndex, int 
arraySize) throws JsonException {
+        if (arrayIndex >= arraySize) {
+            throw new JsonException("'" + jsonArray + "' contains no element 
for index " + arrayIndex);
+        }
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/cc830c64/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java 
b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java
index 7750ba6..9b6c722 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java
@@ -21,34 +21,38 @@ package org.apache.johnzon.core;
 import org.junit.Test;
 
 import javax.json.Json;
+import javax.json.JsonArray;
 import javax.json.JsonException;
+import javax.json.JsonObject;
 import javax.json.JsonReader;
 import javax.json.JsonStructure;
 import javax.json.JsonValue;
 import java.util.Collections;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 public class JsonPointerTest {
 
     @Test(expected = NullPointerException.class)
-    public void testConstructorWithNullShouldThrowNullPointerException() {
+    public void testConstructorWithJsonPointerNull() {
         new JsonPointer(null);
     }
 
     @Test(expected = JsonException.class)
-    public void 
testConstructorWithInvalidJsonPointerShouldThrowJsonException() {
+    public void testConstructorWithInvalidJsonPointer() {
         new JsonPointer("a");
     }
 
     @Test(expected = NullPointerException.class)
-    public void testGetValueWithNullShouldThrowNullPointerException() {
+    public void testGetValueWithTargetNull() {
         JsonPointer jsonPointer = new JsonPointer("");
         jsonPointer.getValue(null);
     }
 
     @Test
-    public void testGetValueWholeDocument() {
+    public void testGetValueWithWholeDocument() {
         JsonStructure jsonDocument = getJsonDocument();
 
         JsonPointer jsonPointer = new JsonPointer("");
@@ -138,7 +142,7 @@ public class JsonPointerTest {
     }
 
     @Test(expected = JsonException.class)
-    public void testGetValueElementNotExistentShouldThrowJsonException() {
+    public void testGetValueWithElementNotExistent() {
         JsonStructure jsonDocument = getJsonDocument();
 
         JsonPointer jsonPointer = new JsonPointer("/fool");
@@ -146,7 +150,7 @@ public class JsonPointerTest {
     }
 
     @Test
-    public void testGetValueWholeJsonArray() {
+    public void testGetValueWithWholeJsonArray() {
         JsonStructure jsonDocument = getJsonDocument();
 
         JsonPointer jsonPointer = new JsonPointer("/foo");
@@ -155,7 +159,7 @@ public class JsonPointerTest {
     }
 
     @Test
-    public void testGetValueJsonArrayElement() {
+    public void testGetValueWithJsonArray() {
         JsonStructure jsonDocument = getJsonDocument();
 
         JsonPointer jsonPointer = new JsonPointer("/foo/0");
@@ -164,7 +168,7 @@ public class JsonPointerTest {
     }
 
     @Test(expected = JsonException.class)
-    public void 
testGetValueJsonArrayElementNotExistentShouldThrowJsonException() {
+    public void testGetValueWithJsonArrayIndexOutOfRange() {
         JsonStructure jsonDocument = getJsonDocument();
 
         JsonPointer jsonPointer = new JsonPointer("/foo/2");
@@ -172,7 +176,7 @@ public class JsonPointerTest {
     }
 
     @Test(expected = JsonException.class)
-    public void testGetValueJsonArrayElementNoNumberShouldThrowJsonException() 
{
+    public void testGetValueWithJsonArrayIndexNoNumber() {
         JsonStructure jsonDocument = getJsonDocument();
 
         JsonPointer jsonPointer = new JsonPointer("/foo/a");
@@ -180,14 +184,407 @@ public class JsonPointerTest {
     }
 
     @Test(expected = JsonException.class)
-    public void 
testGetValueJsonArrayElementLeadingZeroShouldThrowJsonException() {
+    public void testGetValueWithJsonArrayLeadingZeroIndex() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/foo/001");
+        JsonPointer jsonPointer = new JsonPointer("/foo/01");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("\"bar\"", result.toString());
     }
 
+    @Test(expected = JsonException.class)
+    public void testGetValueWithJsonArrayInvalidIndex() {
+        JsonStructure jsonDocument = getJsonDocument();
+
+        JsonPointer jsonPointer = new JsonPointer("/foo/-1");
+        jsonPointer.getValue(jsonDocument);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testAddJsonStructureWithTargetNull() {
+        JsonPointer jsonPointer = new JsonPointer("");
+        jsonPointer.add((JsonStructure) null, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testAddJsonStructureWithTypeValueNotTypeTarget() {
+        JsonPointer jsonPointer = new JsonPointer("");
+        JsonObject target = Json.createObjectBuilder().build();
+        JsonArray value = Json.createArrayBuilder().build();
+
+        jsonPointer.add((JsonStructure) target, value);
+    }
+
+    @Test
+    public void testAddJsonStructureWithEmptyJsonPointer() {
+        JsonPointer jsonPointer = new JsonPointer("");
+        JsonStructure target = Json.createObjectBuilder().build();
+        JsonObject value = Json.createObjectBuilder()
+                .add("foo", "bar").build(); // { "foo": "bar" }
+
+        JsonStructure result = jsonPointer.add(target, value);
+        assertEquals("{\"foo\":\"bar\"}", result.toString());
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testAddJsonObjectWithTargetNull() {
+        JsonPointer jsonPointer = new JsonPointer("");
+        jsonPointer.add((JsonObject) null, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testAddJsonArrayWithTargetNull() {
+        JsonPointer jsonPointer = new JsonPointer("");
+        jsonPointer.add((JsonArray) null, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testAddArrayElementWithInvalidIndex() {
+        JsonPointer jsonPointer = new JsonPointer("/+");
+        JsonStructure target = Json.createArrayBuilder().build();
+
+        jsonPointer.add(target, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testAddArrayElementWithIndexOutOfRange() {
+        JsonPointer jsonPointer = new JsonPointer("/1");
+        JsonStructure target = Json.createArrayBuilder().build();
+
+        jsonPointer.add(target, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testAddArrayElementWithLeadingZeroIndex() {
+        JsonPointer jsonPointer = new JsonPointer("/01");
+        JsonStructure target = Json.createArrayBuilder()
+                .add("foo").build();
+
+        jsonPointer.add(target, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testAddArrayElementWithIndexNoNumber() {
+        JsonPointer jsonPointer = new JsonPointer("/a");
+        JsonStructure target = Json.createArrayBuilder()
+                .add("foo").build();
+
+        jsonPointer.add(target, new JsonStringImpl("qux"));
+    }
+
+    @Test
+    public void testAddObject() {
+        JsonPointer jsonPointer = new JsonPointer("/child");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("foo", "bar").build(); // {"foo":"bar"}
+        JsonObject value = Json.createObjectBuilder()
+                .add("grandchild", Json.createObjectBuilder()).build(); // 
{"grandchild":{}}
+
+        JsonStructure result = jsonPointer.add(target, value);
+        assertEquals("{\"foo\":\"bar\",\"child\":{\"grandchild\":{}}}", 
result.toString()); // {"foo":"bar","child":{"grandchild":{}}}
+    }
+
+    @Test
+    public void testAddObjectMember() {
+        JsonPointer jsonPointer = new JsonPointer("/baz");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("foo", "bar").build(); // {"foo":"bar"}
+
+        JsonStructure result = jsonPointer.add(target, new 
JsonStringImpl("qux"));
+        assertEquals("{\"foo\":\"bar\",\"baz\":\"qux\"}", result.toString()); 
// {"foo":"bar","baz":"qux"}
+    }
+
+    @Test
+    public void testAddFirstObjectMember() {
+        JsonPointer jsonPointer = new JsonPointer("/foo");
+        JsonStructure target = Json.createObjectBuilder().build(); // {}
+
+        JsonStructure result = jsonPointer.add(target, new 
JsonStringImpl("bar"));
+        assertEquals("{\"foo\":\"bar\"}", result.toString()); // {"foo":"bar"}
+    }
+
+    @Test(expected = JsonException.class)
+    public void testAddObjectMemberWithNonexistentTarget() {
+        JsonPointer jsonPointer = new JsonPointer("/baz/bat");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("foo", "bar").build(); // {"foo":"bar"}
+
+        jsonPointer.add(target, new JsonStringImpl("qux"));
+    }
+
+    @Test
+    public void testAddReplaceObjectMember() {
+        JsonPointer jsonPointer = new JsonPointer("/baz");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("baz", "qux")
+                .add("foo", "bar").build(); // {"baz":"qux","foo":"bar"}
+
+        JsonStructure result = jsonPointer.add(target, new 
JsonStringImpl("boo"));
+        assertEquals("{\"baz\":\"boo\",\"foo\":\"bar\"}", result.toString()); 
// {"baz":"boo","foo":"bar"}
+    }
+
+    @Test
+    public void testAddArray() {
+        JsonPointer jsonPointer = new JsonPointer("/0/-");
+        JsonStructure target = Json.createArrayBuilder()
+                .add(Json.createArrayBuilder()
+                        .add("bar")).build(); // [["bar"]]
+        JsonArray value = Json.createArrayBuilder()
+                .add("abc")
+                .add("def").build();// ["abc","def"]
+
+        JsonStructure result = jsonPointer.add(target, value);
+        assertEquals("[[\"bar\",[\"abc\",\"def\"]]]", result.toString()); // 
[["bar",["abc","def"]]]
+    }
+
+    @Test
+    public void testAddArrayElement() {
+        JsonPointer jsonPointer = new JsonPointer("/foo/1");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("foo", Json.createArrayBuilder()
+                        .add("bar")
+                        .add("baz")).build(); // {"foo":["bar","baz"]}
+
+        JsonStructure result = jsonPointer.add(target, new 
JsonStringImpl("qux"));
+        assertEquals("{\"foo\":[\"bar\",\"qux\",\"baz\"]}", 
result.toString()); // {"foo":["bar","qux","baz"]}
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testRemoveJsonObjectWithTargetNull() {
+        JsonPointer jsonPointer = new JsonPointer("/");
+        jsonPointer.remove((JsonObject) null);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testRemoveJsonObjectWithEmptyJsonPointer() {
+        JsonPointer jsonPointer = new JsonPointer("");
+        JsonObject target = Json.createObjectBuilder().build();
+
+        jsonPointer.remove(target);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testRemoveJsonArrayWithTargetNull() {
+        JsonPointer jsonPointer = new JsonPointer("/");
+        jsonPointer.remove((JsonArray) null);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testRemoveJsonArrayWithEmptyJsonPointer() {
+        JsonPointer jsonPointer = new JsonPointer("");
+        JsonArray target = Json.createArrayBuilder().build();
+
+        jsonPointer.remove(target);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testRemoveArrayElementWithIndexNoNumber() {
+        JsonPointer jsonPointer = new JsonPointer("/foo/a");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("foo", Json.createArrayBuilder()
+                        .add("bar")
+                        .add("qux")
+                        .add("baz")).build(); // {"foo":["bar","qux","baz"]}
+
+        jsonPointer.remove(target);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testRemoveArrayElementWithIndexOutOfRange() {
+        JsonPointer jsonPointer = new JsonPointer("/foo/3");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("foo", Json.createArrayBuilder()
+                        .add("bar")
+                        .add("qux")
+                        .add("baz")).build(); // {"foo":["bar","qux","baz"]}
+
+        jsonPointer.remove(target);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testRemoveArrayElementWithInvalidIndex() {
+        JsonPointer jsonPointer = new JsonPointer("/foo/+");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("foo", Json.createArrayBuilder()
+                        .add("bar")
+                        .add("qux")
+                        .add("baz")).build(); // {"foo":["bar","qux","baz"]}
+
+        jsonPointer.remove(target);
+    }
+
+    @Test(expected = JsonException.class)
+    public void testRemoveArrayElementWithLeadingZeroIndex() {
+        JsonPointer jsonPointer = new JsonPointer("/foo/01");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("foo", Json.createArrayBuilder()
+                        .add("bar")
+                        .add("qux")
+                        .add("baz")).build(); // {"foo":["bar","qux","baz"]}
+
+        jsonPointer.remove(target);
+    }
+
+    @Test
+    public void testRemoveArrayElement() {
+        JsonPointer jsonPointer = new JsonPointer("/0/1");
+        JsonStructure target = Json.createArrayBuilder()
+                .add(Json.createArrayBuilder()
+                        .add("bar")
+                        .add("qux")
+                        .add("baz")).build(); // [["bar","qux","baz"]]
+
+        JsonStructure result = jsonPointer.remove(target);
+        assertEquals("[[\"bar\",\"baz\"]]", result.toString()); // 
[["bar","baz"]]
+    }
+
+    @Test
+    public void testRemoveObjectMember() {
+        JsonPointer jsonPointer = new JsonPointer("/baz");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("baz", "qux")
+                .add("foo", "bar").build(); // {"baz":"qux","foo":"bar"}
+
+        JsonStructure result = jsonPointer.remove(target);
+        assertEquals("{\"foo\":\"bar\"}", result.toString()); // {"foo":"bar"}
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testReplaceJsonObjectWithTargetNull() {
+        JsonPointer jsonPointer = new JsonPointer("/");
+        jsonPointer.replace((JsonObject) null, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testReplaceJsonObjectWithEmptyJsonPointer() {
+        JsonPointer jsonPointer = new JsonPointer("");
+        JsonObject target = Json.createObjectBuilder().build();
+
+        jsonPointer.replace(target, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testReplaceJsonArrayWithTargetNull() {
+        JsonPointer jsonPointer = new JsonPointer("/");
+        jsonPointer.replace((JsonArray) null, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testReplaceJsonArrayWithEmptyJsonPointer() {
+        JsonPointer jsonPointer = new JsonPointer("");
+        JsonArray target = Json.createArrayBuilder().build();
+
+        jsonPointer.replace(target, new JsonStringImpl("qux"));
+    }
+
+    @Test
+    public void testReplaceArrayElement() {
+        JsonPointer jsonPointer = new JsonPointer("/1/1");
+        JsonStructure target = Json.createArrayBuilder()
+                .add("bar")
+                .add(Json.createArrayBuilder()
+                        .add("abc")
+                        .add("def")).build(); // ["bar",["abc","def"]]
+
+        JsonStructure result = jsonPointer.replace(target, new 
JsonStringImpl("qux"));
+        assertEquals("[\"bar\",[\"abc\",\"qux\"]]", result.toString()); // 
["bar",["abc","qux"]]
+    }
+
+    @Test(expected = JsonException.class)
+    public void testReplaceArrayElementWithIndexOutOfRange() {
+        JsonPointer jsonPointer = new JsonPointer("/1/2");
+        JsonStructure target = Json.createArrayBuilder()
+                .add("bar")
+                .add(Json.createArrayBuilder()
+                        .add("abc")
+                        .add("def")).build(); // ["bar",["abc","def"]]
+
+        jsonPointer.replace(target, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testReplaceArrayElementWithIndexNoNumber() {
+        JsonPointer jsonPointer = new JsonPointer("/1/a");
+        JsonStructure target = Json.createArrayBuilder()
+                .add("bar")
+                .add(Json.createArrayBuilder()
+                        .add("abc")
+                        .add("def")).build(); // ["bar",["abc","def"]]
+
+        jsonPointer.replace(target, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testReplaceArrayElementWithLeadingZeroIndex() {
+        JsonPointer jsonPointer = new JsonPointer("/1/01");
+        JsonStructure target = Json.createArrayBuilder()
+                .add("bar")
+                .add(Json.createArrayBuilder()
+                        .add("abc")
+                        .add("def")).build(); // ["bar",["abc","def"]]
+
+        jsonPointer.replace(target, new JsonStringImpl("qux"));
+    }
+
+    @Test(expected = JsonException.class)
+    public void testReplaceArrayElementWithInvalidIndex() {
+        JsonPointer jsonPointer = new JsonPointer("/1/+");
+        JsonStructure target = Json.createArrayBuilder()
+                .add("bar")
+                .add(Json.createArrayBuilder()
+                        .add("abc")
+                        .add("def")).build(); // ["bar",["abc","def"]]
+
+        jsonPointer.replace(target, new JsonStringImpl("qux"));
+    }
+
+    @Test
+    public void testReplaceObjectMember() {
+        JsonPointer jsonPointer = new JsonPointer("/baz");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("foo", "bar")
+                .add("baz", "qux").build(); // {"foo":"bar","baz":"qux"}
+
+        JsonStructure result = jsonPointer.replace(target, new 
JsonStringImpl("boo"));
+        assertEquals("{\"foo\":\"bar\",\"baz\":\"boo\"}", result.toString()); 
// {"foo":"bar","baz":"boo"}
+    }
+
+    @Test(expected = JsonException.class)
+    public void testReplaceObjectMemberWithNonexistentTarget1() {
+        JsonPointer jsonPointer = new JsonPointer("/baz/a");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("foo", "bar")
+                .add("baz", "qux").build(); // {"foo":"bar","baz":"qux"}
+
+        JsonStructure result = jsonPointer.replace(target, new 
JsonStringImpl("boo"));
+        assertEquals("{\"foo\":\"bar\",\"baz\":\"boo\"}", result.toString()); 
// {"foo":"bar","baz":"boo"}
+    }
+
+    @Test(expected = JsonException.class)
+    public void testReplaceObjectMemberWithNonexistentTarget2() {
+        JsonPointer jsonPointer = new JsonPointer("/fo");
+        JsonStructure target = Json.createObjectBuilder()
+                .add("foo", "bar")
+                .add("baz", "qux").build(); // {"foo":"bar","baz":"qux"}
+
+        JsonStructure result = jsonPointer.replace(target, new 
JsonStringImpl("boo"));
+        assertEquals("{\"foo\":\"bar\",\"baz\":\"boo\"}", result.toString()); 
// {"foo":"bar","baz":"boo"}
+    }
+
+    @Test
+    public void testEqualsTrue() {
+        JsonPointer jsonPointer1 = new JsonPointer("/foo/1");
+        JsonPointer jsonPointer2 = new JsonPointer("/foo/1");
+        assertTrue(jsonPointer1.equals(jsonPointer2));
+    }
+
+    @Test
+    public void testEqualsFalse() {
+        JsonPointer jsonPointer1 = new JsonPointer("/foo/1");
+        JsonPointer jsonPointer2 = new JsonPointer("/foo/2");
+        assertFalse(jsonPointer1.equals(jsonPointer2));
+    }
+
     private JsonStructure getJsonDocument() {
         JsonReader reader = Json.createReaderFactory(Collections.<String, 
Object>emptyMap()).createReader(
                 
Thread.currentThread().getContextClassLoader().getResourceAsStream("json/jsonPointerTest.json"));

Reply via email to