@@ -45,14 +45,16 @@ public class AnnotatedElementUtils {
45
45
* <em>present</em> on the annotation (of the specified
46
46
* {@code annotationType}) on the supplied {@link AnnotatedElement}.
47
47
*
48
- * <p>This method also finds all meta-annotations in the annotation
49
- * hierarchy above the specified annotation.
48
+ * <p>This method finds all meta-annotations in the annotation hierarchy
49
+ * above the specified annotation.
50
50
*
51
51
* @param element the annotated element; never {@code null}
52
52
* @param annotationType the annotation type on which to find
53
53
* meta-annotations; never {@code null}
54
54
* @return the names of all meta-annotations present on the annotation,
55
55
* or {@code null} if not found
56
+ * @see #getMetaAnnotationTypes(AnnotatedElement, String)
57
+ * @see #hasMetaAnnotationTypes
56
58
*/
57
59
public static Set <String > getMetaAnnotationTypes (AnnotatedElement element ,
58
60
Class <? extends Annotation > annotationType ) {
@@ -65,47 +67,66 @@ public static Set<String> getMetaAnnotationTypes(AnnotatedElement element,
65
67
* <em>present</em> on the annotation (of the specified
66
68
* {@code annotationType}) on the supplied {@link AnnotatedElement}.
67
69
*
68
- * <p>This method also finds all meta-annotations in the annotation
69
- * hierarchy above the specified annotation.
70
+ * <p>This method finds all meta-annotations in the annotation hierarchy
71
+ * above the specified annotation.
70
72
*
71
73
* @param element the annotated element; never {@code null}
72
74
* @param annotationType the fully qualified class name of the annotation
73
75
* type on which to find meta-annotations; never {@code null} or empty
74
76
* @return the names of all meta-annotations present on the annotation,
75
77
* or {@code null} if not found
78
+ * @see #getMetaAnnotationTypes(AnnotatedElement, Class)
79
+ * @see #hasMetaAnnotationTypes
76
80
*/
77
81
public static Set <String > getMetaAnnotationTypes (AnnotatedElement element , String annotationType ) {
78
82
Assert .notNull (element , "AnnotatedElement must not be null" );
79
83
Assert .hasText (annotationType , "annotationType must not be null or empty" );
80
84
81
85
final Set <String > types = new LinkedHashSet <String >();
82
86
83
- processWithGetSemantics (element , annotationType , new SimpleAnnotationProcessor <Object >() {
84
- @ Override
85
- public Object process (Annotation annotation , int metaDepth ) {
86
- if (metaDepth > 0 ) {
87
- types .add (annotation .annotationType ().getName ());
88
- }
89
- return null ;
87
+ try {
88
+ Annotation annotation = getAnnotation (element , annotationType );
89
+ if (annotation != null ) {
90
+ processWithGetSemantics (annotation .annotationType (), annotationType , new SimpleAnnotationProcessor <Object >() {
91
+
92
+ @ Override
93
+ public Object process (Annotation annotation , int metaDepth ) {
94
+ types .add (annotation .annotationType ().getName ());
95
+ return null ;
96
+ }
97
+ }, new HashSet <AnnotatedElement >(), 1 );
90
98
}
91
- });
99
+ }
100
+ catch (Throwable ex ) {
101
+ throw new IllegalStateException ("Failed to introspect annotations on " + element , ex );
102
+ }
92
103
93
104
return (types .isEmpty () ? null : types );
94
105
}
95
106
96
107
/**
108
+ * Determine if the supplied {@link AnnotatedElement} is annotated with
109
+ * a <em>composed annotation</em> that is meta-annotated with an
110
+ * annotation of the specified {@code annotationType}.
111
+ *
112
+ * <p>This method finds all meta-annotations in the annotation hierarchy
113
+ * above the specified element.
114
+ *
97
115
* @param element the annotated element; never {@code null}
98
- * @param annotationType the fully qualified class name of the annotation
116
+ * @param annotationType the fully qualified class name of the meta- annotation
99
117
* type to find; never {@code null} or empty
118
+ * @return {@code true} if a matching meta-annotation is present
119
+ * @see #getMetaAnnotationTypes
100
120
*/
101
- public static boolean hasMetaAnnotationTypes (AnnotatedElement element , String annotationType ) {
121
+ public static boolean hasMetaAnnotationTypes (AnnotatedElement element , final String annotationType ) {
102
122
Assert .notNull (element , "AnnotatedElement must not be null" );
103
123
Assert .hasText (annotationType , "annotationType must not be null or empty" );
104
124
105
125
return Boolean .TRUE .equals (processWithGetSemantics (element , annotationType , new SimpleAnnotationProcessor <Boolean >() {
106
126
@ Override
107
127
public Boolean process (Annotation annotation , int metaDepth ) {
108
- if (metaDepth > 0 ) {
128
+ boolean found = annotation .annotationType ().getName ().equals (annotationType );
129
+ if (found && (metaDepth > 0 )) {
109
130
return Boolean .TRUE ;
110
131
}
111
132
return null ;
@@ -114,18 +135,27 @@ public Boolean process(Annotation annotation, int metaDepth) {
114
135
}
115
136
116
137
/**
138
+ * Determine if an annotation of the specified {@code annotationType}
139
+ * is <em>present</em> on the supplied {@link AnnotatedElement} or
140
+ * within the annotation hierarchy above the specified element.
141
+ *
142
+ * <p>If this method returns {@code true}, then {@link #getAnnotationAttributes}
143
+ * will return a non-null value.
144
+ *
117
145
* @param element the annotated element; never {@code null}
118
146
* @param annotationType the fully qualified class name of the annotation
119
147
* type to find; never {@code null} or empty
148
+ * @return {@code true} if a matching annotation is present
120
149
*/
121
- public static boolean isAnnotated (AnnotatedElement element , String annotationType ) {
150
+ public static boolean isAnnotated (AnnotatedElement element , final String annotationType ) {
122
151
Assert .notNull (element , "AnnotatedElement must not be null" );
123
152
Assert .hasText (annotationType , "annotationType must not be null or empty" );
124
153
125
154
return Boolean .TRUE .equals (processWithGetSemantics (element , annotationType , new SimpleAnnotationProcessor <Boolean >() {
126
155
@ Override
127
156
public Boolean process (Annotation annotation , int metaDepth ) {
128
- return Boolean .TRUE ;
157
+ boolean found = annotation .annotationType ().getName ().equals (annotationType );
158
+ return (found ? Boolean .TRUE : null );
129
159
}
130
160
}));
131
161
}
@@ -167,7 +197,7 @@ public static AnnotationAttributes getAnnotationAttributes(AnnotatedElement elem
167
197
*/
168
198
public static AnnotationAttributes getAnnotationAttributes (AnnotatedElement element , String annotationType ,
169
199
boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
170
- return processWithGetSemantics (element , annotationType , new MergeAnnotationAttributesProcessor (
200
+ return processWithGetSemantics (element , annotationType , new MergeAnnotationAttributesProcessor (annotationType ,
171
201
classValuesAsString , nestedAnnotationsAsMap ));
172
202
}
173
203
@@ -269,7 +299,7 @@ private static AnnotationAttributes findAnnotationAttributes(AnnotatedElement el
269
299
270
300
return processWithFindSemantics (element , annotationType , searchOnInterfaces , searchOnSuperclasses ,
271
301
searchOnMethodsInInterfaces , searchOnMethodsInSuperclasses , new MergeAnnotationAttributesProcessor (
272
- classValuesAsString , nestedAnnotationsAsMap ));
302
+ annotationType , classValuesAsString , nestedAnnotationsAsMap ));
273
303
}
274
304
275
305
/**
@@ -376,29 +406,20 @@ private static <T> T processWithGetSemantics(AnnotatedElement element, String an
376
406
377
407
// Search in local annotations
378
408
for (Annotation annotation : annotations ) {
379
- // TODO Add check for !isInJavaLangAnnotationPackage()
380
- // if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)
381
- // && (annotation.annotationType().getName().equals(annotationType) ||
382
- // metaDepth > 0)) {
409
+ // TODO Test for !AnnotationUtils.isInJavaLangAnnotationPackage(annotation)
383
410
if (annotation .annotationType ().getName ().equals (annotationType ) || metaDepth > 0 ) {
384
411
T result = processor .process (annotation , metaDepth );
385
412
if (result != null ) {
386
413
return result ;
387
414
}
388
- result = processWithGetSemantics (annotation .annotationType (), annotationType , processor ,
389
- visited , metaDepth + 1 );
390
- if (result != null ) {
391
- processor .postProcess (annotation , result );
392
- return result ;
393
- }
394
415
}
395
416
}
396
417
397
418
// Search in meta annotations on local annotations
398
419
for (Annotation annotation : annotations ) {
399
420
if (!AnnotationUtils .isInJavaLangAnnotationPackage (annotation )) {
400
421
T result = processWithGetSemantics (annotation .annotationType (), annotationType , processor ,
401
- visited , metaDepth );
422
+ visited , metaDepth + 1 );
402
423
if (result != null ) {
403
424
processor .postProcess (annotation , result );
404
425
return result ;
@@ -492,13 +513,6 @@ private static <T> T processWithFindSemantics(AnnotatedElement element, String a
492
513
if (result != null ) {
493
514
return result ;
494
515
}
495
- result = processWithFindSemantics (annotation .annotationType (), annotationType ,
496
- searchOnInterfaces , searchOnSuperclasses , searchOnMethodsInInterfaces ,
497
- searchOnMethodsInSuperclasses , processor , visited , metaDepth + 1 );
498
- if (result != null ) {
499
- processor .postProcess (annotation , result );
500
- return result ;
501
- }
502
516
}
503
517
}
504
518
@@ -507,7 +521,7 @@ private static <T> T processWithFindSemantics(AnnotatedElement element, String a
507
521
if (!AnnotationUtils .isInJavaLangAnnotationPackage (annotation )) {
508
522
T result = processWithFindSemantics (annotation .annotationType (), annotationType ,
509
523
searchOnInterfaces , searchOnSuperclasses , searchOnMethodsInInterfaces ,
510
- searchOnMethodsInSuperclasses , processor , visited , metaDepth );
524
+ searchOnMethodsInSuperclasses , processor , visited , metaDepth + 1 );
511
525
if (result != null ) {
512
526
processor .postProcess (annotation , result );
513
527
return result ;
@@ -636,6 +650,14 @@ private static <T> T searchOnInterfaces(Method method, String annotationType, bo
636
650
return null ;
637
651
}
638
652
653
+ private static Annotation getAnnotation (AnnotatedElement element , String annotationType ) {
654
+ for (Annotation annotation : element .getAnnotations ()) {
655
+ if (annotation .annotationType ().getName ().equals (annotationType )) {
656
+ return annotation ;
657
+ }
658
+ }
659
+ return null ;
660
+ }
639
661
640
662
/**
641
663
* Callback interface that is used to process a target annotation (or
@@ -707,18 +729,21 @@ public final void postProcess(Annotation annotation, T result) {
707
729
*/
708
730
private static class MergeAnnotationAttributesProcessor implements Processor <AnnotationAttributes > {
709
731
732
+ private final String annotationType ;
710
733
private final boolean classValuesAsString ;
711
734
private final boolean nestedAnnotationsAsMap ;
712
735
713
736
714
- MergeAnnotationAttributesProcessor (boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
737
+ MergeAnnotationAttributesProcessor (String annotationType , boolean classValuesAsString , boolean nestedAnnotationsAsMap ) {
738
+ this .annotationType = annotationType ;
715
739
this .classValuesAsString = classValuesAsString ;
716
740
this .nestedAnnotationsAsMap = nestedAnnotationsAsMap ;
717
741
}
718
742
719
743
@ Override
720
744
public AnnotationAttributes process (Annotation annotation , int metaDepth ) {
721
- return AnnotationUtils .getAnnotationAttributes (annotation , classValuesAsString , nestedAnnotationsAsMap );
745
+ boolean found = annotation .annotationType ().getName ().equals (annotationType );
746
+ return (!found ? null : AnnotationUtils .getAnnotationAttributes (annotation , classValuesAsString , nestedAnnotationsAsMap ));
722
747
}
723
748
724
749
@ Override
0 commit comments