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<AnnotationInfo<Bean>> <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<AnnotationInfo<Annotation>> <jv>annotations</jv> = <jv>provider</jv>.find(MyClass.<jk>class</jk>); 167 * 168 * <jc>// Find specific annotation type on a class</jc> 169 * Stream<AnnotationInfo<MyAnnotation>> <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<AnnotationInfo<MyAnnotation>> <jv>l1</jv> = 499 * find(MyAnnotation.<jk>class</jk>, <jv>ci</jv>, SELF); 500 * 501 * <jc>// Search class and parents</jc> 502 * List<AnnotationInfo<MyAnnotation>> <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<AnnotationInfo<MyAnnotation>> <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<AnnotationInfo<MyAnnotation>> <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<AnnotationInfo<MyAnnotation>> <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<AnnotationInfo<MyAnnotation>> <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<AnnotationInfo<MyAnnotation>> <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<AnnotationInfo<MyAnnotation>> <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<AnnotationInfo<MyAnnotation>> <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<AnnotationInfo<MyAnnotation>> <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<AnnotationInfo<Annotation>> <jv>l1</jv> = 657 * find(<jv>ci</jv>, SELF); 658 * 659 * <jc>// Get all annotations from class and parents</jc> 660 * List<AnnotationInfo<Annotation>> <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<AnnotationInfo<Annotation>> <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<AnnotationInfo<Annotation>> <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<AnnotationInfo<Annotation>> <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<AnnotationInfo<Annotation>> <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<AnnotationInfo<Annotation>> <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<AnnotationInfo<Annotation>> <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}