001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.commons.reflect;
018
019import static java.util.Collections.*;
020import static org.apache.juneau.commons.reflect.AnnotationTraversal.*;
021import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
022import static org.apache.juneau.commons.utils.Shorts.*;
023import static org.apache.juneau.commons.utils.SystemUtils.*;
024
025import java.lang.annotation.*;
026import java.lang.reflect.*;
027import java.util.*;
028
029import org.apache.juneau.commons.collections.*;
030import org.apache.juneau.commons.lang.*;
031import org.apache.juneau.commons.utils.*;
032
033/**
034 * Enhanced annotation provider that returns {@link AnnotationInfo} objects and supports runtime annotations.
035 *
036 * <p>
037 * This class provides a modern API for retrieving annotations with the following benefits:
038 * <ul>
039 *    <li>Returns {@link AnnotationInfo} wrappers that provide additional methods and type safety
040 *    <li>Supports filtering by annotation type using streams
041 *    <li>Properly handles repeatable annotations
042 *    <li>Searches up the class/method hierarchy with well-defined order of precedence
043 *    <li>Supports runtime annotations (annotations added programmatically at runtime)
044 *    <li>Caches results for performance
045 * </ul>
046 *
047 * <h5 class='section'>Annotation Order of Precedence:</h5>
048 *
049 * <h6 class='topic'>For Classes ({@link #find(Class, ClassInfo, AnnotationTraversal...)}):</h6>
050 * <p>
051 * Annotations are returned in <b>child-to-parent</b> order with the following precedence:
052 * <ol>
053 *    <li><b>Runtime annotations</b> on the class (highest priority)
054 *    <li><b>Declared annotations</b> on the class
055 *    <li><b>Runtime annotations</b> on parent classes (child-to-parent order)
056 *    <li><b>Declared annotations</b> on parent classes (child-to-parent order)
057 *    <li><b>Runtime annotations</b> on interfaces (child-to-parent order)
058 *    <li><b>Declared annotations</b> on interfaces (child-to-parent order)
059 *    <li><b>Declared annotations</b> on the package (lowest priority)
060 * </ol>
061 *
062 * <p class='bcode'>
063 *    <jc>// Example: Given class Child extends Parent</jc>
064 *    <jc>// Annotation order will be:</jc>
065 *    <jc>// 1. Runtime annotations on Child</jc>
066 *    <jc>// 2. @Annotation on Child</jc>
067 *    <jc>// 3. Runtime annotations on Parent</jc>
068 *    <jc>// 4. @Annotation on Parent</jc>
069 *    <jc>// 5. Runtime annotations on IChild (if Child implements IChild)</jc>
070 *    <jc>// 6. @Annotation on IChild</jc>
071 *    <jc>// 7. @Annotation on package-info.java</jc>
072 * </p>
073 *
074 * <h6 class='topic'>For Methods ({@link #find(Class, MethodInfo, AnnotationTraversal...)}):</h6>
075 * <p>
076 * Annotations are returned in <b>child-to-parent</b> order with the following precedence:
077 * <ol>
078 *    <li><b>Runtime annotations</b> on the method (highest priority)
079 *    <li><b>Declared annotations</b> on the method
080 *    <li><b>Runtime annotations</b> on overridden parent methods (child-to-parent order)
081 *    <li><b>Declared annotations</b> on overridden parent methods (child-to-parent order)
082 * </ol>
083 *
084 * <h6 class='topic'>For Fields ({@link #find(Class, FieldInfo, AnnotationTraversal...)}):</h6>
085 * <p>
086 * Annotations are returned with the following precedence:
087 * <ol>
088 *    <li><b>Runtime annotations</b> on the field (highest priority)
089 *    <li><b>Declared annotations</b> on the field
090 * </ol>
091 *
092 * <h6 class='topic'>For Constructors ({@link #find(Class, ConstructorInfo, AnnotationTraversal...)}):</h6>
093 * <p>
094 * Annotations are returned with the following precedence:
095 * <ol>
096 *    <li><b>Runtime annotations</b> on the constructor (highest priority)
097 *    <li><b>Declared annotations</b> on the constructor
098 * </ol>
099 *
100 * <h5 class='section'>Runtime Annotations:</h5>
101 * <p>
102 * Runtime annotations are concrete objects that implement annotation interfaces, added programmatically via the
103 * builder's {@link Builder#addRuntimeAnnotations(List)} method. They allow you to dynamically apply annotations
104 * to classes, methods, fields, and constructors at runtime without modifying source code.
105 *
106 * <p>
107 * <b>How Runtime Annotations Work:</b>
108 * <ul>
109 *    <li>Runtime annotations are Java objects that implement annotation interfaces (e.g., {@code @Marshalled})
110 *    <li>They use special methods like {@code on()} or {@code onClass()} to specify their targets
111 *    <li>They always take precedence over declared annotations at the same level
112 *    <li>They are particularly useful for applying annotations to classes you don't control
113 * </ul>
114 *
115 * <p class='bjava'>
116 *    <jc>// Example: Creating a runtime annotation</jc>
117 *    Bean <jv>runtimeAnnotation</jv> = MarshalledAnnotation
118 *       .<jsm>create</jsm>()
119 *       .onClass(MyClass.<jk>class</jk>)  <jc>// Target class</jc>
120 *       .typeName(<js>"MyType"</js>)         <jc>// Annotation property</jc>
121 *       .build();
122 *
123 *    <jc>// Add to provider</jc>
124 *    AnnotationProvider <jv>provider</jv> = AnnotationProvider
125 *       .<jsm>create</jsm>()
126 *       .addRuntimeAnnotations(<jv>runtimeAnnotation</jv>)
127 *       .build();
128 *
129 *    <jc>// Now MyClass will be found with @Marshalled annotation</jc>
130 *    Stream&lt;AnnotationInfo&lt;Bean&gt;&gt; <jv>annotations</jv> = <jv>provider</jv>.find(Bean.<jk>class</jk>, MyClass.<jk>class</jk>);
131 * </p>
132 *
133 * <p>
134 * <b>Targeting Methods:</b>
135 * <ul>
136 *    <li>{@code on()} - String array of fully-qualified names (e.g., {@code "com.example.MyClass.myMethod"})
137 *    <li>{@code onClass()} - Class array for type-safe targeting
138 * </ul>
139 *
140 * <p>
141 * Runtime annotations are evaluated before declared annotations at each level, giving them higher priority.
142 * For example, a runtime {@code @Marshalled} annotation on a class will be found before any {@code @Marshalled} annotation
143 * declared directly on that class.
144 *
145 * <h5 class='section'>Comparison with ElementInfo Methods:</h5>
146 * <p>
147 * The methods in this class differ from {@link ClassInfo#getAnnotations()}, {@link MethodInfo#getAnnotations()}, etc.:
148 * <ul>
149 *    <li><b>Runtime Annotations</b>: ElementInfo methods return ONLY declared annotations. This class includes runtime annotations.
150 *    <li><b>Hierarchy</b>: ElementInfo methods may have different traversal logic. This class uses a consistent approach.
151 *    <li><b>Precedence</b>: Runtime annotations are inserted at each level with higher priority than declared annotations.
152 * </ul>
153 *
154 * <h5 class='section'>Usage:</h5>
155 * <p class='bjava'>
156 *    <jc>// Create with default settings</jc>
157 *    AnnotationProvider <jv>provider</jv> = AnnotationProvider.<jsm>create</jsm>().build();
158 *
159 *    <jc>// Create with runtime annotations</jc>
160 *    AnnotationProvider <jv>provider</jv> = AnnotationProvider
161 *       .<jsm>create</jsm>()
162 *       .annotations(<jk>new</jk> MyAnnotationImpl())
163 *       .build();
164 *
165 *    <jc>// Find all annotations on a class</jc>
166 *    List&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>annotations</jv> = <jv>provider</jv>.find(MyClass.<jk>class</jk>);
167 *
168 *    <jc>// Find specific annotation type on a class</jc>
169 *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>myAnnotations</jv> = <jv>provider</jv>.find(MyAnnotation.<jk>class</jk>, MyClass.<jk>class</jk>);
170 * </p>
171 *
172 * <h5 class='section'>See Also:</h5>
173 * <ul>
174 *    <li class='jc'>{@link AnnotationProvider}
175 *    <li class='jc'>{@link AnnotationInfo}
176 *    <li class='jc'>{@link ClassInfo}
177 *    <li class='jc'>{@link MethodInfo}
178 * </ul>
179 */
180@SuppressWarnings({
181   "java:S1192", // Duplicated literals (argument/property names) read more clearly inline than as constants
182   "java:S1452", // Wildcard required - List<AnnotationInfo<? extends Annotation>> for heterogeneous annotations
183   "java:S3776", // load() and the find()/has() lookups combine traversal order, type filtering and caching in a single pass
184   "rawtypes", // Raw types necessary for generic type handling
185   "unchecked" // Type erasure requires unchecked casts
186})
187public class AnnotationProvider {
188
189   //-----------------------------------------------------------------------------------------------------------------
190   // System properties
191   //-----------------------------------------------------------------------------------------------------------------
192
193   /**
194    * Builder for creating configured {@link AnnotationProvider} instances.
195    *
196    * <h5 class='section'>Example:</h5>
197    * <p class='bjava'>
198    *    AnnotationProvider <jv>provider</jv> = AnnotationProvider
199    *       .<jsm>create</jsm>()
200    *       .disableCaching()
201    *       .build();
202    * </p>
203    *
204    * <h5 class='section'>See Also:</h5>
205    * <ul>
206    *    <li class='jm'>{@link AnnotationProvider#create()}
207    * </ul>
208    */
209   public static class Builder {
210      CacheMode cacheMode;
211      boolean logOnExit;
212      ReflectionMap.Builder<Annotation> runtimeAnnotations;
213
214      Builder() {
215         cacheMode = CACHING_MODE;
216         logOnExit = LOG_ON_EXIT;
217      }
218
219      /**
220       * Adds runtime annotations to be applied to classes, methods, fields, and constructors.
221       *
222       * <p>
223       * This is a convenience method that delegates to {@link #addRuntimeAnnotations(List)}.
224       * See that method for detailed documentation on how runtime annotations work.
225       *
226       * <p class='bjava'>
227       *    <jc>// Example: Add multiple runtime annotations using varargs</jc>
228       *    Bean <jv>beanAnnotation</jv> = MarshalledAnnotation
229       *       .<jsm>create</jsm>()
230       *       .onClass(MyClass.<jk>class</jk>)
231       *       .typeName(<js>"MyType"</js>)
232       *       .build();
233       *
234       *    Swap <jv>swapAnnotation</jv> = SwapAnnotation
235       *       .<jsm>create</jsm>()
236       *       .on(<js>"com.example.MyClass.getValue"</js>)
237       *       .value(MySwap.<jk>class</jk>)
238       *       .build();
239       *
240       *    AnnotationProvider <jv>provider</jv> = AnnotationProvider
241       *       .<jsm>create</jsm>()
242       *       .addRuntimeAnnotations(<jv>beanAnnotation</jv>, <jv>swapAnnotation</jv>)  <jc>// Varargs</jc>
243       *       .build();
244       * </p>
245       *
246       * @param annotations The runtime annotation objects to add (varargs).
247       * @return This object for method chaining.
248       * @throws BeanRuntimeException If any annotation is invalid.
249       * @see #addRuntimeAnnotations(List)
250       */
251      public Builder addRuntimeAnnotations(Annotation...annotations) {
252         return addRuntimeAnnotations(l(annotations));
253      }
254
255      /**
256       * Adds runtime annotations to be applied to classes, methods, fields, and constructors.
257       *
258       * <p>
259       * Runtime annotations are concrete Java objects that implement annotation interfaces (e.g., {@code @Marshalled}).
260       * They allow you to dynamically apply annotations to code elements at runtime without modifying source code.
261       *
262       * <p>
263       * <b>How It Works:</b>
264       * <ol>
265       *    <li>Create annotation objects using builder classes (e.g., {@code MarshalledAnnotation.create()})
266       *    <li>Specify targets using {@code on()} or {@code onClass()} methods
267       *    <li>Set annotation properties (e.g., {@code typeName()}, {@code properties()})
268       *    <li>Build the annotation object
269       *    <li>Add to the provider via this method
270       * </ol>
271       *
272       * <p>
273       * <b>Targeting Requirements:</b>
274       * <ul>
275       *    <li>Annotations MUST define an {@code onClass()} method returning {@code Class[]} for type-safe targeting
276       *    <li>OR an {@code on()} method returning {@code String[]} for string-based targeting
277       *    <li>The {@code on()} method accepts fully-qualified names:
278       *       <ul>
279       *          <li>{@code "com.example.MyClass"} - targets a class
280       *          <li>{@code "com.example.MyClass.myMethod"} - targets a method
281       *          <li>{@code "com.example.MyClass.myField"} - targets a field
282       *       </ul>
283       * </ul>
284       *
285       * <p class='bjava'>
286       *    <jc>// Example 1: Target a specific class using type-safe targeting</jc>
287       *    Bean <jv>beanAnnotation</jv> = MarshalledAnnotation
288       *       .<jsm>create</jsm>()
289       *       .onClass(MyClass.<jk>class</jk>)  <jc>// Targets MyClass</jc>
290       *       .typeName(<js>"MyType"</js>)
291       *       .properties(<js>"id,name"</js>)
292       *       .build();
293       *
294       *    <jc>// Example 2: Target multiple classes</jc>
295       *    Bean <jv>multiAnnotation</jv> = MarshalledAnnotation
296       *       .<jsm>create</jsm>()
297       *       .onClass(MyClass.<jk>class</jk>, OtherClass.<jk>class</jk>)
298       *       .sort(<jk>true</jk>)
299       *       .build();
300       *
301       *    <jc>// Example 3: Target using string names (useful for dynamic/reflection scenarios)</jc>
302       *    Bean <jv>stringAnnotation</jv> = MarshalledAnnotation
303       *       .<jsm>create</jsm>()
304       *       .on(<js>"com.example.MyClass"</js>)
305       *       .findFluentSetters(<jk>true</jk>)
306       *       .build();
307       *
308       *    <jc>// Example 4: Target a specific method</jc>
309       *    Swap <jv>swapAnnotation</jv> = SwapAnnotation
310       *       .<jsm>create</jsm>()
311       *       .on(<js>"com.example.MyClass.getValue"</js>)
312       *       .value(MySwap.<jk>class</jk>)
313       *       .build();
314       *
315       *    <jc>// Add all runtime annotations to the provider</jc>
316       *    AnnotationProvider <jv>provider</jv> = AnnotationProvider
317       *       .<jsm>create</jsm>()
318       *       .addRuntimeAnnotations(<jv>beanAnnotation</jv>, <jv>multiAnnotation</jv>, <jv>stringAnnotation</jv>, <jv>swapAnnotation</jv>)
319       *       .build();
320       * </p>
321       *
322       * <p>
323       * <b>Priority:</b> Runtime annotations always take precedence over declared annotations at the same level.
324       * They are evaluated first when searching for annotations.
325       *
326       * @param annotations The list of runtime annotation objects to add.
327       * @return This object for method chaining.
328       * @throws BeanRuntimeException If any annotation is invalid (missing {@code on()} or {@code onClass()} methods,
329       *    or if the methods return incorrect types).
330       */
331      public Builder addRuntimeAnnotations(List<Annotation> annotations) {
332         if (runtimeAnnotations == null)
333            runtimeAnnotations = ReflectionMap.create(Annotation.class);
334
335         for (var a : annotations) {
336            try {
337               var ci = ClassInfo.of(a.getClass());
338
339               // XApply pattern: if annotation has a value() returning a single Annotation,
340               // unwrap and store the inner annotation instead of the wrapper.
341               var annotationToStore = unwrapXApply(ci, a);
342
343               ci.getPublicMethod(x -> x.hasName("onClass")).ifPresent(mi -> {
344                  if (! mi.getReturnType().is(Class[].class))
345                     throw brex("Invalid annotation @%s used in runtime annotations.  Annotation must define an onClass() method that returns a Class array.", cns(a));
346                  for (var c : (Class<?>[])mi.accessible().invoke(a))
347                     runtimeAnnotations.append(c.getName(), annotationToStore);
348               });
349
350               ci.getPublicMethod(x -> x.hasName("on")).ifPresent(mi -> {
351                  if (! mi.getReturnType().is(String[].class))
352                     throw brex("Invalid annotation @%s used in runtime annotations.  Annotation must define an on() method that returns a String array.", cns(a));
353                  for (var s : (String[])mi.accessible().invoke(a))
354                     runtimeAnnotations.append(s, annotationToStore);
355               });
356
357            } catch (BeanRuntimeException e) {
358               throw e;
359            } catch (Exception e) {
360               throw brex(e, (Class<?>)null, "Invalid annotation @%s used in runtime annotations.", cn(a));
361            }
362         }
363         return this;
364      }
365
366      private static Annotation unwrapXApply(ClassInfo ci, Annotation a) {
367         var valueMethod = ci.getPublicMethod(x -> x.hasName("value"));
368         if (valueMethod.isEmpty())
369            return a;
370         var mi = valueMethod.get();
371         var rt = mi.getReturnType().inner();
372         if (! Annotation.class.isAssignableFrom(rt) || rt.isArray())
373            return a;
374         var inner = (Annotation) mi.accessible().invoke(a);
375         return or(inner, a);
376      }
377
378      /**
379       * Builds a new {@link AnnotationProvider} instance with the configured settings.
380       *
381       * @return A new immutable {@link AnnotationProvider} instance.
382       */
383      public AnnotationProvider build() {
384         if (ie(runtimeAnnotations))
385            return INSTANCE;
386         return new AnnotationProvider(this);
387      }
388
389      /**
390       * Sets the caching mode for annotation lookups.
391       *
392       * <p>
393       * Available modes:
394       * <ul>
395       *    <li><c>NONE</c> - Disables all caching (always recompute)
396       *    <li><c>WEAK</c> - Uses WeakHashMap (allows GC of cached entries)
397       *    <li><c>FULL</c> - Uses ConcurrentHashMap (best performance)
398       * </ul>
399       *
400       * @param value The caching mode.
401       * @return This object for method chaining.
402       */
403      public Builder cacheMode(CacheMode value) {
404         cacheMode = value;
405         return this;
406      }
407
408      /**
409       * Enables logging of cache statistics on JVM shutdown.
410       *
411       * @return This object for method chaining.
412       */
413      public Builder logOnExit() {
414         logOnExit = true;
415         return this;
416      }
417
418      /**
419       * Conditionally enables logging of cache statistics on JVM shutdown.
420       *
421       * @param value Whether to log on exit.
422       * @return This object for method chaining.
423       */
424      public Builder logOnExit(boolean value) {
425         logOnExit = value;
426         return this;
427      }
428   }
429
430   /**
431    * Caching mode for annotation lookups.
432    *
433    * <p>
434    * System property: <c>juneau.annotationProvider.caching</c>
435    * <br>Valid values: <c>NONE</c>, <c>WEAK</c>, <c>FULL</c> (case-insensitive)
436    * <br>Default: <c>FULL</c>
437    *
438    * <ul>
439    *    <li><c>NONE</c> - Disables all caching (always recompute)
440    *    <li><c>WEAK</c> - Uses WeakHashMap (allows GC of cached entries)
441    *    <li><c>FULL</c> - Uses ConcurrentHashMap (best performance)
442    * </ul>
443    */
444   private static final CacheMode CACHING_MODE = env("juneau.annotationProvider.caching", CacheMode.FULL);
445
446   /**
447    * Enable logging of cache statistics on JVM shutdown.
448    *
449    * <p>
450    * System property: <c>juneau.annotationProvider.caching.logOnExit</c>
451    * <br>Valid values: <c>TRUE</c>, <c>FALSE</c> (case-insensitive)
452    * <br>Default: <c>FALSE</c>
453    */
454   private static final boolean LOG_ON_EXIT = env("juneau.annotationProvider.caching.logOnExit", false);
455
456   //-----------------------------------------------------------------------------------------------------------------
457   // Builder
458   //-----------------------------------------------------------------------------------------------------------------
459
460   /**
461    * Default instance.
462    */
463   public static final AnnotationProvider INSTANCE = new AnnotationProvider(create().logOnExit());
464
465   /**
466    * Creates a new {@link Builder} for constructing an annotation provider.
467    *
468    * @return A new builder for configuring the annotation provider.
469    */
470   public static Builder create() {
471      return new Builder();
472   }
473
474   private static <A extends Annotation> AnnotationInfo<A> ai(Annotatable on, A value) {
475      return AnnotationInfo.of(on, value);
476   }
477
478   private final Cache<Object,List<AnnotationInfo<Annotation>>> runtimeCache;
479   private final Cache3<Class<?>,ElementInfo,AnnotationTraversal[],List> cache;
480
481   private final ReflectionMap<Annotation> annotationMap;
482
483   //-----------------------------------------------------------------------------------------------------------------
484   // Stream-based traversal methods
485   //-----------------------------------------------------------------------------------------------------------------
486
487   /**
488    * Constructor.
489    *
490    * @param builder The builder containing configuration settings.
491    */
492   protected AnnotationProvider(Builder builder) {
493      // @formatter:off
494      this.runtimeCache = Cache.<Object,List<AnnotationInfo<Annotation>>>create()
495         .supplier(this::load)
496         .cacheMode(builder.cacheMode)
497         .logOnExit(builder.logOnExit, "AnnotationProvider.runtimeAnnotations")
498         .build();
499
500      this.cache = Cache3.<Class<?>,ElementInfo,AnnotationTraversal[],List>create()
501         .supplier(this::load)
502         .cacheMode(builder.cacheMode)
503         .logOnExit(builder.logOnExit, "AnnotationProvider.cache")
504         .build();
505
506      this.annotationMap = o(builder.runtimeAnnotations).map(ReflectionMap.Builder::build).orElse(null);
507      // @formatter:on
508   }
509
510   /**
511    * Finds annotations from a class using configurable traversal options.
512    *
513    * <p>
514    * This method provides a flexible API for traversing annotations.
515    * It uses {@link AnnotationTraversal} enums to configure what elements to search and in what order.
516    *
517    * <h5 class='section'>Examples:</h5>
518    * <p class='bjava'>
519    *    <jc>// Search class only</jc>
520    *    List&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>l1</jv> =
521    *       find(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF);
522    *
523    *    <jc>// Search class and parents</jc>
524    *    List&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>l2</jv> =
525    *       find(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF, PARENTS);
526    *
527    *    <jc>// Search class, parents, and package (parent-first order using rstream)</jc>
528    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s3</jv> =
529    *       rstream(find(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF, PARENTS, PACKAGE));
530    * </p>
531    *
532    * @param <A> The annotation type.
533    * @param type The annotation type to search for.  Must not be <jk>null</jk>.
534    * @param c The class to search.  Must not be <jk>null</jk>.
535    * @param traversals The traversal options (what to search and order).
536    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
537    */
538   public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, ClassInfo c, AnnotationTraversal...traversals) {
539      reqnn("type", type);
540      reqnn("c", c);
541      return cache.get(type, c, traversals);
542   }
543
544   /**
545    * Finds annotations from a constructor using configurable traversal options.
546    *
547    * <p>
548    * This method provides a flexible, stream-based API for traversing constructor annotations without creating intermediate lists.
549    *
550    * <h5 class='section'>Examples:</h5>
551    * <p class='bjava'>
552    *    <jc>// Search constructor annotations</jc>
553    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
554    *       findAnnotations(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF);
555    * </p>
556    *
557    * @param <A> The annotation type.
558    * @param type The annotation type to search for.  Must not be <jk>null</jk>.
559    * @param c The constructor to search.  Must not be <jk>null</jk>.
560    * @param traversals The traversal options.
561    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
562    */
563   public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, ConstructorInfo c, AnnotationTraversal...traversals) {
564      reqnn("type", type);
565      reqnn("c", c);
566      return cache.get(type, c, traversals);
567   }
568
569   /**
570    * Finds annotations from a field using configurable traversal options.
571    *
572    * <p>
573    * This method provides a flexible, stream-based API for traversing field annotations without creating intermediate lists.
574    *
575    * <h5 class='section'>Examples:</h5>
576    * <p class='bjava'>
577    *    <jc>// Search field annotations</jc>
578    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
579    *       findAnnotations(MyAnnotation.<jk>class</jk>, <jv>fi</jv>, SELF);
580    * </p>
581    *
582    * @param <A> The annotation type.
583    * @param type The annotation type to search for.  Must not be <jk>null</jk>.
584    * @param f The field to search.  Must not be <jk>null</jk>.
585    * @param traversals The traversal options.
586    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
587    */
588   public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, FieldInfo f, AnnotationTraversal...traversals) {
589      reqnn("type", type);
590      reqnn("f", f);
591      return cache.get(type, f, traversals);
592   }
593
594   /**
595    * Finds annotations from a method using configurable traversal options.
596    *
597    * <p>
598    * This method provides a flexible API for traversing method annotations.
599    *
600    * <h5 class='section'>Examples:</h5>
601    * <p class='bjava'>
602    *    <jc>// Search method and matching parent methods</jc>
603    *    List&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>l1</jv> =
604    *       find(MyAnnotation.<jk>class</jk>, <jv>mi</jv>, SELF, MATCHING_METHODS);
605    *
606    *    <jc>// Search method, matching methods, and return type (parent-first using rstream)</jc>
607    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> =
608    *       rstream(find(MyAnnotation.<jk>class</jk>, <jv>mi</jv>, SELF, MATCHING_METHODS, RETURN_TYPE));
609    * </p>
610    *
611    * @param <A> The annotation type.
612    * @param type The annotation type to search for.  Must not be <jk>null</jk>.
613    * @param m The method to search.  Must not be <jk>null</jk>.
614    * @param traversals The traversal options.
615    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
616    */
617   public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, MethodInfo m, AnnotationTraversal...traversals) {
618      reqnn("type", type);
619      reqnn("m", m);
620      return cache.get(type, m, traversals);
621   }
622
623   /**
624    * Finds annotations from a parameter using configurable traversal options in child-to-parent order.
625    *
626    * <p>
627    * This method provides a flexible, stream-based API for traversing parameter annotations without creating intermediate lists.
628    *
629    * <h5 class='section'>Supported Traversal Types:</h5>
630    * <ul>
631    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this parameter
632    *    <li>{@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS} - Matching parameters in parent methods/constructors (child-to-parent)
633    *    <li>{@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE} - The parameter's type hierarchy (includes class parents and package)
634    * </ul>
635    *
636    * <p>
637    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}
638    *
639    * <h5 class='section'>Examples:</h5>
640    * <p class='bjava'>
641    *    <jc>// Search parameter, matching parameters, and parameter type (child-to-parent)</jc>
642    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
643    *       find(MyAnnotation.<jk>class</jk>, <jv>pi</jv>, SELF, MATCHING_PARAMETERS, PARAMETER_TYPE);
644    *
645    *    <jc>// Just search this parameter</jc>
646    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> =
647    *       find(MyAnnotation.<jk>class</jk>, <jv>pi</jv>, SELF);
648    *
649    *    <jc>// Search in parent-to-child order using findTopDown</jc>
650    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s3</jv> =
651    *       findTopDown(MyAnnotation.<jk>class</jk>, <jv>pi</jv>, SELF, MATCHING_PARAMETERS, PARAMETER_TYPE);
652    * </p>
653    *
654    * @param <A> The annotation type.
655    * @param type The annotation type to search for.  Must not be <jk>null</jk>.
656    * @param p The parameter to search.  Must not be <jk>null</jk>.
657    * @param traversals
658    *    The traversal options. If not specified, defaults to {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}.
659    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS}, {@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE}
660    * @return A list of {@link AnnotationInfo} objects in child-to-parent order. Never <jk>null</jk>.
661    */
662   public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, ParameterInfo p, AnnotationTraversal...traversals) {
663      reqnn("type", type);
664      reqnn("p", p);
665      return cache.get(type, p, traversals);
666   }
667
668   /**
669    * Finds all annotations from a class using configurable traversal options, without filtering by annotation type.
670    *
671    * <p>
672    * This method provides a flexible API for traversing all class annotations.
673    * Unlike {@link #find(Class, ClassInfo, AnnotationTraversal...)}, this method does not filter by annotation type.
674    *
675    * <h5 class='section'>Examples:</h5>
676    * <p class='bjava'>
677    *    <jc>// Get all annotations from class only</jc>
678    *    List&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>l1</jv> =
679    *       find(<jv>ci</jv>, SELF);
680    *
681    *    <jc>// Get all annotations from class and parents</jc>
682    *    List&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>l2</jv> =
683    *       find(<jv>ci</jv>, SELF, PARENTS);
684    * </p>
685    *
686    * @param c The class to search.  Must not be <jk>null</jk>.
687    * @param traversals The traversal options (what to search and order).
688    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
689    */
690   public List<AnnotationInfo<? extends Annotation>> find(ClassInfo c, AnnotationTraversal...traversals) {
691      reqnn("c", c);
692      return cache.get(null, c, traversals);
693   }
694
695   /**
696    * Finds all annotations from a constructor using configurable traversal options, without filtering by annotation type.
697    *
698    * <p>
699    * This method provides a flexible, stream-based API for traversing all constructor annotations without creating intermediate lists.
700    * Unlike {@link #find(Class, ConstructorInfo, AnnotationTraversal...)}, this method does not filter by annotation type.
701    *
702    * <h5 class='section'>Examples:</h5>
703    * <p class='bjava'>
704    *    <jc>// Get all annotations from constructor</jc>
705    *    Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s1</jv> =
706    *       find(<jv>ci</jv>, SELF);
707    * </p>
708    *
709    * @param c The constructor to search.  Must not be <jk>null</jk>.
710    * @param traversals The traversal options.
711    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
712    */
713   public List<AnnotationInfo<? extends Annotation>> find(ConstructorInfo c, AnnotationTraversal...traversals) {
714      reqnn("c", c);
715      return cache.get(null, c, traversals);
716   }
717
718   /**
719    * Finds all annotations from a field using configurable traversal options, without filtering by annotation type.
720    *
721    * <p>
722    * This method provides a flexible, stream-based API for traversing all field annotations without creating intermediate lists.
723    * Unlike {@link #find(Class, FieldInfo, AnnotationTraversal...)}, this method does not filter by annotation type.
724    *
725    * <h5 class='section'>Examples:</h5>
726    * <p class='bjava'>
727    *    <jc>// Get all annotations from field</jc>
728    *    Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s1</jv> =
729    *       find(<jv>fi</jv>, SELF);
730    * </p>
731    *
732    * @param f The field to search.  Must not be <jk>null</jk>.
733    * @param traversals The traversal options.
734    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
735    */
736   public List<AnnotationInfo<? extends Annotation>> find(FieldInfo f, AnnotationTraversal...traversals) {
737      reqnn("f", f);
738      return cache.get(null, f, traversals);
739   }
740
741   /**
742    * Finds all annotations from a method using configurable traversal options, without filtering by annotation type.
743    *
744    * <p>
745    * This method provides a flexible API for traversing all method annotations.
746    * Unlike {@link #find(Class, MethodInfo, AnnotationTraversal...)}, this method does not filter by annotation type.
747    *
748    * <h5 class='section'>Examples:</h5>
749    * <p class='bjava'>
750    *    <jc>// Get all annotations from method and matching parent methods</jc>
751    *    List&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>l1</jv> =
752    *       find(<jv>mi</jv>, SELF, MATCHING_METHODS);
753    *
754    *    <jc>// Get all annotations from method, matching methods, and return type</jc>
755    *    List&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>l2</jv> =
756    *       find(<jv>mi</jv>, SELF, MATCHING_METHODS, RETURN_TYPE);
757    * </p>
758    *
759    * @param m The method to search.  Must not be <jk>null</jk>.
760    * @param traversals The traversal options.
761    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
762    */
763   public List<AnnotationInfo<? extends Annotation>> find(MethodInfo m, AnnotationTraversal...traversals) {
764      reqnn("m", m);
765      return cache.get(null, m, traversals);
766   }
767
768   /**
769    * Finds all annotations from a parameter using configurable traversal options, without filtering by annotation type.
770    *
771    * <p>
772    * This method provides a flexible, stream-based API for traversing all parameter annotations without creating intermediate lists.
773    * Unlike {@link #find(Class, ParameterInfo, AnnotationTraversal...)}, this method does not filter by annotation type.
774    *
775    * <h5 class='section'>Supported Traversal Types:</h5>
776    * <ul>
777    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this parameter
778    *    <li>{@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS} - Matching parameters in parent methods/constructors (child-to-parent)
779    *    <li>{@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE} - The parameter's type hierarchy (includes class parents and package)
780    * </ul>
781    *
782    * <p>
783    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}
784    *
785    * <h5 class='section'>Examples:</h5>
786    * <p class='bjava'>
787    *    <jc>// Get all annotations from parameter, matching parameters, and parameter type</jc>
788    *    Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s1</jv> =
789    *       find(<jv>pi</jv>, SELF, MATCHING_PARAMETERS, PARAMETER_TYPE);
790    *
791    *    <jc>// Just get annotations from this parameter</jc>
792    *    Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s2</jv> =
793    *       find(<jv>pi</jv>, SELF);
794    * </p>
795    *
796    * @param p The parameter to search.  Must not be <jk>null</jk>.
797    * @param traversals
798    *    The traversal options. If not specified, defaults to {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}.
799    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS}, {@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE}
800    * @return A list of {@link AnnotationInfo} objects in child-to-parent order. Never <jk>null</jk>.
801    */
802   public List<AnnotationInfo<? extends Annotation>> find(ParameterInfo p, AnnotationTraversal...traversals) {
803      reqnn("p", p);
804      return cache.get(null, p, traversals);
805   }
806
807   /**
808    * Checks if a class has the specified annotation.
809    *
810    * <p>
811    * This is a convenience method equivalent to:
812    * <p class='bjava'>
813    *    find(<jv>type</jv>, <jv>clazz</jv>, <jv>traversals</jv>).findFirst().isPresent()
814    * </p>
815    *
816    * <h5 class='section'>Supported Traversal Types:</h5>
817    * <ul>
818    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this class
819    *    <li>{@link AnnotationTraversal#PARENTS PARENTS} - Parent classes and interfaces (child-to-parent order)
820    *    <li>{@link AnnotationTraversal#PACKAGE PACKAGE} - The package annotations
821    * </ul>
822    *
823    * <p>
824    * <b>Default:</b> If no traversals are specified, defaults to: {@code PARENTS, PACKAGE}
825    * <br>Note: {@code PARENTS} includes the class itself plus all parent classes and interfaces.
826    *
827    * <h5 class='section'>Example:</h5>
828    * <p class='bjava'>
829    *    <jc>// Check if class has @MyAnnotation anywhere in hierarchy</jc>
830    *    <jk>boolean</jk> <jv>hasIt</jv> = has(MyAnnotation.<jk>class</jk>, <jv>ci</jv>);
831    *
832    *    <jc>// Check only on the class itself</jc>
833    *    <jk>boolean</jk> <jv>hasIt2</jv> = has(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF);
834    * </p>
835    *
836    * @param <A> The annotation type.
837    * @param type The annotation type to search for.  Must not be <jk>null</jk>.
838    * @param c The class to search.  Must not be <jk>null</jk>.
839    * @param traversals
840    *    The traversal options. If not specified, defaults to {@code SELF, PARENTS, PACKAGE}.
841    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link AnnotationTraversal#PARENTS PARENTS}, {@link AnnotationTraversal#PACKAGE PACKAGE}
842    * @return <jk>true</jk> if the annotation is found, <jk>false</jk> otherwise.
843    */
844   public <A extends Annotation> boolean has(Class<A> type, ClassInfo c, AnnotationTraversal...traversals) {
845      return ! find(type, c, traversals).isEmpty();
846   }
847
848   /**
849    * Checks if a constructor has the specified annotation.
850    *
851    * <p>
852    * This is a convenience method equivalent to:
853    * <p class='bjava'>
854    *    find(<jv>type</jv>, <jv>constructor</jv>, <jv>traversals</jv>).findFirst().isPresent()
855    * </p>
856    *
857    * <h5 class='section'>Supported Traversal Types:</h5>
858    * <ul>
859    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this constructor
860    * </ul>
861    *
862    * <p>
863    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF}
864    *
865    * <h5 class='section'>Example:</h5>
866    * <p class='bjava'>
867    *    <jc>// Check if constructor has @MyAnnotation</jc>
868    *    <jk>boolean</jk> <jv>hasIt</jv> = has(MyAnnotation.<jk>class</jk>, <jv>ci</jv>);
869    * </p>
870    *
871    * @param <A> The annotation type.
872    * @param type The annotation type to search for.  Must not be <jk>null</jk>.
873    * @param c The constructor to search.  Must not be <jk>null</jk>.
874    * @param traversals
875    *    The traversal options. If not specified, defaults to {@code SELF}.
876    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}
877    * @return <jk>true</jk> if the annotation is found, <jk>false</jk> otherwise.
878    */
879   public <A extends Annotation> boolean has(Class<A> type, ConstructorInfo c, AnnotationTraversal...traversals) {
880      return ! find(type, c, traversals).isEmpty();
881   }
882
883   /**
884    * Checks if a field has the specified annotation.
885    *
886    * <p>
887    * This is a convenience method equivalent to:
888    * <p class='bjava'>
889    *    find(<jv>type</jv>, <jv>field</jv>, <jv>traversals</jv>).findFirst().isPresent()
890    * </p>
891    *
892    * <h5 class='section'>Supported Traversal Types:</h5>
893    * <ul>
894    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this field
895    * </ul>
896    *
897    * <p>
898    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF}
899    *
900    * <h5 class='section'>Example:</h5>
901    * <p class='bjava'>
902    *    <jc>// Check if field has @MyAnnotation</jc>
903    *    <jk>boolean</jk> <jv>hasIt</jv> = has(MyAnnotation.<jk>class</jk>, <jv>fi</jv>);
904    * </p>
905    *
906    * @param <A> The annotation type.
907    * @param type The annotation type to search for.  Must not be <jk>null</jk>.
908    * @param f The field to search.  Must not be <jk>null</jk>.
909    * @param traversals
910    *    The traversal options. If not specified, defaults to {@code SELF}.
911    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}
912    * @return <jk>true</jk> if the annotation is found, <jk>false</jk> otherwise.
913    */
914   public <A extends Annotation> boolean has(Class<A> type, FieldInfo f, AnnotationTraversal...traversals) {
915      return ! find(type, f, traversals).isEmpty();
916   }
917
918   /**
919    * Checks if a method has the specified annotation.
920    *
921    * <p>
922    * This is a convenience method equivalent to:
923    * <p class='bjava'>
924    *    find(<jv>type</jv>, <jv>method</jv>, <jv>traversals</jv>).findFirst().isPresent()
925    * </p>
926    *
927    * <h5 class='section'>Supported Traversal Types:</h5>
928    * <ul>
929    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this method
930    *    <li>{@link AnnotationTraversal#MATCHING_METHODS MATCHING_METHODS} - Matching methods in parent classes (child-to-parent)
931    *    <li>{@link AnnotationTraversal#RETURN_TYPE RETURN_TYPE} - The return type hierarchy (includes class parents and package)
932    *    <li>{@link AnnotationTraversal#PACKAGE PACKAGE} - The declaring class's package annotations
933    * </ul>
934    *
935    * <p>
936    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF, MATCHING_METHODS, RETURN_TYPE, PACKAGE}
937    *
938    * <h5 class='section'>Example:</h5>
939    * <p class='bjava'>
940    *    <jc>// Check if method has @MyAnnotation anywhere in hierarchy</jc>
941    *    <jk>boolean</jk> <jv>hasIt</jv> = has(MyAnnotation.<jk>class</jk>, <jv>mi</jv>);
942    *
943    *    <jc>// Check only on the method itself</jc>
944    *    <jk>boolean</jk> <jv>hasIt2</jv> = has(MyAnnotation.<jk>class</jk>, <jv>mi</jv>, SELF);
945    * </p>
946    *
947    * @param <A> The annotation type.
948    * @param type The annotation type to search for.  Must not be <jk>null</jk>.
949    * @param m The method to search.  Must not be <jk>null</jk>.
950    * @param traversals
951    *    The traversal options. If not specified, defaults to {@code SELF, MATCHING_METHODS, RETURN_TYPE, PACKAGE}.
952    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link AnnotationTraversal#MATCHING_METHODS MATCHING_METHODS}, {@link AnnotationTraversal#RETURN_TYPE RETURN_TYPE}, {@link AnnotationTraversal#PACKAGE PACKAGE}
953    * @return <jk>true</jk> if the annotation is found, <jk>false</jk> otherwise.
954    */
955   public <A extends Annotation> boolean has(Class<A> type, MethodInfo m, AnnotationTraversal...traversals) {
956      return ! find(type, m, traversals).isEmpty();
957   }
958
959   /**
960    * Checks if a parameter has the specified annotation.
961    *
962    * <p>
963    * This is a convenience method equivalent to:
964    * <p class='bjava'>
965    *    find(<jv>type</jv>, <jv>parameter</jv>, <jv>traversals</jv>).findFirst().isPresent()
966    * </p>
967    *
968    * <h5 class='section'>Supported Traversal Types:</h5>
969    * <ul>
970    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this parameter
971    *    <li>{@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS} - Matching parameters in parent methods/constructors (child-to-parent)
972    *    <li>{@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE} - The parameter's type hierarchy (includes class parents and package)
973    * </ul>
974    *
975    * <p>
976    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}
977    *
978    * <h5 class='section'>Example:</h5>
979    * <p class='bjava'>
980    *    <jc>// Check if parameter has @MyAnnotation anywhere in hierarchy</jc>
981    *    <jk>boolean</jk> <jv>hasIt</jv> = has(MyAnnotation.<jk>class</jk>, <jv>pi</jv>);
982    *
983    *    <jc>// Check only on the parameter itself</jc>
984    *    <jk>boolean</jk> <jv>hasIt2</jv> = has(MyAnnotation.<jk>class</jk>, <jv>pi</jv>, SELF);
985    * </p>
986    *
987    * @param <A> The annotation type.
988    * @param type The annotation type to search for.  Must not be <jk>null</jk>.
989    * @param p The parameter to search.  Must not be <jk>null</jk>.
990    * @param traversals
991    *    The traversal options. If not specified, defaults to {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}.
992    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS}, {@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE}
993    * @return <jk>true</jk> if the annotation is found, <jk>false</jk> otherwise.
994    */
995   public <A extends Annotation> boolean has(Class<A> type, ParameterInfo p, AnnotationTraversal...traversals) {
996      return ! find(type, p, traversals).isEmpty();
997   }
998
999   /**
1000    * Computes and caches the complete list of annotations for a given type, class, and traversal combination.
1001    * This is the supplier function for the findCache.
1002    */
1003   @SuppressWarnings({
1004      "java:S6541" // Synchronization not needed for cache access pattern
1005   })
1006   private List load(Class<?> type, ElementInfo element, AnnotationTraversal[] traversals) {
1007
1008      if (type != null) {
1009         return cache.get(null, element, traversals).stream().filter(x -> ((AnnotationInfo)x).isType(type)).toList();
1010      }
1011
1012      var l = new ArrayList();
1013
1014      List<AnnotationTraversal> t;
1015      if (traversals.length > 0)
1016         t = l(traversals);
1017      else if (element instanceof ClassInfo)
1018         t = l(a(PARENTS, PACKAGE));
1019      else if (element instanceof MethodInfo)
1020         t = l(a(SELF, MATCHING_METHODS, DECLARING_CLASS, RETURN_TYPE, PACKAGE));
1021      else if (element instanceof FieldInfo || element instanceof ConstructorInfo)
1022         t = l(a(SELF));
1023      else {
1024         reqt(ParameterInfo.class, element, Shorts::uoex);
1025         t = l(a(SELF, MATCHING_PARAMETERS, PARAMETER_TYPE));
1026      }
1027
1028      if (element instanceof ClassInfo element2) {
1029         if (t.contains(SELF)) {
1030            l.addAll(runtimeCache.get(element2.inner()));
1031            l.addAll(element2.getDeclaredAnnotations());
1032         }
1033         if (t.contains(PARENTS)) {
1034            for (var p : element2.getParentsAndInterfaces()) {
1035               l.addAll(runtimeCache.get(p.inner()));
1036               l.addAll(p.getDeclaredAnnotations());
1037            }
1038         }
1039         if (t.contains(PACKAGE) && element2.getPackage() != null)
1040            l.addAll(element2.getPackage().getAnnotations());
1041      } else if (element instanceof MethodInfo element2) {
1042         if (t.contains(SELF)) {
1043            l.addAll(runtimeCache.get(element2.inner()));
1044            l.addAll(element2.getDeclaredAnnotations());
1045         }
1046         if (t.contains(MATCHING_METHODS)) {
1047            for (var m : element2.getMatchingMethods().stream().skip(1).toList()) {
1048               l.addAll(runtimeCache.get(m.inner()));
1049               l.addAll(m.getDeclaredAnnotations());
1050            }
1051         }
1052         if (t.contains(DECLARING_CLASS)) {
1053            l.addAll(find(element2.getDeclaringClass(), a(PARENTS)));
1054         }
1055         if (t.contains(RETURN_TYPE)) {
1056            l.addAll(find(element2.getReturnType().unwrap(Holder.class, Optional.class), a(PARENTS)));
1057         }
1058         if (t.contains(PACKAGE) && element2.getDeclaringClass().getPackage() != null)
1059            l.addAll(element2.getDeclaringClass().getPackage().getAnnotations());
1060      } else if (element instanceof FieldInfo element2) {
1061         if (t.contains(SELF)) {
1062            l.addAll(runtimeCache.get(element2.inner()));
1063            l.addAll(element2.getAnnotations());
1064         }
1065      } else if (element instanceof ConstructorInfo element2) {
1066         if (t.contains(SELF)) {
1067            l.addAll(runtimeCache.get(element2.inner()));
1068            l.addAll(element2.getDeclaredAnnotations());
1069         }
1070      } else if (element instanceof ParameterInfo element2) {
1071         if (t.contains(SELF)) {
1072            l.addAll(element2.getAnnotations());
1073         }
1074         if (t.contains(MATCHING_PARAMETERS)) {
1075            for (var p : element2.getMatchingParameters().stream().skip(1).toList()) {
1076               l.addAll(p.getAnnotations());
1077            }
1078         }
1079         if (t.contains(PARAMETER_TYPE)) {
1080            l.addAll(find(element2.getParameterType().unwrap(Holder.class, Optional.class), a(PARENTS, PACKAGE)));
1081         }
1082      }
1083
1084      return l;
1085   }
1086
1087   private List load(Object o) {
1088      if (o instanceof Class o2) {
1089         var ci = ClassInfo.of(o2);
1090         return annotationMap == null ? emptyList() : annotationMap.find(ci.inner()).map(a -> ai(ci, a)).toList();
1091      }
1092      if (o instanceof Method o2) {
1093         var mi = info(o2);
1094         return annotationMap == null ? emptyList() : annotationMap.find(mi.inner()).map(a -> ai(mi, a)).toList();
1095      }
1096      if (o instanceof Field o2) {
1097         var fi = info(o2);
1098         return annotationMap == null ? emptyList() : annotationMap.find(fi.inner()).map(a -> ai(fi, a)).toList();
1099      }
1100      if (o instanceof Constructor o2) {
1101         var ci = info(o2);
1102         return annotationMap == null ? emptyList() : annotationMap.find(ci.inner()).map(a -> ai(ci, a)).toList();
1103      }
1104      throw uoex();
1105   }
1106}