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 05ee2ecede Utility class modernization
05ee2ecede is described below
commit 05ee2ecede55bb9914e3988cab4615ce5b378a90
Author: James Bognar <[email protected]>
AuthorDate: Thu Nov 6 15:41:42 2025 -0500
Utility class modernization
---
.../juneau/common/reflect/AnnotationProvider2.java | 467 +++++++++++++++++++--
.../apache/juneau/common/reflect/FieldInfo.java | 14 -
2 files changed, 426 insertions(+), 55 deletions(-)
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider2.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider2.java
index 4855a01799..c4844f4556 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider2.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationProvider2.java
@@ -29,34 +29,150 @@ import java.util.stream.*;
import org.apache.juneau.common.collections.*;
/**
- * Enhanced annotation provider for classes that returns {@link
AnnotationInfo} objects instead of raw {@link Annotation} objects.
+ * Enhanced annotation provider that returns {@link AnnotationInfo} objects
and supports runtime annotations.
*
* <p>
- * This class provides a modern API for retrieving class annotations with the
following benefits:
+ * This class provides a modern API for retrieving annotations with the
following benefits:
* <ul>
* <li>Returns {@link AnnotationInfo} wrappers that provide additional
methods and type safety
* <li>Supports filtering by annotation type using streams
* <li>Properly handles repeatable annotations
- * <li>Searches up the class hierarchy (class → parents → interfaces →
package)
+ * <li>Searches up the class/method hierarchy with well-defined order of
precedence
+ * <li>Supports runtime annotations (annotations added programmatically at
runtime)
* <li>Caches results for performance
* </ul>
*
+ * <h5 class='section'>Annotation Order of Precedence:</h5>
+ *
+ * <h6 class='topic'>For Classes ({@link #find(Class)}):</h6>
+ * <p>
+ * Annotations are returned in <b>child-to-parent</b> order with the following
precedence:
+ * <ol>
+ * <li><b>Runtime annotations</b> on the class (highest priority)
+ * <li><b>Declared annotations</b> on the class
+ * <li><b>Runtime annotations</b> on parent classes (child-to-parent order)
+ * <li><b>Declared annotations</b> on parent classes (child-to-parent
order)
+ * <li><b>Runtime annotations</b> on interfaces (child-to-parent order)
+ * <li><b>Declared annotations</b> on interfaces (child-to-parent order)
+ * <li><b>Declared annotations</b> on the package (lowest priority)
+ * </ol>
+ *
+ * <p class='bcode'>
+ * <jc>// Example: Given class Child extends Parent</jc>
+ * <jc>// Annotation order will be:</jc>
+ * <jc>// 1. Runtime annotations on Child</jc>
+ * <jc>// 2. @Annotation on Child</jc>
+ * <jc>// 3. Runtime annotations on Parent</jc>
+ * <jc>// 4. @Annotation on Parent</jc>
+ * <jc>// 5. Runtime annotations on IChild (if Child implements
IChild)</jc>
+ * <jc>// 6. @Annotation on IChild</jc>
+ * <jc>// 7. @Annotation on package-info.java</jc>
+ * </p>
+ *
+ * <h6 class='topic'>For Methods ({@link #find(Method)}):</h6>
+ * <p>
+ * Annotations are returned in <b>child-to-parent</b> order with the following
precedence:
+ * <ol>
+ * <li><b>Runtime annotations</b> on the method (highest priority)
+ * <li><b>Declared annotations</b> on the method
+ * <li><b>Runtime annotations</b> on overridden parent methods
(child-to-parent order)
+ * <li><b>Declared annotations</b> on overridden parent methods
(child-to-parent order)
+ * </ol>
+ *
+ * <h6 class='topic'>For Fields ({@link #find(Field)}):</h6>
+ * <p>
+ * Annotations are returned with the following precedence:
+ * <ol>
+ * <li><b>Runtime annotations</b> on the field (highest priority)
+ * <li><b>Declared annotations</b> on the field
+ * </ol>
+ *
+ * <h6 class='topic'>For Constructors ({@link #find(Constructor)}):</h6>
+ * <p>
+ * Annotations are returned with the following precedence:
+ * <ol>
+ * <li><b>Runtime annotations</b> on the constructor (highest priority)
+ * <li><b>Declared annotations</b> on the constructor
+ * </ol>
+ *
+ * <h5 class='section'>Runtime Annotations:</h5>
+ * <p>
+ * Runtime annotations are concrete objects that implement annotation
interfaces, added programmatically via the
+ * builder's {@link Builder#addRuntimeAnnotations(List)} method. They allow
you to dynamically apply annotations
+ * to classes, methods, fields, and constructors at runtime without modifying
source code.
+ *
+ * <p>
+ * <b>How Runtime Annotations Work:</b>
+ * <ul>
+ * <li>Runtime annotations are Java objects that implement annotation
interfaces (e.g., {@code @Bean})
+ * <li>They use special methods like {@code on()} or {@code onClass()} to
specify their targets
+ * <li>They always take precedence over declared annotations at the same
level
+ * <li>They are particularly useful for applying annotations to classes
you don't control
+ * </ul>
+ *
+ * <p class='bjava'>
+ * <jc>// Example: Creating a runtime annotation</jc>
+ * Bean <jv>runtimeAnnotation</jv> = BeanAnnotation
+ * .<jsm>create</jsm>()
+ * .onClass(MyClass.<jk>class</jk>) <jc>// Target class</jc>
+ * .typeName(<js>"MyType"</js>) <jc>// Annotation
property</jc>
+ * .build();
+ *
+ * <jc>// Add to provider</jc>
+ * AnnotationProvider2 <jv>provider</jv> = AnnotationProvider2
+ * .<jsm>create</jsm>()
+ * .addRuntimeAnnotations(<jv>runtimeAnnotation</jv>)
+ * .build();
+ *
+ * <jc>// Now MyClass will be found with @Bean annotation</jc>
+ * Stream<AnnotationInfo<Bean>> <jv>annotations</jv> =
<jv>provider</jv>.find(Bean.<jk>class</jk>, MyClass.<jk>class</jk>);
+ * </p>
+ *
+ * <p>
+ * <b>Targeting Methods:</b>
+ * <ul>
+ * <li>{@code on()} - String array of fully-qualified names (e.g., {@code
"com.example.MyClass.myMethod"})
+ * <li>{@code onClass()} - Class array for type-safe targeting
+ * </ul>
+ *
+ * <p>
+ * Runtime annotations are evaluated before declared annotations at each
level, giving them higher priority.
+ * For example, a runtime {@code @Bean} annotation on a class will be found
before any {@code @Bean} annotation
+ * declared directly on that class.
+ *
+ * <h5 class='section'>Comparison with ElementInfo Methods:</h5>
+ * <p>
+ * The methods in this class differ from {@link
ClassInfo#getAnnotationInfos()}, {@link MethodInfo#getAnnotationInfos()}, etc.:
+ * <ul>
+ * <li><b>Runtime Annotations</b>: ElementInfo methods return ONLY
declared annotations. This class includes runtime annotations.
+ * <li><b>Hierarchy</b>: ElementInfo methods may have different traversal
logic. This class uses a consistent approach.
+ * <li><b>Precedence</b>: Runtime annotations are inserted at each level
with higher priority than declared annotations.
+ * </ul>
+ *
* <h5 class='section'>Usage:</h5>
* <p class='bjava'>
* <jc>// Create with default settings</jc>
* AnnotationProvider2 <jv>provider</jv> =
AnnotationProvider2.<jsm>create</jsm>().build();
*
- * <jc>// Create with caching disabled</jc>
+ * <jc>// Create with runtime annotations</jc>
* AnnotationProvider2 <jv>provider</jv> = AnnotationProvider2
* .<jsm>create</jsm>()
- * .disableCaching()
+ * .annotations(<jk>new</jk> MyAnnotationImpl())
* .build();
+ *
+ * <jc>// Find all annotations on a class</jc>
+ * List<AnnotationInfo<Annotation>> <jv>annotations</jv> =
<jv>provider</jv>.find(MyClass.<jk>class</jk>);
+ *
+ * <jc>// Find specific annotation type on a class</jc>
+ * Stream<AnnotationInfo<MyAnnotation>> <jv>myAnnotations</jv>
= <jv>provider</jv>.find(MyAnnotation.<jk>class</jk>, MyClass.<jk>class</jk>);
* </p>
*
* <h5 class='section'>See Also:</h5>
* <ul>
* <li class='jc'>{@link AnnotationProvider}
* <li class='jc'>{@link AnnotationInfo}
+ * <li class='jc'>{@link ClassInfo}
+ * <li class='jc'>{@link MethodInfo}
* </ul>
*/
public class AnnotationProvider2 {
@@ -132,18 +248,83 @@ public class AnnotationProvider2 {
return this;
}
- /**
- * Adds runtime annotations to be applied to classes and
methods.
- *
- * <p>
- * Annotations must define either an {@code onClass()} method
that returns a {@code Class[]} array,
- * or an {@code on()} method that returns a {@code String[]}
array to specify the targets.
- *
- * @param annotations The annotations to add.
- * @return This object for method chaining.
- * @throws BeanRuntimeException If the annotations are invalid.
- */
- public Builder addRuntimeAnnotations(List<Annotation>
annotations) {
+ /**
+ * Adds runtime annotations to be applied to classes, methods, fields,
and constructors.
+ *
+ * <p>
+ * Runtime annotations are concrete Java objects that implement
annotation interfaces (e.g., {@code @Bean}).
+ * They allow you to dynamically apply annotations to code elements at
runtime without modifying source code.
+ *
+ * <p>
+ * <b>How It Works:</b>
+ * <ol>
+ * <li>Create annotation objects using builder classes (e.g.,
{@code BeanAnnotation.create()})
+ * <li>Specify targets using {@code on()} or {@code onClass()}
methods
+ * <li>Set annotation properties (e.g., {@code typeName()}, {@code
properties()})
+ * <li>Build the annotation object
+ * <li>Add to the provider via this method
+ * </ol>
+ *
+ * <p>
+ * <b>Targeting Requirements:</b>
+ * <ul>
+ * <li>Annotations MUST define an {@code onClass()} method
returning {@code Class[]} for type-safe targeting
+ * <li>OR an {@code on()} method returning {@code String[]} for
string-based targeting
+ * <li>The {@code on()} method accepts fully-qualified names:
+ * <ul>
+ * <li>{@code "com.example.MyClass"} - targets a
class
+ * <li>{@code "com.example.MyClass.myMethod"} -
targets a method
+ * <li>{@code "com.example.MyClass.myField"} -
targets a field
+ * </ul>
+ * </ul>
+ *
+ * <p class='bjava'>
+ * <jc>// Example 1: Target a specific class using type-safe
targeting</jc>
+ * Bean <jv>beanAnnotation</jv> = BeanAnnotation
+ * .<jsm>create</jsm>()
+ * .onClass(MyClass.<jk>class</jk>) <jc>// Targets
MyClass</jc>
+ * .typeName(<js>"MyType"</js>)
+ * .properties(<js>"id,name"</js>)
+ * .build();
+ *
+ * <jc>// Example 2: Target multiple classes</jc>
+ * Bean <jv>multiAnnotation</jv> = BeanAnnotation
+ * .<jsm>create</jsm>()
+ * .onClass(MyClass.<jk>class</jk>,
OtherClass.<jk>class</jk>)
+ * .sort(<jk>true</jk>)
+ * .build();
+ *
+ * <jc>// Example 3: Target using string names (useful for
dynamic/reflection scenarios)</jc>
+ * Bean <jv>stringAnnotation</jv> = BeanAnnotation
+ * .<jsm>create</jsm>()
+ * .on(<js>"com.example.MyClass"</js>)
+ * .findFluentSetters(<jk>true</jk>)
+ * .build();
+ *
+ * <jc>// Example 4: Target a specific method</jc>
+ * Swap <jv>swapAnnotation</jv> = SwapAnnotation
+ * .<jsm>create</jsm>()
+ * .on(<js>"com.example.MyClass.getValue"</js>)
+ * .value(MySwap.<jk>class</jk>)
+ * .build();
+ *
+ * <jc>// Add all runtime annotations to the provider</jc>
+ * AnnotationProvider2 <jv>provider</jv> = AnnotationProvider2
+ * .<jsm>create</jsm>()
+ * .addRuntimeAnnotations(<jv>beanAnnotation</jv>,
<jv>multiAnnotation</jv>, <jv>stringAnnotation</jv>, <jv>swapAnnotation</jv>)
+ * .build();
+ * </p>
+ *
+ * <p>
+ * <b>Priority:</b> Runtime annotations always take precedence over
declared annotations at the same level.
+ * They are evaluated first when searching for annotations.
+ *
+ * @param annotations The list of runtime annotation objects to add.
+ * @return This object for method chaining.
+ * @throws BeanRuntimeException If any annotation is invalid (missing
{@code on()} or {@code onClass()} methods,
+ * or if the methods return incorrect types).
+ */
+ public Builder addRuntimeAnnotations(List<Annotation> annotations) {
for (var a : annotations) {
try {
@@ -174,6 +355,38 @@ public class AnnotationProvider2 {
return this;
}
+ /**
+ * Adds runtime annotations to be applied to classes, methods,
fields, and constructors.
+ *
+ * <p>
+ * This is a convenience method that delegates to {@link
#addRuntimeAnnotations(List)}.
+ * See that method for detailed documentation on how runtime
annotations work.
+ *
+ * <p class='bjava'>
+ * <jc>// Example: Add multiple runtime annotations using
varargs</jc>
+ * Bean <jv>beanAnnotation</jv> = BeanAnnotation
+ * .<jsm>create</jsm>()
+ * .onClass(MyClass.<jk>class</jk>)
+ * .typeName(<js>"MyType"</js>)
+ * .build();
+ *
+ * Swap <jv>swapAnnotation</jv> = SwapAnnotation
+ * .<jsm>create</jsm>()
+ * .on(<js>"com.example.MyClass.getValue"</js>)
+ * .value(MySwap.<jk>class</jk>)
+ * .build();
+ *
+ * AnnotationProvider2 <jv>provider</jv> =
AnnotationProvider2
+ * .<jsm>create</jsm>()
+ * .addRuntimeAnnotations(<jv>beanAnnotation</jv>,
<jv>swapAnnotation</jv>) <jc>// Varargs</jc>
+ * .build();
+ * </p>
+ *
+ * @param annotations The runtime annotation objects to add
(varargs).
+ * @return This object for method chaining.
+ * @throws BeanRuntimeException If any annotation is invalid.
+ * @see #addRuntimeAnnotations(List)
+ */
public Builder addRuntimeAnnotations(Annotation...annotations) {
return addRuntimeAnnotations(l(annotations));
}
@@ -232,14 +445,33 @@ public class AnnotationProvider2 {
//-----------------------------------------------------------------------------------------------------------------
/**
- * Finds all annotations on the specified class.
+ * Finds all annotations on the specified class, including runtime
annotations.
*
* <p>
- * Returns annotations in child-to-parent order.
+ * Searches the class, its parent classes, interfaces, and package for
annotations.
+ * Returns annotations in <b>child-to-parent</b> order with runtime
annotations
+ * taking precedence at each level.
+ *
+ * <p>
+ * <b>Order of precedence</b> (see class javadocs for details):
+ * <ol>
+ * <li>Runtime + declared annotations on this class
+ * <li>Runtime + declared annotations on parent classes
(child-to-parent)
+ * <li>Runtime + declared annotations on interfaces
(child-to-parent)
+ * <li>Declared annotations on the package
+ * </ol>
+ *
+ * <p>
+ * <b>Comparison with {@link ClassInfo#getAnnotationInfos(Class)}:</b>
+ * <ul>
+ * <li>This method includes <b>runtime annotations</b>; ClassInfo
does not
+ * <li>Same traversal order (child-to-parent with interfaces and
package)
+ * <li>Runtime annotations are inserted with higher priority at
each level
+ * </ul>
*
* @param onClass The class to search on.
- * @return A list of {@link AnnotationInfo} objects representing
annotations on the specified class and its parents.
- * Never <jk>null</jk>.
+ * @return A list of {@link AnnotationInfo} objects representing all
annotations on the specified class,
+ * its parents, interfaces, and package. Never <jk>null</jk>.
*/
public List<AnnotationInfo<Annotation>> find(Class<?> onClass) {
assertArgNotNull("onClass", onClass);
@@ -247,16 +479,29 @@ public class AnnotationProvider2 {
}
/**
- * Finds all annotations of the specified type on the specified class.
+ * Finds all annotations of the specified type on the specified class,
including runtime annotations.
+ *
+ * <p>
+ * Searches the class, its parent classes, interfaces, and package for
annotations of the specified type.
+ * Returns annotations in <b>child-to-parent</b> order with runtime
annotations
+ * taking precedence at each level.
*
* <p>
- * Returns annotations in child-to-parent order.
+ * This is a filtered version of {@link #find(Class)} that only returns
annotations matching the specified type.
+ *
+ * <p>
+ * <b>Comparison with {@link ClassInfo#getAnnotationInfos(Class)}:</b>
+ * <ul>
+ * <li>This method includes <b>runtime annotations</b>; ClassInfo
does not
+ * <li>Same traversal order (child-to-parent with interfaces and
package)
+ * <li>Runtime annotations are inserted with higher priority at
each level
+ * </ul>
*
* @param <A> The annotation type to find.
* @param type The annotation type to find.
* @param onClass The class to search on.
- * @return A stream of {@link AnnotationInfo} objects representing
annotations of the specified type on the specified class and its parents.
- * Never <jk>null</jk>.
+ * @return A stream of {@link AnnotationInfo} objects representing
annotations of the specified type on the
+ * specified class, its parents, interfaces, and package. Never
<jk>null</jk>.
*/
@SuppressWarnings("unchecked")
public <A extends Annotation> Stream<AnnotationInfo<A>> find(Class<A>
type, Class<?> onClass) {
@@ -267,11 +512,48 @@ public class AnnotationProvider2 {
.map(a -> (AnnotationInfo<A>)a);
}
+ /**
+ * Finds annotations declared directly on the specified class,
including runtime annotations.
+ *
+ * <p>
+ * Unlike {@link #find(Class)}, this method only returns annotations
declared directly on the specified class,
+ * not on its parents, interfaces, or package.
+ *
+ * <p>
+ * <b>Order of precedence</b>:
+ * <ol>
+ * <li>Runtime annotations on this class (highest priority)
+ * <li>Declared annotations on this class
+ * </ol>
+ *
+ * <p>
+ * <b>Comparison with {@link
ClassInfo#getDeclaredAnnotationInfos()}:</b>
+ * <ul>
+ * <li>This method includes <b>runtime annotations</b>; ClassInfo
does not
+ * <li>Runtime annotations are returned first (higher priority)
+ * </ul>
+ *
+ * @param onClass The class to search on.
+ * @return A list of {@link AnnotationInfo} objects representing
annotations declared directly on the class.
+ * Never <jk>null</jk>.
+ */
public List<AnnotationInfo<Annotation>> findDeclared(Class<?> onClass) {
assertArgNotNull("onClass", onClass);
return classDeclaredAnnotations.get(onClass);
}
+ /**
+ * Finds annotations of the specified type declared directly on the
specified class, including runtime annotations.
+ *
+ * <p>
+ * This is a filtered version of {@link #findDeclared(Class)} that only
returns annotations matching the specified type.
+ *
+ * @param <A> The annotation type to find.
+ * @param type The annotation type to find.
+ * @param onClass The class to search on.
+ * @return A stream of {@link AnnotationInfo} objects representing
annotations of the specified type declared
+ * directly on the class. Never <jk>null</jk>.
+ */
@SuppressWarnings("unchecked")
public <A extends Annotation> Stream<AnnotationInfo<A>>
findDeclared(Class<A> type, Class<?> onClass) {
assertArgNotNull("type", type);
@@ -286,9 +568,19 @@ public class AnnotationProvider2 {
*
* <p>
* This method returns annotations in the opposite order from {@link
#findDeclared(Class)}.
- * It processes parent/declared annotations first (lower priority),
then runtime annotations (higher priority).
- * This is useful when you want to process multiple annotation values
where child annotations
- * can override values from parent annotations.
+ * Returns annotations in <b>parent-to-child</b> order with declared
annotations coming before
+ * runtime annotations at each level.
+ *
+ * <p>
+ * <b>Order of precedence</b>:
+ * <ol>
+ * <li>Declared annotations on this class (lowest priority)
+ * <li>Runtime annotations on this class (highest priority)
+ * </ol>
+ *
+ * <p>
+ * This is useful when you want to process multiple annotation values
where runtime annotations
+ * can override values from declared annotations.
*
* @param onClass The class to search on.
* @return A stream of {@link AnnotationInfo} objects in
parent-to-child order.
@@ -320,11 +612,51 @@ public class AnnotationProvider2 {
.map(a -> (AnnotationInfo<A>)a);
}
+ /**
+ * Finds all annotations on the specified method, including runtime
annotations.
+ *
+ * <p>
+ * Searches the method and all overridden parent methods for
annotations.
+ * Returns annotations in <b>child-to-parent</b> order with runtime
annotations
+ * taking precedence at each level.
+ *
+ * <p>
+ * <b>Order of precedence</b> (see class javadocs for details):
+ * <ol>
+ * <li>Runtime annotations on this method (highest priority)
+ * <li>Declared annotations on this method
+ * <li>Runtime annotations on overridden parent methods
(child-to-parent)
+ * <li>Declared annotations on overridden parent methods
(child-to-parent)
+ * </ol>
+ *
+ * <p>
+ * <b>Comparison with {@link MethodInfo#getAnnotationInfos()}:</b>
+ * <ul>
+ * <li>This method includes <b>runtime annotations</b>; MethodInfo
does not
+ * <li>Runtime annotations are inserted with higher priority at
each level
+ * </ul>
+ *
+ * @param onMethod The method to search on.
+ * @return A list of {@link AnnotationInfo} objects representing all
annotations on the method and
+ * overridden parent methods. Never <jk>null</jk>.
+ */
public List<AnnotationInfo<Annotation>> find(Method onMethod) {
assertArgNotNull("onMethod", onMethod);
return methodAnnotations.get(onMethod);
}
+ /**
+ * Finds all annotations of the specified type on the specified method,
including runtime annotations.
+ *
+ * <p>
+ * This is a filtered version of {@link #find(Method)} that only
returns annotations matching the specified type.
+ *
+ * @param <A> The annotation type to find.
+ * @param type The annotation type to find.
+ * @param onMethod The method to search on.
+ * @return A stream of {@link AnnotationInfo} objects representing
annotations of the specified type on the
+ * method and overridden parent methods. Never <jk>null</jk>.
+ */
@SuppressWarnings("unchecked")
public <A extends Annotation> Stream<AnnotationInfo<A>> find(Class<A>
type, Method onMethod) {
assertArgNotNull("type", type);
@@ -334,11 +666,44 @@ public class AnnotationProvider2 {
.map(a -> (AnnotationInfo<A>)a);
}
+ /**
+ * Finds all annotations on the specified field, including runtime
annotations.
+ *
+ * <p>
+ * <b>Order of precedence</b>:
+ * <ol>
+ * <li>Runtime annotations on this field (highest priority)
+ * <li>Declared annotations on this field
+ * </ol>
+ *
+ * <p>
+ * <b>Comparison with {@link FieldInfo#getAnnotationInfos()}:</b>
+ * <ul>
+ * <li>This method includes <b>runtime annotations</b>; FieldInfo
does not
+ * <li>Runtime annotations are returned first (higher priority)
+ * </ul>
+ *
+ * @param onField The field to search on.
+ * @return A list of {@link AnnotationInfo} objects representing all
annotations on the field.
+ * Never <jk>null</jk>.
+ */
public List<AnnotationInfo<Annotation>> find(Field onField) {
assertArgNotNull("onField", onField);
return fieldAnnotations.get(onField);
}
+ /**
+ * Finds all annotations of the specified type on the specified field,
including runtime annotations.
+ *
+ * <p>
+ * This is a filtered version of {@link #find(Field)} that only returns
annotations matching the specified type.
+ *
+ * @param <A> The annotation type to find.
+ * @param type The annotation type to find.
+ * @param onField The field to search on.
+ * @return A stream of {@link AnnotationInfo} objects representing
annotations of the specified type on the field.
+ * Never <jk>null</jk>.
+ */
@SuppressWarnings("unchecked")
public <A extends Annotation> Stream<AnnotationInfo<A>> find(Class<A>
type, Field onField) {
assertArgNotNull("type", type);
@@ -348,11 +713,44 @@ public class AnnotationProvider2 {
.map(a -> (AnnotationInfo<A>)a);
}
+ /**
+ * Finds all annotations on the specified constructor, including
runtime annotations.
+ *
+ * <p>
+ * <b>Order of precedence</b>:
+ * <ol>
+ * <li>Runtime annotations on this constructor (highest priority)
+ * <li>Declared annotations on this constructor
+ * </ol>
+ *
+ * <p>
+ * <b>Comparison with {@link
ConstructorInfo#getDeclaredAnnotationInfos()}:</b>
+ * <ul>
+ * <li>This method includes <b>runtime annotations</b>;
ConstructorInfo does not
+ * <li>Runtime annotations are returned first (higher priority)
+ * </ul>
+ *
+ * @param onConstructor The constructor to search on.
+ * @return A list of {@link AnnotationInfo} objects representing all
annotations on the constructor.
+ * Never <jk>null</jk>.
+ */
public List<AnnotationInfo<Annotation>> find(Constructor<?>
onConstructor) {
assertArgNotNull("onConstructor", onConstructor);
return constructorAnnotations.get(onConstructor);
}
+ /**
+ * Finds all annotations of the specified type on the specified
constructor, including runtime annotations.
+ *
+ * <p>
+ * This is a filtered version of {@link #find(Constructor)} that only
returns annotations matching the specified type.
+ *
+ * @param <A> The annotation type to find.
+ * @param type The annotation type to find.
+ * @param onConstructor The constructor to search on.
+ * @return A stream of {@link AnnotationInfo} objects representing
annotations of the specified type on the constructor.
+ * Never <jk>null</jk>.
+ */
@SuppressWarnings("unchecked")
public <A extends Annotation> Stream<AnnotationInfo<A>> find(Class<A>
type, Constructor<?> onConstructor) {
assertArgNotNull("type", type);
@@ -455,17 +853,4 @@ public class AnnotationProvider2 {
for (var a2 : splitRepeated(a))
appendTo.add(AnnotationInfo.of(ci, a2));
}
-
- /**
- * Finds all annotations on the specified package and appends them to
the list.
- *
- * @param appendTo The list to append to.
- * @param forPackage The package to find annotations on.
- */
- private void findDeclaredAnnotations(List<AnnotationInfo<Annotation>>
appendTo, Package forPackage) {
- var pi = PackageInfo.of(forPackage);
- for (var a : forPackage.getAnnotations())
- for (var a2 : splitRepeated(a))
- appendTo.add(AnnotationInfo.of(pi, a2));
- }
}
\ 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 9757582666..7eabf313fd 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
@@ -165,20 +165,6 @@ public class FieldInfo extends AccessibleInfo implements
Comparable<FieldInfo>,
}
}
- /**
- * Returns the specified annotation on this field.
- *
- * @param <A> The annotation type to look for.
- * @param annotationProvider The annotation provider.
- * @param type The annotation to look for.
- * @return The annotation, or <jk>null</jk> if not found.
- */
- public <A extends Annotation> A getAnnotation(AnnotationProvider
annotationProvider, Class<A> type) {
- Value<A> t = Value.empty();
- annotationProvider.forEachAnnotation(type, f, x -> true, x ->
t.set(x));
- return t.orElse(null);
- }
-
/**
* Returns metadata about the declaring class.
*