This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new ef223e7dd0 Marshall module improvements
ef223e7dd0 is described below
commit ef223e7dd09b7c9f3fc1f6b5f34f6de54d6c7e7a
Author: James Bognar <[email protected]>
AuthorDate: Wed Dec 10 13:24:05 2025 -0500
Marshall module improvements
---
.../juneau/commons/reflect/ConstructorInfo.java | 42 +++++++++++++++
.../apache/juneau/commons/reflect/FieldInfo.java | 42 +++++++++++++++
.../apache/juneau/commons/reflect/MethodInfo.java | 42 +++++++++++++++
.../juneau/commons/reflect/ParameterInfo.java | 42 +++++++++++++++
.../commons/reflect/ConstructorInfo_Test.java | 59 +++++++++++++++++++++
.../juneau/commons/reflect/FieldInfo_Test.java | 60 ++++++++++++++++++++++
.../juneau/commons/reflect/MethodInfo_Test.java | 59 +++++++++++++++++++++
.../juneau/commons/reflect/ParameterInfo_Test.java | 60 ++++++++++++++++++++++
8 files changed, 406 insertions(+)
diff --git
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ConstructorInfo.java
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ConstructorInfo.java
index 8d33dc0c24..20730cb035 100644
---
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ConstructorInfo.java
+++
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ConstructorInfo.java
@@ -176,6 +176,48 @@ public class ConstructorInfo extends ExecutableInfo
implements Comparable<Constr
return (Constructor<T>)inner;
}
+ /**
+ * Compares this ConstructorInfo with the specified object for equality.
+ *
+ * <p>
+ * Two ConstructorInfo objects are considered equal if they wrap the
same underlying {@link Constructor} object.
+ * This delegates to the underlying {@link Constructor#equals(Object)}
method.
+ *
+ * <p>
+ * This method makes ConstructorInfo suitable for use as keys in
hash-based collections such as {@link HashMap}
+ * and {@link HashSet}.
+ *
+ * @param obj The object to compare with.
+ * @return <jk>true</jk> if the objects are equal, <jk>false</jk>
otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (obj instanceof ConstructorInfo other)
+ return inner.equals(other.inner);
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this ConstructorInfo.
+ *
+ * <p>
+ * This delegates to the underlying {@link Constructor#hashCode()}
method.
+ *
+ * <p>
+ * This method makes ConstructorInfo suitable for use as keys in
hash-based collections such as {@link HashMap}
+ * and {@link HashSet}.
+ *
+ * @return A hash code value for this ConstructorInfo.
+ */
+ @Override
+ public int hashCode() {
+ return inner.hashCode();
+ }
+
/**
* Shortcut for calling the new-instance method on the underlying
constructor.
*
diff --git
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/FieldInfo.java
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/FieldInfo.java
index a8c25dada6..8cbd6523ed 100644
---
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/FieldInfo.java
+++
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/FieldInfo.java
@@ -298,6 +298,48 @@ public class FieldInfo extends AccessibleInfo implements
Comparable<FieldInfo>,
return inner;
}
+ /**
+ * Compares this FieldInfo with the specified object for equality.
+ *
+ * <p>
+ * Two FieldInfo objects are considered equal if they wrap the same
underlying {@link Field} object.
+ * This delegates to the underlying {@link Field#equals(Object)} method.
+ *
+ * <p>
+ * This method makes FieldInfo suitable for use as keys in hash-based
collections such as {@link HashMap}
+ * and {@link HashSet}.
+ *
+ * @param obj The object to compare with.
+ * @return <jk>true</jk> if the objects are equal, <jk>false</jk>
otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (obj instanceof FieldInfo other)
+ return inner.equals(other.inner);
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this FieldInfo.
+ *
+ * <p>
+ * This delegates to the underlying {@link Field#hashCode()} method.
+ *
+ * <p>
+ * This method makes FieldInfo suitable for use as keys in hash-based
collections such as {@link HashMap}
+ * and {@link HashSet}.
+ *
+ * @return A hash code value for this FieldInfo.
+ */
+ @Override
+ public int hashCode() {
+ return inner.hashCode();
+ }
+
/**
* Returns <jk>true</jk> if all specified flags are applicable to this
field.
*
diff --git
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/MethodInfo.java
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/MethodInfo.java
index 6dc8fdeee2..36b9bd67d9 100644
---
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/MethodInfo.java
+++
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/MethodInfo.java
@@ -541,6 +541,48 @@ public class MethodInfo extends ExecutableInfo implements
Comparable<MethodInfo>
return inner;
}
+ /**
+ * Compares this MethodInfo with the specified object for equality.
+ *
+ * <p>
+ * Two MethodInfo objects are considered equal if they wrap the same
underlying {@link Method} object.
+ * This delegates to the underlying {@link Method#equals(Object)}
method.
+ *
+ * <p>
+ * This method makes MethodInfo suitable for use as keys in hash-based
collections such as {@link HashMap}
+ * and {@link HashSet}.
+ *
+ * @param obj The object to compare with.
+ * @return <jk>true</jk> if the objects are equal, <jk>false</jk>
otherwise.
+ */
+// @Override
+// public boolean equals(Object obj) {
+// if (this == obj)
+// return true;
+// if (obj == null)
+// return false;
+// if (obj instanceof MethodInfo other)
+// return inner.equals(other.inner);
+// return false;
+// }
+
+ /**
+ * Returns a hash code value for this MethodInfo.
+ *
+ * <p>
+ * This delegates to the underlying {@link Method#hashCode()} method.
+ *
+ * <p>
+ * This method makes MethodInfo suitable for use as keys in hash-based
collections such as {@link HashMap}
+ * and {@link HashSet}.
+ *
+ * @return A hash code value for this MethodInfo.
+ */
+ @Override
+ public int hashCode() {
+ return inner.hashCode();
+ }
+
/**
* Shortcut for calling the invoke method on the underlying method.
*
diff --git
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ParameterInfo.java
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ParameterInfo.java
index 8e22c8f14f..486d92b608 100644
---
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ParameterInfo.java
+++
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ParameterInfo.java
@@ -459,6 +459,48 @@ public class ParameterInfo extends ElementInfo implements
Annotatable {
return inner;
}
+ /**
+ * Compares this ParameterInfo with the specified object for equality.
+ *
+ * <p>
+ * Two ParameterInfo objects are considered equal if they wrap the same
underlying {@link Parameter} object.
+ * This delegates to the underlying {@link Parameter#equals(Object)}
method.
+ *
+ * <p>
+ * This method makes ParameterInfo suitable for use as keys in
hash-based collections such as {@link HashMap}
+ * and {@link HashSet}.
+ *
+ * @param obj The object to compare with.
+ * @return <jk>true</jk> if the objects are equal, <jk>false</jk>
otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (obj instanceof ParameterInfo other)
+ return inner.equals(other.inner);
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this ParameterInfo.
+ *
+ * <p>
+ * This delegates to the underlying {@link Parameter#hashCode()} method.
+ *
+ * <p>
+ * This method makes ParameterInfo suitable for use as keys in
hash-based collections such as {@link HashMap}
+ * and {@link HashSet}.
+ *
+ * @return A hash code value for this ParameterInfo.
+ */
+ @Override
+ public int hashCode() {
+ return inner.hashCode();
+ }
+
@Override
public boolean is(ElementFlag flag) {
return switch (flag) {
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ConstructorInfo_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ConstructorInfo_Test.java
index 6fc80709e1..358d473e56 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ConstructorInfo_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ConstructorInfo_Test.java
@@ -117,6 +117,11 @@ class ConstructorInfo_Test extends TestBase {
public ExceptionClass() throws Exception {}
}
+ public static class EqualsTestClass {
+ public EqualsTestClass() {}
+ public EqualsTestClass(String param) {}
+ }
+
//====================================================================================================
// accessible()
//====================================================================================================
@@ -715,5 +720,59 @@ class ConstructorInfo_Test extends TestBase {
check("B()", b_c1.toString());
check("B(String)", b_c2.toString());
}
+
+
//====================================================================================================
+ // equals(Object) and hashCode()
+
//====================================================================================================
+ @Test
+ void a054_equals_hashCode() throws Exception {
+ // Get ConstructorInfo instances from the same Constructor
+ Constructor<?> c1 = EqualsTestClass.class.getConstructor();
+ ConstructorInfo ci1a = ConstructorInfo.of(c1);
+ ConstructorInfo ci1b = ConstructorInfo.of(c1);
+
+ Constructor<?> c2 =
EqualsTestClass.class.getConstructor(String.class);
+ ConstructorInfo ci2 = ConstructorInfo.of(c2);
+
+ // Same constructor should be equal
+ assertEquals(ci1a, ci1b);
+ assertEquals(ci1a.hashCode(), ci1b.hashCode());
+
+ // Different constructors should not be equal
+ assertNotEquals(ci1a, ci2);
+ assertNotEquals(ci1a, null);
+ assertNotEquals(ci1a, "not a ConstructorInfo");
+
+ // Reflexive
+ assertEquals(ci1a, ci1a);
+
+ // Symmetric
+ assertEquals(ci1a, ci1b);
+ assertEquals(ci1b, ci1a);
+
+ // Transitive
+ ConstructorInfo ci1c = ConstructorInfo.of(c1);
+ assertEquals(ci1a, ci1b);
+ assertEquals(ci1b, ci1c);
+ assertEquals(ci1a, ci1c);
+
+ // HashMap usage - same constructor should map to same value
+ Map<ConstructorInfo, String> map = new HashMap<>();
+ map.put(ci1a, "value1");
+ assertEquals("value1", map.get(ci1b));
+ assertEquals("value1", map.get(ci1c));
+
+ // HashMap usage - different constructors should map to
different values
+ map.put(ci2, "value2");
+ assertEquals("value2", map.get(ci2));
+ assertNotEquals("value2", map.get(ci1a));
+
+ // HashSet usage
+ Set<ConstructorInfo> set = new HashSet<>();
+ set.add(ci1a);
+ assertTrue(set.contains(ci1b));
+ assertTrue(set.contains(ci1c));
+ assertFalse(set.contains(ci2));
+ }
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/FieldInfo_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/FieldInfo_Test.java
index 2075afb3b9..c1334ee39e 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/FieldInfo_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/FieldInfo_Test.java
@@ -24,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
+import java.util.*;
import java.util.function.*;
import org.apache.juneau.*;
@@ -194,6 +195,11 @@ class FieldInfo_Test extends TestBase {
testEnum_value1 = testEnum.getPublicField(x ->
x.hasName("VALUE1")).get(),
testEnum_value2 = testEnum.getPublicField(x ->
x.hasName("VALUE2")).get();
+ public static class EqualsTestClass {
+ public String field1;
+ public int field2;
+ }
+
//====================================================================================================
// accessible()
//====================================================================================================
@@ -666,5 +672,59 @@ class FieldInfo_Test extends TestBase {
void a031_toString() {
assertEquals("org.apache.juneau.commons.reflect.FieldInfo_Test$E.a1",
e_a1.toString());
}
+
+
//====================================================================================================
+ // equals(Object) and hashCode()
+
//====================================================================================================
+ @Test
+ void a032_equals_hashCode() throws Exception {
+ // Get FieldInfo instances from the same Field
+ Field f1 = EqualsTestClass.class.getField("field1");
+ FieldInfo fi1a = FieldInfo.of(f1);
+ FieldInfo fi1b = FieldInfo.of(f1);
+
+ Field f2 = EqualsTestClass.class.getField("field2");
+ FieldInfo fi2 = FieldInfo.of(f2);
+
+ // Same field should be equal
+ assertEquals(fi1a, fi1b);
+ assertEquals(fi1a.hashCode(), fi1b.hashCode());
+
+ // Different fields should not be equal
+ assertNotEquals(fi1a, fi2);
+ assertNotEquals(fi1a, null);
+ assertNotEquals(fi1a, "not a FieldInfo");
+
+ // Reflexive
+ assertEquals(fi1a, fi1a);
+
+ // Symmetric
+ assertEquals(fi1a, fi1b);
+ assertEquals(fi1b, fi1a);
+
+ // Transitive
+ FieldInfo fi1c = FieldInfo.of(f1);
+ assertEquals(fi1a, fi1b);
+ assertEquals(fi1b, fi1c);
+ assertEquals(fi1a, fi1c);
+
+ // HashMap usage - same field should map to same value
+ Map<FieldInfo, String> map = new HashMap<>();
+ map.put(fi1a, "value1");
+ assertEquals("value1", map.get(fi1b));
+ assertEquals("value1", map.get(fi1c));
+
+ // HashMap usage - different fields should map to different
values
+ map.put(fi2, "value2");
+ assertEquals("value2", map.get(fi2));
+ assertNotEquals("value2", map.get(fi1a));
+
+ // HashSet usage
+ Set<FieldInfo> set = new HashSet<>();
+ set.add(fi1a);
+ assertTrue(set.contains(fi1b));
+ assertTrue(set.contains(fi1c));
+ assertFalse(set.contains(fi2));
+ }
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/MethodInfo_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/MethodInfo_Test.java
index b327d1f13a..07eb0f5588 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/MethodInfo_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/MethodInfo_Test.java
@@ -97,6 +97,11 @@ class MethodInfo_Test extends TestBase {
}
static MethodInfo a_m = ofm(A1.class, "m"); // NOSONAR
+ public static class EqualsTestClass {
+ public void method1() {}
+ public void method2(String param) {}
+ }
+
public interface B1 {
int foo(int x);
int foo(String x);
@@ -738,5 +743,59 @@ class MethodInfo_Test extends TestBase {
assertFalse(a_m.isConstructor());
assertTrue(ClassInfo.of(A1.class).getPublicConstructor(cons ->
cons.getParameterCount() == 0).get().isConstructor());
}
+
+
//====================================================================================================
+ // equals(Object) and hashCode()
+
//====================================================================================================
+ @Test
+ void a041_equals_hashCode() throws Exception {
+ // Get MethodInfo instances from the same Method
+ Method m1 = EqualsTestClass.class.getMethod("method1");
+ MethodInfo mi1a = MethodInfo.of(m1);
+ MethodInfo mi1b = MethodInfo.of(m1);
+
+ Method m2 = EqualsTestClass.class.getMethod("method2",
String.class);
+ MethodInfo mi2 = MethodInfo.of(m2);
+
+ // Same method should be equal
+ assertEquals(mi1a, mi1b);
+ assertEquals(mi1a.hashCode(), mi1b.hashCode());
+
+ // Different methods should not be equal
+ assertNotEquals(mi1a, mi2);
+ assertNotEquals(mi1a, null);
+ assertNotEquals(mi1a, "not a MethodInfo");
+
+ // Reflexive
+ assertEquals(mi1a, mi1a);
+
+ // Symmetric
+ assertEquals(mi1a, mi1b);
+ assertEquals(mi1b, mi1a);
+
+ // Transitive
+ MethodInfo mi1c = MethodInfo.of(m1);
+ assertEquals(mi1a, mi1b);
+ assertEquals(mi1b, mi1c);
+ assertEquals(mi1a, mi1c);
+
+ // HashMap usage - same method should map to same value
+ Map<MethodInfo, String> map = new HashMap<>();
+ map.put(mi1a, "value1");
+ assertEquals("value1", map.get(mi1b));
+ assertEquals("value1", map.get(mi1c));
+
+ // HashMap usage - different methods should map to different
values
+ map.put(mi2, "value2");
+ assertEquals("value2", map.get(mi2));
+ assertNotEquals("value2", map.get(mi1a));
+
+ // HashSet usage
+ Set<MethodInfo> set = new HashSet<>();
+ set.add(mi1a);
+ assertTrue(set.contains(mi1b));
+ assertTrue(set.contains(mi1c));
+ assertFalse(set.contains(mi2));
+ }
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ParameterInfo_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ParameterInfo_Test.java
index 61bb047168..0093fa6e1d 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ParameterInfo_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ParameterInfo_Test.java
@@ -23,6 +23,7 @@ import static org.apache.juneau.commons.utils.Utils.*;
import static org.junit.jupiter.api.Assertions.*;
import java.lang.annotation.*;
+import java.lang.reflect.*;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
@@ -246,6 +247,10 @@ class ParameterInfo_Test extends TestBase {
}
// Constructor hierarchy tests
+ public static class EqualsTestClass {
+ public void method(String param1, int param2) {}
+ }
+
public static class PC1 {
public PC1(String foo) {} // NOSONAR
}
@@ -859,5 +864,60 @@ class ParameterInfo_Test extends TestBase {
void a029_toString() {
assertEquals("a1[1]", e_a1_b.toString());
}
+
+
//====================================================================================================
+ // equals(Object) and hashCode()
+
//====================================================================================================
+ @Test
+ void a030_equals_hashCode() throws Exception {
+ // Get ParameterInfo instances from the same Parameter
+ Method method = EqualsTestClass.class.getMethod("method",
String.class, int.class);
+ Parameter p1 = method.getParameters()[0];
+ ParameterInfo pi1a = ParameterInfo.of(p1);
+ ParameterInfo pi1b = ParameterInfo.of(p1);
+
+ Parameter p2 = method.getParameters()[1];
+ ParameterInfo pi2 = ParameterInfo.of(p2);
+
+ // Same parameter should be equal
+ assertEquals(pi1a, pi1b);
+ assertEquals(pi1a.hashCode(), pi1b.hashCode());
+
+ // Different parameters should not be equal
+ assertNotEquals(pi1a, pi2);
+ assertNotEquals(pi1a, null);
+ assertNotEquals(pi1a, "not a ParameterInfo");
+
+ // Reflexive
+ assertEquals(pi1a, pi1a);
+
+ // Symmetric
+ assertEquals(pi1a, pi1b);
+ assertEquals(pi1b, pi1a);
+
+ // Transitive
+ ParameterInfo pi1c = ParameterInfo.of(p1);
+ assertEquals(pi1a, pi1b);
+ assertEquals(pi1b, pi1c);
+ assertEquals(pi1a, pi1c);
+
+ // HashMap usage - same parameter should map to same value
+ Map<ParameterInfo, String> map = new HashMap<>();
+ map.put(pi1a, "value1");
+ assertEquals("value1", map.get(pi1b));
+ assertEquals("value1", map.get(pi1c));
+
+ // HashMap usage - different parameters should map to different
values
+ map.put(pi2, "value2");
+ assertEquals("value2", map.get(pi2));
+ assertNotEquals("value2", map.get(pi1a));
+
+ // HashSet usage
+ Set<ParameterInfo> set = new HashSet<>();
+ set.add(pi1a);
+ assertTrue(set.contains(pi1b));
+ assertTrue(set.contains(pi1c));
+ assertFalse(set.contains(pi2));
+ }
}