diff --git a/build.gradle b/build.gradle index cb1a1ed7..c87a72f9 100644 --- a/build.gradle +++ b/build.gradle @@ -43,30 +43,29 @@ apply(plugin: "eclipse"); group = "com.github.java-json-tools"; version = "1.11-SNAPSHOT"; -sourceCompatibility = "1.6"; -targetCompatibility = "1.6"; // defaults to sourceCompatibility +sourceCompatibility = JavaVersion.VERSION_1_6; +targetCompatibility = JavaVersion.VERSION_1_6; // defaults to sourceCompatibility /* * List of dependencies */ dependencies { - provided(group: "com.google.code.findbugs", name: "jsr305", version: "2.0.1"); - compile(group: "com.github.java-json-tools", name: "jackson-coreutils", version: "1.9"); - testCompile(group: "org.testng", name: "testng", version: "6.8.7") { + provided(group: "com.google.code.findbugs", name: "jsr305", version: "3.0.2"); + implementation(group: "com.github.java-json-tools", name: "jackson-coreutils", version: "1.10-SNAPSHOT"); + testImplementation(group: "com.google.guava", name: "guava", version: "16.0.1"); + testImplementation(group: "org.testng", name: "testng", version: "7.0.0-beta1") { exclude(group: "junit", module: "junit"); exclude(group: "org.beanshell", module: "bsh"); exclude(group: "org.yaml", module: "snakeyaml"); }; - testCompile(group: "org.mockito", name: "mockito-core", version: "1.9.5"); - testCompile(group: "org.assertj", name: "assertj-core", version: "1.7.0"); + testImplementation(group: "org.mockito", name: "mockito-core", version: "2.23.4"); + testImplementation(group: "org.assertj", name: "assertj-core", version: "3.11.1"); } javadoc.options.links("http://docs.oracle.com/javase/6/docs/api/"); -javadoc.options.links("http://jsr-305.googlecode.com/svn/trunk/javadoc/"); javadoc.options.links("http://fasterxml.github.com/jackson-databind/javadoc/2.2.0/"); javadoc.options.links("http://fasterxml.github.com/jackson-core/javadoc/2.2.0/"); javadoc.options.links("http://fasterxml.github.com/jackson-annotations/javadoc/2.2.0/"); -javadoc.options.links("http://docs.guava-libraries.googlecode.com/git-history/v16.0.1/javadoc/"); javadoc.options.links("http://fge.github.io/msg-simple/"); javadoc.options.links("http://fge.github.io/jackson-coreutils/"); @@ -115,13 +114,15 @@ artifacts { archives javadocJar; } -task wrapper(type: Wrapper) { - gradleVersion = "3.5"; - distributionUrl = "http://services.gradle.org/distributions/gradle-${gradleVersion}-all.zip"; +wrapper { + gradleVersion = "5.0"; + distributionUrl = "https://services.gradle.org/distributions/gradle-${gradleVersion}-all.zip"; } -task pom << { - pom {}.writeTo("${projectDir}/pom.xml"); +task pom { + doLast { + pom {}.writeTo("${projectDir}/pom.xml"); + } } /* @@ -136,18 +137,20 @@ project.ext { sonatypeSnapshots = "https://oss.sonatype.org/content/repositories/snapshots/"; }; -task checkSigningRequirements << { - def requiredProperties = [ "sonatypeUsername", "sonatypePassword" ]; - def noDice = false; - requiredProperties.each { - if (project.properties[it] == null) { - noDice = true; - System.err.printf("property \"%s\" is not defined!") +task checkSigningRequirements { + doLast { + def requiredProperties = [ "sonatypeUsername", "sonatypePassword" ]; + def noDice = false; + requiredProperties.each { + if (project.properties[it] == null) { + noDice = true; + System.err.printf("property \"%s\" is not defined!") + } } + if (noDice) + throw new IllegalStateException("missing required properties for " + + "upload"); } - if (noDice) - throw new IllegalStateException("missing required properties for " + - "upload"); } uploadArchives { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 3c7abdf1..457aad0d 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 44638189..ee671127 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Fri May 11 21:07:09 PDT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-3.5-all.zip diff --git a/gradlew b/gradlew index 91a7e269..af6708ff 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,20 +6,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m"' + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -114,6 +113,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -154,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index aec99730..0f8d5937 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..e69de29b diff --git a/src/main/java/com/github/fge/jsonpatch/AddOperation.java b/src/main/java/com/github/fge/jsonpatch/AddOperation.java index 56716fb0..5e5fb57a 100644 --- a/src/main/java/com/github/fge/jsonpatch/AddOperation.java +++ b/src/main/java/com/github/fge/jsonpatch/AddOperation.java @@ -27,7 +27,8 @@ import com.github.fge.jackson.jsonpointer.JsonPointer; import com.github.fge.jackson.jsonpointer.ReferenceToken; import com.github.fge.jackson.jsonpointer.TokenResolver; -import com.google.common.collect.Iterables; + +import java.util.NoSuchElementException; /** @@ -105,6 +106,7 @@ private JsonNode addToArray(final JsonPointer path, final JsonNode node) { final JsonNode ret = node.deepCopy(); final ArrayNode target = (ArrayNode) path.parent().get(ret); + final TokenResolver token = Iterables.getLast(path); if (token.getToken().equals(LAST_ARRAY_ELEMENT)) { @@ -131,9 +133,10 @@ private JsonNode addToArray(final JsonPointer path, final JsonNode node) private JsonNode addToObject(final JsonPointer path, final JsonNode node) { + final TokenResolver token = Iterables.getLast(path); final JsonNode ret = node.deepCopy(); final ObjectNode target = (ObjectNode) path.parent().get(ret); - target.put(Iterables.getLast(path).getToken().getRaw(), value); + target.set(token.getToken().getRaw(), value); return ret; } } diff --git a/src/main/java/com/github/fge/jsonpatch/Iterables.java b/src/main/java/com/github/fge/jsonpatch/Iterables.java new file mode 100644 index 00000000..84697884 --- /dev/null +++ b/src/main/java/com/github/fge/jsonpatch/Iterables.java @@ -0,0 +1,29 @@ +package com.github.fge.jsonpatch; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * @author Sergey Nazin on 30-Nov-18 + */ +public final class Iterables { + + private Iterables() {} + + /** + * Returns the last element of {@code iterable}. + * + * @param iterable type of iterable + * @return the last element of {@code iterable} + * @throws NoSuchElementException if the iterable is empty + */ + public static T getLast(Iterable iterable) { + Iterator iterator = iterable.iterator(); + while (true) { + T current = iterator.next(); + if (!iterator.hasNext()) { + return current; + } + } + } +} diff --git a/src/main/java/com/github/fge/jsonpatch/JsonPatch.java b/src/main/java/com/github/fge/jsonpatch/JsonPatch.java index 178ab867..c92d951a 100644 --- a/src/main/java/com/github/fge/jsonpatch/JsonPatch.java +++ b/src/main/java/com/github/fge/jsonpatch/JsonPatch.java @@ -28,9 +28,10 @@ import com.github.fge.jackson.JacksonUtils; import com.github.fge.msgsimple.bundle.MessageBundle; import com.github.fge.msgsimple.load.MessageBundles; -import com.google.common.collect.ImmutableList; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -111,7 +112,7 @@ public final class JsonPatch @JsonCreator public JsonPatch(final List operations) { - this.operations = ImmutableList.copyOf(operations); + this.operations = Collections.unmodifiableList(new ArrayList(operations)); } /** @@ -126,7 +127,7 @@ public static JsonPatch fromJson(final JsonNode node) throws IOException { BUNDLE.checkNotNull(node, "jsonPatch.nullInput"); - return JacksonUtils.getReader().withType(JsonPatch.class) + return JacksonUtils.getReader().forType(JsonPatch.class) .readValue(node); } diff --git a/src/main/java/com/github/fge/jsonpatch/RemoveOperation.java b/src/main/java/com/github/fge/jsonpatch/RemoveOperation.java index 16b0011d..4c528baa 100644 --- a/src/main/java/com/github/fge/jsonpatch/RemoveOperation.java +++ b/src/main/java/com/github/fge/jsonpatch/RemoveOperation.java @@ -30,7 +30,6 @@ import com.fasterxml.jackson.databind.node.MissingNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.github.fge.jackson.jsonpointer.JsonPointer; -import com.google.common.collect.Iterables; import java.io.IOException; diff --git a/src/main/java/com/github/fge/jsonpatch/ReplaceOperation.java b/src/main/java/com/github/fge/jsonpatch/ReplaceOperation.java index 72405a6a..8851427c 100644 --- a/src/main/java/com/github/fge/jsonpatch/ReplaceOperation.java +++ b/src/main/java/com/github/fge/jsonpatch/ReplaceOperation.java @@ -25,7 +25,6 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.github.fge.jackson.jsonpointer.JsonPointer; -import com.google.common.collect.Iterables; /** * JSON Patch {@code replace} operation @@ -73,7 +72,7 @@ public JsonNode apply(final JsonNode node) final JsonNode parent = path.parent().get(ret); final String rawToken = Iterables.getLast(path).getToken().getRaw(); if (parent.isObject()) - ((ObjectNode) parent).put(rawToken, replacement); + ((ObjectNode) parent).set(rawToken, replacement); else ((ArrayNode) parent).set(Integer.parseInt(rawToken), replacement); return ret; diff --git a/src/main/java/com/github/fge/jsonpatch/diff/DiffProcessor.java b/src/main/java/com/github/fge/jsonpatch/diff/DiffProcessor.java index 05ee8874..765c29e4 100644 --- a/src/main/java/com/github/fge/jsonpatch/diff/DiffProcessor.java +++ b/src/main/java/com/github/fge/jsonpatch/diff/DiffProcessor.java @@ -26,12 +26,9 @@ import com.github.fge.jsonpatch.JsonPatchOperation; import com.google.common.base.Equivalence; import com.google.common.base.Predicate; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; import javax.annotation.Nullable; -import java.util.List; -import java.util.Map; +import java.util.*; // TODO: cleanup final class DiffProcessor @@ -41,11 +38,11 @@ final class DiffProcessor private final Map unchanged; - private final List diffs = Lists.newArrayList(); + private final List diffs = new ArrayList(); DiffProcessor(final Map unchanged) { - this.unchanged = ImmutableMap.copyOf(unchanged); + this.unchanged = Collections.unmodifiableMap(new HashMap(unchanged)); } void valueReplaced(final JsonPointer pointer, final JsonNode oldValue, @@ -79,7 +76,7 @@ void valueAdded(final JsonPointer pointer, final JsonNode value) JsonPatch getPatch() { - final List list = Lists.newArrayList(); + final List list = new ArrayList(); for (final DiffOperation op: diffs) list.add(op.asJsonPatchOperation()); diff --git a/src/main/java/com/github/fge/jsonpatch/diff/JsonDiff.java b/src/main/java/com/github/fge/jsonpatch/diff/JsonDiff.java index 5ff3ee12..ab9135b2 100644 --- a/src/main/java/com/github/fge/jsonpatch/diff/JsonDiff.java +++ b/src/main/java/com/github/fge/jsonpatch/diff/JsonDiff.java @@ -31,16 +31,11 @@ import com.github.fge.jsonpatch.JsonPatchMessages; import com.github.fge.msgsimple.bundle.MessageBundle; import com.github.fge.msgsimple.load.MessageBundles; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Equivalence; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import javax.annotation.ParametersAreNonnullByDefault; import java.io.IOException; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * JSON "diff" implementation @@ -164,21 +159,46 @@ private static void generateObjectDiffs(final DiffProcessor processor, final ObjectNode target) { final Set firstFields - = Sets.newTreeSet(Sets.newHashSet(source.fieldNames())); + = collect(source.fieldNames(), new TreeSet()); final Set secondFields - = Sets.newTreeSet(Sets.newHashSet(target.fieldNames())); + = collect(target.fieldNames(), new TreeSet()); - for (final String field: Sets.difference(firstFields, secondFields)) + final Set copy1 = new HashSet(firstFields); + copy1.removeAll(secondFields); + + for (final String field: Collections.unmodifiableSet(copy1)) processor.valueRemoved(pointer.append(field), source.get(field)); - for (final String field: Sets.difference(secondFields, firstFields)) + final Set copy2 = new HashSet(secondFields); + copy2.removeAll(firstFields); + + + for (final String field: Collections.unmodifiableSet(copy2)) processor.valueAdded(pointer.append(field), target.get(field)); - for (final String field: Sets.intersection(firstFields, secondFields)) + final Set intersection = new HashSet(firstFields); + intersection.retainAll(secondFields); + + for (final String field: intersection) generateDiffs(processor, pointer.append(field), source.get(field), target.get(field)); } + private static Set collect(Iterator from, Set to) { + if (from == null) { + throw new NullPointerException(); + } + if (to == null) { + throw new NullPointerException(); + } + while (from.hasNext()) { + to.add(from.next()); + } + return Collections.unmodifiableSet(to); + } + + + private static void generateArrayDiffs(final DiffProcessor processor, final JsonPointer pointer, final ArrayNode source, final ArrayNode target) @@ -204,11 +224,10 @@ private static void generateArrayDiffs(final DiffProcessor processor, } - @VisibleForTesting static Map getUnchangedValues(final JsonNode source, final JsonNode target) { - final Map ret = Maps.newHashMap(); + final Map ret = new HashMap(); computeUnchanged(ret, JsonPointer.empty(), source, target); return ret; } diff --git a/src/main/java/com/github/fge/jsonpatch/mergepatch/JsonMergePatchDeserializer.java b/src/main/java/com/github/fge/jsonpatch/mergepatch/JsonMergePatchDeserializer.java index f571438c..957e45ad 100644 --- a/src/main/java/com/github/fge/jsonpatch/mergepatch/JsonMergePatchDeserializer.java +++ b/src/main/java/com/github/fge/jsonpatch/mergepatch/JsonMergePatchDeserializer.java @@ -27,13 +27,9 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.NullNode; import com.github.fge.jackson.JacksonUtils; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import java.io.IOException; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; +import java.util.*; final class JsonMergePatchDeserializer extends JsonDeserializer @@ -71,8 +67,8 @@ public JsonMergePatch deserialize(final JsonParser jp, * members. */ - final Set removedMembers = Sets.newHashSet(); - final Map modifiedMembers = Maps.newHashMap(); + final Set removedMembers = new HashSet(); + final Map modifiedMembers = new HashMap(); final Iterator> iterator = node.fields(); Map.Entry entry; diff --git a/src/main/java/com/github/fge/jsonpatch/mergepatch/NonObjectMergePatch.java b/src/main/java/com/github/fge/jsonpatch/mergepatch/NonObjectMergePatch.java index 1735f775..9a1ae8c0 100644 --- a/src/main/java/com/github/fge/jsonpatch/mergepatch/NonObjectMergePatch.java +++ b/src/main/java/com/github/fge/jsonpatch/mergepatch/NonObjectMergePatch.java @@ -25,7 +25,6 @@ import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.jsontype.TypeSerializer; import com.github.fge.jsonpatch.JsonPatchException; -import com.google.common.base.Preconditions; import javax.annotation.ParametersAreNonnullByDefault; import java.io.IOException; @@ -38,7 +37,10 @@ final class NonObjectMergePatch NonObjectMergePatch(final JsonNode node) { - this.node = Preconditions.checkNotNull(node); + if (node == null) { + throw new NullPointerException(); + } + this.node = node; } @Override diff --git a/src/main/java/com/github/fge/jsonpatch/mergepatch/ObjectMergePatch.java b/src/main/java/com/github/fge/jsonpatch/mergepatch/ObjectMergePatch.java index 39f79d65..8ab53125 100644 --- a/src/main/java/com/github/fge/jsonpatch/mergepatch/ObjectMergePatch.java +++ b/src/main/java/com/github/fge/jsonpatch/mergepatch/ObjectMergePatch.java @@ -28,14 +28,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.github.fge.jackson.JacksonUtils; import com.github.fge.jsonpatch.JsonPatchException; -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import javax.annotation.ParametersAreNonnullByDefault; import java.io.IOException; -import java.util.Map; -import java.util.Set; +import java.util.*; @ParametersAreNonnullByDefault final class ObjectMergePatch @@ -47,8 +43,8 @@ final class ObjectMergePatch ObjectMergePatch(final Set removedMembers, final Map modifiedMembers) { - this.removedMembers = ImmutableSet.copyOf(removedMembers); - this.modifiedMembers = ImmutableMap.copyOf(modifiedMembers); + this.removedMembers = Collections.unmodifiableSet(new HashSet(removedMembers)); + this.modifiedMembers = Collections.unmodifiableMap(new HashMap(modifiedMembers)); } @Override @@ -82,9 +78,9 @@ public JsonNode apply(final JsonNode input) * * if it is an ObjectMergePatch, we get back here; the value will * be replaced with a JSON Object anyway before being processed. */ - value = Optional.fromNullable(ret.get(key)) - .or(NullNode.getInstance()); - ret.put(key, entry.getValue().apply(value)); + final JsonNode jsonNode = ret.get(key); + value = jsonNode != null ? jsonNode : NullNode.getInstance(); + ret.set(key, entry.getValue().apply(value)); } ret.remove(removedMembers);