Nullability refinements (no IntelliJ warnings, fewer null checks)

Includes consistent ignoring of all java.lang (meta-)annotations.

Closes gh-22586
This commit is contained in:
Juergen Hoeller 2019-03-23 12:13:38 +01:00
parent 75b52309a7
commit 5e15338a09
33 changed files with 439 additions and 801 deletions

View File

@ -33,8 +33,7 @@ import org.springframework.util.Assert;
* @since 5.2
* @param <A> the annotation type
*/
abstract class AbstractMergedAnnotation<A extends Annotation>
implements MergedAnnotation<A> {
abstract class AbstractMergedAnnotation<A extends Annotation> implements MergedAnnotation<A> {
@Nullable
private volatile A synthesizedAnnotation;

View File

@ -828,13 +828,13 @@ public abstract class AnnotatedElementUtils {
}
@Nullable
private static AnnotationAttributes getAnnotationAttributes(
MergedAnnotation<?> annotation, boolean classValuesAsString,
boolean nestedAnnotationsAsMap) {
private static AnnotationAttributes getAnnotationAttributes(MergedAnnotation<?> annotation,
boolean classValuesAsString, boolean nestedAnnotationsAsMap) {
if (!annotation.isPresent()) {
return null;
}
return annotation.asMap((mergedAnnotation) -> new AnnotationAttributes(),
return annotation.asMap(mergedAnnotation -> new AnnotationAttributes(),
MapValues.of(classValuesAsString, nestedAnnotationsAsMap));
}

View File

@ -68,14 +68,12 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
return findOrderFromAnnotation(obj);
}
@Nullable
private Integer findOrderFromAnnotation(Object obj) {
AnnotatedElement element = obj instanceof AnnotatedElement
? (AnnotatedElement) obj
: obj.getClass();
MergedAnnotations annotations = MergedAnnotations.from(element,
SearchStrategy.EXHAUSTIVE);
AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass());
MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.EXHAUSTIVE);
Integer order = OrderUtils.getOrderFromAnnotations(element, annotations);
if (order == null && obj instanceof DecoratingProxy) {
if (order == null && obj instanceof DecoratingProxy) {
return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass());
}
return order;

View File

@ -20,7 +20,6 @@ import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collection;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
@ -37,31 +36,27 @@ public interface AnnotationFilter {
* {@code java.lang.*} or in the
* {@code org.springframework.lang.*} package.
*/
static final AnnotationFilter PLAIN = packages("java.lang",
"org.springframework.lang");
AnnotationFilter PLAIN = packages("java.lang", "org.springframework.lang");
/**
* {@link AnnotationFilter} that matches annotations in the
* {@code java.lang.*} package.
*/
static final AnnotationFilter JAVA = packages("java.lang");
AnnotationFilter JAVA = packages("java.lang");
/**
* {@link AnnotationFilter} that never matches and can be used when no
* filtering is needed.
*/
static final AnnotationFilter NONE = new AnnotationFilter() {
AnnotationFilter NONE = new AnnotationFilter() {
@Override
public boolean matches(@Nullable String typeName) {
public boolean matches(String typeName) {
return false;
}
@Override
public String toString() {
return "No annotation filtering";
}
};
@ -70,8 +65,8 @@ public interface AnnotationFilter {
* @param annotation the annotation to test
* @return {@code true} if the annotation matches
*/
default boolean matches(@Nullable Annotation annotation) {
return matches(annotation != null ? annotation.annotationType() : null);
default boolean matches(Annotation annotation) {
return matches(annotation.annotationType());
}
/**
@ -79,8 +74,8 @@ public interface AnnotationFilter {
* @param type the annotation type to test
* @return {@code true} if the annotation matches
*/
default boolean matches(@Nullable Class<?> type) {
return matches(type != null ? type.getName() : null);
default boolean matches(Class<?> type) {
return matches(type.getName());
}
/**
@ -88,7 +83,8 @@ public interface AnnotationFilter {
* @param typeName the annotation type to test
* @return {@code true} if the annotation matches
*/
boolean matches(@Nullable String typeName);
boolean matches(String typeName);
/**
* Return a new {@link AnnotationFilter} that matches annotations in the
@ -107,8 +103,8 @@ public interface AnnotationFilter {
* @param annotationType the annotation type to check
* @return the most appropriate annotation filter
*/
static AnnotationFilter mostAppropriateFor(@Nullable Class<?> annotationType) {
return PLAIN.matches(annotationType) ? NONE : PLAIN;
static AnnotationFilter mostAppropriateFor(Class<?> annotationType) {
return (PLAIN.matches(annotationType) ? NONE : PLAIN);
}
/**
@ -119,30 +115,6 @@ public interface AnnotationFilter {
* @return the most appropriate annotation filter
*/
static AnnotationFilter mostAppropriateFor(Class<?>... annotationTypes) {
Assert.notNull(annotationTypes, "AnnotationTypes must not be null");
return mostAppropriateFor(Arrays.asList(annotationTypes));
}
/**
* Return an {@link AnnotationFilter} that is the most appropriate for, and
* will always match all the given annotation type. Whenever possible,
* {@link AnnotationFilter#PLAIN} will be returned.
* @param annotationType the annotation type to check
* @return the most appropriate annotation filter
*/
static AnnotationFilter mostAppropriateFor(@Nullable String annotationType) {
return PLAIN.matches(annotationType) ? NONE : PLAIN;
}
/**
* Return an {@link AnnotationFilter} that is the most appropriate for, and
* will always match all the given annotation types. Whenever possible,
* {@link AnnotationFilter#PLAIN} will be returned.
* @param annotationTypes the annotation types to check
* @return the most appropriate annotation filter
*/
static AnnotationFilter mostAppropriateFor(String... annotationTypes) {
Assert.notNull(annotationTypes, "AnnotationTypes must not be null");
return mostAppropriateFor(Arrays.asList(annotationTypes));
}
@ -156,20 +128,16 @@ public interface AnnotationFilter {
*/
@SuppressWarnings("unchecked")
static AnnotationFilter mostAppropriateFor(Collection<?> annotationTypes) {
Assert.notNull(annotationTypes, "AnnotationTypes must not be null");
for (Object annotationType : annotationTypes) {
if (annotationType == null) {
continue;
}
Assert.isTrue(
annotationType instanceof Class || annotationType instanceof String,
Assert.isTrue(annotationType instanceof Class || annotationType instanceof String,
"AnnotationType must be a Class or String");
if (annotationType instanceof Class
&& PLAIN.matches((Class<Annotation>) annotationType)) {
if (annotationType instanceof Class && PLAIN.matches((Class<Annotation>) annotationType)) {
return NONE;
}
if (annotationType instanceof String
&& PLAIN.matches((String) annotationType)) {
if (annotationType instanceof String && PLAIN.matches((String) annotationType)) {
return NONE;
}
}

View File

@ -45,7 +45,7 @@ import org.springframework.util.StringUtils;
* @since 5.2
* @see AnnotationTypeMappings
*/
class AnnotationTypeMapping {
final class AnnotationTypeMapping {
@Nullable
private final AnnotationTypeMapping parent;

View File

@ -24,7 +24,6 @@ import java.util.List;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ConcurrentReferenceHashMap;
/**
@ -75,11 +74,9 @@ final class AnnotationTypeMappings {
}
}
private void addMetaAnnotationsToQueue(Deque<AnnotationTypeMapping> queue,
AnnotationTypeMapping parent) {
Annotation[] metaAnnotations = AnnotationsScanner.getDeclaredAnnotations(
parent.getAnnotationType(), false);
private void addMetaAnnotationsToQueue(Deque<AnnotationTypeMapping> queue, AnnotationTypeMapping parent) {
Annotation[] metaAnnotations =
AnnotationsScanner.getDeclaredAnnotations(parent.getAnnotationType(), false);
for (Annotation metaAnnotation : metaAnnotations) {
if (!isMappable(parent, metaAnnotation)) {
continue;
@ -125,19 +122,17 @@ final class AnnotationTypeMappings {
}
}
private boolean isMappable(AnnotationTypeMapping parent, Annotation metaAnnotation) {
return !this.filter.matches(metaAnnotation) &&
private boolean isMappable(AnnotationTypeMapping parent, @Nullable Annotation metaAnnotation) {
return (metaAnnotation != null && !this.filter.matches(metaAnnotation) &&
!AnnotationFilter.PLAIN.matches(parent.getAnnotationType()) &&
!isAlreadyMapped(parent, metaAnnotation);
!isAlreadyMapped(parent, metaAnnotation));
}
private boolean isAlreadyMapped(AnnotationTypeMapping parent,
Annotation metaAnnotation) {
private boolean isAlreadyMapped(AnnotationTypeMapping parent, Annotation metaAnnotation) {
Class<? extends Annotation> annotationType = metaAnnotation.annotationType();
AnnotationTypeMapping mapping = parent;
while (mapping != null) {
if (mapping.getAnnotationType().equals(annotationType)) {
if (mapping.getAnnotationType() == annotationType) {
return true;
}
mapping = mapping.getParent();
@ -171,11 +166,8 @@ final class AnnotationTypeMappings {
* @param annotationType the source annotation type
* @return type mappings for the annotation type
*/
static AnnotationTypeMappings forAnnotationType(
Class<? extends Annotation> annotationType) {
return forAnnotationType(annotationType,
AnnotationFilter.mostAppropriateFor(annotationType));
static AnnotationTypeMappings forAnnotationType(Class<? extends Annotation> annotationType) {
return forAnnotationType(annotationType, AnnotationFilter.mostAppropriateFor(annotationType));
}
/**
@ -186,11 +178,8 @@ final class AnnotationTypeMappings {
* @return type mappings for the annotation type
*/
static AnnotationTypeMappings forAnnotationType(
Class<? extends Annotation> annotationType,
AnnotationFilter annotationFilter) {
Class<? extends Annotation> annotationType, AnnotationFilter annotationFilter) {
Assert.notNull(annotationType, "AnnotationType must not be null");
Assert.notNull(annotationFilter, "AnnotationFilter must not be null");
return cache.computeIfAbsent(annotationFilter, Cache::new).get(annotationType);
}

View File

@ -477,8 +477,10 @@ public abstract class AnnotationUtils {
* @see #getAnnotation(Method, Class)
*/
@Nullable
public static <A extends Annotation> A findAnnotation(Method method,
@Nullable Class<A> annotationType) {
public static <A extends Annotation> A findAnnotation(Method method, @Nullable Class<A> annotationType) {
if (annotationType == null) {
return null;
}
AnnotationFilter annotationFilter = AnnotationFilter.mostAppropriateFor(annotationType);
return MergedAnnotations.from(method, SearchStrategy.EXHAUSTIVE,
@ -510,9 +512,7 @@ public abstract class AnnotationUtils {
* @return the first matching annotation, or {@code null} if not found
*/
@Nullable
public static <A extends Annotation> A findAnnotation(Class<?> clazz,
Class<A> annotationType) {
public static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) {
AnnotationFilter annotationFilter = AnnotationFilter.mostAppropriateFor(annotationType);
return MergedAnnotations.from(clazz, SearchStrategy.EXHAUSTIVE,
RepeatableContainers.none(), annotationFilter)
@ -535,8 +535,8 @@ public abstract class AnnotationUtils {
* @param annotationType the annotation type to look for
* @param clazz the class to check for the annotation on (may be {@code null})
* @return the first {@link Class} in the inheritance hierarchy that
* declares an annotation of the specified {@code annotationType}, or
* {@code null} if not found
* declares an annotation of the specified {@code annotationType},
* or {@code null} if not found
* @see Class#isAnnotationPresent(Class)
* @see Class#getDeclaredAnnotations()
* @see #findAnnotationDeclaringClassForTypes(List, Class)
@ -546,6 +546,10 @@ public abstract class AnnotationUtils {
public static Class<?> findAnnotationDeclaringClass(
Class<? extends Annotation> annotationType, @Nullable Class<?> clazz) {
if (clazz == null) {
return null;
}
AnnotationFilter annotationFilter = AnnotationFilter.mostAppropriateFor(annotationType);
return (Class<?>) MergedAnnotations.from(clazz, SearchStrategy.SUPER_CLASS,
RepeatableContainers.none(), annotationFilter)
@ -567,7 +571,7 @@ public abstract class AnnotationUtils {
* one of several candidate {@linkplain Annotation annotations}, so we
* need to handle this explicitly.
* @param annotationTypes the annotation types to look for
* @param clazz the class to check for the annotations on, or {@code null}
* @param clazz the class to check for the annotation on (may be {@code null})
* @return the first {@link Class} in the inheritance hierarchy that
* declares an annotation of at least one of the specified
* {@code annotationTypes}, or {@code null} if not found
@ -581,6 +585,10 @@ public abstract class AnnotationUtils {
public static Class<?> findAnnotationDeclaringClassForTypes(
List<Class<? extends Annotation>> annotationTypes, @Nullable Class<?> clazz) {
if (clazz == null) {
return null;
}
AnnotationFilter annotationFilter = AnnotationFilter.mostAppropriateFor(annotationTypes);
return (Class<?>) MergedAnnotations.from(clazz, SearchStrategy.SUPER_CLASS,
RepeatableContainers.none(), annotationFilter)
@ -608,9 +616,7 @@ public abstract class AnnotationUtils {
* @see java.lang.Class#getDeclaredAnnotation(Class)
* @see #isAnnotationInherited(Class, Class)
*/
public static boolean isAnnotationDeclaredLocally(
Class<? extends Annotation> annotationType, Class<?> clazz) {
public static boolean isAnnotationDeclaredLocally(Class<? extends Annotation> annotationType, Class<?> clazz) {
return MergedAnnotations.from(clazz).get(annotationType).isDirectlyPresent();
}
@ -633,9 +639,7 @@ public abstract class AnnotationUtils {
* @see Class#isAnnotationPresent(Class)
* @see #isAnnotationDeclaredLocally(Class, Class)
*/
public static boolean isAnnotationInherited(
Class<? extends Annotation> annotationType, Class<?> clazz) {
public static boolean isAnnotationInherited(Class<? extends Annotation> annotationType, Class<?> clazz) {
return MergedAnnotations.from(clazz, SearchStrategy.INHERITED_ANNOTATIONS)
.stream(annotationType)
.filter(MergedAnnotation::isDirectlyPresent)
@ -651,12 +655,10 @@ public abstract class AnnotationUtils {
* @return {@code true} if such an annotation is meta-present
* @since 4.2.1
*/
public static boolean isAnnotationMetaPresent(
Class<? extends Annotation> annotationType,
public static boolean isAnnotationMetaPresent(Class<? extends Annotation> annotationType,
@Nullable Class<? extends Annotation> metaAnnotationType) {
return MergedAnnotations.from(annotationType, SearchStrategy.EXHAUSTIVE)
.isPresent(annotationType);
return MergedAnnotations.from(annotationType, SearchStrategy.EXHAUSTIVE).isPresent(annotationType);
}
/**
@ -666,7 +668,7 @@ public abstract class AnnotationUtils {
* @return {@code true} if the annotation is in the {@code java.lang.annotation} package
*/
public static boolean isInJavaLangAnnotationPackage(@Nullable Annotation annotation) {
return JAVA_LANG_ANNOTATION_FILTER.matches(annotation);
return (annotation != null && JAVA_LANG_ANNOTATION_FILTER.matches(annotation));
}
/**
@ -677,7 +679,7 @@ public abstract class AnnotationUtils {
* @since 4.2
*/
public static boolean isInJavaLangAnnotationPackage(@Nullable String annotationType) {
return JAVA_LANG_ANNOTATION_FILTER.matches(annotationType);
return (annotationType != null && JAVA_LANG_ANNOTATION_FILTER.matches(annotationType));
}
/**
@ -693,8 +695,7 @@ public abstract class AnnotationUtils {
* @see #getAnnotationAttributes(Annotation)
*/
public static void validateAnnotation(Annotation annotation) {
AttributeMethods.forAnnotationType(annotation.annotationType())
.validate(annotation);
AttributeMethods.forAnnotationType(annotation.annotationType()).validate(annotation);
}
/**
@ -889,13 +890,15 @@ public abstract class AnnotationUtils {
public static void postProcessAnnotationAttributes(@Nullable Object annotatedElement,
@Nullable AnnotationAttributes attributes, boolean classValuesAsString) {
if (attributes == null || attributes.annotationType() == null) {
if (attributes == null) {
return;
}
if (!attributes.validated) {
Class<? extends Annotation> annotationType = attributes.annotationType();
AnnotationTypeMapping mapping = AnnotationTypeMappings
.forAnnotationType(annotationType).get(0);
if (annotationType == null) {
return;
}
AnnotationTypeMapping mapping = AnnotationTypeMappings.forAnnotationType(annotationType).get(0);
for (int i = 0; i < mapping.getMirrorSets().size(); i++) {
MirrorSet mirrorSet = mapping.getMirrorSets().get(i);
int resolved = mirrorSet.resolve(attributes.displayName, attributes,

View File

@ -55,13 +55,12 @@ interface AnnotationsProcessor<C, R> {
* @return a {@code non-null} result if no further processing is required
*/
@Nullable
R doWithAnnotations(C context, int aggregateIndex, @Nullable Object source,
Annotation[] annotations);
R doWithAnnotations(C context, int aggregateIndex, @Nullable Object source, Annotation[] annotations);
/**
* Return the final result to be returned. By default this method returns
* the last process result.
* @param result the last early exit result, or {@code null}.
* @param result the last early exit result, or {@code null} if none
* @return the final result to be returned to the caller
*/
@Nullable

View File

@ -71,8 +71,9 @@ abstract class AnnotationsScanner {
* @return the result of {@link AnnotationsProcessor#finish(Object)}
*/
@Nullable
static <C, R> R scan(C context, AnnotatedElement source,
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor) {
static <C, R> R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy,
AnnotationsProcessor<C, R> processor) {
return scan(context, source, searchStrategy, processor, null);
}
@ -89,9 +90,8 @@ abstract class AnnotationsScanner {
* @return the result of {@link AnnotationsProcessor#finish(Object)}
*/
@Nullable
static <C, R> R scan(C context, AnnotatedElement source,
SearchStrategy searchStrategy, AnnotationsProcessor<C, R> processor,
@Nullable BiPredicate<C, Class<?>> classFilter) {
static <C, R> R scan(C context, AnnotatedElement source, SearchStrategy searchStrategy,
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
R result = process(context, source, searchStrategy, processor, classFilter);
return processor.finish(result);
@ -135,8 +135,7 @@ abstract class AnnotationsScanner {
@Nullable
private static <C, R> R processClassInheritedAnnotations(C context, Class<?> source,
AnnotationsProcessor<C, R> processor,
@Nullable BiPredicate<C, Class<?>> classFilter) {
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
if (isWithoutHierarchy(source)) {
return processElement(context, source, processor, classFilter);
@ -145,8 +144,8 @@ abstract class AnnotationsScanner {
int remaining = Integer.MAX_VALUE;
int aggregateIndex = 0;
Class<?> root = source;
while (source != null && source != Object.class && remaining > 0
&& !hasPlainJavaAnnotationsOnly(source)) {
while (source != null && source != Object.class && remaining > 0 &&
!hasPlainJavaAnnotationsOnly(source)) {
R result = processor.doWithAggregate(context, aggregateIndex);
if (result != null) {
return result;
@ -208,7 +207,7 @@ abstract class AnnotationsScanner {
if (includeInterfaces) {
for (Class<?> interfaceType : source.getInterfaces()) {
R interfacesResult = processClassHierarchy(context, aggregateIndex,
interfaceType, processor, classFilter, includeInterfaces);
interfaceType, processor, classFilter, true);
if (interfacesResult != null) {
return interfacesResult;
}
@ -233,13 +232,12 @@ abstract class AnnotationsScanner {
switch (searchStrategy) {
case DIRECT:
case INHERITED_ANNOTATIONS:
return processMethodInheritedAnnotations(context, source,
processor, classFilter);
return processMethodInheritedAnnotations(context, source, processor, classFilter);
case SUPER_CLASS:
return processMethodHierarchy(context, new int[] { 0 }, source.getDeclaringClass(),
return processMethodHierarchy(context, new int[] {0}, source.getDeclaringClass(),
processor, classFilter, source, false);
case EXHAUSTIVE:
return processMethodHierarchy(context, new int[] { 0 }, source.getDeclaringClass(),
return processMethodHierarchy(context, new int[] {0}, source.getDeclaringClass(),
processor, classFilter, source, true);
}
throw new IllegalStateException("Unsupported search strategy " + searchStrategy);
@ -247,12 +245,11 @@ abstract class AnnotationsScanner {
@Nullable
private static <C, R> R processMethodInheritedAnnotations(C context, Method source,
AnnotationsProcessor<C, R> processor,
@Nullable BiPredicate<C, Class<?>> classFilter) {
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
R result = processor.doWithAggregate(context, 0);
return result != null ? result :
processMethodAnnotations(context, 0, source, processor, classFilter);
return (result != null ? result :
processMethodAnnotations(context, 0, source, processor, classFilter));
}
@Nullable
@ -298,7 +295,7 @@ abstract class AnnotationsScanner {
if (includeInterfaces) {
for (Class<?> interfaceType : sourceClass.getInterfaces()) {
R interfacesResult = processMethodHierarchy(context, aggregateIndex,
interfaceType, processor, classFilter, rootMethod, includeInterfaces);
interfaceType, processor, classFilter, rootMethod, true);
if (interfacesResult != null) {
return interfacesResult;
}
@ -315,8 +312,8 @@ abstract class AnnotationsScanner {
return null;
}
private static <C> Method[] getBaseTypeMethods(C context, Class<?> baseType,
@Nullable BiPredicate<C, Class<?>> classFilter) {
private static <C> Method[] getBaseTypeMethods(
C context, Class<?> baseType, @Nullable BiPredicate<C, Class<?>> classFilter) {
if (baseType == Object.class || hasPlainJavaAnnotationsOnly(baseType) ||
isFiltered(baseType, context, classFilter)) {
@ -326,8 +323,7 @@ abstract class AnnotationsScanner {
Method[] methods = baseTypeMethodsCache.get(baseType);
if (methods == null) {
boolean isInterface = baseType.isInterface();
methods = isInterface ? baseType.getMethods()
: ReflectionUtils.getDeclaredMethods(baseType);
methods = isInterface ? baseType.getMethods() : ReflectionUtils.getDeclaredMethods(baseType);
int cleared = 0;
for (int i = 0; i < methods.length; i++) {
if ((!isInterface && Modifier.isPrivate(methods[i].getModifiers())) ||
@ -346,14 +342,12 @@ abstract class AnnotationsScanner {
}
private static boolean isOverride(Method rootMethod, Method candidateMethod) {
return !Modifier.isPrivate(candidateMethod.getModifiers()) &&
return (!Modifier.isPrivate(candidateMethod.getModifiers()) &&
candidateMethod.getName().equals(rootMethod.getName()) &&
hasSameParameterTypes(rootMethod, candidateMethod);
hasSameParameterTypes(rootMethod, candidateMethod));
}
private static boolean hasSameParameterTypes(Method rootMethod,
Method candidateMethod) {
private static boolean hasSameParameterTypes(Method rootMethod, Method candidateMethod) {
if (candidateMethod.getParameterCount() != rootMethod.getParameterCount()) {
return false;
}
@ -366,8 +360,8 @@ abstract class AnnotationsScanner {
rootParameterTypes);
}
private static boolean hasSameGenericTypeParameters(Method rootMethod,
Method candidateMethod, Class<?>[] rootParameterTypes) {
private static boolean hasSameGenericTypeParameters(
Method rootMethod, Method candidateMethod, Class<?>[] rootParameterTypes) {
Class<?> sourceDeclaringClass = rootMethod.getDeclaringClass();
Class<?> candidateDeclaringClass = candidateMethod.getDeclaringClass();
@ -385,53 +379,43 @@ abstract class AnnotationsScanner {
}
@Nullable
private static <C, R> R processMethodAnnotations(C context, int aggregateIndex,
Method source, AnnotationsProcessor<C, R> processor,
@Nullable BiPredicate<C, Class<?>> classFilter) {
private static <C, R> R processMethodAnnotations(C context, int aggregateIndex, Method source,
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
Annotation[] annotations = getDeclaredAnnotations(context, source, classFilter,
false);
R result = processor.doWithAnnotations(context, aggregateIndex, source,
annotations);
Annotation[] annotations = getDeclaredAnnotations(context, source, classFilter, false);
R result = processor.doWithAnnotations(context, aggregateIndex, source, annotations);
if (result != null) {
return result;
}
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(source);
if (bridgedMethod != source) {
Annotation[] bridgedAnnotations = getDeclaredAnnotations(context,
bridgedMethod, classFilter, true);
Annotation[] bridgedAnnotations = getDeclaredAnnotations(context, bridgedMethod, classFilter, true);
for (int i = 0; i < bridgedAnnotations.length; i++) {
if (ObjectUtils.containsElement(annotations, bridgedAnnotations[i])) {
bridgedAnnotations[i] = null;
}
}
return processor.doWithAnnotations(context, aggregateIndex, source,
bridgedAnnotations);
return processor.doWithAnnotations(context, aggregateIndex, source, bridgedAnnotations);
}
return null;
}
@Nullable
private static <C, R> R processElement(C context, AnnotatedElement source,
AnnotationsProcessor<C, R> processor,
@Nullable BiPredicate<C, Class<?>> classFilter) {
AnnotationsProcessor<C, R> processor, @Nullable BiPredicate<C, Class<?>> classFilter) {
R result = processor.doWithAggregate(context, 0);
return result != null ? result
: processor.doWithAnnotations(context, 0, source,
getDeclaredAnnotations(context, source, classFilter, false));
return (result != null ? result : processor.doWithAnnotations(context, 0, source,
getDeclaredAnnotations(context, source, classFilter, false)));
}
private static <C, R> Annotation[] getDeclaredAnnotations(C context,
AnnotatedElement source, @Nullable BiPredicate<C, Class<?>> classFilter,
boolean copy) {
AnnotatedElement source, @Nullable BiPredicate<C, Class<?>> classFilter, boolean copy) {
if (source instanceof Class &&
isFiltered((Class<?>) source, context, classFilter)) {
if (source instanceof Class && isFiltered((Class<?>) source, context, classFilter)) {
return NO_ANNOTATIONS;
}
if (source instanceof Method &&
isFiltered(((Method) source).getDeclaringClass(), context, classFilter)) {
if (source instanceof Method && isFiltered(((Method) source).getDeclaringClass(), context, classFilter)) {
return NO_ANNOTATIONS;
}
return getDeclaredAnnotations(source, copy);
@ -439,40 +423,37 @@ abstract class AnnotationsScanner {
@SuppressWarnings("unchecked")
@Nullable
static <A extends Annotation> A getDeclaredAnnotation(AnnotatedElement source,
Class<A> annotationType) {
static <A extends Annotation> A getDeclaredAnnotation(AnnotatedElement source, Class<A> annotationType) {
Annotation[] annotations = getDeclaredAnnotations(source, false);
for (int i = 0; i < annotations.length; i++) {
if (annotations[i] != null &&
annotationType.equals(annotations[i].annotationType())) {
return (A) annotations[i];
for (Annotation annotation : annotations) {
if (annotation != null && annotationType.equals(annotation.annotationType())) {
return (A) annotation;
}
}
return null;
}
static Annotation[] getDeclaredAnnotations(AnnotatedElement source,
boolean defensive) {
boolean cached = true;
static Annotation[] getDeclaredAnnotations(AnnotatedElement source, boolean defensive) {
boolean cached = false;
Annotation[] annotations = declaredAnnotationCache.get(source);
if (annotations == null) {
if (annotations != null) {
cached = true;
}
else {
annotations = source.getDeclaredAnnotations();
if (annotations.length != 0) {
boolean allIgnored = true;
for (int i = 0; i < annotations.length; i++) {
Annotation annotation = annotations[i];
if (isIgnorable(annotation.annotationType()) ||
!AttributeMethods.forAnnotationType(
annotation.annotationType()).isValid(annotation)) {
!AttributeMethods.forAnnotationType(annotation.annotationType()).isValid(annotation)) {
annotations[i] = null;
}
else {
allIgnored = false;
}
}
annotations = allIgnored ? NO_ANNOTATIONS : annotations;
annotations = (allIgnored ? NO_ANNOTATIONS : annotations);
if (source instanceof Class || source instanceof Member) {
declaredAnnotationCache.put(source, annotations);
cached = true;
@ -486,19 +467,17 @@ abstract class AnnotationsScanner {
}
private static boolean isIgnorable(Class<?> annotationType) {
return (annotationType == Nullable.class ||
annotationType == FunctionalInterface.class);
return AnnotationFilter.PLAIN.matches(annotationType);
}
private static <C> boolean isFiltered(Class<?> sourceClass, C context,
@Nullable BiPredicate<C, Class<?>> classFilter) {
return classFilter != null && classFilter.test(context, sourceClass);
private static <C> boolean isFiltered(
Class<?> sourceClass, C context, @Nullable BiPredicate<C, Class<?>> classFilter) {
return (classFilter != null && classFilter.test(context, sourceClass));
}
static boolean isKnownEmpty(AnnotatedElement source,
SearchStrategy searchStrategy, AnnotationFilter annotationFilter) {
if (annotationFilter == AnnotationFilter.PLAIN &&
hasPlainJavaAnnotationsOnly(source)) {
static boolean isKnownEmpty(AnnotatedElement source,SearchStrategy searchStrategy, AnnotationFilter annotationFilter) {
if (annotationFilter == AnnotationFilter.PLAIN && hasPlainJavaAnnotationsOnly(source)) {
return true;
}
if (searchStrategy == SearchStrategy.DIRECT || isWithoutHierarchy(source)) {
@ -511,7 +490,7 @@ abstract class AnnotationsScanner {
}
static boolean hasPlainJavaAnnotationsOnly(@Nullable Object annotatedElement) {
Class<?> type = null;
Class<?> type;
if (annotatedElement instanceof Class) {
type = (Class<?>) annotatedElement;
}
@ -522,11 +501,11 @@ abstract class AnnotationsScanner {
return false;
}
String name = type.getName();
return type.equals(Ordered.class) ||
return (type == Ordered.class ||
name.startsWith("java") ||
name.startsWith("org.springframework.lang.") ||
name.startsWith("org.springframework.util.") ||
(name.startsWith("com.sun") && !name.contains("Proxy"));
(name.startsWith("com.sun") && !name.contains("Proxy")));
}
private static boolean isWithoutHierarchy(AnnotatedElement source) {
@ -535,13 +514,13 @@ abstract class AnnotationsScanner {
}
if (source instanceof Class) {
Class<?> sourceClass = (Class<?>) source;
return sourceClass.getSuperclass() == Object.class &&
sourceClass.getInterfaces().length == 0;
return (sourceClass.getSuperclass() == Object.class &&
sourceClass.getInterfaces().length == 0);
}
if (source instanceof Method) {
Method sourceMethod = (Method) source;
return Modifier.isPrivate(sourceMethod.getModifiers()) ||
isWithoutHierarchy(sourceMethod.getDeclaringClass());
return (Modifier.isPrivate(sourceMethod.getModifiers()) ||
isWithoutHierarchy(sourceMethod.getDeclaringClass()));
}
return true;
}

View File

@ -48,6 +48,7 @@ final class AttributeMethods {
return m1 != null ? -1 : 1;
};
@Nullable
private final Class<? extends Annotation> annotationType;
@ -60,8 +61,7 @@ final class AttributeMethods {
private final boolean hasNestedAnnotation;
private AttributeMethods(@Nullable Class<? extends Annotation> annotationType,
Method[] attributeMethods) {
private AttributeMethods(@Nullable Class<? extends Annotation> annotationType, Method[] attributeMethods) {
this.annotationType = annotationType;
this.attributeMethods = attributeMethods;
this.canThrowTypeNotPresentException = new boolean[attributeMethods.length];
@ -94,8 +94,8 @@ final class AttributeMethods {
* @return {@code true} if this is only a value attribute
*/
boolean isOnlyValueAttribute() {
return this.attributeMethods.length == 1 &&
MergedAnnotation.VALUE.equals(this.attributeMethods[0].getName());
return (this.attributeMethods.length == 1 &&
MergedAnnotation.VALUE.equals(this.attributeMethods[0].getName()));
}
@ -104,7 +104,7 @@ final class AttributeMethods {
* accessed without causing any {@link TypeNotPresentException
* TypeNotPresentExceptions}.
* @param annotation the annotation to check
* @return {@true} if all values are present
* @return {@code true} if all values are present
* @see #validate(Annotation)
*/
boolean isValid(Annotation annotation) {
@ -123,14 +123,13 @@ final class AttributeMethods {
}
/**
* Checks if values from the given annotation can be safely accessed without
* causing any {@link TypeNotPresentException TypeNotPresentExceptions}. In
* particular, this method is designed to cover Google App Engine's late
* arrival of such exceptions for {@code Class} values (instead of the more
* typical early {@code Class.getAnnotations() failure}.
* Checks if values from the given annotation can be safely accessed without causing
* any {@link TypeNotPresentException TypeNotPresentExceptions}. In particular,
* this method is designed to cover Google App Engine's late arrival of such
* exceptions for {@code Class} values (instead of the more typical early
* {@code Class.getAnnotations() failure}.
* @param annotation the annotation to validate
* @throws IllegalStateException if a declared {@code Class} attribute could
* not be read
* @throws IllegalStateException if a declared {@code Class} attribute could not be read
* @see #isValid(Annotation)
*/
void validate(Annotation annotation) {
@ -141,11 +140,8 @@ final class AttributeMethods {
get(i).invoke(annotation);
}
catch (Throwable ex) {
throw new IllegalStateException(
"Could not obtain annotation attribute value for "
+ get(i).getName() + " declared on "
+ annotation.annotationType(),
ex);
throw new IllegalStateException("Could not obtain annotation attribute value for " +
get(i).getName() + " declared on " + annotation.annotationType(), ex);
}
}
}
@ -246,14 +242,13 @@ final class AttributeMethods {
return this.hasNestedAnnotation;
}
/**
* Return the attribute methods for the given annotation type.
* @param annotationType the annotation type
* @return the attribute methods for the annotation
*/
static AttributeMethods forAnnotationType(
@Nullable Class<? extends Annotation> annotationType) {
static AttributeMethods forAnnotationType(@Nullable Class<? extends Annotation> annotationType) {
if (annotationType == null) {
return NONE;
}
@ -279,7 +274,7 @@ final class AttributeMethods {
}
private static boolean isAttributeMethod(Method method) {
return method.getParameterCount() == 0 && method.getReturnType() != void.class;
return (method.getParameterCount() == 0 && method.getReturnType() != void.class);
}
/**
@ -302,14 +297,11 @@ final class AttributeMethods {
* @param attributeName the attribute name
* @return a description of the attribute
*/
static String describe(@Nullable Class<?> annotationType,
@Nullable String attributeName) {
static String describe(@Nullable Class<?> annotationType, @Nullable String attributeName) {
if (attributeName == null) {
return "(none)";
}
String in = annotationType != null ?
" in annotation [" + annotationType.getName() + "]" :
"";
String in = (annotationType != null ? " in annotation [" + annotationType.getName() + "]" : "");
return "attribute '" + attributeName + "'" + in;
}

View File

@ -33,12 +33,10 @@ import org.springframework.lang.Nullable;
enum IntrospectionFailureLogger {
DEBUG {
@Override
public boolean isEnabled() {
return getLogger().isDebugEnabled();
}
@Override
public void log(String message) {
getLogger().debug(message);
@ -46,12 +44,10 @@ enum IntrospectionFailureLogger {
},
INFO {
@Override
public boolean isEnabled() {
return getLogger().isInfoEnabled();
}
@Override
public void log(String message) {
getLogger().info(message);
@ -63,15 +59,16 @@ enum IntrospectionFailureLogger {
private static Log logger;
abstract boolean isEnabled();
void log(String message, @Nullable Object source, Exception ex) {
String on = source != null ? " on " + source : "";
String on = (source != null ? " on " + source : "");
log(message + on + ": " + ex);
}
abstract boolean isEnabled();
abstract void log(String message);
private static Log getLogger() {
Log logger = IntrospectionFailureLogger.logger;
if (logger == null) {

View File

@ -40,8 +40,8 @@ import org.springframework.lang.Nullable;
* For example, to access an {@code int} attribute the {@link #getInt(String)}
* method would be used.
*
* <p>Note that attribute values are <b>not</b> converted when accessed. For
* example, it is not possible to call {@link #getString(String)} if the
* <p>Note that attribute values are <b>not</b> converted when accessed.
* For example, it is not possible to call {@link #getString(String)} if the
* underlying attribute is an {@code int}. The only exception to this rule is
* {@code Class} and {@code Class[]} values which may be accessed as
* {@code String} and {@code String[]} respectively to prevent potential early
@ -63,6 +63,7 @@ public interface MergedAnnotation<A extends Annotation> {
*/
String VALUE = "value";
/**
* Return the class name of the actual annotation type.
* @return the annotation type
@ -342,8 +343,8 @@ public interface MergedAnnotation<A extends Annotation> {
* @return the value as a {@link MergedAnnotation}
* @throws NoSuchElementException if there is no matching attribute
*/
<T extends Annotation> MergedAnnotation<T> getAnnotation(String attributeName,
Class<T> type) throws NoSuchElementException;
<T extends Annotation> MergedAnnotation<T> getAnnotation(String attributeName, Class<T> type)
throws NoSuchElementException;
/**
* Return a required annotation array attribute value from the annotation.
@ -413,10 +414,9 @@ public interface MergedAnnotation<A extends Annotation> {
MergedAnnotation<A> filterAttributes(Predicate<String> predicate);
/**
* Return a new view of the annotation that exposes non-merged attribute
* values. Methods from this view will return attribute values with only
* alias mirroring rules applied. Aliases to parent attributes will not be
* applied.
* Return a new view of the annotation that exposes non-merged attribute values.
* Methods from this view will return attribute values with only alias mirroring
* rules applied. Aliases to parent attributes will not be applied.
* @return a non-merged view of the annotation
*/
MergedAnnotation<A> withNonMergedAttributes();
@ -431,9 +431,9 @@ public interface MergedAnnotation<A extends Annotation> {
Map<String, Object> asMap(MapValues... options);
/**
* Return a {@link Map} of the supplied type that contains all the
* annotation attributes. The {@link MapValues} options may be used to
* change the way that values are added.
* Return a {@link Map} of the supplied type that contains all the annotation
* attributes. The {@link MapValues} options may be used to change the way
* that values are added.
* @param factory a map factory or {@code null} to return an immutable map.
* @param options map value options
* @return a map containing the attributes and values
@ -443,22 +443,19 @@ public interface MergedAnnotation<A extends Annotation> {
/**
* Return a type-safe synthesized version of this annotation that can be
* used directly in code. The result is synthesized using a JDK
* {@link Proxy} and as a result may incur a computational cost when first
* invoked.
* @return a sythesized version of the annotation.
* used directly in code. The result is synthesized using a JDK {@link Proxy}
* and as a result may incur a computational cost when first invoked.
* @return a synthesized version of the annotation.
* @throws NoSuchElementException on a missing annotation
*/
A synthesize() throws NoSuchElementException;
/**
* Optionally return type-safe synthesized version of this annotation based
* on a condition predicate. The result is synthesized using a JDK
* {@link Proxy} and as a result may incur a computational cost when first
* invoked.
* @param condition the test to determine if the annotation can be
* sythesized
* @return a optional containing the sythesized version of the annotation or
* on a condition predicate. The result is synthesized using a JDK {@link Proxy}
* and as a result may incur a computational cost when first invoked.
* @param condition the test to determine if the annotation can be synthesized
* @return a optional containing the synthesized version of the annotation or
* an empty optional if the condition doesn't match
* @throws NoSuchElementException on a missing annotation
* @see MergedAnnotationPredicates
@ -466,6 +463,7 @@ public interface MergedAnnotation<A extends Annotation> {
Optional<A> synthesize(@Nullable Predicate<? super MergedAnnotation<A>> condition)
throws NoSuchElementException;
/**
* Return an {@link MergedAnnotation} that represents a missing annotation
* (i.e. one that is not present).
@ -494,8 +492,7 @@ public interface MergedAnnotation<A extends Annotation> {
* @param annotation the annotation to include
* @return a {@link MergedAnnotation} instance for the annotation
*/
static <A extends Annotation> MergedAnnotation<A> from(@Nullable Object source,
A annotation) {
static <A extends Annotation> MergedAnnotation<A> from(@Nullable Object source, A annotation) {
return TypeMappedAnnotation.from(source, annotation);
}
@ -520,8 +517,9 @@ public interface MergedAnnotation<A extends Annotation> {
* attributes
* @see #from(AnnotatedElement, Class, Map)
*/
static <A extends Annotation> MergedAnnotation<A> from(Class<A> annotationType,
@Nullable Map<String, ?> attributes) {
static <A extends Annotation> MergedAnnotation<A> from(
Class<A> annotationType, @Nullable Map<String, ?> attributes) {
return from(null, annotationType, attributes);
}
@ -538,8 +536,8 @@ public interface MergedAnnotation<A extends Annotation> {
* attributes
*/
static <A extends Annotation> MergedAnnotation<A> from(
@Nullable AnnotatedElement source, Class<A> annotationType,
@Nullable Map<String, ?> attributes) {
@Nullable AnnotatedElement source, Class<A> annotationType, @Nullable Map<String, ?> attributes) {
return TypeMappedAnnotation.from(source, annotationType, attributes);
}
@ -561,7 +559,6 @@ public interface MergedAnnotation<A extends Annotation> {
*/
ANNOTATION_TO_MAP;
protected final boolean isIn(MapValues... options) {
for (MapValues candidate : options) {
if (candidate == this) {
@ -572,11 +569,9 @@ public interface MergedAnnotation<A extends Annotation> {
}
/**
* Factory method to create a {@link MapValues} array from a set of
* boolean flags.
* Factory method to create a {@link MapValues} array from a set of boolean flags.
* @param classToString if {@link MapValues#CLASS_TO_STRING} is included
* @param annotationsToMap if {@link MapValues#ANNOTATION_TO_MAP} is
* included
* @param annotationsToMap if {@link MapValues#ANNOTATION_TO_MAP} is included
* @return a new {@link MapValues} array
*/
public static MapValues[] of(boolean classToString, boolean annotationsToMap) {
@ -591,7 +586,6 @@ public interface MergedAnnotation<A extends Annotation> {
result.add(value);
}
}
}
}

View File

@ -27,7 +27,6 @@ import java.util.stream.Collector;
import java.util.stream.Collector.Characteristics;
import org.springframework.core.annotation.MergedAnnotation.MapValues;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@ -42,8 +41,7 @@ public abstract class MergedAnnotationCollectors {
private static final Characteristics[] NO_CHARACTERISTICS = {};
private static final Characteristics[] IDENTITY_FINISH_CHARACTERISTICS = {
Characteristics.IDENTITY_FINISH };
private static final Characteristics[] IDENTITY_FINISH_CHARACTERISTICS = {Characteristics.IDENTITY_FINISH};
private MergedAnnotationCollectors() {
@ -128,15 +126,14 @@ public abstract class MergedAnnotationCollectors {
Function<MultiValueMap<String, Object>, MultiValueMap<String, Object>> finisher,
MapValues... options) {
Assert.notNull(finisher, "Finisher must not be null");
Characteristics[] characteristics = isSameInstance(finisher, Function.identity()) ?
IDENTITY_FINISH_CHARACTERISTICS :
NO_CHARACTERISTICS;
Characteristics[] characteristics = (isSameInstance(finisher, Function.identity()) ?
IDENTITY_FINISH_CHARACTERISTICS : NO_CHARACTERISTICS);
return Collector.of(LinkedMultiValueMap::new,
(map, annotation) -> annotation.asMap(options).forEach(map::add),
MergedAnnotationCollectors::merge, finisher, characteristics);
}
private static boolean isSameInstance(Object instance, Object candidate) {
return instance == candidate;
}

View File

@ -49,10 +49,7 @@ public abstract class MergedAnnotationPredicates {
* @param typeNames the names that should be matched
* @return a {@link Predicate} to test the annotation type
*/
public static <A extends Annotation> Predicate<MergedAnnotation<? extends A>> typeIn(
String... typeNames) {
Assert.notNull(typeNames, "TypeNames must not be null");
public static <A extends Annotation> Predicate<MergedAnnotation<? extends A>> typeIn(String... typeNames) {
return annotation -> ObjectUtils.containsElement(typeNames, annotation.getType());
}
@ -64,12 +61,8 @@ public abstract class MergedAnnotationPredicates {
* @param types the types that should be matched
* @return a {@link Predicate} to test the annotation type
*/
public static <A extends Annotation> Predicate<MergedAnnotation<? extends A>> typeIn(
Class<?>... types) {
Assert.notNull(types, "Types must not be null");
return annotation -> Arrays.stream(types)
.anyMatch(type -> type.getName().equals(annotation.getType()));
public static <A extends Annotation> Predicate<MergedAnnotation<? extends A>> typeIn(Class<?>... types) {
return annotation -> Arrays.stream(types).anyMatch(type -> type.getName().equals(annotation.getType()));
}
/**
@ -80,10 +73,7 @@ public abstract class MergedAnnotationPredicates {
* @param types the type names or classes that should be matched
* @return a {@link Predicate} to test the annotation type
*/
public static <A extends Annotation> Predicate<MergedAnnotation<? extends A>> typeIn(
Collection<?> types) {
Assert.notNull(types, "Types must not be null");
public static <A extends Annotation> Predicate<MergedAnnotation<? extends A>> typeIn(Collection<?> types) {
return annotation -> types.stream()
.map(type -> type instanceof Class ? ((Class<?>) type).getName() : type.toString())
.anyMatch(typeName -> typeName.equals(annotation.getType()));
@ -103,7 +93,6 @@ public abstract class MergedAnnotationPredicates {
public static <A extends Annotation> Predicate<MergedAnnotation<A>> firstRunOf(
Function<? super MergedAnnotation<A>, ?> valueExtractor) {
Assert.notNull(valueExtractor, "ValueExtractor must not be null");
return new FirstRunOfPredicate<>(valueExtractor);
}
@ -120,7 +109,6 @@ public abstract class MergedAnnotationPredicates {
public static <A extends Annotation, K> Predicate<MergedAnnotation<A>> unique(
Function<? super MergedAnnotation<A>, K> keyExtractor) {
Assert.notNull(keyExtractor, "KeyExtractor must not be null");
return new UniquePredicate<>(keyExtractor);
}
@ -129,8 +117,7 @@ public abstract class MergedAnnotationPredicates {
* {@link Predicate} implementation used for
* {@link MergedAnnotationPredicates#firstRunOf(Function)}.
*/
private static class FirstRunOfPredicate<A extends Annotation>
implements Predicate<MergedAnnotation<A>> {
private static class FirstRunOfPredicate<A extends Annotation> implements Predicate<MergedAnnotation<A>> {
private final Function<? super MergedAnnotation<A>, ?> valueExtractor;
@ -139,13 +126,11 @@ public abstract class MergedAnnotationPredicates {
@Nullable
private Object lastValue;
FirstRunOfPredicate(
Function<? super MergedAnnotation<A>, ?> valueExtractor) {
FirstRunOfPredicate(Function<? super MergedAnnotation<A>, ?> valueExtractor) {
Assert.notNull(valueExtractor, "Value extractor must not be null");
this.valueExtractor = valueExtractor;
}
@Override
public boolean test(@Nullable MergedAnnotation<A> annotation) {
if (!this.hasLastValue) {
@ -164,19 +149,17 @@ public abstract class MergedAnnotationPredicates {
* {@link Predicate} implementation used for
* {@link MergedAnnotationPredicates#unique(Function)}.
*/
private static class UniquePredicate<A extends Annotation, K>
implements Predicate<MergedAnnotation<A>> {
private static class UniquePredicate<A extends Annotation, K> implements Predicate<MergedAnnotation<A>> {
private final Function<? super MergedAnnotation<A>, K> keyExtractor;
private final Set<K> seen = new HashSet<>();
UniquePredicate(Function<? super MergedAnnotation<A>, K> keyExtractor) {
Assert.notNull(keyExtractor, "Key extractor must not be null");
this.keyExtractor = keyExtractor;
}
@Override
public boolean test(@Nullable MergedAnnotation<A> annotation) {
K key = this.keyExtractor.apply(annotation);

View File

@ -47,7 +47,6 @@ public interface MergedAnnotationSelector<A extends Annotation> {
* @return the most appropriate annotation from the {@code existing} or
* {@code candidate}
*/
MergedAnnotation<A> select(MergedAnnotation<A> existing,
MergedAnnotation<A> candidate);
MergedAnnotation<A> select(MergedAnnotation<A> existing, MergedAnnotation<A> candidate);
}

View File

@ -70,8 +70,9 @@ public abstract class MergedAnnotationSelectors {
}
@Override
public MergedAnnotation<Annotation> select(MergedAnnotation<Annotation> existing,
MergedAnnotation<Annotation> candidate) {
public MergedAnnotation<Annotation> select(
MergedAnnotation<Annotation> existing, MergedAnnotation<Annotation> candidate) {
if (candidate.getDepth() < existing.getDepth()) {
return candidate;
}
@ -93,8 +94,9 @@ public abstract class MergedAnnotationSelectors {
}
@Override
public MergedAnnotation<Annotation> select(MergedAnnotation<Annotation> existing,
MergedAnnotation<Annotation> candidate) {
public MergedAnnotation<Annotation> select(
MergedAnnotation<Annotation> existing, MergedAnnotation<Annotation> candidate) {
if (existing.getDepth() > 0 && candidate.getDepth() == 0) {
return candidate;
}

View File

@ -133,7 +133,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @param annotationType the annotation type to check
* @return {@code true} if the annotation is present
*/
<A extends Annotation> boolean isPresent(@Nullable Class<A> annotationType);
<A extends Annotation> boolean isPresent(Class<A> annotationType);
/**
* Return if the specified annotation is directly present. Equivalent to
@ -141,7 +141,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @param annotationType the annotation type to check
* @return {@code true} if the annotation is present
*/
boolean isPresent(@Nullable String annotationType);
boolean isPresent(String annotationType);
/**
* Return if the specified annotation is directly present. Equivalent to
@ -149,7 +149,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @param annotationType the annotation type to check
* @return {@code true} if the annotation is present
*/
<A extends Annotation> boolean isDirectlyPresent(@Nullable Class<A> annotationType);
<A extends Annotation> boolean isDirectlyPresent(Class<A> annotationType);
/**
* Return if the specified annotation is either directly present, or
@ -158,7 +158,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @param annotationType the annotation type to check
* @return {@code true} if the annotation is present
*/
boolean isDirectlyPresent(@Nullable String annotationType);
boolean isDirectlyPresent(String annotationType);
/**
* Return the {@link MergedAnnotationSelectors#nearest() nearest} matching
@ -167,7 +167,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @param annotationType the annotation type to get
* @return a {@link MergedAnnotation} instance
*/
<A extends Annotation> MergedAnnotation<A> get(@Nullable Class<A> annotationType);
<A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType);
/**
* Return the {@link MergedAnnotationSelectors#nearest() nearest} matching
@ -179,7 +179,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @return a {@link MergedAnnotation} instance
* @see MergedAnnotationPredicates
*/
<A extends Annotation> MergedAnnotation<A> get(@Nullable Class<A> annotationType,
<A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate);
/**
@ -195,7 +195,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @see MergedAnnotationPredicates
* @see MergedAnnotationSelectors
*/
<A extends Annotation> MergedAnnotation<A> get(@Nullable Class<A> annotationType,
<A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate,
@Nullable MergedAnnotationSelector<A> selector);
@ -206,7 +206,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @param annotationType the annotation type to get
* @return a {@link MergedAnnotation} instance
*/
<A extends Annotation> MergedAnnotation<A> get(@Nullable String annotationType);
<A extends Annotation> MergedAnnotation<A> get(String annotationType);
/**
* Return the {@link MergedAnnotationSelectors#nearest() nearest} matching
@ -218,7 +218,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @return a {@link MergedAnnotation} instance
* @see MergedAnnotationPredicates
*/
<A extends Annotation> MergedAnnotation<A> get(@Nullable String annotationType,
<A extends Annotation> MergedAnnotation<A> get(String annotationType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate);
/**
@ -234,7 +234,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @see MergedAnnotationPredicates
* @see MergedAnnotationSelectors
*/
<A extends Annotation> MergedAnnotation<A> get(@Nullable String annotationType,
<A extends Annotation> MergedAnnotation<A> get(String annotationType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate,
@Nullable MergedAnnotationSelector<A> selector);
@ -245,8 +245,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @param annotationType the annotation type to match
* @return a stream of matching annotations
*/
<A extends Annotation> Stream<MergedAnnotation<A>> stream(
@Nullable Class<A> annotationType);
<A extends Annotation> Stream<MergedAnnotation<A>> stream(Class<A> annotationType);
/**
* Stream all annotations and meta-annotations that match the specified
@ -255,8 +254,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @param annotationType the annotation type to match
* @return a stream of matching annotations
*/
<A extends Annotation> Stream<MergedAnnotation<A>> stream(
@Nullable String annotationType);
<A extends Annotation> Stream<MergedAnnotation<A>> stream(String annotationType);
/**
* Stream all contained annotations and meta-annotations contained in this
@ -269,6 +267,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
*/
Stream<MergedAnnotation<Annotation>> stream();
/**
* Create a new {@link MergedAnnotations} instance containing all
* annotations and meta-annotations from the specified element. The
@ -280,7 +279,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @return a {@link MergedAnnotations} instance containing the element
* annotations
*/
static MergedAnnotations from(@Nullable AnnotatedElement element) {
static MergedAnnotations from(AnnotatedElement element) {
return from(element, SearchStrategy.DIRECT);
}
@ -293,10 +292,8 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @return a {@link MergedAnnotations} instance containing the merged
* element annotations
*/
static MergedAnnotations from(@Nullable AnnotatedElement element,
SearchStrategy searchStrategy) {
return from(element, searchStrategy, RepeatableContainers.standardRepeatables(),
AnnotationFilter.PLAIN);
static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy) {
return from(element, searchStrategy, RepeatableContainers.standardRepeatables(), AnnotationFilter.PLAIN);
}
/**
@ -312,11 +309,10 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @return a {@link MergedAnnotations} instance containing the merged
* element annotations
*/
static MergedAnnotations from(@Nullable AnnotatedElement element,
SearchStrategy searchStrategy, RepeatableContainers repeatableContainers,
AnnotationFilter annotationFilter) {
return TypeMappedAnnotations.from(element, searchStrategy, repeatableContainers,
annotationFilter);
static MergedAnnotations from(AnnotatedElement element, SearchStrategy searchStrategy,
RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
return TypeMappedAnnotations.from(element, searchStrategy, repeatableContainers, annotationFilter);
}
/**
@ -342,8 +338,7 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @see #from(AnnotatedElement)
*/
static MergedAnnotations from(@Nullable Object source, Annotation... annotations) {
return from(source, annotations, RepeatableContainers.standardRepeatables(),
AnnotationFilter.PLAIN);
return from(source, annotations, RepeatableContainers.standardRepeatables(), AnnotationFilter.PLAIN);
}
/**
@ -360,10 +355,9 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* @return a {@link MergedAnnotations} instance containing the annotations
*/
static MergedAnnotations from(@Nullable Object source, Annotation[] annotations,
RepeatableContainers repeatableContainers,
AnnotationFilter annotationFilter) {
return TypeMappedAnnotations.from(source, annotations, repeatableContainers,
annotationFilter);
RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
return TypeMappedAnnotations.from(source, annotations, repeatableContainers, annotationFilter);
}
@ -406,7 +400,6 @@ public interface MergedAnnotations extends Iterable<MergedAnnotation<Annotation>
* not need to be meta-annotated with {@link Inherited @Inherited}.
*/
EXHAUSTIVE
}
}

View File

@ -34,8 +34,7 @@ import org.springframework.lang.Nullable;
* @since 5.2
* @param <A> the annotation type
*/
final class MissingMergedAnnotation<A extends Annotation>
extends AbstractMergedAnnotation<A> {
final class MissingMergedAnnotation<A extends Annotation> extends AbstractMergedAnnotation<A> {
private static final MissingMergedAnnotation<?> INSTANCE = new MissingMergedAnnotation<>();
@ -153,6 +152,7 @@ final class MissingMergedAnnotation<A extends Annotation>
throw new NoSuchElementException("Unable to synthesize missing annotation");
}
@SuppressWarnings("unchecked")
static <A extends Annotation> MergedAnnotation<A> getInstance() {
return (MergedAnnotation<A>) INSTANCE;

View File

@ -92,8 +92,8 @@ public abstract class OrderUtils {
* @param annotations the annotation to consider
* @return the order value, or {@code null} if none can be found
*/
static Integer getOrderFromAnnotations(AnnotatedElement element,
MergedAnnotations annotations) {
@Nullable
static Integer getOrderFromAnnotations(AnnotatedElement element, MergedAnnotations annotations) {
if (!(element instanceof Class)) {
return findOrder(annotations);
}
@ -106,6 +106,7 @@ public abstract class OrderUtils {
return result;
}
@Nullable
private static Integer findOrder(MergedAnnotations annotations) {
MergedAnnotation<Order> orderAnnotation = annotations.get(Order.class);
if (orderAnnotation.isPresent()) {

View File

@ -29,7 +29,7 @@ import org.springframework.util.StringUtils;
* @author Phillip Webb
* @since 5.2
*/
class PackagesAnnotationFilter implements AnnotationFilter {
final class PackagesAnnotationFilter implements AnnotationFilter {
private final String[] prefixes;
@ -40,8 +40,9 @@ class PackagesAnnotationFilter implements AnnotationFilter {
Assert.notNull(packages, "Packages must not be null");
this.prefixes = new String[packages.length];
for (int i = 0; i < packages.length; i++) {
Assert.hasText(packages[i], "Package must not have empty elements");
this.prefixes[i] = packages[i] + ".";
String pkg = packages[i];
Assert.hasText(pkg, "Package must not have empty elements");
this.prefixes[i] = pkg + ".";
}
Arrays.sort(this.prefixes);
this.hashCode = Arrays.hashCode(this.prefixes);
@ -49,27 +50,25 @@ class PackagesAnnotationFilter implements AnnotationFilter {
@Override
public boolean matches(@Nullable String annotationType) {
if (annotationType != null) {
for (String prefix : this.prefixes) {
if (annotationType.startsWith(prefix)) {
return true;
}
public boolean matches(String annotationType) {
for (String prefix : this.prefixes) {
if (annotationType.startsWith(prefix)) {
return true;
}
}
return false;
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
if (other == null || getClass() != other.getClass()) {
return false;
}
PackagesAnnotationFilter other = (PackagesAnnotationFilter) obj;
return Arrays.equals(this.prefixes, other.prefixes);
return Arrays.equals(this.prefixes, ((PackagesAnnotationFilter) other).prefixes);
}
@Override

View File

@ -73,16 +73,16 @@ public abstract class RepeatableContainers {
return this.parent.findRepeatedAnnotations(annotation);
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj == this) {
public boolean equals(@Nullable Object other) {
if (other == this) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
if (other == null || getClass() != other.getClass()) {
return false;
}
RepeatableContainers other = (RepeatableContainers) obj;
return Objects.equals(this.parent, other.parent);
return Objects.equals(this.parent, ((RepeatableContainers) other).parent);
}
@Override
@ -90,6 +90,7 @@ public abstract class RepeatableContainers {
return ObjectUtils.nullSafeHashCode(this.parent);
}
/**
* Return a {@link RepeatableContainers} instance that searches using Java's
* {@link Repeatable @Repeatable} annotation.
@ -198,10 +199,8 @@ public abstract class RepeatableContainers {
private final Method valueMethod;
ExplicitRepeatableContainer(@Nullable RepeatableContainers parent,
Class<? extends Annotation> repeatable,
@Nullable Class<? extends Annotation> container) {
Class<? extends Annotation> repeatable, @Nullable Class<? extends Annotation> container) {
super(parent);
Assert.notNull(repeatable, "Repeatable must not be null");
@ -235,11 +234,9 @@ public abstract class RepeatableContainers {
this.valueMethod = valueMethod;
}
private Class<? extends Annotation> deduceContainer(
Class<? extends Annotation> repeatable) {
private Class<? extends Annotation> deduceContainer(Class<? extends Annotation> repeatable) {
Repeatable annotation = repeatable.getAnnotation(Repeatable.class);
Assert.notNull(annotation, "Annotation type must be a repeatable annotation: " +
Assert.notNull(annotation, () -> "Annotation type must be a repeatable annotation: " +
"failed to resolve container type for " + repeatable.getName());
return annotation.value();
}
@ -254,13 +251,12 @@ public abstract class RepeatableContainers {
}
@Override
public boolean equals(@Nullable Object obj) {
if (super.equals(obj)) {
ExplicitRepeatableContainer other = (ExplicitRepeatableContainer) obj;
return this.container.equals(other.container) &&
this.repeatable.equals(other.repeatable);
public boolean equals(@Nullable Object other) {
if (!super.equals(other)) {
return false;
}
return false;
ExplicitRepeatableContainer otherErc = (ExplicitRepeatableContainer) other;
return (this.container.equals(otherErc.container) && this.repeatable.equals(otherErc.repeatable));
}
@Override
@ -270,7 +266,6 @@ public abstract class RepeatableContainers {
hashCode = 31 * hashCode + this.repeatable.hashCode();
return hashCode;
}
}
@ -284,7 +279,6 @@ public abstract class RepeatableContainers {
NoRepeatableContainers() {
super(null);
}
}
}

View File

@ -33,8 +33,8 @@ import org.springframework.util.ReflectionUtils;
/**
* {@link InvocationHandler} for an {@link Annotation} that Spring has
* <em>synthesized</em> (i.e., wrapped in a dynamic proxy) with additional
* functionality.
* <em>synthesized</em> (i.e. wrapped in a dynamic proxy) with additional
* functionality such as attribute alias handling.
*
* @author Sam Brannen
* @author Phillip Webb
@ -44,8 +44,7 @@ import org.springframework.util.ReflectionUtils;
* @see AnnotationAttributeExtractor
* @see AnnotationUtils#synthesizeAnnotation(Annotation, AnnotatedElement)
*/
class SynthesizedMergedAnnotationInvocationHandler<A extends Annotation>
implements InvocationHandler {
final class SynthesizedMergedAnnotationInvocationHandler<A extends Annotation> implements InvocationHandler {
private final MergedAnnotation<?> annotation;
@ -57,10 +56,8 @@ class SynthesizedMergedAnnotationInvocationHandler<A extends Annotation>
private volatile Integer hashCode;
private SynthesizedMergedAnnotationInvocationHandler(MergedAnnotation<A> annotation,
Class<A> type) {
Assert.notNull(annotation, "Annotation must not be null");
private SynthesizedMergedAnnotationInvocationHandler(MergedAnnotation<A> annotation, Class<A> type) {
Assert.notNull(annotation, "MergedAnnotation must not be null");
Assert.notNull(type, "Type must not be null");
Assert.isTrue(type.isAnnotation(), "Type must be an annotation");
this.annotation = annotation;
@ -90,18 +87,15 @@ class SynthesizedMergedAnnotationInvocationHandler<A extends Annotation>
return getAttributeValue(method);
}
throw new AnnotationConfigurationException(String.format(
"Method [%s] is unsupported for synthesized annotation type [%s]", method,
this.type));
"Method [%s] is unsupported for synthesized annotation type [%s]", method, this.type));
}
private boolean isAnnotationTypeMethod(Method method) {
return Objects.equals(method.getName(), "annotationType")
&& method.getParameterCount() == 0;
return (Objects.equals(method.getName(), "annotationType") && method.getParameterCount() == 0);
}
/**
* See {@link Annotation#equals(Object)} for a definition of the required
* algorithm.
* See {@link Annotation#equals(Object)} for a definition of the required algorithm.
* @param other the other object to compare against
*/
private boolean annotationEquals(Object other) {
@ -123,8 +117,7 @@ class SynthesizedMergedAnnotationInvocationHandler<A extends Annotation>
}
/**
* See {@link Annotation#hashCode()} for a definition of the required
* algorithm.
* See {@link Annotation#hashCode()} for a definition of the required algorithm.
*/
private int annotationHashCode() {
Integer hashCode = this.hashCode;
@ -182,26 +175,22 @@ class SynthesizedMergedAnnotationInvocationHandler<A extends Annotation>
String name = method.getName();
Class<?> type = ClassUtils.resolvePrimitiveIfNecessary(method.getReturnType());
return this.annotation.getValue(name, type).orElseThrow(
() -> new NoSuchElementException("No value found for attribute named '"
+ name + "' in merged annotation " + this.annotation.getType()));
() -> new NoSuchElementException("No value found for attribute named '" + name +
"' in merged annotation " + this.annotation.getType()));
}
@SuppressWarnings("unchecked")
static <A extends Annotation> A createProxy(MergedAnnotation<A> annotation,
Class<A> type) {
static <A extends Annotation> A createProxy(MergedAnnotation<A> annotation, Class<A> type) {
ClassLoader classLoader = type.getClassLoader();
InvocationHandler handler = new SynthesizedMergedAnnotationInvocationHandler<>(
annotation, type);
Class<?>[] interfaces = isVisible(classLoader, SynthesizedAnnotation.class)
? new Class<?>[] { type, SynthesizedAnnotation.class }
: new Class<?>[] { type };
InvocationHandler handler = new SynthesizedMergedAnnotationInvocationHandler<>(annotation, type);
Class<?>[] interfaces = isVisible(classLoader, SynthesizedAnnotation.class) ?
new Class<?>[] {type, SynthesizedAnnotation.class} : new Class<?>[] {type};
return (A) Proxy.newProxyInstance(classLoader, interfaces, handler);
}
private static boolean isVisible(ClassLoader classLoader, Class<?> interfaceClass) {
try {
return Class.forName(interfaceClass.getName(), false,
classLoader) == interfaceClass;
return Class.forName(interfaceClass.getName(), false, classLoader) == interfaceClass;
}
catch (ClassNotFoundException ex) {
return false;

View File

@ -190,13 +190,12 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
@Override
@SuppressWarnings("unchecked")
public <T extends Annotation> MergedAnnotation<T> getAnnotation(String attributeName,
Class<T> type) throws NoSuchElementException {
public <T extends Annotation> MergedAnnotation<T> getAnnotation(String attributeName, Class<T> type)
throws NoSuchElementException {
Assert.notNull(attributeName, "AttributeName must not be null");
Assert.notNull(type, "Type must not be null");
int attributeIndex = getAttributeIndex(attributeName, true);
Method attribute = this.mapping.getAttributes().get(attributeIndex);
Assert.notNull(type, "Type must not be null");
Assert.isAssignable(type, attribute.getReturnType(),
"Attribute " + attributeName + " type mismatch:");
return (MergedAnnotation<T>) getRequiredValue(attributeIndex, Object.class);
@ -207,13 +206,12 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
public <T extends Annotation> MergedAnnotation<T>[] getAnnotationArray(
String attributeName, Class<T> type) throws NoSuchElementException {
Assert.notNull(attributeName, "AttributeName must not be null");
Assert.notNull(type, "Type must not be null");
int attributeIndex = getAttributeIndex(attributeName, true);
Method attribute = this.mapping.getAttributes().get(attributeIndex);
Class<?> componentType = attribute.getReturnType().getComponentType();
Assert.notNull(type, "Type must not be null");
Assert.notNull(componentType, () -> "Attribute " + attributeName + " is not an array");
Assert.isAssignable(type, componentType, "Attribute " + attributeName + " component type mismatch:");
Assert.isAssignable(type, componentType, () -> "Attribute " + attributeName + " component type mismatch:");
return (MergedAnnotation<T>[]) getRequiredValue(attributeIndex, Object.class);
}
@ -229,7 +227,6 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
@Override
public MergedAnnotation<A> filterAttributes(Predicate<String> predicate) {
Assert.notNull(predicate, "Predicate must not be null");
if (this.attributeFilter != null) {
predicate = this.attributeFilter.and(predicate);
}
@ -250,9 +247,8 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
public <T extends Map<String, Object>> T asMap(
@Nullable Function<MergedAnnotation<?>, T> factory, MapValues... options) {
T map = factory != null ? factory.apply(this) : (T) new LinkedHashMap<String, Object>();
Assert.state(map != null,
"Factory used to create MergedAnnotation Map must not return null;");
T map = (factory != null ? factory.apply(this) : (T) new LinkedHashMap<String, Object>());
Assert.state(map != null, "Factory used to create MergedAnnotation Map must not return null");
AttributeMethods attributes = this.mapping.getAttributes();
for (int i = 0; i < attributes.size(); i++) {
Method attribute = attributes.get(i);
@ -361,14 +357,13 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
@Nullable
protected <T> T getAttributeValue(String attributeName, Class<T> type) {
int attributeIndex = getAttributeIndex(attributeName, false);
return attributeIndex != -1 ? getValue(attributeIndex, type) : null;
return (attributeIndex != -1 ? getValue(attributeIndex, type) : null);
}
protected final <T> T getRequiredValue(int attributeIndex, Class<T> type) {
T value = getValue(attributeIndex, type);
if (value == null) {
throw new NoSuchElementException(
"No element at attribute index " + attributeIndex);
throw new NoSuchElementException("No element at attribute index " + attributeIndex);
}
return value;
}
@ -457,8 +452,7 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
MergedAnnotation<?> annotation = (MergedAnnotation<?>) value;
value = annotation.synthesize();
}
else if (value instanceof MergedAnnotation[] && type.isArray()
&& type.getComponentType().isAnnotation()) {
else if (value instanceof MergedAnnotation[] && type.isArray() && type.getComponentType().isAnnotation()) {
MergedAnnotation<?>[] annotations = (MergedAnnotation<?>[]) value;
Object array = Array.newInstance(type.getComponentType(), annotations.length);
for (int i = 0; i < annotations.length; i++) {
@ -484,8 +478,7 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
if (attributeType.isAnnotation()) {
return adaptToMergedAnnotation(value,(Class<? extends Annotation>) attributeType);
}
if (attributeType.isArray() &&
attributeType.getComponentType().isAnnotation() &&
if (attributeType.isArray() && attributeType.getComponentType().isAnnotation() &&
value.getClass().isArray()) {
MergedAnnotation<?>[] result = new MergedAnnotation<?>[Array.getLength(value)];
for (int i = 0; i < result.length; i++) {
@ -539,10 +532,9 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
}
private int getAttributeIndex(String attributeName, boolean required) {
Assert.hasText(attributeName, "AttributeName must not be null");
int attributeIndex = isFiltered(attributeName) ?
-1 :
this.mapping.getAttributes().indexOf(attributeName);
Assert.hasText(attributeName, "Attribute name must not be null");
int attributeIndex = (isFiltered(attributeName) ? -1 :
this.mapping.getAttributes().indexOf(attributeName));
if (attributeIndex == -1 && required) {
throw new NoSuchElementException("No attribute named '" + attributeName +
"' present in merged annotation " + getType());
@ -562,20 +554,16 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
return (Class<A>) this.mapping.getAnnotationType();
}
static <A extends Annotation> MergedAnnotation<A> from(@Nullable Object source,
A annotation) {
static <A extends Annotation> MergedAnnotation<A> from(@Nullable Object source, A annotation) {
Assert.notNull(annotation, "Annotation must not be null");
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(
annotation.annotationType());
return new TypeMappedAnnotation<>(mappings.get(0), source, annotation,
ReflectionUtils::invokeMethod, 0);
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(annotation.annotationType());
return new TypeMappedAnnotation<>(mappings.get(0), source, annotation, ReflectionUtils::invokeMethod, 0);
}
static <A extends Annotation> MergedAnnotation<A> from(@Nullable Object source,
Class<A> annotationType, @Nullable Map<String, ?> attributes) {
Assert.notNull(annotationType, "AnnotationType must not be null");
Assert.notNull(annotationType, "Annotation type must not be null");
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(annotationType);
return new TypeMappedAnnotation<>(mappings.get(0), source, attributes,
TypeMappedAnnotation::extractFromMap, 0);
@ -596,9 +584,8 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
}
if (logger.isEnabled()) {
String type = mapping.getAnnotationType().getName();
String item = mapping.getDepth() == 0 ?
"annotation " + type :
"meta-annotation " + type + " from " + mapping.getRoot().getAnnotationType().getName();
String item = (mapping.getDepth() == 0 ? "annotation " + type :
"meta-annotation " + type + " from " + mapping.getRoot().getAnnotationType().getName());
logger.log("Failed to introspect " + item, source, ex);
}
return null;
@ -608,7 +595,7 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
@SuppressWarnings("unchecked")
@Nullable
private static Object extractFromMap(Method attribute, @Nullable Object map) {
return map != null ? ((Map<String, ?>) map).get(attribute.getName()) : null;
return (map != null ? ((Map<String, ?>) map).get(attribute.getName()) : null);
}
}

View File

@ -36,14 +36,14 @@ import org.springframework.lang.Nullable;
* annotations and meta-annotations using {@link AnnotationTypeMappings}.
*
* @author Phillip Webb
* @since 5.1
* @since 5.2
*/
final class TypeMappedAnnotations implements MergedAnnotations {
private static final AnnotationFilter FILTER_ALL = annotationType -> true;
private static final MergedAnnotations NONE = new TypeMappedAnnotations(null,
new Annotation[0], RepeatableContainers.none(), FILTER_ALL);
private static final MergedAnnotations NONE = new TypeMappedAnnotations(
null, new Annotation[0], RepeatableContainers.none(), FILTER_ALL);
@Nullable
@ -67,8 +67,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
private TypeMappedAnnotations(AnnotatedElement element, SearchStrategy searchStrategy,
RepeatableContainers repeatableContainers,
AnnotationFilter annotationFilter) {
RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
this.source = element;
this.element = element;
@ -79,8 +78,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
}
private TypeMappedAnnotations(@Nullable Object source, Annotation[] annotations,
RepeatableContainers repeatableContainers,
AnnotationFilter annotationFilter) {
RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
this.source = source;
this.element = null;
@ -92,8 +90,8 @@ final class TypeMappedAnnotations implements MergedAnnotations {
@Override
public <A extends Annotation> boolean isPresent(@Nullable Class<A> annotationType) {
if (annotationType == null || this.annotationFilter.matches(annotationType)) {
public <A extends Annotation> boolean isPresent(Class<A> annotationType) {
if (this.annotationFilter.matches(annotationType)) {
return false;
}
return Boolean.TRUE.equals(scan(annotationType,
@ -101,8 +99,8 @@ final class TypeMappedAnnotations implements MergedAnnotations {
}
@Override
public boolean isPresent(@Nullable String annotationType) {
if (annotationType == null || this.annotationFilter.matches(annotationType)) {
public boolean isPresent(String annotationType) {
if (this.annotationFilter.matches(annotationType)) {
return false;
}
return Boolean.TRUE.equals(scan(annotationType,
@ -119,8 +117,8 @@ final class TypeMappedAnnotations implements MergedAnnotations {
}
@Override
public boolean isDirectlyPresent(@Nullable String annotationType) {
if (annotationType == null || this.annotationFilter.matches(annotationType)) {
public boolean isDirectlyPresent(String annotationType) {
if (this.annotationFilter.matches(annotationType)) {
return false;
}
return Boolean.TRUE.equals(scan(annotationType,
@ -128,57 +126,53 @@ final class TypeMappedAnnotations implements MergedAnnotations {
}
@Override
public <A extends Annotation> MergedAnnotation<A> get(
@Nullable Class<A> annotationType) {
public <A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType) {
return get(annotationType, null, null);
}
@Override
public <A extends Annotation> MergedAnnotation<A> get(
@Nullable Class<A> annotationType,
public <A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate) {
return get(annotationType, predicate, null);
}
@Override
public <A extends Annotation> MergedAnnotation<A> get(
@Nullable Class<A> annotationType,
public <A extends Annotation> MergedAnnotation<A> get(Class<A> annotationType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate,
@Nullable MergedAnnotationSelector<A> selector) {
if (annotationType == null || this.annotationFilter.matches(annotationType)) {
if (this.annotationFilter.matches(annotationType)) {
return MergedAnnotation.missing();
}
MergedAnnotation<A> result = scan(annotationType,
new MergedAnnotationFinder<>(annotationType, predicate, selector));
return result != null ? result : MergedAnnotation.missing();
return (result != null ? result : MergedAnnotation.missing());
}
@Override
public <A extends Annotation> MergedAnnotation<A> get(
@Nullable String annotationType) {
public <A extends Annotation> MergedAnnotation<A> get(String annotationType) {
return get(annotationType, null, null);
}
@Override
public <A extends Annotation> MergedAnnotation<A> get(@Nullable String annotationType,
public <A extends Annotation> MergedAnnotation<A> get(String annotationType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate) {
return get(annotationType, predicate, null);
}
@Override
public <A extends Annotation> MergedAnnotation<A> get(@Nullable String annotationType,
public <A extends Annotation> MergedAnnotation<A> get(String annotationType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate,
@Nullable MergedAnnotationSelector<A> selector) {
if (annotationType == null || this.annotationFilter.matches(annotationType)) {
if (this.annotationFilter.matches(annotationType)) {
return MergedAnnotation.missing();
}
MergedAnnotation<A> result = scan(annotationType,
new MergedAnnotationFinder<>(annotationType, predicate, selector));
return result != null ? result : MergedAnnotation.missing();
return (result != null ? result : MergedAnnotation.missing());
}
@Override
@ -261,13 +255,11 @@ final class TypeMappedAnnotations implements MergedAnnotations {
if (element == null || AnnotationsScanner.isKnownEmpty(element, searchStrategy, annotationFilter)) {
return NONE;
}
return new TypeMappedAnnotations(element, searchStrategy, repeatableContainers,
annotationFilter);
return new TypeMappedAnnotations(element, searchStrategy, repeatableContainers, annotationFilter);
}
static MergedAnnotations from(@Nullable Object source,
Annotation[] annotations, RepeatableContainers repeatableContainers,
AnnotationFilter annotationFilter) {
static MergedAnnotations from(@Nullable Object source, Annotation[] annotations,
RepeatableContainers repeatableContainers, AnnotationFilter annotationFilter) {
if (annotations.length == 0) {
return NONE;
@ -282,8 +274,8 @@ final class TypeMappedAnnotations implements MergedAnnotations {
return false;
}
Class<? extends Annotation> actualType = mapping.getAnnotationType();
return !annotationFilter.matches(actualType) &&
(requiredType == null || actualType == requiredType || actualType.getName().equals(requiredType));
return (!annotationFilter.matches(actualType) &&
(requiredType == null || actualType == requiredType || actualType.getName().equals(requiredType)));
}
@ -291,8 +283,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
* {@link AnnotationsProcessor} used to detect if an annotation is directly
* or meta-present.
*/
private static final class IsPresent
implements AnnotationsProcessor<Object, Boolean> {
private static final class IsPresent implements AnnotationsProcessor<Object, Boolean> {
/**
* Shared instances that save us needing to create a new processor for
@ -307,14 +298,12 @@ final class TypeMappedAnnotations implements MergedAnnotations {
SHARED[3] = new IsPresent(RepeatableContainers.standardRepeatables(), AnnotationFilter.PLAIN, false);
}
private final RepeatableContainers repeatableContainers;
private final AnnotationFilter annotationFilter;
private final boolean directOnly;
private IsPresent(RepeatableContainers repeatableContainers,
AnnotationFilter annotationFilter, boolean directOnly) {
@ -323,7 +312,6 @@ final class TypeMappedAnnotations implements MergedAnnotations {
this.directOnly = directOnly;
}
@Override
@Nullable
public Boolean doWithAnnotations(Object requiredType, int aggregateIndex,
@ -374,7 +362,6 @@ final class TypeMappedAnnotations implements MergedAnnotations {
}
return new IsPresent(repeatableContainers, annotationFilter, directOnly);
}
}
@ -395,18 +382,14 @@ final class TypeMappedAnnotations implements MergedAnnotations {
@Nullable
private MergedAnnotation<A> result;
MergedAnnotationFinder(Object requiredType,
@Nullable Predicate<? super MergedAnnotation<A>> predicate,
MergedAnnotationFinder(Object requiredType, @Nullable Predicate<? super MergedAnnotation<A>> predicate,
@Nullable MergedAnnotationSelector<A> selector) {
this.requiredType = requiredType;
this.predicate = predicate;
this.selector = selector != null ? selector
: MergedAnnotationSelectors.nearest();
this.selector = (selector != null ? selector : MergedAnnotationSelectors.nearest());
}
@Override
@Nullable
public MergedAnnotation<A> doWithAggregate(Object context, int aggregateIndex) {
@ -431,26 +414,21 @@ final class TypeMappedAnnotations implements MergedAnnotations {
}
@Nullable
private MergedAnnotation<A> process(Object type, int aggregateIndex,
@Nullable Object source, Annotation annotation) {
Annotation[] repeatedAnnotations = repeatableContainers.findRepeatedAnnotations(
annotation);
private MergedAnnotation<A> process(
Object type, int aggregateIndex, @Nullable Object source, Annotation annotation) {
Annotation[] repeatedAnnotations = repeatableContainers.findRepeatedAnnotations(annotation);
if (repeatedAnnotations != null) {
return doWithAnnotations(type, aggregateIndex, source,
repeatedAnnotations);
return doWithAnnotations(type, aggregateIndex, source, repeatedAnnotations);
}
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(
annotation.annotationType(),
annotationFilter);
annotation.annotationType(), annotationFilter);
for (int i = 0; i < mappings.size(); i++) {
AnnotationTypeMapping mapping = mappings.get(i);
if (isMappingForType(mapping, annotationFilter,
this.requiredType)) {
if (isMappingForType(mapping, annotationFilter, this.requiredType)) {
MergedAnnotation<A> candidate = TypeMappedAnnotation.createIfPossible(
mapping, source, annotation, aggregateIndex,
IntrospectionFailureLogger.INFO);
if (candidate != null && (this.predicate == null
|| this.predicate.test(candidate))) {
mapping, source, annotation, aggregateIndex, IntrospectionFailureLogger.INFO);
if (candidate != null && (this.predicate == null || this.predicate.test(candidate))) {
if (this.selector.isBestCandidate(candidate)) {
return candidate;
}
@ -463,24 +441,21 @@ final class TypeMappedAnnotations implements MergedAnnotations {
private void updateLastResult(MergedAnnotation<A> candidate) {
MergedAnnotation<A> lastResult = this.result;
this.result = lastResult != null
? this.selector.select(lastResult, candidate)
: candidate;
this.result = (lastResult != null ? this.selector.select(lastResult, candidate) : candidate);
}
@Override
@Nullable
public MergedAnnotation<A> finish(@Nullable MergedAnnotation<A> result) {
return result != null ? result : this.result;
return (result != null ? result : this.result);
}
}
/**
* {@link AnnotationsProcessor} that collects {@link Aggregate} instances.
*/
private class AggregatesCollector
implements AnnotationsProcessor<Object, List<Aggregate>> {
private class AggregatesCollector implements AnnotationsProcessor<Object, List<Aggregate>> {
private final List<Aggregate> aggregates = new ArrayList<>();
@ -488,12 +463,12 @@ final class TypeMappedAnnotations implements MergedAnnotations {
@Nullable
public List<Aggregate> doWithAnnotations(Object criteria, int aggregateIndex,
@Nullable Object source, Annotation[] annotations) {
this.aggregates.add(createAggregate(aggregateIndex, source, annotations));
return null;
}
private Aggregate createAggregate(int aggregateIndex, @Nullable Object source,
Annotation[] annotations) {
private Aggregate createAggregate(int aggregateIndex, @Nullable Object source, Annotation[] annotations) {
List<Annotation> aggregateAnnotations = getAggregateAnnotations(annotations);
return new Aggregate(aggregateIndex, source, aggregateAnnotations);
}
@ -504,17 +479,12 @@ final class TypeMappedAnnotations implements MergedAnnotations {
return result;
}
private void addAggregateAnnotations(List<Annotation> aggregateAnnotations,
Annotation[] annotations) {
private void addAggregateAnnotations(List<Annotation> aggregateAnnotations, Annotation[] annotations) {
for (Annotation annotation : annotations) {
if (annotation != null
&& !annotationFilter.matches(
annotation)) {
Annotation[] repeatedAnnotations = repeatableContainers.findRepeatedAnnotations(
annotation);
if (annotation != null && !annotationFilter.matches(annotation)) {
Annotation[] repeatedAnnotations = repeatableContainers.findRepeatedAnnotations(annotation);
if (repeatedAnnotations != null) {
addAggregateAnnotations(aggregateAnnotations,
repeatedAnnotations);
addAggregateAnnotations(aggregateAnnotations, repeatedAnnotations);
}
else {
aggregateAnnotations.add(annotation);
@ -527,9 +497,9 @@ final class TypeMappedAnnotations implements MergedAnnotations {
public List<Aggregate> finish(@Nullable List<Aggregate> processResult) {
return this.aggregates;
}
}
private static class Aggregate {
private final int aggregateIndex;
@ -541,8 +511,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
private final AnnotationTypeMappings[] mappings;
Aggregate(int aggregateIndex, @Nullable Object source,
List<Annotation> annotations) {
Aggregate(int aggregateIndex, @Nullable Object source, List<Annotation> annotations) {
this.aggregateIndex = aggregateIndex;
this.source = source;
this.annotations = annotations;
@ -575,15 +544,14 @@ final class TypeMappedAnnotations implements MergedAnnotations {
this.mappings[annotationIndex].get(mappingIndex), this.source,
this.annotations.get(annotationIndex), this.aggregateIndex, logger);
}
}
/**
* {@link Spliterator} used to consume merged annotations from the
* aggregates in depth fist order.
*/
private class AggregatesSpliterator<A extends Annotation>
implements Spliterator<MergedAnnotation<A>> {
private class AggregatesSpliterator<A extends Annotation> implements Spliterator<MergedAnnotation<A>> {
@Nullable
private final Object requiredType;
@ -595,8 +563,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
@Nullable
private int[] mappingCursors;
AggregatesSpliterator(@Nullable Object requiredType,
List<Aggregate> aggregates) {
AggregatesSpliterator(@Nullable Object requiredType, List<Aggregate> aggregates) {
this.requiredType = requiredType;
this.aggregates = aggregates;
this.aggregateCursor = 0;
@ -614,8 +581,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
return false;
}
private boolean tryAdvance(Aggregate aggregate,
Consumer<? super MergedAnnotation<A>> action) {
private boolean tryAdvance(Aggregate aggregate, Consumer<? super MergedAnnotation<A>> action) {
if (this.mappingCursors == null) {
this.mappingCursors = new int[aggregate.size()];
}
@ -646,8 +612,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
}
@Nullable
private AnnotationTypeMapping getNextSuitableMapping(Aggregate aggregate,
int annotationIndex) {
private AnnotationTypeMapping getNextSuitableMapping(Aggregate aggregate, int annotationIndex) {
int[] cursors = this.mappingCursors;
if (cursors != null) {
AnnotationTypeMapping mapping;
@ -691,7 +656,6 @@ final class TypeMappedAnnotations implements MergedAnnotations {
public int characteristics() {
return NONNULL | IMMUTABLE;
}
}
}

View File

@ -35,8 +35,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
import org.springframework.lang.Nullable;
import org.springframework.util.ConcurrentReferenceHashMap.Reference;
import org.springframework.util.ConcurrentReferenceHashMap.Restructure;
/**
* A {@link ConcurrentHashMap} that uses {@link ReferenceType#SOFT soft} or
@ -579,7 +577,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
}
}
private void restructure(boolean allowResize, Reference<K, V> ref) {
private void restructure(boolean allowResize, @Nullable Reference<K, V> ref) {
boolean needsResize;
lock();
try {

View File

@ -700,17 +700,12 @@ public class AnnotatedElementUtilsTests {
assertArrayEquals("path attribute: ", asArray("/test"), webMapping.path());
}
@Test
public void javaLangAnnotationTypeViaFindMergedAnnotation() throws Exception {
Constructor<?> deprecatedCtor = Date.class.getConstructor(String.class);
assertEquals(deprecatedCtor.getAnnotation(Deprecated.class), findMergedAnnotation(deprecatedCtor, Deprecated.class));
assertEquals(Date.class.getAnnotation(Deprecated.class), findMergedAnnotation(Date.class, Deprecated.class));
}
@Test
public void javaxAnnotationTypeViaFindMergedAnnotation() throws Exception {
assertEquals(ResourceHolder.class.getAnnotation(Resource.class), findMergedAnnotation(ResourceHolder.class, Resource.class));
assertEquals(SpringAppConfigClass.class.getAnnotation(Resource.class), findMergedAnnotation(SpringAppConfigClass.class, Resource.class));
assertEquals(ResourceHolder.class.getAnnotation(Resource.class),
findMergedAnnotation(ResourceHolder.class, Resource.class));
assertEquals(SpringAppConfigClass.class.getAnnotation(Resource.class),
findMergedAnnotation(SpringAppConfigClass.class, Resource.class));
}
@Test

View File

@ -16,19 +16,16 @@
package org.springframework.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.*;
/**
* Tests for {@link AnnotationFilter}.
@ -37,35 +34,22 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
*/
public class AnnotationFilterTests {
private static final AnnotationFilter FILTER = annotationType -> ObjectUtils.nullSafeEquals(
annotationType, TestAnnotation.class.getName());
private static final AnnotationFilter FILTER = annotationType ->
ObjectUtils.nullSafeEquals(annotationType, TestAnnotation.class.getName());
@Test
public void matchesAnnotationWhenAnnotationIsNullReturnsFalse() {
TestAnnotation annotation = null;
assertThat(FILTER.matches(annotation)).isFalse();
}
@Test
public void matchesAnnotationWhenMatchReturnsTrue() {
TestAnnotation annotation = WithTestAnnotation.class.getDeclaredAnnotation(
TestAnnotation.class);
TestAnnotation annotation = WithTestAnnotation.class.getDeclaredAnnotation(TestAnnotation.class);
assertThat(FILTER.matches(annotation)).isTrue();
}
@Test
public void matchesAnnotationWhenNoMatchReturnsFalse() {
OtherAnnotation annotation = WithOtherAnnotation.class.getDeclaredAnnotation(
OtherAnnotation.class);
OtherAnnotation annotation = WithOtherAnnotation.class.getDeclaredAnnotation(OtherAnnotation.class);
assertThat(FILTER.matches(annotation)).isFalse();
}
@Test
public void matchesAnnotationClassWhenAnnotationClassIsNullReturnsFalse() {
Class<Annotation> annotationType = null;
assertThat(FILTER.matches(annotationType)).isFalse();
}
@Test
public void matchesAnnotationClassWhenMatchReturnsTrue() {
Class<TestAnnotation> annotationType = TestAnnotation.class;
@ -109,27 +93,15 @@ public class AnnotationFilterTests {
}
@Test
public void noneWhenNonNullReturnsFalse() {
public void noneReturnsFalse() {
assertThat(AnnotationFilter.NONE.matches(Retention.class)).isFalse();
assertThat(AnnotationFilter.NONE.matches(Nullable.class)).isFalse();
assertThat(AnnotationFilter.NONE.matches(TestAnnotation.class)).isFalse();
assertThat(AnnotationFilter.NONE.matches((Annotation) null)).isFalse();
assertThat(AnnotationFilter.NONE.matches((Class<Annotation>) null)).isFalse();
assertThat(AnnotationFilter.NONE.matches((String) null)).isFalse();
}
@Test
public void pacakgesReturnsPackagesAnnotationFilter() {
assertThat(AnnotationFilter.packages("com.example")).isInstanceOf(
PackagesAnnotationFilter.class);
}
@Test
public void mostAppropriateForCollectionWhenAnnotationTypesIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> AnnotationFilter.mostAppropriateFor(
(Collection<Class<? extends Annotation>>) null)).withMessage(
"AnnotationTypes must not be null");
assertThat(AnnotationFilter.packages("com.example")).isInstanceOf(PackagesAnnotationFilter.class);
}
@Test
@ -146,14 +118,6 @@ public class AnnotationFilterTests {
assertThat(filter).isSameAs(AnnotationFilter.NONE);
}
@Test
public void mostAppropriateForArrayWhenAnnotationTypesIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> AnnotationFilter.mostAppropriateFor(
(Class<? extends Annotation>[]) null)).withMessage(
"AnnotationTypes must not be null");
}
@Test
public void mostAppropriateForArrayReturnsPlainWhenPossible() {
AnnotationFilter filter = AnnotationFilter.mostAppropriateFor(
@ -168,24 +132,21 @@ public class AnnotationFilterTests {
assertThat(filter).isSameAs(AnnotationFilter.NONE);
}
@Retention(RetentionPolicy.RUNTIME)
static @interface TestAnnotation {
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation {
}
@TestAnnotation
static class WithTestAnnotation {
}
@Retention(RetentionPolicy.RUNTIME)
static @interface OtherAnnotation {
@interface OtherAnnotation {
}
@OtherAnnotation
static class WithOtherAnnotation {
}
}

View File

@ -28,7 +28,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.junit.Test;
@ -47,35 +46,24 @@ import static org.assertj.core.api.Assertions.*;
*/
public class AnnotationTypeMappingsTests {
@Test
public void forAnnotationTypeWhenAnnotationIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> AnnotationTypeMappings.forAnnotationType(null)).withMessage(
"AnnotationType must not be null");
}
@Test
public void forAnnotationTypeWhenNoMetaAnnotationsReturnsMappings() {
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(
SimpleAnnotation.class);
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(SimpleAnnotation.class);
assertThat(mappings.size()).isEqualTo(1);
assertThat(mappings.get(0).getAnnotationType()).isEqualTo(SimpleAnnotation.class);
assertThat(getAll(mappings)).flatExtracting(
AnnotationTypeMapping::getAnnotationType).containsExactly(
SimpleAnnotation.class);
AnnotationTypeMapping::getAnnotationType).containsExactly(SimpleAnnotation.class);
}
@Test
public void forAnnotationWhenHasSpringAnnotationReturnsFilteredMappings() {
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(
WithSpringLangAnnotation.class);
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(WithSpringLangAnnotation.class);
assertThat(mappings.size()).isEqualTo(1);
}
@Test
public void forAnnotationTypeWhenMetaAnnotationsReturnsMappings() {
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(
MetaAnnotated.class);
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(MetaAnnotated.class);
assertThat(mappings.size()).isEqualTo(6);
assertThat(getAll(mappings)).flatExtracting(
AnnotationTypeMapping::getAnnotationType).containsExactly(
@ -85,33 +73,27 @@ public class AnnotationTypeMappingsTests {
@Test
public void forAnnotationTypeWhenHasRepeatingMetaAnnotationReturnsMapping() {
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(
WithRepeatedMetaAnnotations.class);
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(WithRepeatedMetaAnnotations.class);
assertThat(mappings.size()).isEqualTo(3);
assertThat(getAll(mappings)).flatExtracting(
AnnotationTypeMapping::getAnnotationType).containsExactly(
WithRepeatedMetaAnnotations.class, Repeating.class,
Repeating.class);
WithRepeatedMetaAnnotations.class, Repeating.class, Repeating.class);
}
@Test
public void forAnnotationTypeWhenSelfAnnotatedReturnsMapping() {
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(
SelfAnnotated.class);
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(SelfAnnotated.class);
assertThat(mappings.size()).isEqualTo(1);
assertThat(getAll(mappings)).flatExtracting(
AnnotationTypeMapping::getAnnotationType).containsExactly(
SelfAnnotated.class);
AnnotationTypeMapping::getAnnotationType).containsExactly(SelfAnnotated.class);
}
@Test
public void forAnnotationTypeWhenFormsLoopReturnsMapping() {
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(
LoopA.class);
AnnotationTypeMappings mappings = AnnotationTypeMappings.forAnnotationType(LoopA.class);
assertThat(mappings.size()).isEqualTo(2);
assertThat(getAll(mappings)).flatExtracting(
AnnotationTypeMapping::getAnnotationType).containsExactly(LoopA.class,
LoopB.class);
AnnotationTypeMapping::getAnnotationType).containsExactly(LoopA.class, LoopB.class);
}
@Test

View File

@ -540,13 +540,6 @@ public class AnnotationUtilsTests {
assertEquals(Ordered.LOWEST_PRECEDENCE, getDefaultValue(Order.class));
}
@Test
public void findRepeatableAnnotationOnComposedAnnotation() {
Repeatable repeatable = findAnnotation(MyRepeatableMeta1.class, Repeatable.class);
assertNotNull(repeatable);
assertEquals(MyRepeatableContainer.class, repeatable.value());
}
@Test
public void getRepeatableAnnotationsDeclaredOnMethod() throws Exception {
Method method = InterfaceWithRepeated.class.getMethod("foo");

View File

@ -511,6 +511,7 @@ public class AnnotationsScannerTests {
assertThat(result).isEqualTo("OK");
}
private Method methodFrom(Class<?> type) {
return ReflectionUtils.findMethod(type, "method");
}
@ -532,81 +533,68 @@ public class AnnotationsScannerTests {
return result.stream();
}
@Retention(RetentionPolicy.RUNTIME)
static @interface TestAnnotation1 {
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation1 {
}
@Retention(RetentionPolicy.RUNTIME)
static @interface TestAnnotation2 {
@interface TestAnnotation2 {
}
@Retention(RetentionPolicy.RUNTIME)
static @interface TestAnnotation3 {
@interface TestAnnotation3 {
}
@Retention(RetentionPolicy.RUNTIME)
static @interface TestAnnotation4 {
@interface TestAnnotation4 {
}
@Retention(RetentionPolicy.RUNTIME)
static @interface TestAnnotation5 {
@interface TestAnnotation5 {
}
@Retention(RetentionPolicy.RUNTIME)
static @interface TestAnnotation6 {
@interface TestAnnotation6 {
}
@Retention(RetentionPolicy.RUNTIME)
@Inherited
static @interface TestInheritedAnnotation1 {
@interface TestInheritedAnnotation1 {
}
@Retention(RetentionPolicy.RUNTIME)
@Inherited
static @interface TestInheritedAnnotation2 {
@interface TestInheritedAnnotation2 {
}
@Retention(RetentionPolicy.RUNTIME)
@Inherited
static @interface TestInheritedAnnotation3 {
@interface TestInheritedAnnotation3 {
}
@Retention(RetentionPolicy.RUNTIME)
@Inherited
static @interface TestInheritedAnnotation4 {
@interface TestInheritedAnnotation4 {
}
@Retention(RetentionPolicy.RUNTIME)
@Inherited
static @interface TestInheritedAnnotation5 {
@interface TestInheritedAnnotation5 {
}
@Retention(RetentionPolicy.RUNTIME)
static @interface OnSuperClass {
@interface OnSuperClass {
}
@Retention(RetentionPolicy.RUNTIME)
static @interface OnInterface {
@interface OnInterface {
}
static class WithNoAnnotations {
public void method() {
}
}
@TestAnnotation1
@ -615,7 +603,6 @@ public class AnnotationsScannerTests {
@TestAnnotation1
public void method() {
}
}
@TestAnnotation1
@ -626,7 +613,6 @@ public class AnnotationsScannerTests {
@TestAnnotation2
public void method() {
}
}
@TestAnnotation2
@ -637,7 +623,6 @@ public class AnnotationsScannerTests {
@TestInheritedAnnotation2
public void method() {
}
}
@TestAnnotation1
@ -646,7 +631,6 @@ public class AnnotationsScannerTests {
@TestAnnotation1
public void method() {
}
}
@TestInheritedAnnotation2
@ -655,7 +639,6 @@ public class AnnotationsScannerTests {
@TestAnnotation1
public void method() {
}
}
@TestAnnotation1
@ -664,17 +647,15 @@ public class AnnotationsScannerTests {
@TestAnnotation1
public void method() {
}
}
@TestAnnotation2
@TestInheritedAnnotation2
static interface SingleInterface {
interface SingleInterface {
@TestAnnotation2
@TestInheritedAnnotation2
public void method();
void method();
}
@TestAnnotation1
@ -683,7 +664,6 @@ public class AnnotationsScannerTests {
@TestAnnotation1
public void method() {
}
}
@TestAnnotation2
@ -694,7 +674,6 @@ public class AnnotationsScannerTests {
@TestInheritedAnnotation2
public void method() {
}
}
@TestAnnotation3
@ -703,33 +682,29 @@ public class AnnotationsScannerTests {
@TestAnnotation3
public void method() {
}
}
@TestAnnotation4
static interface HierarchySuperSuperclassInterface {
interface HierarchySuperSuperclassInterface {
@TestAnnotation4
public void method();
void method();
}
@TestAnnotation5
@TestInheritedAnnotation5
static interface HierarchyInterface extends HierarchyInterfaceInterface {
interface HierarchyInterface extends HierarchyInterfaceInterface {
@TestAnnotation5
@TestInheritedAnnotation5
public void method();
void method();
}
@TestAnnotation6
static interface HierarchyInterfaceInterface {
interface HierarchyInterfaceInterface {
@TestAnnotation6
public void method();
void method();
}
static class BridgedMethod implements BridgeMethod<String> {
@ -738,37 +713,32 @@ public class AnnotationsScannerTests {
@TestAnnotation1
public void method(String arg) {
}
}
static interface BridgeMethod<T> {
interface BridgeMethod<T> {
@TestAnnotation2
void method(T arg);
}
static class Ignoreable implements IgnoreableOverrideInterface1,
IgnoreableOverrideInterface2, Serializable {
@SuppressWarnings("serial")
static class Ignoreable implements IgnoreableOverrideInterface1, IgnoreableOverrideInterface2, Serializable {
@TestAnnotation1
public void method() {
}
}
static interface IgnoreableOverrideInterface1 {
interface IgnoreableOverrideInterface1 {
@Nullable
public void method();
void method();
}
static interface IgnoreableOverrideInterface2 {
interface IgnoreableOverrideInterface2 {
@Nullable
public void method();
void method();
}
static abstract class MultipleMethods implements MultipleMethodsInterface {
@ -776,7 +746,6 @@ public class AnnotationsScannerTests {
@TestAnnotation1
public void method() {
}
}
interface MultipleMethodsInterface {
@ -786,23 +755,19 @@ public class AnnotationsScannerTests {
@TestAnnotation2
void method1();
}
static class GenericOverride implements GenericOverrideInterface<String> {
@TestAnnotation1
public void method(String argument) {
}
}
static interface GenericOverrideInterface<T extends CharSequence> {
interface GenericOverrideInterface<T extends CharSequence> {
@TestAnnotation2
void method(T argument);
}
static abstract class GenericNonOverride
@ -810,16 +775,13 @@ public class AnnotationsScannerTests {
@TestAnnotation1
public void method(StringBuilder argument) {
}
}
static interface GenericNonOverrideInterface<T extends CharSequence> {
interface GenericNonOverrideInterface<T extends CharSequence> {
@TestAnnotation2
void method(T argument);
}
}

View File

@ -23,7 +23,6 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.Test;
@ -31,8 +30,7 @@ import org.junit.Test;
import org.springframework.core.annotation.MergedAnnotation.MapValues;
import org.springframework.util.MultiValueMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.*;
/**
* Tests for {@link MergedAnnotationCollectors}.
@ -93,18 +91,10 @@ public class MergedAnnotationCollectorsTests {
assertThat(map.get("finished")).containsExactly(true);
}
@Test
@SuppressWarnings({ "unchecked", "rawtypes" })
public void toFinishedMultiValueMapWhenFinisherIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> stream().collect(
MergedAnnotationCollectors.toMultiValueMap((Function) null))).withMessage(
"Finisher must not be null");
private Stream<MergedAnnotation<TestAnnotation>> stream() {
return MergedAnnotations.from(WithTestAnnotations.class).stream(TestAnnotation.class);
}
private Stream<MergedAnnotation<TestAnnotation>> stream() {
return MergedAnnotations.from(WithTestAnnotations.class).stream(
TestAnnotation.class);
}
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(TestAnnotations.class)
@ -124,14 +114,12 @@ public class MergedAnnotationCollectorsTests {
@interface TestAnnotations {
TestAnnotation[] value();
}
@TestAnnotation("a")
@TestAnnotation(name = "b", extra = String.class)
@TestAnnotation(name = "c", extra = Integer.class)
static class WithTestAnnotations {
}
}

View File

@ -16,20 +16,17 @@
package org.springframework.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.*;
/**
* Tests for {@link MergedAnnotationPredicates}.
@ -54,35 +51,18 @@ public class MergedAnnotationPredicatesTests {
MissingAnnotation.class.getName())).rejects(annotation);
}
@Test
public void typeInStringArrayWhenStringArraysIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> MergedAnnotationPredicates.typeIn((String[]) null)).withMessage(
"TypeNames must not be null");
}
@Test
public void typeInClassArrayWhenNameMatchesAccepts() {
MergedAnnotation<TestAnnotation> annotation = MergedAnnotations.from(
WithTestAnnotation.class).get(TestAnnotation.class);
assertThat(MergedAnnotationPredicates.typeIn(TestAnnotation.class)).accepts(
annotation);
MergedAnnotation<TestAnnotation> annotation =
MergedAnnotations.from(WithTestAnnotation.class).get(TestAnnotation.class);
assertThat(MergedAnnotationPredicates.typeIn(TestAnnotation.class)).accepts(annotation);
}
@Test
public void typeInClassArrayWhenNameDoesNotMatchRejects() {
MergedAnnotation<TestAnnotation> annotation = MergedAnnotations.from(
WithTestAnnotation.class).get(TestAnnotation.class);
assertThat(MergedAnnotationPredicates.typeIn(MissingAnnotation.class)).rejects(
annotation);
}
@Test
public void typeInClassArrayWhenClassArraysIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> MergedAnnotationPredicates.typeIn(
(Class<Annotation>[]) null)).withMessage(
"Types must not be null");
MergedAnnotation<TestAnnotation> annotation =
MergedAnnotations.from(WithTestAnnotation.class).get(TestAnnotation.class);
assertThat(MergedAnnotationPredicates.typeIn(MissingAnnotation.class)).rejects(annotation);
}
@Test
@ -90,8 +70,7 @@ public class MergedAnnotationPredicatesTests {
MergedAnnotation<TestAnnotation> annotation = MergedAnnotations.from(
WithTestAnnotation.class).get(TestAnnotation.class);
assertThat(MergedAnnotationPredicates.typeIn(
Collections.singleton(TestAnnotation.class.getName()))).accepts(
annotation);
Collections.singleton(TestAnnotation.class.getName()))).accepts(annotation);
}
@Test
@ -107,15 +86,7 @@ public class MergedAnnotationPredicatesTests {
MergedAnnotation<TestAnnotation> annotation = MergedAnnotations.from(
WithTestAnnotation.class).get(TestAnnotation.class);
assertThat(MergedAnnotationPredicates.typeIn(Arrays.asList(
MissingAnnotation.class.getName(), MissingAnnotation.class))).rejects(
annotation);
}
@Test
public void typeInCollectionWhenCollectionIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> MergedAnnotationPredicates.typeIn(
(Collection<?>) null)).withMessage("Types must not be null");
MissingAnnotation.class.getName(), MissingAnnotation.class))).rejects(annotation);
}
@Test
@ -125,15 +96,13 @@ public class MergedAnnotationPredicatesTests {
MergedAnnotationPredicates.firstRunOf(
this::firstCharOfValue)).collect(Collectors.toList());
assertThat(filtered.stream().map(
annotation -> annotation.getString("value"))).containsExactly("a1", "a2",
"a3");
annotation -> annotation.getString("value"))).containsExactly("a1", "a2", "a3");
}
@Test
public void firstRunOfWhenValueExtractorIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> MergedAnnotationPredicates.firstRunOf(null)).withMessage(
"ValueExtractor must not be null");
() -> MergedAnnotationPredicates.firstRunOf(null));
}
@Test
@ -143,42 +112,38 @@ public class MergedAnnotationPredicatesTests {
MergedAnnotationPredicates.unique(
this::firstCharOfValue)).collect(Collectors.toList());
assertThat(filtered.stream().map(
annotation -> annotation.getString("value"))).containsExactly("a1", "b1",
"c1");
annotation -> annotation.getString("value"))).containsExactly("a1", "b1", "c1");
}
@Test
public void uniqueWhenKeyExtractorIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(
() -> MergedAnnotationPredicates.unique(null)).withMessage(
"KeyExtractor must not be null");
() -> MergedAnnotationPredicates.unique(null));
}
private char firstCharOfValue(MergedAnnotation<TestAnnotation> annotation) {
return annotation.getString("value").charAt(0);
}
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(TestAnnotations.class)
static @interface TestAnnotation {
@interface TestAnnotation {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
static @interface TestAnnotations {
@interface TestAnnotations {
TestAnnotation[] value();
}
static @interface MissingAnnotation {
@interface MissingAnnotation {
}
@TestAnnotation("test")
static class WithTestAnnotation {
}
@TestAnnotation("a1")
@ -191,7 +156,6 @@ public class MergedAnnotationPredicatesTests {
@TestAnnotation("c2")
@TestAnnotation("c3")
static class WithMultipleTestAnnotation {
}
}

View File

@ -24,19 +24,16 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Resource;
import org.junit.Test;
@ -74,44 +71,41 @@ public class MergedAnnotationsTests {
@Test
public void streamWhenFromNonAnnotatedClass() {
assertThat(MergedAnnotations.from(NonAnnotatedClass.class).stream(
TransactionalComponent.class)).isEmpty();
assertThat(MergedAnnotations.from(NonAnnotatedClass.class).
stream(TransactionalComponent.class)).isEmpty();
}
@Test
public void streamWhenFromClassWithMetaDepth1() {
Stream<String> names = MergedAnnotations.from(
TransactionalComponent.class).stream().map(MergedAnnotation::getType);
Stream<String> names = MergedAnnotations.from(TransactionalComponent.class)
.stream().map(MergedAnnotation::getType);
assertThat(names).containsExactly(Transactional.class.getName(),
Component.class.getName(), Indexed.class.getName());
}
@Test
public void streamWhenFromClassWithMetaDepth2() {
Stream<String> names = MergedAnnotations.from(
ComposedTransactionalComponent.class).stream().map(
MergedAnnotation::getType);
Stream<String> names = MergedAnnotations.from(ComposedTransactionalComponent.class)
.stream().map(MergedAnnotation::getType);
assertThat(names).containsExactly(TransactionalComponent.class.getName(),
Transactional.class.getName(), Component.class.getName(),
Indexed.class.getName());
Transactional.class.getName(), Component.class.getName(), Indexed.class.getName());
}
@Test
public void isPresentWhenFromNonAnnotatedClass() {
assertThat(MergedAnnotations.from(NonAnnotatedClass.class).isPresent(
Transactional.class)).isFalse();
assertThat(MergedAnnotations.from(NonAnnotatedClass.class).
isPresent(Transactional.class)).isFalse();
}
@Test
public void isPresentWhenFromAnnotationClassWithMetaDepth0() {
assertThat(MergedAnnotations.from(TransactionalComponent.class).isPresent(
TransactionalComponent.class)).isFalse();
assertThat(MergedAnnotations.from(TransactionalComponent.class).
isPresent(TransactionalComponent.class)).isFalse();
}
@Test
public void isPresentWhenFromAnnotationClassWithMetaDepth1() {
MergedAnnotations annotations = MergedAnnotations.from(
TransactionalComponent.class);
MergedAnnotations annotations = MergedAnnotations.from(TransactionalComponent.class);
assertThat(annotations.isPresent(Transactional.class)).isTrue();
assertThat(annotations.isPresent(Component.class)).isTrue();
}
@ -204,8 +198,6 @@ public class MergedAnnotationsTests {
* type within the class hierarchy. Such undesirable behavior would cause
* the logic in
* {@link org.springframework.context.annotation.ProfileCondition} to fail.
*
* @see org.springframework.core.env.EnvironmentSystemIntegrationTests#mostSpecificDerivedClassDrivesEnvironment_withDevEnvAndDerivedDevConfigClass
*/
@Test
public void collectMultiValueMapFromClassWithLocalAnnotationThatShadowsAnnotationFromSuperclass() {
@ -218,8 +210,6 @@ public class MergedAnnotationsTests {
/**
* Note: this functionality is required by
* {@link org.springframework.context.annotation.ProfileCondition}.
*
* @see org.springframework.core.env.EnvironmentSystemIntegrationTests
*/
@Test
public void collectMultiValueMapFromClassWithMultipleComposedAnnotations() {
@ -629,38 +619,26 @@ public class MergedAnnotationsTests {
}
@Test
public void getWithExhaustiveOnMethodWithSingleElementOverridingAnArrayViaConvention()
throws Exception {
public void getWithExhaustiveOnMethodWithSingleElementOverridingAnArrayViaConvention() throws Exception {
testGetWithExhaustiveWebMapping(
WebController.class.getMethod("postMappedWithPathAttribute"));
}
@Test
public void getWithExhaustiveOnMethodWithSingleElementOverridingAnArrayViaAliasFor()
throws Exception {
public void getWithExhaustiveOnMethodWithSingleElementOverridingAnArrayViaAliasFor() throws Exception {
testGetWithExhaustiveWebMapping(
WebController.class.getMethod("getMappedWithValueAttribute"));
testGetWithExhaustiveWebMapping(
WebController.class.getMethod("getMappedWithPathAttribute"));
}
private void testGetWithExhaustiveWebMapping(AnnotatedElement element)
throws ArrayComparisonFailure {
private void testGetWithExhaustiveWebMapping(AnnotatedElement element) throws ArrayComparisonFailure {
MergedAnnotation<?> annotation = MergedAnnotations.from(element,
SearchStrategy.EXHAUSTIVE).get(RequestMapping.class);
assertThat(annotation.getStringArray("value")).containsExactly("/test");
assertThat(annotation.getStringArray("path")).containsExactly("/test");
}
@Test
public void getDirectWithJavaLangAnnotationType() throws Exception {
Constructor<?> deprecatedConstructor = Date.class.getConstructor(String.class);
MergedAnnotation<?> annotation = MergedAnnotations.from(deprecatedConstructor,
SearchStrategy.DIRECT, RepeatableContainers.standardRepeatables(),
AnnotationFilter.NONE).get(Deprecated.class);
assertThat(annotation.isPresent()).isTrue();
}
@Test
public void getDirectWithJavaxAnnotationType() throws Exception {
assertThat(MergedAnnotations.from(ResourceHolder.class).get(
@ -1267,14 +1245,6 @@ public class MergedAnnotationsTests {
Ordered.LOWEST_PRECEDENCE);
}
@Test
public void getRepeatableOnComposedAnnotation() {
MergedAnnotation<?> annotation = MergedAnnotations.from(MyRepeatableMeta1.class,
SearchStrategy.EXHAUSTIVE, RepeatableContainers.none(),
AnnotationFilter.NONE).get(Repeatable.class);
assertThat(annotation.getClass("value")).isEqualTo(MyRepeatableContainer.class);
}
@Test
public void getRepeatableDeclaredOnMethod() throws Exception {
Method method = InterfaceWithRepeated.class.getMethod("foo");
@ -1286,8 +1256,7 @@ public class MergedAnnotationsTests {
}
@Test
public void getRepeatableDeclaredOnClassWithMissingAttributeAliasDeclaration()
throws Exception {
public void getRepeatableDeclaredOnClassWithMissingAttributeAliasDeclaration() {
RepeatableContainers containers = RepeatableContainers.of(
BrokenContextConfiguration.class, BrokenHierarchy.class);
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(