SynthesizedMergedAnnotationInvocationHandler does not pre-load values

Closes gh-24029
This commit is contained in:
Juergen Hoeller 2019-11-19 14:54:12 +01:00
parent 4af6039359
commit 06b1f31cdd
3 changed files with 150 additions and 223 deletions

View File

@ -61,9 +61,6 @@ final class SynthesizedMergedAnnotationInvocationHandler<A extends Annotation> i
this.annotation = annotation; this.annotation = annotation;
this.type = type; this.type = type;
this.attributes = AttributeMethods.forAnnotationType(type); this.attributes = AttributeMethods.forAnnotationType(type);
for (int i = 0; i < this.attributes.size(); i++) {
getAttributeValue(this.attributes.get(i));
}
} }

View File

@ -28,6 +28,7 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -46,7 +47,7 @@ import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.springframework.core.annotation.AnnotationUtils.VALUE; import static org.springframework.core.annotation.AnnotationUtils.VALUE;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation; import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotationDeclaringClass; import static org.springframework.core.annotation.AnnotationUtils.findAnnotationDeclaringClass;
@ -685,7 +686,8 @@ class AnnotationUtilsTests {
assertThat(values).isEqualTo(expectedValuesJava); assertThat(values).isEqualTo(expectedValuesJava);
// Spring // Spring
Set<MyRepeatable> set = getDeclaredRepeatableAnnotations(MyRepeatableClass.class, MyRepeatable.class, MyRepeatableContainer.class); Set<MyRepeatable> set = getDeclaredRepeatableAnnotations(
MyRepeatableClass.class, MyRepeatable.class, MyRepeatableContainer.class);
assertThat(set).isNotNull(); assertThat(set).isNotNull();
values = set.stream().map(MyRepeatable::value).collect(toList()); values = set.stream().map(MyRepeatable::value).collect(toList());
assertThat(values).isEqualTo(expectedValuesSpring); assertThat(values).isEqualTo(expectedValuesSpring);
@ -720,7 +722,8 @@ class AnnotationUtilsTests {
@Test @Test
void synthesizeAnnotationWithImplicitAliasesWithMissingDefaultValues() throws Exception { void synthesizeAnnotationWithImplicitAliasesWithMissingDefaultValues() throws Exception {
Class<?> clazz = ImplicitAliasesWithMissingDefaultValuesContextConfigClass.class; Class<?> clazz = ImplicitAliasesWithMissingDefaultValuesContextConfigClass.class;
Class<ImplicitAliasesWithMissingDefaultValuesContextConfig> annotationType = ImplicitAliasesWithMissingDefaultValuesContextConfig.class; Class<ImplicitAliasesWithMissingDefaultValuesContextConfig> annotationType =
ImplicitAliasesWithMissingDefaultValuesContextConfig.class;
ImplicitAliasesWithMissingDefaultValuesContextConfig config = clazz.getAnnotation(annotationType); ImplicitAliasesWithMissingDefaultValuesContextConfig config = clazz.getAnnotation(annotationType);
assertThat(config).isNotNull(); assertThat(config).isNotNull();
@ -735,7 +738,8 @@ class AnnotationUtilsTests {
@Test @Test
void synthesizeAnnotationWithImplicitAliasesWithDifferentDefaultValues() throws Exception { void synthesizeAnnotationWithImplicitAliasesWithDifferentDefaultValues() throws Exception {
Class<?> clazz = ImplicitAliasesWithDifferentDefaultValuesContextConfigClass.class; Class<?> clazz = ImplicitAliasesWithDifferentDefaultValuesContextConfigClass.class;
Class<ImplicitAliasesWithDifferentDefaultValuesContextConfig> annotationType = ImplicitAliasesWithDifferentDefaultValuesContextConfig.class; Class<ImplicitAliasesWithDifferentDefaultValuesContextConfig> annotationType =
ImplicitAliasesWithDifferentDefaultValuesContextConfig.class;
ImplicitAliasesWithDifferentDefaultValuesContextConfig config = clazz.getAnnotation(annotationType); ImplicitAliasesWithDifferentDefaultValuesContextConfig config = clazz.getAnnotation(annotationType);
assertThat(config).isNotNull(); assertThat(config).isNotNull();
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
@ -749,7 +753,8 @@ class AnnotationUtilsTests {
@Test @Test
void synthesizeAnnotationWithImplicitAliasesWithDuplicateValues() throws Exception { void synthesizeAnnotationWithImplicitAliasesWithDuplicateValues() throws Exception {
Class<?> clazz = ImplicitAliasesWithDuplicateValuesContextConfigClass.class; Class<?> clazz = ImplicitAliasesWithDuplicateValuesContextConfigClass.class;
Class<ImplicitAliasesWithDuplicateValuesContextConfig> annotationType = ImplicitAliasesWithDuplicateValuesContextConfig.class; Class<ImplicitAliasesWithDuplicateValuesContextConfig> annotationType =
ImplicitAliasesWithDuplicateValuesContextConfig.class;
ImplicitAliasesWithDuplicateValuesContextConfig config = clazz.getAnnotation(annotationType); ImplicitAliasesWithDuplicateValuesContextConfig config = clazz.getAnnotation(annotationType);
assertThat(config).isNotNull(); assertThat(config).isNotNull();
@ -780,7 +785,8 @@ class AnnotationUtilsTests {
@Test @Test
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
void synthesizeAnnotationFromMapWithNestedMap() throws Exception { void synthesizeAnnotationFromMapWithNestedMap() throws Exception {
ComponentScanSingleFilter componentScan = ComponentScanSingleFilterClass.class.getAnnotation(ComponentScanSingleFilter.class); ComponentScanSingleFilter componentScan =
ComponentScanSingleFilterClass.class.getAnnotation(ComponentScanSingleFilter.class);
assertThat(componentScan).isNotNull(); assertThat(componentScan).isNotNull();
assertThat(componentScan.value().pattern()).as("value from ComponentScan: ").isEqualTo("*Foo"); assertThat(componentScan.value().pattern()).as("value from ComponentScan: ").isEqualTo("*Foo");
@ -827,7 +833,8 @@ class AnnotationUtilsTests {
filters[1].put("pattern", "newBar"); filters[1].put("pattern", "newBar");
filters[1].put("enigma", 42); filters[1].put("enigma", 42);
ComponentScan synthesizedComponentScan = synthesizeAnnotation(attributes, ComponentScan.class, ComponentScanClass.class); ComponentScan synthesizedComponentScan =
synthesizeAnnotation(attributes, ComponentScan.class, ComponentScanClass.class);
assertThat(synthesizedComponentScan).isNotNull(); assertThat(synthesizedComponentScan).isNotNull();
assertThat(synthesizedComponentScan).isNotSameAs(componentScan); assertThat(synthesizedComponentScan).isNotSameAs(componentScan);
@ -911,16 +918,16 @@ class AnnotationUtilsTests {
} }
private void assertMissingTextAttribute(Map<String, Object> attributes) { private void assertMissingTextAttribute(Map<String, Object> attributes) {
assertThatIllegalArgumentException().isThrownBy(() -> assertThatExceptionOfType(NoSuchElementException.class).isThrownBy(() ->
synthesizeAnnotation(attributes, AnnotationWithoutDefaults.class, null)) synthesizeAnnotation(attributes, AnnotationWithoutDefaults.class, null).text())
.withMessageContaining("No value found for attribute named 'text' in merged annotation"); .withMessageContaining("No value found for attribute named 'text' in merged annotation");
} }
@Test @Test
void synthesizeAnnotationFromMapWithAttributeOfIncorrectType() throws Exception { void synthesizeAnnotationFromMapWithAttributeOfIncorrectType() throws Exception {
Map<String, Object> map = Collections.singletonMap(VALUE, 42L); Map<String, Object> map = Collections.singletonMap(VALUE, 42L);
assertThatIllegalArgumentException().isThrownBy(() -> assertThatIllegalStateException().isThrownBy(() ->
synthesizeAnnotation(map, Component.class, null)) synthesizeAnnotation(map, Component.class, null).value())
.withMessageContaining("Attribute 'value' in annotation org.springframework.stereotype.Component " .withMessageContaining("Attribute 'value' in annotation org.springframework.stereotype.Component "
+ "should be compatible with java.lang.String but a java.lang.Long value was returned"); + "should be compatible with java.lang.String but a java.lang.Long value was returned");
} }

View File

@ -272,8 +272,7 @@ class MergedAnnotationsTests {
@Test @Test
void getWithInheritedAnnotationsFromMetaCycleAnnotatedClassWithMissingTargetMetaAnnotation() { void getWithInheritedAnnotationsFromMetaCycleAnnotatedClassWithMissingTargetMetaAnnotation() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
MetaCycleAnnotatedClass.class, SearchStrategy.INHERITED_ANNOTATIONS).get( MetaCycleAnnotatedClass.class, SearchStrategy.INHERITED_ANNOTATIONS).get(Transactional.class);
Transactional.class);
assertThat(annotation.isPresent()).isFalse(); assertThat(annotation.isPresent()).isFalse();
} }
@ -396,8 +395,7 @@ class MergedAnnotationsTests {
@Test @Test
void getWithInheritedAnnotationsFromAliasedValueComposedAnnotation() { void getWithInheritedAnnotationsFromAliasedValueComposedAnnotation() {
testGetWithInherited(AliasedValueComposedContextConfigurationClass.class, testGetWithInherited(AliasedValueComposedContextConfigurationClass.class, "test.xml");
"test.xml");
} }
@Test @Test
@ -409,29 +407,25 @@ class MergedAnnotationsTests {
@Test @Test
void getWithInheritedAnnotationsFromTransitiveImplicitAliases() { void getWithInheritedAnnotationsFromTransitiveImplicitAliases() {
testGetWithInherited(TransitiveImplicitAliasesContextConfigurationClass.class, testGetWithInherited(TransitiveImplicitAliasesContextConfigurationClass.class, "test.groovy");
"test.groovy");
} }
@Test @Test
void getWithInheritedAnnotationsFromTransitiveImplicitAliasesWithSingleElementOverridingAnArrayViaAliasFor() { void getWithInheritedAnnotationsFromTransitiveImplicitAliasesWithSingleElementOverridingAnArrayViaAliasFor() {
testGetWithInherited( testGetWithInherited(
SingleLocationTransitiveImplicitAliasesContextConfigurationClass.class, SingleLocationTransitiveImplicitAliasesContextConfigurationClass.class, "test.groovy");
"test.groovy");
} }
@Test @Test
void getWithInheritedAnnotationsFromTransitiveImplicitAliasesWithSkippedLevel() { void getWithInheritedAnnotationsFromTransitiveImplicitAliasesWithSkippedLevel() {
testGetWithInherited( testGetWithInherited(
TransitiveImplicitAliasesWithSkippedLevelContextConfigurationClass.class, TransitiveImplicitAliasesWithSkippedLevelContextConfigurationClass.class, "test.xml");
"test.xml");
} }
@Test @Test
void getWithInheritedAnnotationsFromTransitiveImplicitAliasesWithSkippedLevelWithSingleElementOverridingAnArrayViaAliasFor() { void getWithInheritedAnnotationsFromTransitiveImplicitAliasesWithSkippedLevelWithSingleElementOverridingAnArrayViaAliasFor() {
testGetWithInherited( testGetWithInherited(
SingleLocationTransitiveImplicitAliasesWithSkippedLevelContextConfigurationClass.class, SingleLocationTransitiveImplicitAliasesWithSkippedLevelContextConfigurationClass.class, "test.xml");
"test.xml");
} }
private void testGetWithInherited(Class<?> element, String... expected) { private void testGetWithInherited(Class<?> element, String... expected) {
@ -461,8 +455,7 @@ class MergedAnnotationsTests {
@Test @Test
void getWithTypeHierarchyFromInheritedAnnotationInterface() { void getWithTypeHierarchyFromInheritedAnnotationInterface() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
InheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get( InheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get(Transactional.class);
Transactional.class);
assertThat(annotation.isPresent()).isTrue(); assertThat(annotation.isPresent()).isTrue();
assertThat(annotation.getAggregateIndex()).isEqualTo(0); assertThat(annotation.getAggregateIndex()).isEqualTo(0);
} }
@ -470,8 +463,7 @@ class MergedAnnotationsTests {
@Test @Test
void getWithTypeHierarchyFromSubInheritedAnnotationInterface() { void getWithTypeHierarchyFromSubInheritedAnnotationInterface() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
SubInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get( SubInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get(Transactional.class);
Transactional.class);
assertThat(annotation.isPresent()).isTrue(); assertThat(annotation.isPresent()).isTrue();
assertThat(annotation.getAggregateIndex()).isEqualTo(1); assertThat(annotation.getAggregateIndex()).isEqualTo(1);
} }
@ -479,8 +471,7 @@ class MergedAnnotationsTests {
@Test @Test
void getWithTypeHierarchyFromSubSubInheritedAnnotationInterface() { void getWithTypeHierarchyFromSubSubInheritedAnnotationInterface() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
SubSubInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get( SubSubInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get(Transactional.class);
Transactional.class);
assertThat(annotation.isPresent()).isTrue(); assertThat(annotation.isPresent()).isTrue();
assertThat(annotation.getAggregateIndex()).isEqualTo(2); assertThat(annotation.getAggregateIndex()).isEqualTo(2);
} }
@ -488,8 +479,7 @@ class MergedAnnotationsTests {
@Test @Test
void getWithTypeHierarchyFromNonInheritedAnnotationInterface() { void getWithTypeHierarchyFromNonInheritedAnnotationInterface() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
NonInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get( NonInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get(Order.class);
Order.class);
assertThat(annotation.isPresent()).isTrue(); assertThat(annotation.isPresent()).isTrue();
assertThat(annotation.getAggregateIndex()).isEqualTo(0); assertThat(annotation.getAggregateIndex()).isEqualTo(0);
} }
@ -497,8 +487,7 @@ class MergedAnnotationsTests {
@Test @Test
void getWithTypeHierarchyFromSubNonInheritedAnnotationInterface() { void getWithTypeHierarchyFromSubNonInheritedAnnotationInterface() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
SubNonInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get( SubNonInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get(Order.class);
Order.class);
assertThat(annotation.isPresent()).isTrue(); assertThat(annotation.isPresent()).isTrue();
assertThat(annotation.getAggregateIndex()).isEqualTo(1); assertThat(annotation.getAggregateIndex()).isEqualTo(1);
} }
@ -524,8 +513,7 @@ class MergedAnnotationsTests {
} }
@Test @Test
void getWithTypeHierarchyInheritedFromAbstractMethod() void getWithTypeHierarchyInheritedFromAbstractMethod() throws NoSuchMethodException {
throws NoSuchMethodException {
Method method = ConcreteClassWithInheritedAnnotation.class.getMethod("handle"); Method method = ConcreteClassWithInheritedAnnotation.class.getMethod("handle");
MergedAnnotation<?> annotation = MergedAnnotations.from(method, MergedAnnotation<?> annotation = MergedAnnotations.from(method,
SearchStrategy.TYPE_HIERARCHY).get(Transactional.class); SearchStrategy.TYPE_HIERARCHY).get(Transactional.class);
@ -534,8 +522,7 @@ class MergedAnnotationsTests {
} }
@Test @Test
void getWithTypeHierarchyInheritedFromBridgedMethod() void getWithTypeHierarchyInheritedFromBridgedMethod() throws NoSuchMethodException {
throws NoSuchMethodException {
Method method = ConcreteClassWithInheritedAnnotation.class.getMethod( Method method = ConcreteClassWithInheritedAnnotation.class.getMethod(
"handleParameterized", String.class); "handleParameterized", String.class);
MergedAnnotation<?> annotation = MergedAnnotations.from(method, MergedAnnotation<?> annotation = MergedAnnotations.from(method,
@ -552,12 +539,10 @@ class MergedAnnotationsTests {
methods.add(method); methods.add(method);
} }
}); });
Method bridgeMethod = methods.get(0).getReturnType().equals(Object.class) Method bridgeMethod = methods.get(0).getReturnType().equals(Object.class) ?
? methods.get(0) methods.get(0) : methods.get(1);
: methods.get(1); Method bridgedMethod = methods.get(0).getReturnType().equals(Object.class) ?
Method bridgedMethod = methods.get(0).getReturnType().equals(Object.class) methods.get(1) : methods.get(0);
? methods.get(1)
: methods.get(0);
assertThat(bridgeMethod.isBridge()).isTrue(); assertThat(bridgeMethod.isBridge()).isTrue();
assertThat(bridgedMethod.isBridge()).isFalse(); assertThat(bridgedMethod.isBridge()).isFalse();
MergedAnnotation<?> annotation = MergedAnnotations.from(bridgeMethod, MergedAnnotation<?> annotation = MergedAnnotations.from(bridgeMethod,
@ -612,30 +597,25 @@ class MergedAnnotationsTests {
MergedAnnotation<Filter>[] excludeFilters = annotation.getAnnotationArray( MergedAnnotation<Filter>[] excludeFilters = annotation.getAnnotationArray(
"excludeFilters", Filter.class); "excludeFilters", Filter.class);
assertThat(Arrays.stream(excludeFilters).map( assertThat(Arrays.stream(excludeFilters).map(
filter -> filter.getString("pattern"))).containsExactly("*Test", filter -> filter.getString("pattern"))).containsExactly("*Test", "*Tests");
"*Tests");
} }
@Test @Test
void getWithTypeHierarchyFromClassWithBothAttributesOfAnAliasPairDeclared() { void getWithTypeHierarchyFromClassWithBothAttributesOfAnAliasPairDeclared() {
testGetWithTypeHierarchy(ComponentScanWithBasePackagesAndValueAliasClass.class, testGetWithTypeHierarchy(ComponentScanWithBasePackagesAndValueAliasClass.class, "com.example.app.test");
"com.example.app.test");
} }
@Test @Test
void getWithTypeHierarchyWithSingleElementOverridingAnArrayViaConvention() { void getWithTypeHierarchyWithSingleElementOverridingAnArrayViaConvention() {
testGetWithTypeHierarchy(ConventionBasedSinglePackageComponentScanClass.class, testGetWithTypeHierarchy(ConventionBasedSinglePackageComponentScanClass.class, "com.example.app.test");
"com.example.app.test");
} }
@Test @Test
void getWithTypeHierarchyWithSingleElementOverridingAnArrayViaAliasFor() { void getWithTypeHierarchyWithSingleElementOverridingAnArrayViaAliasFor() {
testGetWithTypeHierarchy(AliasForBasedSinglePackageComponentScanClass.class, testGetWithTypeHierarchy(AliasForBasedSinglePackageComponentScanClass.class, "com.example.app.test");
"com.example.app.test");
} }
private MergedAnnotation<?> testGetWithTypeHierarchy(Class<?> element, private MergedAnnotation<?> testGetWithTypeHierarchy(Class<?> element, String... expected) {
String... expected) {
MergedAnnotation<?> annotation = MergedAnnotations.from(element, MergedAnnotation<?> annotation = MergedAnnotations.from(element,
SearchStrategy.TYPE_HIERARCHY).get(ComponentScan.class); SearchStrategy.TYPE_HIERARCHY).get(ComponentScan.class);
assertThat(annotation.getStringArray("value")).containsExactly(expected); assertThat(annotation.getStringArray("value")).containsExactly(expected);
@ -698,8 +678,7 @@ class MergedAnnotationsTests {
@Test @Test
void streamInheritedFromClassWithInterface() throws Exception { void streamInheritedFromClassWithInterface() throws Exception {
Method method = TransactionalServiceImpl.class.getMethod("doIt"); Method method = TransactionalServiceImpl.class.getMethod("doIt");
assertThat(MergedAnnotations.from(method, assertThat(MergedAnnotations.from(method, SearchStrategy.INHERITED_ANNOTATIONS).stream(
SearchStrategy.INHERITED_ANNOTATIONS).stream(
Transactional.class)).isEmpty(); Transactional.class)).isEmpty();
} }
@ -727,8 +706,7 @@ class MergedAnnotationsTests {
void getFromMethodWithMethodAnnotationOnLeaf() throws Exception { void getFromMethodWithMethodAnnotationOnLeaf() throws Exception {
Method method = Leaf.class.getMethod("annotatedOnLeaf"); Method method = Leaf.class.getMethod("annotatedOnLeaf");
assertThat(method.getAnnotation(Order.class)).isNotNull(); assertThat(method.getAnnotation(Order.class)).isNotNull();
assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo( assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo(0);
0);
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Order.class).getDistance()).isEqualTo(0); Order.class).getDistance()).isEqualTo(0);
} }
@ -737,8 +715,7 @@ class MergedAnnotationsTests {
void getFromMethodWithAnnotationOnMethodInInterface() throws Exception { void getFromMethodWithAnnotationOnMethodInInterface() throws Exception {
Method method = Leaf.class.getMethod("fromInterfaceImplementedByRoot"); Method method = Leaf.class.getMethod("fromInterfaceImplementedByRoot");
assertThat(method.getAnnotation(Order.class)).isNull(); assertThat(method.getAnnotation(Order.class)).isNull();
assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo( assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo(-1);
-1);
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Order.class).getDistance()).isEqualTo(0); Order.class).getDistance()).isEqualTo(0);
} }
@ -747,8 +724,7 @@ class MergedAnnotationsTests {
void getFromMethodWithMetaAnnotationOnLeaf() throws Exception { void getFromMethodWithMetaAnnotationOnLeaf() throws Exception {
Method method = Leaf.class.getMethod("metaAnnotatedOnLeaf"); Method method = Leaf.class.getMethod("metaAnnotatedOnLeaf");
assertThat(method.getAnnotation(Order.class)).isNull(); assertThat(method.getAnnotation(Order.class)).isNull();
assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo( assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo(1);
1);
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Order.class).getDistance()).isEqualTo(1); Order.class).getDistance()).isEqualTo(1);
} }
@ -757,9 +733,7 @@ class MergedAnnotationsTests {
void getFromMethodWithMetaMetaAnnotationOnLeaf() throws Exception { void getFromMethodWithMetaMetaAnnotationOnLeaf() throws Exception {
Method method = Leaf.class.getMethod("metaMetaAnnotatedOnLeaf"); Method method = Leaf.class.getMethod("metaMetaAnnotatedOnLeaf");
assertThat(method.getAnnotation(Component.class)).isNull(); assertThat(method.getAnnotation(Component.class)).isNull();
assertThat( assertThat(MergedAnnotations.from(method).get(Component.class).getDistance()).isEqualTo(2);
MergedAnnotations.from(method).get(Component.class).getDistance()).isEqualTo(
2);
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Component.class).getDistance()).isEqualTo(2); Component.class).getDistance()).isEqualTo(2);
} }
@ -768,8 +742,7 @@ class MergedAnnotationsTests {
void getWithAnnotationOnRoot() throws Exception { void getWithAnnotationOnRoot() throws Exception {
Method method = Leaf.class.getMethod("annotatedOnRoot"); Method method = Leaf.class.getMethod("annotatedOnRoot");
assertThat(method.getAnnotation(Order.class)).isNotNull(); assertThat(method.getAnnotation(Order.class)).isNotNull();
assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo( assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo(0);
0);
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Order.class).getDistance()).isEqualTo(0); Order.class).getDistance()).isEqualTo(0);
} }
@ -778,8 +751,7 @@ class MergedAnnotationsTests {
void getFromMethodWithMetaAnnotationOnRoot() throws Exception { void getFromMethodWithMetaAnnotationOnRoot() throws Exception {
Method method = Leaf.class.getMethod("metaAnnotatedOnRoot"); Method method = Leaf.class.getMethod("metaAnnotatedOnRoot");
assertThat(method.getAnnotation(Order.class)).isNull(); assertThat(method.getAnnotation(Order.class)).isNull();
assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo( assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo(1);
1);
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Order.class).getDistance()).isEqualTo(1); Order.class).getDistance()).isEqualTo(1);
} }
@ -788,8 +760,7 @@ class MergedAnnotationsTests {
void getFromMethodWithOnRootButOverridden() throws Exception { void getFromMethodWithOnRootButOverridden() throws Exception {
Method method = Leaf.class.getMethod("overrideWithoutNewAnnotation"); Method method = Leaf.class.getMethod("overrideWithoutNewAnnotation");
assertThat(method.getAnnotation(Order.class)).isNull(); assertThat(method.getAnnotation(Order.class)).isNull();
assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo( assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo(-1);
-1);
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Order.class).getDistance()).isEqualTo(0); Order.class).getDistance()).isEqualTo(0);
} }
@ -798,8 +769,7 @@ class MergedAnnotationsTests {
void getFromMethodWithNotAnnotated() throws Exception { void getFromMethodWithNotAnnotated() throws Exception {
Method method = Leaf.class.getMethod("notAnnotated"); Method method = Leaf.class.getMethod("notAnnotated");
assertThat(method.getAnnotation(Order.class)).isNull(); assertThat(method.getAnnotation(Order.class)).isNull();
assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo( assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo(-1);
-1);
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Order.class).getDistance()).isEqualTo(-1); Order.class).getDistance()).isEqualTo(-1);
} }
@ -837,12 +807,10 @@ class MergedAnnotationsTests {
@Test @Test
void getFromMethodWithBridgedMethod() throws Exception { void getFromMethodWithBridgedMethod() throws Exception {
Method method = TransactionalStringGeneric.class.getMethod("something", Method method = TransactionalStringGeneric.class.getMethod("something", String.class);
String.class);
assertThat(method.isBridge()).isFalse(); assertThat(method.isBridge()).isFalse();
assertThat(method.getAnnotation(Order.class)).isNull(); assertThat(method.getAnnotation(Order.class)).isNull();
assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo( assertThat(MergedAnnotations.from(method).get(Order.class).getDistance()).isEqualTo(-1);
-1);
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Order.class).getDistance()).isEqualTo(0); Order.class).getDistance()).isEqualTo(0);
assertThat(method.getAnnotation(Transactional.class)).isNotNull(); assertThat(method.getAnnotation(Transactional.class)).isNotNull();
@ -861,16 +829,14 @@ class MergedAnnotationsTests {
@Test // SPR-16060 @Test // SPR-16060
void getFromMethodWithGenericInterface() throws Exception { void getFromMethodWithGenericInterface() throws Exception {
Method method = ImplementsInterfaceWithGenericAnnotatedMethod.class.getMethod( Method method = ImplementsInterfaceWithGenericAnnotatedMethod.class.getMethod("foo", String.class);
"foo", String.class);
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Order.class).getDistance()).isEqualTo(0); Order.class).getDistance()).isEqualTo(0);
} }
@Test // SPR-17146 @Test // SPR-17146
void getFromMethodWithGenericSuperclass() throws Exception { void getFromMethodWithGenericSuperclass() throws Exception {
Method method = ExtendsBaseClassWithGenericAnnotatedMethod.class.getMethod("foo", Method method = ExtendsBaseClassWithGenericAnnotatedMethod.class.getMethod("foo", String.class);
String.class);
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Order.class).getDistance()).isEqualTo(0); Order.class).getDistance()).isEqualTo(0);
} }
@ -884,10 +850,8 @@ class MergedAnnotationsTests {
} }
@Test @Test
void getFromMethodWhenInterfaceWhenSuperDoesNotImplementMethod() void getFromMethodWhenInterfaceWhenSuperDoesNotImplementMethod() throws Exception {
throws Exception { Method method = SubOfAbstractImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo");
Method method = SubOfAbstractImplementsInterfaceWithAnnotatedMethod.class.getMethod(
"foo");
assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get( assertThat(MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(
Order.class).getDistance()).isEqualTo(0); Order.class).getDistance()).isEqualTo(0);
} }
@ -903,8 +867,7 @@ class MergedAnnotationsTests {
@Test @Test
void getDirectFromClassFavorsMoreLocallyDeclaredComposedAnnotationsOverInheritedAnnotations() { void getDirectFromClassFavorsMoreLocallyDeclaredComposedAnnotationsOverInheritedAnnotations() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
SubSubClassWithInheritedAnnotation.class, SearchStrategy.TYPE_HIERARCHY).get( SubSubClassWithInheritedAnnotation.class, SearchStrategy.TYPE_HIERARCHY).get(Transactional.class);
Transactional.class);
assertThat(annotation.getBoolean("readOnly")).isTrue(); assertThat(annotation.getBoolean("readOnly")).isTrue();
} }
@ -919,16 +882,14 @@ class MergedAnnotationsTests {
@Test @Test
void getDirectFromClassgetDirectFromClassMetaMetaAnnotatedClass() { void getDirectFromClassgetDirectFromClassMetaMetaAnnotatedClass() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
MetaMetaAnnotatedClass.class, SearchStrategy.TYPE_HIERARCHY).get( MetaMetaAnnotatedClass.class, SearchStrategy.TYPE_HIERARCHY).get(Component.class);
Component.class);
assertThat(annotation.getString("value")).isEqualTo("meta2"); assertThat(annotation.getString("value")).isEqualTo("meta2");
} }
@Test @Test
void getDirectFromClassWithMetaMetaMetaAnnotatedClass() { void getDirectFromClassWithMetaMetaMetaAnnotatedClass() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
MetaMetaMetaAnnotatedClass.class, SearchStrategy.TYPE_HIERARCHY).get( MetaMetaMetaAnnotatedClass.class, SearchStrategy.TYPE_HIERARCHY).get(Component.class);
Component.class);
assertThat(annotation.getString("value")).isEqualTo("meta2"); assertThat(annotation.getString("value")).isEqualTo("meta2");
} }
@ -943,48 +904,42 @@ class MergedAnnotationsTests {
@Test @Test
void getDirectFromClassWithMetaCycleAnnotatedClassWithMissingTargetMetaAnnotation() { void getDirectFromClassWithMetaCycleAnnotatedClassWithMissingTargetMetaAnnotation() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
MetaCycleAnnotatedClass.class, SearchStrategy.TYPE_HIERARCHY).get( MetaCycleAnnotatedClass.class, SearchStrategy.TYPE_HIERARCHY).get(Component.class);
Component.class);
assertThat(annotation.isPresent()).isFalse(); assertThat(annotation.isPresent()).isFalse();
} }
@Test @Test
void getDirectFromClassWithInheritedAnnotationInterface() { void getDirectFromClassWithInheritedAnnotationInterface() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
InheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get( InheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get(Transactional.class);
Transactional.class);
assertThat(annotation.getAggregateIndex()).isEqualTo(0); assertThat(annotation.getAggregateIndex()).isEqualTo(0);
} }
@Test @Test
void getDirectFromClassWithSubInheritedAnnotationInterface() { void getDirectFromClassWithSubInheritedAnnotationInterface() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
SubInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get( SubInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get(Transactional.class);
Transactional.class);
assertThat(annotation.getAggregateIndex()).isEqualTo(1); assertThat(annotation.getAggregateIndex()).isEqualTo(1);
} }
@Test @Test
void getDirectFromClassWithSubSubInheritedAnnotationInterface() { void getDirectFromClassWithSubSubInheritedAnnotationInterface() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
SubSubInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get( SubSubInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get(Transactional.class);
Transactional.class);
assertThat(annotation.getAggregateIndex()).isEqualTo(2); assertThat(annotation.getAggregateIndex()).isEqualTo(2);
} }
@Test @Test
void getDirectFromClassWithNonInheritedAnnotationInterface() { void getDirectFromClassWithNonInheritedAnnotationInterface() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
NonInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get( NonInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get(Order.class);
Order.class);
assertThat(annotation.getAggregateIndex()).isEqualTo(0); assertThat(annotation.getAggregateIndex()).isEqualTo(0);
} }
@Test @Test
void getDirectFromClassWithSubNonInheritedAnnotationInterface() { void getDirectFromClassWithSubNonInheritedAnnotationInterface() {
MergedAnnotation<?> annotation = MergedAnnotations.from( MergedAnnotation<?> annotation = MergedAnnotations.from(
SubNonInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get( SubNonInheritedAnnotationInterface.class, SearchStrategy.TYPE_HIERARCHY).get(Order.class);
Order.class);
assertThat(annotation.getAggregateIndex()).isEqualTo(1); assertThat(annotation.getAggregateIndex()).isEqualTo(1);
} }
@ -1039,8 +994,7 @@ class MergedAnnotationsTests {
@Test @Test
void getSuperClassSourceForTypesWithSingleCandidateType() { void getSuperClassSourceForTypesWithSingleCandidateType() {
// no class-level annotation // no class-level annotation
List<Class<? extends Annotation>> transactionalCandidateList = Collections.singletonList( List<Class<? extends Annotation>> transactionalCandidateList = Collections.singletonList(Transactional.class);
Transactional.class);
assertThat(getSuperClassSourceWithTypeIn(NonAnnotatedInterface.class, assertThat(getSuperClassSourceWithTypeIn(NonAnnotatedInterface.class,
transactionalCandidateList)).isNull(); transactionalCandidateList)).isNull();
assertThat(getSuperClassSourceWithTypeIn(NonAnnotatedClass.class, assertThat(getSuperClassSourceWithTypeIn(NonAnnotatedClass.class,
@ -1071,8 +1025,7 @@ class MergedAnnotationsTests {
@Test @Test
void getSuperClassSourceForTypesWithMultipleCandidateTypes() { void getSuperClassSourceForTypesWithMultipleCandidateTypes() {
List<Class<? extends Annotation>> candidates = Arrays.asList(Transactional.class, List<Class<? extends Annotation>> candidates = Arrays.asList(Transactional.class, Order.class);
Order.class);
// no class-level annotation // no class-level annotation
assertThat(getSuperClassSourceWithTypeIn(NonAnnotatedInterface.class, assertThat(getSuperClassSourceWithTypeIn(NonAnnotatedInterface.class,
candidates)).isNull(); candidates)).isNull();
@ -1107,8 +1060,7 @@ class MergedAnnotationsTests {
candidates)).isEqualTo(TransactionalAndOrderedClass.class); candidates)).isEqualTo(TransactionalAndOrderedClass.class);
} }
private Object getSuperClassSourceWithTypeIn(Class<?> clazz, private Object getSuperClassSourceWithTypeIn(Class<?> clazz, List<Class<? extends Annotation>> annotationTypes) {
List<Class<? extends Annotation>> annotationTypes) {
return MergedAnnotations.from(clazz, SearchStrategy.SUPERCLASS).stream().filter( return MergedAnnotations.from(clazz, SearchStrategy.SUPERCLASS).stream().filter(
MergedAnnotationPredicates.typeIn(annotationTypes).and( MergedAnnotationPredicates.typeIn(annotationTypes).and(
MergedAnnotation::isDirectlyPresent)).map( MergedAnnotation::isDirectlyPresent)).map(
@ -1184,8 +1136,7 @@ class MergedAnnotationsTests {
SearchStrategy.INHERITED_ANNOTATIONS).get( SearchStrategy.INHERITED_ANNOTATIONS).get(
Transactional.class).getAggregateIndex()).isEqualTo(0); Transactional.class).getAggregateIndex()).isEqualTo(0);
// Since we're not traversing interface hierarchies the following, // Since we're not traversing interface hierarchies the following,
// though perhaps // though perhaps counter intuitive, must be false:
// counter intuitive, must be false:
assertThat(MergedAnnotations.from(SubInheritedAnnotationInterface.class, assertThat(MergedAnnotations.from(SubInheritedAnnotationInterface.class,
SearchStrategy.INHERITED_ANNOTATIONS).get( SearchStrategy.INHERITED_ANNOTATIONS).get(
Transactional.class).getAggregateIndex()).isEqualTo(-1); Transactional.class).getAggregateIndex()).isEqualTo(-1);
@ -1212,15 +1163,13 @@ class MergedAnnotationsTests {
@Test @Test
void getDirectWithoutAttributeAliases() { void getDirectWithoutAttributeAliases() {
MergedAnnotation<?> annotation = MergedAnnotations.from(WebController.class) MergedAnnotation<?> annotation = MergedAnnotations.from(WebController.class).get(Component.class);
.get(Component.class);
assertThat(annotation.getString("value")).isEqualTo("webController"); assertThat(annotation.getString("value")).isEqualTo("webController");
} }
@Test @Test
void getDirectWithNestedAnnotations() { void getDirectWithNestedAnnotations() {
MergedAnnotation<?> annotation = MergedAnnotations.from(ComponentScanClass.class) MergedAnnotation<?> annotation = MergedAnnotations.from(ComponentScanClass.class).get(ComponentScan.class);
.get(ComponentScan.class);
MergedAnnotation<Filter>[] filters = annotation.getAnnotationArray("excludeFilters", Filter.class); MergedAnnotation<Filter>[] filters = annotation.getAnnotationArray("excludeFilters", Filter.class);
assertThat(Arrays.stream(filters).map( assertThat(Arrays.stream(filters).map(
filter -> filter.getString("pattern"))).containsExactly("*Foo", "*Bar"); filter -> filter.getString("pattern"))).containsExactly("*Foo", "*Bar");
@ -1256,8 +1205,8 @@ class MergedAnnotationsTests {
@Test @Test
void getValueFromAnnotation() throws Exception { void getValueFromAnnotation() throws Exception {
Method method = TransactionalStringGeneric.class.getMethod("something", Object.class); Method method = TransactionalStringGeneric.class.getMethod("something", Object.class);
MergedAnnotation<?> annotation = MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY) MergedAnnotation<?> annotation =
.get(Order.class); MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(Order.class);
assertThat(annotation.getInt("value")).isEqualTo(1); assertThat(annotation.getInt("value")).isEqualTo(1);
} }
@ -1275,8 +1224,8 @@ class MergedAnnotationsTests {
@Test @Test
void getDefaultValueFromAnnotation() throws Exception { void getDefaultValueFromAnnotation() throws Exception {
Method method = TransactionalStringGeneric.class.getMethod("something", Object.class); Method method = TransactionalStringGeneric.class.getMethod("something", Object.class);
MergedAnnotation<Order> annotation = MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY) MergedAnnotation<Order> annotation =
.get(Order.class); MergedAnnotations.from(method, SearchStrategy.TYPE_HIERARCHY).get(Order.class);
assertThat(annotation.getDefaultValue("value")).contains(Ordered.LOWEST_PRECEDENCE); assertThat(annotation.getDefaultValue("value")).contains(Ordered.LOWEST_PRECEDENCE);
} }
@ -1294,8 +1243,7 @@ class MergedAnnotationsTests {
@Test @Test
void getDefaultValueFromAnnotationType() { void getDefaultValueFromAnnotationType() {
MergedAnnotation<?> annotation = MergedAnnotation.of(Order.class); MergedAnnotation<?> annotation = MergedAnnotation.of(Order.class);
assertThat(annotation.getDefaultValue("value")).contains( assertThat(annotation.getDefaultValue("value")).contains(Ordered.LOWEST_PRECEDENCE);
Ordered.LOWEST_PRECEDENCE);
} }
@Test @Test
@ -1327,8 +1275,7 @@ class MergedAnnotationsTests {
Class<?> element = MyRepeatableClass.class; Class<?> element = MyRepeatableClass.class;
String[] expectedValuesJava = { "A", "B", "C" }; String[] expectedValuesJava = { "A", "B", "C" };
String[] expectedValuesSpring = { "A", "B", "C", "meta1" }; String[] expectedValuesSpring = { "A", "B", "C", "meta1" };
testRepeatables(SearchStrategy.SUPERCLASS, element, expectedValuesJava, testRepeatables(SearchStrategy.SUPERCLASS, element, expectedValuesJava, expectedValuesSpring);
expectedValuesSpring);
} }
@Test @Test
@ -1336,8 +1283,7 @@ class MergedAnnotationsTests {
Class<?> element = SubMyRepeatableClass.class; Class<?> element = SubMyRepeatableClass.class;
String[] expectedValuesJava = { "A", "B", "C" }; String[] expectedValuesJava = { "A", "B", "C" };
String[] expectedValuesSpring = { "A", "B", "C", "meta1" }; String[] expectedValuesSpring = { "A", "B", "C", "meta1" };
testRepeatables(SearchStrategy.SUPERCLASS, element, expectedValuesJava, testRepeatables(SearchStrategy.SUPERCLASS, element, expectedValuesJava, expectedValuesSpring);
expectedValuesSpring);
} }
@Test @Test
@ -1345,8 +1291,7 @@ class MergedAnnotationsTests {
Class<?> element = SubMyRepeatableWithAdditionalLocalDeclarationsClass.class; Class<?> element = SubMyRepeatableWithAdditionalLocalDeclarationsClass.class;
String[] expectedValuesJava = { "X", "Y", "Z" }; String[] expectedValuesJava = { "X", "Y", "Z" };
String[] expectedValuesSpring = { "X", "Y", "Z", "meta2" }; String[] expectedValuesSpring = { "X", "Y", "Z", "meta2" };
testRepeatables(SearchStrategy.SUPERCLASS, element, expectedValuesJava, testRepeatables(SearchStrategy.SUPERCLASS, element, expectedValuesJava, expectedValuesSpring);
expectedValuesSpring);
} }
@Test @Test
@ -1354,8 +1299,7 @@ class MergedAnnotationsTests {
Class<?> element = SubSubMyRepeatableWithAdditionalLocalDeclarationsClass.class; Class<?> element = SubSubMyRepeatableWithAdditionalLocalDeclarationsClass.class;
String[] expectedValuesJava = { "X", "Y", "Z" }; String[] expectedValuesJava = { "X", "Y", "Z" };
String[] expectedValuesSpring = { "X", "Y", "Z", "meta2" }; String[] expectedValuesSpring = { "X", "Y", "Z", "meta2" };
testRepeatables(SearchStrategy.SUPERCLASS, element, expectedValuesJava, testRepeatables(SearchStrategy.SUPERCLASS, element, expectedValuesJava, expectedValuesSpring);
expectedValuesSpring);
} }
@Test @Test
@ -1363,8 +1307,7 @@ class MergedAnnotationsTests {
Class<?> element = MyRepeatableClass.class; Class<?> element = MyRepeatableClass.class;
String[] expectedValuesJava = { "A", "B", "C" }; String[] expectedValuesJava = { "A", "B", "C" };
String[] expectedValuesSpring = { "A", "B", "C", "meta1" }; String[] expectedValuesSpring = { "A", "B", "C", "meta1" };
testRepeatables(SearchStrategy.DIRECT, element, expectedValuesJava, testRepeatables(SearchStrategy.DIRECT, element, expectedValuesJava, expectedValuesSpring);
expectedValuesSpring);
} }
@Test @Test
@ -1372,28 +1315,26 @@ class MergedAnnotationsTests {
Class<?> element = SubMyRepeatableClass.class; Class<?> element = SubMyRepeatableClass.class;
String[] expectedValuesJava = {}; String[] expectedValuesJava = {};
String[] expectedValuesSpring = {}; String[] expectedValuesSpring = {};
testRepeatables(SearchStrategy.DIRECT, element, expectedValuesJava, testRepeatables(SearchStrategy.DIRECT, element, expectedValuesJava, expectedValuesSpring);
expectedValuesSpring);
} }
private void testRepeatables(SearchStrategy searchStrategy, Class<?> element, private void testRepeatables(SearchStrategy searchStrategy, Class<?> element,
String[] expectedValuesJava, String[] expectedValuesSpring) { String[] expectedValuesJava, String[] expectedValuesSpring) {
testJavaRepeatables(searchStrategy, element, expectedValuesJava); testJavaRepeatables(searchStrategy, element, expectedValuesJava);
testExplicitRepeatables(searchStrategy, element, expectedValuesSpring); testExplicitRepeatables(searchStrategy, element, expectedValuesSpring);
testStandardRepeatables(searchStrategy, element, expectedValuesSpring); testStandardRepeatables(searchStrategy, element, expectedValuesSpring);
} }
private void testJavaRepeatables(SearchStrategy searchStrategy, Class<?> element, private void testJavaRepeatables(SearchStrategy searchStrategy, Class<?> element, String[] expected) {
String[] expected) { MyRepeatable[] annotations = searchStrategy == SearchStrategy.DIRECT ?
MyRepeatable[] annotations = searchStrategy == SearchStrategy.DIRECT element.getDeclaredAnnotationsByType(MyRepeatable.class) :
? element.getDeclaredAnnotationsByType(MyRepeatable.class) element.getAnnotationsByType(MyRepeatable.class);
: element.getAnnotationsByType(MyRepeatable.class);
assertThat(Arrays.stream(annotations).map(MyRepeatable::value)).containsExactly( assertThat(Arrays.stream(annotations).map(MyRepeatable::value)).containsExactly(
expected); expected);
} }
private void testExplicitRepeatables(SearchStrategy searchStrategy, Class<?> element, private void testExplicitRepeatables(SearchStrategy searchStrategy, Class<?> element, String[] expected) {
String[] expected) {
MergedAnnotations annotations = MergedAnnotations.from(element, searchStrategy, MergedAnnotations annotations = MergedAnnotations.from(element, searchStrategy,
RepeatableContainers.of(MyRepeatable.class, MyRepeatableContainer.class), RepeatableContainers.of(MyRepeatable.class, MyRepeatableContainer.class),
AnnotationFilter.PLAIN); AnnotationFilter.PLAIN);
@ -1404,8 +1345,7 @@ class MergedAnnotationsTests {
"value"))).containsExactly(expected); "value"))).containsExactly(expected);
} }
private void testStandardRepeatables(SearchStrategy searchStrategy, Class<?> element, private void testStandardRepeatables(SearchStrategy searchStrategy, Class<?> element, String[] expected) {
String[] expected) {
MergedAnnotations annotations = MergedAnnotations.from(element, searchStrategy); MergedAnnotations annotations = MergedAnnotations.from(element, searchStrategy);
assertThat(annotations.stream(MyRepeatable.class).filter( assertThat(annotations.stream(MyRepeatable.class).filter(
MergedAnnotationPredicates.firstRunOf( MergedAnnotationPredicates.firstRunOf(
@ -1429,10 +1369,8 @@ class MergedAnnotationsTests {
Method method = WebController.class.getMethod("handleMappedWithValueAttribute"); Method method = WebController.class.getMethod("handleMappedWithValueAttribute");
RequestMapping webMapping = method.getAnnotation(RequestMapping.class); RequestMapping webMapping = method.getAnnotation(RequestMapping.class);
assertThat(webMapping).isNotNull(); assertThat(webMapping).isNotNull();
RequestMapping synthesizedWebMapping = MergedAnnotation.from( RequestMapping synthesizedWebMapping = MergedAnnotation.from(webMapping).synthesize();
webMapping).synthesize(); RequestMapping synthesizedAgainWebMapping = MergedAnnotation.from(synthesizedWebMapping).synthesize();
RequestMapping synthesizedAgainWebMapping = MergedAnnotation.from(
synthesizedWebMapping).synthesize();
assertThat(synthesizedWebMapping).isInstanceOf(SynthesizedAnnotation.class); assertThat(synthesizedWebMapping).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesizedAgainWebMapping).isInstanceOf(SynthesizedAnnotation.class); assertThat(synthesizedAgainWebMapping).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesizedWebMapping).isEqualTo(synthesizedAgainWebMapping); assertThat(synthesizedWebMapping).isEqualTo(synthesizedAgainWebMapping);
@ -1443,7 +1381,8 @@ class MergedAnnotationsTests {
@Test @Test
void synthesizeWhenAliasForIsMissingAttributeDeclaration() throws Exception { void synthesizeWhenAliasForIsMissingAttributeDeclaration() throws Exception {
AliasForWithMissingAttributeDeclaration annotation = AliasForWithMissingAttributeDeclarationClass.class.getAnnotation( AliasForWithMissingAttributeDeclaration annotation =
AliasForWithMissingAttributeDeclarationClass.class.getAnnotation(
AliasForWithMissingAttributeDeclaration.class); AliasForWithMissingAttributeDeclaration.class);
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
MergedAnnotation.from(annotation)) MergedAnnotation.from(annotation))
@ -1453,8 +1392,7 @@ class MergedAnnotationsTests {
} }
@Test @Test
void synthesizeWhenAliasForHasDuplicateAttributeDeclaration() void synthesizeWhenAliasForHasDuplicateAttributeDeclaration() throws Exception {
throws Exception {
AliasForWithDuplicateAttributeDeclaration annotation = AliasForWithDuplicateAttributeDeclarationClass.class.getAnnotation( AliasForWithDuplicateAttributeDeclaration annotation = AliasForWithDuplicateAttributeDeclarationClass.class.getAnnotation(
AliasForWithDuplicateAttributeDeclaration.class); AliasForWithDuplicateAttributeDeclaration.class);
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
@ -1476,9 +1414,9 @@ class MergedAnnotationsTests {
} }
@Test @Test
void synthesizeWhenAttributeAliasWithMirroredAliasForWrongAttribute() void synthesizeWhenAttributeAliasWithMirroredAliasForWrongAttribute() throws Exception {
throws Exception { AliasForWithMirroredAliasForWrongAttribute annotation =
AliasForWithMirroredAliasForWrongAttribute annotation = AliasForWithMirroredAliasForWrongAttributeClass.class.getAnnotation( AliasForWithMirroredAliasForWrongAttributeClass.class.getAnnotation(
AliasForWithMirroredAliasForWrongAttribute.class); AliasForWithMirroredAliasForWrongAttribute.class);
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
MergedAnnotation.from(annotation)) MergedAnnotation.from(annotation))
@ -1488,8 +1426,7 @@ class MergedAnnotationsTests {
} }
@Test @Test
void synthesizeWhenAttributeAliasForAttributeOfDifferentType() void synthesizeWhenAttributeAliasForAttributeOfDifferentType() throws Exception {
throws Exception {
AliasForAttributeOfDifferentType annotation = AliasForAttributeOfDifferentTypeClass.class.getAnnotation( AliasForAttributeOfDifferentType annotation = AliasForAttributeOfDifferentTypeClass.class.getAnnotation(
AliasForAttributeOfDifferentType.class); AliasForAttributeOfDifferentType.class);
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
@ -1502,8 +1439,7 @@ class MergedAnnotationsTests {
} }
@Test @Test
void synthesizeWhenAttributeAliasForWithMissingDefaultValues() void synthesizeWhenAttributeAliasForWithMissingDefaultValues() throws Exception {
throws Exception {
AliasForWithMissingDefaultValues annotation = AliasForWithMissingDefaultValuesClass.class.getAnnotation( AliasForWithMissingDefaultValues annotation = AliasForWithMissingDefaultValuesClass.class.getAnnotation(
AliasForWithMissingDefaultValues.class); AliasForWithMissingDefaultValues.class);
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
@ -1516,9 +1452,9 @@ class MergedAnnotationsTests {
} }
@Test @Test
void synthesizeWhenAttributeAliasForAttributeWithDifferentDefaultValue() void synthesizeWhenAttributeAliasForAttributeWithDifferentDefaultValue() throws Exception {
throws Exception { AliasForAttributeWithDifferentDefaultValue annotation =
AliasForAttributeWithDifferentDefaultValue annotation = AliasForAttributeWithDifferentDefaultValueClass.class.getAnnotation( AliasForAttributeWithDifferentDefaultValueClass.class.getAnnotation(
AliasForAttributeWithDifferentDefaultValue.class); AliasForAttributeWithDifferentDefaultValue.class);
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
MergedAnnotation.from(annotation)) MergedAnnotation.from(annotation))
@ -1530,9 +1466,9 @@ class MergedAnnotationsTests {
} }
@Test @Test
void synthesizeWhenAttributeAliasForMetaAnnotationThatIsNotMetaPresent() void synthesizeWhenAttributeAliasForMetaAnnotationThatIsNotMetaPresent() throws Exception {
throws Exception { AliasedComposedTestConfigurationNotMetaPresent annotation =
AliasedComposedTestConfigurationNotMetaPresent annotation = AliasedComposedTestConfigurationNotMetaPresentClass.class.getAnnotation( AliasedComposedTestConfigurationNotMetaPresentClass.class.getAnnotation(
AliasedComposedTestConfigurationNotMetaPresent.class); AliasedComposedTestConfigurationNotMetaPresent.class);
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
MergedAnnotation.from(annotation)) MergedAnnotation.from(annotation))
@ -1545,14 +1481,10 @@ class MergedAnnotationsTests {
@Test @Test
void synthesizeWithImplicitAliases() throws Exception { void synthesizeWithImplicitAliases() throws Exception {
testSynthesisWithImplicitAliases(ValueImplicitAliasesTestConfigurationClass.class, testSynthesisWithImplicitAliases(ValueImplicitAliasesTestConfigurationClass.class, "value");
"value"); testSynthesisWithImplicitAliases(Location1ImplicitAliasesTestConfigurationClass.class, "location1");
testSynthesisWithImplicitAliases( testSynthesisWithImplicitAliases(XmlImplicitAliasesTestConfigurationClass.class, "xmlFile");
Location1ImplicitAliasesTestConfigurationClass.class, "location1"); testSynthesisWithImplicitAliases(GroovyImplicitAliasesSimpleTestConfigurationClass.class, "groovyScript");
testSynthesisWithImplicitAliases(XmlImplicitAliasesTestConfigurationClass.class,
"xmlFile");
testSynthesisWithImplicitAliases(
GroovyImplicitAliasesSimpleTestConfigurationClass.class, "groovyScript");
} }
private void testSynthesisWithImplicitAliases(Class<?> clazz, String expected) private void testSynthesisWithImplicitAliases(Class<?> clazz, String expected)
@ -1588,8 +1520,8 @@ class MergedAnnotationsTests {
ImplicitAliasesWithImpliedAliasNamesOmittedTestConfiguration config = clazz.getAnnotation( ImplicitAliasesWithImpliedAliasNamesOmittedTestConfiguration config = clazz.getAnnotation(
ImplicitAliasesWithImpliedAliasNamesOmittedTestConfiguration.class); ImplicitAliasesWithImpliedAliasNamesOmittedTestConfiguration.class);
assertThat(config).isNotNull(); assertThat(config).isNotNull();
ImplicitAliasesWithImpliedAliasNamesOmittedTestConfiguration synthesized = MergedAnnotation.from( ImplicitAliasesWithImpliedAliasNamesOmittedTestConfiguration synthesized =
config).synthesize(); MergedAnnotation.from(config).synthesize();
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class); assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesized.value()).isEqualTo(expected); assertThat(synthesized.value()).isEqualTo(expected);
assertThat(synthesized.location()).isEqualTo(expected); assertThat(synthesized.location()).isEqualTo(expected);
@ -1598,10 +1530,10 @@ class MergedAnnotationsTests {
@Test @Test
void synthesizeWithImplicitAliasesForAliasPair() throws Exception { void synthesizeWithImplicitAliasesForAliasPair() throws Exception {
ImplicitAliasesForAliasPairTestConfiguration config = ImplicitAliasesForAliasPairTestConfigurationClass.class.getAnnotation( ImplicitAliasesForAliasPairTestConfiguration config =
ImplicitAliasesForAliasPairTestConfigurationClass.class.getAnnotation(
ImplicitAliasesForAliasPairTestConfiguration.class); ImplicitAliasesForAliasPairTestConfiguration.class);
ImplicitAliasesForAliasPairTestConfiguration synthesized = MergedAnnotation.from( ImplicitAliasesForAliasPairTestConfiguration synthesized = MergedAnnotation.from(config).synthesize();
config).synthesize();
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class); assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesized.xmlFile()).isEqualTo("test.xml"); assertThat(synthesized.xmlFile()).isEqualTo("test.xml");
assertThat(synthesized.groovyScript()).isEqualTo("test.xml"); assertThat(synthesized.groovyScript()).isEqualTo("test.xml");
@ -1609,10 +1541,10 @@ class MergedAnnotationsTests {
@Test @Test
void synthesizeWithTransitiveImplicitAliases() throws Exception { void synthesizeWithTransitiveImplicitAliases() throws Exception {
TransitiveImplicitAliasesTestConfiguration config = TransitiveImplicitAliasesTestConfigurationClass.class.getAnnotation( TransitiveImplicitAliasesTestConfiguration config =
TransitiveImplicitAliasesTestConfigurationClass.class.getAnnotation(
TransitiveImplicitAliasesTestConfiguration.class); TransitiveImplicitAliasesTestConfiguration.class);
TransitiveImplicitAliasesTestConfiguration synthesized = MergedAnnotation.from( TransitiveImplicitAliasesTestConfiguration synthesized = MergedAnnotation.from(config).synthesize();
config).synthesize();
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class); assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesized.xml()).isEqualTo("test.xml"); assertThat(synthesized.xml()).isEqualTo("test.xml");
assertThat(synthesized.groovy()).isEqualTo("test.xml"); assertThat(synthesized.groovy()).isEqualTo("test.xml");
@ -1620,7 +1552,8 @@ class MergedAnnotationsTests {
@Test @Test
void synthesizeWithTransitiveImplicitAliasesForAliasPair() throws Exception { void synthesizeWithTransitiveImplicitAliasesForAliasPair() throws Exception {
TransitiveImplicitAliasesForAliasPairTestConfiguration config = TransitiveImplicitAliasesForAliasPairTestConfigurationClass.class.getAnnotation( TransitiveImplicitAliasesForAliasPairTestConfiguration config =
TransitiveImplicitAliasesForAliasPairTestConfigurationClass.class.getAnnotation(
TransitiveImplicitAliasesForAliasPairTestConfiguration.class); TransitiveImplicitAliasesForAliasPairTestConfiguration.class);
TransitiveImplicitAliasesForAliasPairTestConfiguration synthesized = MergedAnnotation.from( TransitiveImplicitAliasesForAliasPairTestConfiguration synthesized = MergedAnnotation.from(
config).synthesize(); config).synthesize();
@ -1632,7 +1565,8 @@ class MergedAnnotationsTests {
@Test @Test
void synthesizeWithImplicitAliasesWithMissingDefaultValues() throws Exception { void synthesizeWithImplicitAliasesWithMissingDefaultValues() throws Exception {
Class<?> clazz = ImplicitAliasesWithMissingDefaultValuesTestConfigurationClass.class; Class<?> clazz = ImplicitAliasesWithMissingDefaultValuesTestConfigurationClass.class;
Class<ImplicitAliasesWithMissingDefaultValuesTestConfiguration> annotationType = ImplicitAliasesWithMissingDefaultValuesTestConfiguration.class; Class<ImplicitAliasesWithMissingDefaultValuesTestConfiguration> annotationType =
ImplicitAliasesWithMissingDefaultValuesTestConfiguration.class;
ImplicitAliasesWithMissingDefaultValuesTestConfiguration config = clazz.getAnnotation( ImplicitAliasesWithMissingDefaultValuesTestConfiguration config = clazz.getAnnotation(
annotationType); annotationType);
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
@ -1647,7 +1581,8 @@ class MergedAnnotationsTests {
void synthesizeWithImplicitAliasesWithDifferentDefaultValues() void synthesizeWithImplicitAliasesWithDifferentDefaultValues()
throws Exception { throws Exception {
Class<?> clazz = ImplicitAliasesWithDifferentDefaultValuesTestConfigurationClass.class; Class<?> clazz = ImplicitAliasesWithDifferentDefaultValuesTestConfigurationClass.class;
Class<ImplicitAliasesWithDifferentDefaultValuesTestConfiguration> annotationType = ImplicitAliasesWithDifferentDefaultValuesTestConfiguration.class; Class<ImplicitAliasesWithDifferentDefaultValuesTestConfiguration> annotationType =
ImplicitAliasesWithDifferentDefaultValuesTestConfiguration.class;
ImplicitAliasesWithDifferentDefaultValuesTestConfiguration config = clazz.getAnnotation( ImplicitAliasesWithDifferentDefaultValuesTestConfiguration config = clazz.getAnnotation(
annotationType); annotationType);
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
@ -1661,7 +1596,8 @@ class MergedAnnotationsTests {
@Test @Test
void synthesizeWithImplicitAliasesWithDuplicateValues() throws Exception { void synthesizeWithImplicitAliasesWithDuplicateValues() throws Exception {
Class<?> clazz = ImplicitAliasesWithDuplicateValuesTestConfigurationClass.class; Class<?> clazz = ImplicitAliasesWithDuplicateValuesTestConfigurationClass.class;
Class<ImplicitAliasesWithDuplicateValuesTestConfiguration> annotationType = ImplicitAliasesWithDuplicateValuesTestConfiguration.class; Class<ImplicitAliasesWithDuplicateValuesTestConfiguration> annotationType =
ImplicitAliasesWithDuplicateValuesTestConfiguration.class;
ImplicitAliasesWithDuplicateValuesTestConfiguration config = clazz.getAnnotation( ImplicitAliasesWithDuplicateValuesTestConfiguration config = clazz.getAnnotation(
annotationType); annotationType);
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
@ -1678,8 +1614,7 @@ class MergedAnnotationsTests {
Component component = WebController.class.getAnnotation(Component.class); Component component = WebController.class.getAnnotation(Component.class);
assertThat(component).isNotNull(); assertThat(component).isNotNull();
Map<String, Object> map = Collections.singletonMap("value", "webController"); Map<String, Object> map = Collections.singletonMap("value", "webController");
MergedAnnotation<Component> annotation = MergedAnnotation.of(Component.class, MergedAnnotation<Component> annotation = MergedAnnotation.of(Component.class, map);
map);
Component synthesizedComponent = annotation.synthesize(); Component synthesizedComponent = annotation.synthesize();
assertThat(synthesizedComponent).isInstanceOf(SynthesizedAnnotation.class); assertThat(synthesizedComponent).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesizedComponent.value()).isEqualTo("webController"); assertThat(synthesizedComponent.value()).isEqualTo("webController");
@ -1824,7 +1759,7 @@ class MergedAnnotationsTests {
private void testMissingTextAttribute(Map<String, Object> attributes) { private void testMissingTextAttribute(Map<String, Object> attributes) {
assertThatExceptionOfType(NoSuchElementException.class).isThrownBy(() -> assertThatExceptionOfType(NoSuchElementException.class).isThrownBy(() ->
MergedAnnotation.of(AnnotationWithoutDefaults.class, attributes).synthesize()) MergedAnnotation.of(AnnotationWithoutDefaults.class, attributes).synthesize().text())
.withMessage("No value found for attribute named 'text' in merged annotation " + .withMessage("No value found for attribute named 'text' in merged annotation " +
AnnotationWithoutDefaults.class.getName()); AnnotationWithoutDefaults.class.getName());
} }
@ -1832,46 +1767,34 @@ class MergedAnnotationsTests {
@Test @Test
void synthesizeFromMapWithAttributeOfIncorrectType() throws Exception { void synthesizeFromMapWithAttributeOfIncorrectType() throws Exception {
Map<String, Object> map = Collections.singletonMap("value", 42L); Map<String, Object> map = Collections.singletonMap("value", 42L);
MergedAnnotation<Component> annotation = MergedAnnotation.of(Component.class, MergedAnnotation<Component> annotation = MergedAnnotation.of(Component.class, map);
map); assertThatIllegalStateException().isThrownBy(() -> annotation.synthesize().value())
// annotation.synthesize();
assertThatIllegalStateException().isThrownBy(() ->
annotation.synthesize())
.withMessage("Attribute 'value' in annotation " + .withMessage("Attribute 'value' in annotation " +
"org.springframework.stereotype.Component should be " + "org.springframework.stereotype.Component should be " +
"compatible with java.lang.String but a java.lang.Long value was returned"); "compatible with java.lang.String but a java.lang.Long value was returned");
} }
@Test @Test
void synthesizeFromAnnotationAttributesWithoutAttributeAliases() void synthesizeFromAnnotationAttributesWithoutAttributeAliases() throws Exception {
throws Exception {
Component component = WebController.class.getAnnotation(Component.class); Component component = WebController.class.getAnnotation(Component.class);
assertThat(component).isNotNull(); assertThat(component).isNotNull();
Map<String, Object> attributes = MergedAnnotation.from(component).asMap(); Map<String, Object> attributes = MergedAnnotation.from(component).asMap();
Component synthesized = MergedAnnotation.of(Component.class, Component synthesized = MergedAnnotation.of(Component.class, attributes).synthesize();
attributes).synthesize();
assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class); assertThat(synthesized).isInstanceOf(SynthesizedAnnotation.class);
assertThat(synthesized).isEqualTo(component); assertThat(synthesized).isEqualTo(component);
} }
@Test @Test
void toStringForSynthesizedAnnotations() throws Exception { void toStringForSynthesizedAnnotations() throws Exception {
Method methodWithPath = WebController.class.getMethod( Method methodWithPath = WebController.class.getMethod("handleMappedWithPathAttribute");
"handleMappedWithPathAttribute"); RequestMapping webMappingWithAliases = methodWithPath.getAnnotation(RequestMapping.class);
RequestMapping webMappingWithAliases = methodWithPath.getAnnotation(
RequestMapping.class);
assertThat(webMappingWithAliases).isNotNull(); assertThat(webMappingWithAliases).isNotNull();
Method methodWithPathAndValue = WebController.class.getMethod( Method methodWithPathAndValue = WebController.class.getMethod("handleMappedWithSamePathAndValueAttributes");
"handleMappedWithSamePathAndValueAttributes"); RequestMapping webMappingWithPathAndValue = methodWithPathAndValue.getAnnotation(RequestMapping.class);
RequestMapping webMappingWithPathAndValue = methodWithPathAndValue.getAnnotation(
RequestMapping.class);
assertThat(methodWithPathAndValue).isNotNull(); assertThat(methodWithPathAndValue).isNotNull();
RequestMapping synthesizedWebMapping1 = MergedAnnotation.from( RequestMapping synthesizedWebMapping1 = MergedAnnotation.from(webMappingWithAliases).synthesize();
webMappingWithAliases).synthesize(); RequestMapping synthesizedWebMapping2 = MergedAnnotation.from(webMappingWithPathAndValue).synthesize();
RequestMapping synthesizedWebMapping2 = MergedAnnotation.from( assertThat(webMappingWithAliases.toString()).isNotEqualTo(synthesizedWebMapping1.toString());
webMappingWithPathAndValue).synthesize();
assertThat(webMappingWithAliases.toString()).isNotEqualTo(
synthesizedWebMapping1.toString());
assertToStringForWebMappingWithPathAndValue(synthesizedWebMapping1); assertToStringForWebMappingWithPathAndValue(synthesizedWebMapping1);
assertToStringForWebMappingWithPathAndValue(synthesizedWebMapping2); assertToStringForWebMappingWithPathAndValue(synthesizedWebMapping2);
} }