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
The {@code equivalent} method implements an equivalence relation on object references: - * - *
The {@code hash} has the following properties: - *
The {@code equivalent} method implements an equivalence relation on object references: + * + *
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}. + * + *
The {@code hash} has the following properties: + *
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. + * + *
For example: + * + *
{@code + * Equivalence+ * + *SAME_AGE = Equivalence.equals().onResultOf(GET_PERSON_AGE);}
{@code function} will never be invoked with a null value. + * + *
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 For example, given an {@link Equivalence} for {@link String strings} named {@code equiv}
+ * that tests equivalence using their lengths:
+ *
+ * Note in particular that an equivalence wrapper is never equal to the object it wraps.
+ *
+ * Wrapper wrap(@Nullable S reference) {
+ return new Wrapper(this, reference);
+ }
+
+ /**
+ * Wraps an object so that {@link #equals(Object)} and {@link #hashCode()} delegate to an
+ * {@link Equivalence}.
+ *
+ * {@code
+ * equiv.wrap("a").equals(equiv.wrap("b")) // true
+ * equiv.wrap("a").equals(equiv.wrap("hello")) // false}
+ *
+ * {@code
+ * equiv.wrap(obj).equals(obj) // always false}
+ */
+ public static final class Wrapper