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 695b7c770d Utility class modernization
695b7c770d is described below

commit 695b7c770dcbe490fd02a78767763c7c53bd8b12
Author: James Bognar <[email protected]>
AuthorDate: Wed Nov 5 15:54:37 2025 -0500

    Utility class modernization
---
 .../juneau/common/reflect/AnnotationProvider2.java | 42 ++++++++++++++++++
 .../apache/juneau/common/utils/PredicateUtils.java | 50 ++++++++++++++++++++++
 .../src/main/java/org/apache/juneau/Context.java   |  5 +--
 3 files changed, 93 insertions(+), 4 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 e425717e59..7e97c077c5 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
@@ -272,6 +272,7 @@ public class AnnotationProvider2 {
                return classDeclaredAnnotations.get(onClass);
        }
 
+       @SuppressWarnings("unchecked")
        public <A extends Annotation> Stream<AnnotationInfo<A>> 
findDeclared(Class<A> type, Class<?> onClass) {
                assertArgNotNull("type", type);
                assertArgNotNull("onClass", onClass);
@@ -280,6 +281,47 @@ public class AnnotationProvider2 {
                        .map(a -> (AnnotationInfo<A>)a);
        }
 
+       /**
+        * 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 
#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.
+        *
+        * @param onClass The class to search on.
+        * @return A stream of {@link AnnotationInfo} objects in 
parent-to-child order.
+        */
+       public Stream<AnnotationInfo<Annotation>> 
findDeclaredParentFirst(Class<?> onClass) {
+               assertArgNotNull("onClass", onClass);
+               var list = classDeclaredAnnotations.get(onClass);
+               // Iterate backwards to get parent-to-child order
+               return java.util.stream.IntStream.range(0, list.size())
+                       .map(i -> list.size() - 1 - i)
+                       .mapToObj(list::get);
+       }
+
+       /**
+        * 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 
#findDeclared(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.
+        */
+       @SuppressWarnings("unchecked")
+       public <A extends Annotation> Stream<AnnotationInfo<A>> 
findDeclaredParentFirst(Class<A> type, Class<?> onClass) {
+               assertArgNotNull("type", type);
+               assertArgNotNull("onClass", onClass);
+               return findDeclaredParentFirst(onClass)
+                       .filter(a -> a.isType(type))
+                       .map(a -> (AnnotationInfo<A>)a);
+       }
+
        public List<AnnotationInfo<Annotation>> find(Method onMethod) {
                assertArgNotNull("onMethod", onMethod);
                return methodAnnotations.get(onMethod);
diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/PredicateUtils.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/PredicateUtils.java
index 6c81f67a85..ac8186b639 100644
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/PredicateUtils.java
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/PredicateUtils.java
@@ -124,4 +124,54 @@ public final class PredicateUtils {
                if (test(predicate, value))
                        consumer.accept(value);
        }
+
+       /**
+        * Returns a function that prints the input value to stderr and returns 
it unchanged.
+        *
+        * <p>
+        * Useful for debugging streams by inserting into a stream pipeline 
with {@code .map(peek())}.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      list.stream()
+        *              .map(peek())
+        *              .filter(x -&gt; x != <jk>null</jk>)
+        *              .collect(Collectors.toList());
+        * </p>
+        *
+        * @param <T> The type of value.
+        * @return A function that prints and returns the value.
+        */
+       public static <T> Function<T,T> peek() {
+               return v -> {
+                       System.err.println(v);
+                       return v;
+               };
+       }
+
+       /**
+        * Returns a function that prints the input value to stderr using a 
custom formatter and returns it unchanged.
+        *
+        * <p>
+        * Useful for debugging streams by inserting into a stream pipeline 
with {@code .map(peek(...))}.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      list.stream()
+        *              .map(peek(<js>"Processing: {0}"</js>, x -&gt; 
x.getName()))
+        *              .filter(x -&gt; x != <jk>null</jk>)
+        *              .collect(Collectors.toList());
+        * </p>
+        *
+        * @param <T> The type of value.
+        * @param message A format string using {@code {0}} as placeholder for 
the formatted value.
+        * @param formatter A function to extract/format the value for display.
+        * @return A function that prints and returns the value.
+        */
+       public static <T> Function<T,T> peek(String message, Function<T,?> 
formatter) {
+               return v -> {
+                       System.err.println(message.replace("{0}", 
String.valueOf(formatter.apply(v))));
+                       return v;
+               };
+       }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
index ce025328e4..2f4fc7f394 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
@@ -895,10 +895,7 @@ public abstract class Context implements 
AnnotationProvider {
 
        @Override /* Overridden from MetaProvider */
        public <A extends Annotation> void forEachDeclaredAnnotation(Class<A> 
type, Class<?> onClass, Predicate<A> filter, Consumer<A> action) {
-//             getAnnotationProvider().find(type, onClass).map(x -> 
x.inner()).filter(x -> filter.test(x)).forEach(x -> action.accept(x));
-               if (nn(type) && nn(onClass))
-                       for (var a : declaredAnnotations(type, onClass))
-                               consumeIf(filter, action, a);
+               getAnnotationProvider().findDeclaredParentFirst(type, 
onClass).map(x -> x.inner()).filter(x -> filter == null || 
filter.test(x)).forEach(x -> action.accept(x));
        }
 
        /**

Reply via email to