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 81b1eee387 Improvements to ClassInfo APIs
81b1eee387 is described below

commit 81b1eee387e98226c0cad616917997a309eaf081
Author: James Bognar <[email protected]>
AuthorDate: Thu Nov 13 08:51:03 2025 -0500

    Improvements to ClassInfo APIs
---
 .../juneau/common/reflect/AnnotationProvider.java  | 286 +++++++++++++++++++++
 .../juneau/common/reflect/AnnotationTraversal.java | 250 ++++++++++++++++++
 .../apache/juneau/common/reflect/ClassInfo.java    |  73 ++++++
 .../juneau/common/reflect/ConstructorInfo.java     |  62 +++++
 .../apache/juneau/common/reflect/FieldInfo.java    |  59 ++++-
 .../apache/juneau/common/reflect/MethodInfo.java   |  74 ++++++
 .../juneau/common/reflect/ParameterInfo.java       |  65 +++++
 7 files changed, 868 insertions(+), 1 deletion(-)

diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider.java
index eb09b86a4a..5021f6f062 100644
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider.java
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider.java
@@ -20,7 +20,9 @@ import static org.apache.juneau.common.utils.AssertionUtils.*;
 import static org.apache.juneau.common.utils.ClassUtils.*;
 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 static org.apache.juneau.common.reflect.AnnotationTraversal.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
@@ -912,4 +914,288 @@ public class AnnotationProvider {
                for (int i = parents2.size() - 1; i >= 0; i--)
                        findDeclaredParentFirst(type, 
parents2.get(i).inner()).map(x -> x.inner()).filter(x -> filter == null || 
filter.test(x)).forEach(x -> action.accept(x));
        }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Stream-based traversal methods
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Streams annotations from a class using configurable traversal 
options.
+        *
+        * <p>
+        * This method provides a flexible, stream-based API for traversing 
annotations without creating intermediate lists.
+        * It uses {@link AnnotationTraversal} enums to configure what elements 
to search and in what order.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Search class only</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
+        *              search(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF);
+        *
+        *      <jc>// Search class and parents</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> =
+        *              search(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF, 
PARENTS);
+        *
+        *      <jc>// Search class, parents, and package (parent-first order 
using rstream)</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s3</jv> =
+        *              rstream(search(MyAnnotation.<jk>class</jk>, 
<jv>ci</jv>, SELF, PARENTS, PACKAGE).toList());
+        * </p>
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param clazz The class to search.
+        * @param traversals The traversal options (what to search and order).
+        * @return A stream of {@link AnnotationInfo} objects. Never 
<jk>null</jk>.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotations(Class<A> type, ClassInfo clazz, AnnotationTraversal... 
traversals) {
+               assertArgNotNull("type", type);
+               assertArgNotNull("clazz", clazz);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == SELF) {
+                                       return findDeclared(type, 
clazz.inner());
+                               } else if (traversal == PARENTS) {
+                                       return 
clazz.getParentsAndInterfaces().stream().flatMap(x -> findDeclared(type, 
x.inner()));
+                               } else if (traversal == PACKAGE) {
+                                       A packageAnn = 
clazz.getPackageAnnotation(type);
+                                       return nn(packageAnn) ? 
Stream.of(AnnotationInfo.of(clazz, packageAnn)) : Stream.empty();
+                               }
+                               throw illegalArg("Invalid traversal type for 
class annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Streams annotations from a class using configurable traversal 
options in parent-first order.
+        *
+        * <p>
+        * This is equivalent to calling {@link #findAnnotations(Class, 
ClassInfo, AnnotationTraversal...)} 
+        * and reversing the result.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param clazz The class to search.
+        * @param traversals The traversal options (what to search and order).
+        * @return A stream of {@link AnnotationInfo} objects in parent-first 
order. Never <jk>null</jk>.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotationsParentFirst(Class<A> type, ClassInfo clazz, 
AnnotationTraversal... traversals) {
+               return rstream(findAnnotations(type, clazz, 
traversals).toList());
+       }
+
+       /**
+        * Streams annotations from a method using configurable traversal 
options.
+        *
+        * <p>
+        * This method provides a flexible, stream-based API for traversing 
method annotations without creating intermediate lists.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Search method and matching parent methods</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
+        *              findAnnotations(MyAnnotation.<jk>class</jk>, 
<jv>mi</jv>, SELF, MATCHING_METHODS);
+        *
+        *      <jc>// Search method, matching methods, and return type 
(parent-first using findAnnotationsParentFirst)</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> =
+        *              findAnnotationsParentFirst(MyAnnotation.<jk>class</jk>, 
<jv>mi</jv>, SELF, MATCHING_METHODS, RETURN_TYPE);
+        * </p>
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param method The method to search.
+        * @param traversals The traversal options.
+        * @return A stream of {@link AnnotationInfo} objects. Never 
<jk>null</jk>.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotations(Class<A> type, MethodInfo method, AnnotationTraversal... 
traversals) {
+               assertArgNotNull("type", type);
+               assertArgNotNull("method", method);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == SELF) {
+                                       return find(type, method.inner());
+                               } else if (traversal == MATCHING_METHODS) {
+                                       return 
method.getMatchingMethods().stream().skip(1).flatMap(x -> find(type, 
x.inner()));
+                               } else if (traversal == RETURN_TYPE) {
+                                       return findAnnotations(type, 
method.getReturnType().unwrap(Value.class, Optional.class), PARENTS);
+                               }
+                               throw illegalArg("Invalid traversal type for 
method annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Streams annotations from a method using configurable traversal 
options in parent-first order.
+        *
+        * <p>
+        * This is equivalent to calling {@link #findAnnotations(Class, 
MethodInfo, AnnotationTraversal...)} 
+        * and reversing the result.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param method The method to search.
+        * @param traversals The traversal options.
+        * @return A stream of {@link AnnotationInfo} objects in parent-first 
order. Never <jk>null</jk>.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotationsParentFirst(Class<A> type, MethodInfo method, 
AnnotationTraversal... traversals) {
+               return rstream(findAnnotations(type, method, 
traversals).toList());
+       }
+
+       /**
+        * Streams annotations from a parameter using configurable traversal 
options.
+        *
+        * <p>
+        * This method provides a flexible, stream-based API for traversing 
parameter annotations without creating intermediate lists.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Search parameter, matching parameters, and parameter 
type</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
+        *              findAnnotations(MyAnnotation.<jk>class</jk>, 
<jv>pi</jv>, SELF, MATCHING_PARAMETERS, PARAMETER_TYPE);
+        *
+        *      <jc>// Search in parent-first order using 
findAnnotationsParentFirst</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> =
+        *              findAnnotationsParentFirst(MyAnnotation.<jk>class</jk>, 
<jv>pi</jv>, SELF, MATCHING_PARAMETERS, PARAMETER_TYPE);
+        * </p>
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param parameter The parameter to search.
+        * @param traversals The traversal options.
+        * @return A stream of {@link AnnotationInfo} objects. Never 
<jk>null</jk>.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotations(Class<A> type, ParameterInfo parameter, AnnotationTraversal... 
traversals) {
+               assertArgNotNull("type", type);
+               assertArgNotNull("parameter", parameter);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == SELF) {
+                                       return 
parameter.getAnnotationInfos(type);
+                               } else if (traversal == MATCHING_PARAMETERS) {
+                                       return 
parameter.getMatchingParameters().stream().skip(1).flatMap(x -> 
x.getAnnotationInfos(type));
+                               } else if (traversal == PARAMETER_TYPE) {
+                                       return findAnnotations(type, 
parameter.getParameterType().unwrap(Value.class, Optional.class), PARENTS, 
PACKAGE);
+                               }
+                               throw illegalArg("Invalid traversal type for 
parameter annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Streams annotations from a parameter using configurable traversal 
options in parent-first order.
+        *
+        * <p>
+        * This is equivalent to calling {@link #findAnnotations(Class, 
ParameterInfo, AnnotationTraversal...)} 
+        * and reversing the result.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param parameter The parameter to search.
+        * @param traversals The traversal options.
+        * @return A stream of {@link AnnotationInfo} objects in parent-first 
order. Never <jk>null</jk>.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotationsParentFirst(Class<A> type, ParameterInfo parameter, 
AnnotationTraversal... traversals) {
+               return rstream(findAnnotations(type, parameter, 
traversals).toList());
+       }
+
+       /**
+        * Streams annotations from a field using configurable traversal 
options.
+        *
+        * <p>
+        * This method provides a flexible, stream-based API for traversing 
field annotations without creating intermediate lists.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Search field annotations</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
+        *              findAnnotations(MyAnnotation.<jk>class</jk>, 
<jv>fi</jv>, SELF);
+        * </p>
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param field The field to search.
+        * @param traversals The traversal options.
+        * @return A stream of {@link AnnotationInfo} objects. Never 
<jk>null</jk>.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotations(Class<A> type, FieldInfo field, AnnotationTraversal... 
traversals) {
+               assertArgNotNull("type", type);
+               assertArgNotNull("field", field);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == SELF) {
+                                       return find(type, field.inner());
+                               }
+                               throw illegalArg("Invalid traversal type for 
field annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Streams annotations from a field using configurable traversal 
options in parent-first order.
+        *
+        * <p>
+        * This is equivalent to calling {@link #findAnnotations(Class, 
FieldInfo, AnnotationTraversal...)} 
+        * and reversing the result.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param field The field to search.
+        * @param traversals The traversal options.
+        * @return A stream of {@link AnnotationInfo} objects in parent-first 
order. Never <jk>null</jk>.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotationsParentFirst(Class<A> type, FieldInfo field, 
AnnotationTraversal... traversals) {
+               return rstream(findAnnotations(type, field, 
traversals).toList());
+       }
+
+       /**
+        * Streams annotations from a constructor using configurable traversal 
options.
+        *
+        * <p>
+        * This method provides a flexible, stream-based API for traversing 
constructor annotations without creating intermediate lists.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Search constructor annotations</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
+        *              findAnnotations(MyAnnotation.<jk>class</jk>, 
<jv>ci</jv>, SELF);
+        * </p>
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param constructor The constructor to search.
+        * @param traversals The traversal options.
+        * @return A stream of {@link AnnotationInfo} objects. Never 
<jk>null</jk>.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotations(Class<A> type, ConstructorInfo constructor, 
AnnotationTraversal... traversals) {
+               assertArgNotNull("type", type);
+               assertArgNotNull("constructor", constructor);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == SELF) {
+                                       return find(type, constructor.inner());
+                               }
+                               throw illegalArg("Invalid traversal type for 
constructor annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Streams annotations from a constructor using configurable traversal 
options in parent-first order.
+        *
+        * <p>
+        * This is equivalent to calling {@link #findAnnotations(Class, 
ConstructorInfo, AnnotationTraversal...)} 
+        * and reversing the result.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param constructor The constructor to search.
+        * @param traversals The traversal options.
+        * @return A stream of {@link AnnotationInfo} objects in parent-first 
order. Never <jk>null</jk>.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotationsParentFirst(Class<A> type, ConstructorInfo constructor, 
AnnotationTraversal... traversals) {
+               return rstream(findAnnotations(type, constructor, 
traversals).toList());
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationTraversal.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationTraversal.java
new file mode 100644
index 0000000000..a9a9afb4ab
--- /dev/null
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationTraversal.java
@@ -0,0 +1,250 @@
+/*
+ * 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;
+
+/**
+ * Defines traversal options for annotation searches.
+ *
+ * <p>
+ * These enums configure what elements to traverse and in what order when 
searching for annotations.
+ * They are used with {@link AnnotationProvider#search(Class, ClassInfo, 
AnnotationTraversal...)} 
+ * and related methods.
+ *
+ * <p>
+ * Each traversal type has an order of precedence that determines the search 
order.
+ * When multiple traversal types are specified, they are automatically sorted 
by their precedence
+ * to ensure consistent behavior regardless of the order they are specified.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ *     <jc>// These produce the same result (automatically sorted by 
precedence):</jc>
+ *     Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> = 
+ *             
annotationProvider.streamClassAnnotations(MyAnnotation.<jk>class</jk>, 
<jv>ci</jv>, PACKAGE, PARENTS, SELF);
+ *     Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> = 
+ *             
annotationProvider.streamClassAnnotations(MyAnnotation.<jk>class</jk>, 
<jv>ci</jv>, SELF, PARENTS, PACKAGE);
+ * </p>
+ *
+ * <h5 class='section'>See Also:</h5><ul>
+ *     <li class='jc'>{@link AnnotationProvider}
+ *     <li class='jm'>{@link AnnotationProvider#search(Class, ClassInfo, 
AnnotationTraversal...)}
+ *     <li class='jm'>{@link AnnotationProvider#search(Class, MethodInfo, 
AnnotationTraversal...)}
+ *     <li class='jm'>{@link AnnotationProvider#search(Class, ParameterInfo, 
AnnotationTraversal...)}
+ * </ul>
+ */
+public enum AnnotationTraversal {
+
+       /**
+        * Include the element itself (class, method, field, constructor, 
parameter).
+        *
+        * <p>
+        * This searches for annotations directly declared on the target 
element.
+        *
+        * <h5 class='section'>Applicable to:</h5>
+        * All element types (classes, methods, fields, constructors, 
parameters).
+        *
+        * <h5 class='section'>Order:</h5>
+        * Precedence: 10 (highest - searched first)
+        */
+       SELF(10),
+
+       /**
+        * Include parent classes and interfaces in the traversal.
+        *
+        * <p>
+        * For classes: Traverses the superclass hierarchy and all implemented 
interfaces,
+        * interleaved in child-to-parent order (using {@link 
ClassInfo#getParentsAndInterfaces()}).
+        * Default order is child-to-parent unless {@link #REVERSE} is 
specified.
+        *
+        * <h5 class='section'>Applicable to:</h5>
+        * Classes.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Given: class Child extends Parent implements 
Interface</jc>
+        *      <jc>// Traverses parents and interfaces interleaved: Parent → 
Interface → GrandParent → ...</jc>
+        * </p>
+        *
+        * <h5 class='section'>Order:</h5>
+        * Precedence: 20
+        */
+       PARENTS(20),
+
+       /**
+        * Include matching methods in the traversal.
+        *
+        * <p>
+        * For methods: Searches annotations on methods with the same signature 
in parent classes and interfaces.
+        * This finds annotations on overridden methods.
+        *
+        * <h5 class='section'>Applicable to:</h5>
+        * Methods.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Given:</jc>
+        *      <jk>class</jk> Parent {
+        *              <ja>@MyAnnotation</ja>
+        *              <jk>public void</jk> method() {}
+        *      }
+        *      <jk>class</jk> Child <jk>extends</jk> Parent {
+        *              <ja>@Override</ja>
+        *              <jk>public void</jk> method() {}  <jc>// Will find 
@MyAnnotation from Parent</jc>
+        *      }
+        * </p>
+        *
+        * <h5 class='section'>Order:</h5>
+        * Precedence: 20
+        */
+       MATCHING_METHODS(20),
+
+       /**
+        * Include matching parameters in the traversal.
+        *
+        * <p>
+        * For parameters: Searches annotations on parameters in matching 
parent methods or constructors.
+        * This finds annotations on parameters in overridden methods or parent 
constructors.
+        *
+        * <h5 class='section'>Applicable to:</h5>
+        * Parameters.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Given:</jc>
+        *      <jk>class</jk> Parent {
+        *              <jk>public void</jk> method(<ja>@MyAnnotation</ja> 
String <jv>param</jv>) {}
+        *      }
+        *      <jk>class</jk> Child <jk>extends</jk> Parent {
+        *              <ja>@Override</ja>
+        *              <jk>public void</jk> method(String <jv>param</jv>) {}  
<jc>// Will find @MyAnnotation from Parent</jc>
+        *      }
+        * </p>
+        *
+        * <h5 class='section'>Order:</h5>
+        * Precedence: 20
+        */
+       MATCHING_PARAMETERS(20),
+
+       /**
+        * Include the return type in the traversal.
+        *
+        * <p>
+        * For methods: Searches annotations on the method's return type and 
its hierarchy.
+        * Automatically includes {@link #PARENTS} of the return type.
+        *
+        * <h5 class='section'>Applicable to:</h5>
+        * Methods.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Given: public MyClass myMethod() {...}</jc>
+        *      <jc>// Searches: MyClass hierarchy and its interfaces</jc>
+        * </p>
+        *
+        * <h5 class='section'>Order:</h5>
+        * Precedence: 30
+        */
+       RETURN_TYPE(30),
+
+       /**
+        * Include the parameter type in the traversal.
+        *
+        * <p>
+        * For parameters: Searches annotations on the parameter's type and its 
hierarchy.
+        * Automatically includes {@link #PARENTS} and {@link #PACKAGE} of the 
parameter type.
+        *
+        * <h5 class='section'>Applicable to:</h5>
+        * Parameters.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Given: void method(MyClass param) {...}</jc>
+        *      <jc>// Searches: MyClass hierarchy, its interfaces, and 
package</jc>
+        * </p>
+        *
+        * <h5 class='section'>Order:</h5>
+        * Precedence: 30
+        */
+       PARAMETER_TYPE(30),
+
+       /**
+        * Include package annotations in the traversal.
+        *
+        * <p>
+        * Searches for annotations on the package-info class.
+        *
+        * <h5 class='section'>Applicable to:</h5>
+        * Classes and parameters (via {@link #PARAMETER_TYPE}).
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Searches annotations in package-info.java</jc>
+        * </p>
+        *
+        * <h5 class='section'>Order:</h5>
+        * Precedence: 40 (lowest - searched last)
+        */
+       PACKAGE(40),
+
+       /**
+        * Reverse the order of the resulting stream.
+        *
+        * <p>
+        * When this flag is present, the final stream is wrapped in {@code 
rstream()} to reverse the order.
+        * This allows parent-first ordering (parent annotations before child 
annotations).
+        *
+        * <p>
+        * By default, traversals return results in child-to-parent order 
(child annotations first).
+        * Using {@code REVERSE} changes this to parent-to-child order (parent 
annotations first).
+        *
+        * <h5 class='section'>Applicable to:</h5>
+        * All stream-based traversal methods.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Default (child-first): Child → Parent → GrandParent</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> = 
+        *              streamClassAnnotations(MyAnnotation.<jk>class</jk>, 
<jv>ci</jv>, PARENTS);
+        *
+        *      <jc>// With REVERSE (parent-first): GrandParent → Parent → 
Child</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> = 
+        *              streamClassAnnotations(MyAnnotation.<jk>class</jk>, 
<jv>ci</jv>, PARENTS, REVERSE);
+        * </p>
+        *
+        * <h5 class='section'>Order:</h5>
+        * Precedence: 999 (modifier - does not affect traversal order)
+        */
+       REVERSE(999);
+
+       private final int order;
+
+       AnnotationTraversal(int order) {
+               this.order = order;
+       }
+
+       /**
+        * Returns the precedence order of this traversal type.
+        *
+        * <p>
+        * Lower values have higher precedence and are processed first.
+        *
+        * @return The order value.
+        */
+       public int getOrder() {
+               return order;
+       }
+}
+
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 393d4b1077..11767a3651 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
@@ -752,6 +752,79 @@ public class ClassInfo extends ElementInfo implements 
Annotatable {
                        .map(a -> (AnnotationInfo<A>)a);
        }
 
+       /**
+        * Finds annotations on this class using the specified traversal 
settings.
+        *
+        * <p>
+        * This method allows flexible annotation traversal across different 
scopes using {@link AnnotationTraversal} enums.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Search class only</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
+        *              
<jv>ci</jv>.findAnnotations(MyAnnotation.<jk>class</jk>, SELF);
+        *
+        *      <jc>// Search class and parents</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> =
+        *              
<jv>ci</jv>.findAnnotations(MyAnnotation.<jk>class</jk>, SELF, PARENTS);
+        *
+        *      <jc>// Search class, parents, and package</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s3</jv> =
+        *              
<jv>ci</jv>.findAnnotations(MyAnnotation.<jk>class</jk>, SELF, PARENTS, 
PACKAGE);
+        * </p>
+        *
+        * <p>
+        * This does NOT include runtime annotations. For runtime annotation 
support, use
+        * {@link org.apache.juneau.common.reflect.AnnotationProvider}.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param traversals The traversal settings defining what to search 
(e.g., SELF, PARENTS, PACKAGE).
+        * @return A stream of annotation infos matching the specified type and 
traversal settings.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotations(Class<A> type, AnnotationTraversal... traversals) {
+               assertArgNotNull("type", type);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == AnnotationTraversal.SELF) {
+                                       return 
Arrays.stream(inner.getDeclaredAnnotations())
+                                               .flatMap(a -> 
Arrays.stream(splitRepeated(a)))
+                                               .map(a -> 
AnnotationInfo.of(this, a))
+                                               .filter(a -> a.isType(type))
+                                               .map(a -> (AnnotationInfo<A>)a);
+                               } else if (traversal == 
AnnotationTraversal.PARENTS) {
+                                       return 
getParentsAndInterfaces().stream()
+                                               .flatMap(x -> 
Arrays.stream(x.inner().getDeclaredAnnotations())
+                                                       .flatMap(a -> 
Arrays.stream(splitRepeated(a)))
+                                                       .map(a -> 
AnnotationInfo.of(x, a))
+                                                       .filter(a -> 
a.isType(type))
+                                                       .map(a -> 
(AnnotationInfo<A>)a));
+                               } else if (traversal == 
AnnotationTraversal.PACKAGE) {
+                                       A packageAnn = 
getPackageAnnotation(type);
+                                       return nn(packageAnn) ? 
Stream.of(AnnotationInfo.of(this, packageAnn)) : Stream.empty();
+                               }
+                               throw illegalArg("Invalid traversal type for 
class annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Finds annotations on this class using the specified traversal 
settings in parent-first order.
+        *
+        * <p>
+        * This method is identical to {@link #findAnnotations(Class, 
AnnotationTraversal...)} but returns
+        * results in parent-to-child order.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param traversals The traversal settings defining what to search 
(e.g., SELF, PARENTS, PACKAGE).
+        * @return A stream of annotation infos matching the specified type and 
traversal settings in parent-first order.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotationsParentFirst(Class<A> type, AnnotationTraversal... traversals) {
+               return rstream(findAnnotations(type, traversals).toList());
+       }
+
        /**
         * Returns the first matching method on this class.
         *
diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ConstructorInfo.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ConstructorInfo.java
index 6b3b874af9..c14b510661 100644
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ConstructorInfo.java
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/ConstructorInfo.java
@@ -17,8 +17,15 @@
 package org.apache.juneau.common.reflect;
 
 import static org.apache.juneau.common.utils.AssertionUtils.*;
+import static org.apache.juneau.common.utils.ClassUtils.*;
+import static org.apache.juneau.common.utils.CollectionUtils.*;
+import static org.apache.juneau.common.utils.ThrowableUtils.*;
+import static org.apache.juneau.common.utils.Utils.*;
 
+import java.lang.annotation.*;
 import java.lang.reflect.*;
+import java.util.*;
+import java.util.stream.*;
 
 import org.apache.juneau.common.utils.*;
 
@@ -88,6 +95,61 @@ public class ConstructorInfo extends ExecutableInfo 
implements Comparable<Constr
                return this;
        }
 
+       /**
+        * Finds annotations on this constructor using the specified traversal 
settings.
+        *
+        * <p>
+        * This method allows flexible annotation traversal across different 
scopes using {@link AnnotationTraversal} enums.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Search constructor only</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
+        *              
<jv>ci</jv>.findAnnotations(MyAnnotation.<jk>class</jk>, SELF);
+        * </p>
+        *
+        * <p>
+        * This does NOT include runtime annotations. For runtime annotation 
support, use
+        * {@link org.apache.juneau.common.reflect.AnnotationProvider}.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param traversals The traversal settings defining what to search 
(currently only SELF is supported for constructors).
+        * @return A stream of annotation infos matching the specified type and 
traversal settings.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotations(Class<A> type, AnnotationTraversal... traversals) {
+               assertArgNotNull("type", type);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == AnnotationTraversal.SELF) {
+                                       return 
Arrays.stream(inner.getDeclaredAnnotations())
+                                               .flatMap(a -> 
Arrays.stream(splitRepeated(a)))
+                                               .map(a -> 
AnnotationInfo.of(this, a))
+                                               .filter(a -> a.isType(type))
+                                               .map(a -> (AnnotationInfo<A>)a);
+                               }
+                               throw illegalArg("Invalid traversal type for 
constructor annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Finds annotations on this constructor using the specified traversal 
settings in parent-first order.
+        *
+        * <p>
+        * This method is identical to {@link #findAnnotations(Class, 
AnnotationTraversal...)} but returns
+        * results in parent-to-child order.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param traversals The traversal settings defining what to search 
(currently only SELF is supported for constructors).
+        * @return A stream of annotation infos matching the specified type and 
traversal settings in parent-first order.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotationsParentFirst(Class<A> type, AnnotationTraversal... traversals) {
+               return rstream(findAnnotations(type, traversals).toList());
+       }
+
        @Override
        public int compareTo(ConstructorInfo o) {
                int i = getSimpleName().compareTo(o.getSimpleName());
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 827c0f486b..2d6dcf1961 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
@@ -19,8 +19,10 @@ package org.apache.juneau.common.reflect;
 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.ClassUtils.*;
+import static org.apache.juneau.common.utils.CollectionUtils.*;
+import static org.apache.juneau.common.utils.ThrowableUtils.*;
 import static org.apache.juneau.common.utils.Utils.*;
-import static java.util.Arrays.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
@@ -117,6 +119,61 @@ public class FieldInfo extends AccessibleInfo implements 
Comparable<FieldInfo>,
                        .map(x -> (AnnotationInfo<A>)x);
        }
 
+       /**
+        * Finds annotations on this field using the specified traversal 
settings.
+        *
+        * <p>
+        * This method allows flexible annotation traversal across different 
scopes using {@link AnnotationTraversal} enums.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Search field only</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
+        *              
<jv>fi</jv>.findAnnotations(MyAnnotation.<jk>class</jk>, SELF);
+        * </p>
+        *
+        * <p>
+        * This does NOT include runtime annotations. For runtime annotation 
support, use
+        * {@link org.apache.juneau.common.reflect.AnnotationProvider}.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param traversals The traversal settings defining what to search 
(currently only SELF is supported for fields).
+        * @return A stream of annotation infos matching the specified type and 
traversal settings.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotations(Class<A> type, AnnotationTraversal... traversals) {
+               assertArgNotNull("type", type);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == AnnotationTraversal.SELF) {
+                                       return 
Arrays.stream(inner.getDeclaredAnnotations())
+                                               .flatMap(a -> 
Arrays.stream(splitRepeated(a)))
+                                               .map(a -> 
AnnotationInfo.of(this, a))
+                                               .filter(a -> a.isType(type))
+                                               .map(a -> (AnnotationInfo<A>)a);
+                               }
+                               throw illegalArg("Invalid traversal type for 
field annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Finds annotations on this field using the specified traversal 
settings in parent-first order.
+        *
+        * <p>
+        * This method is identical to {@link #findAnnotations(Class, 
AnnotationTraversal...)} but returns
+        * results in parent-to-child order.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param traversals The traversal settings defining what to search 
(currently only SELF is supported for fields).
+        * @return A stream of annotation infos matching the specified type and 
traversal settings in parent-first order.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotationsParentFirst(Class<A> type, AnnotationTraversal... traversals) {
+               return rstream(findAnnotations(type, traversals).toList());
+       }
+
        /**
         * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and 
quietly ignores security exceptions.
         *
diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/MethodInfo.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/MethodInfo.java
index 5addb984f3..fa319ca42d 100644
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/MethodInfo.java
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/MethodInfo.java
@@ -17,8 +17,10 @@
 package org.apache.juneau.common.reflect;
 
 import static org.apache.juneau.common.utils.AssertionUtils.*;
+import static org.apache.juneau.common.utils.ClassUtils.*;
 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.beans.*;
@@ -169,6 +171,78 @@ public class MethodInfo extends ExecutableInfo implements 
Comparable<MethodInfo>
                        .map(a -> (AnnotationInfo<A>)a);
        }
 
+       /**
+        * Finds annotations on this method using the specified traversal 
settings.
+        *
+        * <p>
+        * This method allows flexible annotation traversal across different 
scopes using {@link AnnotationTraversal} enums.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Search method only</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
+        *              
<jv>mi</jv>.findAnnotations(MyAnnotation.<jk>class</jk>, SELF);
+        *
+        *      <jc>// Search method and matching methods in parent classes</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> =
+        *              
<jv>mi</jv>.findAnnotations(MyAnnotation.<jk>class</jk>, SELF, 
MATCHING_METHODS);
+        *
+        *      <jc>// Search method, matching methods, and return type</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s3</jv> =
+        *              
<jv>mi</jv>.findAnnotations(MyAnnotation.<jk>class</jk>, SELF, 
MATCHING_METHODS, RETURN_TYPE);
+        * </p>
+        *
+        * <p>
+        * This does NOT include runtime annotations. For runtime annotation 
support, use
+        * {@link org.apache.juneau.common.reflect.AnnotationProvider}.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param traversals The traversal settings defining what to search 
(e.g., SELF, MATCHING_METHODS, RETURN_TYPE).
+        * @return A stream of annotation infos matching the specified type and 
traversal settings.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotations(Class<A> type, AnnotationTraversal... traversals) {
+               assertArgNotNull("type", type);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == AnnotationTraversal.SELF) {
+                                       return 
Arrays.stream(inner.getDeclaredAnnotations())
+                                               .flatMap(a -> 
Arrays.stream(splitRepeated(a)))
+                                               .map(a -> 
AnnotationInfo.of(this, a))
+                                               .filter(a -> a.isType(type))
+                                               .map(a -> (AnnotationInfo<A>)a);
+                               } else if (traversal == 
AnnotationTraversal.MATCHING_METHODS) {
+                                       return 
getMatchingMethods().stream().skip(1)
+                                               .flatMap(x -> 
Arrays.stream(x.inner().getDeclaredAnnotations())
+                                                       .flatMap(a -> 
Arrays.stream(splitRepeated(a)))
+                                                       .map(a -> 
AnnotationInfo.of(x, a))
+                                                       .filter(a -> 
a.isType(type))
+                                                       .map(a -> 
(AnnotationInfo<A>)a));
+                               } else if (traversal == 
AnnotationTraversal.RETURN_TYPE) {
+                                       return 
getReturnType().unwrap(Value.class, Optional.class).findAnnotations(type, 
AnnotationTraversal.PARENTS);
+                               }
+                               throw illegalArg("Invalid traversal type for 
method annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Finds annotations on this method using the specified traversal 
settings in parent-first order.
+        *
+        * <p>
+        * This method is identical to {@link #findAnnotations(Class, 
AnnotationTraversal...)} but returns
+        * results in parent-to-child order.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param traversals The traversal settings defining what to search 
(e.g., SELF, MATCHING_METHODS, RETURN_TYPE).
+        * @return A stream of annotation infos matching the specified type and 
traversal settings in parent-first order.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotationsParentFirst(Class<A> type, AnnotationTraversal... traversals) {
+               return rstream(findAnnotations(type, traversals).toList());
+       }
+
        /**
         * Returns all annotations on the declaring class, this method and 
parent overridden methods, return type, and package in child-to-parent order.
         *
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 caacb793bd..29b0bee81d 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
@@ -17,8 +17,10 @@
 package org.apache.juneau.common.reflect;
 
 
+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.ThrowableUtils.*;
 import static org.apache.juneau.common.utils.Utils.*;
 
 import java.lang.annotation.*;
@@ -128,6 +130,69 @@ public class ParameterInfo extends ElementInfo implements 
Annotatable {
                return getAnnotationInfos().stream().filter(x -> 
x.isType(type)).map(x -> (AnnotationInfo<A>)x);
        }
 
+       /**
+        * Finds annotations on this parameter using the specified traversal 
settings.
+        *
+        * <p>
+        * This method allows flexible annotation traversal across different 
scopes using {@link AnnotationTraversal} enums.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Search parameter only</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
+        *              
<jv>pi</jv>.findAnnotations(MyAnnotation.<jk>class</jk>, SELF);
+        *
+        *      <jc>// Search parameter and matching parameters in parent 
methods</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> =
+        *              
<jv>pi</jv>.findAnnotations(MyAnnotation.<jk>class</jk>, SELF, 
MATCHING_PARAMETERS);
+        *
+        *      <jc>// Search parameter, matching parameters, and parameter 
type</jc>
+        *      Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s3</jv> =
+        *              
<jv>pi</jv>.findAnnotations(MyAnnotation.<jk>class</jk>, SELF, 
MATCHING_PARAMETERS, PARAMETER_TYPE);
+        * </p>
+        *
+        * <p>
+        * This does NOT include runtime annotations. For runtime annotation 
support, use
+        * {@link org.apache.juneau.common.reflect.AnnotationProvider}.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param traversals The traversal settings defining what to search 
(e.g., SELF, MATCHING_PARAMETERS, PARAMETER_TYPE).
+        * @return A stream of annotation infos matching the specified type and 
traversal settings.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotations(Class<A> type, AnnotationTraversal... traversals) {
+               assertArgNotNull("type", type);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == AnnotationTraversal.SELF) {
+                                       return getAnnotationInfos(type);
+                               } else if (traversal == 
AnnotationTraversal.MATCHING_PARAMETERS) {
+                                       return 
getMatchingParameters().stream().skip(1).flatMap(x -> 
x.getAnnotationInfos(type));
+                               } else if (traversal == 
AnnotationTraversal.PARAMETER_TYPE) {
+                                       return 
getParameterType().unwrap(Value.class, Optional.class).findAnnotations(type, 
AnnotationTraversal.PARENTS, AnnotationTraversal.PACKAGE);
+                               }
+                               throw illegalArg("Invalid traversal type for 
parameter annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Finds annotations on this parameter using the specified traversal 
settings in parent-first order.
+        *
+        * <p>
+        * This method is identical to {@link #findAnnotations(Class, 
AnnotationTraversal...)} but returns
+        * results in parent-to-child order.
+        *
+        * @param <A> The annotation type.
+        * @param type The annotation type to search for.
+        * @param traversals The traversal settings defining what to search 
(e.g., SELF, MATCHING_PARAMETERS, PARAMETER_TYPE).
+        * @return A stream of annotation infos matching the specified type and 
traversal settings in parent-first order.
+        */
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findAnnotationsParentFirst(Class<A> type, AnnotationTraversal... traversals) {
+               return rstream(findAnnotations(type, traversals).toList());
+       }
+
        /**
         * Returns this parameter and all matching parameters in parent classes.
         *


Reply via email to