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:
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user