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 org.apache.juneau.commons.reflect.AnnotationTraversal.*;
020import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
021import static org.apache.juneau.commons.utils.AssertionUtils.*;
022import static org.apache.juneau.commons.utils.CollectionUtils.*;
023import static org.apache.juneau.commons.utils.ThrowableUtils.*;
024import static org.apache.juneau.commons.utils.Utils.*;
025
026import java.lang.annotation.*;
027import java.lang.reflect.*;
028import java.util.*;
029
030import org.apache.juneau.commons.collections.*;
031import org.apache.juneau.commons.lang.*;
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 @Bean})
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> = BeanAnnotation
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 @Bean 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 @Bean} annotation on a class will be found before any {@code @Bean} 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({ "unchecked", "rawtypes" })
181public class AnnotationProvider {
182
183   //-----------------------------------------------------------------------------------------------------------------
184   // System properties
185   //-----------------------------------------------------------------------------------------------------------------
186
187   /**
188    * Builder for creating configured {@link AnnotationProvider} instances.
189    *
190    * <h5 class='section'>Example:</h5>
191    * <p class='bjava'>
192    *    AnnotationProvider <jv>provider</jv> = AnnotationProvider
193    *       .<jsm>create</jsm>()
194    *       .disableCaching()
195    *       .build();
196    * </p>
197    *
198    * <h5 class='section'>See Also:</h5>
199    * <ul>
200    *    <li class='jm'>{@link AnnotationProvider#create()}
201    * </ul>
202    */
203   public static class Builder {
204      CacheMode cacheMode;
205      boolean logOnExit;
206      ReflectionMap.Builder<Annotation> runtimeAnnotations;
207
208      Builder() {
209         cacheMode = CACHING_MODE;
210         logOnExit = LOG_ON_EXIT;
211      }
212
213      /**
214       * Adds runtime annotations to be applied to classes, methods, fields, and constructors.
215       *
216       * <p>
217       * This is a convenience method that delegates to {@link #addRuntimeAnnotations(List)}.
218       * See that method for detailed documentation on how runtime annotations work.
219       *
220       * <p class='bjava'>
221       *    <jc>// Example: Add multiple runtime annotations using varargs</jc>
222       *    Bean <jv>beanAnnotation</jv> = BeanAnnotation
223       *       .<jsm>create</jsm>()
224       *       .onClass(MyClass.<jk>class</jk>)
225       *       .typeName(<js>"MyType"</js>)
226       *       .build();
227       *
228       *    Swap <jv>swapAnnotation</jv> = SwapAnnotation
229       *       .<jsm>create</jsm>()
230       *       .on(<js>"com.example.MyClass.getValue"</js>)
231       *       .value(MySwap.<jk>class</jk>)
232       *       .build();
233       *
234       *    AnnotationProvider <jv>provider</jv> = AnnotationProvider
235       *       .<jsm>create</jsm>()
236       *       .addRuntimeAnnotations(<jv>beanAnnotation</jv>, <jv>swapAnnotation</jv>)  <jc>// Varargs</jc>
237       *       .build();
238       * </p>
239       *
240       * @param annotations The runtime annotation objects to add (varargs).
241       * @return This object for method chaining.
242       * @throws BeanRuntimeException If any annotation is invalid.
243       * @see #addRuntimeAnnotations(List)
244       */
245      public Builder addRuntimeAnnotations(Annotation...annotations) {
246         return addRuntimeAnnotations(l(annotations));
247      }
248
249      /**
250       * Adds runtime annotations to be applied to classes, methods, fields, and constructors.
251       *
252       * <p>
253       * Runtime annotations are concrete Java objects that implement annotation interfaces (e.g., {@code @Bean}).
254       * They allow you to dynamically apply annotations to code elements at runtime without modifying source code.
255       *
256       * <p>
257       * <b>How It Works:</b>
258       * <ol>
259       *    <li>Create annotation objects using builder classes (e.g., {@code BeanAnnotation.create()})
260       *    <li>Specify targets using {@code on()} or {@code onClass()} methods
261       *    <li>Set annotation properties (e.g., {@code typeName()}, {@code properties()})
262       *    <li>Build the annotation object
263       *    <li>Add to the provider via this method
264       * </ol>
265       *
266       * <p>
267       * <b>Targeting Requirements:</b>
268       * <ul>
269       *    <li>Annotations MUST define an {@code onClass()} method returning {@code Class[]} for type-safe targeting
270       *    <li>OR an {@code on()} method returning {@code String[]} for string-based targeting
271       *    <li>The {@code on()} method accepts fully-qualified names:
272       *       <ul>
273       *          <li>{@code "com.example.MyClass"} - targets a class
274       *          <li>{@code "com.example.MyClass.myMethod"} - targets a method
275       *          <li>{@code "com.example.MyClass.myField"} - targets a field
276       *       </ul>
277       * </ul>
278       *
279       * <p class='bjava'>
280       *    <jc>// Example 1: Target a specific class using type-safe targeting</jc>
281       *    Bean <jv>beanAnnotation</jv> = BeanAnnotation
282       *       .<jsm>create</jsm>()
283       *       .onClass(MyClass.<jk>class</jk>)  <jc>// Targets MyClass</jc>
284       *       .typeName(<js>"MyType"</js>)
285       *       .properties(<js>"id,name"</js>)
286       *       .build();
287       *
288       *    <jc>// Example 2: Target multiple classes</jc>
289       *    Bean <jv>multiAnnotation</jv> = BeanAnnotation
290       *       .<jsm>create</jsm>()
291       *       .onClass(MyClass.<jk>class</jk>, OtherClass.<jk>class</jk>)
292       *       .sort(<jk>true</jk>)
293       *       .build();
294       *
295       *    <jc>// Example 3: Target using string names (useful for dynamic/reflection scenarios)</jc>
296       *    Bean <jv>stringAnnotation</jv> = BeanAnnotation
297       *       .<jsm>create</jsm>()
298       *       .on(<js>"com.example.MyClass"</js>)
299       *       .findFluentSetters(<jk>true</jk>)
300       *       .build();
301       *
302       *    <jc>// Example 4: Target a specific method</jc>
303       *    Swap <jv>swapAnnotation</jv> = SwapAnnotation
304       *       .<jsm>create</jsm>()
305       *       .on(<js>"com.example.MyClass.getValue"</js>)
306       *       .value(MySwap.<jk>class</jk>)
307       *       .build();
308       *
309       *    <jc>// Add all runtime annotations to the provider</jc>
310       *    AnnotationProvider <jv>provider</jv> = AnnotationProvider
311       *       .<jsm>create</jsm>()
312       *       .addRuntimeAnnotations(<jv>beanAnnotation</jv>, <jv>multiAnnotation</jv>, <jv>stringAnnotation</jv>, <jv>swapAnnotation</jv>)
313       *       .build();
314       * </p>
315       *
316       * <p>
317       * <b>Priority:</b> Runtime annotations always take precedence over declared annotations at the same level.
318       * They are evaluated first when searching for annotations.
319       *
320       * @param annotations The list of runtime annotation objects to add.
321       * @return This object for method chaining.
322       * @throws BeanRuntimeException If any annotation is invalid (missing {@code on()} or {@code onClass()} methods,
323       *    or if the methods return incorrect types).
324       */
325      public Builder addRuntimeAnnotations(List<Annotation> annotations) {
326         if (runtimeAnnotations == null)
327            runtimeAnnotations = ReflectionMap.create(Annotation.class);
328
329         for (var a : annotations) {
330            try {
331               var ci = ClassInfo.of(a.getClass());
332
333               ci.getPublicMethod(x -> x.hasName("onClass")).ifPresent(mi -> {
334                  if (! mi.getReturnType().is(Class[].class))
335                     throw bex("Invalid annotation @{0} used in runtime annotations.  Annotation must define an onClass() method that returns a Class array.", cns(a));
336                  for (var c : (Class<?>[])mi.accessible().invoke(a))
337                     runtimeAnnotations.append(c.getName(), a);
338               });
339
340               ci.getPublicMethod(x -> x.hasName("on")).ifPresent(mi -> {
341                  if (! mi.getReturnType().is(String[].class))
342                     throw bex("Invalid annotation @{0} used in runtime annotations.  Annotation must define an on() method that returns a String array.", cns(a));
343                  for (var s : (String[])mi.accessible().invoke(a))
344                     runtimeAnnotations.append(s, a);
345               });
346
347            } catch (BeanRuntimeException e) {
348               throw e;
349            } catch (Exception e) {
350               throw bex(e, (Class<?>)null, "Invalid annotation @{0} used in runtime annotations.", cn(a));
351            }
352         }
353         return this;
354      }
355
356      /**
357       * Builds a new {@link AnnotationProvider} instance with the configured settings.
358       *
359       * @return A new immutable {@link AnnotationProvider} instance.
360       */
361      public AnnotationProvider build() {
362         if (e(runtimeAnnotations) && INSTANCE != null)  // HTT
363            return INSTANCE;
364         return new AnnotationProvider(this);
365      }
366
367      /**
368       * Sets the caching mode for annotation lookups.
369       *
370       * <p>
371       * Available modes:
372       * <ul>
373       *    <li><c>NONE</c> - Disables all caching (always recompute)
374       *    <li><c>WEAK</c> - Uses WeakHashMap (allows GC of cached entries)
375       *    <li><c>FULL</c> - Uses ConcurrentHashMap (best performance)
376       * </ul>
377       *
378       * @param value The caching mode.
379       * @return This object for method chaining.
380       */
381      public Builder cacheMode(CacheMode value) {
382         cacheMode = value;
383         return this;
384      }
385
386      /**
387       * Enables logging of cache statistics on JVM shutdown.
388       *
389       * @return This object for method chaining.
390       */
391      public Builder logOnExit() {
392         logOnExit = true;
393         return this;
394      }
395
396      /**
397       * Conditionally enables logging of cache statistics on JVM shutdown.
398       *
399       * @param value Whether to log on exit.
400       * @return This object for method chaining.
401       */
402      public Builder logOnExit(boolean value) {
403         logOnExit = value;
404         return this;
405      }
406   }
407
408   /**
409    * Caching mode for annotation lookups.
410    *
411    * <p>
412    * System property: <c>juneau.annotationProvider.caching</c>
413    * <br>Valid values: <c>NONE</c>, <c>WEAK</c>, <c>FULL</c> (case-insensitive)
414    * <br>Default: <c>FULL</c>
415    *
416    * <ul>
417    *    <li><c>NONE</c> - Disables all caching (always recompute)
418    *    <li><c>WEAK</c> - Uses WeakHashMap (allows GC of cached entries)
419    *    <li><c>FULL</c> - Uses ConcurrentHashMap (best performance)
420    * </ul>
421    */
422   private static final CacheMode CACHING_MODE = CacheMode.parse(System.getProperty("juneau.annotationProvider.caching", "FULL"));
423
424   /**
425    * Enable logging of cache statistics on JVM shutdown.
426    *
427    * <p>
428    * System property: <c>juneau.annotationProvider.caching.logOnExit</c>
429    * <br>Valid values: <c>TRUE</c>, <c>FALSE</c> (case-insensitive)
430    * <br>Default: <c>FALSE</c>
431    */
432   private static final boolean LOG_ON_EXIT = bool(System.getProperty("juneau.annotationProvider.caching.logOnExit"));
433
434   //-----------------------------------------------------------------------------------------------------------------
435   // Builder
436   //-----------------------------------------------------------------------------------------------------------------
437
438   /**
439    * Default instance.
440    */
441   public static final AnnotationProvider INSTANCE = new AnnotationProvider(create().logOnExit());
442
443   /**
444    * Creates a new {@link Builder} for constructing an annotation provider.
445    *
446    * @return A new builder for configuring the annotation provider.
447    */
448   public static Builder create() {
449      return new Builder();
450   }
451
452   private static <A extends Annotation> AnnotationInfo<A> ai(Annotatable on, A value) {
453      return AnnotationInfo.of(on, value);
454   }
455
456   private final Cache<Object,List<AnnotationInfo<Annotation>>> runtimeCache;
457   private final Cache3<Class<?>,ElementInfo,AnnotationTraversal[],List> cache;
458
459   private final ReflectionMap<Annotation> annotationMap;
460
461   //-----------------------------------------------------------------------------------------------------------------
462   // Stream-based traversal methods
463   //-----------------------------------------------------------------------------------------------------------------
464
465   /**
466    * Constructor.
467    *
468    * @param builder The builder containing configuration settings.
469    */
470   protected AnnotationProvider(Builder builder) {
471      // @formatter:off
472      this.runtimeCache = Cache.<Object,List<AnnotationInfo<Annotation>>>create()
473         .supplier(this::load)
474         .cacheMode(builder.cacheMode)
475         .logOnExit(builder.logOnExit, "AnnotationProvider.runtimeAnnotations")
476         .build();
477
478      this.cache = Cache3.<Class<?>,ElementInfo,AnnotationTraversal[],List>create()
479         .supplier(this::load)
480         .cacheMode(builder.cacheMode)
481         .logOnExit(builder.logOnExit, "AnnotationProvider.cache")
482         .build();
483
484      this.annotationMap = opt(builder.runtimeAnnotations).map(x -> x.build()).orElse(null);
485      // @formatter:on
486   }
487
488   /**
489    * Finds annotations from a class using configurable traversal options.
490    *
491    * <p>
492    * This method provides a flexible API for traversing annotations.
493    * It uses {@link AnnotationTraversal} enums to configure what elements to search and in what order.
494    *
495    * <h5 class='section'>Examples:</h5>
496    * <p class='bjava'>
497    *    <jc>// Search class only</jc>
498    *    List&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>l1</jv> =
499    *       find(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF);
500    *
501    *    <jc>// Search class and parents</jc>
502    *    List&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>l2</jv> =
503    *       find(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF, PARENTS);
504    *
505    *    <jc>// Search class, parents, and package (parent-first order using rstream)</jc>
506    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s3</jv> =
507    *       rstream(find(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF, PARENTS, PACKAGE));
508    * </p>
509    *
510    * @param <A> The annotation type.
511    * @param type The annotation type to search for.
512    * @param c The class to search.
513    * @param traversals The traversal options (what to search and order).
514    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
515    */
516   public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, ClassInfo c, AnnotationTraversal...traversals) {
517      assertArgNotNull("type", type);
518      assertArgNotNull("c", c);
519      return cache.get(type, c, traversals);
520   }
521
522   /**
523    * Finds annotations from a constructor using configurable traversal options.
524    *
525    * <p>
526    * This method provides a flexible, stream-based API for traversing constructor annotations without creating intermediate lists.
527    *
528    * <h5 class='section'>Examples:</h5>
529    * <p class='bjava'>
530    *    <jc>// Search constructor annotations</jc>
531    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
532    *       findAnnotations(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF);
533    * </p>
534    *
535    * @param <A> The annotation type.
536    * @param type The annotation type to search for.
537    * @param c The constructor to search.
538    * @param traversals The traversal options.
539    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
540    */
541   public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, ConstructorInfo c, AnnotationTraversal...traversals) {
542      assertArgNotNull("type", type);
543      assertArgNotNull("c", c);
544      return cache.get(type, c, traversals);
545   }
546
547   /**
548    * Finds annotations from a field using configurable traversal options.
549    *
550    * <p>
551    * This method provides a flexible, stream-based API for traversing field annotations without creating intermediate lists.
552    *
553    * <h5 class='section'>Examples:</h5>
554    * <p class='bjava'>
555    *    <jc>// Search field annotations</jc>
556    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
557    *       findAnnotations(MyAnnotation.<jk>class</jk>, <jv>fi</jv>, SELF);
558    * </p>
559    *
560    * @param <A> The annotation type.
561    * @param type The annotation type to search for.
562    * @param f The field to search.
563    * @param traversals The traversal options.
564    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
565    */
566   public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, FieldInfo f, AnnotationTraversal...traversals) {
567      assertArgNotNull("type", type);
568      assertArgNotNull("f", f);
569      return cache.get(type, f, traversals);
570   }
571
572   /**
573    * Finds annotations from a method using configurable traversal options.
574    *
575    * <p>
576    * This method provides a flexible API for traversing method annotations.
577    *
578    * <h5 class='section'>Examples:</h5>
579    * <p class='bjava'>
580    *    <jc>// Search method and matching parent methods</jc>
581    *    List&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>l1</jv> =
582    *       find(MyAnnotation.<jk>class</jk>, <jv>mi</jv>, SELF, MATCHING_METHODS);
583    *
584    *    <jc>// Search method, matching methods, and return type (parent-first using rstream)</jc>
585    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> =
586    *       rstream(find(MyAnnotation.<jk>class</jk>, <jv>mi</jv>, SELF, MATCHING_METHODS, RETURN_TYPE));
587    * </p>
588    *
589    * @param <A> The annotation type.
590    * @param type The annotation type to search for.
591    * @param m The method to search.
592    * @param traversals The traversal options.
593    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
594    */
595   public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, MethodInfo m, AnnotationTraversal...traversals) {
596      assertArgNotNull("type", type);
597      assertArgNotNull("m", m);
598      return cache.get(type, m, traversals);
599   }
600
601   /**
602    * Finds annotations from a parameter using configurable traversal options in child-to-parent order.
603    *
604    * <p>
605    * This method provides a flexible, stream-based API for traversing parameter annotations without creating intermediate lists.
606    *
607    * <h5 class='section'>Supported Traversal Types:</h5>
608    * <ul>
609    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this parameter
610    *    <li>{@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS} - Matching parameters in parent methods/constructors (child-to-parent)
611    *    <li>{@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE} - The parameter's type hierarchy (includes class parents and package)
612    * </ul>
613    *
614    * <p>
615    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}
616    *
617    * <h5 class='section'>Examples:</h5>
618    * <p class='bjava'>
619    *    <jc>// Search parameter, matching parameters, and parameter type (child-to-parent)</jc>
620    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s1</jv> =
621    *       find(MyAnnotation.<jk>class</jk>, <jv>pi</jv>, SELF, MATCHING_PARAMETERS, PARAMETER_TYPE);
622    *
623    *    <jc>// Just search this parameter</jc>
624    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s2</jv> =
625    *       find(MyAnnotation.<jk>class</jk>, <jv>pi</jv>, SELF);
626    *
627    *    <jc>// Search in parent-to-child order using findTopDown</jc>
628    *    Stream&lt;AnnotationInfo&lt;MyAnnotation&gt;&gt; <jv>s3</jv> =
629    *       findTopDown(MyAnnotation.<jk>class</jk>, <jv>pi</jv>, SELF, MATCHING_PARAMETERS, PARAMETER_TYPE);
630    * </p>
631    *
632    * @param <A> The annotation type.
633    * @param type The annotation type to search for.
634    * @param p The parameter to search.
635    * @param traversals
636    *    The traversal options. If not specified, defaults to {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}.
637    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS}, {@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE}
638    * @return A list of {@link AnnotationInfo} objects in child-to-parent order. Never <jk>null</jk>.
639    */
640   public <A extends Annotation> List<AnnotationInfo<A>> find(Class<A> type, ParameterInfo p, AnnotationTraversal...traversals) {
641      assertArgNotNull("type", type);
642      assertArgNotNull("p", p);
643      return cache.get(type, p, traversals);
644   }
645
646   /**
647    * Finds all annotations from a class using configurable traversal options, without filtering by annotation type.
648    *
649    * <p>
650    * This method provides a flexible API for traversing all class annotations.
651    * Unlike {@link #find(Class, ClassInfo, AnnotationTraversal...)}, this method does not filter by annotation type.
652    *
653    * <h5 class='section'>Examples:</h5>
654    * <p class='bjava'>
655    *    <jc>// Get all annotations from class only</jc>
656    *    List&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>l1</jv> =
657    *       find(<jv>ci</jv>, SELF);
658    *
659    *    <jc>// Get all annotations from class and parents</jc>
660    *    List&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>l2</jv> =
661    *       find(<jv>ci</jv>, SELF, PARENTS);
662    * </p>
663    *
664    * @param c The class to search.
665    * @param traversals The traversal options (what to search and order).
666    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
667    */
668   public List<AnnotationInfo<? extends Annotation>> find(ClassInfo c, AnnotationTraversal...traversals) {
669      assertArgNotNull("c", c);
670      return cache.get(null, c, traversals);
671   }
672
673   /**
674    * Finds all annotations from a constructor using configurable traversal options, without filtering by annotation type.
675    *
676    * <p>
677    * This method provides a flexible, stream-based API for traversing all constructor annotations without creating intermediate lists.
678    * Unlike {@link #find(Class, ConstructorInfo, AnnotationTraversal...)}, this method does not filter by annotation type.
679    *
680    * <h5 class='section'>Examples:</h5>
681    * <p class='bjava'>
682    *    <jc>// Get all annotations from constructor</jc>
683    *    Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s1</jv> =
684    *       find(<jv>ci</jv>, SELF);
685    * </p>
686    *
687    * @param c The constructor to search.
688    * @param traversals The traversal options.
689    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
690    */
691   public List<AnnotationInfo<? extends Annotation>> find(ConstructorInfo c, AnnotationTraversal...traversals) {
692      assertArgNotNull("c", c);
693      return cache.get(null, c, traversals);
694   }
695
696   /**
697    * Finds all annotations from a field using configurable traversal options, without filtering by annotation type.
698    *
699    * <p>
700    * This method provides a flexible, stream-based API for traversing all field annotations without creating intermediate lists.
701    * Unlike {@link #find(Class, FieldInfo, AnnotationTraversal...)}, this method does not filter by annotation type.
702    *
703    * <h5 class='section'>Examples:</h5>
704    * <p class='bjava'>
705    *    <jc>// Get all annotations from field</jc>
706    *    Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s1</jv> =
707    *       find(<jv>fi</jv>, SELF);
708    * </p>
709    *
710    * @param f The field to search.
711    * @param traversals The traversal options.
712    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
713    */
714   public List<AnnotationInfo<? extends Annotation>> find(FieldInfo f, AnnotationTraversal...traversals) {
715      assertArgNotNull("f", f);
716      return cache.get(null, f, traversals);
717   }
718
719   /**
720    * Finds all annotations from a method using configurable traversal options, without filtering by annotation type.
721    *
722    * <p>
723    * This method provides a flexible API for traversing all method annotations.
724    * Unlike {@link #find(Class, MethodInfo, AnnotationTraversal...)}, this method does not filter by annotation type.
725    *
726    * <h5 class='section'>Examples:</h5>
727    * <p class='bjava'>
728    *    <jc>// Get all annotations from method and matching parent methods</jc>
729    *    List&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>l1</jv> =
730    *       find(<jv>mi</jv>, SELF, MATCHING_METHODS);
731    *
732    *    <jc>// Get all annotations from method, matching methods, and return type</jc>
733    *    List&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>l2</jv> =
734    *       find(<jv>mi</jv>, SELF, MATCHING_METHODS, RETURN_TYPE);
735    * </p>
736    *
737    * @param m The method to search.
738    * @param traversals The traversal options.
739    * @return A list of {@link AnnotationInfo} objects. Never <jk>null</jk>.
740    */
741   public List<AnnotationInfo<? extends Annotation>> find(MethodInfo m, AnnotationTraversal...traversals) {
742      assertArgNotNull("m", m);
743      return cache.get(null, m, traversals);
744   }
745
746   /**
747    * Finds all annotations from a parameter using configurable traversal options, without filtering by annotation type.
748    *
749    * <p>
750    * This method provides a flexible, stream-based API for traversing all parameter annotations without creating intermediate lists.
751    * Unlike {@link #find(Class, ParameterInfo, AnnotationTraversal...)}, this method does not filter by annotation type.
752    *
753    * <h5 class='section'>Supported Traversal Types:</h5>
754    * <ul>
755    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this parameter
756    *    <li>{@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS} - Matching parameters in parent methods/constructors (child-to-parent)
757    *    <li>{@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE} - The parameter's type hierarchy (includes class parents and package)
758    * </ul>
759    *
760    * <p>
761    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}
762    *
763    * <h5 class='section'>Examples:</h5>
764    * <p class='bjava'>
765    *    <jc>// Get all annotations from parameter, matching parameters, and parameter type</jc>
766    *    Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s1</jv> =
767    *       find(<jv>pi</jv>, SELF, MATCHING_PARAMETERS, PARAMETER_TYPE);
768    *
769    *    <jc>// Just get annotations from this parameter</jc>
770    *    Stream&lt;AnnotationInfo&lt;Annotation&gt;&gt; <jv>s2</jv> =
771    *       find(<jv>pi</jv>, SELF);
772    * </p>
773    *
774    * @param p The parameter to search.
775    * @param traversals
776    *    The traversal options. If not specified, defaults to {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}.
777    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS}, {@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE}
778    * @return A list of {@link AnnotationInfo} objects in child-to-parent order. Never <jk>null</jk>.
779    */
780   public List<AnnotationInfo<? extends Annotation>> find(ParameterInfo p, AnnotationTraversal...traversals) {
781      assertArgNotNull("p", p);
782      return cache.get(null, p, traversals);
783   }
784
785   /**
786    * Checks if a class has the specified annotation.
787    *
788    * <p>
789    * This is a convenience method equivalent to:
790    * <p class='bjava'>
791    *    find(<jv>type</jv>, <jv>clazz</jv>, <jv>traversals</jv>).findFirst().isPresent()
792    * </p>
793    *
794    * <h5 class='section'>Supported Traversal Types:</h5>
795    * <ul>
796    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this class
797    *    <li>{@link AnnotationTraversal#PARENTS PARENTS} - Parent classes and interfaces (child-to-parent order)
798    *    <li>{@link AnnotationTraversal#PACKAGE PACKAGE} - The package annotations
799    * </ul>
800    *
801    * <p>
802    * <b>Default:</b> If no traversals are specified, defaults to: {@code PARENTS, PACKAGE}
803    * <br>Note: {@code PARENTS} includes the class itself plus all parent classes and interfaces.
804    *
805    * <h5 class='section'>Example:</h5>
806    * <p class='bjava'>
807    *    <jc>// Check if class has @MyAnnotation anywhere in hierarchy</jc>
808    *    <jk>boolean</jk> <jv>hasIt</jv> = has(MyAnnotation.<jk>class</jk>, <jv>ci</jv>);
809    *
810    *    <jc>// Check only on the class itself</jc>
811    *    <jk>boolean</jk> <jv>hasIt2</jv> = has(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF);
812    * </p>
813    *
814    * @param <A> The annotation type.
815    * @param type The annotation type to search for.
816    * @param c The class to search.
817    * @param traversals
818    *    The traversal options. If not specified, defaults to {@code SELF, PARENTS, PACKAGE}.
819    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link AnnotationTraversal#PARENTS PARENTS}, {@link AnnotationTraversal#PACKAGE PACKAGE}
820    * @return <jk>true</jk> if the annotation is found, <jk>false</jk> otherwise.
821    */
822   public <A extends Annotation> boolean has(Class<A> type, ClassInfo c, AnnotationTraversal...traversals) {
823      return ! find(type, c, traversals).isEmpty();
824   }
825
826   /**
827    * Checks if a constructor has the specified annotation.
828    *
829    * <p>
830    * This is a convenience method equivalent to:
831    * <p class='bjava'>
832    *    find(<jv>type</jv>, <jv>constructor</jv>, <jv>traversals</jv>).findFirst().isPresent()
833    * </p>
834    *
835    * <h5 class='section'>Supported Traversal Types:</h5>
836    * <ul>
837    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this constructor
838    * </ul>
839    *
840    * <p>
841    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF}
842    *
843    * <h5 class='section'>Example:</h5>
844    * <p class='bjava'>
845    *    <jc>// Check if constructor has @MyAnnotation</jc>
846    *    <jk>boolean</jk> <jv>hasIt</jv> = has(MyAnnotation.<jk>class</jk>, <jv>ci</jv>);
847    * </p>
848    *
849    * @param <A> The annotation type.
850    * @param type The annotation type to search for.
851    * @param c The constructor to search.
852    * @param traversals
853    *    The traversal options. If not specified, defaults to {@code SELF}.
854    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}
855    * @return <jk>true</jk> if the annotation is found, <jk>false</jk> otherwise.
856    */
857   public <A extends Annotation> boolean has(Class<A> type, ConstructorInfo c, AnnotationTraversal...traversals) {
858      return ! find(type, c, traversals).isEmpty();
859   }
860
861   /**
862    * Checks if a field has the specified annotation.
863    *
864    * <p>
865    * This is a convenience method equivalent to:
866    * <p class='bjava'>
867    *    find(<jv>type</jv>, <jv>field</jv>, <jv>traversals</jv>).findFirst().isPresent()
868    * </p>
869    *
870    * <h5 class='section'>Supported Traversal Types:</h5>
871    * <ul>
872    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this field
873    * </ul>
874    *
875    * <p>
876    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF}
877    *
878    * <h5 class='section'>Example:</h5>
879    * <p class='bjava'>
880    *    <jc>// Check if field has @MyAnnotation</jc>
881    *    <jk>boolean</jk> <jv>hasIt</jv> = has(MyAnnotation.<jk>class</jk>, <jv>fi</jv>);
882    * </p>
883    *
884    * @param <A> The annotation type.
885    * @param type The annotation type to search for.
886    * @param f The field to search.
887    * @param traversals
888    *    The traversal options. If not specified, defaults to {@code SELF}.
889    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}
890    * @return <jk>true</jk> if the annotation is found, <jk>false</jk> otherwise.
891    */
892   public <A extends Annotation> boolean has(Class<A> type, FieldInfo f, AnnotationTraversal...traversals) {
893      return ! find(type, f, traversals).isEmpty();
894   }
895
896   /**
897    * Checks if a method has the specified annotation.
898    *
899    * <p>
900    * This is a convenience method equivalent to:
901    * <p class='bjava'>
902    *    find(<jv>type</jv>, <jv>method</jv>, <jv>traversals</jv>).findFirst().isPresent()
903    * </p>
904    *
905    * <h5 class='section'>Supported Traversal Types:</h5>
906    * <ul>
907    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this method
908    *    <li>{@link AnnotationTraversal#MATCHING_METHODS MATCHING_METHODS} - Matching methods in parent classes (child-to-parent)
909    *    <li>{@link AnnotationTraversal#RETURN_TYPE RETURN_TYPE} - The return type hierarchy (includes class parents and package)
910    *    <li>{@link AnnotationTraversal#PACKAGE PACKAGE} - The declaring class's package annotations
911    * </ul>
912    *
913    * <p>
914    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF, MATCHING_METHODS, RETURN_TYPE, PACKAGE}
915    *
916    * <h5 class='section'>Example:</h5>
917    * <p class='bjava'>
918    *    <jc>// Check if method has @MyAnnotation anywhere in hierarchy</jc>
919    *    <jk>boolean</jk> <jv>hasIt</jv> = has(MyAnnotation.<jk>class</jk>, <jv>mi</jv>);
920    *
921    *    <jc>// Check only on the method itself</jc>
922    *    <jk>boolean</jk> <jv>hasIt2</jv> = has(MyAnnotation.<jk>class</jk>, <jv>mi</jv>, SELF);
923    * </p>
924    *
925    * @param <A> The annotation type.
926    * @param type The annotation type to search for.
927    * @param m The method to search.
928    * @param traversals
929    *    The traversal options. If not specified, defaults to {@code SELF, MATCHING_METHODS, RETURN_TYPE, PACKAGE}.
930    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link AnnotationTraversal#MATCHING_METHODS MATCHING_METHODS}, {@link AnnotationTraversal#RETURN_TYPE RETURN_TYPE}, {@link AnnotationTraversal#PACKAGE PACKAGE}
931    * @return <jk>true</jk> if the annotation is found, <jk>false</jk> otherwise.
932    */
933   public <A extends Annotation> boolean has(Class<A> type, MethodInfo m, AnnotationTraversal...traversals) {
934      return ! find(type, m, traversals).isEmpty();
935   }
936
937   /**
938    * Checks if a parameter has the specified annotation.
939    *
940    * <p>
941    * This is a convenience method equivalent to:
942    * <p class='bjava'>
943    *    find(<jv>type</jv>, <jv>parameter</jv>, <jv>traversals</jv>).findFirst().isPresent()
944    * </p>
945    *
946    * <h5 class='section'>Supported Traversal Types:</h5>
947    * <ul>
948    *    <li>{@link AnnotationTraversal#SELF SELF} - Annotations declared directly on this parameter
949    *    <li>{@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS} - Matching parameters in parent methods/constructors (child-to-parent)
950    *    <li>{@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE} - The parameter's type hierarchy (includes class parents and package)
951    * </ul>
952    *
953    * <p>
954    * <b>Default:</b> If no traversals are specified, defaults to: {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}
955    *
956    * <h5 class='section'>Example:</h5>
957    * <p class='bjava'>
958    *    <jc>// Check if parameter has @MyAnnotation anywhere in hierarchy</jc>
959    *    <jk>boolean</jk> <jv>hasIt</jv> = has(MyAnnotation.<jk>class</jk>, <jv>pi</jv>);
960    *
961    *    <jc>// Check only on the parameter itself</jc>
962    *    <jk>boolean</jk> <jv>hasIt2</jv> = has(MyAnnotation.<jk>class</jk>, <jv>pi</jv>, SELF);
963    * </p>
964    *
965    * @param <A> The annotation type.
966    * @param type The annotation type to search for.
967    * @param p The parameter to search.
968    * @param traversals
969    *    The traversal options. If not specified, defaults to {@code SELF, MATCHING_PARAMETERS, PARAMETER_TYPE}.
970    *    <br>Valid values: {@link AnnotationTraversal#SELF SELF}, {@link AnnotationTraversal#MATCHING_PARAMETERS MATCHING_PARAMETERS}, {@link AnnotationTraversal#PARAMETER_TYPE PARAMETER_TYPE}
971    * @return <jk>true</jk> if the annotation is found, <jk>false</jk> otherwise.
972    */
973   public <A extends Annotation> boolean has(Class<A> type, ParameterInfo p, AnnotationTraversal...traversals) {
974      return ! find(type, p, traversals).isEmpty();
975   }
976
977   /**
978    * Computes and caches the complete list of annotations for a given type, class, and traversal combination.
979    * This is the supplier function for the findCache.
980    */
981   private List load(Class<?> type, ElementInfo element, AnnotationTraversal[] traversals) {
982
983      if (type != null) {
984         return cache.get(null, element, traversals).stream().filter(x -> ((AnnotationInfo)x).isType(type)).toList();
985      }
986
987      var l = new ArrayList();
988
989      List<AnnotationTraversal> t;
990      if (traversals.length > 0)
991         t = l(traversals);
992      else if (element instanceof ClassInfo)
993         t = l(a(PARENTS, PACKAGE));
994      else if (element instanceof MethodInfo)
995         t = l(a(SELF, MATCHING_METHODS, DECLARING_CLASS, RETURN_TYPE, PACKAGE));
996      else if (element instanceof FieldInfo || element instanceof ConstructorInfo)
997         t = l(a(SELF));
998      else {
999         assertType(ParameterInfo.class, element, () -> unsupportedOp());
1000         t = l(a(SELF, MATCHING_PARAMETERS, PARAMETER_TYPE));
1001      }
1002
1003      if (element instanceof ClassInfo element2) {
1004         if (t.contains(SELF)) {
1005            l.addAll(runtimeCache.get(element2.inner()));
1006            l.addAll(element2.getDeclaredAnnotations());
1007         }
1008         if (t.contains(PARENTS)) {
1009            for (var p : element2.getParentsAndInterfaces()) {
1010               l.addAll(runtimeCache.get(p.inner()));
1011               l.addAll(p.getDeclaredAnnotations());
1012            }
1013         }
1014         if (t.contains(PACKAGE)) {
1015            if (element2.getPackage() != null)
1016               l.addAll(element2.getPackage().getAnnotations());
1017         }
1018      } else if (element instanceof MethodInfo element3) {
1019         if (t.contains(SELF)) {
1020            l.addAll(runtimeCache.get(element3.inner()));
1021            l.addAll(element3.getDeclaredAnnotations());
1022         }
1023         if (t.contains(MATCHING_METHODS)) {
1024            for (var m : element3.getMatchingMethods().stream().skip(1).toList()) {
1025               l.addAll(runtimeCache.get(m.inner()));
1026               l.addAll(m.getDeclaredAnnotations());
1027            }
1028         }
1029         if (t.contains(DECLARING_CLASS)) {
1030            l.addAll(find(element3.getDeclaringClass(), a(PARENTS)));
1031         }
1032         if (t.contains(RETURN_TYPE)) {
1033            l.addAll(find(element3.getReturnType().unwrap(Value.class, Optional.class), a(PARENTS)));
1034         }
1035         if (t.contains(PACKAGE)) {
1036            if (element3.getDeclaringClass().getPackage() != null)
1037               l.addAll(element3.getDeclaringClass().getPackage().getAnnotations());
1038         }
1039      } else if (element instanceof FieldInfo element4) {
1040         if (t.contains(SELF)) {
1041            l.addAll(runtimeCache.get(element4.inner()));
1042            l.addAll(element4.getAnnotations());
1043         }
1044      } else if (element instanceof ConstructorInfo element5) {
1045         if (t.contains(SELF)) {
1046            l.addAll(runtimeCache.get(element5.inner()));
1047            l.addAll(element5.getDeclaredAnnotations());
1048         }
1049      } else if (element instanceof ParameterInfo element6) {
1050         if (t.contains(SELF)) {
1051            l.addAll(element6.getAnnotations());
1052         }
1053         if (t.contains(MATCHING_PARAMETERS)) {
1054            for (var p : element6.getMatchingParameters().stream().skip(1).toList()) {
1055               l.addAll(p.getAnnotations());
1056            }
1057         }
1058         if (t.contains(PARAMETER_TYPE)) {
1059            l.addAll(find(element6.getParameterType().unwrap(Value.class, Optional.class), a(PARENTS, PACKAGE)));
1060         }
1061      }
1062
1063      return l;
1064   }
1065
1066   private List load(Object o) {
1067      if (o instanceof Class o2) {
1068         var ci = ClassInfo.of(o2);
1069         return annotationMap == null ? liste() : annotationMap.find(ci.inner()).map(a -> ai(ci, a)).toList();
1070      }
1071      if (o instanceof Method o2) {
1072         var mi = info(o2);
1073         return annotationMap == null ? liste() : annotationMap.find(mi.inner()).map(a -> ai(mi, a)).toList();
1074      }
1075      if (o instanceof Field o2) {
1076         var fi = info(o2);
1077         return annotationMap == null ? liste() : annotationMap.find(fi.inner()).map(a -> ai(fi, a)).toList();
1078      }
1079      if (o instanceof Constructor o2) {
1080         var ci = info(o2);
1081         return annotationMap == null ? liste() : annotationMap.find(ci.inner()).map(a -> ai(ci, a)).toList();
1082      }
1083      throw unsupportedOp();
1084   }
1085}