@@ -451,6 +451,38 @@ public static <A extends Annotation> A getMergedAnnotation(AnnotatedElement elem
451
451
return AnnotationUtils .synthesizeAnnotation (attributes , annotationType , element );
452
452
}
453
453
454
+ /**
455
+ * Get <strong>all</strong> annotations of the specified {@code annotationType}
456
+ * within the annotation hierarchy <em>above</em> the supplied {@code element};
457
+ * and for each annotation found, merge that annotation's attributes with
458
+ * <em>matching</em> attributes from annotations in lower levels of the annotation
459
+ * hierarchy and synthesize the results back into an annotation of the specified
460
+ * {@code annotationType}.
461
+ * <p>{@link AliasFor @AliasFor} semantics are fully supported, both within a
462
+ * single annotation and within annotation hierarchies.
463
+ * <p>This method follows <em>get semantics</em> as described in the
464
+ * {@linkplain AnnotatedElementUtils class-level javadoc}.
465
+ * @param element the annotated element; never {@code null}
466
+ * @param annotationType the annotation type to find; never {@code null}
467
+ * @return the set of all merged, synthesized {@code Annotations} found, or an empty
468
+ * set if none were found
469
+ * @since 4.3
470
+ * @see #getMergedAnnotation(AnnotatedElement, Class)
471
+ * @see #getAllAnnotationAttributes(AnnotatedElement, String)
472
+ * @see #findAllMergedAnnotations(AnnotatedElement, Class)
473
+ */
474
+ public static <A extends Annotation > Set <A > getAllMergedAnnotations (AnnotatedElement element ,
475
+ Class <A > annotationType ) {
476
+
477
+ Assert .notNull (element , "AnnotatedElement must not be null" );
478
+ Assert .notNull (annotationType , "annotationType must not be null" );
479
+
480
+ MergedAnnotationAttributesProcessor processor =
481
+ new MergedAnnotationAttributesProcessor (annotationType , null , false , false , true );
482
+ searchWithGetSemantics (element , annotationType , null , processor );
483
+ return postProcessAndSynthesizeAggregatedResults (element , annotationType , processor .getAggregatedResults ());
484
+ }
485
+
454
486
/**
455
487
* Get the annotation attributes of <strong>all</strong> annotations of the specified
456
488
* {@code annotationName} in the annotation hierarchy above the supplied
@@ -688,7 +720,7 @@ public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement ele
688
720
* within the annotation hierarchy <em>above</em> the supplied {@code element};
689
721
* and for each annotation found, merge that annotation's attributes with
690
722
* <em>matching</em> attributes from annotations in lower levels of the annotation
691
- * hierarchy and synthesize the result back into an annotation of the specified
723
+ * hierarchy and synthesize the results back into an annotation of the specified
692
724
* {@code annotationType}.
693
725
* <p>{@link AliasFor @AliasFor} semantics are fully supported, both within a
694
726
* single annotation and within annotation hierarchies.
@@ -700,6 +732,7 @@ public static <A extends Annotation> A findMergedAnnotation(AnnotatedElement ele
700
732
* set if none were found
701
733
* @since 4.3
702
734
* @see #findMergedAnnotation(AnnotatedElement, Class)
735
+ * @see #getAllMergedAnnotations(AnnotatedElement, Class)
703
736
*/
704
737
public static <A extends Annotation > Set <A > findAllMergedAnnotations (AnnotatedElement element ,
705
738
Class <A > annotationType ) {
@@ -710,21 +743,15 @@ public static <A extends Annotation> Set<A> findAllMergedAnnotations(AnnotatedEl
710
743
MergedAnnotationAttributesProcessor processor =
711
744
new MergedAnnotationAttributesProcessor (annotationType , null , false , false , true );
712
745
searchWithFindSemantics (element , annotationType , annotationType .getName (), processor );
713
-
714
- Set <A > annotations = new LinkedHashSet <A >();
715
- for (AnnotationAttributes attributes : processor .getAggregatedResults ()) {
716
- AnnotationUtils .postProcessAnnotationAttributes (element , attributes , false , false );
717
- annotations .add (AnnotationUtils .synthesizeAnnotation (attributes , annotationType , element ));
718
- }
719
- return annotations ;
746
+ return postProcessAndSynthesizeAggregatedResults (element , annotationType , processor .getAggregatedResults ());
720
747
}
721
748
722
749
/**
723
750
* Find all <em>repeatable annotations</em> of the specified {@code annotationType}
724
751
* within the annotation hierarchy <em>above</em> the supplied {@code element};
725
752
* and for each annotation found, merge that annotation's attributes with
726
753
* <em>matching</em> attributes from annotations in lower levels of the annotation
727
- * hierarchy and synthesize the result back into an annotation of the specified
754
+ * hierarchy and synthesize the results back into an annotation of the specified
728
755
* {@code annotationType}.
729
756
* <p>The container type that holds the repeatable annotations will be looked up
730
757
* via {@link java.lang.annotation.Repeatable}.
@@ -754,7 +781,7 @@ public static <A extends Annotation> Set<A> findMergedRepeatableAnnotations(Anno
754
781
* within the annotation hierarchy <em>above</em> the supplied {@code element};
755
782
* and for each annotation found, merge that annotation's attributes with
756
783
* <em>matching</em> attributes from annotations in lower levels of the annotation
757
- * hierarchy and synthesize the result back into an annotation of the specified
784
+ * hierarchy and synthesize the results back into an annotation of the specified
758
785
* {@code annotationType}.
759
786
* <p>{@link AliasFor @AliasFor} semantics are fully supported, both within a
760
787
* single annotation and within annotation hierarchies.
@@ -791,13 +818,7 @@ public static <A extends Annotation> Set<A> findMergedRepeatableAnnotations(Anno
791
818
MergedAnnotationAttributesProcessor processor =
792
819
new MergedAnnotationAttributesProcessor (annotationType , null , false , false , true );
793
820
searchWithFindSemantics (element , annotationType , annotationType .getName (), containerType , processor );
794
-
795
- Set <A > annotations = new LinkedHashSet <A >();
796
- for (AnnotationAttributes attributes : processor .getAggregatedResults ()) {
797
- AnnotationUtils .postProcessAnnotationAttributes (element , attributes , false , false );
798
- annotations .add (AnnotationUtils .synthesizeAnnotation (attributes , annotationType , element ));
799
- }
800
- return annotations ;
821
+ return postProcessAndSynthesizeAggregatedResults (element , annotationType , processor .getAggregatedResults ());
801
822
}
802
823
803
824
/**
@@ -906,13 +927,18 @@ private static <T> T searchWithGetSemanticsInAnnotations(AnnotatedElement annota
906
927
907
928
// Search in annotations
908
929
for (Annotation annotation : annotations ) {
930
+ // Note: we only check for (metaDepth > 0) due to the nuances of getMetaAnnotationTypes().
909
931
if (!AnnotationUtils .isInJavaLangAnnotationPackage (annotation ) &&
910
- ((annotationType != null ? annotation .annotationType () == annotationType :
911
- annotation .annotationType ().getName ().equals (annotationName )) ||
912
- metaDepth > 0 )) {
932
+ ((annotation .annotationType () == annotationType
933
+ || annotation .annotationType ().getName ().equals (annotationName )) || metaDepth > 0 )) {
913
934
T result = processor .process (annotatedElement , annotation , metaDepth );
914
935
if (result != null ) {
915
- return result ;
936
+ if (processor .aggregates () && metaDepth == 0 ) {
937
+ processor .getAggregatedResults ().add (result );
938
+ }
939
+ else {
940
+ return result ;
941
+ }
916
942
}
917
943
}
918
944
}
@@ -924,7 +950,12 @@ private static <T> T searchWithGetSemanticsInAnnotations(AnnotatedElement annota
924
950
annotationName , processor , visited , metaDepth + 1 );
925
951
if (result != null ) {
926
952
processor .postProcess (annotatedElement , annotation , result );
927
- return result ;
953
+ if (processor .aggregates () && metaDepth == 0 ) {
954
+ processor .getAggregatedResults ().add (result );
955
+ }
956
+ else {
957
+ return result ;
958
+ }
928
959
}
929
960
}
930
961
}
@@ -1234,6 +1265,20 @@ private static void validateRepeatableContainerType(Class<? extends Annotation>
1234
1265
}
1235
1266
}
1236
1267
1268
+ /**
1269
+ * @since 4.3
1270
+ */
1271
+ private static <A extends Annotation > Set <A > postProcessAndSynthesizeAggregatedResults (AnnotatedElement element ,
1272
+ Class <A > annotationType , List <AnnotationAttributes > aggregatedResults ) {
1273
+
1274
+ Set <A > annotations = new LinkedHashSet <A >();
1275
+ for (AnnotationAttributes attributes : aggregatedResults ) {
1276
+ AnnotationUtils .postProcessAnnotationAttributes (element , attributes , false , false );
1277
+ annotations .add (AnnotationUtils .synthesizeAnnotation (attributes , annotationType , element ));
1278
+ }
1279
+ return annotations ;
1280
+ }
1281
+
1237
1282
1238
1283
/**
1239
1284
* Callback interface that is used to process annotations during a search.
@@ -1305,7 +1350,6 @@ private interface Processor<T> {
1305
1350
* Determine if this processor aggregates the results returned by {@link #process}.
1306
1351
* <p>If this method returns {@code true}, then {@link #getAggregatedResults()}
1307
1352
* must return a non-null value.
1308
- * <p>WARNING: aggregation is currently only supported for <em>find semantics</em>.
1309
1353
* @return {@code true} if this processor supports aggregated results
1310
1354
* @see #getAggregatedResults
1311
1355
* @since 4.3
@@ -1319,7 +1363,6 @@ private interface Processor<T> {
1319
1363
* responsible for asking this processor if it {@link #aggregates} results
1320
1364
* and then adding the post-processed results to the list returned by this
1321
1365
* method.
1322
- * <p>WARNING: aggregation is currently only supported for <em>find semantics</em>.
1323
1366
* @return the list of results aggregated by this processor; never
1324
1367
* {@code null} unless {@link #aggregates} returns {@code false}
1325
1368
* @see #aggregates
0 commit comments