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 6cb791e  ClassInfo refactoring.
6cb791e is described below

commit 6cb791e6ab740443a6d92579a8a010bd19499f3a
Author: JamesBognar <[email protected]>
AuthorDate: Mon Jan 24 09:36:34 2022 -0500

    ClassInfo refactoring.
---
 .../src/main/java/org/apache/juneau/BeanMeta.java  |  35 ++--
 .../java/org/apache/juneau/BeanPropertyMeta.java   |  37 ++---
 .../src/main/java/org/apache/juneau/Context.java   | 185 ++++++++++-----------
 .../main/java/org/apache/juneau/MetaProvider.java  | 102 +++++++++---
 .../apache/juneau/html/HtmlBeanPropertyMeta.java   |   9 +-
 .../apache/juneau/internal/CollectionUtils.java    |  13 ++
 .../org/apache/juneau/reflect/ConstructorInfo.java |   6 +-
 .../java/org/apache/juneau/reflect/FieldInfo.java  |   7 +-
 .../java/org/apache/juneau/reflect/MethodInfo.java |   9 +-
 9 files changed, 230 insertions(+), 173 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
index b50bcb5..be14842 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
@@ -23,6 +23,7 @@ import java.io.*;
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
+import java.util.function.*;
 
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.collections.*;
@@ -228,9 +229,11 @@ public class BeanMeta<T> {
                                                        throw new 
BeanRuntimeException(c, "Multiple instances of '@Beanc' found.");
                                                constructor = x;
                                                constructorArgs = new String[0];
-                                               for (Beanc bc : 
ctx.getAnnotations(Beanc.class, x))
-                                                       if (! 
bc.properties().isEmpty())
-                                                               constructorArgs 
= split(bc.properties());
+                                               Consumer<Beanc> consumer = y -> 
{
+                                                       if (! 
y.properties().isEmpty())
+                                                               constructorArgs 
= split(y.properties());
+                                               };
+                                               ctx.getAnnotations(Beanc.class, 
x.inner(), consumer);
                                                if (! 
x.hasNumParams(constructorArgs.length)) {
                                                        if 
(constructorArgs.length != 0)
                                                                throw new 
BeanRuntimeException(c, "Number of properties defined in '@Beanc' annotation 
does not match number of parameters in constructor.");
@@ -255,9 +258,11 @@ public class BeanMeta<T> {
                                                                throw new 
BeanRuntimeException(c, "Multiple instances of '@Beanc' found.");
                                                        constructor = x;
                                                        constructorArgs = new 
String[0];
-                                                       for (Beanc bc : 
ctx.getAnnotations(Beanc.class, x))
-                                                               if (! 
bc.properties().isEmpty())
-                                                                       
constructorArgs = split(bc.properties());
+                                                       Consumer<Beanc> 
consumer = y -> {
+                                                               if (! 
y.properties().isEmpty())
+                                                                       
constructorArgs = split(y.properties());
+                                                       };
+                                                       
ctx.getAnnotations(Beanc.class, x.inner(), consumer);
                                                        if (! 
x.hasNumParams(constructorArgs.length)) {
                                                                if 
(constructorArgs.length != 0)
                                                                        throw 
new BeanRuntimeException(c, "Number of properties defined in '@Beanc' 
annotation does not match number of parameters in constructor.");
@@ -539,8 +544,10 @@ public class BeanMeta<T> {
                 * Returns null if the field isn't a valid property.
                 */
                private String findPropertyName(Field f) {
-                       List<Beanp> lp = ctx.getAnnotations(Beanp.class, f);
-                       List<Name> ln = ctx.getAnnotations(Name.class, f);
+                       List<Beanp> lp = new ArrayList<>();
+                       List<Name> ln = new ArrayList<>();
+                       ctx.getAnnotations(Beanp.class, f, x -> lp.add(x));
+                       ctx.getAnnotations(Name.class, f, x -> ln.add(x));
                        String name = bpName(lp, ln);
                        if (isNotEmpty(name))
                                return name;
@@ -667,15 +674,17 @@ public class BeanMeta<T> {
                                if (m.getParamCount() > 2)
                                        continue;
 
-                               BeanIgnore bi = 
ctx.getLastAnnotation(BeanIgnore.class, m);
+                               BeanIgnore bi = 
ctx.getLastAnnotation(BeanIgnore.class, m.inner());
                                if (bi != null)
                                        continue;
-                               Transient t = 
ctx.getLastAnnotation(Transient.class, m);
+                               Transient t = 
ctx.getLastAnnotation(Transient.class, m.inner());
                                if (t != null && t.value())
                                        continue;
 
-                               List<Beanp> lp = 
ctx.getAnnotations(Beanp.class, m);
-                               List<Name> ln = ctx.getAnnotations(Name.class, 
m);
+                               List<Beanp> lp = new ArrayList<>();
+                               List<Name> ln = new ArrayList<>();
+                               ctx.getAnnotations(Beanp.class, m.inner(), x -> 
lp.add(x));
+                               ctx.getAnnotations(Name.class, m.inner(), x -> 
ln.add(x));
                                if (! (m.isVisible(v) || lp.size() > 0 || 
ln.size() > 0))
                                        continue;
 
@@ -774,7 +783,7 @@ public class BeanMeta<T> {
                                && (x.isNotTransient() || noIgnoreTransients)
                                && (x.hasNoAnnotation(Transient.class) || 
noIgnoreTransients)
                                && x.hasNoAnnotation(BeanIgnore.class, ctx)
-                               && (v.isVisible(x.inner()) || 
ctx.getAnnotations(Beanp.class, x).size() > 0),
+                               && (v.isVisible(x.inner()) || 
ctx.hasAnnotation(Beanp.class, x)),
                                x -> l.add(x.inner())
                        );
                }
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 3338e71..af3da26 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
@@ -180,7 +180,8 @@ public final class BeanPropertyMeta {
                        canWrite |= (field != null || setter != null);
 
                        if (innerField != null) {
-                               List<Beanp> lp = bc.getAnnotations(Beanp.class, 
innerField);
+                               List<Beanp> lp = new ArrayList<>();
+                               bc.getAnnotations(Beanp.class, innerField, x -> 
lp.add(x));
                                if (field != null || lp.size() > 0) {
                                        // Only use field type if it's a bean 
property or has @Beanp annotation.
                                        // Otherwise, we want to infer the type 
from the getter or setter.
@@ -196,13 +197,13 @@ public final class BeanPropertyMeta {
                                        if (! p.wo().isEmpty())
                                                writeOnly = 
Boolean.valueOf(p.wo());
                                }
-                               for (Swap s : bc.getAnnotations(Swap.class, 
innerField))
-                                       swap = getPropertySwap(s);
-                               isUri |= last(bc.getAnnotations(Uri.class, 
innerField)) != null;
+                               bc.getAnnotations(Swap.class, innerField, x -> 
swap = getPropertySwap(x));
+                               isUri |= bc.getAnnotation(Uri.class, 
innerField, x->true) != null;
                        }
 
                        if (getter != null) {
-                               List<Beanp> lp = bc.getAnnotations(Beanp.class, 
getter);
+                               List<Beanp> lp = new ArrayList<>();
+                               bc.getAnnotations(Beanp.class, getter, x -> 
lp.add(x));
                                if (rawTypeMeta == null)
                                        rawTypeMeta = 
bc.resolveClassMeta(last(lp), getter.getGenericReturnType(), typeVarImpls);
                                isUri |= (rawTypeMeta.isUri() || 
bc.hasAnnotation(Uri.class, getter));
@@ -215,12 +216,12 @@ public final class BeanPropertyMeta {
                                        if (! p.wo().isEmpty())
                                                writeOnly = 
Boolean.valueOf(p.wo());
                                }
-                               for (Swap s : bc.getAnnotations(Swap.class, 
getter))
-                                       swap = getPropertySwap(s);
+                               bc.getAnnotations(Swap.class, getter, x -> swap 
= getPropertySwap(x));
                        }
 
                        if (setter != null) {
-                               List<Beanp> lp = bc.getAnnotations(Beanp.class, 
setter);
+                               List<Beanp> lp = new ArrayList<>();
+                               bc.getAnnotations(Beanp.class, setter, x -> 
lp.add(x));
                                if (rawTypeMeta == null)
                                        rawTypeMeta = 
bc.resolveClassMeta(last(lp), setter.getGenericParameterTypes()[0], 
typeVarImpls);
                                isUri |= (rawTypeMeta.isUri() || 
bc.hasAnnotation(Uri.class, setter));
@@ -235,8 +236,7 @@ public final class BeanPropertyMeta {
                                        if (! p.wo().isEmpty())
                                                writeOnly = 
Boolean.valueOf(p.wo());
                                }
-                               for (Swap s : bc.getAnnotations(Swap.class, 
setter))
-                                       swap = getPropertySwap(s);
+                               bc.getAnnotations(Swap.class, setter, x -> swap 
= getPropertySwap(x));
                        }
 
                        if (rawTypeMeta == null)
@@ -322,7 +322,7 @@ public final class BeanPropertyMeta {
                        return null;
                }
 
-               private ObjectSwap getPropertySwap(Swap s) throws Exception {
+               private ObjectSwap getPropertySwap(Swap s) throws 
RuntimeException {
                        Class<?> c = s.value();
                        if (c == Null.class)
                                c = s.impl();
@@ -1112,21 +1112,20 @@ public final class BeanPropertyMeta {
                if (a == null)
                        return l;
                getBeanMeta().getClassMeta().getInfo().getAnnotations(a, bc, x 
-> l.add(x));
-
                if (field != null) {
-                       l.addAll(bc.getAnnotations(a, field));
+                       bc.getAnnotations(a, field, x -> l.add(x));
                        ClassInfo.of(field.getType()).getAnnotations(a, bc, x 
-> l.add(x));
                }
                if (getter != null) {
-                       l.addAll(bc.getAnnotations(a, getter));
+                       bc.getAnnotations(a, getter, x -> l.add(x));
                        ClassInfo.of(getter.getReturnType()).getAnnotations(a, 
bc, x -> l.add(x));
                }
                if (setter != null) {
-                       l.addAll(bc.getAnnotations(a, setter));
+                       bc.getAnnotations(a, setter, x -> l.add(x));
                        ClassInfo.of(setter.getReturnType()).getAnnotations(a, 
bc, x -> l.add(x));
                }
                if (extraKeys != null) {
-                       l.addAll(bc.getAnnotations(a, extraKeys));
+                       bc.getAnnotations(a, extraKeys, x -> l.add(x));
                        
ClassInfo.of(extraKeys.getReturnType()).getAnnotations(a, bc, x -> l.add(x));
                }
 
@@ -1145,9 +1144,9 @@ public final class BeanPropertyMeta {
                BeanContext bc = beanContext;
                if (a == null)
                        return l;
-               l.addAll(bc.getAnnotations(a, field));
-               l.addAll(bc.getAnnotations(a, getter));
-               l.addAll(bc.getAnnotations(a, setter));
+               bc.getAnnotations(a, field, x -> l.add(x));
+               bc.getAnnotations(a, getter, x -> l.add(x));
+               bc.getAnnotations(a, setter, x -> l.add(x));
                return l;
        }
 
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 b39c96f..62de0b2 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
@@ -930,9 +930,9 @@ public abstract class Context implements MetaProvider {
 
        private TwoKeyConcurrentCache<Class<?>,Class<? extends 
Annotation>,Annotation[]> classAnnotationCache = new 
TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING);
        private TwoKeyConcurrentCache<Class<?>,Class<? extends 
Annotation>,Annotation[]> declaredClassAnnotationCache = new 
TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING);
-       private TwoKeyConcurrentCache<Method,Class<? extends 
Annotation>,List<Annotation>> methodAnnotationCache = new 
TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING);
-       private TwoKeyConcurrentCache<Field,Class<? extends 
Annotation>,List<Annotation>> fieldAnnotationCache = new 
TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING);
-       private TwoKeyConcurrentCache<Constructor<?>,Class<? extends 
Annotation>,List<Annotation>> constructorAnnotationCache = new 
TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING);
+       private TwoKeyConcurrentCache<Method,Class<? extends 
Annotation>,Annotation[]> methodAnnotationCache = new 
TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING);
+       private TwoKeyConcurrentCache<Field,Class<? extends 
Annotation>,Annotation[]> fieldAnnotationCache = new 
TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING);
+       private TwoKeyConcurrentCache<Constructor<?>,Class<? extends 
Annotation>,Annotation[]> constructorAnnotationCache = new 
TwoKeyConcurrentCache<>(DISABLE_ANNOTATION_CACHING);
 
        @Override /* MetaProvider */
        public <A extends Annotation> void getAnnotations(Class<A> a, Class<?> 
c, Consumer<A> consumer) {
@@ -996,136 +996,121 @@ public abstract class Context implements MetaProvider {
                return aa;
        }
 
-       /**
-        * Finds the specified annotations on the specified method.
-        *
-        * @param <A> The annotation type to find.
-        * @param a The annotation type to find.
-        * @param m The method to search on.
-        * @return The annotations in an unmodifiable list, or an empty list if 
not found.
-        */
-       @SuppressWarnings("unchecked")
        @Override /* MetaProvider */
-       public <A extends Annotation> List<A> getAnnotations(Class<A> a, Method 
m) {
-               if (a == null || m == null)
-                       return emptyList();
-               List<Annotation> aa = methodAnnotationCache.get(m, a);
+       public <A extends Annotation> void getAnnotations(Class<A> a, Method m, 
Consumer<A> consumer) {
+               if (a != null && m != null)
+                       for (A aa : annotations(a, m))
+                               consumer.accept(aa);
+       }
+
+       @Override /* MetaProvider */
+       public <A extends Annotation> A getAnnotation(Class<A> a, Method m, 
Predicate<A> predicate) {
+               if (a != null && m != null)
+                       for (A aa : annotations(a, m))
+                               if (predicate.test(aa))
+                                       return aa;
+               return null;
+       }
+
+       @SuppressWarnings("unchecked")
+       private <A extends Annotation> A[] annotations(Class<A> a, Method m) {
+               A[] aa = (A[])methodAnnotationCache.get(m, a);
                if (aa == null) {
                        A[] x = m.getAnnotationsByType(a);
                        AList<Annotation> l = new AList<>(Arrays.asList(x));
                        annotationMap.appendAll(m, a, l);
-                       aa = l.unmodifiable();
+                       aa = (A[]) Array.newInstance(a, l.size());
+                       for (int i = 0; i < l.size(); i++)
+                               Array.set(aa, i, l.get(i));
                        methodAnnotationCache.put(m, a, aa);
                }
-               return (List<A>)aa;
-       }
-
-       /**
-        * Finds the specified annotations on the specified method.
-        *
-        * @param <A> The annotation type to find.
-        * @param a The annotation type to find.
-        * @param m The method to search on.
-        * @return The annotations in an unmodifiable list, or an empty list if 
not found.
-        */
-       public <A extends Annotation> List<A> getAnnotations(Class<A> a, 
MethodInfo m) {
-               return getAnnotations(a, m == null ? null : m.inner());
+               return aa;
        }
 
-       /**
-        * Finds the last specified annotations on the specified method.
-        *
-        * @param <A> The annotation type to find.
-        * @param a The annotation type to find.
-        * @param m The method to search on.
-        * @return The annotation, or <jk>null</jk> if not found.
-        */
-       public <A extends Annotation> A getLastAnnotation(Class<A> a, Method m) 
{
-               return last(getAnnotations(a, m));
+       @Override /* MetaProvider */
+       public <A extends Annotation> void getAnnotations(Class<A> a, Field f, 
Consumer<A> consumer) {
+               if (a != null && f != null)
+                       for (A aa : annotations(a, f))
+                               consumer.accept(aa);
        }
 
-       /**
-        * Finds the last specified annotations on the specified method.
-        *
-        * @param <A> The annotation type to find.
-        * @param a The annotation type to find.
-        * @param m The method to search on.
-        * @return The annotation, or <jk>null</jk> if not found.
-        */
-       public <A extends Annotation> A getLastAnnotation(Class<A> a, 
MethodInfo m) {
-               return last(getAnnotations(a, m));
+       @Override /* MetaProvider */
+       public <A extends Annotation> A getAnnotation(Class<A> a, Field f, 
Predicate<A> predicate) {
+               if (a != null && f != null)
+                       for (A aa : annotations(a, f))
+                               if (predicate.test(aa))
+                                       return aa;
+               return null;
        }
 
-       /**
-        * Finds the specified annotations on the specified field.
-        *
-        * @param <A> The annotation type to find.
-        * @param a The annotation type to find.
-        * @param f The field to search on.
-        * @return The annotations in an unmodifiable list, or an empty list if 
not found.
-        */
        @SuppressWarnings("unchecked")
-       @Override /* MetaProvider */
-       public <A extends Annotation> List<A> getAnnotations(Class<A> a, Field 
f) {
-               if (a == null || f == null)
-                       return emptyList();
-               List<Annotation> aa = fieldAnnotationCache.get(f, a);
+       private <A extends Annotation> A[] annotations(Class<A> a, Field f) {
+               A[] aa = (A[])fieldAnnotationCache.get(f, a);
                if (aa == null) {
                        A[] x = f.getAnnotationsByType(a);
                        AList<Annotation> l = new AList<>(Arrays.asList(x));
                        annotationMap.appendAll(f, a, l);
-                       aa = l.unmodifiable();
+                       aa = (A[]) Array.newInstance(a, l.size());
+                       for (int i = 0; i < l.size(); i++)
+                               Array.set(aa, i, l.get(i));
                        fieldAnnotationCache.put(f, a, aa);
                }
-               return (List<A>)aa;
+               return aa;
        }
 
-       /**
-        * Finds the specified annotations on the specified field.
-        *
-        * @param <A> The annotation type to find.
-        * @param a The annotation type to find.
-        * @param f The field to search on.
-        * @return The annotations in an unmodifiable list, or an empty list if 
not found.
-        */
-       public <A extends Annotation> List<A> getAnnotations(Class<A> a, 
FieldInfo f) {
-               return getAnnotations(a, f == null ? null: f.inner());
+       @Override /* MetaProvider */
+       public <A extends Annotation> void getAnnotations(Class<A> a, 
Constructor<?> c, Consumer<A> consumer) {
+               if (a != null && c != null)
+                       for (A aa : annotations(a, c))
+                               consumer.accept(aa);
        }
 
-       /**
-        * Finds the specified annotations on the specified constructor.
-        *
-        * @param <A> The annotation type to find.
-        * @param a The annotation type to find.
-        * @param c The constructor to search on.
-        * @return The annotations in an unmodifiable list, or an empty list if 
not found.
-        */
-       @SuppressWarnings("unchecked")
        @Override /* MetaProvider */
-       public <A extends Annotation> List<A> getAnnotations(Class<A> a, 
Constructor<?> c) {
-               if (a == null || c == null)
-                       return emptyList();
-               List<Annotation> aa = constructorAnnotationCache.get(c, a);
+       public <A extends Annotation> A getAnnotation(Class<A> a, 
Constructor<?> c, Predicate<A> predicate) {
+               if (a != null && c != null)
+                       for (A aa : annotations(a, c))
+                               if (predicate.test(aa))
+                                       return aa;
+               return null;
+       }
+
+       @SuppressWarnings("unchecked")
+       private <A extends Annotation> A[] annotations(Class<A> a, 
Constructor<?> c) {
+               A[] aa = (A[])constructorAnnotationCache.get(c, a);
                if (aa == null) {
                        A[] x = c.getAnnotationsByType(a);
                        AList<Annotation> l = new AList<>(Arrays.asList(x));
                        annotationMap.appendAll(c, a, l);
-                       aa = l.unmodifiable();
-                       constructorAnnotationCache.put(c, a, l);
+                       aa = (A[]) Array.newInstance(a, l.size());
+                       for (int i = 0; i < l.size(); i++)
+                               Array.set(aa, i, l.get(i));
+                       constructorAnnotationCache.put(c, a, aa);
                }
-               return (List<A>)aa;
+               return aa;
+       }
+
+       /**
+        * Finds the last specified annotations on the specified method.
+        *
+        * @param <A> The annotation type to find.
+        * @param a The annotation type to find.
+        * @param m The method to search on.
+        * @return The annotation, or <jk>null</jk> if not found.
+        */
+       public <A extends Annotation> A getLastAnnotation(Class<A> a, Method m) 
{
+               return last(annotations(a, m));
        }
 
        /**
-        * Finds the specified annotations on the specified constructor.
+        * Finds the last specified annotations on the specified field.
         *
         * @param <A> The annotation type to find.
         * @param a The annotation type to find.
-        * @param c The constructor to search on.
-        * @return The annotations in an unmodifiable list, or an empty list if 
not found.
+        * @param f The field to search on.
+        * @return The annotation, or <jk>null</jk> if not found.
         */
-       public <A extends Annotation> List<A> getAnnotations(Class<A> a, 
ConstructorInfo c) {
-               return getAnnotations(a, c == null ? null : c.inner());
+       public <A extends Annotation> A getLastAnnotation(Class<A> a, Field f) {
+               return last(annotations(a, f));
        }
 
        /**
@@ -1158,7 +1143,7 @@ public abstract class Context implements MetaProvider {
         * @return <jk>true</jk> if the annotation exists on the specified 
method.
         */
        public <A extends Annotation> boolean hasAnnotation(Class<A> a, Method 
m) {
-               return getAnnotations(a, m).size() > 0;
+               return annotations(a, m).length > 0;
        }
 
        /**
@@ -1169,7 +1154,7 @@ public abstract class Context implements MetaProvider {
         * @return <jk>true</jk> if the annotation exists on the specified 
method.
         */
        public <A extends Annotation> boolean hasAnnotation(Class<A> a, 
MethodInfo m) {
-               return getAnnotations(a, m == null ? null : m.inner()).size() > 
0;
+               return annotations(a, m == null ? null : m.inner()).length > 0;
        }
 
        /**
@@ -1180,7 +1165,7 @@ public abstract class Context implements MetaProvider {
         * @return <jk>true</jk> if the annotation exists on the specified 
field.
         */
        public <A extends Annotation> boolean hasAnnotation(Class<A> a, 
FieldInfo f) {
-               return getAnnotations(a, f == null ? null : f.inner()).size() > 
0;
+               return annotations(a, f == null ? null : f.inner()).length > 0;
        }
 
        /**
@@ -1191,7 +1176,7 @@ public abstract class Context implements MetaProvider {
         * @return <jk>true</jk> if the annotation exists on the specified 
constructor.
         */
        public <A extends Annotation> boolean hasAnnotation(Class<A> a, 
ConstructorInfo c) {
-               return getAnnotations(a, c == null ? null : c.inner()).size() > 
0;
+               return annotations(a, c == null ? null : c.inner()).length > 0;
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MetaProvider.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MetaProvider.java
index 0b413d0..4b236ce 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MetaProvider.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/MetaProvider.java
@@ -14,11 +14,8 @@ package org.apache.juneau;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
-import java.util.*;
 import java.util.function.*;
 
-import static java.util.Collections.*;
-
 /**
  * Parent interface for all class/method language-specific metadata providers.
  *
@@ -66,27 +63,51 @@ public interface MetaProvider {
                }
 
                @Override /* MetaProvider */
-               public <A extends Annotation> List<A> getAnnotations(Class<A> 
a, Method m) {
-                       if (a == null || m == null)
-                               return emptyList();
-                       A[] aa = m.getAnnotationsByType(a);
-                       return Arrays.asList(aa);
+               public <A extends Annotation> void getAnnotations(Class<A> a, 
Method m, Consumer<A> consumer) {
+                       if (a != null && m != null)
+                               for (A aa : m.getAnnotationsByType(a))
+                                       consumer.accept(aa);
+               }
+
+               @Override /* MetaProvider */
+               public <A extends Annotation> A getAnnotation(Class<A> a, 
Method m, Predicate<A> predicate) {
+                       if (a != null && m != null)
+                               for (A aa : m.getAnnotationsByType(a))
+                                       if (predicate.test(aa))
+                                               return aa;
+                       return null;
                }
 
                @Override /* MetaProvider */
-               public <A extends Annotation> List<A> getAnnotations(Class<A> 
a, Field f) {
-                       if (a == null || f == null)
-                               return emptyList();
-                       A[] aa = f.getAnnotationsByType(a);
-                       return Arrays.asList(aa);
+               public <A extends Annotation> void getAnnotations(Class<A> a, 
Field f, Consumer<A> consumer) {
+                       if (a != null && f != null)
+                               for (A aa : f.getAnnotationsByType(a))
+                                       consumer.accept(aa);
                }
 
                @Override /* MetaProvider */
-               public <A extends Annotation> List<A> getAnnotations(Class<A> 
a, Constructor<?> c) {
-                       if (a == null || c == null)
-                               return emptyList();
-                       A[] aa = c.getAnnotationsByType(a);
-                       return Arrays.asList(aa);
+               public <A extends Annotation> A getAnnotation(Class<A> a, Field 
f, Predicate<A> predicate) {
+                       if (a != null && f != null)
+                               for (A aa : f.getAnnotationsByType(a))
+                                       if (predicate.test(aa))
+                                               return aa;
+                       return null;
+               }
+
+               @Override /* MetaProvider */
+               public <A extends Annotation> void getAnnotations(Class<A> a, 
Constructor<?> c, Consumer<A> consumer) {
+                       if (a != null && c != null)
+                               for (A aa : c.getAnnotationsByType(a))
+                                       consumer.accept(aa);
+               }
+
+               @Override /* MetaProvider */
+               public <A extends Annotation> A getAnnotation(Class<A> a, 
Constructor<?> c, Predicate<A> predicate) {
+                       if (a != null && c != null)
+                               for (A aa : c.getAnnotationsByType(a))
+                                       if (predicate.test(aa))
+                                               return aa;
+                       return null;
                }
        };
 
@@ -134,9 +155,20 @@ public interface MetaProvider {
         * @param <A> The annotation type to find.
         * @param a The annotation type to find.
         * @param m The method to search on.
-        * @return The annotations in an unmodifiable list, or an empty list if 
not found.
+        * @param consumer The consumer of the annotations.
+        */
+       <A extends Annotation> void getAnnotations(Class<A> a, Method m, 
Consumer<A> consumer);
+
+       /**
+        * Finds the specified annotations on the specified method.
+        *
+        * @param <A> The annotation type to find.
+        * @param a The annotation type to find.
+        * @param m The method to search on.
+        * @param predicate The predicate to match the annotation against.
+        * @return The matched annotation, or <jk>null</jk> if no annotations 
matched.
         */
-       <A extends Annotation> List<A> getAnnotations(Class<A> a, Method m);
+       <A extends Annotation> A getAnnotation(Class<A> a, Method m, 
Predicate<A> predicate);
 
        /**
         * Finds the specified annotations on the specified field.
@@ -144,9 +176,20 @@ public interface MetaProvider {
         * @param <A> The annotation type to find.
         * @param a The annotation type to find.
         * @param f The field to search on.
-        * @return The annotations in an unmodifiable list, or an empty list if 
not found.
+        * @param consumer The consumer of the annotations.
         */
-       <A extends Annotation> List<A> getAnnotations(Class<A> a, Field f);
+       <A extends Annotation> void getAnnotations(Class<A> a, Field f, 
Consumer<A> consumer);
+
+       /**
+        * Finds the specified annotations on the specified field.
+        *
+        * @param <A> The annotation type to find.
+        * @param a The annotation type to find.
+        * @param f The field to search on.
+        * @param predicate The predicate to match the annotation against.
+        * @return The matched annotation, or <jk>null</jk> if no annotations 
matched.
+        */
+       <A extends Annotation> A getAnnotation(Class<A> a, Field f, 
Predicate<A> predicate);
 
        /**
         * Finds the specified annotations on the specified constructor.
@@ -154,7 +197,18 @@ public interface MetaProvider {
         * @param <A> The annotation type to find.
         * @param a The annotation type to find.
         * @param c The constructor to search on.
-        * @return The annotations in an unmodifiable list, or an empty list if 
not found.
+        * @param consumer The consumer of the annotations.
+        */
+       <A extends Annotation> void getAnnotations(Class<A> a, Constructor<?> 
c, Consumer<A> consumer);
+
+       /**
+        * Finds the specified annotations on the specified constructor.
+        *
+        * @param <A> The annotation type to find.
+        * @param a The annotation type to find.
+        * @param c The constructor to search on.
+        * @param predicate The predicate to match the annotation against.
+        * @return The matched annotation, or <jk>null</jk> if no annotations 
matched.
         */
-       <A extends Annotation> List<A> getAnnotations(Class<A> a, 
Constructor<?> c);
+       <A extends Annotation> A getAnnotation(Class<A> a, Constructor<?> c, 
Predicate<A> predicate);
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
index e427427..5c067dd 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
@@ -50,14 +50,11 @@ public final class HtmlBeanPropertyMeta extends 
ExtendedBeanPropertyMeta {
 
                Builder b = new Builder();
                if (bpm.getInnerField() != null)
-                       for (Html html : mp.getAnnotations(Html.class, 
bpm.getInnerField()))
-                               b.findHtmlInfo(html);
+                       mp.getAnnotations(Html.class, bpm.getInnerField(), x -> 
b.findHtmlInfo(x));
                if (bpm.getGetter() != null)
-                       for (Html html : mp.getAnnotations(Html.class, 
bpm.getGetter()))
-                               b.findHtmlInfo(html);
+                       mp.getAnnotations(Html.class, bpm.getGetter(), x -> 
b.findHtmlInfo(x));
                if (bpm.getSetter() != null)
-                       for (Html html : mp.getAnnotations(Html.class, 
bpm.getSetter()))
-                               b.findHtmlInfo(html);
+                       mp.getAnnotations(Html.class, bpm.getSetter(), x -> 
b.findHtmlInfo(x));
 
                this.format = b.format;
                this.noTables = b.noTables;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/CollectionUtils.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/CollectionUtils.java
index 7c699bd..da763db 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/CollectionUtils.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/CollectionUtils.java
@@ -159,4 +159,17 @@ public final class CollectionUtils {
                        return null;
                return l.get(l.size()-1);
        }
+
+       /**
+        * Returns the last entry in an array.
+        *
+        * @param <T> The element type.
+        * @param l The array.
+        * @return The last element, or <jk>null</jk> if the array is 
<jk>null</jk> or empty.
+        */
+       public static <T> T last(T[] l) {
+               if (l == null || l.length == 0)
+                       return null;
+               return l[l.length-1];
+       }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ConstructorInfo.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ConstructorInfo.java
index 6cfece0..00f65f5 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ConstructorInfo.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ConstructorInfo.java
@@ -12,8 +12,6 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.reflect;
 
-import static org.apache.juneau.internal.CollectionUtils.*;
-
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.function.*;
@@ -111,7 +109,9 @@ public final class ConstructorInfo extends ExecutableInfo 
implements Comparable<
         *      The first annotation found, or <jk>null</jk> if it doesn't 
exist.
         */
        public final <T extends Annotation> T getAnnotation(Class<T> a, 
MetaProvider mp) {
-               return last(mp.getAnnotations(a, c));
+               Value<T> t = Value.empty();
+               mp.getAnnotations(a, c, x -> t.set(x));
+               return t.orElse(null);
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java
index 282fc41..2e8a451 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java
@@ -12,7 +12,6 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.reflect;
 
-import static org.apache.juneau.internal.CollectionUtils.*;
 import static org.apache.juneau.internal.ThrowableUtils.*;
 
 import java.lang.annotation.*;
@@ -114,7 +113,9 @@ public final class FieldInfo implements 
Comparable<FieldInfo> {
         * @return The annotation, or <jk>null</jk> if not found.
         */
        public <T extends Annotation> T getAnnotation(Class<T> a, MetaProvider 
mp) {
-               return last(mp.getAnnotations(a, f));
+               Value<T> t = Value.empty();
+               mp.getAnnotations(a, f, x -> t.set(x));
+               return t.orElse(null);
        }
 
        /**
@@ -145,7 +146,7 @@ public final class FieldInfo implements 
Comparable<FieldInfo> {
         * @return <jk>true</jk> if the specified annotation is present.
         */
        public boolean hasAnnotation(Class<? extends Annotation> a, 
MetaProvider mp) {
-               return ! mp.getAnnotations(a, f).isEmpty();
+               return mp.getAnnotation(a, f, x -> true) != null;
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java
index 83123b4..30035b4 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/MethodInfo.java
@@ -12,8 +12,6 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.reflect;
 
-import static org.apache.juneau.internal.CollectionUtils.*;
-
 import java.beans.*;
 import java.lang.annotation.*;
 import java.lang.reflect.*;
@@ -237,10 +235,11 @@ public final class MethodInfo extends ExecutableInfo 
implements Comparable<Metho
        public final <T extends Annotation> T getLastAnnotation(Class<T> a, 
MetaProvider mp) {
                if (a == null)
                        return null;
+               Value<T> t = Value.empty();
                for (Method m2 : _getMatching()) {
-                       T t = last(mp.getAnnotations(a, m2));
-                       if (t != null)
-                               return t;
+                       mp.getAnnotations(a, m2, x -> t.set(x));
+                       if (t.isPresent())
+                               return t.get();
                }
                return null;
        }

Reply via email to