From dbe3357c23420a450f3044c0bc93cda713dbee90 Mon Sep 17 00:00:00 2001 From: soberich <25544967+soberich@users.noreply.github.com> Date: Fri, 30 Nov 2018 00:15:30 +0300 Subject: [PATCH] Rebase on upstream master, resolve errorprone. Shadow Google classes. Use diamonds from Java 7. --- project.gradle | 4 +- .../com/github/fge/jackson/JacksonUtils.java | 4 +- .../com/github/fge/jackson/JsonNumEquals.java | 69 +--- .../java/com/github/fge/jackson/NodeType.java | 4 +- .../com/google/common/base/Equivalence.java | 333 ++++++++++++++++++ .../com/google/common/base/Function.java | 64 ++++ .../common/base/FunctionalEquivalence.java | 77 ++++ .../common/base/PairwiseEquivalence.java | 79 +++++ .../com/google/common/base/Predicate.java | 62 ++++ .../fge/jackson/jsonpointer/JsonPointer.java | 8 +- .../fge/jackson/jsonpointer/TreePointer.java | 6 +- .../fge/jackson/JsonNodeReaderTest.java | 9 +- .../github/fge/jackson/JsonNumEqualsTest.java | 2 +- .../fge/jackson/SampleNodeProvider.java | 6 +- .../jsonpointer/JsonNodeResolverTest.java | 2 +- .../jackson/jsonpointer/JsonPointerTest.java | 6 +- .../jackson/jsonpointer/TreePointerTest.java | 4 +- 17 files changed, 649 insertions(+), 90 deletions(-) create mode 100644 src/main/java/com/github/fge/jackson/com/google/common/base/Equivalence.java create mode 100644 src/main/java/com/github/fge/jackson/com/google/common/base/Function.java create mode 100644 src/main/java/com/github/fge/jackson/com/google/common/base/FunctionalEquivalence.java create mode 100644 src/main/java/com/github/fge/jackson/com/google/common/base/PairwiseEquivalence.java create mode 100644 src/main/java/com/github/fge/jackson/com/google/common/base/Predicate.java diff --git a/project.gradle b/project.gradle index d93a5be..eb944d3 100644 --- a/project.gradle +++ b/project.gradle @@ -31,8 +31,8 @@ targetCompatibility = JavaVersion.VERSION_1_7; // defaults to sourceCompatibilit dependencies { implementation(group: "com.fasterxml.jackson.core", name: "jackson-databind", version: "2.9.9"); implementation(group: "com.github.fge", name: "msg-simple", version: "1.1"); - implementation(group: "com.google.code.findbugs", name: "jsr305", version: "2.0.1"); - testImplementation(group: "org.testng", name: "testng", version: "6.8.7") { + implementation(group: "com.google.code.findbugs", name: "jsr305", version: "3.0.2"); + 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"); diff --git a/src/main/java/com/github/fge/jackson/JacksonUtils.java b/src/main/java/com/github/fge/jackson/JacksonUtils.java index 85c41ff..5750d77 100644 --- a/src/main/java/com/github/fge/jackson/JacksonUtils.java +++ b/src/main/java/com/github/fge/jackson/JacksonUtils.java @@ -99,7 +99,7 @@ public static Map<String, JsonNode> asMap(final JsonNode node) return Collections.emptyMap(); final Iterator<Map.Entry<String, JsonNode>> iterator = node.fields(); - final Map<String, JsonNode> ret = new HashMap<String, JsonNode>(); + final Map<String, JsonNode> ret = new HashMap<>(); Map.Entry<String, JsonNode> entry; @@ -108,7 +108,7 @@ public static Map<String, JsonNode> asMap(final JsonNode node) ret.put(entry.getKey(), entry.getValue()); } - return ret; + return Collections.unmodifiableMap(ret); } /** diff --git a/src/main/java/com/github/fge/jackson/JsonNumEquals.java b/src/main/java/com/github/fge/jackson/JsonNumEquals.java index f098d4b..e061c8e 100644 --- a/src/main/java/com/github/fge/jackson/JsonNumEquals.java +++ b/src/main/java/com/github/fge/jackson/JsonNumEquals.java @@ -20,8 +20,8 @@ package com.github.fge.jackson; import com.fasterxml.jackson.databind.JsonNode; +import com.github.fge.jackson.com.google.common.base.Equivalence; -import javax.annotation.Nullable; import java.util.HashSet; import java.util.Iterator; import java.util.Map; @@ -41,50 +41,21 @@ * kind of equality.</p> */ public final class JsonNumEquals + extends Equivalence<JsonNode> { - private static final JsonNumEquals INSTANCE + private static final Equivalence<JsonNode> INSTANCE = new JsonNumEquals(); private JsonNumEquals() { } - public static JsonNumEquals getInstance() + public static Equivalence<JsonNode> getInstance() { return INSTANCE; } - /** - * Returns {@code true} if the given objects are considered equivalent. - * - * <p>The {@code equivalent} method implements an equivalence relation on object references: - * - * <ul> - * <li>It is <i>reflexive</i>: for any reference {@code x}, including null, {@code - * equivalent(x, x)} returns {@code true}. - * <li>It is <i>symmetric</i>: for any references {@code x} and {@code y}, {@code - * equivalent(x, y) == equivalent(y, x)}. - * <li>It is <i>transitive</i>: for any references {@code x}, {@code y}, and {@code z}, if - * {@code equivalent(x, y)} returns {@code true} and {@code equivalent(y, z)} returns {@code - * true}, then {@code equivalent(x, z)} returns {@code true}. - * <li>It is <i>consistent</i>: for any references {@code x} and {@code y}, multiple invocations - * of {@code equivalent(x, y)} consistently return {@code true} or consistently return {@code - * false} (provided that neither {@code x} nor {@code y} is modified). - * </ul> - * @param a x - * @param b y - * @return whether nodes are equal according to IETF RFCs - */ - public final boolean equivalent(@Nullable JsonNode a, @Nullable JsonNode b) { - if (a == b) { - return true; - } - if (a == null || b == null) { - return false; - } - return doEquivalent(a, b); - } - + @Override protected boolean doEquivalent(final JsonNode a, final JsonNode b) { /* @@ -122,31 +93,7 @@ protected boolean doEquivalent(final JsonNode a, final JsonNode b) return typeA == NodeType.ARRAY ? arrayEquals(a, b) : objectEquals(a, b); } - /** - * Returns a hash code for {@code t}. - * - * <p>The {@code hash} has the following properties: - * <ul> - * <li>It is <i>consistent</i>: for any reference {@code x}, multiple invocations of - * {@code hash(x}} consistently return the same value provided {@code x} remains unchanged - * according to the definition of the equivalence. The hash need not remain consistent from - * one execution of an application to another execution of the same application. - * <li>It is <i>distributable across equivalence</i>: for any references {@code x} and {@code y}, - * if {@code equivalent(x, y)}, then {@code hash(x) == hash(y)}. It is <i>not</i> necessary - * that the hash be distributable across <i>inequivalence</i>. If {@code equivalence(x, y)} - * is false, {@code hash(x) == hash(y)} may still be true. - * <li>{@code hash(null)} is {@code 0}. - * </ul> - * @param t node to hash - * @return hash - */ - public final int hash(@Nullable JsonNode t) { - if (t == null) { - return 0; - } - return doHash(t); - } - + @Override protected int doHash(final JsonNode t) { /* @@ -236,7 +183,7 @@ private boolean objectEquals(final JsonNode a, final JsonNode b) /* * Grab the key set from the first node */ - final Set<String> keys = new HashSet<String>(); + final Set<String> keys = new HashSet<>(); Iterator<String> iterator1 = a.fieldNames(); while (iterator1.hasNext()) { final String next = iterator1.next(); @@ -251,7 +198,7 @@ private boolean objectEquals(final JsonNode a, final JsonNode b) * Grab the key set from the second node, and see if both sets are the * same. If not, objects are not equal, no need to check for children. */ - final Set<String> set = new HashSet<String>(); + final Set<String> set = new HashSet<>(); Iterator<String> iterator2 = b.fieldNames(); while (iterator2.hasNext()) { final String next = iterator2.next(); diff --git a/src/main/java/com/github/fge/jackson/NodeType.java b/src/main/java/com/github/fge/jackson/NodeType.java index ea15551..67ddf86 100644 --- a/src/main/java/com/github/fge/jackson/NodeType.java +++ b/src/main/java/com/github/fge/jackson/NodeType.java @@ -86,7 +86,7 @@ public enum NodeType * #getNodeType(JsonNode)}) */ private static final Map<JsonToken, NodeType> TOKEN_MAP - = new EnumMap<JsonToken, NodeType>(JsonToken.class); + = new EnumMap<>(JsonToken.class); static { TOKEN_MAP.put(JsonToken.START_ARRAY, ARRAY); @@ -99,7 +99,7 @@ public enum NodeType TOKEN_MAP.put(JsonToken.VALUE_STRING, STRING); final Map<String, NodeType> builder - = new HashMap<String, NodeType>(); + = new HashMap<>(); for (final NodeType type: NodeType.values()) builder.put(type.name, type); diff --git a/src/main/java/com/github/fge/jackson/com/google/common/base/Equivalence.java b/src/main/java/com/github/fge/jackson/com/google/common/base/Equivalence.java new file mode 100644 index 0000000..11633dc --- /dev/null +++ b/src/main/java/com/github/fge/jackson/com/google/common/base/Equivalence.java @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2010 The Guava Authors + * + * Licensed 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 com.github.fge.jackson.com.google.common.base; + +import javax.annotation.Nullable; +import java.io.Serializable; +import java.util.Arrays; + +/** + * A strategy for determining whether two instances are considered equivalent. Examples of + * equivalences are the {@linkplain #identity() identity equivalence} and {@linkplain #equals equals + * equivalence}. + * + * @author Bob Lee + * @author Ben Yu + * @author Gregory Kick + * @author <a href="mailto:43personal@gmail.com">soberich</a> on 29-Nov-18 + */ +public abstract class Equivalence<T> { + /** + * Constructor for use by subclasses. + */ + protected Equivalence() {} + + /** + * Returns {@code true} if the given objects are considered equivalent. + * + * <p>The {@code equivalent} method implements an equivalence relation on object references: + * + * <ul> + * <li>It is <i>reflexive</i>: for any reference {@code x}, including null, {@code + * equivalent(x, x)} returns {@code true}. + * <li>It is <i>symmetric</i>: for any references {@code x} and {@code y}, {@code + * equivalent(x, y) == equivalent(y, x)}. + * <li>It is <i>transitive</i>: for any references {@code x}, {@code y}, and {@code z}, if + * {@code equivalent(x, y)} returns {@code true} and {@code equivalent(y, z)} returns {@code + * true}, then {@code equivalent(x, z)} returns {@code true}. + * <li>It is <i>consistent</i>: for any references {@code x} and {@code y}, multiple invocations + * of {@code equivalent(x, y)} consistently return {@code true} or consistently return {@code + * false} (provided that neither {@code x} nor {@code y} is modified). + * </ul> + */ + public final boolean equivalent(@Nullable T a, @Nullable T b) { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + return doEquivalent(a, b); + } + + /** + * Returns {@code true} if {@code a} and {@code b} are considered equivalent. + * + * <p>Called by {@link #equivalent}. {@code a} and {@code b} are not the same + * object and are not nulls. + */ + protected abstract boolean doEquivalent(T a, T b); + + /** + * Returns a hash code for {@code t}. + * + * <p>The {@code hash} has the following properties: + * <ul> + * <li>It is <i>consistent</i>: for any reference {@code x}, multiple invocations of + * {@code hash(x}} consistently return the same value provided {@code x} remains unchanged + * according to the definition of the equivalence. The hash need not remain consistent from + * one execution of an application to another execution of the same application. + * <li>It is <i>distributable across equivalence</i>: for any references {@code x} and {@code y}, + * if {@code equivalent(x, y)}, then {@code hash(x) == hash(y)}. It is <i>not</i> necessary + * that the hash be distributable across <i>inequivalence</i>. If {@code equivalence(x, y)} + * is false, {@code hash(x) == hash(y)} may still be true. + * <li>{@code hash(null)} is {@code 0}. + * </ul> + */ + public final int hash(@Nullable T t) { + if (t == null) { + return 0; + } + return doHash(t); + } + + /** + * Returns a hash code for non-null object {@code t}. + * + * <p>Called by {@link #hash}. + */ + protected abstract int doHash(T t); + + /** + * Returns a new equivalence relation for {@code F} which evaluates equivalence by first applying + * {@code function} to the argument, then evaluating using {@code this}. That is, for any pair of + * non-null objects {@code x} and {@code y}, {@code + * equivalence.onResultOf(function).equivalent(a, b)} is true if and only if {@code + * equivalence.equivalent(function.apply(a), function.apply(b))} is true. + * + * <p>For example: + * + * <pre> {@code + * Equivalence<Person> SAME_AGE = Equivalence.equals().onResultOf(GET_PERSON_AGE);}</pre> + * + * <p>{@code function} will never be invoked with a null value. + * + * <p>Note that {@code function} must be consistent according to {@code this} equivalence + * relation. That is, invoking {@code com.google.common.base.Function#apply} multiple times for a given value must return + * equivalent results. + * For example, {@code Equivalence.identity().onResultOf(Functions.toStringFunction())} is broken + * because it's not guaranteed that {@link Object#toString}) always returns the same string + * instance. + */ + public final <F> Equivalence<F> onResultOf(Function<F, ? extends T> function) { + return new FunctionalEquivalence<>(function, this); + } + + /** + * Returns a wrapper of {@code reference} that implements + * {@link Wrapper#equals(Object) Object.equals()} such that + * {@code wrap(a).equals(wrap(b))} if and only if {@code equivalent(a, b)}. + */ + public final <S extends T> Wrapper<S> wrap(@Nullable S reference) { + return new Wrapper<S>(this, reference); + } + + /** + * Wraps an object so that {@link #equals(Object)} and {@link #hashCode()} delegate to an + * {@link Equivalence}. + * + * <p>For example, given an {@link Equivalence} for {@link String strings} named {@code equiv} + * that tests equivalence using their lengths: + * + * <pre> {@code + * equiv.wrap("a").equals(equiv.wrap("b")) // true + * equiv.wrap("a").equals(equiv.wrap("hello")) // false}</pre> + * + * <p>Note in particular that an equivalence wrapper is never equal to the object it wraps. + * + * <pre> {@code + * equiv.wrap(obj).equals(obj) // always false}</pre> + */ + public static final class Wrapper<T> implements Serializable { + private final Equivalence<? super T> equivalence; + @Nullable private final T reference; + + private Wrapper(Equivalence<? super T> equivalence, @Nullable T reference) { + if (equivalence == null) { + throw new NullPointerException(); + } + this.equivalence = equivalence; + this.reference = reference; + } + + /** Returns the (possibly null) reference wrapped by this instance. */ + @Nullable public T get() { + return reference; + } + + /** + * Returns {@code true} if {@link Equivalence#equivalent(Object, Object)} applied to the wrapped + * references is {@code true} and both wrappers use the {@link Object#equals(Object) same} + * equivalence. + */ + @Override public boolean equals(@Nullable Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof Wrapper) { + Wrapper<?> that = (Wrapper<?>) obj; // note: not necessarily a Wrapper<T> + + if (this.equivalence.equals(that.equivalence)) { + /* + * We'll accept that as sufficient "proof" that either equivalence should be able to + * handle either reference, so it's safe to circumvent compile-time type checking. + */ + @SuppressWarnings("unchecked") + Equivalence<Object> equivalence = (Equivalence<Object>) this.equivalence; + return equivalence.equivalent(this.reference, that.reference); + } + } + return false; + } + + /** + * Returns the result of {@link Equivalence#hash(Object)} applied to the wrapped reference. + */ + @Override public int hashCode() { + return equivalence.hash(reference); + } + + /** + * Returns a string representation for this equivalence wrapper. The form of this string + * representation is not specified. + */ + @Override public String toString() { + return equivalence + ".wrap(" + reference + ")"; + } + + private static final long serialVersionUID = 0; + } + + /** + * Returns an equivalence over iterables based on the equivalence of their elements. More + * specifically, two iterables are considered equivalent if they both contain the same number of + * elements, and each pair of corresponding elements is equivalent according to + * {@code this}. Null iterables are equivalent to one another. + * + * <p>Note that this method performs a similar function for equivalences as {@code + * com.google.common.collect.Ordering#lexicographical} does for orderings. + */ + public final <S extends T> Equivalence<Iterable<S>> pairwise() { + // Ideally, the returned equivalence would support Iterable<? extends T>. However, + // the need for this is so rare that it's not worth making callers deal with the ugly wildcard. + return new PairwiseEquivalence<>(this); + } + + /** + * Returns a predicate that evaluates to true if and only if the input is + * equivalent to {@code target} according to this equivalence relation. + */ + public final Predicate<T> equivalentTo(@Nullable T target) { + return new EquivalentToPredicate<>(this, target); + } + + private static final class EquivalentToPredicate<T> implements Predicate<T>, Serializable { + + private final Equivalence<T> equivalence; + @Nullable private final T target; + + EquivalentToPredicate(Equivalence<T> equivalence, @Nullable T target) { + if (equivalence == null) { + throw new NullPointerException(); + } + this.equivalence = equivalence; + this.target = target; + } + + @Override public boolean apply(@Nullable T input) { + return equivalence.equivalent(input, target); + } + + @Override public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof EquivalentToPredicate) { + EquivalentToPredicate<?> that = (EquivalentToPredicate<?>) obj; + return (equivalence.equals(that.equivalence) + && (target == that.target)) || ((target != null) && target.equals(that.target)); + } + return false; + } + + @Override public int hashCode() { + return Arrays.hashCode(new Object[]{equivalence, target}); + } + + @Override public String toString() { + return equivalence + ".equivalentTo(" + target + ")"; + } + + private static final long serialVersionUID = 0; + } + + /** + * Returns an equivalence that delegates to {@link Object#equals} and {@link Object#hashCode}. + * {@link Equivalence#equivalent} returns {@code true} if both values are null, or if neither + * value is null and {@link Object#equals} returns {@code true}. {@link Equivalence#hash} returns + * {@code 0} if passed a null value. + */ + public static Equivalence<Object> equals() { + return Equals.INSTANCE; + } + + /** + * Returns an equivalence that uses {@code ==} to compare values and {@link + * System#identityHashCode(Object)} to compute the hash code. {@link Equivalence#equivalent} + * returns {@code true} if {@code a == b}, including in the case that a and b are both null. + */ + public static Equivalence<Object> identity() { + return Identity.INSTANCE; + } + + static final class Equals extends Equivalence<Object> + implements Serializable { + + static final Equals INSTANCE = new Equals(); + + @Override protected boolean doEquivalent(Object a, Object b) { + return a.equals(b); + } + @Override public int doHash(Object o) { + return o.hashCode(); + } + + private Object readResolve() { + return INSTANCE; + } + private static final long serialVersionUID = 1; + } + + static final class Identity extends Equivalence<Object> + implements Serializable { + + static final Identity INSTANCE = new Identity(); + + @Override protected boolean doEquivalent(Object a, Object b) { + return false; + } + + @Override protected int doHash(Object o) { + return System.identityHashCode(o); + } + + private Object readResolve() { + return INSTANCE; + } + private static final long serialVersionUID = 1; + } +} diff --git a/src/main/java/com/github/fge/jackson/com/google/common/base/Function.java b/src/main/java/com/github/fge/jackson/com/google/common/base/Function.java new file mode 100644 index 0000000..fb53cd2 --- /dev/null +++ b/src/main/java/com/github/fge/jackson/com/google/common/base/Function.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed 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 com.github.fge.jackson.com.google.common.base; + +import javax.annotation.Nullable; + +/** + * Determines an output value based on an input value. + * + * <p>The {@code com.google.common.base.Functions} class provides common functions and related utilites. + * + * <p>See the Guava User Guide article on <a href= + * "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the use of {@code + * Function}</a>. + * + * @author Kevin Bourrillion + * @author <a href="mailto:43personal@gmail.com">soberich</a> on 29-Nov-18 + * @since 1.10 (imported from Google Collections Library) + */ +public interface Function<F, T> { + /** + * Returns the result of applying this function to {@code input}. This method is <i>generally + * expected</i>, but not absolutely required, to have the following properties: + * + * <ul> + * <li>Its execution does not cause any observable side effects. + * <li>The computation is <i>consistent with equals</i>; that is, {@code com.google.common.base.Objects#equal + * Objects.equal}{@code (a, b)} implies that {@code Objects.equal(function.apply(a), + * function.apply(b))}. + * </ul> + * + * @throws NullPointerException if {@code input} is null and this function does not accept null + * arguments + */ + @Nullable + T apply(@Nullable F input); + + /** + * Indicates whether another object is equal to this function. + * + * <p>Most implementations will have no reason to override the behavior of {@link Object#equals}. + * However, an implementation may also choose to return {@code true} whenever {@code object} is a + * {@link Function} that it considers <i>interchangeable</i> with this one. "Interchangeable" + * <i>typically</i> means that {@code Objects.equal(this.apply(f), that.apply(f))} is true for all + * {@code f} of type {@code F}. Note that a {@code false} result from this method does not imply + * that the functions are known <i>not</i> to be interchangeable. + */ + @Override + boolean equals(@Nullable Object object); +} diff --git a/src/main/java/com/github/fge/jackson/com/google/common/base/FunctionalEquivalence.java b/src/main/java/com/github/fge/jackson/com/google/common/base/FunctionalEquivalence.java new file mode 100644 index 0000000..423a096 --- /dev/null +++ b/src/main/java/com/github/fge/jackson/com/google/common/base/FunctionalEquivalence.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2011 The Guava Authors + * + * Licensed 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 com.github.fge.jackson.com.google.common.base; + +import javax.annotation.Nullable; +import java.io.Serializable; +import java.util.Arrays; + +/** + * Equivalence applied on functional result. + * + * @author Bob Lee + * @author <a href="mailto:43personal@gmail.com">soberich</a> on 29-Nov-18 + * @since 1.10 + */ +final class FunctionalEquivalence<F, T> extends Equivalence<F> + implements Serializable { + + private static final long serialVersionUID = 0; + + private final Function<F, ? extends T> function; + private final Equivalence<T> resultEquivalence; + + FunctionalEquivalence( + Function<F, ? extends T> function, Equivalence<T> resultEquivalence) { + if (function == null) { + throw new NullPointerException(); + } + this.function = function; + if (resultEquivalence == null) { + throw new NullPointerException(); + } + this.resultEquivalence = resultEquivalence; + } + + @Override protected boolean doEquivalent(F a, F b) { + return resultEquivalence.equivalent(function.apply(a), function.apply(b)); + } + + @Override protected int doHash(F a) { + return resultEquivalence.hash(function.apply(a)); + } + + @Override public boolean equals(@Nullable Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof FunctionalEquivalence) { + FunctionalEquivalence<?, ?> that = (FunctionalEquivalence<?, ?>) obj; + return function.equals(that.function) + && resultEquivalence.equals(that.resultEquivalence); + } + return false; + } + + @Override public int hashCode() { + return Arrays.hashCode(new Object[]{function, resultEquivalence}); + } + + @Override public String toString() { + return resultEquivalence + ".onResultOf(" + function + ")"; + } +} diff --git a/src/main/java/com/github/fge/jackson/com/google/common/base/PairwiseEquivalence.java b/src/main/java/com/github/fge/jackson/com/google/common/base/PairwiseEquivalence.java new file mode 100644 index 0000000..d1d2f19 --- /dev/null +++ b/src/main/java/com/github/fge/jackson/com/google/common/base/PairwiseEquivalence.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011 The Guava Authors + * + * Licensed 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 com.github.fge.jackson.com.google.common.base; + +import javax.annotation.Nullable; +import java.io.Serializable; +import java.util.Iterator; + +final class PairwiseEquivalence<T> extends Equivalence<Iterable<T>> + implements Serializable { + + final Equivalence<? super T> elementEquivalence; + + PairwiseEquivalence(Equivalence<? super T> elementEquivalence) { + if (elementEquivalence == null) { + throw new NullPointerException(); + } + this.elementEquivalence = elementEquivalence; + } + + @Override + protected boolean doEquivalent(Iterable<T> iterableA, Iterable<T> iterableB) { + Iterator<T> iteratorA = iterableA.iterator(); + Iterator<T> iteratorB = iterableB.iterator(); + + while (iteratorA.hasNext() && iteratorB.hasNext()) { + if (!elementEquivalence.equivalent(iteratorA.next(), iteratorB.next())) { + return false; + } + } + + return !iteratorA.hasNext() && !iteratorB.hasNext(); + } + + @Override + protected int doHash(Iterable<T> iterable) { + int hash = 78721; + for (T element : iterable) { + hash = hash * 24943 + elementEquivalence.hash(element); + } + return hash; + } + + @Override + public boolean equals(@Nullable Object object) { + if (object instanceof PairwiseEquivalence) { + PairwiseEquivalence<?> that = (PairwiseEquivalence<?>) object; + return this.elementEquivalence.equals(that.elementEquivalence); + } + + return false; + } + + @Override + public int hashCode() { + return elementEquivalence.hashCode() ^ 0x46a3eb07; + } + + @Override + public String toString() { + return elementEquivalence + ".pairwise()"; + } + + private static final long serialVersionUID = 1; +} diff --git a/src/main/java/com/github/fge/jackson/com/google/common/base/Predicate.java b/src/main/java/com/github/fge/jackson/com/google/common/base/Predicate.java new file mode 100644 index 0000000..6ffa6d0 --- /dev/null +++ b/src/main/java/com/github/fge/jackson/com/google/common/base/Predicate.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed 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 com.github.fge.jackson.com.google.common.base; + +import javax.annotation.Nullable; + +/** + * Determines a true or false value for a given input. + * + * <p>The {@code com.google.common.base.Predicates} class provides common predicates and related utilities. + * + * <p>See the Guava User Guide article on <a href= + * "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the use of {@code + * Predicate}</a>. + * + * @author Kevin Bourrillion + * @since 2.0 (imported from Google Collections Library) + */ +public interface Predicate<T> { + /** + * Returns the result of applying this predicate to {@code input}. This method is <i>generally + * expected</i>, but not absolutely required, to have the following properties: + * + * <ul> + * <li>Its execution does not cause any observable side effects. + * <li>The computation is <i>consistent with equals</i>; that is, {@code com.google.common.base.Objects#equal + * Objects.equal}{@code (a, b)} implies that {@code predicate.apply(a) == + * predicate.apply(b))}. + * </ul> + * + * @throws NullPointerException if {@code input} is null and this predicate does not accept null + * arguments + */ + boolean apply(@Nullable T input); + + /** + * Indicates whether another object is equal to this predicate. + * + * <p>Most implementations will have no reason to override the behavior of {@link Object#equals}. + * However, an implementation may also choose to return {@code true} whenever {@code object} is a + * {@link Predicate} that it considers <i>interchangeable</i> with this one. "Interchangeable" + * <i>typically</i> means that {@code this.apply(t) == that.apply(t)} for all {@code t} of type + * {@code T}). Note that a {@code false} result from this method does not imply that the + * predicates are known <i>not</i> to be interchangeable. + */ + @Override + boolean equals(@Nullable Object object); +} diff --git a/src/main/java/com/github/fge/jackson/jsonpointer/JsonPointer.java b/src/main/java/com/github/fge/jackson/jsonpointer/JsonPointer.java index 670e50b..0aae6a5 100644 --- a/src/main/java/com/github/fge/jackson/jsonpointer/JsonPointer.java +++ b/src/main/java/com/github/fge/jackson/jsonpointer/JsonPointer.java @@ -72,7 +72,7 @@ public static JsonPointer empty() */ public static JsonPointer of(final Object first, final Object... other) { - final List<ReferenceToken> tokens = new ArrayList<ReferenceToken>(); + final List<ReferenceToken> tokens = new ArrayList<>(); tokens.add(ReferenceToken.fromRaw(first.toString())); @@ -120,7 +120,7 @@ public JsonPointer append(final String raw) final ReferenceToken refToken = ReferenceToken.fromRaw(raw); final JsonNodeResolver resolver = new JsonNodeResolver(refToken); final List<TokenResolver<JsonNode>> list - = new ArrayList<TokenResolver<JsonNode>>(); + = new ArrayList<>(); for (final TokenResolver<JsonNode> tokenResolver : tokenResolvers) { if (tokenResolver != null) { list.add(tokenResolver); @@ -154,7 +154,7 @@ public JsonPointer append(final JsonPointer other) { BUNDLE.checkNotNull(other, "nullInput"); final List<TokenResolver<JsonNode>> list - = new ArrayList<TokenResolver<JsonNode>>(); + = new ArrayList<>(); for (final TokenResolver<JsonNode> tokenResolver : tokenResolvers) { if (tokenResolver != null) { list.add(tokenResolver); @@ -191,7 +191,7 @@ public JsonPointer parent() private static List<TokenResolver<JsonNode>> fromTokens( final List<ReferenceToken> tokens) { - final List<TokenResolver<JsonNode>> list = new ArrayList<TokenResolver<JsonNode>>(); + final List<TokenResolver<JsonNode>> list = new ArrayList<>(); for (final ReferenceToken token: tokens) list.add(new JsonNodeResolver(token)); return list; diff --git a/src/main/java/com/github/fge/jackson/jsonpointer/TreePointer.java b/src/main/java/com/github/fge/jackson/jsonpointer/TreePointer.java index df82ef8..8d6daee 100644 --- a/src/main/java/com/github/fge/jackson/jsonpointer/TreePointer.java +++ b/src/main/java/com/github/fge/jackson/jsonpointer/TreePointer.java @@ -92,7 +92,7 @@ protected TreePointer(final T missing, final List<TokenResolver<T>> tokenResolvers) { this.missing = missing; - this.tokenResolvers = Collections.unmodifiableList(new ArrayList<TokenResolver<T>>(tokenResolvers)); + this.tokenResolvers = Collections.unmodifiableList(new ArrayList<>(tokenResolvers)); } /** @@ -174,7 +174,7 @@ public final boolean equals(final Object obj) return false; if (this == obj) return true; - if (getClass() != obj.getClass()) + if (!(obj instanceof TreePointer)) return false; final TreePointer<?> other = (TreePointer<?>) obj; return tokenResolvers.equals(other.tokenResolvers); @@ -206,7 +206,7 @@ protected static List<ReferenceToken> tokensFromInput(final String input) throws JsonPointerException { String s = BUNDLE.checkNotNull(input, "nullInput"); - final List<ReferenceToken> ret = new ArrayList<ReferenceToken>(); + final List<ReferenceToken> ret = new ArrayList<>(); String cooked; int index; char c; diff --git a/src/test/java/com/github/fge/jackson/JsonNodeReaderTest.java b/src/test/java/com/github/fge/jackson/JsonNodeReaderTest.java index 7a60cd4..2965822 100644 --- a/src/test/java/com/github/fge/jackson/JsonNodeReaderTest.java +++ b/src/test/java/com/github/fge/jackson/JsonNodeReaderTest.java @@ -33,6 +33,7 @@ import java.io.Reader; import java.io.StringReader; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -70,7 +71,7 @@ public void readerIsClosedOnRead() @DataProvider public Iterator<Object[]> getMalformedData() { - final List<Object[]> list = new ArrayList<Object[]>(); + final List<Object[]> list = new ArrayList<>(); list.add(new Object[] { "", "read.noContent"}); list.add(new Object[] { "[]{}", "read.trailingData"}); @@ -104,11 +105,7 @@ private static Supplier<InputStream> provideInputStream(final String input) @Override public InputStream get() { - try { - return new ByteArrayInputStream(input.getBytes("UTF-8")); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("Unhandled exception", e); - } + return new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)); } }; } diff --git a/src/test/java/com/github/fge/jackson/JsonNumEqualsTest.java b/src/test/java/com/github/fge/jackson/JsonNumEqualsTest.java index cecb942..af4d068 100644 --- a/src/test/java/com/github/fge/jackson/JsonNumEqualsTest.java +++ b/src/test/java/com/github/fge/jackson/JsonNumEqualsTest.java @@ -49,7 +49,7 @@ public void initData() @DataProvider public Iterator<Object[]> getInputs() { - final List<Object[]> list = new ArrayList<Object[]>(); + final List<Object[]> list = new ArrayList<>(); JsonNode reference; diff --git a/src/test/java/com/github/fge/jackson/SampleNodeProvider.java b/src/test/java/com/github/fge/jackson/SampleNodeProvider.java index ec03e32..23817f7 100644 --- a/src/test/java/com/github/fge/jackson/SampleNodeProvider.java +++ b/src/test/java/com/github/fge/jackson/SampleNodeProvider.java @@ -35,7 +35,7 @@ private SampleNodeProvider() } static { - SAMPLE_DATA = new EnumMap<NodeType, JsonNode>(NodeType.class); + SAMPLE_DATA = new EnumMap<>(NodeType.class); SAMPLE_DATA.put(NodeType.ARRAY, FACTORY.arrayNode()); SAMPLE_DATA.put(NodeType.BOOLEAN, FACTORY.booleanNode(true)); @@ -52,10 +52,10 @@ private SampleNodeProvider() // differ... public static Iterator<Object[]> getSamples(final EnumSet<NodeType> types) { - final Map<NodeType, JsonNode> map = new EnumMap<NodeType, JsonNode>(SAMPLE_DATA); + final Map<NodeType, JsonNode> map = new EnumMap<>(SAMPLE_DATA); map.keySet().retainAll(types); - final ArrayList<Object[]> samples = new ArrayList<Object[]>(); + final List<Object[]> samples = new ArrayList<>(); for (final JsonNode input : map.values()) { samples.add(new Object[] { input }); } diff --git a/src/test/java/com/github/fge/jackson/jsonpointer/JsonNodeResolverTest.java b/src/test/java/com/github/fge/jackson/jsonpointer/JsonNodeResolverTest.java index d4a042f..6f22fda 100644 --- a/src/test/java/com/github/fge/jackson/jsonpointer/JsonNodeResolverTest.java +++ b/src/test/java/com/github/fge/jackson/jsonpointer/JsonNodeResolverTest.java @@ -104,7 +104,7 @@ public void resolvingArrayIndicesWorks() @DataProvider public Iterator<Object[]> invalidIndices() { - final List<Object[]> list = new ArrayList<Object[]>(); + final List<Object[]> list = new ArrayList<>(); list.add(new Object[] { "-1" }); list.add(new Object[] { "232398087298731987987232" }); diff --git a/src/test/java/com/github/fge/jackson/jsonpointer/JsonPointerTest.java b/src/test/java/com/github/fge/jackson/jsonpointer/JsonPointerTest.java index c04fded..be19a61 100644 --- a/src/test/java/com/github/fge/jackson/jsonpointer/JsonPointerTest.java +++ b/src/test/java/com/github/fge/jackson/jsonpointer/JsonPointerTest.java @@ -66,7 +66,7 @@ public void cannotAppendNullPointer() @DataProvider public Iterator<Object[]> rawPointers() { - final List<Object[]> list = new ArrayList<Object[]>(); + final List<Object[]> list = new ArrayList<>(); final JsonNode testNode = testData.get("pointers"); final Map<String, JsonNode> map = JacksonUtils.asMap(testNode); @@ -89,7 +89,7 @@ public void rawPointerResolvingWorks(final String input, @DataProvider public Iterator<Object[]> uriPointers() { - final List<Object[]> list = new ArrayList<Object[]>(); + final List<Object[]> list = new ArrayList<>(); final JsonNode testNode = testData.get("uris"); final Map<String, JsonNode> map = JacksonUtils.asMap(testNode); @@ -181,7 +181,7 @@ public void staticConstructionFromTokensWorks() @DataProvider public Iterator<Object[]> parentTestData() { - final List<Object[]> list = new ArrayList<Object[]>(); + final List<Object[]> list = new ArrayList<>(); // Empty list.add(new Object[] { JsonPointer.empty(), JsonPointer.empty() }); diff --git a/src/test/java/com/github/fge/jackson/jsonpointer/TreePointerTest.java b/src/test/java/com/github/fge/jackson/jsonpointer/TreePointerTest.java index a42a406..2edc050 100644 --- a/src/test/java/com/github/fge/jackson/jsonpointer/TreePointerTest.java +++ b/src/test/java/com/github/fge/jackson/jsonpointer/TreePointerTest.java @@ -154,7 +154,7 @@ public void gettingPathOfMissingNodeReturnsMissingNode() @Test public void treePointerCanTellWhetherItIsEmpty() { - final List<TokenResolver<TreeNode>> list = new ArrayList<TokenResolver<TreeNode>>(); + final List<TokenResolver<TreeNode>> list = new ArrayList<>(); assertTrue(new DummyPointer(null, list).isEmpty()); @@ -168,7 +168,7 @@ public void treePointerCanTellWhetherItIsEmpty() @Test public void treeIsUnalteredWhenOriginalListIsAltered() { - final List<TokenResolver<TreeNode>> list = new ArrayList<TokenResolver<TreeNode>>(); + final List<TokenResolver<TreeNode>> list = new ArrayList<>(); final DummyPointer dummy = new DummyPointer(null, list); @SuppressWarnings("unchecked")