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

commit 2c9fabf9d4f969956f04835ceb67868927f407e5
Author: James Bognar <[email protected]>
AuthorDate: Fri Nov 7 18:10:11 2025 -0500

    Utility class modernization
---
 .../juneau/common/reflect/ParameterInfo.java       | 102 +++++++++++++--------
 1 file changed, 66 insertions(+), 36 deletions(-)

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 fac0dd1687..a253c49150 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
@@ -59,7 +59,7 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
        private final ClassInfo type;
 
        @SuppressWarnings({"rawtypes","unchecked"})
-       private final Cache<Class,List<AnnotationInfo<Annotation>>> 
allAnnotations = 
Cache.<Class,List<AnnotationInfo<Annotation>>>create().supplier((k) -> 
findAnnotationInfosInternal(k)).build();
+       private final Cache<Class,List<AnnotationInfo<Annotation>>> 
allAnnotations = 
Cache.<Class,List<AnnotationInfo<Annotation>>>create().supplier((k) -> 
findAllAnnotationInfos(k)).build();
 
        private final Supplier<List<AnnotationInfo<Annotation>>> 
declaredAnnotations;  // All annotations declared directly on this parameter.
        private final Supplier<List<ParameterInfo>> matchingParameters;  // 
Matching parameters in parent methods.
@@ -263,14 +263,51 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
        }
 
        /**
-        * Returns all annotation infos of the specified type defined on this 
method parameter.
+        * Returns all annotation infos of the specified type defined on this 
parameter.
         *
         * <p>
-        * Searches through matching parameters in the hierarchy and the 
parameter type.
+        * Performs a comprehensive search through the parameter hierarchy and 
parameter type hierarchy.
+        *
+        * <h5 class='section'>Search Order (child-to-parent):</h5>
+        * <ol>
+        *      <li><b>Matching parameters in hierarchy</b>
+        *              <ul>
+        *                      <li>For methods: This parameter → parent method 
parameters (via {@link #getMatchingParameters()})
+        *                      <li>For constructors: This parameter → parent 
constructor parameters (via {@link #getMatchingParameters()})
+        *              </ul>
+        *      <li><b>Parameter type hierarchy</b> (via {@link 
ClassInfo#getParentsAndInterfaces()})
+        *              <ul>
+        *                      <li>Parameter's class and its interfaces 
(interleaved)
+        *                      <li>Parameter's parent classes and their 
interfaces (interleaved)
+        *                      <li>Continues up to Object class
+        *              </ul>
+        *      <li><b>Package annotation</b> - Package of the parameter type
+        * </ol>
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Given:</jc>
+        *      <jk>class</jk> Parent {
+        *              <jk>void</jk> method(@MyAnnotation String 
<jv>param</jv>) {}
+        *      }
+        *      <jk>class</jk> Child <jk>extends</jk> Parent {
+        *              <ja>@Override</ja>
+        *              <jk>void</jk> method(@MyAnnotation String 
<jv>param</jv>) {}
+        *      }
+        *
+        *      <jc>// Search order for Child.method parameter:</jc>
+        *      ParameterInfo <jv>pi</jv> = 
ClassInfo.<jsm>of</jsm>(Child.<jk>class</jk>).getMethod(<js>"method"</js>, 
String.<jk>class</jk>).getParameter(0);
+        *      List&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; 
<jv>annotations</jv> = 
<jv>pi</jv>.getAllAnnotationInfos(MyAnnotation.<jk>class</jk>);
+        *      <jc>// Returns (in order):</jc>
+        *      <jc>//   1. @MyAnnotation on Child.method parameter</jc>
+        *      <jc>//   2. @MyAnnotation on Parent.method parameter</jc>
+        *      <jc>//   3. Any @MyAnnotation on String class hierarchy</jc>
+        *      <jc>//   4. Any @MyAnnotation on java.lang package</jc>
+        * </p>
         *
         * @param <A> The annotation type to look for.
         * @param type The annotation type to look for.
-        * @return A list of annotation infos found, or an empty list if none 
found.
+        * @return An unmodifiable list of annotation infos in child-to-parent 
order, or an empty list if none found.
         */
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public <A extends Annotation> List<AnnotationInfo<A>> 
getAllAnnotationInfos(Class<A> type) {
@@ -278,14 +315,19 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
        }
 
        /**
-        * Returns the first annotation info of the specified type defined on 
this method parameter.
+        * Returns the first annotation info of the specified type defined on 
this parameter.
         *
         * <p>
-        * Searches through matching parameters in the hierarchy and the 
parameter type.
+        * This is a convenience method that returns the first result from 
{@link #getAllAnnotationInfos(Class)}.
+        *
+        * <p>
+        * Performs a comprehensive search through the parameter hierarchy and 
parameter type hierarchy
+        * in child-to-parent order, returning the first annotation found.
         *
         * @param <A> The annotation type to look for.
         * @param type The annotation type to look for.
-        * @return The annotation info if found, or <jk>null</jk> if not.
+        * @return The first annotation info if found (closest to this 
parameter), or <jk>null</jk> if not found.
+        * @see #getAllAnnotationInfos(Class)
         */
        public <A extends Annotation> AnnotationInfo<A> 
getAllAnnotationInfo(Class<A> type) {
                var list = getAllAnnotationInfos(type);
@@ -750,10 +792,10 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
        }
 
        @SuppressWarnings("unchecked")
-       private <A extends Annotation> List<AnnotationInfo<A>> 
findAnnotationInfosInternal(Class<A> type) {
+       private <A extends Annotation> List<AnnotationInfo<A>> 
findAllAnnotationInfos(Class<A> type) {
                var list = new ArrayList<AnnotationInfo<A>>();
 
-               // Search through matching parameters in hierarchy
+               // Search through matching parameters in hierarchy 
(child-to-parent order)
                for (var mp : getMatchingParameters()) {
                        mp.getAnnotationInfos().stream()
                                .filter(x -> x.isType(type))
@@ -761,38 +803,26 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
                                .forEach(list::add);
                }
 
-               // Search on parameter type
+               // Search parameter type hierarchy in child-to-parent order 
(interleaved classes and interfaces)
                var paramType = 
executable.getParameter(index).getParameterType().unwrap(Value.class, 
Optional.class);
-               paramType.getDeclaredAnnotationInfos().stream()
-                       .filter(x -> x.isType(type))
-                       .map(x -> (AnnotationInfo<A>)x)
-                       .forEach(list::add);
+               
+               // Traverse parent classes and interfaces (child-to-parent, 
interleaved)
+               var parentsAndInterfaces = paramType.getParentsAndInterfaces();
+               for (int i = 0; i < parentsAndInterfaces.size(); i++) {
+                       
parentsAndInterfaces.get(i).getDeclaredAnnotationInfos().stream()
+                               .filter(x -> x.isType(type))
+                               .map(x -> (AnnotationInfo<A>)x)
+                               .forEach(list::add);
+               }
+               
+               // Package annotation (last)
+               var packageAnn = paramType.getPackageAnnotation(type);
+               if (nn(packageAnn))
+                       list.add(AnnotationInfo.of(paramType, packageAnn));
 
                return list;
        }
 
-       private <A extends Annotation> ParameterInfo 
forEachAnnotation(AnnotationProvider ap, Class<A> a, Predicate<A> filter, 
Consumer<A> action) {
-               if (executable.isConstructor()) {
-                       var ci = 
executable.getParameter(index).getParameterType().unwrap(Value.class, 
Optional.class);
-                       var annotationInfos = getAnnotationInfos();
-                       ap.forEachClassAnnotation(a, ci, filter, action);
-                       for (var ai : annotationInfos)
-                               if (a.isInstance(ai.inner()))
-                                       consumeIf(filter, action, 
a.cast(ai.inner()));
-               } else {
-                       var mi = (MethodInfo)executable;
-                       var ci = 
executable.getParameter(index).getParameterType().unwrap(Value.class, 
Optional.class);
-                       ap.forEachClassAnnotation(a, ci, filter, action);
-                       rstream(mi.getMatchingMethods()).forEach(x -> {
-                               
x.getParameter(index).getAnnotationInfos().stream()
-                                       .filter(ai -> a.isInstance(ai.inner()))
-                                       .map(ai -> a.cast(ai.inner()))
-                                       .forEach(ann -> consumeIf(filter, 
action, ann));
-                       });
-               }
-               return this;
-       }
-
        
//-----------------------------------------------------------------------------------------------------------------
        // Annotatable interface methods
        
//-----------------------------------------------------------------------------------------------------------------

Reply via email to