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 a273f2d8d0 Utility class modernization
a273f2d8d0 is described below

commit a273f2d8d0e16ec26eee1fb1f837fd487a79e48a
Author: James Bognar <[email protected]>
AuthorDate: Fri Nov 7 11:31:22 2025 -0500

    Utility class modernization
---
 .../apache/juneau/common/reflect/ClassInfo.java    | 334 ++++++++++-----------
 .../juneau/common/reflect/ExecutableInfo.java      |  70 ++---
 .../apache/juneau/common/reflect/FieldInfo.java    |  16 +-
 .../apache/juneau/common/reflect/PackageInfo.java  |  13 +-
 .../juneau/common/reflect/ParameterInfo.java       |  29 +-
 5 files changed, 203 insertions(+), 259 deletions(-)

diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ClassInfo.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ClassInfo.java
index d29d37774c..4c097af3ef 100644
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ClassInfo.java
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ClassInfo.java
@@ -179,189 +179,41 @@ public class ClassInfo extends ElementInfo implements 
Annotatable {
                return c == null ? ClassInfo.of(o) : ClassInfo.of(c);
        }
 
-       // The underlying Type object (may be Class, ParameterizedType, 
GenericArrayType, etc.).
-       private final Type t;
-
-       // The underlying Class object (null for non-class types like 
TypeVariable).  Effectively final.
-       private Class<?> inner;
-
-       // True if this represents a ParameterizedType (e.g., List<String>).
-       private final boolean isParameterizedType;
-
-       // Number of array dimensions (0 if not an array).
-       private final Supplier<Integer> dimensions = 
memoize(this::findDimensions);
-
-       // Base component type for arrays (e.g., String for String[][]), also 
handles GenericArrayType.  Cached and never null.
-       private final Supplier<ClassInfo> componentType = 
memoize(this::findComponentType);
-
-       // The package this class belongs to (null for primitive types and 
arrays).
-       private final Supplier<PackageInfo> packageInfo = memoize(() -> 
opt(inner).map(x -> PackageInfo.of(x.getPackage())).orElse(null));
-
-       // All superclasses of this class in child-to-parent order, starting 
with this class.
-       private final Supplier<List<ClassInfo>> parents = 
memoize(this::findParents);
-
-       // All annotations declared directly on this class, wrapped in 
AnnotationInfo.
-       private final Supplier<List<AnnotationInfo>> declaredAnnotations2 = 
memoize(() -> (List)opt(inner).map(x -> 
u(l(x.getDeclaredAnnotations()))).orElse(liste()).stream().map(a -> 
AnnotationInfo.of(this, a)).toList());
-
-       // Fully qualified class name with generics (e.g., 
"java.util.List<java.lang.String>").
-       private final Supplier<String> fullName = memoize(() -> 
getNameFormatted(FULL, true, '$', BRACKETS));
-
-       // Simple class name with generics (e.g., "List<String>").
-       private final Supplier<String> shortName = memoize(() -> 
getNameFormatted(SHORT, true, '$', BRACKETS));
-
-       // Human-readable class name without generics (e.g., "List").
-       private final Supplier<String> readableName = memoize(() -> 
getNameFormatted(SIMPLE, false, '$', WORD));
-
-       // All interfaces declared directly by this class.
-       private final Supplier<List<ClassInfo>> declaredInterfaces = memoize(() 
-> opt(inner).map(x -> 
stream(x.getInterfaces()).map(ClassInfo::of).toList()).orElse(liste()));
-
-       // All interfaces implemented by this class and its parents, in 
child-to-parent order.
-       private final Supplier<List<ClassInfo>> interfaces = memoize(() -> 
getParents().stream().flatMap(x -> 
x.getDeclaredInterfaces().stream()).flatMap(ci2 -> concat(Stream.of(ci2), 
ci2.getInterfaces().stream())).distinct().toList());
-
-       // All parent classes and interfaces, classes first, then in 
child-to-parent order.
-       // TODO - Determine if this field is still needed now that we have 
parentsAndInterfaces which handles the hierarchy better.
-       private final Supplier<List<ClassInfo>> allParents = memoize(() -> 
concat(getParents().stream(), getInterfaces().stream()).toList());
-
-       // All parent classes and interfaces with proper traversal of interface 
hierarchy to avoid duplicates.
-       private final Supplier<List<ClassInfo>> parentsAndInterfaces = 
memoize(this::findParentsAndInterfaces);
-
-       /**
-        * Finds all parent classes and interfaces with proper traversal of 
interface hierarchy.
-        *
-        * @return A list of all parent classes and interfaces without 
duplicates.
-        */
-       private List<ClassInfo> findParentsAndInterfaces() {
-               var set = new LinkedHashSet<ClassInfo>();
-
-               // Process all parent classes (includes this class)
-               var parents = getParents();
-               for (int i = 0; i < parents.size(); i++) {
-                       var parent = parents.get(i);
-                       set.add(parent);
-
-                       // Process interfaces declared on this parent (and 
their parent interfaces)
-                       var declaredInterfaces = parent.getDeclaredInterfaces();
-                       for (int j = 0; j < declaredInterfaces.size(); j++)
-                               addInterfaceHierarchy(set, 
declaredInterfaces.get(j));
-               }
-
-               return u(new ArrayList<>(set));
-       }
-
-       /**
-        * Helper method to recursively add an interface and its parent 
interfaces to the set.
-        *
-        * @param set The set to add to.
-        * @param iface The interface to add.
-        */
-       private void addInterfaceHierarchy(LinkedHashSet<ClassInfo> set, 
ClassInfo iface) {
-               if (!set.add(iface))
-                       return;
-
-               // Process parent interfaces recursively
-               var parentInterfaces = iface.getDeclaredInterfaces();
-               for (int i = 0; i < parentInterfaces.size(); i++)
-                       addInterfaceHierarchy(set, parentInterfaces.get(i));
-       }
-
-       /**
-        * Finds all annotations on this class and parent classes/interfaces in 
child-to-parent order.
-        *
-        * <p>
-        * This is similar to {@link 
org.apache.juneau.common.reflect.AnnotationProvider#find(Class)} but without 
runtime annotations.
-        *
-        * <p>
-        * Order of traversal:
-        * <ol>
-        *      <li>Annotations declared on this class
-        *      <li>Annotations declared on parent classes (child-to-parent 
order)
-        *      <li>For each parent class, annotations on interfaces declared 
on that class (child-to-parent interface hierarchy)
-        *      <li>Annotations on the package of this class
-        * </ol>
-        *
-        * @return A list of all annotation infos in child-to-parent order.
-        */
-       private List<AnnotationInfo<Annotation>> findAnnotationInfos() {
-               var list = new ArrayList<AnnotationInfo<Annotation>>();
-
-               // On all parent classes and interfaces (properly traversed to 
avoid duplicates)
-               var parentsAndInterfaces = getParentsAndInterfaces();
-               for (int i = 0; i < parentsAndInterfaces.size(); i++) {
-                       var ci = parentsAndInterfaces.get(i);
-                       // Add declared annotations from this class/interface
-                       for (var a : ci.inner().getDeclaredAnnotations())
-                               for (var a2 : splitRepeated(a))
-                                       list.add(AnnotationInfo.of(ci, a2));
-               }
-
-               // On the package of this class
-               var pkg = getPackage();
-               if (nn(pkg)) {
-                       var pi = PackageInfo.of(pkg.inner());
-                       for (var a : pkg.inner().getAnnotations())
-                               for (var a2 : splitRepeated(a))
-                                       list.add(AnnotationInfo.of(pi, a2));
-               }
-
-               return u(list);
-       }
-
-       // All annotations on this class and parent classes/interfaces in 
child-to-parent order.
-       private final Supplier<List<AnnotationInfo<Annotation>>> 
annotationInfos = memoize(this::findAnnotationInfos);
-
-       // All record components if this is a record class (Java 14+).
-       private final Supplier<List<RecordComponent>> recordComponents = 
memoize(() -> opt(inner).filter(Class::isRecord).map(x -> 
u(l(x.getRecordComponents()))).orElse(liste()));
-
-       // All generic interface types (e.g., List<String> implements 
Comparable<List<String>>).
-       private final Supplier<List<Type>> genericInterfaces = memoize(() -> 
opt(inner).map(x -> u(l(x.getGenericInterfaces()))).orElse(liste()));
-
-       // All type parameters declared on this class (e.g., <T, U> in class 
Foo<T, U>).
-       private final Supplier<List<TypeVariable<?>>> typeParameters = 
memoize(() -> opt(inner).map(x -> 
u(l((TypeVariable<?>[])x.getTypeParameters()))).orElse(liste()));
-
-       // All annotated interface types with their annotations.
-       private final Supplier<List<AnnotatedType>> annotatedInterfaces = 
memoize(() -> opt(inner).map(x -> 
u(l(x.getAnnotatedInterfaces()))).orElse(liste()));
-
-       // All signers of this class (for signed JARs).
-       private final Supplier<List<Object>> signers = memoize(() -> 
opt(inner).map(Class::getSigners).map(x -> u(l(x))).orElse(liste()));
-
-       // All public methods on this class and inherited, excluding Object 
methods.
-       private final Supplier<List<MethodInfo>> publicMethods = memoize(() -> 
opt(inner).map(x -> stream(x.getMethods()).filter(m -> 
ne(m.getDeclaringClass(), 
Object.class)).map(this::getMethodInfo).sorted().toList()).orElse(liste()));
-
-       // All methods declared directly on this class (public, protected, 
package, private).
-       private final Supplier<List<MethodInfo>> declaredMethods = memoize(() 
-> opt(inner).map(x -> stream(x.getDeclaredMethods()).filter(m -> 
ne("$jacocoInit", 
m.getName())).map(this::getMethodInfo).sorted().toList()).orElse(liste()));
-
-       // All methods from this class and all parents, in child-to-parent 
order.
-       private final Supplier<List<MethodInfo>> allMethods = memoize(() -> 
allParents.get().stream().flatMap(c -> 
c.getDeclaredMethods().stream()).toList());
-
-       // All methods from this class and all parents, in parent-to-child 
order.
-       private final Supplier<List<MethodInfo>> allMethodsParentFirst = 
memoize(() -> rstream(getAllParents()).flatMap(c -> 
c.getDeclaredMethods().stream()).toList());
-
-       // All public fields from this class and parents, deduplicated by name 
(child wins).
-       private final Supplier<List<FieldInfo>> publicFields = memoize(() -> 
parents.get().stream().flatMap(c -> c.getDeclaredFields().stream()).filter(f -> 
f.isPublic() && ne("$jacocoData", 
f.getName())).collect(toMap(FieldInfo::getName, x -> x, (a, b) -> a, 
LinkedHashMap::new)).values().stream().sorted().collect(toList()));
-
-       // All fields declared directly on this class (public, protected, 
package, private).
-       private final Supplier<List<FieldInfo>> declaredFields = memoize(() -> 
opt(inner).map(x -> stream(x.getDeclaredFields()).filter(f -> ne("$jacocoData", 
f.getName())).map(this::getFieldInfo).sorted().toList()).orElse(liste()));
-
-       // All fields from this class and all parents, in parent-to-child order.
-       private final Supplier<List<FieldInfo>> allFields = memoize(() -> 
rstream(allParents.get()).flatMap(c -> 
c.getDeclaredFields().stream()).toList());
-
-       // All public constructors declared on this class.
-       private final Supplier<List<ConstructorInfo>> publicConstructors = 
memoize(() -> opt(inner).map(x -> 
stream(x.getConstructors()).map(this::getConstructorInfo).sorted().toList()).orElse(liste()));
-
-       // All constructors declared on this class (public, protected, package, 
private).
-       private final Supplier<List<ConstructorInfo>> declaredConstructors = 
memoize(() -> opt(inner).map(x -> 
stream(x.getDeclaredConstructors()).map(this::getConstructorInfo).sorted().toList()).orElse(liste()));
-
-       // The repeated annotation method (value()) if this class is a 
@Repeatable container.
-       private final Supplier<MethodInfo> repeatedAnnotationMethod = 
memoize(this::findRepeatedAnnotationMethod);
-
-       // Cache of wrapped Method objects.
-       private final Cache<Method,MethodInfo> methodCache = 
Cache.of(Method.class, MethodInfo.class).build();
-
-       // Cache of wrapped Field objects.
-       private final Cache<Field,FieldInfo> fieldCache = Cache.of(Field.class, 
FieldInfo.class).build();
-
-       // Cache of wrapped Constructor objects.
-       private final Cache<Constructor,ConstructorInfo> constructorCache = 
Cache.of(Constructor.class, ConstructorInfo.class).build();
+       private final Type t;  // The underlying Type object (may be Class, 
ParameterizedType, GenericArrayType, etc.).
+       private Class<?> inner;  // The underlying Class object (null for 
non-class types like TypeVariable).  Effectively final.
+       private final boolean isParameterizedType;  // True if this represents 
a ParameterizedType (e.g., List<String>).
+
+       private final Supplier<Integer> dimensions;  // Number of array 
dimensions (0 if not an array).
+       private final Supplier<ClassInfo> componentType;  // Base component 
type for arrays (e.g., String for String[][]), also handles GenericArrayType.  
Cached and never null.
+       private final Supplier<PackageInfo> packageInfo;  // The package this 
class belongs to (null for primitive types and arrays).
+       private final Supplier<List<ClassInfo>> parents;  // All superclasses 
of this class in child-to-parent order, starting with this class.
+       private final Supplier<List<AnnotationInfo>> declaredAnnotations2;  // 
All annotations declared directly on this class, wrapped in AnnotationInfo.
+       private final Supplier<String> fullName;  // Fully qualified class name 
with generics (e.g., "java.util.List<java.lang.String>").
+       private final Supplier<String> shortName;  // Simple class name with 
generics (e.g., "List<String>").
+       private final Supplier<String> readableName;  // Human-readable class 
name without generics (e.g., "List").
+       private final Supplier<List<ClassInfo>> declaredInterfaces;  // All 
interfaces declared directly by this class.
+       private final Supplier<List<ClassInfo>> interfaces;  // All interfaces 
implemented by this class and its parents, in child-to-parent order.
+       private final Supplier<List<ClassInfo>> allParents;  // All parent 
classes and interfaces, classes first, then in child-to-parent order.
+       private final Supplier<List<ClassInfo>> parentsAndInterfaces;  // All 
parent classes and interfaces with proper traversal of interface hierarchy to 
avoid duplicates.
+       private final Supplier<List<AnnotationInfo<Annotation>>> 
annotationInfos;  // All annotations on this class and parent 
classes/interfaces in child-to-parent order.
+       private final Supplier<List<RecordComponent>> recordComponents;  // All 
record components if this is a record class (Java 14+).
+       private final Supplier<List<Type>> genericInterfaces;  // All generic 
interface types (e.g., List<String> implements Comparable<List<String>>).
+       private final Supplier<List<TypeVariable<?>>> typeParameters;  // All 
type parameters declared on this class (e.g., <T, U> in class Foo<T, U>).
+       private final Supplier<List<AnnotatedType>> annotatedInterfaces;  // 
All annotated interface types with their annotations.
+       private final Supplier<List<Object>> signers;  // All signers of this 
class (for signed JARs).
+       private final Supplier<List<MethodInfo>> publicMethods;  // All public 
methods on this class and inherited, excluding Object methods.
+       private final Supplier<List<MethodInfo>> declaredMethods;  // All 
methods declared directly on this class (public, protected, package, private).
+       private final Supplier<List<MethodInfo>> allMethods;  // All methods 
from this class and all parents, in child-to-parent order.
+       private final Supplier<List<MethodInfo>> allMethodsParentFirst;  // All 
methods from this class and all parents, in parent-to-child order.
+       private final Supplier<List<FieldInfo>> publicFields;  // All public 
fields from this class and parents, deduplicated by name (child wins).
+       private final Supplier<List<FieldInfo>> declaredFields;  // All fields 
declared directly on this class (public, protected, package, private).
+       private final Supplier<List<FieldInfo>> allFields;  // All fields from 
this class and all parents, in parent-to-child order.
+       private final Supplier<List<ConstructorInfo>> publicConstructors;  // 
All public constructors declared on this class.
+       private final Supplier<List<ConstructorInfo>> declaredConstructors;  // 
All constructors declared on this class (public, protected, package, private).
+       private final Supplier<MethodInfo> repeatedAnnotationMethod;  // The 
repeated annotation method (value()) if this class is a @Repeatable container.
+       private final Cache<Method,MethodInfo> methodCache;  // Cache of 
wrapped Method objects.
+       private final Cache<Field,FieldInfo> fieldCache;  // Cache of wrapped 
Field objects.
+       private final Cache<Constructor,ConstructorInfo> constructorCache;  // 
Cache of wrapped Constructor objects.
 
        /**
         * Constructor.
@@ -374,6 +226,37 @@ public class ClassInfo extends ElementInfo implements 
Annotatable {
                this.t = t;
                this.inner = c;
                this.isParameterizedType = t == null ? false : (t instanceof 
ParameterizedType);
+               this.dimensions = memoize(this::findDimensions);
+               this.componentType = memoize(this::findComponentType);
+               this.packageInfo = memoize(() -> opt(inner).map(x -> 
PackageInfo.of(x.getPackage())).orElse(null));
+               this.parents = memoize(this::findParents);
+               this.declaredAnnotations2 = memoize(() -> 
(List)opt(inner).map(x -> 
u(l(x.getDeclaredAnnotations()))).orElse(liste()).stream().map(a -> 
AnnotationInfo.of(this, a)).toList());
+               this.fullName = memoize(() -> getNameFormatted(FULL, true, '$', 
BRACKETS));
+               this.shortName = memoize(() -> getNameFormatted(SHORT, true, 
'$', BRACKETS));
+               this.readableName = memoize(() -> getNameFormatted(SIMPLE, 
false, '$', WORD));
+               this.declaredInterfaces = memoize(() -> opt(inner).map(x -> 
stream(x.getInterfaces()).map(ClassInfo::of).toList()).orElse(liste()));
+               this.interfaces = memoize(() -> getParents().stream().flatMap(x 
-> x.getDeclaredInterfaces().stream()).flatMap(ci2 -> concat(Stream.of(ci2), 
ci2.getInterfaces().stream())).distinct().toList());
+               this.allParents = memoize(() -> concat(getParents().stream(), 
getInterfaces().stream()).toList());
+               this.parentsAndInterfaces = 
memoize(this::findParentsAndInterfaces);
+               this.annotationInfos = memoize(this::findAnnotationInfos);
+               this.recordComponents = memoize(() -> 
opt(inner).filter(Class::isRecord).map(x -> 
u(l(x.getRecordComponents()))).orElse(liste()));
+               this.genericInterfaces = memoize(() -> opt(inner).map(x -> 
u(l(x.getGenericInterfaces()))).orElse(liste()));
+               this.typeParameters = memoize(() -> opt(inner).map(x -> 
u(l((TypeVariable<?>[])x.getTypeParameters()))).orElse(liste()));
+               this.annotatedInterfaces = memoize(() -> opt(inner).map(x -> 
u(l(x.getAnnotatedInterfaces()))).orElse(liste()));
+               this.signers = memoize(() -> 
opt(inner).map(Class::getSigners).map(x -> u(l(x))).orElse(liste()));
+               this.publicMethods = memoize(() -> opt(inner).map(x -> 
stream(x.getMethods()).filter(m -> ne(m.getDeclaringClass(), 
Object.class)).map(this::getMethodInfo).sorted().toList()).orElse(liste()));
+               this.declaredMethods = memoize(() -> opt(inner).map(x -> 
stream(x.getDeclaredMethods()).filter(m -> ne("$jacocoInit", 
m.getName())).map(this::getMethodInfo).sorted().toList()).orElse(liste()));
+               this.allMethods = memoize(() -> 
allParents.get().stream().flatMap(c2 -> 
c2.getDeclaredMethods().stream()).toList());
+               this.allMethodsParentFirst = memoize(() -> 
rstream(getAllParents()).flatMap(c2 -> 
c2.getDeclaredMethods().stream()).toList());
+               this.publicFields = memoize(() -> 
parents.get().stream().flatMap(c2 -> c2.getDeclaredFields().stream()).filter(f 
-> f.isPublic() && ne("$jacocoData", 
f.getName())).collect(toMap(FieldInfo::getName, x -> x, (a, b) -> a, 
LinkedHashMap::new)).values().stream().sorted().collect(toList()));
+               this.declaredFields = memoize(() -> opt(inner).map(x -> 
stream(x.getDeclaredFields()).filter(f -> ne("$jacocoData", 
f.getName())).map(this::getFieldInfo).sorted().toList()).orElse(liste()));
+               this.allFields = memoize(() -> 
rstream(allParents.get()).flatMap(c2 -> 
c2.getDeclaredFields().stream()).toList());
+               this.publicConstructors = memoize(() -> opt(inner).map(x -> 
stream(x.getConstructors()).map(this::getConstructorInfo).sorted().toList()).orElse(liste()));
+               this.declaredConstructors = memoize(() -> opt(inner).map(x -> 
stream(x.getDeclaredConstructors()).map(this::getConstructorInfo).sorted().toList()).orElse(liste()));
+               this.repeatedAnnotationMethod = 
memoize(this::findRepeatedAnnotationMethod);
+               this.methodCache = Cache.of(Method.class, 
MethodInfo.class).build();
+               this.fieldCache = Cache.of(Field.class, 
FieldInfo.class).build();
+               this.constructorCache = Cache.of(Constructor.class, 
ConstructorInfo.class).build();
        }
 
        /**
@@ -2460,6 +2343,91 @@ public class ClassInfo extends ElementInfo implements 
Annotatable {
                }
        }
 
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Find methods
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Finds all parent classes and interfaces with proper traversal of 
interface hierarchy.
+        *
+        * @return A list of all parent classes and interfaces without 
duplicates.
+        */
+       private List<ClassInfo> findParentsAndInterfaces() {
+               var set = new LinkedHashSet<ClassInfo>();
+
+               // Process all parent classes (includes this class)
+               var parents = getParents();
+               for (int i = 0; i < parents.size(); i++) {
+                       var parent = parents.get(i);
+                       set.add(parent);
+
+                       // Process interfaces declared on this parent (and 
their parent interfaces)
+                       var declaredInterfaces = parent.getDeclaredInterfaces();
+                       for (int j = 0; j < declaredInterfaces.size(); j++)
+                               addInterfaceHierarchy(set, 
declaredInterfaces.get(j));
+               }
+
+               return u(new ArrayList<>(set));
+       }
+
+       /**
+        * Helper method to recursively add an interface and its parent 
interfaces to the set.
+        *
+        * @param set The set to add to.
+        * @param iface The interface to add.
+        */
+       private void addInterfaceHierarchy(LinkedHashSet<ClassInfo> set, 
ClassInfo iface) {
+               if (!set.add(iface))
+                       return;
+
+               // Process parent interfaces recursively
+               var parentInterfaces = iface.getDeclaredInterfaces();
+               for (int i = 0; i < parentInterfaces.size(); i++)
+                       addInterfaceHierarchy(set, parentInterfaces.get(i));
+       }
+
+       /**
+        * Finds all annotations on this class and parent classes/interfaces in 
child-to-parent order.
+        *
+        * <p>
+        * This is similar to {@link 
org.apache.juneau.common.reflect.AnnotationProvider#find(Class)} but without 
runtime annotations.
+        *
+        * <p>
+        * Order of traversal:
+        * <ol>
+        *      <li>Annotations declared on this class
+        *      <li>Annotations declared on parent classes (child-to-parent 
order)
+        *      <li>For each parent class, annotations on interfaces declared 
on that class (child-to-parent interface hierarchy)
+        *      <li>Annotations on the package of this class
+        * </ol>
+        *
+        * @return A list of all annotation infos in child-to-parent order.
+        */
+       private List<AnnotationInfo<Annotation>> findAnnotationInfos() {
+               var list = new ArrayList<AnnotationInfo<Annotation>>();
+
+               // On all parent classes and interfaces (properly traversed to 
avoid duplicates)
+               var parentsAndInterfaces = getParentsAndInterfaces();
+               for (int i = 0; i < parentsAndInterfaces.size(); i++) {
+                       var ci = parentsAndInterfaces.get(i);
+                       // Add declared annotations from this class/interface
+                       for (var a : ci.inner().getDeclaredAnnotations())
+                               for (var a2 : splitRepeated(a))
+                                       list.add(AnnotationInfo.of(ci, a2));
+               }
+
+               // On the package of this class
+               var pkg = getPackage();
+               if (nn(pkg)) {
+                       var pi = PackageInfo.of(pkg.inner());
+                       for (var a : pkg.inner().getAnnotations())
+                               for (var a2 : splitRepeated(a))
+                                       list.add(AnnotationInfo.of(pi, a2));
+               }
+
+               return u(list);
+       }
+
        
//-----------------------------------------------------------------------------------------------------------------
        // Annotatable interface methods
        
//-----------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ExecutableInfo.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ExecutableInfo.java
index 5a41ef45d6..86b8901376 100644
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ExecutableInfo.java
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ExecutableInfo.java
@@ -20,7 +20,6 @@ import static 
org.apache.juneau.common.reflect.ClassArrayFormat.*;
 import static org.apache.juneau.common.reflect.ClassNameFormat.*;
 import static org.apache.juneau.common.utils.AssertionUtils.*;
 import static org.apache.juneau.common.utils.CollectionUtils.*;
-import static org.apache.juneau.common.utils.PredicateUtils.*;
 import static org.apache.juneau.common.utils.StringUtils.*;
 import static org.apache.juneau.common.utils.Utils.*;
 import static java.util.stream.Collectors.*;
@@ -46,23 +45,28 @@ public abstract class ExecutableInfo extends AccessibleInfo 
{
        private final Executable inner;
        private final boolean isConstructor;
 
-       private final Supplier<List<ParameterInfo>> parameters = 
memoize(this::findParameters);
-       private final Supplier<List<ClassInfo>> exceptions = 
memoize(this::findExceptions);
-       private final Supplier<List<AnnotationInfo<Annotation>>> 
declaredAnnotations = memoize(this::findDeclaredAnnotations);
-       private final Supplier<String> shortName = memoize(this::findShortName);
-       private final Supplier<String> fullName = memoize(this::findFullName);
+       private final Supplier<List<ParameterInfo>> parameters;  // All 
parameters of this executable.
+       private final Supplier<List<ClassInfo>> exceptions;  // All exceptions 
declared by this executable.
+       private final Supplier<List<AnnotationInfo<Annotation>>> 
declaredAnnotations;  // All annotations declared directly on this executable.
+       private final Supplier<String> shortName;  // Short name 
(method/constructor name with parameters).
+       private final Supplier<String> fullName;  // Fully qualified name 
(declaring-class.method-name with parameters).
 
        /**
         * Constructor.
         *
         * @param declaringClass The class that declares this method or 
constructor.
-        * @param e The constructor orĂ¥ method that this info represents.
+        * @param e The constructor or method that this info represents.
         */
        protected ExecutableInfo(ClassInfo declaringClass, Executable e) {
                super(e, e.getModifiers());
                this.declaringClass = declaringClass;
                this.inner = e;
                this.isConstructor = e instanceof Constructor;
+               this.parameters = memoize(this::findParameters);
+               this.exceptions = memoize(() -> 
stream(inner.getExceptionTypes()).map(ClassInfo::of).toList());
+               this.declaredAnnotations = memoize(() -> 
stream(inner.getDeclaredAnnotations()).map(a -> 
AnnotationInfo.of((Annotatable)this, a)).toList());
+               this.shortName = memoize(() -> f("{0}({1})", getSimpleName(), 
getParameters().stream().map(p -> 
p.getParameterType().getNameSimple()).collect(joining(","))));
+               this.fullName = memoize(this::findFullName);
        }
 
        /**
@@ -221,24 +225,6 @@ public abstract class ExecutableInfo extends 
AccessibleInfo {
                return fullName.get();
        }
 
-       private String findFullName() {
-               var sb = new StringBuilder(128);
-               var dc = declaringClass;
-               var pi = dc.getPackage();
-               if (nn(pi))
-                       sb.append(pi.getName()).append('.');
-               dc.appendNameFormatted(sb, SHORT, true, '$', BRACKETS);
-               if (! isConstructor)
-                       sb.append('.').append(getSimpleName());
-               sb.append('(');
-               sb.append(getParameters().stream()
-                       .map(p -> p.getParameterType().getNameFormatted(FULL, 
true, '$', BRACKETS))
-                       .collect(joining(","))
-               );
-               sb.append(')');
-               return sb.toString();
-       }
-
        /**
         * Returns parameter information at the specified index.
         *
@@ -285,10 +271,6 @@ public abstract class ExecutableInfo extends 
AccessibleInfo {
                return shortName.get();
        }
 
-       private String findShortName() {
-               return f("{0}({1})", getSimpleName(), 
getParameters().stream().map(p -> 
p.getParameterType().getNameSimple()).collect(joining(",")));
-       }
-
        /**
         * Returns the simple name of the underlying method.
         *
@@ -741,18 +723,6 @@ public abstract class ExecutableInfo extends 
AccessibleInfo {
                        throw new IndexOutOfBoundsException(format("Invalid 
index ''{0}''.  Parameter count: {1}", index, pc));
        }
 
-       private List<AnnotationInfo<Annotation>> findDeclaredAnnotations() {
-               return stream(inner.getDeclaredAnnotations())
-                       .map(a -> AnnotationInfo.of((Annotatable)this, a))
-                       .toList();
-       }
-
-       private List<ClassInfo> findExceptions() {
-               return stream(inner.getExceptionTypes())
-                       .map(ClassInfo::of)
-                       .toList();
-       }
-
        private List<ParameterInfo> findParameters() {
                var rp = inner.getParameters();
                var ptc = inner.getParameterTypes();
@@ -779,4 +749,22 @@ public abstract class ExecutableInfo extends 
AccessibleInfo {
                        .mapToObj(i -> new ParameterInfo(this, rp[i], i, 
ClassInfo.of(ptc[i], genericTypes[i])))
                        .toList();
        }
+
+       private String findFullName() {
+               var sb = new StringBuilder(128);
+               var dc = declaringClass;
+               var pi = dc.getPackage();
+               if (nn(pi))
+                       sb.append(pi.getName()).append('.');
+               dc.appendNameFormatted(sb, SHORT, true, '$', BRACKETS);
+               if (! isConstructor)
+                       sb.append('.').append(getSimpleName());
+               sb.append('(');
+               sb.append(getParameters().stream()
+                       .map(p -> p.getParameterType().getNameFormatted(FULL, 
true, '$', BRACKETS))
+                       .collect(joining(","))
+               );
+               sb.append(')');
+               return sb.toString();
+       }
 }
\ 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 86717cb262..1bc43a8cf7 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
@@ -68,8 +68,8 @@ public class FieldInfo extends AccessibleInfo implements 
Comparable<FieldInfo>,
        private final Field inner;
        private final ClassInfo declaringClass;
        private final Supplier<ClassInfo> type;
-       private final Supplier<List<AnnotationInfo<Annotation>>> annotations = 
memoize(this::_findAnnotations);
-       private final Supplier<String> fullName = memoize(this::findFullName);
+       private final Supplier<List<AnnotationInfo<Annotation>>> annotations;  
// All annotations on this field.
+       private final Supplier<String> fullName;  // Fully qualified field name 
(declaring-class.field-name).
 
        /**
         * Constructor.
@@ -81,15 +81,9 @@ public class FieldInfo extends AccessibleInfo implements 
Comparable<FieldInfo>,
                super(f, f.getModifiers());
                this.declaringClass = declaringClass;
                this.inner = f;
-               this.type = memoize(() -> findType(f));
-       }
-
-       private static ClassInfo findType(Field f) {
-               return ClassInfo.of(f.getType());
-       }
-
-       private List<AnnotationInfo<Annotation>> _findAnnotations() {
-               return stream(inner.getAnnotations()).map(a -> 
AnnotationInfo.of(this, a)).toList();
+               this.type = memoize(() -> ClassInfo.of(f.getType()));
+               this.annotations = memoize(() -> 
stream(inner.getAnnotations()).map(a -> AnnotationInfo.of(this, a)).toList());
+               this.fullName = memoize(this::findFullName);
        }
 
        private String findFullName() {
diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/PackageInfo.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/PackageInfo.java
index 57a18e9151..555b9c3f2c 100644
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/PackageInfo.java
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/PackageInfo.java
@@ -48,13 +48,13 @@ public class PackageInfo implements Annotatable {
        /**
         * Returns a package info wrapper around the specified package object.
         *
-        * @param p The package object.  Can be <jk>null</jk>.
+        * @param inner The package object.  Can be <jk>null</jk>.
         * @return A package info wrapper, or <jk>null</jk> if the parameter 
was null.
         */
-       public static PackageInfo of(Package p) {
-               if (p == null)
+       public static PackageInfo of(Package inner) {
+               if (inner == null)
                        return null;
-               return CACHE.get(p, () -> new PackageInfo(p));
+               return CACHE.get(inner, () -> new PackageInfo(inner));
        }
 
        /**
@@ -82,9 +82,7 @@ public class PackageInfo implements Annotatable {
        
//-----------------------------------------------------------------------------------------------------------------
 
        private Package inner;  // Effectively final
-
-       // All annotations on this package, wrapped in AnnotationInfo. Repeated 
annotations have been unwrapped and are present as individual instances. 
Lazy-initialized in getter.
-       private final Supplier<List<AnnotationInfo<Annotation>>> annotations = 
memoize(() -> opt(inner).map(p -> stream(p.getAnnotations()).flatMap(a -> 
stream(splitRepeated(a))).map(a -> AnnotationInfo.of(this, 
a)).toList()).orElse(liste()));
+       private final Supplier<List<AnnotationInfo<Annotation>>> annotations;  
// All annotations on this package, wrapped in AnnotationInfo. Repeated 
annotations have been unwrapped and are present as individual instances.
 
        /**
         * Constructor.
@@ -93,6 +91,7 @@ public class PackageInfo implements Annotatable {
         */
        protected PackageInfo(Package p) {
                this.inner = p;
+               this.annotations = memoize(() -> opt(inner).map(pkg -> 
stream(pkg.getAnnotations()).flatMap(a -> stream(splitRepeated(a))).map(a -> 
AnnotationInfo.of(this, a)).toList()).orElse(liste()));
        }
 
        /**
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 95f276ee8e..9a57a7011e 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
@@ -61,8 +61,8 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
        @SuppressWarnings({"rawtypes","unchecked"})
        private final Cache<Class,List<AnnotationInfo<Annotation>>> 
foundAnnotations = 
Cache.<Class,List<AnnotationInfo<Annotation>>>create().supplier((k) -> 
findAnnotationInfosInternal(k)).build();
 
-       private final Supplier<List<AnnotationInfo<Annotation>>> annotations = 
memoize(this::_findAnnotations);
-       private final Supplier<List<ParameterInfo>> matchingParameters = 
memoize(this::_findMatchingParameters);
+       private final Supplier<List<AnnotationInfo<Annotation>>> annotations;  
// All annotations on this parameter.
+       private final Supplier<List<ParameterInfo>> matchingParameters;  // 
Matching parameters in parent methods.
        private final ResettableSupplier<String> foundName = 
memoizeResettable(this::findNameInternal);
        private final ResettableSupplier<String> foundQualifier = 
memoizeResettable(this::findQualifierInternal);
 
@@ -81,6 +81,8 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
                this.inner = p;
                this.index = index;
                this.type = type;
+               this.annotations = memoize(() -> 
stream(inner.getAnnotations()).map(a -> AnnotationInfo.of(this, a)).toList());
+               this.matchingParameters = memoize(this::findMatchingParameters);
        }
 
        /**
@@ -92,10 +94,6 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
                return inner;
        }
 
-       private List<AnnotationInfo<Annotation>> _findAnnotations() {
-               return stream(inner.getAnnotations()).map(a -> 
AnnotationInfo.of(this, a)).toList();
-       }
-
        /**
         * Returns all annotations declared on this parameter.
         *
@@ -226,7 +224,7 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
                return matchingParameters.get();
        }
 
-       private List<ParameterInfo> _findMatchingParameters() {
+       private List<ParameterInfo> findMatchingParameters() {
                if (executable.isConstructor()) {
                        // For constructors: search parent class constructors 
for parameters with matching index and type
                        // Note: We match by index and type only, not by name, 
to avoid circular dependency
@@ -398,16 +396,13 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
 
        private String findQualifierInternal() {
                // Search through matching parameters in hierarchy for @Named 
or javax.inject.Qualifier annotations
-               for (var mp : getMatchingParameters()) {
-                       for (var ai : mp.getAnnotationInfos()) {
-                               if (ai.hasSimpleName("Named") || 
ai.hasSimpleName("Qualifier")) {
-                                       String value = 
ai.getValue().orElse(null);
-                                       if (value != null)
-                                               return value;
-                               }
-                       }
-               }
-               return null;
+               return getMatchingParameters().stream()
+                       .flatMap(mp -> mp.getAnnotationInfos().stream())
+                       .filter(ai -> ai.hasSimpleName("Named") || 
ai.hasSimpleName("Qualifier"))
+                       .map(ai -> ai.getValue().orElse(null))
+                       .filter(Objects::nonNull)
+                       .findFirst()
+                       .orElse(null);
        }
 
        /**


Reply via email to