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 2016/11/22 21:06:41 UTC

[6/6] johnzon git commit: JOHNZON-95 make JsonPointer an internal class which implements the spec API interface

JOHNZON-95 make JsonPointer an internal class which implements the spec API interface

txs to Armin Hasler for providing the JsonPointer implementation


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

Branch: refs/heads/JSONP-1.1
Commit: 24b01af8ebe37aa42fb98c2237edf807d5ec7379
Parents: bfdab10
Author: Mark Struberg <st...@apache.org>
Authored: Tue Nov 22 21:49:32 2016 +0100
Committer: Mark Struberg <st...@apache.org>
Committed: Tue Nov 22 21:49:32 2016 +0100

----------------------------------------------------------------------
 .../org/apache/johnzon/core/JsonPointer.java    | 476 -------------------
 .../apache/johnzon/core/JsonPointerImpl.java    | 456 ++++++++++++++++++
 .../apache/johnzon/core/JsonProviderImpl.java   |   2 +-
 .../apache/johnzon/core/JsonPointerTest.java    | 124 ++---
 4 files changed, 519 insertions(+), 539 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/johnzon/blob/24b01af8/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
deleted file mode 100644
index ca942ef..0000000
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointer.java
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * 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 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
- * <a href="http://tools.ietf.org/html/rfc6901">RFC 6901</a>.
- * </p>
- * <p> A JSON Pointer, when applied to a target {@link JsonValue},
- * defines a reference location in the target.</p>
- * <p> An empty JSON Pointer string defines a reference to the target itself.</p>
- * <p> If the JSON Pointer string is non-empty, it must be a sequence
- * of '/' prefixed tokens, and the target must either be a {@link JsonArray}
- * or {@link JsonObject}. If the target is a {@code JsonArray}, the pointer
- * defines a reference to an array element, and the last token specifies the index.
- * If the target is a {@link JsonObject}, the pointer defines a reference to a
- * name/value pair, and the last token specifies the name.
- * </p>
- * <p> The method {@link JsonPointer#getValue getValue()} returns the referenced value.
- * The methods {@link JsonPointer#add add()}, {@link JsonPointer#replace replace()},
- * and {@link JsonPointer#remove remove()} executes the operations specified in
- * <a href="http://tools.ietf.org/html/rfc6902">RFC 6902</a>. </p>
- *
- * @since 1.1
- */
-
-public class JsonPointer {
-
-    private final String jsonPointer;
-    private final List<String> referenceTokens = new ArrayList<String>();
-    private final String lastReferenceToken;
-
-    /**
-     * Constructs and initializes a JsonPointer.
-     *
-     * @param jsonPointer the JSON Pointer string
-     * @throws NullPointerException if {@code jsonPointer} is {@code null}
-     * @throws JsonException        if {@code jsonPointer} is not a valid JSON Pointer
-     */
-    public JsonPointer(String jsonPointer) {
-        if (jsonPointer == null) {
-            throw new NullPointerException("jsonPointer must not be null");
-        }
-        if (!jsonPointer.equals("") && !jsonPointer.startsWith("/")) {
-            throw new JsonException("A non-empty JsonPointer string must begin with a '/'");
-        }
-
-        this.jsonPointer = jsonPointer;
-        String[] encodedReferenceTokens = jsonPointer.split("/", -1);
-
-        for (String encodedReferenceToken : encodedReferenceTokens) {
-            referenceTokens.add(JsonPointerUtil.decode(encodedReferenceToken));
-        }
-        lastReferenceToken = referenceTokens.get(referenceTokens.size() - 1);
-    }
-
-    /**
-     * Compares this {@code JsonPointer} with another object.
-     *
-     * @param obj the object to compare this {@code JsonPointer} against
-     * @return true if the given object is a {@code JsonPointer} with the same
-     * reference tokens as this one, false otherwise.
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null || getClass() != obj.getClass()) {
-            return false;
-        }
-
-        JsonPointer that = (JsonPointer) obj;
-        return jsonPointer.equals(that.jsonPointer);
-    }
-
-    /**
-     * Returns the hash code value for this {@code JsonPointer} object.
-     * The hash code of this object is defined by the hash codes of it's reference tokens.
-     *
-     * @return the hash code value for this {@code JsonPointer} object
-     */
-    @Override
-    public int hashCode() {
-        return jsonPointer.hashCode();
-    }
-
-    /**
-     * Returns the value at the referenced location in the specified {@code target}
-     *
-     * @param target the target referenced by this {@code JsonPointer}
-     * @return the referenced value in the target.
-     * @throws NullPointerException if {@code target} is null
-     * @throws JsonException        if the referenced value does not exist
-     */
-    public JsonValue getValue(JsonStructure target) {
-        if (target == null) {
-            throw new NullPointerException("target must not be null");
-        }
-        if (isEmptyJsonPointer()) {
-            return target;
-        }
-
-        JsonValue jsonValue = target;
-        for (int i = 1; i < referenceTokens.size(); i++) {
-            jsonValue = getValue(jsonValue, referenceTokens.get(i), i, referenceTokens.size() - 1);
-        }
-        return jsonValue;
-    }
-
-    /**
-     * Adds or replaces a value at the referenced location in the specified
-     * {@code target} with the specified {@code value}.
-     * <ol>
-     * <li>If the reference is the target (empty JSON Pointer string),
-     * the specified {@code value}, which must be the same type as
-     * specified {@code target}, is returned.</li>
-     * <li>If the reference is an array element, the specified {@code value} is inserted
-     * into the array, at the referenced index. The value currently at that location, and
-     * any subsequent values, are shifted to the right (adds one to the indices).
-     * Index starts with 0. If the reference is specified with a "-", or if the
-     * index is equal to the size of the array, the value is appended to the array.</li>
-     * <li>If the reference is a name/value pair of a {@code JsonObject}, and the
-     * referenced value exists, the value is replaced by the specified {@code value}.
-     * If the value does not exist, a new name/value pair is added to the object.</li>
-     * </ol>
-     *
-     * @param target the target referenced by this {@code JsonPointer}
-     * @param value  the value to be added
-     * @return the transformed {@code target} after the value is added.
-     * @throws NullPointerException if {@code target} is {@code null}
-     * @throws JsonException        if the reference is an array element and
-     *                              the index is out of range ({@code index < 0 || index > array size}),
-     *                              or if the pointer contains references to non-existing objects or arrays.
-     */
-    public JsonStructure add(JsonStructure target, JsonValue value) {
-        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;
-        }
-
-        if (target instanceof JsonObject) {
-            return add((JsonObject) target, value);
-        } else {
-            return add((JsonArray) target, value);
-        }
-    }
-
-    /**
-     * Adds or replaces a 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 added
-     * @return the transformed {@code target} after the value is added.
-     * @throws NullPointerException if {@code target} is {@code null}
-     * @throws JsonException        if the reference is an array element and
-     *                              the index is out of range ({@code index < 0 || index > array size}),
-     *                              or if the pointer contains references to non-existing objects or arrays.
-     * @see #add(JsonStructure, JsonValue)
-     */
-    public JsonObject add(JsonObject target, JsonValue value) {
-        validateAdd(target);
-
-        return (JsonObject) add(target, 1, referenceTokens.size() - 1, value);
-    }
-
-    /**
-     * Adds or replaces a 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 added
-     * @return the transformed {@code target} after the value is added.
-     * @throws NullPointerException if {@code target} is {@code null}
-     * @throws JsonException        if the reference is an array element and
-     *                              the index is out of range ({@code index < 0 || index > array size}),
-     *                              or if the pointer contains references to non-existing objects or arrays.
-     * @see #add(JsonStructure, JsonValue)
-     */
-    public JsonArray add(JsonArray target, JsonValue 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);
-        }
-    }
-
-    /**
-     * Replaces the value at the referenced location in the specified
-     *
-     * @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.
-     * @see #replace(JsonStructure, JsonValue)
-     */
-    public JsonObject replace(JsonObject target, JsonValue value) {
-        return add(remove(target), value);
-    }
-
-    /**
-     * Replaces the value at the referenced location in the specified
-     *
-     * @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.
-     * @see #replace(JsonStructure, JsonValue)
-     */
-    public JsonArray replace(JsonArray target, JsonValue 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);
-        }
-    }
-
-    /**
-     * 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.
-     * @see #remove(JsonStructure)
-     */
-    public JsonObject remove(JsonObject target) {
-        validateRemove(target);
-
-        return (JsonObject) remove(target, 1, referenceTokens.size() - 1);
-    }
-
-    /**
-     * 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.
-     * @see #remove(JsonStructure)
-     */
-    public JsonArray remove(JsonArray 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/24b01af8/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerImpl.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerImpl.java
new file mode 100644
index 0000000..25e5ceb
--- /dev/null
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPointerImpl.java
@@ -0,0 +1,456 @@
+/*
+ * 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 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.JsonPointer;
+import javax.json.JsonStructure;
+import javax.json.JsonValue;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+
+public class JsonPointerImpl implements JsonPointer {
+
+    private final String jsonPointer;
+    private final List<String> referenceTokens = new ArrayList<String>();
+    private final String lastReferenceToken;
+
+    /**
+     * Constructs and initializes a JsonPointer.
+     *
+     * @param jsonPointer the JSON Pointer string
+     * @throws NullPointerException if {@code jsonPointer} is {@code null}
+     * @throws JsonException        if {@code jsonPointer} is not a valid JSON Pointer
+     */
+    public JsonPointerImpl(String jsonPointer) {
+        if (jsonPointer == null) {
+            throw new NullPointerException("jsonPointer must not be null");
+        }
+        if (!jsonPointer.equals("") && !jsonPointer.startsWith("/")) {
+            throw new JsonException("A non-empty JsonPointer string must begin with a '/'");
+        }
+
+        this.jsonPointer = jsonPointer;
+        String[] encodedReferenceTokens = jsonPointer.split("/", -1);
+
+        for (String encodedReferenceToken : encodedReferenceTokens) {
+            referenceTokens.add(JsonPointerUtil.decode(encodedReferenceToken));
+        }
+        lastReferenceToken = referenceTokens.get(referenceTokens.size() - 1);
+    }
+
+    /**
+     * Compares this {@code JsonPointer} with another object.
+     *
+     * @param obj the object to compare this {@code JsonPointer} against
+     * @return true if the given object is a {@code JsonPointer} with the same
+     * reference tokens as this one, false otherwise.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+
+        JsonPointerImpl that = (JsonPointerImpl) obj;
+        return jsonPointer.equals(that.jsonPointer);
+    }
+
+    /**
+     * Returns the hash code value for this {@code JsonPointer} object.
+     * The hash code of this object is defined by the hash codes of it's reference tokens.
+     *
+     * @return the hash code value for this {@code JsonPointer} object
+     */
+    @Override
+    public int hashCode() {
+        return jsonPointer.hashCode();
+    }
+
+    /**
+     * Returns the value at the referenced location in the specified {@code target}
+     *
+     * @param target the target referenced by this {@code JsonPointer}
+     * @return the referenced value in the target.
+     * @throws NullPointerException if {@code target} is null
+     * @throws JsonException        if the referenced value does not exist
+     */
+    public JsonValue getValue(JsonStructure target) {
+        if (target == null) {
+            throw new NullPointerException("target must not be null");
+        }
+        if (isEmptyJsonPointer()) {
+            return target;
+        }
+
+        JsonValue jsonValue = target;
+        for (int i = 1; i < referenceTokens.size(); i++) {
+            jsonValue = getValue(jsonValue, referenceTokens.get(i), i, referenceTokens.size() - 1);
+        }
+        return jsonValue;
+    }
+
+    /**
+     * Adds or replaces a value at the referenced location in the specified
+     * {@code target} with the specified {@code value}.
+     * <ol>
+     * <li>If the reference is the target (empty JSON Pointer string),
+     * the specified {@code value}, which must be the same type as
+     * specified {@code target}, is returned.</li>
+     * <li>If the reference is an array element, the specified {@code value} is inserted
+     * into the array, at the referenced index. The value currently at that location, and
+     * any subsequent values, are shifted to the right (adds one to the indices).
+     * Index starts with 0. If the reference is specified with a "-", or if the
+     * index is equal to the size of the array, the value is appended to the array.</li>
+     * <li>If the reference is a name/value pair of a {@code JsonObject}, and the
+     * referenced value exists, the value is replaced by the specified {@code value}.
+     * If the value does not exist, a new name/value pair is added to the object.</li>
+     * </ol>
+     *
+     * @param target the target referenced by this {@code JsonPointer}
+     * @param value  the value to be added
+     * @return the transformed {@code target} after the value is added.
+     * @throws NullPointerException if {@code target} is {@code null}
+     * @throws JsonException        if the reference is an array element and
+     *                              the index is out of range ({@code index < 0 || index > array size}),
+     *                              or if the pointer contains references to non-existing objects or arrays.
+     */
+    public JsonStructure add(JsonStructure target, JsonValue value) {
+        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;
+        }
+
+        if (target instanceof JsonObject) {
+            return add((JsonObject) target, value);
+        } else {
+            return add((JsonArray) target, value);
+        }
+    }
+
+    /**
+     * Adds or replaces a 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 added
+     * @return the transformed {@code target} after the value is added.
+     * @throws NullPointerException if {@code target} is {@code null}
+     * @throws JsonException        if the reference is an array element and
+     *                              the index is out of range ({@code index < 0 || index > array size}),
+     *                              or if the pointer contains references to non-existing objects or arrays.
+     * @see #add(JsonStructure, JsonValue)
+     */
+    public JsonObject add(JsonObject target, JsonValue value) {
+        validateAdd(target);
+
+        return (JsonObject) add(target, 1, referenceTokens.size() - 1, value);
+    }
+
+    /**
+     * Adds or replaces a 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 added
+     * @return the transformed {@code target} after the value is added.
+     * @throws NullPointerException if {@code target} is {@code null}
+     * @throws JsonException        if the reference is an array element and
+     *                              the index is out of range ({@code index < 0 || index > array size}),
+     *                              or if the pointer contains references to non-existing objects or arrays.
+     * @see #add(JsonStructure, JsonValue)
+     */
+    public JsonArray add(JsonArray target, JsonValue 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);
+        }
+    }
+
+    /**
+     * Replaces the value at the referenced location in the specified
+     *
+     * @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.
+     * @see #replace(JsonStructure, JsonValue)
+     */
+    public JsonObject replace(JsonObject target, JsonValue value) {
+        return add(remove(target), value);
+    }
+
+    /**
+     * Replaces the value at the referenced location in the specified
+     *
+     * @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.
+     * @see #replace(JsonStructure, JsonValue)
+     */
+    public JsonArray replace(JsonArray target, JsonValue 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);
+        }
+    }
+
+    /**
+     * 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.
+     * @see #remove(JsonStructure)
+     */
+    public JsonObject remove(JsonObject target) {
+        validateRemove(target);
+
+        return (JsonObject) remove(target, 1, referenceTokens.size() - 1);
+    }
+
+    /**
+     * 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.
+     * @see #remove(JsonStructure)
+     */
+    public JsonArray remove(JsonArray 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/24b01af8/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 99fd6fc..e9926f9 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
@@ -236,7 +236,7 @@ public class JsonProviderImpl extends JsonProvider implements Serializable {
 
         @Override
         public JsonPointer createJsonPointer(String path) {
-            throw new UnsupportedOperationException("TODO JSON-P 1.1");
+            return new JsonPointerImpl(path);
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/johnzon/blob/24b01af8/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 9b6c722..7a3d32a 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
@@ -37,17 +37,17 @@ public class JsonPointerTest {
 
     @Test(expected = NullPointerException.class)
     public void testConstructorWithJsonPointerNull() {
-        new JsonPointer(null);
+        new JsonPointerImpl(null);
     }
 
     @Test(expected = JsonException.class)
     public void testConstructorWithInvalidJsonPointer() {
-        new JsonPointer("a");
+        new JsonPointerImpl("a");
     }
 
     @Test(expected = NullPointerException.class)
     public void testGetValueWithTargetNull() {
-        JsonPointer jsonPointer = new JsonPointer("");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("");
         jsonPointer.getValue(null);
     }
 
@@ -55,7 +55,7 @@ public class JsonPointerTest {
     public void testGetValueWithWholeDocument() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals(jsonDocument.toString(), result.toString());
     }
@@ -64,7 +64,7 @@ public class JsonPointerTest {
     public void testGetValue0() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("0", result.toString());
     }
@@ -73,7 +73,7 @@ public class JsonPointerTest {
     public void testGetValue1() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/a~1b");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/a~1b");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("1", result.toString());
     }
@@ -82,7 +82,7 @@ public class JsonPointerTest {
     public void testGetValue2() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/c%d");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/c%d");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("2", result.toString());
     }
@@ -91,7 +91,7 @@ public class JsonPointerTest {
     public void testGetValue3() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/e^f");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/e^f");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("3", result.toString());
     }
@@ -100,7 +100,7 @@ public class JsonPointerTest {
     public void testGetValue4() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/g|h");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/g|h");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("4", result.toString());
     }
@@ -109,7 +109,7 @@ public class JsonPointerTest {
     public void testGetValue5() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/i\\j");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/i\\j");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("5", result.toString());
     }
@@ -118,7 +118,7 @@ public class JsonPointerTest {
     public void testGetValue6() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/k\"l");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/k\"l");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("6", result.toString());
     }
@@ -127,7 +127,7 @@ public class JsonPointerTest {
     public void testGetValue7() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/ ");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/ ");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("7", result.toString());
     }
@@ -136,7 +136,7 @@ public class JsonPointerTest {
     public void testGetValue8() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/m~0n");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/m~0n");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("8", result.toString());
     }
@@ -145,7 +145,7 @@ public class JsonPointerTest {
     public void testGetValueWithElementNotExistent() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/fool");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/fool");
         jsonPointer.getValue(jsonDocument);
     }
 
@@ -153,7 +153,7 @@ public class JsonPointerTest {
     public void testGetValueWithWholeJsonArray() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/foo");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("[\"bar\",\"baz\"]", result.toString());
     }
@@ -162,7 +162,7 @@ public class JsonPointerTest {
     public void testGetValueWithJsonArray() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/foo/0");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo/0");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("\"bar\"", result.toString());
     }
@@ -171,7 +171,7 @@ public class JsonPointerTest {
     public void testGetValueWithJsonArrayIndexOutOfRange() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/foo/2");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo/2");
         jsonPointer.getValue(jsonDocument);
     }
 
@@ -179,7 +179,7 @@ public class JsonPointerTest {
     public void testGetValueWithJsonArrayIndexNoNumber() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/foo/a");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo/a");
         jsonPointer.getValue(jsonDocument);
     }
 
@@ -187,7 +187,7 @@ public class JsonPointerTest {
     public void testGetValueWithJsonArrayLeadingZeroIndex() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/foo/01");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo/01");
         JsonValue result = jsonPointer.getValue(jsonDocument);
         assertEquals("\"bar\"", result.toString());
     }
@@ -196,19 +196,19 @@ public class JsonPointerTest {
     public void testGetValueWithJsonArrayInvalidIndex() {
         JsonStructure jsonDocument = getJsonDocument();
 
-        JsonPointer jsonPointer = new JsonPointer("/foo/-1");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo/-1");
         jsonPointer.getValue(jsonDocument);
     }
 
     @Test(expected = NullPointerException.class)
     public void testAddJsonStructureWithTargetNull() {
-        JsonPointer jsonPointer = new JsonPointer("");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("");
         jsonPointer.add((JsonStructure) null, new JsonStringImpl("qux"));
     }
 
     @Test(expected = JsonException.class)
     public void testAddJsonStructureWithTypeValueNotTypeTarget() {
-        JsonPointer jsonPointer = new JsonPointer("");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("");
         JsonObject target = Json.createObjectBuilder().build();
         JsonArray value = Json.createArrayBuilder().build();
 
@@ -217,7 +217,7 @@ public class JsonPointerTest {
 
     @Test
     public void testAddJsonStructureWithEmptyJsonPointer() {
-        JsonPointer jsonPointer = new JsonPointer("");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("");
         JsonStructure target = Json.createObjectBuilder().build();
         JsonObject value = Json.createObjectBuilder()
                 .add("foo", "bar").build(); // { "foo": "bar" }
@@ -228,19 +228,19 @@ public class JsonPointerTest {
 
     @Test(expected = NullPointerException.class)
     public void testAddJsonObjectWithTargetNull() {
-        JsonPointer jsonPointer = new JsonPointer("");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("");
         jsonPointer.add((JsonObject) null, new JsonStringImpl("qux"));
     }
 
     @Test(expected = NullPointerException.class)
     public void testAddJsonArrayWithTargetNull() {
-        JsonPointer jsonPointer = new JsonPointer("");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("");
         jsonPointer.add((JsonArray) null, new JsonStringImpl("qux"));
     }
 
     @Test(expected = JsonException.class)
     public void testAddArrayElementWithInvalidIndex() {
-        JsonPointer jsonPointer = new JsonPointer("/+");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/+");
         JsonStructure target = Json.createArrayBuilder().build();
 
         jsonPointer.add(target, new JsonStringImpl("qux"));
@@ -248,7 +248,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testAddArrayElementWithIndexOutOfRange() {
-        JsonPointer jsonPointer = new JsonPointer("/1");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/1");
         JsonStructure target = Json.createArrayBuilder().build();
 
         jsonPointer.add(target, new JsonStringImpl("qux"));
@@ -256,7 +256,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testAddArrayElementWithLeadingZeroIndex() {
-        JsonPointer jsonPointer = new JsonPointer("/01");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/01");
         JsonStructure target = Json.createArrayBuilder()
                 .add("foo").build();
 
@@ -265,7 +265,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testAddArrayElementWithIndexNoNumber() {
-        JsonPointer jsonPointer = new JsonPointer("/a");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/a");
         JsonStructure target = Json.createArrayBuilder()
                 .add("foo").build();
 
@@ -274,7 +274,7 @@ public class JsonPointerTest {
 
     @Test
     public void testAddObject() {
-        JsonPointer jsonPointer = new JsonPointer("/child");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/child");
         JsonStructure target = Json.createObjectBuilder()
                 .add("foo", "bar").build(); // {"foo":"bar"}
         JsonObject value = Json.createObjectBuilder()
@@ -286,7 +286,7 @@ public class JsonPointerTest {
 
     @Test
     public void testAddObjectMember() {
-        JsonPointer jsonPointer = new JsonPointer("/baz");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/baz");
         JsonStructure target = Json.createObjectBuilder()
                 .add("foo", "bar").build(); // {"foo":"bar"}
 
@@ -296,7 +296,7 @@ public class JsonPointerTest {
 
     @Test
     public void testAddFirstObjectMember() {
-        JsonPointer jsonPointer = new JsonPointer("/foo");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo");
         JsonStructure target = Json.createObjectBuilder().build(); // {}
 
         JsonStructure result = jsonPointer.add(target, new JsonStringImpl("bar"));
@@ -305,7 +305,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testAddObjectMemberWithNonexistentTarget() {
-        JsonPointer jsonPointer = new JsonPointer("/baz/bat");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/baz/bat");
         JsonStructure target = Json.createObjectBuilder()
                 .add("foo", "bar").build(); // {"foo":"bar"}
 
@@ -314,7 +314,7 @@ public class JsonPointerTest {
 
     @Test
     public void testAddReplaceObjectMember() {
-        JsonPointer jsonPointer = new JsonPointer("/baz");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/baz");
         JsonStructure target = Json.createObjectBuilder()
                 .add("baz", "qux")
                 .add("foo", "bar").build(); // {"baz":"qux","foo":"bar"}
@@ -325,7 +325,7 @@ public class JsonPointerTest {
 
     @Test
     public void testAddArray() {
-        JsonPointer jsonPointer = new JsonPointer("/0/-");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/0/-");
         JsonStructure target = Json.createArrayBuilder()
                 .add(Json.createArrayBuilder()
                         .add("bar")).build(); // [["bar"]]
@@ -339,7 +339,7 @@ public class JsonPointerTest {
 
     @Test
     public void testAddArrayElement() {
-        JsonPointer jsonPointer = new JsonPointer("/foo/1");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo/1");
         JsonStructure target = Json.createObjectBuilder()
                 .add("foo", Json.createArrayBuilder()
                         .add("bar")
@@ -351,13 +351,13 @@ public class JsonPointerTest {
 
     @Test(expected = NullPointerException.class)
     public void testRemoveJsonObjectWithTargetNull() {
-        JsonPointer jsonPointer = new JsonPointer("/");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/");
         jsonPointer.remove((JsonObject) null);
     }
 
     @Test(expected = JsonException.class)
     public void testRemoveJsonObjectWithEmptyJsonPointer() {
-        JsonPointer jsonPointer = new JsonPointer("");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("");
         JsonObject target = Json.createObjectBuilder().build();
 
         jsonPointer.remove(target);
@@ -365,13 +365,13 @@ public class JsonPointerTest {
 
     @Test(expected = NullPointerException.class)
     public void testRemoveJsonArrayWithTargetNull() {
-        JsonPointer jsonPointer = new JsonPointer("/");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/");
         jsonPointer.remove((JsonArray) null);
     }
 
     @Test(expected = JsonException.class)
     public void testRemoveJsonArrayWithEmptyJsonPointer() {
-        JsonPointer jsonPointer = new JsonPointer("");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("");
         JsonArray target = Json.createArrayBuilder().build();
 
         jsonPointer.remove(target);
@@ -379,7 +379,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testRemoveArrayElementWithIndexNoNumber() {
-        JsonPointer jsonPointer = new JsonPointer("/foo/a");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo/a");
         JsonStructure target = Json.createObjectBuilder()
                 .add("foo", Json.createArrayBuilder()
                         .add("bar")
@@ -391,7 +391,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testRemoveArrayElementWithIndexOutOfRange() {
-        JsonPointer jsonPointer = new JsonPointer("/foo/3");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo/3");
         JsonStructure target = Json.createObjectBuilder()
                 .add("foo", Json.createArrayBuilder()
                         .add("bar")
@@ -403,7 +403,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testRemoveArrayElementWithInvalidIndex() {
-        JsonPointer jsonPointer = new JsonPointer("/foo/+");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo/+");
         JsonStructure target = Json.createObjectBuilder()
                 .add("foo", Json.createArrayBuilder()
                         .add("bar")
@@ -415,7 +415,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testRemoveArrayElementWithLeadingZeroIndex() {
-        JsonPointer jsonPointer = new JsonPointer("/foo/01");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/foo/01");
         JsonStructure target = Json.createObjectBuilder()
                 .add("foo", Json.createArrayBuilder()
                         .add("bar")
@@ -427,7 +427,7 @@ public class JsonPointerTest {
 
     @Test
     public void testRemoveArrayElement() {
-        JsonPointer jsonPointer = new JsonPointer("/0/1");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/0/1");
         JsonStructure target = Json.createArrayBuilder()
                 .add(Json.createArrayBuilder()
                         .add("bar")
@@ -440,7 +440,7 @@ public class JsonPointerTest {
 
     @Test
     public void testRemoveObjectMember() {
-        JsonPointer jsonPointer = new JsonPointer("/baz");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/baz");
         JsonStructure target = Json.createObjectBuilder()
                 .add("baz", "qux")
                 .add("foo", "bar").build(); // {"baz":"qux","foo":"bar"}
@@ -451,13 +451,13 @@ public class JsonPointerTest {
 
     @Test(expected = NullPointerException.class)
     public void testReplaceJsonObjectWithTargetNull() {
-        JsonPointer jsonPointer = new JsonPointer("/");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/");
         jsonPointer.replace((JsonObject) null, new JsonStringImpl("qux"));
     }
 
     @Test(expected = JsonException.class)
     public void testReplaceJsonObjectWithEmptyJsonPointer() {
-        JsonPointer jsonPointer = new JsonPointer("");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("");
         JsonObject target = Json.createObjectBuilder().build();
 
         jsonPointer.replace(target, new JsonStringImpl("qux"));
@@ -465,13 +465,13 @@ public class JsonPointerTest {
 
     @Test(expected = NullPointerException.class)
     public void testReplaceJsonArrayWithTargetNull() {
-        JsonPointer jsonPointer = new JsonPointer("/");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/");
         jsonPointer.replace((JsonArray) null, new JsonStringImpl("qux"));
     }
 
     @Test(expected = JsonException.class)
     public void testReplaceJsonArrayWithEmptyJsonPointer() {
-        JsonPointer jsonPointer = new JsonPointer("");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("");
         JsonArray target = Json.createArrayBuilder().build();
 
         jsonPointer.replace(target, new JsonStringImpl("qux"));
@@ -479,7 +479,7 @@ public class JsonPointerTest {
 
     @Test
     public void testReplaceArrayElement() {
-        JsonPointer jsonPointer = new JsonPointer("/1/1");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/1/1");
         JsonStructure target = Json.createArrayBuilder()
                 .add("bar")
                 .add(Json.createArrayBuilder()
@@ -492,7 +492,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testReplaceArrayElementWithIndexOutOfRange() {
-        JsonPointer jsonPointer = new JsonPointer("/1/2");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/1/2");
         JsonStructure target = Json.createArrayBuilder()
                 .add("bar")
                 .add(Json.createArrayBuilder()
@@ -504,7 +504,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testReplaceArrayElementWithIndexNoNumber() {
-        JsonPointer jsonPointer = new JsonPointer("/1/a");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/1/a");
         JsonStructure target = Json.createArrayBuilder()
                 .add("bar")
                 .add(Json.createArrayBuilder()
@@ -516,7 +516,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testReplaceArrayElementWithLeadingZeroIndex() {
-        JsonPointer jsonPointer = new JsonPointer("/1/01");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/1/01");
         JsonStructure target = Json.createArrayBuilder()
                 .add("bar")
                 .add(Json.createArrayBuilder()
@@ -528,7 +528,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testReplaceArrayElementWithInvalidIndex() {
-        JsonPointer jsonPointer = new JsonPointer("/1/+");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/1/+");
         JsonStructure target = Json.createArrayBuilder()
                 .add("bar")
                 .add(Json.createArrayBuilder()
@@ -540,7 +540,7 @@ public class JsonPointerTest {
 
     @Test
     public void testReplaceObjectMember() {
-        JsonPointer jsonPointer = new JsonPointer("/baz");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/baz");
         JsonStructure target = Json.createObjectBuilder()
                 .add("foo", "bar")
                 .add("baz", "qux").build(); // {"foo":"bar","baz":"qux"}
@@ -551,7 +551,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testReplaceObjectMemberWithNonexistentTarget1() {
-        JsonPointer jsonPointer = new JsonPointer("/baz/a");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/baz/a");
         JsonStructure target = Json.createObjectBuilder()
                 .add("foo", "bar")
                 .add("baz", "qux").build(); // {"foo":"bar","baz":"qux"}
@@ -562,7 +562,7 @@ public class JsonPointerTest {
 
     @Test(expected = JsonException.class)
     public void testReplaceObjectMemberWithNonexistentTarget2() {
-        JsonPointer jsonPointer = new JsonPointer("/fo");
+        JsonPointerImpl jsonPointer = new JsonPointerImpl("/fo");
         JsonStructure target = Json.createObjectBuilder()
                 .add("foo", "bar")
                 .add("baz", "qux").build(); // {"foo":"bar","baz":"qux"}
@@ -573,15 +573,15 @@ public class JsonPointerTest {
 
     @Test
     public void testEqualsTrue() {
-        JsonPointer jsonPointer1 = new JsonPointer("/foo/1");
-        JsonPointer jsonPointer2 = new JsonPointer("/foo/1");
+        JsonPointerImpl jsonPointer1 = new JsonPointerImpl("/foo/1");
+        JsonPointerImpl jsonPointer2 = new JsonPointerImpl("/foo/1");
         assertTrue(jsonPointer1.equals(jsonPointer2));
     }
 
     @Test
     public void testEqualsFalse() {
-        JsonPointer jsonPointer1 = new JsonPointer("/foo/1");
-        JsonPointer jsonPointer2 = new JsonPointer("/foo/2");
+        JsonPointerImpl jsonPointer1 = new JsonPointerImpl("/foo/1");
+        JsonPointerImpl jsonPointer2 = new JsonPointerImpl("/foo/2");
         assertFalse(jsonPointer1.equals(jsonPointer2));
     }