Support transitive implicit attribute aliases with @AliasFor
This commit picks up where 3eacb837c2
(SPR-13345) left off by adding support for transitive implicit aliases
configured via @AliasFor.
Issue: SPR-13405
This commit is contained in:
@@ -351,13 +351,23 @@ public class AnnotatedElementUtilsTests {
|
||||
assertGetMergedAnnotation(ImplicitAliasesContextConfigClass3.class, "baz.xml");
|
||||
}
|
||||
|
||||
private void assertGetMergedAnnotation(Class<?> element, String expected) {
|
||||
@Test
|
||||
public void getMergedAnnotationWithTransitiveImplicitAliases() {
|
||||
assertGetMergedAnnotation(TransitiveImplicitAliasesContextConfigClass.class, "test.groovy");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMergedAnnotationWithTransitiveImplicitAliasesWithSkippedLevel() {
|
||||
assertGetMergedAnnotation(TransitiveImplicitAliasesWithSkippedLevelContextConfigClass.class, "test.xml");
|
||||
}
|
||||
|
||||
private void assertGetMergedAnnotation(Class<?> element, String... expected) {
|
||||
String name = ContextConfig.class.getName();
|
||||
ContextConfig contextConfig = getMergedAnnotation(element, ContextConfig.class);
|
||||
|
||||
assertNotNull("Should find @ContextConfig on " + element.getSimpleName(), contextConfig);
|
||||
assertArrayEquals("locations", new String[] { expected }, contextConfig.locations());
|
||||
assertArrayEquals("value", new String[] { expected }, contextConfig.value());
|
||||
assertArrayEquals("locations", expected, contextConfig.locations());
|
||||
assertArrayEquals("value", expected, contextConfig.value());
|
||||
assertArrayEquals("classes", new Class<?>[0], contextConfig.classes());
|
||||
|
||||
// Verify contracts between utility methods:
|
||||
@@ -800,6 +810,28 @@ public class AnnotatedElementUtilsTests {
|
||||
@interface ComposedImplicitAliasesContextConfig {
|
||||
}
|
||||
|
||||
@ImplicitAliasesContextConfig
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface TransitiveImplicitAliasesContextConfig {
|
||||
|
||||
@AliasFor(annotation = ImplicitAliasesContextConfig.class, attribute = "xmlFiles")
|
||||
String[] xml() default {};
|
||||
|
||||
@AliasFor(annotation = ImplicitAliasesContextConfig.class, attribute = "groovyScripts")
|
||||
String[] groovy() default {};
|
||||
}
|
||||
|
||||
@ImplicitAliasesContextConfig
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface TransitiveImplicitAliasesWithSkippedLevelContextConfig {
|
||||
|
||||
@AliasFor(annotation = ContextConfig.class, attribute = "locations")
|
||||
String[] xml() default {};
|
||||
|
||||
@AliasFor(annotation = ImplicitAliasesContextConfig.class, attribute = "groovyScripts")
|
||||
String[] groovy() default {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalid because the configuration declares a value for 'value' and
|
||||
* requires a value for the aliased 'locations'. So we likely end up with
|
||||
@@ -1028,6 +1060,14 @@ public class AnnotatedElementUtilsTests {
|
||||
static class ImplicitAliasesContextConfigClass3 {
|
||||
}
|
||||
|
||||
@TransitiveImplicitAliasesContextConfig(groovy = "test.groovy")
|
||||
static class TransitiveImplicitAliasesContextConfigClass {
|
||||
}
|
||||
|
||||
@TransitiveImplicitAliasesWithSkippedLevelContextConfig(xml = "test.xml")
|
||||
static class TransitiveImplicitAliasesWithSkippedLevelContextConfigClass {
|
||||
}
|
||||
|
||||
@ComposedImplicitAliasesContextConfig
|
||||
static class ComposedImplicitAliasesContextConfigClass {
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public class AnnotationUtilsTests {
|
||||
|
||||
static void clearCaches() {
|
||||
clearCache("findAnnotationCache", "annotatedInterfaceCache", "metaPresentCache", "synthesizableCache",
|
||||
"attributeAliasesCache", "attributeMethodsCache");
|
||||
"attributeAliasesCache", "attributeMethodsCache", "aliasDescriptorCache");
|
||||
}
|
||||
|
||||
static void clearCache(String... cacheNames) {
|
||||
@@ -720,26 +720,26 @@ public class AnnotationUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAliasedAttributeNamesFromWrongTargetAnnotation() throws Exception {
|
||||
public void getAttributeOverrideNameFromWrongTargetAnnotation() throws Exception {
|
||||
Method attribute = AliasedComposedContextConfig.class.getDeclaredMethod("xmlConfigFile");
|
||||
assertThat("xmlConfigFile is not an alias for @Component.",
|
||||
getAliasedAttributeNames(attribute, Component.class), is(empty()));
|
||||
getAttributeOverrideName(attribute, Component.class), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAliasedAttributeNamesForNonAliasedAttribute() throws Exception {
|
||||
public void getAttributeOverrideNameForNonAliasedAttribute() throws Exception {
|
||||
Method nonAliasedAttribute = ImplicitAliasesContextConfig.class.getDeclaredMethod("nonAliasedAttribute");
|
||||
assertThat(getAliasedAttributeNames(nonAliasedAttribute, ContextConfig.class), is(empty()));
|
||||
assertThat(getAttributeOverrideName(nonAliasedAttribute, ContextConfig.class), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAliasedAttributeNamesFromAliasedComposedAnnotation() throws Exception {
|
||||
public void getAttributeOverrideNameFromAliasedComposedAnnotation() throws Exception {
|
||||
Method attribute = AliasedComposedContextConfig.class.getDeclaredMethod("xmlConfigFile");
|
||||
assertEquals(asList("location"), getAliasedAttributeNames(attribute, ContextConfig.class));
|
||||
assertEquals("location", getAttributeOverrideName(attribute, ContextConfig.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAliasedAttributeNamesFromComposedAnnotationWithImplicitAliases() throws Exception {
|
||||
public void getAttributeAliasNamesFromComposedAnnotationWithImplicitAliases() throws Exception {
|
||||
Method xmlFile = ImplicitAliasesContextConfig.class.getDeclaredMethod("xmlFile");
|
||||
Method groovyScript = ImplicitAliasesContextConfig.class.getDeclaredMethod("groovyScript");
|
||||
Method value = ImplicitAliasesContextConfig.class.getDeclaredMethod("value");
|
||||
@@ -748,17 +748,63 @@ public class AnnotationUtilsTests {
|
||||
Method location3 = ImplicitAliasesContextConfig.class.getDeclaredMethod("location3");
|
||||
|
||||
// Meta-annotation attribute overrides
|
||||
assertEquals(asList("location"), getAliasedAttributeNames(xmlFile, ContextConfig.class));
|
||||
assertEquals(asList("location"), getAliasedAttributeNames(groovyScript, ContextConfig.class));
|
||||
assertEquals(asList("location"), getAliasedAttributeNames(value, ContextConfig.class));
|
||||
assertEquals("location", getAttributeOverrideName(xmlFile, ContextConfig.class));
|
||||
assertEquals("location", getAttributeOverrideName(groovyScript, ContextConfig.class));
|
||||
assertEquals("location", getAttributeOverrideName(value, ContextConfig.class));
|
||||
|
||||
// Implicit Aliases
|
||||
assertThat(getAliasedAttributeNames(xmlFile), containsInAnyOrder("value", "groovyScript", "location1", "location2", "location3"));
|
||||
assertThat(getAliasedAttributeNames(groovyScript), containsInAnyOrder("value", "xmlFile", "location1", "location2", "location3"));
|
||||
assertThat(getAliasedAttributeNames(value), containsInAnyOrder("xmlFile", "groovyScript", "location1", "location2", "location3"));
|
||||
assertThat(getAliasedAttributeNames(location1), containsInAnyOrder("xmlFile", "groovyScript", "value", "location2", "location3"));
|
||||
assertThat(getAliasedAttributeNames(location2), containsInAnyOrder("xmlFile", "groovyScript", "value", "location1", "location3"));
|
||||
assertThat(getAliasedAttributeNames(location3), containsInAnyOrder("xmlFile", "groovyScript", "value", "location1", "location2"));
|
||||
// Implicit aliases
|
||||
assertThat(getAttributeAliasNames(xmlFile), containsInAnyOrder("value", "groovyScript", "location1", "location2", "location3"));
|
||||
assertThat(getAttributeAliasNames(groovyScript), containsInAnyOrder("value", "xmlFile", "location1", "location2", "location3"));
|
||||
assertThat(getAttributeAliasNames(value), containsInAnyOrder("xmlFile", "groovyScript", "location1", "location2", "location3"));
|
||||
assertThat(getAttributeAliasNames(location1), containsInAnyOrder("xmlFile", "groovyScript", "value", "location2", "location3"));
|
||||
assertThat(getAttributeAliasNames(location2), containsInAnyOrder("xmlFile", "groovyScript", "value", "location1", "location3"));
|
||||
assertThat(getAttributeAliasNames(location3), containsInAnyOrder("xmlFile", "groovyScript", "value", "location1", "location2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAttributeAliasNamesFromComposedAnnotationWithImplicitAliasesForAliasPair() throws Exception {
|
||||
Method xmlFile = ImplicitAliasesForAliasPairContextConfig.class.getDeclaredMethod("xmlFile");
|
||||
Method groovyScript = ImplicitAliasesForAliasPairContextConfig.class.getDeclaredMethod("groovyScript");
|
||||
|
||||
// Meta-annotation attribute overrides
|
||||
assertEquals("location", getAttributeOverrideName(xmlFile, ContextConfig.class));
|
||||
assertEquals("value", getAttributeOverrideName(groovyScript, ContextConfig.class));
|
||||
|
||||
// Implicit aliases
|
||||
assertThat(getAttributeAliasNames(xmlFile), containsInAnyOrder("groovyScript"));
|
||||
assertThat(getAttributeAliasNames(groovyScript), containsInAnyOrder("xmlFile"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAttributeAliasNamesFromComposedAnnotationWithTransitiveImplicitAliases() throws Exception {
|
||||
Method xml = TransitiveImplicitAliasesContextConfig.class.getDeclaredMethod("xml");
|
||||
Method groovy = TransitiveImplicitAliasesContextConfig.class.getDeclaredMethod("groovy");
|
||||
|
||||
// Explicit meta-annotation attribute overrides
|
||||
assertEquals("xmlFile", getAttributeOverrideName(xml, ImplicitAliasesContextConfig.class));
|
||||
assertEquals("groovyScript", getAttributeOverrideName(groovy, ImplicitAliasesContextConfig.class));
|
||||
|
||||
// Transitive meta-annotation attribute overrides
|
||||
assertEquals("location", getAttributeOverrideName(xml, ContextConfig.class));
|
||||
assertEquals("location", getAttributeOverrideName(groovy, ContextConfig.class));
|
||||
|
||||
// Transitive implicit aliases
|
||||
assertThat(getAttributeAliasNames(xml), containsInAnyOrder("groovy"));
|
||||
assertThat(getAttributeAliasNames(groovy), containsInAnyOrder("xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAttributeAliasNamesFromComposedAnnotationWithTransitiveImplicitAliasesForAliasPair() throws Exception {
|
||||
Method xml = TransitiveImplicitAliasesForAliasPairContextConfig.class.getDeclaredMethod("xml");
|
||||
Method groovy = TransitiveImplicitAliasesForAliasPairContextConfig.class.getDeclaredMethod("groovy");
|
||||
|
||||
// Explicit meta-annotation attribute overrides
|
||||
assertEquals("xmlFile", getAttributeOverrideName(xml, ImplicitAliasesForAliasPairContextConfig.class));
|
||||
assertEquals("groovyScript", getAttributeOverrideName(groovy, ImplicitAliasesForAliasPairContextConfig.class));
|
||||
|
||||
// Transitive implicit aliases
|
||||
assertThat(getAttributeAliasNames(xml), containsInAnyOrder("groovy"));
|
||||
assertThat(getAttributeAliasNames(groovy), containsInAnyOrder("xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -936,7 +982,6 @@ public class AnnotationUtilsTests {
|
||||
|
||||
ImplicitAliasesContextConfig synthesizedConfig = synthesizeAnnotation(config);
|
||||
assertThat(synthesizedConfig, instanceOf(SynthesizedAnnotation.class));
|
||||
assertNotSame(config, synthesizedConfig);
|
||||
|
||||
assertEquals("value: ", expected, synthesizedConfig.value());
|
||||
assertEquals("location1: ", expected, synthesizedConfig.location1());
|
||||
@@ -944,6 +989,45 @@ public class AnnotationUtilsTests {
|
||||
assertEquals("groovyScript: ", expected, synthesizedConfig.groovyScript());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void synthesizeAnnotationWithImplicitAliasesForAliasPair() throws Exception {
|
||||
Class<?> clazz = ImplicitAliasesForAliasPairContextConfigClass.class;
|
||||
ImplicitAliasesForAliasPairContextConfig config = clazz.getAnnotation(ImplicitAliasesForAliasPairContextConfig.class);
|
||||
assertNotNull(config);
|
||||
|
||||
ImplicitAliasesForAliasPairContextConfig synthesizedConfig = synthesizeAnnotation(config);
|
||||
assertThat(synthesizedConfig, instanceOf(SynthesizedAnnotation.class));
|
||||
|
||||
assertEquals("xmlFile: ", "test.xml", synthesizedConfig.xmlFile());
|
||||
assertEquals("groovyScript: ", "test.xml", synthesizedConfig.groovyScript());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void synthesizeAnnotationWithTransitiveImplicitAliases() throws Exception {
|
||||
Class<?> clazz = TransitiveImplicitAliasesContextConfigClass.class;
|
||||
TransitiveImplicitAliasesContextConfig config = clazz.getAnnotation(TransitiveImplicitAliasesContextConfig.class);
|
||||
assertNotNull(config);
|
||||
|
||||
TransitiveImplicitAliasesContextConfig synthesizedConfig = synthesizeAnnotation(config);
|
||||
assertThat(synthesizedConfig, instanceOf(SynthesizedAnnotation.class));
|
||||
|
||||
assertEquals("xml: ", "test.xml", synthesizedConfig.xml());
|
||||
assertEquals("groovy: ", "test.xml", synthesizedConfig.groovy());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void synthesizeAnnotationWithTransitiveImplicitAliasesForAliasPair() throws Exception {
|
||||
Class<?> clazz = TransitiveImplicitAliasesForAliasPairContextConfigClass.class;
|
||||
TransitiveImplicitAliasesForAliasPairContextConfig config = clazz.getAnnotation(TransitiveImplicitAliasesForAliasPairContextConfig.class);
|
||||
assertNotNull(config);
|
||||
|
||||
TransitiveImplicitAliasesForAliasPairContextConfig synthesizedConfig = synthesizeAnnotation(config);
|
||||
assertThat(synthesizedConfig, instanceOf(SynthesizedAnnotation.class));
|
||||
|
||||
assertEquals("xml: ", "test.xml", synthesizedConfig.xml());
|
||||
assertEquals("groovy: ", "test.xml", synthesizedConfig.groovy());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void synthesizeAnnotationWithImplicitAliasesWithMissingDefaultValues() throws Exception {
|
||||
Class<?> clazz = ImplicitAliasesWithMissingDefaultValuesContextConfigClass.class;
|
||||
@@ -2007,6 +2091,51 @@ public class AnnotationUtilsTests {
|
||||
static class ImplicitAliasesWithDuplicateValuesContextConfigClass {
|
||||
}
|
||||
|
||||
@ContextConfig
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface ImplicitAliasesForAliasPairContextConfig {
|
||||
|
||||
@AliasFor(annotation = ContextConfig.class, attribute = "location")
|
||||
String xmlFile() default "";
|
||||
|
||||
@AliasFor(annotation = ContextConfig.class, value = "value")
|
||||
String groovyScript() default "";
|
||||
}
|
||||
|
||||
@ImplicitAliasesForAliasPairContextConfig(xmlFile = "test.xml")
|
||||
static class ImplicitAliasesForAliasPairContextConfigClass {
|
||||
}
|
||||
|
||||
@ImplicitAliasesContextConfig
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface TransitiveImplicitAliasesContextConfig {
|
||||
|
||||
@AliasFor(annotation = ImplicitAliasesContextConfig.class, attribute = "xmlFile")
|
||||
String xml() default "";
|
||||
|
||||
@AliasFor(annotation = ImplicitAliasesContextConfig.class, attribute = "groovyScript")
|
||||
String groovy() default "";
|
||||
}
|
||||
|
||||
@TransitiveImplicitAliasesContextConfig(xml = "test.xml")
|
||||
static class TransitiveImplicitAliasesContextConfigClass {
|
||||
}
|
||||
|
||||
@ImplicitAliasesForAliasPairContextConfig
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface TransitiveImplicitAliasesForAliasPairContextConfig {
|
||||
|
||||
@AliasFor(annotation = ImplicitAliasesForAliasPairContextConfig.class, attribute = "xmlFile")
|
||||
String xml() default "";
|
||||
|
||||
@AliasFor(annotation = ImplicitAliasesForAliasPairContextConfig.class, attribute = "groovyScript")
|
||||
String groovy() default "";
|
||||
}
|
||||
|
||||
@TransitiveImplicitAliasesForAliasPairContextConfig(xml = "test.xml")
|
||||
static class TransitiveImplicitAliasesForAliasPairContextConfigClass {
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({})
|
||||
@interface Filter {
|
||||
|
||||
Reference in New Issue
Block a user