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 a3b9c8f543 Utility class modernization
a3b9c8f543 is described below
commit a3b9c8f543725b82aa1c3b2923af02ef08ec8f5f
Author: James Bognar <[email protected]>
AuthorDate: Tue Nov 4 18:44:05 2025 -0500
Utility class modernization
---
.../juneau/common/reflect/AnnotationInfo.java | 140 ++++++++++++++-
.../apache/juneau/common/reflect/FieldInfo.java | 1 -
.../juneau/common/reflect/ParameterInfo.java | 4 +-
.../reflect/AnnotationInfo_ValueMethods_Test.java | 189 +++++++++++++++++++++
4 files changed, 328 insertions(+), 6 deletions(-)
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationInfo.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationInfo.java
index 0b2e046bea..8af5663e01 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationInfo.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationInfo.java
@@ -494,15 +494,149 @@ public class AnnotationInfo<T extends Annotation> {
mi.getDeclaredAnnotationInfos().forEach(ai ->
ai.accept(filter, action));
}
+ /**
+ * Returns <jk>true</jk> if this annotation has the specified simple
name.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ * <jk>boolean</jk> <jv>isName</jv> =
<jv>annotationInfo</jv>.hasSimpleName(<js>"Name"</js>);
+ * </p>
+ *
+ * @param value The simple name to check.
+ * @return <jk>true</jk> if this annotation has the specified simple
name.
+ */
public boolean hasSimpleName(String value) {
return eq(value, a.annotationType().getSimpleName());
}
- public String getValue() {
+ /**
+ * Returns <jk>true</jk> if this annotation has the specified
fully-qualified name.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ * <jk>boolean</jk> <jv>isName</jv> =
<jv>annotationInfo</jv>.hasName(<js>"org.apache.juneau.annotation.Name"</js>);
+ * </p>
+ *
+ * @param value The fully-qualified name to check.
+ * @return <jk>true</jk> if this annotation has the specified
fully-qualified name.
+ */
+ public boolean hasName(String value) {
+ return eq(value, a.annotationType().getName());
+ }
+
+ /**
+ * Returns the value of the <c>value()</c> method on this annotation as
a string.
+ *
+ * @return An optional containing the value of the <c>value()</c>
method, or empty if not found or not a string.
+ */
+ public Optional<String> getValue() {
return getString("value");
}
- public String getString(String methodName) {
- return methods.get().stream().filter(x -> eq(methodName,
x.getSimpleName()) && x.hasReturnType(String.class)).map(x ->
s(x.invoke(a))).findFirst().orElse(null);
+ /**
+ * Returns the value of the specified method on this annotation as a
string.
+ *
+ * @param methodName The method name.
+ * @return An optional containing the value of the specified method, or
empty if not found or not a string.
+ */
+ public Optional<String> getString(String methodName) {
+ return methods.get().stream().filter(x -> eq(methodName,
x.getSimpleName()) && x.hasReturnType(String.class)).map(x ->
s(x.invoke(a))).findFirst();
+ }
+
+ /**
+ * Returns the value of the specified method on this annotation as an
integer.
+ *
+ * @param methodName The method name.
+ * @return An optional containing the value of the specified method, or
empty if not found or not an integer.
+ */
+ public Optional<Integer> getInt(String methodName) {
+ return methods.get().stream().filter(x -> eq(methodName,
x.getSimpleName()) && x.hasReturnType(int.class)).map(x ->
(Integer)x.invoke(a)).findFirst();
+ }
+
+ /**
+ * Returns the value of the specified method on this annotation as a
boolean.
+ *
+ * @param methodName The method name.
+ * @return An optional containing the value of the specified method, or
empty if not found or not a boolean.
+ */
+ public Optional<Boolean> getBoolean(String methodName) {
+ return methods.get().stream().filter(x -> eq(methodName,
x.getSimpleName()) && x.hasReturnType(boolean.class)).map(x ->
(Boolean)x.invoke(a)).findFirst();
+ }
+
+ /**
+ * Returns the value of the specified method on this annotation as a
long.
+ *
+ * @param methodName The method name.
+ * @return An optional containing the value of the specified method, or
empty if not found or not a long.
+ */
+ public Optional<Long> getLong(String methodName) {
+ return methods.get().stream().filter(x -> eq(methodName,
x.getSimpleName()) && x.hasReturnType(long.class)).map(x ->
(Long)x.invoke(a)).findFirst();
+ }
+
+ /**
+ * Returns the value of the specified method on this annotation as a
double.
+ *
+ * @param methodName The method name.
+ * @return An optional containing the value of the specified method, or
empty if not found or not a double.
+ */
+ public Optional<Double> getDouble(String methodName) {
+ return methods.get().stream().filter(x -> eq(methodName,
x.getSimpleName()) && x.hasReturnType(double.class)).map(x ->
(Double)x.invoke(a)).findFirst();
+ }
+
+ /**
+ * Returns the value of the specified method on this annotation as a
float.
+ *
+ * @param methodName The method name.
+ * @return An optional containing the value of the specified method, or
empty if not found or not a float.
+ */
+ public Optional<Float> getFloat(String methodName) {
+ return methods.get().stream().filter(x -> eq(methodName,
x.getSimpleName()) && x.hasReturnType(float.class)).map(x ->
(Float)x.invoke(a)).findFirst();
+ }
+
+ /**
+ * Returns the value of the specified method on this annotation as a
class.
+ *
+ * @param methodName The method name.
+ * @return An optional containing the value of the specified method, or
empty if not found or not a class.
+ */
+ @SuppressWarnings("unchecked")
+ public Optional<Class<?>> getClassValue(String methodName) {
+ return
(Optional<Class<?>>)(Optional<?>)methods.get().stream().filter(x ->
eq(methodName, x.getSimpleName()) && x.hasReturnType(Class.class)).map(x ->
x.invoke(a)).findFirst();
+ }
+
+ /**
+ * Returns the value of the specified method on this annotation as a
string array.
+ *
+ * @param methodName The method name.
+ * @return An optional containing the value of the specified method, or
empty if not found or not a string array.
+ */
+ public Optional<String[]> getStringArray(String methodName) {
+ return methods.get().stream().filter(x -> eq(methodName,
x.getSimpleName()) && x.hasReturnType(String[].class)).map(x ->
(String[])x.invoke(a)).findFirst();
+ }
+
+ /**
+ * Returns the value of the specified method on this annotation as a
class array.
+ *
+ * @param methodName The method name.
+ * @return An optional containing the value of the specified method, or
empty if not found or not a class array.
+ */
+ @SuppressWarnings("unchecked")
+ public Optional<Class<?>[]> getClassArray(String methodName) {
+ return
(Optional<Class<?>[]>)(Optional<?>)methods.get().stream().filter(x ->
eq(methodName, x.getSimpleName()) && x.hasReturnType(Class[].class)).map(x ->
x.invoke(a)).findFirst();
+ }
+
+ /**
+ * Returns the return type of the specified method on this annotation.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ * Optional<ClassInfo> <jv>returnType</jv> =
<jv>annotationInfo</jv>.getReturnType(<js>"value"</js>);
+ * </p>
+ *
+ * @param methodName The method name.
+ * @return An optional containing the return type of the specified
method, or empty if method not found.
+ */
+ public Optional<ClassInfo> getReturnType(String methodName) {
+ return methods.get().stream().filter(x -> eq(methodName,
x.getSimpleName())).map(x -> x.getReturnType()).findFirst();
}
}
\ No newline at end of file
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/FieldInfo.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/FieldInfo.java
index 1356dcb912..a67db4fdb1 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/FieldInfo.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/FieldInfo.java
@@ -18,7 +18,6 @@ package org.apache.juneau.common.reflect;
import static org.apache.juneau.common.utils.CollectionUtils.*;
import static org.apache.juneau.common.utils.PredicateUtils.*;
-import static org.apache.juneau.common.utils.ThrowableUtils.*;
import static org.apache.juneau.common.utils.Utils.*;
import java.lang.annotation.*;
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ParameterInfo.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ParameterInfo.java
index c34e0610ff..110489cbb6 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ParameterInfo.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ParameterInfo.java
@@ -308,7 +308,7 @@ public class ParameterInfo extends ElementInfo implements
Annotatable {
for (var mp : getMatchingParameters()) {
for (var ai : mp.getAnnotationInfos()) {
if (ai.hasSimpleName("Name")) {
- String value = ai.getValue();
+ String value =
ai.getValue().orElse(null);
if (value != null)
return value;
}
@@ -349,7 +349,7 @@ public class ParameterInfo extends ElementInfo implements
Annotatable {
for (var mp : getMatchingParameters()) {
for (var ai : mp.getAnnotationInfos()) {
if (ai.hasSimpleName("Named") ||
ai.hasSimpleName("Qualifier")) {
- String value = ai.getValue();
+ String value =
ai.getValue().orElse(null);
if (value != null)
return value;
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/reflect/AnnotationInfo_ValueMethods_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/reflect/AnnotationInfo_ValueMethods_Test.java
new file mode 100644
index 0000000000..0299759dbe
--- /dev/null
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/reflect/AnnotationInfo_ValueMethods_Test.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.juneau.common.reflect;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.lang.annotation.*;
+
+import org.junit.jupiter.api.*;
+
+/**
+ * Tests for AnnotationInfo value retrieval methods.
+ */
+public class AnnotationInfo_ValueMethods_Test {
+
+ @Target(ElementType.TYPE)
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface TestAnnotation {
+ String stringValue() default "default";
+ int intValue() default 42;
+ boolean boolValue() default true;
+ long longValue() default 100L;
+ double doubleValue() default 3.14;
+ float floatValue() default 2.5f;
+ Class<?> classValue() default String.class;
+ String[] stringArray() default {"a", "b"};
+ Class<?>[] classArray() default {String.class, Integer.class};
+ }
+
+ @TestAnnotation(
+ stringValue = "test",
+ intValue = 123,
+ boolValue = false,
+ longValue = 999L,
+ doubleValue = 1.23,
+ floatValue = 4.56f,
+ classValue = Integer.class,
+ stringArray = {"x", "y", "z"},
+ classArray = {Long.class, Double.class}
+ )
+ public static class AnnotatedClass {}
+
+ private AnnotationInfo<TestAnnotation> getTestAnnotationInfo() {
+ var ci = ClassInfo.of(AnnotatedClass.class);
+ var annotation = ci.getAnnotation(TestAnnotation.class);
+ return AnnotationInfo.of(ci, annotation);
+ }
+
+ @Test
+ public void testHasName() {
+ var ai = getTestAnnotationInfo();
+
+
assertTrue(ai.hasName("org.apache.juneau.common.reflect.AnnotationInfo_ValueMethods_Test$TestAnnotation"));
+ assertFalse(ai.hasName("TestAnnotation"));
+ }
+
+ @Test
+ public void testHasSimpleName() {
+ var ai = getTestAnnotationInfo();
+
+ assertTrue(ai.hasSimpleName("TestAnnotation"));
+
assertFalse(ai.hasSimpleName("org.apache.juneau.common.reflect.AnnotationInfo_ValueMethods_Test$TestAnnotation"));
+ }
+
+ @Test
+ public void testGetString() {
+ var ai = getTestAnnotationInfo();
+
+ assertTrue(ai.getString("stringValue").isPresent());
+ assertEquals("test", ai.getString("stringValue").get());
+ assertTrue(ai.getString("nonexistent").isEmpty());
+ }
+
+ @Test
+ public void testGetInt() {
+ var ai = getTestAnnotationInfo();
+
+ assertTrue(ai.getInt("intValue").isPresent());
+ assertEquals(123, ai.getInt("intValue").get());
+ assertTrue(ai.getInt("nonexistent").isEmpty());
+ }
+
+ @Test
+ public void testGetBoolean() {
+ var ai = getTestAnnotationInfo();
+
+ assertTrue(ai.getBoolean("boolValue").isPresent());
+ assertEquals(false, ai.getBoolean("boolValue").get());
+ assertTrue(ai.getBoolean("nonexistent").isEmpty());
+ }
+
+ @Test
+ public void testGetLong() {
+ var ai = getTestAnnotationInfo();
+
+ assertTrue(ai.getLong("longValue").isPresent());
+ assertEquals(999L, ai.getLong("longValue").get());
+ assertTrue(ai.getLong("nonexistent").isEmpty());
+ }
+
+ @Test
+ public void testGetDouble() {
+ var ai = getTestAnnotationInfo();
+
+ assertTrue(ai.getDouble("doubleValue").isPresent());
+ assertEquals(1.23, ai.getDouble("doubleValue").get(), 0.001);
+ assertTrue(ai.getDouble("nonexistent").isEmpty());
+ }
+
+ @Test
+ public void testGetFloat() {
+ var ai = getTestAnnotationInfo();
+
+ assertTrue(ai.getFloat("floatValue").isPresent());
+ assertEquals(4.56f, ai.getFloat("floatValue").get(), 0.001);
+ assertTrue(ai.getFloat("nonexistent").isEmpty());
+ }
+
+ @Test
+ public void testGetClassValue() {
+ var ai = getTestAnnotationInfo();
+
+ assertTrue(ai.getClassValue("classValue").isPresent());
+ assertEquals(Integer.class,
ai.getClassValue("classValue").get());
+ assertTrue(ai.getClassValue("nonexistent").isEmpty());
+ }
+
+ @Test
+ public void testGetStringArray() {
+ var ai = getTestAnnotationInfo();
+
+ assertTrue(ai.getStringArray("stringArray").isPresent());
+ String[] array = ai.getStringArray("stringArray").get();
+ assertNotNull(array);
+ assertEquals(3, array.length);
+ assertEquals("x", array[0]);
+ assertEquals("y", array[1]);
+ assertEquals("z", array[2]);
+ assertTrue(ai.getStringArray("nonexistent").isEmpty());
+ }
+
+ @Test
+ public void testGetClassArray() {
+ var ai = getTestAnnotationInfo();
+
+ assertTrue(ai.getClassArray("classArray").isPresent());
+ Class<?>[] array = ai.getClassArray("classArray").get();
+ assertNotNull(array);
+ assertEquals(2, array.length);
+ assertEquals(Long.class, array[0]);
+ assertEquals(Double.class, array[1]);
+ assertTrue(ai.getClassArray("nonexistent").isEmpty());
+ }
+
+ @Test
+ public void testGetReturnType() {
+ var ai = getTestAnnotationInfo();
+
+ // Test various return types
+ assertTrue(ai.getReturnType("stringValue").isPresent());
+ assertEquals(String.class,
ai.getReturnType("stringValue").get().inner());
+ assertEquals(int.class,
ai.getReturnType("intValue").get().inner());
+ assertEquals(boolean.class,
ai.getReturnType("boolValue").get().inner());
+ assertEquals(long.class,
ai.getReturnType("longValue").get().inner());
+ assertEquals(double.class,
ai.getReturnType("doubleValue").get().inner());
+ assertEquals(float.class,
ai.getReturnType("floatValue").get().inner());
+ assertEquals(Class.class,
ai.getReturnType("classValue").get().inner());
+ assertEquals(String[].class,
ai.getReturnType("stringArray").get().inner());
+ assertEquals(Class[].class,
ai.getReturnType("classArray").get().inner());
+
+ // Nonexistent method
+ assertTrue(ai.getReturnType("nonexistent").isEmpty());
+ }
+}
+