diff --git a/core/src/main/java/org/jboss/jandex/AnnotationInstance.java b/core/src/main/java/org/jboss/jandex/AnnotationInstance.java index 82404ee6..941ab8e6 100644 --- a/core/src/main/java/org/jboss/jandex/AnnotationInstance.java +++ b/core/src/main/java/org/jboss/jandex/AnnotationInstance.java @@ -527,4 +527,11 @@ public int equivalenceHashCode() { result = 31 * result + Arrays.hashCode(values); return result; } + + /** + * Returns an {@linkplain AnnotationInstanceEquivalenceProxy equivalence proxy} for this annotation instance. + */ + public AnnotationInstanceEquivalenceProxy createEquivalenceProxy() { + return new AnnotationInstanceEquivalenceProxy(this); + } } diff --git a/core/src/main/java/org/jboss/jandex/AnnotationInstanceEquivalenceProxy.java b/core/src/main/java/org/jboss/jandex/AnnotationInstanceEquivalenceProxy.java new file mode 100644 index 00000000..cdceba37 --- /dev/null +++ b/core/src/main/java/org/jboss/jandex/AnnotationInstanceEquivalenceProxy.java @@ -0,0 +1,43 @@ +package org.jboss.jandex; + +import java.util.Objects; + +/** + * Holds an {@link AnnotationInstance} and implements equality and hash code as equivalence. + *

+ * When using equivalence proxies, it is usually a mistake to obtain + * the {@linkplain AnnotationInstance#target() target} of the delegate annotation instance. + *

+ * Thread-Safety + *

+ * This class is immutable and can be shared between threads without safe + * publication. + * + * @see AnnotationInstance#equivalentTo(AnnotationInstance) + * @see AnnotationInstance#equivalenceHashCode() + */ +public final class AnnotationInstanceEquivalenceProxy { + private final AnnotationInstance annotation; + + AnnotationInstanceEquivalenceProxy(AnnotationInstance annotation) { + this.annotation = Objects.requireNonNull(annotation); + } + + public AnnotationInstance get() { + return annotation; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + return annotation.equivalentTo(((AnnotationInstanceEquivalenceProxy) o).annotation); + } + + @Override + public int hashCode() { + return annotation.equivalenceHashCode(); + } +} diff --git a/core/src/test/java/org/jboss/jandex/test/AnnotationInstanceTest.java b/core/src/test/java/org/jboss/jandex/test/AnnotationInstanceTest.java index 7212bb82..95f69c2e 100644 --- a/core/src/test/java/org/jboss/jandex/test/AnnotationInstanceTest.java +++ b/core/src/test/java/org/jboss/jandex/test/AnnotationInstanceTest.java @@ -9,6 +9,7 @@ import java.io.IOException; import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationInstanceEquivalenceProxy; import org.jboss.jandex.Index; import org.jboss.jandex.test.util.IndexingUtil; import org.junit.jupiter.api.Test; @@ -51,5 +52,19 @@ private void testEqualityEquivalence(Index index) { assertFalse(foo2.equivalentTo(bar)); assertEquals(foo.equivalenceHashCode(), foo2.equivalenceHashCode()); + + AnnotationInstanceEquivalenceProxy fooEquiv = foo.createEquivalenceProxy(); + AnnotationInstanceEquivalenceProxy foo2Equiv = foo2.createEquivalenceProxy(); + AnnotationInstanceEquivalenceProxy barEquiv = bar.createEquivalenceProxy(); + + assertNotNull(fooEquiv); + assertNotNull(foo2Equiv); + assertNotNull(barEquiv); + + assertEquals(fooEquiv, foo2Equiv); + assertNotEquals(fooEquiv, barEquiv); + assertNotEquals(foo2Equiv, barEquiv); + + assertEquals(fooEquiv.hashCode(), foo2Equiv.hashCode()); } }