Skip to content

Commit 10ab477

Browse files
committed
Merge pull request #23146 from otaconix
* pr/23146: Polish 'Support nested @PropertyMapping annotations' Support nested @PropertyMapping annotations Closes gh-23146
2 parents f60f3cb + 11a1538 commit 10ab477

File tree

2 files changed

+84
-7
lines changed

2 files changed

+84
-7
lines changed

spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -73,10 +73,10 @@ private Map<String, Object> getProperties(Class<?> source) {
7373
return properties;
7474
}
7575

76-
private void collectProperties(String prefix, SkipPropertyMapping defaultSkip, MergedAnnotation<?> annotation,
76+
private void collectProperties(String prefix, SkipPropertyMapping skip, MergedAnnotation<?> annotation,
7777
Method attribute, Map<String, Object> properties) {
7878
MergedAnnotation<?> attributeMapping = MergedAnnotations.from(attribute).get(PropertyMapping.class);
79-
SkipPropertyMapping skip = attributeMapping.getValue("skip", SkipPropertyMapping.class).orElse(defaultSkip);
79+
skip = attributeMapping.getValue("skip", SkipPropertyMapping.class).orElse(skip);
8080
if (skip == SkipPropertyMapping.YES) {
8181
return;
8282
}
@@ -90,7 +90,7 @@ private void collectProperties(String prefix, SkipPropertyMapping defaultSkip, M
9090
}
9191
}
9292
String name = getName(prefix, attributeMapping, attribute);
93-
putProperties(name, value.get(), properties);
93+
putProperties(name, skip, value.get(), properties);
9494
}
9595

9696
private String getName(String prefix, MergedAnnotation<?> attributeMapping, Method attribute) {
@@ -118,11 +118,18 @@ private String dotAppend(String prefix, String postfix) {
118118
return postfix;
119119
}
120120

121-
private void putProperties(String name, Object value, Map<String, Object> properties) {
121+
private void putProperties(String name, SkipPropertyMapping defaultSkip, Object value,
122+
Map<String, Object> properties) {
122123
if (ObjectUtils.isArray(value)) {
123124
Object[] array = ObjectUtils.toObjectArray(value);
124125
for (int i = 0; i < array.length; i++) {
125-
properties.put(name + "[" + i + "]", array[i]);
126+
putProperties(name + "[" + i + "]", defaultSkip, array[i], properties);
127+
}
128+
}
129+
else if (value instanceof MergedAnnotation<?>) {
130+
MergedAnnotation<?> annotation = (MergedAnnotation<?>) value;
131+
for (Method attribute : annotation.getType().getDeclaredMethods()) {
132+
collectProperties(name, defaultSkip, (MergedAnnotation<?>) value, attribute, properties);
126133
}
127134
}
128135
else {

spring-boot-project/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySourceTests.java

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,9 @@
2121

2222
import org.junit.jupiter.api.Test;
2323

24+
import org.springframework.boot.test.autoconfigure.properties.AnnotationsPropertySourceTests.DeeplyNestedAnnotations.Level1;
25+
import org.springframework.boot.test.autoconfigure.properties.AnnotationsPropertySourceTests.DeeplyNestedAnnotations.Level2;
26+
import org.springframework.boot.test.autoconfigure.properties.AnnotationsPropertySourceTests.NestedAnnotations.Entry;
2427
import org.springframework.core.annotation.AliasFor;
2528

2629
import static org.assertj.core.api.Assertions.assertThat;
@@ -172,6 +175,26 @@ void enumValueNotMapped() {
172175
assertThat(source.containsProperty("testenum.value")).isFalse();
173176
}
174177

178+
@Test
179+
void nestedAnnotationsMapped() {
180+
AnnotationsPropertySource source = new AnnotationsPropertySource(PropertyMappedWithNestedAnnotations.class);
181+
assertThat(source.getProperty("testnested")).isNull();
182+
assertThat(source.getProperty("testnested.entries[0]")).isNull();
183+
assertThat(source.getProperty("testnested.entries[0].value")).isEqualTo("one");
184+
assertThat(source.getProperty("testnested.entries[1]")).isNull();
185+
assertThat(source.getProperty("testnested.entries[1].value")).isEqualTo("two");
186+
}
187+
188+
@Test
189+
void deeplyNestedAnnotationsMapped() {
190+
AnnotationsPropertySource source = new AnnotationsPropertySource(
191+
PropertyMappedWithDeeplyNestedAnnotations.class);
192+
assertThat(source.getProperty("testdeeplynested")).isNull();
193+
assertThat(source.getProperty("testdeeplynested.level1")).isNull();
194+
assertThat(source.getProperty("testdeeplynested.level1.level2")).isNull();
195+
assertThat(source.getProperty("testdeeplynested.level1.level2.value")).isEqualTo("level2");
196+
}
197+
175198
static class NoAnnotation {
176199

177200
}
@@ -396,4 +419,51 @@ enum EnumItem {
396419

397420
}
398421

422+
@Retention(RetentionPolicy.RUNTIME)
423+
@PropertyMapping("testnested")
424+
@interface NestedAnnotations {
425+
426+
Entry[] entries();
427+
428+
@Retention(RetentionPolicy.RUNTIME)
429+
@interface Entry {
430+
431+
String value();
432+
433+
}
434+
435+
}
436+
437+
@NestedAnnotations(entries = { @Entry("one"), @Entry("two") })
438+
static class PropertyMappedWithNestedAnnotations {
439+
440+
}
441+
442+
@Retention(RetentionPolicy.RUNTIME)
443+
@PropertyMapping("testdeeplynested")
444+
@interface DeeplyNestedAnnotations {
445+
446+
Level1 level1();
447+
448+
@Retention(RetentionPolicy.RUNTIME)
449+
@interface Level1 {
450+
451+
Level2 level2();
452+
453+
}
454+
455+
@Retention(RetentionPolicy.RUNTIME)
456+
@interface Level2 {
457+
458+
String value();
459+
460+
}
461+
462+
}
463+
464+
@DeeplyNestedAnnotations(level1 = @Level1(level2 = @Level2("level2")))
465+
static class PropertyMappedWithDeeplyNestedAnnotations {
466+
467+
}
468+
399469
}

0 commit comments

Comments
 (0)