Skip to content

Commit 6ebc69d

Browse files
committed
Polish "Include properties in source merge algorithm"
See gh-25507
1 parent cf4bc6e commit 6ebc69d

File tree

3 files changed

+48
-105
lines changed

3 files changed

+48
-105
lines changed

spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/main/java/org/springframework/boot/configurationmetadata/SimpleConfigurationMetadataRepository.java

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public void add(Collection<ConfigurationMetadataSource> sources) {
6161
}
6262
String sourceType = source.getType();
6363
if (sourceType != null) {
64-
putIfAbsent(group.getSources(), sourceType, source);
64+
addOrMergeSource(group.getSources(), sourceType, source);
6565
}
6666
}
6767
}
@@ -93,7 +93,7 @@ public void include(ConfigurationMetadataRepository repository) {
9393
// Merge properties
9494
group.getProperties().forEach((name, value) -> putIfAbsent(existingGroup.getProperties(), name, value));
9595
// Merge sources
96-
group.getSources().forEach((name, value) -> putIfAbsent(existingGroup.getSources(), name, value));
96+
group.getSources().forEach((name, value) -> addOrMergeSource(existingGroup.getSources(), name, value));
9797
}
9898
}
9999

@@ -111,23 +111,21 @@ private ConfigurationMetadataGroup getGroup(ConfigurationMetadataSource source)
111111
return this.allGroups.get(source.getGroupId());
112112
}
113113

114+
private void addOrMergeSource(Map<String, ConfigurationMetadataSource> sources, String name,
115+
ConfigurationMetadataSource source) {
116+
ConfigurationMetadataSource existingSource = sources.get(name);
117+
if (existingSource == null) {
118+
sources.put(name, source);
119+
}
120+
else {
121+
source.getProperties().forEach((k, v) -> putIfAbsent(existingSource.getProperties(), k, v));
122+
}
123+
}
124+
114125
private <V> void putIfAbsent(Map<String, V> map, String key, V value) {
115126
if (!map.containsKey(key)) {
116127
map.put(key, value);
117128
}
118129
}
119130

120-
/*
121-
Uncomment this code to fix issue revealed by ConfigurationMetadataRepositoryJsonBuilderTests#severalRepositoriesIdenticalGroups3()
122-
123-
private void putIfAbsent(Map<String, ConfigurationMetadataSource> sources, String name,
124-
ConfigurationMetadataSource source) {
125-
ConfigurationMetadataSource existing = sources.get(name);
126-
if (existing == null) {
127-
sources.put(name, source);
128-
} else {
129-
source.getProperties().forEach((k, v) -> putIfAbsent(existing.getProperties(), k, v));
130-
}
131-
}
132-
*/
133131
}

spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/test/java/org/springframework/boot/configurationmetadata/ConfigurationMetadataRepositoryJsonBuilderTests.java

Lines changed: 33 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.io.IOException;
2020
import java.io.InputStream;
21+
import java.util.Arrays;
2122
import java.util.Map;
2223

2324
import org.junit.jupiter.api.Test;
@@ -99,116 +100,60 @@ void severalRepositoriesIdenticalGroups() throws IOException {
99100
try (InputStream foo2 = getInputStreamFor("foo2")) {
100101
ConfigurationMetadataRepository repo = ConfigurationMetadataRepositoryJsonBuilder.create(foo, foo2)
101102
.build();
102-
assertThat(repo.getAllGroups()).hasSize(1);
103+
Iterable<String> allKeys = Arrays.asList("spring.foo.name", "spring.foo.description",
104+
"spring.foo.counter", "spring.foo.enabled", "spring.foo.type");
105+
assertThat(repo.getAllProperties()).containsOnlyKeys(allKeys);
106+
assertThat(repo.getAllGroups()).containsOnlyKeys("spring.foo");
103107
ConfigurationMetadataGroup group = repo.getAllGroups().get("spring.foo");
104-
contains(group.getSources(), "org.acme.Foo", "org.acme.Foo2", "org.springframework.boot.FooProperties");
105-
assertThat(group.getSources()).hasSize(3);
106-
contains(group.getProperties(), "spring.foo.name", "spring.foo.description", "spring.foo.counter",
107-
"spring.foo.enabled", "spring.foo.type");
108-
assertThat(group.getProperties()).hasSize(5);
109-
contains(repo.getAllProperties(), "spring.foo.name", "spring.foo.description", "spring.foo.counter",
110-
"spring.foo.enabled", "spring.foo.type");
111-
assertThat(repo.getAllProperties()).hasSize(5);
108+
assertThat(group.getProperties()).containsOnlyKeys(allKeys);
109+
assertThat(group.getSources()).containsOnlyKeys("org.acme.Foo", "org.acme.Foo2",
110+
"org.springframework.boot.FooProperties");
111+
assertThat(group.getSources().get("org.acme.Foo").getProperties()).containsOnlyKeys("spring.foo.name",
112+
"spring.foo.description");
113+
assertThat(group.getSources().get("org.acme.Foo2").getProperties())
114+
.containsOnlyKeys("spring.foo.enabled", "spring.foo.type");
115+
assertThat(group.getSources().get("org.springframework.boot.FooProperties").getProperties())
116+
.containsOnlyKeys("spring.foo.name", "spring.foo.counter");
112117
}
113118
}
114119
}
115120

116-
117-
/*
118-
* A rewrite of severalRepositoriesIdenticalGroups() using "containsOnlyKeys" to show actual vs. expected when assert fails.
119-
*/
120121
@Test
121-
void severalRepositoriesIdenticalGroups_rewritten() throws IOException {
122+
void severalRepositoriesIdenticalGroupsWithSameType() throws IOException {
122123
try (InputStream foo = getInputStreamFor("foo")) {
123-
try (InputStream foo2 = getInputStreamFor("foo2")) {
124-
ConfigurationMetadataRepository repo = ConfigurationMetadataRepositoryJsonBuilder.create(foo, foo2)
124+
try (InputStream foo3 = getInputStreamFor("foo3")) {
125+
ConfigurationMetadataRepository repo = ConfigurationMetadataRepositoryJsonBuilder.create(foo, foo3)
125126
.build();
126-
127-
// assert all properties are found
128-
assertThat(repo.getAllProperties()).containsOnlyKeys(
129-
"spring.foo.name",
130-
"spring.foo.description",
131-
"spring.foo.counter",
132-
"spring.foo.enabled",
133-
"spring.foo.type");
134-
135-
// we have a single group containing all properties
127+
Iterable<String> allKeys = Arrays.asList("spring.foo.name", "spring.foo.description",
128+
"spring.foo.counter", "spring.foo.enabled", "spring.foo.type");
129+
assertThat(repo.getAllProperties()).containsOnlyKeys(allKeys);
136130
assertThat(repo.getAllGroups()).containsOnlyKeys("spring.foo");
137-
138131
ConfigurationMetadataGroup group = repo.getAllGroups().get("spring.foo");
139-
assertThat(group.getProperties()).containsOnlyKeys(
140-
"spring.foo.name",
141-
"spring.foo.description",
142-
"spring.foo.counter",
143-
"spring.foo.enabled",
144-
"spring.foo.type");
145-
146-
// the group contains 3 different sources
147-
assertThat(group.getSources()).containsOnlyKeys(
148-
"org.acme.Foo", "org.acme.Foo2", "org.springframework.boot.FooProperties");
149-
150-
assertThat(group.getSources().get("org.acme.Foo").getProperties()).containsOnlyKeys(
151-
"spring.foo.name",
152-
"spring.foo.description");
153-
154-
assertThat(group.getSources().get("org.acme.Foo2").getProperties()).containsOnlyKeys(
155-
"spring.foo.enabled",
156-
"spring.foo.type");
157-
158-
assertThat(group.getSources().get("org.springframework.boot.FooProperties").getProperties()).containsOnlyKeys(
159-
"spring.foo.name",
160-
"spring.foo.counter");
132+
assertThat(group.getProperties()).containsOnlyKeys(allKeys);
133+
assertThat(group.getSources()).containsOnlyKeys("org.acme.Foo",
134+
"org.springframework.boot.FooProperties");
135+
assertThat(group.getSources().get("org.acme.Foo").getProperties()).containsOnlyKeys("spring.foo.name",
136+
"spring.foo.description", "spring.foo.enabled", "spring.foo.type");
137+
assertThat(group.getSources().get("org.springframework.boot.FooProperties").getProperties())
138+
.containsOnlyKeys("spring.foo.name", "spring.foo.counter");
161139
}
162140
}
163141
}
164-
165-
/*
166-
* "foo3" contains the same properties as "foo2" except they refer to a group that already exists in
167-
* "foo1" (same NAME, same TYPE).
168-
*
169-
* This test shows that the union of properties collected from the sources is less than what the group actually
170-
* contains (some properties are missing).
171-
*/
142+
172143
@Test
173-
void severalRepositoriesIdenticalGroups3() throws IOException {
144+
void severalRepositoriesIdenticalGroupsWithSameTypeDoesNotOverrideSource() throws IOException {
174145
try (InputStream foo = getInputStreamFor("foo")) {
175146
try (InputStream foo3 = getInputStreamFor("foo3")) {
176147
ConfigurationMetadataRepository repo = ConfigurationMetadataRepositoryJsonBuilder.create(foo, foo3)
177148
.build();
178-
179-
assertThat(repo.getAllProperties()).containsOnlyKeys(
180-
"spring.foo.name",
181-
"spring.foo.description",
182-
"spring.foo.counter",
183-
"spring.foo.enabled",
184-
"spring.foo.type");
185-
186-
assertThat(repo.getAllGroups()).containsOnlyKeys("spring.foo");
187-
188149
ConfigurationMetadataGroup group = repo.getAllGroups().get("spring.foo");
189-
assertThat(group.getProperties()).containsOnlyKeys(
190-
"spring.foo.name",
191-
"spring.foo.description",
192-
"spring.foo.counter",
193-
"spring.foo.enabled",
194-
"spring.foo.type");
195-
196-
197-
assertThat(group.getSources()).containsOnlyKeys("org.acme.Foo", "org.springframework.boot.FooProperties");
198-
assertThat(group.getSources().get("org.acme.Foo").getProperties()).containsOnlyKeys(
199-
"spring.foo.name",
200-
"spring.foo.description",
201-
"spring.foo.enabled", // <-- missing although present in repo.getAllProperties()
202-
"spring.foo.type"); // <-- missing although present in repo.getAllProperties()
203-
204-
assertThat(group.getSources().get("org.springframework.boot.FooProperties").getProperties()).containsOnlyKeys(
205-
"spring.foo.name",
206-
"spring.foo.counter");
150+
ConfigurationMetadataSource fooSource = group.getSources().get("org.acme.Foo");
151+
assertThat(fooSource.getSourceMethod()).isEqualTo("foo()");
152+
assertThat(fooSource.getDescription()).isEqualTo("This is Foo.");
207153
}
208154
}
209155
}
210-
211-
156+
212157
@Test
213158
void emptyGroups() throws IOException {
214159
try (InputStream in = getInputStreamFor("empty-groups")) {

spring-boot-project/spring-boot-tools/spring-boot-configuration-metadata/src/test/resources/metadata/configuration-metadata-foo3.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"name": "spring.foo",
55
"type": "org.acme.Foo",
66
"sourceType": "org.acme.config.FooApp",
7-
"sourceMethod": "foo2()",
8-
"description": "This is Foo."
7+
"sourceMethod": "foo3()",
8+
"description": "This is Foo3."
99
}
1010
],
1111
"properties": [

0 commit comments

Comments
 (0)