AnnotatedElementUtils.java (spring-framework-5.3.23) | : | AnnotatedElementUtils.java (spring-framework-5.3.24) | ||
---|---|---|---|---|
/* | /* | |||
* Copyright 2002-2019 the original author or authors. | * Copyright 2002-2022 the original author or authors. | |||
* | * | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | * You may obtain a copy of the License at | |||
* | * | |||
* https://www.apache.org/licenses/LICENSE-2.0 | * https://www.apache.org/licenses/LICENSE-2.0 | |||
* | * | |||
* Unless required by applicable law or agreed to in writing, software | * Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | * distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
skipping to change at line 436 | skipping to change at line 436 | |||
* Get all <em>repeatable annotations</em> of the specified {@code annota tionType} | * Get all <em>repeatable annotations</em> of the specified {@code annota tionType} | |||
* within the annotation hierarchy <em>above</em> the supplied {@code ele ment}; | * within the annotation hierarchy <em>above</em> the supplied {@code ele ment}; | |||
* and for each annotation found, merge that annotation's attributes with | * and for each annotation found, merge that annotation's attributes with | |||
* <em>matching</em> attributes from annotations in lower levels of the a nnotation | * <em>matching</em> attributes from annotations in lower levels of the a nnotation | |||
* hierarchy and synthesize the results back into an annotation of the sp ecified | * hierarchy and synthesize the results back into an annotation of the sp ecified | |||
* {@code annotationType}. | * {@code annotationType}. | |||
* <p>{@link AliasFor @AliasFor} semantics are fully supported, both with in a | * <p>{@link AliasFor @AliasFor} semantics are fully supported, both with in a | |||
* single annotation and within annotation hierarchies. | * single annotation and within annotation hierarchies. | |||
* <p>This method follows <em>get semantics</em> as described in the | * <p>This method follows <em>get semantics</em> as described in the | |||
* {@linkplain AnnotatedElementUtils class-level javadoc}. | * {@linkplain AnnotatedElementUtils class-level javadoc}. | |||
* <p><strong>WARNING</strong>: if the supplied {@code containerType} is | ||||
not | ||||
* {@code null}, the search will be restricted to supporting only repeata | ||||
ble | ||||
* annotations whose container is the supplied {@code containerType}. Thi | ||||
s | ||||
* prevents the search from finding repeatable annotations declared as | ||||
* meta-annotations on other types of repeatable annotations. If you need | ||||
to | ||||
* support such a use case, favor {@link #getMergedRepeatableAnnotations( | ||||
AnnotatedElement, Class)} | ||||
* over this method or alternatively use the {@link MergedAnnotations} AP | ||||
I | ||||
* directly in conjunction with {@link RepeatableContainers} that are | ||||
* {@linkplain RepeatableContainers#and(Class, Class) composed} to suppor | ||||
t | ||||
* multiple repeatable annotation types. | ||||
* @param element the annotated element (never {@code null}) | * @param element the annotated element (never {@code null}) | |||
* @param annotationType the annotation type to find (never {@code null}) | * @param annotationType the annotation type to find (never {@code null}) | |||
* @param containerType the type of the container that holds the annotati ons; | * @param containerType the type of the container that holds the annotati ons; | |||
* may be {@code null} if the container type should be looked up via | * may be {@code null} if the container type should be looked up via | |||
* {@link java.lang.annotation.Repeatable} | * {@link java.lang.annotation.Repeatable} | |||
* @return the set of all merged repeatable {@code Annotations} found, | * @return the set of all merged repeatable {@code Annotations} found, | |||
* or an empty set if none were found | * or an empty set if none were found | |||
* @throws IllegalArgumentException if the {@code element} or {@code anno tationType} | * @throws IllegalArgumentException if the {@code element} or {@code anno tationType} | |||
* is {@code null}, or if the container type cannot be resolved | * is {@code null}, or if the container type cannot be resolved | |||
* @throws AnnotationConfigurationException if the supplied {@code contai nerType} | * @throws AnnotationConfigurationException if the supplied {@code contai nerType} | |||
skipping to change at line 728 | skipping to change at line 738 | |||
* Find all <em>repeatable annotations</em> of the specified {@code annot ationType} | * Find all <em>repeatable annotations</em> of the specified {@code annot ationType} | |||
* within the annotation hierarchy <em>above</em> the supplied {@code ele ment}; | * within the annotation hierarchy <em>above</em> the supplied {@code ele ment}; | |||
* and for each annotation found, merge that annotation's attributes with | * and for each annotation found, merge that annotation's attributes with | |||
* <em>matching</em> attributes from annotations in lower levels of the a nnotation | * <em>matching</em> attributes from annotations in lower levels of the a nnotation | |||
* hierarchy and synthesize the results back into an annotation of the sp ecified | * hierarchy and synthesize the results back into an annotation of the sp ecified | |||
* {@code annotationType}. | * {@code annotationType}. | |||
* <p>{@link AliasFor @AliasFor} semantics are fully supported, both with in a | * <p>{@link AliasFor @AliasFor} semantics are fully supported, both with in a | |||
* single annotation and within annotation hierarchies. | * single annotation and within annotation hierarchies. | |||
* <p>This method follows <em>find semantics</em> as described in the | * <p>This method follows <em>find semantics</em> as described in the | |||
* {@linkplain AnnotatedElementUtils class-level javadoc}. | * {@linkplain AnnotatedElementUtils class-level javadoc}. | |||
* <p><strong>WARNING</strong>: if the supplied {@code containerType} is | ||||
not | ||||
* {@code null}, the search will be restricted to supporting only repeata | ||||
ble | ||||
* annotations whose container is the supplied {@code containerType}. Thi | ||||
s | ||||
* prevents the search from finding repeatable annotations declared as | ||||
* meta-annotations on other types of repeatable annotations. If you need | ||||
to | ||||
* support such a use case, favor {@link #findMergedRepeatableAnnotations | ||||
(AnnotatedElement, Class)} | ||||
* over this method or alternatively use the {@link MergedAnnotations} AP | ||||
I | ||||
* directly in conjunction with {@link RepeatableContainers} that are | ||||
* {@linkplain RepeatableContainers#and(Class, Class) composed} to suppor | ||||
t | ||||
* multiple repeatable annotation types. | ||||
* @param element the annotated element (never {@code null}) | * @param element the annotated element (never {@code null}) | |||
* @param annotationType the annotation type to find (never {@code null}) | * @param annotationType the annotation type to find (never {@code null}) | |||
* @param containerType the type of the container that holds the annotati ons; | * @param containerType the type of the container that holds the annotati ons; | |||
* may be {@code null} if the container type should be looked up via | * may be {@code null} if the container type should be looked up via | |||
* {@link java.lang.annotation.Repeatable} | * {@link java.lang.annotation.Repeatable} | |||
* @return the set of all merged repeatable {@code Annotations} found, | * @return the set of all merged repeatable {@code Annotations} found, | |||
* or an empty set if none were found | * or an empty set if none were found | |||
* @throws IllegalArgumentException if the {@code element} or {@code anno tationType} | * @throws IllegalArgumentException if the {@code element} or {@code anno tationType} | |||
* is {@code null}, or if the container type cannot be resolved | * is {@code null}, or if the container type cannot be resolved | |||
* @throws AnnotationConfigurationException if the supplied {@code contai nerType} | * @throws AnnotationConfigurationException if the supplied {@code contai nerType} | |||
skipping to change at line 759 | skipping to change at line 779 | |||
.collect(MergedAnnotationCollectors.toAnnotationS et()); | .collect(MergedAnnotationCollectors.toAnnotationS et()); | |||
} | } | |||
private static MergedAnnotations getAnnotations(AnnotatedElement element) { | private static MergedAnnotations getAnnotations(AnnotatedElement element) { | |||
return MergedAnnotations.from(element, SearchStrategy.INHERITED_A NNOTATIONS, RepeatableContainers.none()); | return MergedAnnotations.from(element, SearchStrategy.INHERITED_A NNOTATIONS, RepeatableContainers.none()); | |||
} | } | |||
private static MergedAnnotations getRepeatableAnnotations(AnnotatedElemen t element, | private static MergedAnnotations getRepeatableAnnotations(AnnotatedElemen t element, | |||
@Nullable Class<? extends Annotation> containerType, Clas s<? extends Annotation> annotationType) { | @Nullable Class<? extends Annotation> containerType, Clas s<? extends Annotation> annotationType) { | |||
RepeatableContainers repeatableContainers = RepeatableContainers. | RepeatableContainers repeatableContainers; | |||
of(annotationType, containerType); | if (containerType == null) { | |||
// Invoke RepeatableContainers.of() in order to adhere to | ||||
the contract of | ||||
// getMergedRepeatableAnnotations() which states that an | ||||
IllegalArgumentException | ||||
// will be thrown if the container cannot be resolved. | ||||
// | ||||
// In any case, we use standardRepeatables() in order to | ||||
support repeatable | ||||
// annotations on other types of repeatable annotations ( | ||||
i.e., nested repeatable | ||||
// annotation types). | ||||
// | ||||
// See https://github.com/spring-projects/spring-framewor | ||||
k/issues/20279 | ||||
RepeatableContainers.of(annotationType, null); | ||||
repeatableContainers = RepeatableContainers.standardRepea | ||||
tables(); | ||||
} | ||||
else { | ||||
repeatableContainers = RepeatableContainers.of(annotation | ||||
Type, containerType); | ||||
} | ||||
return MergedAnnotations.from(element, SearchStrategy.INHERITED_A NNOTATIONS, repeatableContainers); | return MergedAnnotations.from(element, SearchStrategy.INHERITED_A NNOTATIONS, repeatableContainers); | |||
} | } | |||
private static MergedAnnotations findAnnotations(AnnotatedElement element ) { | private static MergedAnnotations findAnnotations(AnnotatedElement element ) { | |||
return MergedAnnotations.from(element, SearchStrategy.TYPE_HIERAR CHY, RepeatableContainers.none()); | return MergedAnnotations.from(element, SearchStrategy.TYPE_HIERAR CHY, RepeatableContainers.none()); | |||
} | } | |||
private static MergedAnnotations findRepeatableAnnotations(AnnotatedEleme nt element, | private static MergedAnnotations findRepeatableAnnotations(AnnotatedEleme nt element, | |||
@Nullable Class<? extends Annotation> containerType, Clas s<? extends Annotation> annotationType) { | @Nullable Class<? extends Annotation> containerType, Clas s<? extends Annotation> annotationType) { | |||
RepeatableContainers repeatableContainers = RepeatableContainers. | RepeatableContainers repeatableContainers; | |||
of(annotationType, containerType); | if (containerType == null) { | |||
// Invoke RepeatableContainers.of() in order to adhere to | ||||
the contract of | ||||
// findMergedRepeatableAnnotations() which states that an | ||||
IllegalArgumentException | ||||
// will be thrown if the container cannot be resolved. | ||||
// | ||||
// In any case, we use standardRepeatables() in order to | ||||
support repeatable | ||||
// annotations on other types of repeatable annotations ( | ||||
i.e., nested repeatable | ||||
// annotation types). | ||||
// | ||||
// See https://github.com/spring-projects/spring-framewor | ||||
k/issues/20279 | ||||
RepeatableContainers.of(annotationType, null); | ||||
repeatableContainers = RepeatableContainers.standardRepea | ||||
tables(); | ||||
} | ||||
else { | ||||
repeatableContainers = RepeatableContainers.of(annotation | ||||
Type, containerType); | ||||
} | ||||
return MergedAnnotations.from(element, SearchStrategy.TYPE_HIERAR CHY, repeatableContainers); | return MergedAnnotations.from(element, SearchStrategy.TYPE_HIERAR CHY, repeatableContainers); | |||
} | } | |||
@Nullable | @Nullable | |||
private static MultiValueMap<String, Object> nullIfEmpty(MultiValueMap<St ring, Object> map) { | private static MultiValueMap<String, Object> nullIfEmpty(MultiValueMap<St ring, Object> map) { | |||
return (map.isEmpty() ? null : map); | return (map.isEmpty() ? null : map); | |||
} | } | |||
private static <A extends Annotation> Comparator<MergedAnnotation<A>> hig hAggregateIndexesFirst() { | private static <A extends Annotation> Comparator<MergedAnnotation<A>> hig hAggregateIndexesFirst() { | |||
return Comparator.<MergedAnnotation<A>> comparingInt( | return Comparator.<MergedAnnotation<A>> comparingInt(MergedAnnota | |||
MergedAnnotation::getAggregateIndex).reversed(); | tion::getAggregateIndex).reversed(); | |||
} | } | |||
@Nullable | @Nullable | |||
private static AnnotationAttributes getAnnotationAttributes(MergedAnnotat ion<?> annotation, | private static AnnotationAttributes getAnnotationAttributes(MergedAnnotat ion<?> annotation, | |||
boolean classValuesAsString, boolean nestedAnnotationsAsM ap) { | boolean classValuesAsString, boolean nestedAnnotationsAsM ap) { | |||
if (!annotation.isPresent()) { | if (!annotation.isPresent()) { | |||
return null; | return null; | |||
} | } | |||
return annotation.asAnnotationAttributes( | return annotation.asAnnotationAttributes(Adapt.values(classValues | |||
Adapt.values(classValuesAsString, nestedAnnotatio | AsString, nestedAnnotationsAsMap)); | |||
nsAsMap)); | ||||
} | } | |||
/** | /** | |||
* Adapted {@link AnnotatedElement} that hold specific annotations. | * Adapted {@link AnnotatedElement} that holds specific annotations. | |||
*/ | */ | |||
private static class AnnotatedElementForAnnotations implements AnnotatedE lement { | private static class AnnotatedElementForAnnotations implements AnnotatedE lement { | |||
private final Annotation[] annotations; | private final Annotation[] annotations; | |||
AnnotatedElementForAnnotations(Annotation... annotations) { | AnnotatedElementForAnnotations(Annotation... annotations) { | |||
this.annotations = annotations; | this.annotations = annotations; | |||
} | } | |||
@Override | @Override | |||
End of changes. 8 change blocks. | ||||
11 lines changed or deleted | 88 lines changed or added |