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 91aa3269ee org.apache.juneau.common.reflect API improvements
91aa3269ee is described below
commit 91aa3269eeae698043f0d7a7277d5cef4802d53b
Author: James Bognar <[email protected]>
AuthorDate: Mon Nov 17 11:18:01 2025 -0500
org.apache.juneau.common.reflect API improvements
---
.../juneau/common/reflect/AnnotationInfo.java | 114 ---------------------
.../apache/juneau/common/reflect/ClassInfo.java | 41 ++++++++
.../apache/juneau/common/reflect/MethodInfo.java | 83 +++++++++++++++
3 files changed, 124 insertions(+), 114 deletions(-)
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationInfo.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationInfo.java
index f3b473ac7d..64dc47512f 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationInfo.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/reflect/AnnotationInfo.java
@@ -283,96 +283,6 @@ public class AnnotationInfo<T extends Annotation> {
}
-
//-----------------------------------------------------------------------------------------------------------------
- // Static methods for ClassInfo
-
//-----------------------------------------------------------------------------------------------------------------
-
- /**
- * Performs an action on all matching annotations on the specified
class/parents/package.
- *
- * <p>
- * Annotations are consumed in the following order:
- * <ol>
- * <li>On the package of this class.
- * <li>On interfaces ordered parent-to-child.
- * <li>On parent classes ordered parent-to-child.
- * <li>On this class.
- * </ol>
- *
- * @param classInfo The class to process.
- * @param filter A predicate to apply to the entries to determine if
action should be performed. Can be <jk>null</jk>.
- * @param action An action to perform on the entry.
- */
- // TODO: Once ClassInfo arrays are converted to Lists, convert reverse
iterations to rstream() and nested loops to flatMap()
- public static void forEachAnnotationInfo(ClassInfo classInfo,
Predicate<AnnotationInfo<?>> filter, Consumer<AnnotationInfo<?>> action) {
- var pi = classInfo.getPackage();
- if (nn(pi))
- for (var ai : pi.getAnnotations())
- if (filter == null || filter.test(ai))
- action.accept(ai);
- var interfaces = classInfo.getInterfaces();
- for (int i = interfaces.size() - 1; i >= 0; i--)
- for (var a :
interfaces.get(i).inner().getDeclaredAnnotations())
- for (var a2 : splitRepeated(a)) {
- var ai =
AnnotationInfo.of(interfaces.get(i), a2);
- if (filter == null || filter.test(ai))
- action.accept(ai);
- }
- var parents = classInfo.getParents();
- for (int i = parents.size() - 1; i >= 0; i--)
- for (var a :
parents.get(i).inner().getDeclaredAnnotations())
- for (var a2 : splitRepeated(a)) {
- var ai =
AnnotationInfo.of(parents.get(i), a2);
- if (filter == null || filter.test(ai))
- action.accept(ai);
- }
- }
-
-
//-----------------------------------------------------------------------------------------------------------------
- // Static methods for MethodInfo
-
//-----------------------------------------------------------------------------------------------------------------
-
- /**
- * Performs an action on all matching annotations on the specified
method.
- *
- * @param methodInfo The method to process.
- * @param filter A predicate to apply to the entries to determine if
action should be performed. Can be <jk>null</jk>.
- * @param action An action to perform on the entry.
- */
- // TODO: Once ClassInfo arrays are converted to Lists, convert reverse
iterations to rstream()
- public static void forEachAnnotationInfo(MethodInfo methodInfo,
Predicate<AnnotationInfo<?>> filter, Consumer<AnnotationInfo<?>> action) {
- var c = methodInfo.getDeclaringClass();
- forEachDeclaredAnnotationInfo(c.getPackage(), filter, action);
- var interfaces = c.getInterfaces();
- for (int i = interfaces.size() - 1; i >= 0; i--) {
- forEachDeclaredAnnotationInfo(interfaces.get(i),
filter, action);
- forEachDeclaredMethodAnnotationInfo(methodInfo,
interfaces.get(i), filter, action);
- }
- var parents = c.getParents();
- for (int i = parents.size() - 1; i >= 0; i--) {
- forEachDeclaredAnnotationInfo(parents.get(i), filter,
action);
- forEachDeclaredMethodAnnotationInfo(methodInfo,
parents.get(i), filter, action);
- }
- }
-
- /**
- * Performs an action on all matching annotations on methods only.
- *
- * @param methodInfo The method to process.
- * @param filter A predicate to apply to the entries to determine if
action should be performed. Can be <jk>null</jk>.
- * @param action An action to perform on the entry.
- */
- // TODO: Once ClassInfo arrays are converted to Lists, convert reverse
iterations to rstream()
- public static void forEachAnnotationInfoMethodOnly(MethodInfo
methodInfo, Predicate<AnnotationInfo<?>> filter, Consumer<AnnotationInfo<?>>
action) {
- var c = methodInfo.getDeclaringClass();
- var interfaces = c.getInterfaces();
- for (int i = interfaces.size() - 1; i >= 0; i--)
- forEachDeclaredMethodAnnotationInfo(methodInfo,
interfaces.get(i), filter, action);
- var parents = c.getParents();
- for (int i = parents.size() - 1; i >= 0; i--)
- forEachDeclaredMethodAnnotationInfo(methodInfo,
parents.get(i), filter, action);
- }
-
//-----------------------------------------------------------------------------------------------------------------
// Private helper methods
//-----------------------------------------------------------------------------------------------------------------
@@ -385,30 +295,6 @@ public class AnnotationInfo<T extends Annotation> {
.orElse(0);
}
- @SuppressWarnings("unchecked")
- private static void forEachDeclaredAnnotationInfo(ClassInfo ci,
Predicate<AnnotationInfo<?>> filter, Consumer<AnnotationInfo<?>> action) {
- if (nn(ci))
- for (var ai : ci.getDeclaredAnnotationInfos())
- if (filter == null || filter.test(ai))
- action.accept(ai);
- }
-
- private static void forEachDeclaredAnnotationInfo(PackageInfo pi,
Predicate<AnnotationInfo<?>> filter, Consumer<AnnotationInfo<?>> action) {
- if (nn(pi))
- for (var ai : pi.getAnnotations())
- if (filter == null || filter.test(ai))
- action.accept(ai);
- }
-
- private static void forEachDeclaredMethodAnnotationInfo(MethodInfo
methodInfo, ClassInfo ci, Predicate<AnnotationInfo<?>> filter,
Consumer<AnnotationInfo<?>> action) {
- MethodInfo mi = methodInfo.findMatchingOnClass(ci);
- if (nn(mi))
- mi.getDeclaredAnnotationInfos().forEach(ai -> {
- if (filter == null || filter.test(ai))
- action.accept(ai);
- });
- }
-
/**
* Returns <jk>true</jk> if this annotation has the specified simple
name.
*
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 11767a3651..1ff4436cee 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,47 @@ public class ClassInfo extends ElementInfo implements
Annotatable {
.map(a -> (AnnotationInfo<A>)a);
}
+ /**
+ * Performs an action on all matching annotations on this class and
parent classes/interfaces.
+ *
+ * <p>
+ * Annotations are consumed in the following order:
+ * <ol>
+ * <li>On the package of this class.
+ * <li>On interfaces ordered parent-to-child.
+ * <li>On parent classes ordered parent-to-child.
+ * <li>On this class.
+ * </ol>
+ *
+ * @param filter A predicate to apply to the entries to determine if
action should be performed. Can be <jk>null</jk>.
+ * @param action An action to perform on the entry.
+ * @return This object.
+ */
+ public ClassInfo forEachAnnotationInfo(Predicate<AnnotationInfo<?>>
filter, Consumer<AnnotationInfo<?>> action) {
+ var pi = getPackage();
+ if (nn(pi))
+ for (var ai : pi.getAnnotations())
+ if (filter == null || filter.test(ai))
+ action.accept(ai);
+ var interfaces = getInterfaces();
+ for (int i = interfaces.size() - 1; i >= 0; i--)
+ for (var a :
interfaces.get(i).inner().getDeclaredAnnotations())
+ for (var a2 : splitRepeated(a)) {
+ var ai =
AnnotationInfo.of(interfaces.get(i), a2);
+ if (filter == null || filter.test(ai))
+ action.accept(ai);
+ }
+ var parents = getParents();
+ for (int i = parents.size() - 1; i >= 0; i--)
+ for (var a :
parents.get(i).inner().getDeclaredAnnotations())
+ for (var a2 : splitRepeated(a)) {
+ var ai =
AnnotationInfo.of(parents.get(i), a2);
+ if (filter == null || filter.test(ai))
+ action.accept(ai);
+ }
+ return this;
+ }
+
/**
* Finds annotations on this class using the specified traversal
settings.
*
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 fa319ca42d..145c80c5a2 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
@@ -171,6 +171,62 @@ public class MethodInfo extends ExecutableInfo implements
Comparable<MethodInfo>
.map(a -> (AnnotationInfo<A>)a);
}
+ /**
+ * Performs an action on all matching annotations on this method.
+ *
+ * <p>
+ * Processes annotations on:
+ * <ul>
+ * <li>Package of the declaring class
+ * <li>Interfaces (and their methods) in parent-to-child order
+ * <li>Parent classes (and their methods) in parent-to-child order
+ * </ul>
+ *
+ * @param filter A predicate to apply to the entries to determine if
action should be performed. Can be <jk>null</jk>.
+ * @param action An action to perform on the entry.
+ * @return This object.
+ */
+ public MethodInfo forEachAnnotationInfo(Predicate<AnnotationInfo<?>>
filter, Consumer<AnnotationInfo<?>> action) {
+ var c = getDeclaringClass();
+ forEachDeclaredAnnotationInfo(c.getPackage(), filter, action);
+ var interfaces = c.getInterfaces();
+ for (int i = interfaces.size() - 1; i >= 0; i--) {
+ forEachDeclaredAnnotationInfo(interfaces.get(i),
filter, action);
+ forEachDeclaredMethodAnnotationInfo(this,
interfaces.get(i), filter, action);
+ }
+ var parents = c.getParents();
+ for (int i = parents.size() - 1; i >= 0; i--) {
+ forEachDeclaredAnnotationInfo(parents.get(i), filter,
action);
+ forEachDeclaredMethodAnnotationInfo(this,
parents.get(i), filter, action);
+ }
+ return this;
+ }
+
+ /**
+ * Performs an action on all matching annotations on methods only.
+ *
+ * <p>
+ * Processes annotations on:
+ * <ul>
+ * <li>Matching methods in interfaces in parent-to-child order
+ * <li>Matching methods in parent classes in parent-to-child order
+ * </ul>
+ *
+ * @param filter A predicate to apply to the entries to determine if
action should be performed. Can be <jk>null</jk>.
+ * @param action An action to perform on the entry.
+ * @return This object.
+ */
+ public MethodInfo
forEachAnnotationInfoMethodOnly(Predicate<AnnotationInfo<?>> filter,
Consumer<AnnotationInfo<?>> action) {
+ var c = getDeclaringClass();
+ var interfaces = c.getInterfaces();
+ for (int i = interfaces.size() - 1; i >= 0; i--)
+ forEachDeclaredMethodAnnotationInfo(this,
interfaces.get(i), filter, action);
+ var parents = c.getParents();
+ for (int i = parents.size() - 1; i >= 0; i--)
+ forEachDeclaredMethodAnnotationInfo(this,
parents.get(i), filter, action);
+ return this;
+ }
+
/**
* Finds annotations on this method using the specified traversal
settings.
*
@@ -789,6 +845,33 @@ public class MethodInfo extends ExecutableInfo implements
Comparable<MethodInfo>
return null;
}
+
//-----------------------------------------------------------------------------------------------------------------
+ // Helper methods for forEachAnnotationInfo
+
//-----------------------------------------------------------------------------------------------------------------
+
+ private static void forEachDeclaredAnnotationInfo(ClassInfo ci,
Predicate<AnnotationInfo<?>> filter, Consumer<AnnotationInfo<?>> action) {
+ if (nn(ci))
+ for (var ai : ci.getDeclaredAnnotationInfos())
+ if (filter == null || filter.test(ai))
+ action.accept(ai);
+ }
+
+ private static void forEachDeclaredAnnotationInfo(PackageInfo pi,
Predicate<AnnotationInfo<?>> filter, Consumer<AnnotationInfo<?>> action) {
+ if (nn(pi))
+ for (var ai : pi.getAnnotations())
+ if (filter == null || filter.test(ai))
+ action.accept(ai);
+ }
+
+ private static void forEachDeclaredMethodAnnotationInfo(MethodInfo
methodInfo, ClassInfo ci, Predicate<AnnotationInfo<?>> filter,
Consumer<AnnotationInfo<?>> action) {
+ MethodInfo mi = methodInfo.findMatchingOnClass(ci);
+ if (nn(mi))
+ mi.getDeclaredAnnotationInfos().forEach(ai -> {
+ if (filter == null || filter.test(ai))
+ action.accept(ai);
+ });
+ }
+
//-----------------------------------------------------------------------------------------------------------------
// Annotatable interface methods
//-----------------------------------------------------------------------------------------------------------------