Synthesize nested maps into annotations

Prior to this commit, attempting to synthesize an annotation from a map
of annotation attributes that contained nested maps instead of nested
annotations would result in an exception.

This commit addresses this issue by properly synthesizing nested maps
and nested arrays of maps into nested annotations and nested arrays of
annotations, respectively.

Issue: SPR-13338
This commit is contained in:
Sam Brannen
2015-08-10 14:55:54 +02:00
parent 8289036165
commit f17173f6d5
3 changed files with 155 additions and 17 deletions

View File

@@ -883,6 +883,64 @@ public class AnnotationUtilsTests {
assertEquals("value from synthesized component: ", "webController", synthesizedComponent.value());
}
@Test
@SuppressWarnings("unchecked")
public void synthesizeAnnotationFromMapWithNestedMap() throws Exception {
ComponentScanSingleFilter componentScan = ComponentScanSingleFilterClass.class.getAnnotation(ComponentScanSingleFilter.class);
assertNotNull(componentScan);
assertEquals("value from ComponentScan: ", "*Foo", componentScan.value().pattern());
AnnotationAttributes attributes = getAnnotationAttributes(ComponentScanSingleFilterClass.class, componentScan,
false, true);
assertNotNull(attributes);
assertEquals(ComponentScanSingleFilter.class, attributes.annotationType());
Map<String, Object> filterMap = (Map<String, Object>) attributes.get("value");
assertNotNull(filterMap);
assertEquals("*Foo", filterMap.get("pattern"));
// Modify nested map
filterMap.put("pattern", "newFoo");
filterMap.put("enigma", 42);
ComponentScanSingleFilter synthesizedComponentScan = synthesizeAnnotation(attributes,
ComponentScanSingleFilter.class, ComponentScanSingleFilterClass.class);
assertNotNull(synthesizedComponentScan);
assertNotSame(componentScan, synthesizedComponentScan);
assertEquals("value from synthesized ComponentScan: ", "newFoo", synthesizedComponentScan.value().pattern());
}
@Test
@SuppressWarnings("unchecked")
public void synthesizeAnnotationFromMapWithNestedArrayOfMaps() throws Exception {
ComponentScan componentScan = ComponentScanClass.class.getAnnotation(ComponentScan.class);
assertNotNull(componentScan);
AnnotationAttributes attributes = getAnnotationAttributes(ComponentScanClass.class, componentScan, false, true);
assertNotNull(attributes);
assertEquals(ComponentScan.class, attributes.annotationType());
Map<String, Object>[] filters = (Map[]) attributes.get("excludeFilters");
assertNotNull(filters);
List<String> patterns = stream(filters).map(m -> (String) m.get("pattern")).collect(toList());
assertEquals(asList("*Foo", "*Bar"), patterns);
// Modify nested maps
filters[0].put("pattern", "newFoo");
filters[0].put("enigma", 42);
filters[1].put("pattern", "newBar");
filters[1].put("enigma", 42);
ComponentScan synthesizedComponentScan = synthesizeAnnotation(attributes, ComponentScan.class, ComponentScanClass.class);
assertNotNull(synthesizedComponentScan);
assertNotSame(componentScan, synthesizedComponentScan);
patterns = stream(synthesizedComponentScan.excludeFilters()).map(Filter::pattern).collect(toList());
assertEquals(asList("newFoo", "newBar"), patterns);
}
@Test
public void synthesizeAnnotationFromDefaultsWithoutAttributeAliases() throws Exception {
AnnotationWithDefaults annotationWithDefaults = synthesizeAnnotation(AnnotationWithDefaults.class);
@@ -1711,6 +1769,18 @@ public class AnnotationUtilsTests {
static class ComponentScanClass {
}
/**
* Mock of {@code org.springframework.context.annotation.ComponentScan}
*/
@Retention(RetentionPolicy.RUNTIME)
@interface ComponentScanSingleFilter {
Filter value();
}
@ComponentScanSingleFilter(@Filter(pattern = "*Foo"))
static class ComponentScanSingleFilterClass {
}
@Retention(RetentionPolicy.RUNTIME)
@interface AnnotationWithDefaults {
String text() default "enigma";