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 6bb927a1bd org.apache.juneau.common.reflect API improvements
6bb927a1bd is described below
commit 6bb927a1bd9885c46a76f508e6edd1c6d48f5784
Author: James Bognar <[email protected]>
AuthorDate: Wed Nov 19 13:57:41 2025 -0500
org.apache.juneau.common.reflect API improvements
---
.../juneau/common/reflect/AnnotationProvider.java | 149 ---------------------
.../java/org/apache/juneau/BeanPropertyMeta.java | 10 +-
.../main/java/org/apache/juneau/BeanRegistry.java | 3 +-
.../src/main/java/org/apache/juneau/ClassMeta.java | 4 +-
.../rest/swagger/BasicSwaggerProviderSession.java | 22 +--
5 files changed, 22 insertions(+), 166 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 dddef37fbd..55b10cb9b6 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
@@ -17,9 +17,7 @@
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 static org.apache.juneau.common.reflect.AnnotationTraversal.*;
@@ -28,7 +26,6 @@ import static java.util.stream.Stream.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
-import java.util.function.*;
import java.util.stream.*;
import org.apache.juneau.common.collections.*;
@@ -405,7 +402,6 @@ public class AnnotationProvider {
}
// @formatter:off
- private final Cache<Class<?>,List<AnnotationInfo<Annotation>>>
classDeclaredAnnotations;
private final Cache<Class<?>,List<AnnotationInfo<Annotation>>>
classRuntimeAnnotations;
private final Cache<Method,List<AnnotationInfo<Annotation>>>
methodRuntimeAnnotations;
private final Cache<Field,List<AnnotationInfo<Annotation>>>
fieldRuntimeAnnotations;
@@ -419,10 +415,6 @@ public class AnnotationProvider {
* @param builder The builder containing configuration settings.
*/
protected AnnotationProvider(Builder builder) {
- this.classDeclaredAnnotations =
Cache.<Class<?>,List<AnnotationInfo<Annotation>>>create()
- .supplier(this::findClassDeclaredAnnotations)
- .disableCaching(builder.disableCaching)
- .build();
this.classRuntimeAnnotations =
Cache.<Class<?>,List<AnnotationInfo<Annotation>>>create()
.supplier(this::findClassRuntimeAnnotations)
.disableCaching(builder.disableCaching)
@@ -442,77 +434,10 @@ public class AnnotationProvider {
this.runtimeAnnotations = builder.runtimeAnnotations.build();
}
-
-
//-----------------------------------------------------------------------------------------------------------------
- // Public API
-
//-----------------------------------------------------------------------------------------------------------------
-
- /**
- * Finds all declared annotations on the specified class in
parent-to-child order (reversed).
- *
- * <p>
- * This method returns annotations in the opposite order from {@link
#xfindDeclared(Class)}.
- * 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.
- * @deprecated Use {@link #findTopDown(ClassInfo,
AnnotationTraversal...)} with {@link AnnotationTraversal#SELF SELF} instead.
- */
- @Deprecated
- public Stream<AnnotationInfo<Annotation>>
xfindDeclaredParentFirst(Class<?> onClass) {
- assertArgNotNull("onClass", onClass);
- var list = classDeclaredAnnotations.get(onClass);
- // Iterate backwards to get parent-to-child order
- return rstream(list);
- }
-
- /**
- * Finds all declared annotations of the specified type on the
specified class in parent-to-child order (reversed).
- *
- * <p>
- * This method returns annotations in the opposite order from {@link
#xfindDeclared(Class, Class)}.
- *
- * @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 in
parent-to-child order.
- * @deprecated Use {@link #findTopDown(Class, ClassInfo,
AnnotationTraversal...)} with {@link AnnotationTraversal#SELF SELF} instead.
- */
- @Deprecated
- @SuppressWarnings("unchecked")
- public <A extends Annotation> Stream<AnnotationInfo<A>>
xfindDeclaredParentFirst(Class<A> type, Class<?> onClass) {
- assertArgNotNull("type", type);
- assertArgNotNull("onClass", onClass);
- return xfindDeclaredParentFirst(onClass)
- .filter(a -> a.isType(type))
- .map(a -> (AnnotationInfo<A>)a);
- }
-
//-----------------------------------------------------------------------------------------------------------------
// Private implementation
//-----------------------------------------------------------------------------------------------------------------
- private List<AnnotationInfo<Annotation>>
findClassDeclaredAnnotations(Class<?> forClass) {
- var list = new ArrayList<AnnotationInfo<Annotation>>();
-
- // On this class
- findDeclaredAnnotations(list, forClass);
-
- return u(list);
- }
-
private List<AnnotationInfo<Annotation>>
findClassRuntimeAnnotations(Class<?> forClass) {
ClassInfo ci = ClassInfo.of(forClass);
return runtimeAnnotations.find(forClass).map(a ->
AnnotationInfo.of(ci, a)).toList();
@@ -533,80 +458,6 @@ public class AnnotationProvider {
return runtimeAnnotations.find(forConstructor).map(a ->
AnnotationInfo.of(ci, a)).toList();
}
- /**
- * Finds all declared annotations on the specified class and appends
them to the list.
- *
- * @param appendTo The list to append to.
- * @param forClass The class to find declared annotations on.
- */
- private void findDeclaredAnnotations(List<AnnotationInfo<Annotation>>
appendTo, Class<?> forClass) {
- var ci = ClassInfo.of(forClass);
- runtimeAnnotations.find(forClass).forEach(x ->
appendTo.add(AnnotationInfo.of(ClassInfo.of(forClass), x)));
- for (var a : forClass.getDeclaredAnnotations())
- streamRepeated(a).forEach(a2 ->
appendTo.add(AnnotationInfo.of(ci, a2)));
- }
-
- /**
- * Iterates through annotations on a method, its declaring class
hierarchy, and return type hierarchy.
- *
- * <p>
- * This traverses annotations in parent-first order from:
- * <ol>
- * <li>Declaring class hierarchy (via this AnnotationProvider)
- * <li>Method hierarchy (parent-first, declared annotations only)
- * <li>Return type hierarchy (via this AnnotationProvider)
- * </ol>
- *
- * @param <A> The annotation type.
- * @param type The annotation type to search for.
- * @param mi The method info to traverse.
- * @param filter Optional filter to apply to annotations. Can be
<jk>null</jk>.
- * @param action The action to perform on each matching annotation.
- * @deprecated Use {@link #findTopDown(Class, MethodInfo,
AnnotationTraversal...)} instead.
- */
- @Deprecated
- public <A extends Annotation> void xforEachMethodAnnotation(Class<A>
type, MethodInfo mi, Predicate<A> filter, Consumer<A> action) {
- xforEachClassAnnotation(type, mi.getDeclaringClass(), filter,
action);
- rstream(mi.getMatchingMethods())
- .flatMap(m -> m.getDeclaredAnnotations().stream())
- .map(AnnotationInfo::inner)
- .filter(type::isInstance)
- .map(type::cast)
- .forEach(a -> consumeIf(filter, action, a));
- xforEachClassAnnotation(type,
mi.getReturnType().unwrap(Value.class, Optional.class), filter, action);
- }
-
- /**
- * Iterates through annotations on a class hierarchy.
- *
- * <p>
- * This traverses annotations in parent-first order from:
- * <ol>
- * <li>Package annotations
- * <li>Interface hierarchy (parent-first)
- * <li>Class hierarchy (parent-first)
- * </ol>
- *
- * @param <A> The annotation type.
- * @param type The annotation type to search for.
- * @param ci The class info to traverse.
- * @param filter Optional filter to apply to annotations. Can be
<jk>null</jk>.
- * @param action The action to perform on each matching annotation.
- * @deprecated Use {@link #findTopDown(Class, ClassInfo,
AnnotationTraversal...)} instead.
- */
- @Deprecated
- public <A extends Annotation> void xforEachClassAnnotation(Class<A>
type, ClassInfo ci, Predicate<A> filter, Consumer<A> action) {
- A t2 = ci.getPackageAnnotation(type);
- if (nn(t2))
- consumeIf(filter, action, t2);
- var interfaces2 = ci.getInterfaces();
- for (int i = interfaces2.size() - 1; i >= 0; i--)
- xfindDeclaredParentFirst(type,
interfaces2.get(i).inner()).map(x -> x.inner()).filter(x -> filter == null ||
filter.test(x)).forEach(x -> action.accept(x));
- var parents2 = ci.getParents();
- for (int i = parents2.size() - 1; i >= 0; i--)
- xfindDeclaredParentFirst(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
//-----------------------------------------------------------------------------------------------------------------
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
index b32e96ff05..6803a1a637 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
@@ -688,10 +688,10 @@ public class BeanPropertyMeta implements
Comparable<BeanPropertyMeta> {
var si = setter == null ? null : MethodInfo.of(setter);
if (a == null)
return l;
- ap.xforEachClassAnnotation(a,
getBeanMeta().getClassMeta().getInfo(), x -> true, x -> l.add(x));
+ ap.findTopDown(a, getBeanMeta().getClassMeta().getInfo()).map(x
-> x.inner()).forEach(x -> l.add(x));
if (nn(field)) {
ap.find(a, fi).map(x -> x.inner()).forEach(x ->
l.add(x));
- ap.xforEachClassAnnotation(a,
ClassInfo.of(field.getType()), x -> true, x -> l.add(x));
+ ap.findTopDown(a, ClassInfo.of(field.getType())).map(x
-> x.inner()).forEach(x -> l.add(x));
}
if (nn(gi)) {
// Walk up the inheritance hierarchy for the getter
method
@@ -699,7 +699,7 @@ public class BeanPropertyMeta implements
Comparable<BeanPropertyMeta> {
ap.find(a, MethodInfo.of(parentGetter)).map(x
-> x.inner()).forEach(x -> l.add(x));
});
ap.find(a, gi).map(x -> x.inner()).forEach(x ->
l.add(x));
- ap.xforEachClassAnnotation(a, gi.getReturnType(), x ->
true, x -> l.add(x));
+ ap.findTopDown(a, gi.getReturnType()).map(x ->
x.inner()).forEach(x -> l.add(x));
}
if (nn(setter)) {
// Walk up the inheritance hierarchy for the setter
method
@@ -707,7 +707,7 @@ public class BeanPropertyMeta implements
Comparable<BeanPropertyMeta> {
ap.find(a, MethodInfo.of(parentSetter)).map(x
-> x.inner()).forEach(x -> l.add(x));
});
ap.find(a, si).map(x -> x.inner()).forEach(x ->
l.add(x));
- ap.xforEachClassAnnotation(a,
ClassInfo.of(setter.getReturnType()), x -> true, x -> l.add(x));
+ ap.findTopDown(a,
ClassInfo.of(setter.getReturnType())).map(x -> x.inner()).forEach(x ->
l.add(x));
}
if (nn(extraKeys)) {
MethodInfo eki = MethodInfo.of(extraKeys);
@@ -716,7 +716,7 @@ public class BeanPropertyMeta implements
Comparable<BeanPropertyMeta> {
ap.find(a,
MethodInfo.of(parentExtraKeys)).map(x -> x.inner()).forEach(x -> l.add(x));
});
ap.find(a, eki).map(x -> x.inner()).filter(x ->
true).forEach(x -> l.add(x));
- ap.xforEachClassAnnotation(a,
ClassInfo.of(extraKeys.getReturnType()), x -> true, x -> l.add(x));
+ ap.findTopDown(a,
ClassInfo.of(extraKeys.getReturnType())).map(x -> x.inner()).forEach(x ->
l.add(x));
}
return l;
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
index 8296be7fb7..bc3b90f21f 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
@@ -150,7 +150,8 @@ public class BeanRegistry {
});
} else {
Value<String> typeName = Value.empty();
-
beanContext.getAnnotationProvider().xforEachClassAnnotation(Bean.class, ci, x
-> isNotEmpty(x.typeName()), x -> typeName.set(x.typeName()));
+
//beanContext.getAnnotationProvider().xforEachClassAnnotation(Bean.class, ci, x
-> isNotEmpty(x.typeName()), x -> typeName.set(x.typeName()));
+
beanContext.getAnnotationProvider().findTopDown(Bean.class, ci).map(x ->
x.inner().typeName()).filter(x -> isNotEmpty(x)).forEach(x -> typeName.set(x));
addToMap(typeName.orElseThrow(() -> new
BeanRuntimeException("Class ''{0}'' was passed to BeanRegistry but it doesn't
have a @Bean(typeName) annotation defined.", cn(c))),
beanContext.getClassMeta(c));
}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index 0a38265bc5..d54b571470 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -467,7 +467,7 @@ public class ClassMeta<T> implements Type {
private BeanFilter findBeanFilter(BeanContext bc) {
try {
List<Bean> ba = list();
-
bc.getAnnotationProvider().xforEachClassAnnotation(Bean.class, info, x -> true,
x -> ba.add(x));
+
bc.getAnnotationProvider().findTopDown(Bean.class, info).map(x ->
x.inner()).forEach(x -> ba.add(x));
if (! ba.isEmpty())
return
BeanFilter.create(innerClass).applyAnnotations(ba).build();
} catch (Exception e) {
@@ -483,7 +483,7 @@ public class ClassMeta<T> implements Type {
private MarshalledFilter findMarshalledFilter(BeanContext bc) {
try {
List<Marshalled> ba = list();
-
bc.getAnnotationProvider().xforEachClassAnnotation(Marshalled.class, info, x ->
true, x -> ba.add(x));
+
bc.getAnnotationProvider().findTopDown(Marshalled.class, info).map(x ->
x.inner()).forEach(x -> ba.add(x));
if (! ba.isEmpty())
return
MarshalledFilter.create(innerClass).applyAnnotations(ba).build();
} catch (Exception e) {
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java
index 46b75c7099..1d99a31c48 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java
@@ -33,7 +33,6 @@ import java.util.stream.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
-import org.apache.juneau.annotation.Items;
import org.apache.juneau.bean.swagger.Swagger;
import org.apache.juneau.collections.*;
import org.apache.juneau.common.collections.*;
@@ -159,7 +158,7 @@ public class BasicSwaggerProviderSession {
// Combine it with @Rest(swagger)
List<Rest> restAnnotations = list();
-
context.getAnnotationProvider().xforEachClassAnnotation(Rest.class, rci, x ->
true, x -> restAnnotations.add(x));
+ ap.findTopDown(Rest.class, rci).map(x -> x.inner()).forEach(x
-> restAnnotations.add(x));
for (var rr : restAnnotations) {
JsonMap sInfo = omSwagger.getMap("info", true);
@@ -437,9 +436,9 @@ public class BasicSwaggerProviderSession {
for (var eci : mi.getExceptionTypes()) {
if (eci.hasAnnotation(Response.class)) {
List<Response> la = list();
-
context.getAnnotationProvider().xforEachClassAnnotation(Response.class, eci, x
-> true, x -> la.add(x));
+ ap.findTopDown(Response.class,
eci).map(x -> x.inner()).forEach(x -> la.add(x));
List<StatusCode> la2 = list();
-
context.getAnnotationProvider().xforEachClassAnnotation(StatusCode.class, eci,
x -> true, x -> la2.add(x));
+ ap.findTopDown(StatusCode.class,
eci).map(x -> x.inner()).forEach(x -> la2.add(x));
Set<Integer> codes = getCodes(la2, 500);
for (var a : la) {
for (var code : codes) {
@@ -461,7 +460,8 @@ public class BasicSwaggerProviderSession {
String ha = a.name();
for (var code : codes) {
JsonMap header
= responses.getMap(String.valueOf(code), true).getMap("headers",
true).getMap(ha, true);
-
context.getAnnotationProvider().xforEachMethodAnnotation(Schema.class, ecmi, x
-> true, x -> merge(header, x));
+
ap.findTopDown(Schema.class, ecmi).map(x -> x.inner()).forEach(x ->
merge(header, x));
+ //
context.getAnnotationProvider().xforEachMethodAnnotation(Schema.class, ecmi, x
-> true, x -> merge(header, x));
rstream(ecmi.getReturnType().unwrap(Value.class,
Optional.class).getAnnotations()).map(x ->
x.cast(Schema.class)).filter(Objects::nonNull).map(AnnotationInfo::inner).forEach(x
-> merge(header, x));
pushupSchemaFields(RESPONSE_HEADER, header, getSchema(header.getMap("schema"),
ecmi.getReturnType().unwrap(Value.class, Optional.class).innerType(), bs));
}
@@ -472,16 +472,19 @@ public class BasicSwaggerProviderSession {
if (mi.hasAnnotation(Response.class) ||
mi.getReturnType().unwrap(Value.class,
Optional.class).hasAnnotation(Response.class)) {
List<Response> la = list();
-
context.getAnnotationProvider().xforEachMethodAnnotation(Response.class, mi, x
-> true, x -> la.add(x));
+ ap.findTopDown(Response.class, mi).map(x ->
x.inner()).forEach(x -> la.add(x));
+
//context.getAnnotationProvider().xforEachMethodAnnotation(Response.class, mi,
x -> true, x -> la.add(x));
List<StatusCode> la2 = list();
-
context.getAnnotationProvider().xforEachMethodAnnotation(StatusCode.class, mi,
x -> true, x -> la2.add(x));
+
//context.getAnnotationProvider().xforEachMethodAnnotation(StatusCode.class,
mi, x -> true, x -> la2.add(x));
+ ap.findTopDown(StatusCode.class, mi).map(x ->
x.inner()).forEach(x -> la2.add(x));
Set<Integer> codes = getCodes(la2, 200);
for (var a : la) {
for (var code : codes) {
JsonMap om =
responses.getMap(String.valueOf(code), true);
merge(om, a);
JsonMap schema =
getSchema(om.getMap("schema"), m.getGenericReturnType(), bs);
-
context.getAnnotationProvider().xforEachMethodAnnotation(Schema.class, mi, x ->
true, x -> merge(schema, x));
+ ap.findTopDown(Schema.class,
mi).map(x -> x.inner()).forEach(x -> merge(schema, x));
+
//context.getAnnotationProvider().xforEachMethodAnnotation(Schema.class, mi, x
-> true, x -> merge(schema, x));
pushupSchemaFields(RESPONSE,
om, schema);
om.appendIf(nem, "schema",
schema);
addBodyExamples(sm, om, true,
m.getGenericReturnType(), locale);
@@ -497,7 +500,8 @@ public class BasicSwaggerProviderSession {
if (! isMulti(a)) {
for (var code :
codes) {
JsonMap
header = responses.getMap(String.valueOf(code), true).getMap("headers",
true).getMap(ha, true);
-
context.getAnnotationProvider().xforEachMethodAnnotation(Schema.class, ecmi, x
-> true, x -> merge(header, x));
+
//context.getAnnotationProvider().xforEachMethodAnnotation(Schema.class, ecmi,
x -> true, x -> merge(header, x));
+
ap.findTopDown(Schema.class, ecmi).map(x -> x.inner()).forEach(x ->
merge(header, x));
rstream(ecmi.getReturnType().unwrap(Value.class,
Optional.class).getAnnotations()).map(x ->
x.cast(Schema.class)).filter(Objects::nonNull).map(AnnotationInfo::inner).forEach(x
-> merge(header, x));
merge(header, a.schema());
pushupSchemaFields(RESPONSE_HEADER, header, getSchema(header,
ecmi.getReturnType().innerType(), bs));