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;
020
021/**
022 * Callback interface that can be used to filter specific annotation types.
023 *
024 * <p>Note that the {@link MergedAnnotations} model (which this interface has been
025 * designed for) always ignores lang annotations according to the {@link #PLAIN}
026 * filter (for efficiency reasons). Any additional filters and even custom filter
027 * implementations apply within this boundary and may only narrow further from here.
028 *
029 * @author Phillip Webb
030 * @author Juergen Hoeller
031 * @since 5.2
032 * @see MergedAnnotations
033 */
034@FunctionalInterface
035public interface AnnotationFilter {
036
037        /**
038         * {@link AnnotationFilter} that matches annotations in the
039         * {@code java.lang} and {@code org.springframework.lang} packages
040         * and their subpackages.
041         * <p>This is the default filter in the {@link MergedAnnotations} model.
042         */
043        AnnotationFilter PLAIN = packages("java.lang", "org.springframework.lang");
044
045        /**
046         * {@link AnnotationFilter} that matches annotations in the
047         * {@code java} and {@code javax} packages and their subpackages.
048         */
049        AnnotationFilter JAVA = packages("java", "javax");
050
051        /**
052         * {@link AnnotationFilter} that always matches and can be used when no
053         * relevant annotation types are expected to be present at all.
054         */
055        AnnotationFilter ALL = new AnnotationFilter() {
056                @Override
057                public boolean matches(Annotation annotation) {
058                        return true;
059                }
060                @Override
061                public boolean matches(Class<?> type) {
062                        return true;
063                }
064                @Override
065                public boolean matches(String typeName) {
066                        return true;
067                }
068                @Override
069                public String toString() {
070                        return "All annotations filtered";
071                }
072        };
073
074        /**
075         * {@link AnnotationFilter} that never matches and can be used when no
076         * filtering is needed (allowing for any annotation types to be present).
077         * @deprecated as of 5.2.6 since the {@link MergedAnnotations} model
078         * always ignores lang annotations according to the {@link #PLAIN} filter
079         * (for efficiency reasons)
080         * @see #PLAIN
081         */
082        @Deprecated
083        AnnotationFilter NONE = new AnnotationFilter() {
084                @Override
085                public boolean matches(Annotation annotation) {
086                        return false;
087                }
088                @Override
089                public boolean matches(Class<?> type) {
090                        return false;
091                }
092                @Override
093                public boolean matches(String typeName) {
094                        return false;
095                }
096                @Override
097                public String toString() {
098                        return "No annotation filtering";
099                }
100        };
101
102
103        /**
104         * Test if the given annotation matches the filter.
105         * @param annotation the annotation to test
106         * @return {@code true} if the annotation matches
107         */
108        default boolean matches(Annotation annotation) {
109                return matches(annotation.annotationType());
110        }
111
112        /**
113         * Test if the given type matches the filter.
114         * @param type the annotation type to test
115         * @return {@code true} if the annotation matches
116         */
117        default boolean matches(Class<?> type) {
118                return matches(type.getName());
119        }
120
121        /**
122         * Test if the given type name matches the filter.
123         * @param typeName the fully qualified class name of the annotation type to test
124         * @return {@code true} if the annotation matches
125         */
126        boolean matches(String typeName);
127
128
129        /**
130         * Create a new {@link AnnotationFilter} that matches annotations in the
131         * specified packages.
132         * @param packages the annotation packages that should match
133         * @return a new {@link AnnotationFilter} instance
134         */
135        static AnnotationFilter packages(String... packages) {
136                return new PackagesAnnotationFilter(packages);
137        }
138
139}