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 35e31aadd4 org.apache.juneau.common.reflect API improvements
35e31aadd4 is described below

commit 35e31aadd44abf6a6c96bb8e7a0ad5d8636b97aa
Author: James Bognar <[email protected]>
AuthorDate: Wed Nov 19 11:42:15 2025 -0500

    org.apache.juneau.common.reflect API improvements
---
 .../juneau/common/reflect/AnnotationProvider.java  | 379 ++++++++++++++++++++-
 1 file changed, 374 insertions(+), 5 deletions(-)

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 b98400df11..7645d17a88 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
@@ -1016,6 +1016,8 @@ public class AnnotationProvider {
        public <A extends Annotation> Stream<AnnotationInfo<A>> find(Class<A> 
type, ClassInfo clazz, AnnotationTraversal... traversals) {
                assertArgNotNull("type", type);
                assertArgNotNull("clazz", clazz);
+               if (traversals.length == 0)
+                       traversals = a(SELF, PARENTS, PACKAGE);
 
                return Arrays.stream(traversals)
                        
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
@@ -1065,6 +1067,8 @@ public class AnnotationProvider {
        @SuppressWarnings("unchecked")
        public Stream<AnnotationInfo<Annotation>> find(ClassInfo clazz, 
AnnotationTraversal... traversals) {
                assertArgNotNull("clazz", clazz);
+               if (traversals.length == 0)
+                       traversals = a(SELF, PARENTS, PACKAGE);
 
                return Arrays.stream(traversals)
                        
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
@@ -1105,6 +1109,61 @@ public class AnnotationProvider {
                return rstream(find(type, clazz, traversals).toList());
        }
 
+       /**
+        * Streams all annotations from a class using configurable traversal 
options in parent-first order, without filtering by annotation type.
+        *
+        * <p>
+        * This is equivalent to calling {@link #find(ClassInfo, 
AnnotationTraversal...)}
+        * and reversing the result.
+        *
+        * @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 Stream<AnnotationInfo<Annotation>> findTopDown(ClassInfo clazz, 
AnnotationTraversal... traversals) {
+               return rstream(find(clazz, traversals).toList());
+       }
+
+       /**
+        * Checks if a class has the specified annotation.
+        *
+        * <p>
+        * This is a convenience method equivalent to:
+        * <p class='bjava'>
+        *      find(<jv>type</jv>, <jv>clazz</jv>, 
<jv>traversals</jv>).findFirst().isPresent()
+        * </p>
+        *
+        * <h5 class='section'>Supported Traversal Types:</h5>
+        * <ul>
+        *      <li>{@link AnnotationTraversal#SELF SELF} - Annotations 
declared directly on this class
+        *      <li>{@link AnnotationTraversal#PARENTS PARENTS} - Parent 
classes and interfaces (child-to-parent order)
+        *      <li>{@link AnnotationTraversal#PACKAGE PACKAGE} - The package 
annotations
+        * </ul>
+        *
+        * <p>
+        * <b>Default:</b> If no traversals are specified, defaults to: {@code 
SELF, PARENTS, PACKAGE}
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Check if class has @MyAnnotation anywhere in 
hierarchy</jc>
+        *      <jk>boolean</jk> <jv>hasIt</jv> = 
has(MyAnnotation.<jk>class</jk>, <jv>ci</jv>);
+        *
+        *      <jc>// Check only on the class itself</jc>
+        *      <jk>boolean</jk> <jv>hasIt2</jv> = 
has(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF);
+        * </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. If not specified, defaults to {@code 
SELF, PARENTS, PACKAGE}.
+        *      <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link 
AnnotationTraversal#PARENTS PARENTS}, {@link AnnotationTraversal#PACKAGE 
PACKAGE}
+        * @return <jk>true</jk> if the annotation is found, <jk>false</jk> 
otherwise.
+        */
+       public <A extends Annotation> boolean has(Class<A> type, ClassInfo 
clazz, AnnotationTraversal... traversals) {
+               return find(type, clazz, traversals).findFirst().isPresent();
+       }
+
        /**
         * Streams annotations from a method using configurable traversal 
options.
         *
@@ -1133,7 +1192,7 @@ public class AnnotationProvider {
                assertArgNotNull("type", type);
                assertArgNotNull("method", method);
                if (traversals.length == 0)
-                       traversals = new AnnotationTraversal[]{SELF, 
MATCHING_METHODS, RETURN_TYPE, PACKAGE};
+                       traversals = a(SELF, MATCHING_METHODS, RETURN_TYPE, 
PACKAGE);
 
                return Arrays.stream(traversals)
                        
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
@@ -1184,7 +1243,7 @@ public class AnnotationProvider {
        public Stream<AnnotationInfo<Annotation>> find(MethodInfo method, 
AnnotationTraversal... traversals) {
                assertArgNotNull("method", method);
                if (traversals.length == 0)
-                       traversals = new AnnotationTraversal[]{SELF, 
MATCHING_METHODS, RETURN_TYPE, PACKAGE};
+                       traversals = a(SELF, MATCHING_METHODS, RETURN_TYPE, 
PACKAGE);
 
                return Arrays.stream(traversals)
                        
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
@@ -1227,6 +1286,62 @@ public class AnnotationProvider {
                return rstream(find(type, method, traversals).toList());
        }
 
+       /**
+        * Streams all annotations from a method using configurable traversal 
options in parent-first order, without filtering by annotation type.
+        *
+        * <p>
+        * This is equivalent to calling {@link #find(MethodInfo, 
AnnotationTraversal...)}
+        * and reversing the result.
+        *
+        * @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 Stream<AnnotationInfo<Annotation>> findTopDown(MethodInfo 
method, AnnotationTraversal... traversals) {
+               return rstream(find(method, traversals).toList());
+       }
+
+       /**
+        * Checks if a method has the specified annotation.
+        *
+        * <p>
+        * This is a convenience method equivalent to:
+        * <p class='bjava'>
+        *      find(<jv>type</jv>, <jv>method</jv>, 
<jv>traversals</jv>).findFirst().isPresent()
+        * </p>
+        *
+        * <h5 class='section'>Supported Traversal Types:</h5>
+        * <ul>
+        *      <li>{@link AnnotationTraversal#SELF SELF} - Annotations 
declared directly on this method
+        *      <li>{@link AnnotationTraversal#MATCHING_METHODS 
MATCHING_METHODS} - Matching methods in parent classes (child-to-parent)
+        *      <li>{@link AnnotationTraversal#RETURN_TYPE RETURN_TYPE} - The 
return type hierarchy (includes class parents and package)
+        *      <li>{@link AnnotationTraversal#PACKAGE PACKAGE} - The declaring 
class's package annotations
+        * </ul>
+        *
+        * <p>
+        * <b>Default:</b> If no traversals are specified, defaults to: {@code 
SELF, MATCHING_METHODS, RETURN_TYPE, PACKAGE}
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Check if method has @MyAnnotation anywhere in 
hierarchy</jc>
+        *      <jk>boolean</jk> <jv>hasIt</jv> = 
has(MyAnnotation.<jk>class</jk>, <jv>mi</jv>);
+        *
+        *      <jc>// Check only on the method itself</jc>
+        *      <jk>boolean</jk> <jv>hasIt2</jv> = 
has(MyAnnotation.<jk>class</jk>, <jv>mi</jv>, SELF);
+        * </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. If not specified, defaults to {@code 
SELF, MATCHING_METHODS, RETURN_TYPE, PACKAGE}.
+        *      <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link 
AnnotationTraversal#MATCHING_METHODS MATCHING_METHODS}, {@link 
AnnotationTraversal#RETURN_TYPE RETURN_TYPE}, {@link 
AnnotationTraversal#PACKAGE PACKAGE}
+        * @return <jk>true</jk> if the annotation is found, <jk>false</jk> 
otherwise.
+        */
+       public <A extends Annotation> boolean has(Class<A> type, MethodInfo 
method, AnnotationTraversal... traversals) {
+               return find(type, method, traversals).findFirst().isPresent();
+       }
+
        /**
         * Streams annotations from a parameter using configurable traversal 
options in child-to-parent order.
         *
@@ -1270,7 +1385,7 @@ public class AnnotationProvider {
                assertArgNotNull("type", type);
                assertArgNotNull("parameter", parameter);
                if (traversals.length == 0)
-                       traversals = new AnnotationTraversal[]{SELF, 
MATCHING_PARAMETERS, PARAMETER_TYPE};
+                       traversals = a(SELF, MATCHING_PARAMETERS, 
PARAMETER_TYPE);
 
                return Arrays.stream(traversals)
                        
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
@@ -1325,6 +1440,76 @@ public class AnnotationProvider {
                return rstream(find(type, parameter, traversals).toList());
        }
 
+       /**
+        * Streams all annotations from a parameter using configurable 
traversal options, without filtering by annotation type.
+        *
+        * <p>
+        * This method provides a flexible, stream-based API for traversing all 
parameter annotations without creating intermediate lists.
+        * Unlike {@link #find(Class, ParameterInfo, AnnotationTraversal...)}, 
this method does not filter by annotation type.
+        *
+        * <h5 class='section'>Supported Traversal Types:</h5>
+        * <ul>
+        *      <li>{@link AnnotationTraversal#SELF SELF} - Annotations 
declared directly on this parameter
+        *      <li>{@link AnnotationTraversal#MATCHING_PARAMETERS 
MATCHING_PARAMETERS} - Matching parameters in parent methods/constructors 
(child-to-parent)
+        *      <li>{@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE} - 
The parameter's type hierarchy (includes class parents and package)
+        * </ul>
+        *
+        * <p>
+        * <b>Default:</b> If no traversals are specified, defaults to: {@code 
SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Get all annotations from parameter, matching parameters, 
and parameter type</jc>
+        *      Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s1</jv> =
+        *              find(<jv>pi</jv>, SELF, MATCHING_PARAMETERS, 
PARAMETER_TYPE);
+        *
+        *      <jc>// Just get annotations from this parameter</jc>
+        *      Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s2</jv> =
+        *              find(<jv>pi</jv>, SELF);
+        * </p>
+        *
+        * @param parameter The parameter to search.
+        * @param traversals
+        *      The traversal options. If not specified, defaults to {@code 
SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}.
+        *      <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link 
AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS}, {@link 
AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE}
+        * @return A stream of {@link AnnotationInfo} objects in 
child-to-parent order. Never <jk>null</jk>.
+        */
+       public Stream<AnnotationInfo<Annotation>> find(ParameterInfo parameter, 
AnnotationTraversal... traversals) {
+               assertArgNotNull("parameter", parameter);
+               if (traversals.length == 0)
+                       traversals = a(SELF, MATCHING_PARAMETERS, 
PARAMETER_TYPE);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == SELF) {
+                                       return 
parameter.getAnnotations().stream();
+                               } else if (traversal == MATCHING_PARAMETERS) {
+                                       return 
parameter.getMatchingParameters().stream().skip(1).flatMap(x -> 
x.getAnnotations().stream());
+                               } else if (traversal == PARAMETER_TYPE) {
+                                       return 
find(parameter.getParameterType().unwrap(Value.class, Optional.class), PARENTS, 
PACKAGE);
+                               }
+                               throw illegalArg("Invalid traversal type for 
parameter annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Streams all annotations from a parameter using configurable 
traversal options in parent-first order, without filtering by annotation type.
+        *
+        * <p>
+        * This is equivalent to calling {@link #find(ParameterInfo, 
AnnotationTraversal...)}
+        * and reversing the result.
+        *
+        * @param parameter The parameter to search.
+        * @param traversals
+        *      The traversal options. If not specified, defaults to {@code 
SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}.
+        *      <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link 
AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS}, {@link 
AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE}
+        * @return A stream of {@link AnnotationInfo} objects in 
parent-to-child order. Never <jk>null</jk>.
+        */
+       public Stream<AnnotationInfo<Annotation>> findTopDown(ParameterInfo 
parameter, AnnotationTraversal... traversals) {
+               return rstream(find(parameter, traversals).toList());
+       }
+
        /**
         * Checks if a parameter has the specified annotation.
         *
@@ -1384,15 +1569,57 @@ public class AnnotationProvider {
         * @param traversals The traversal options.
         * @return A stream of {@link AnnotationInfo} objects. Never 
<jk>null</jk>.
         */
+       @SuppressWarnings("unchecked")
        public <A extends Annotation> Stream<AnnotationInfo<A>> find(Class<A> 
type, FieldInfo field, AnnotationTraversal... traversals) {
                assertArgNotNull("type", type);
                assertArgNotNull("field", field);
+               if (traversals.length == 0)
+                       traversals = a(SELF);
 
                return Arrays.stream(traversals)
                        
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
                        .flatMap(traversal -> {
                                if (traversal == SELF) {
-                                       return xfind(type, field.inner());
+                                       return concat(
+                                               
fieldRuntimeAnnotations.get(field.inner()).stream(),
+                                               field.getAnnotations().stream()
+                                       ).filter(a -> a.isType(type)).map(a -> 
(AnnotationInfo<A>)a);
+                               }
+                               throw illegalArg("Invalid traversal type for 
field annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Streams all annotations from a field using configurable traversal 
options, without filtering by annotation type.
+        *
+        * <p>
+        * This method provides a flexible, stream-based API for traversing all 
field annotations without creating intermediate lists.
+        * Unlike {@link #find(Class, FieldInfo, AnnotationTraversal...)}, this 
method does not filter by annotation type.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Get all annotations from field</jc>
+        *      Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s1</jv> =
+        *              find(<jv>fi</jv>, SELF);
+        * </p>
+        *
+        * @param field The field to search.
+        * @param traversals The traversal options.
+        * @return A stream of {@link AnnotationInfo} objects. Never 
<jk>null</jk>.
+        */
+       public Stream<AnnotationInfo<Annotation>> find(FieldInfo field, 
AnnotationTraversal... traversals) {
+               assertArgNotNull("field", field);
+               if (traversals.length == 0)
+                       traversals = a(SELF);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == SELF) {
+                                       return concat(
+                                               
fieldRuntimeAnnotations.get(field.inner()).stream(),
+                                               field.getAnnotations().stream()
+                                       );
                                }
                                throw illegalArg("Invalid traversal type for 
field annotations: {0}", traversal);
                        });
@@ -1415,6 +1642,56 @@ public class AnnotationProvider {
                return rstream(find(type, field, traversals).toList());
        }
 
+       /**
+        * Streams all annotations from a field using configurable traversal 
options in parent-first order, without filtering by annotation type.
+        *
+        * <p>
+        * This is equivalent to calling {@link #find(FieldInfo, 
AnnotationTraversal...)}
+        * and reversing the result.
+        *
+        * @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 Stream<AnnotationInfo<Annotation>> findTopDown(FieldInfo field, 
AnnotationTraversal... traversals) {
+               return rstream(find(field, traversals).toList());
+       }
+
+       /**
+        * Checks if a field has the specified annotation.
+        *
+        * <p>
+        * This is a convenience method equivalent to:
+        * <p class='bjava'>
+        *      find(<jv>type</jv>, <jv>field</jv>, 
<jv>traversals</jv>).findFirst().isPresent()
+        * </p>
+        *
+        * <h5 class='section'>Supported Traversal Types:</h5>
+        * <ul>
+        *      <li>{@link AnnotationTraversal#SELF SELF} - Annotations 
declared directly on this field
+        * </ul>
+        *
+        * <p>
+        * <b>Default:</b> If no traversals are specified, defaults to: {@code 
SELF}
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Check if field has @MyAnnotation</jc>
+        *      <jk>boolean</jk> <jv>hasIt</jv> = 
has(MyAnnotation.<jk>class</jk>, <jv>fi</jv>);
+        * </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. If not specified, defaults to {@code 
SELF}.
+        *      <br>Valid values: {@link AnnotationTraversal#SELF SELF}
+        * @return <jk>true</jk> if the annotation is found, <jk>false</jk> 
otherwise.
+        */
+       public <A extends Annotation> boolean has(Class<A> type, FieldInfo 
field, AnnotationTraversal... traversals) {
+               return find(type, field, traversals).findFirst().isPresent();
+       }
+
        /**
         * Streams annotations from a constructor using configurable traversal 
options.
         *
@@ -1434,15 +1711,57 @@ public class AnnotationProvider {
         * @param traversals The traversal options.
         * @return A stream of {@link AnnotationInfo} objects. Never 
<jk>null</jk>.
         */
+       @SuppressWarnings("unchecked")
        public <A extends Annotation> Stream<AnnotationInfo<A>> find(Class<A> 
type, ConstructorInfo constructor, AnnotationTraversal... traversals) {
                assertArgNotNull("type", type);
                assertArgNotNull("constructor", constructor);
+               if (traversals.length == 0)
+                       traversals = a(SELF);
+
+               return Arrays.stream(traversals)
+                       
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
+                       .flatMap(traversal -> {
+                               if (traversal == SELF) {
+                                       return concat(
+                                               
constructorRuntimeAnnotations.get(constructor.inner()).stream(),
+                                               
constructor.getDeclaredAnnotations().stream()
+                                       ).filter(a -> a.isType(type)).map(a -> 
(AnnotationInfo<A>)a);
+                               }
+                               throw illegalArg("Invalid traversal type for 
constructor annotations: {0}", traversal);
+                       });
+       }
+
+       /**
+        * Streams all annotations from a constructor using configurable 
traversal options, without filtering by annotation type.
+        *
+        * <p>
+        * This method provides a flexible, stream-based API for traversing all 
constructor annotations without creating intermediate lists.
+        * Unlike {@link #find(Class, ConstructorInfo, 
AnnotationTraversal...)}, this method does not filter by annotation type.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bjava'>
+        *      <jc>// Get all annotations from constructor</jc>
+        *      Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s1</jv> =
+        *              find(<jv>ci</jv>, SELF);
+        * </p>
+        *
+        * @param constructor The constructor to search.
+        * @param traversals The traversal options.
+        * @return A stream of {@link AnnotationInfo} objects. Never 
<jk>null</jk>.
+        */
+       public Stream<AnnotationInfo<Annotation>> find(ConstructorInfo 
constructor, AnnotationTraversal... traversals) {
+               assertArgNotNull("constructor", constructor);
+               if (traversals.length == 0)
+                       traversals = a(SELF);
 
                return Arrays.stream(traversals)
                        
.sorted(Comparator.comparingInt(AnnotationTraversal::getOrder))
                        .flatMap(traversal -> {
                                if (traversal == SELF) {
-                                       return xfind(type, constructor.inner());
+                                       return concat(
+                                               
constructorRuntimeAnnotations.get(constructor.inner()).stream(),
+                                               
constructor.getDeclaredAnnotations().stream()
+                                       );
                                }
                                throw illegalArg("Invalid traversal type for 
constructor annotations: {0}", traversal);
                        });
@@ -1464,4 +1783,54 @@ public class AnnotationProvider {
        public <A extends Annotation> Stream<AnnotationInfo<A>> 
findTopDown(Class<A> type, ConstructorInfo constructor, AnnotationTraversal... 
traversals) {
                return rstream(find(type, constructor, traversals).toList());
        }
+
+       /**
+        * Streams all annotations from a constructor using configurable 
traversal options in parent-first order, without filtering by annotation type.
+        *
+        * <p>
+        * This is equivalent to calling {@link #find(ConstructorInfo, 
AnnotationTraversal...)}
+        * and reversing the result.
+        *
+        * @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 Stream<AnnotationInfo<Annotation>> findTopDown(ConstructorInfo 
constructor, AnnotationTraversal... traversals) {
+               return rstream(find(constructor, traversals).toList());
+       }
+
+       /**
+        * Checks if a constructor has the specified annotation.
+        *
+        * <p>
+        * This is a convenience method equivalent to:
+        * <p class='bjava'>
+        *      find(<jv>type</jv>, <jv>constructor</jv>, 
<jv>traversals</jv>).findFirst().isPresent()
+        * </p>
+        *
+        * <h5 class='section'>Supported Traversal Types:</h5>
+        * <ul>
+        *      <li>{@link AnnotationTraversal#SELF SELF} - Annotations 
declared directly on this constructor
+        * </ul>
+        *
+        * <p>
+        * <b>Default:</b> If no traversals are specified, defaults to: {@code 
SELF}
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Check if constructor has @MyAnnotation</jc>
+        *      <jk>boolean</jk> <jv>hasIt</jv> = 
has(MyAnnotation.<jk>class</jk>, <jv>ci</jv>);
+        * </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. If not specified, defaults to {@code 
SELF}.
+        *      <br>Valid values: {@link AnnotationTraversal#SELF SELF}
+        * @return <jk>true</jk> if the annotation is found, <jk>false</jk> 
otherwise.
+        */
+       public <A extends Annotation> boolean has(Class<A> type, 
ConstructorInfo constructor, AnnotationTraversal... traversals) {
+               return find(type, constructor, 
traversals).findFirst().isPresent();
+       }
 }
\ No newline at end of file

Reply via email to