001/*
002 * Copyright 2002-2020 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.core.annotation;
018
019import java.lang.annotation.Annotation;
020import java.lang.annotation.Inherited;
021import java.lang.reflect.AnnotatedElement;
022import java.lang.reflect.Method;
023import java.util.Collection;
024import java.util.function.Predicate;
025import java.util.stream.Stream;
026
027import org.springframework.lang.Nullable;
028import org.springframework.util.Assert;
029
030/**
031 * Provides access to a collection of merged annotations, usually obtained
032 * from a source such as a {@link Class} or {@link Method}.
033 *
034 * <p>Each merged annotation represents a view where the attribute values may be
035 * "merged" from different source values, typically:
036 *
037 * <ul>
038 * <li>Explicit and Implicit {@link AliasFor @AliasFor} declarations on one or
039 * more attributes within the annotation</li>
040 * <li>Explicit {@link AliasFor @AliasFor} declarations for a meta-annotation</li>
041 * <li>Convention based attribute aliases for a meta-annotation</li>
042 * <li>From a meta-annotation declaration</li>
043 * </ul>
044 *
045 * <p>For example, a {@code @PostMapping} annotation might be defined as follows:
046 *
047 * <pre class="code">
048 * &#064;Retention(RetentionPolicy.RUNTIME)
049 * &#064;RequestMapping(method = RequestMethod.POST)
050 * public &#064;interface PostMapping {
051 *
052 *     &#064;AliasFor(attribute = "path")
053 *     String[] value() default {};
054 *
055 *     &#064;AliasFor(attribute = "value")
056 *     String[] path() default {};
057 * }
058 * </pre>
059 *
060 * <p>If a method is annotated with {@code @PostMapping("/home")} it will contain
061 * merged annotations for both {@code @PostMapping} and the meta-annotation
062 * {@code @RequestMapping}. The merged view of the {@code @RequestMapping}
063 * annotation will contain the following attributes:
064 *
065 * <p><table border="1">
066 * <tr>
067 * <th>Name</th>
068 * <th>Value</th>
069 * <th>Source</th>
070 * </tr>
071 * <tr>
072 * <td>value</td>
073 * <td>"/home"</td>
074 * <td>Declared in {@code @PostMapping}</td>
075 * </tr>
076 * <tr>
077 * <td>path</td>
078 * <td>"/home"</td>
079 * <td>Explicit {@code @AliasFor}</td>
080 * </tr>
081 * <tr>
082 * <td>method</td>
083 * <td>RequestMethod.POST</td>
084 * <td>Declared in meta-annotation</td>
085 * </tr>
086 * </table>
087 *
088 * <p>{@link MergedAnnotations} can be obtained {@linkplain #from(AnnotatedElement)
089 * from} any Java {@link AnnotatedElement}. They may also be used for sources that
090 * don't use reflection (such as those that directly parse bytecode).
091 *
092 * <p>Different {@linkplain SearchStrategy search strategies} can be used to locate
093 * related source elements that contain the annotations to be aggregated. For
094 * example, {@link SearchStrategy#TYPE_HIERARCHY} will search both superclasses and
095 * implemented interfaces.
096 *
097 * <p>From a {@link MergedAnnotations} instance you can either
098 * {@linkplain #get(String) get} a single annotation, or {@linkplain #stream()
099 * stream all annotations} or just those that match {@linkplain #stream(String)
100 * a specific type}. You can also quickly tell if an annotation
101 * {@linkplain #isPresent(String) is present}.
102 *
103 * <p>Here are some typical examples:
104 *
105 * <pre class="code">
106 * // is an annotation present or meta-present?
107 * mergedAnnotations.isPresent(ExampleAnnotation.class);
108 *
109 * // get the merged "value" attribute of ExampleAnnotation (either directly or
110 * // meta-present)
111 * mergedAnnotations.get(ExampleAnnotation.class).getString("value");
112 *
113 * // get all meta-annotations but no directly present annotations
114 * mergedAnnotations.stream().filter(MergedAnnotation::isMetaPresent);
115 *
116 * // get all ExampleAnnotation declarations (including any meta-annotations) and
117 * // print the merged "value" attributes
118 * mergedAnnotations.stream(ExampleAnnotation.class)
119 *     .map(mergedAnnotation -&gt; mergedAnnotation.getString("value"))
120 *     .forEach(System.out::println);
121 * </pre>
122 *
123 * <p><b>NOTE: The {@code MergedAnnotations} API and its underlying model have
124 * been designed for composable annotations in Spring's common component model,
125 * with a focus on attribute aliasing and meta-annotation relationships.</b>
126 * There is no support for retrieving plain Java annotations with this API;
127 * please use standard Java reflection or Spring's {@link AnnotationUtils}
128 * for simple annotation retrieval purposes.
129 *
130 * @author Phillip Webb
131 * @author Sam Brannen
132 * @since 5.2
133 * @see MergedAnnotation
134 * @see MergedAnnotationCollectors
135 * @see MergedAnnotationPredicates
136 * @see MergedAnnotationSelectors
137 */
138public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>> {
139
140        /**
141         * Determine if the specified annotation is either directly present or
142         * meta-present.
143         * <p>Equivalent to calling {@code get(annotationType).isPresent()}.
144         * @param annotationType the annotation type to check
145         * @return {@code true} if the annotation is present
146         */
147        <A extends Annotation> boolean isPresent(Class<A> annotationType);
148
149        /**
150         * Determine if the specified annotation is either directly present or
151         * meta-present.
152         * <p>Equivalent to calling {@code get(annotationType).isPresent()}.
153         * @param annotationType the fully qualified class name of the annotation type
154         * to check
155         * @return {@code true} if the annotation is present
156         */
157        boolean isPresent(String annotationType);
158
159        /**
160         * Determine if the specified annotation is directly present.
161         * <p>Equivalent to calling {@code get(annotationType).isDirectlyPresent()}.
162         * @param annotationType the annotation type to check
163         * @return {@code true} if the annotation is directly present
164         */
165        <A extends Annotation> boolean isDirectlyPresent(Class<A> annotationType);
166
167        /**
168         * Determine if the specified annotation is directly present.
169         * <p>Equivalent to calling {@code get(annotationType).isDirectlyPresent()}.
170         * @param annotationType the fully qualified class name of the annotation type
171         * to check
172         * @return {@code true} if the annotation is directly present
173         */
174        boolean isDirectlyPresent(String annotationType);
175
176        /**
177         * Get the {@linkplain MergedAnnotationSelectors#nearest() nearest} matching
178         * annotation or meta-annotation of the specified type, or
179         * {@link MergedAnnotation#missing()} if none is present.
180         * @param annotationType the annotation type to get
181         * @return a {@link MergedAnnotation} instance
182         */
183        <A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType);
184
185        /**
186         * Get the {@linkplain MergedAnnotationSelectors#nearest() nearest} matching
187         * annotation or meta-annotation of the specified type, or
188         * {@link MergedAnnotation#missing()} if none is present.
189         * @param annotationType the annotation type to get
190         * @param predicate a predicate that must match, or {@code null} if only
191         * type matching is required
192         * @return a {@link MergedAnnotation} instance
193         * @see MergedAnnotationPredicates
194         */
195        <A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType,
196                        @Nullable Predicate<? super MergedAnnotation<A>> predicate);
197
198        /**
199         * Get a matching annotation or meta-annotation of the specified type, or
200         * {@link MergedAnnotation#missing()} if none is present.
201         * @param annotationType the annotation type to get
202         * @param predicate a predicate that must match, or {@code null} if only
203         * type matching is required
204         * @param selector a selector used to choose the most appropriate annotation
205         * within an aggregate, or {@code null} to select the
206         * {@linkplain MergedAnnotationSelectors#nearest() nearest}
207         * @return a {@link MergedAnnotation} instance
208         * @see MergedAnnotationPredicates
209         * @see MergedAnnotationSelectors
210         */
211        <A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType,
212                        @Nullable Predicate<? super MergedAnnotation<A>> predicate,
213                        @Nullable MergedAnnotationSelector<A> selector);
214
215        /**
216         * Get the {@linkplain MergedAnnotationSelectors#nearest() nearest} matching
217         * annotation or meta-annotation of the specified type, or
218         * {@link MergedAnnotation#missing()} if none is present.
219         * @param annotationType the fully qualified class name of the annotation type
220         * to get
221         * @return a {@link MergedAnnotation} instance
222         */
223        <A extends Annotation> MergedAnnotation<A> get(String annotationType);
224
225        /**
226         * Get the {@linkplain MergedAnnotationSelectors#nearest() nearest} matching
227         * annotation or meta-annotation of the specified type, or
228         * {@link MergedAnnotation#missing()} if none is present.
229         * @param annotationType the fully qualified class name of the annotation type
230         * to get
231         * @param predicate a predicate that must match, or {@code null} if only
232         * type matching is required
233         * @return a {@link MergedAnnotation} instance
234         * @see MergedAnnotationPredicates
235         */
236        <A extends Annotation> MergedAnnotation<A> get(String annotationType,
237                        @Nullable Predicate<? super MergedAnnotation<A>> predicate);
238
239        /**
240         * Get a matching annotation or meta-annotation of the specified type, or
241         * {@link MergedAnnotation#missing()} if none is present.
242         * @param annotationType the fully qualified class name of the annotation type
243         * to get
244         * @param predicate a predicate that must match, or {@code null} if only
245         * type matching is required
246         * @param selector a selector used to choose the most appropriate annotation
247         * within an aggregate, or {@code null} to select the
248         * {@linkplain MergedAnnotationSelectors#nearest() nearest}
249         * @return a {@link MergedAnnotation} instance
250         * @see MergedAnnotationPredicates
251         * @see MergedAnnotationSelectors
252         */
253        <A extends Annotation> MergedAnnotation<A> get(String annotationType,
254                        @Nullable Predicate<? super MergedAnnotation<A>> predicate,
255                        @Nullable MergedAnnotationSelector<A> selector);
256
257        /**
258         * Stream all annotations and meta-annotations that match the specified
259         * type. The resulting stream follows the same ordering rules as
260         * {@link #stream()}.
261         * @param annotationType the annotation type to match
262         * @return a stream of matching annotations
263         */
264        <A extends Annotation> Stream<MergedAnnotation<A>> stream(Class<A> annotationType);
265
266        /**
267         * Stream all annotations and meta-annotations that match the specified
268         * type. The resulting stream follows the same ordering rules as
269         * {@link #stream()}.
270         * @param annotationType the fully qualified class name of the annotation type
271         * to match
272         * @return a stream of matching annotations
273         */
274        <A extends Annotation> Stream<MergedAnnotation<A>> stream(String annotationType);
275
276        /**
277         * Stream all annotations and meta-annotations contained in this collection.
278         * The resulting stream is ordered first by the
279         * {@linkplain MergedAnnotation#getAggregateIndex() aggregate index} and then
280         * by the annotation distance (with the closest annotations first). This ordering
281         * means that, for most use-cases, the most suitable annotations appear
282         * earliest in the stream.
283         * @return a stream of annotations
284         */
285        Stream<MergedAnnotation<Annotation>> stream();
286
287
288        /**
289         * Create a new {@link MergedAnnotations} instance containing all
290         * annotations and meta-annotations from the specified element. The
291         * resulting instance will not include any inherited annotations. If you
292         * want to include those as well you should use
293         * {@link #from(AnnotatedElement, SearchStrategy)} with an appropriate
294         * {@link SearchStrategy}.
295         * @param element the source element
296         * @return a {@link MergedAnnotations} instance containing the element's
297         * annotations
298         */
299        static MergedAnnotations from(AnnotatedElement element) {
300                return from(element, SearchStrategy.DIRECT);
301        }
302
303        /**
304         * Create a new {@link MergedAnnotations} instance containing all
305         * annotations and meta-annotations from the specified element and,
306         * depending on the {@link SearchStrategy}, related inherited elements.
307         * @param element the source element
308         * @param searchStrategy the search strategy to use
309         * @return a {@link MergedAnnotations} instance containing the merged
310         * element annotations
311         */
312        static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy) {
313                return from(element, searchStrategy, RepeatableContainers.standardRepeatables());
314        }
315
316        /**
317         * Create a new {@link MergedAnnotations} instance containing all
318         * annotations and meta-annotations from the specified element and,
319         * depending on the {@link SearchStrategy}, related inherited elements.
320         * @param element the source element
321         * @param searchStrategy the search strategy to use
322         * @param repeatableContainers the repeatable containers that may be used by
323         * the element annotations or the meta-annotations
324         * @return a {@link MergedAnnotations} instance containing the merged
325         * element annotations
326         */
327        static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy,
328                        RepeatableContainers repeatableContainers) {
329
330                return from(element, searchStrategy, repeatableContainers, AnnotationFilter.PLAIN);
331        }
332
333        /**
334         * Create a new {@link MergedAnnotations} instance containing all
335         * annotations and meta-annotations from the specified element and,
336         * depending on the {@link SearchStrategy}, related inherited elements.
337         * @param element the source element
338         * @param searchStrategy the search strategy to use
339         * @param repeatableContainers the repeatable containers that may be used by
340         * the element annotations or the meta-annotations
341         * @param annotationFilter an annotation filter used to restrict the
342         * annotations considered
343         * @return a {@link MergedAnnotations} instance containing the merged
344         * annotations for the supplied element
345         */
346        static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy,
347                        RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
348
349                Assert.notNull(repeatableContainers, "RepeatableContainers must not be null");
350                Assert.notNull(annotationFilter, "AnnotationFilter must not be null");
351                return TypeMappedAnnotations.from(element, searchStrategy, repeatableContainers, annotationFilter);
352        }
353
354        /**
355         * Create a new {@link MergedAnnotations} instance from the specified
356         * annotations.
357         * @param annotations the annotations to include
358         * @return a {@link MergedAnnotations} instance containing the annotations
359         * @see #from(Object, Annotation...)
360         */
361        static MergedAnnotations from(Annotation... annotations) {
362                return from(annotations, annotations);
363        }
364
365        /**
366         * Create a new {@link MergedAnnotations} instance from the specified
367         * annotations.
368         * @param source the source for the annotations. This source is used only
369         * for information and logging. It does not need to <em>actually</em>
370         * contain the specified annotations, and it will not be searched.
371         * @param annotations the annotations to include
372         * @return a {@link MergedAnnotations} instance containing the annotations
373         * @see #from(Annotation...)
374         * @see #from(AnnotatedElement)
375         */
376        static MergedAnnotations from(Object source, Annotation... annotations) {
377                return from(source, annotations, RepeatableContainers.standardRepeatables());
378        }
379
380        /**
381         * Create a new {@link MergedAnnotations} instance from the specified
382         * annotations.
383         * @param source the source for the annotations. This source is used only
384         * for information and logging. It does not need to <em>actually</em>
385         * contain the specified annotations, and it will not be searched.
386         * @param annotations the annotations to include
387         * @param repeatableContainers the repeatable containers that may be used by
388         * meta-annotations
389         * @return a {@link MergedAnnotations} instance containing the annotations
390         */
391        static MergedAnnotations from(Object source, Annotation[] annotations, RepeatableContainers repeatableContainers) {
392                return from(source, annotations, repeatableContainers, AnnotationFilter.PLAIN);
393        }
394
395        /**
396         * Create a new {@link MergedAnnotations} instance from the specified
397         * annotations.
398         * @param source the source for the annotations. This source is used only
399         * for information and logging. It does not need to <em>actually</em>
400         * contain the specified annotations, and it will not be searched.
401         * @param annotations the annotations to include
402         * @param repeatableContainers the repeatable containers that may be used by
403         * meta-annotations
404         * @param annotationFilter an annotation filter used to restrict the
405         * annotations considered
406         * @return a {@link MergedAnnotations} instance containing the annotations
407         */
408        static MergedAnnotations from(Object source, Annotation[] annotations,
409                        RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
410
411                Assert.notNull(repeatableContainers, "RepeatableContainers must not be null");
412                Assert.notNull(annotationFilter, "AnnotationFilter must not be null");
413                return TypeMappedAnnotations.from(source, annotations, repeatableContainers, annotationFilter);
414        }
415
416        /**
417         * Create a new {@link MergedAnnotations} instance from the specified
418         * collection of directly present annotations. This method allows a
419         * {@link MergedAnnotations} instance to be created from annotations that
420         * are not necessarily loaded using reflection. The provided annotations
421         * must all be {@link MergedAnnotation#isDirectlyPresent() directly present}
422         * and must have an {@link MergedAnnotation#getAggregateIndex() aggregate
423         * index} of {@code 0}.
424         * <p>The resulting {@link MergedAnnotations} instance will contain both the
425         * specified annotations, and any meta-annotations that can be read using
426         * reflection.
427         * @param annotations the annotations to include
428         * @return a {@link MergedAnnotations} instance containing the annotations
429         * @see MergedAnnotation#of(ClassLoader, Object, Class, java.util.Map)
430         */
431        static MergedAnnotations of(Collection<MergedAnnotation<?>> annotations) {
432                return MergedAnnotationsCollection.of(annotations);
433        }
434
435
436        /**
437         * Search strategies supported by
438         * {@link MergedAnnotations#from(AnnotatedElement, SearchStrategy)}.
439         *
440         * <p>Each strategy creates a different set of aggregates that will be
441         * combined to create the final {@link MergedAnnotations}.
442         */
443        enum SearchStrategy {
444
445                /**
446                 * Find only directly declared annotations, without considering
447                 * {@link Inherited @Inherited} annotations and without searching
448                 * superclasses or implemented interfaces.
449                 */
450                DIRECT,
451
452                /**
453                 * Find all directly declared annotations as well as any
454                 * {@link Inherited @Inherited} superclass annotations. This strategy
455                 * is only really useful when used with {@link Class} types since the
456                 * {@link Inherited @Inherited} annotation is ignored for all other
457                 * {@linkplain AnnotatedElement annotated elements}. This strategy does
458                 * not search implemented interfaces.
459                 */
460                INHERITED_ANNOTATIONS,
461
462                /**
463                 * Find all directly declared and superclass annotations. This strategy
464                 * is similar to {@link #INHERITED_ANNOTATIONS} except the annotations
465                 * do not need to be meta-annotated with {@link Inherited @Inherited}.
466                 * This strategy does not search implemented interfaces.
467                 */
468                SUPERCLASS,
469
470                /**
471                 * Perform a full search of the entire type hierarchy, including
472                 * superclasses and implemented interfaces. Superclass annotations do
473                 * not need to be meta-annotated with {@link Inherited @Inherited}.
474                 */
475                TYPE_HIERARCHY,
476
477                /**
478                 * Perform a full search of the entire type hierarchy on the source
479                 * <em>and</em> any enclosing classes. This strategy is similar to
480                 * {@link #TYPE_HIERARCHY} except that {@linkplain Class#getEnclosingClass()
481                 * enclosing classes} are also searched. Superclass annotations do not
482                 * need to be meta-annotated with {@link Inherited @Inherited}. When
483                 * searching a {@link Method} source, this strategy is identical to
484                 * {@link #TYPE_HIERARCHY}.
485                 */
486                TYPE_HIERARCHY_AND_ENCLOSING_CLASSES
487        }
488
489}