Skip to content

Commit 784f902

Browse files
committed
Introduce SmallRyeConfig.subset
- Fixes #981
1 parent 6bd3669 commit 784f902

File tree

4 files changed

+146
-1
lines changed

4 files changed

+146
-1
lines changed

implementation/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@
8282
<groupId>io.smallrye.testing</groupId>
8383
<artifactId>smallrye-testing-utilities</artifactId>
8484
</dependency>
85+
<dependency>
86+
<groupId>org.assertj</groupId>
87+
<artifactId>assertj-core</artifactId>
88+
<scope>test</scope>
89+
</dependency>
8590
</dependencies>
8691

8792
<build>

implementation/src/main/java/io/smallrye/config/SmallRyeConfig.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,6 @@ public <K, V> Map<K, V> getValuesAsMap(String name, Converter<K> keyConverter, C
223223
}
224224

225225
/**
226-
*
227226
* This method handles calls from both {@link Config#getValue} and {@link Config#getOptionalValue}.<br>
228227
*/
229228
@SuppressWarnings("unchecked")
@@ -459,6 +458,37 @@ public Optional<ConfigSource> getConfigSource(final String name) {
459458
return Optional.empty();
460459
}
461460

461+
/**
462+
* Returns a {@link Config} containing every key from the current {@link Config} that starts with the specified
463+
* prefix. The prefix is removed from the keys in the subset. For example, if the configuration contains the following
464+
* properties:
465+
*
466+
* <pre>
467+
* prefix.number = 1
468+
* prefix.string = Hello
469+
* prefixed.foo = bar
470+
* prefix = World
471+
* </pre>
472+
* <p>
473+
* the Configuration returned by {@code subset("prefix")} will contain the properties:
474+
*
475+
* <pre>
476+
* number = 1
477+
* string = Hello
478+
* = World
479+
* </pre>
480+
* <p>
481+
* (The key for the value "World" is an empty string)
482+
* <p>
483+
*
484+
* @param prefix The prefix used to select the properties.
485+
* @return a subset configuration
486+
*/
487+
@Experimental("Return a subset of the configuration")
488+
public Config subset(final String prefix) {
489+
return new SmallRyeSubsetConfig(prefix, this);
490+
}
491+
462492
public <T> T convert(String value, Class<T> asType) {
463493
return value != null ? requireConverter(asType).convert(value) : null;
464494
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package io.smallrye.config;
2+
3+
import java.util.List;
4+
import java.util.Objects;
5+
import java.util.Optional;
6+
import java.util.stream.Collectors;
7+
import java.util.stream.StreamSupport;
8+
9+
import org.eclipse.microprofile.config.Config;
10+
import org.eclipse.microprofile.config.ConfigValue;
11+
import org.eclipse.microprofile.config.spi.ConfigSource;
12+
import org.eclipse.microprofile.config.spi.Converter;
13+
14+
/**
15+
* @author George Gastaldi
16+
*/
17+
class SmallRyeSubsetConfig implements Config {
18+
19+
private final String prefix;
20+
21+
private final Config delegate;
22+
23+
public SmallRyeSubsetConfig(String prefix, Config delegate) {
24+
this.prefix = prefix;
25+
this.delegate = delegate;
26+
}
27+
28+
@Override
29+
public <T> T getValue(String propertyName, Class<T> propertyType) {
30+
return delegate.getValue(toSubsetPropertyName(propertyName), propertyType);
31+
}
32+
33+
@Override
34+
public ConfigValue getConfigValue(String propertyName) {
35+
return delegate.getConfigValue(toSubsetPropertyName(propertyName));
36+
}
37+
38+
@Override
39+
public <T> List<T> getValues(String propertyName, Class<T> propertyType) {
40+
return delegate.getValues(toSubsetPropertyName(propertyName), propertyType);
41+
}
42+
43+
@Override
44+
public <T> Optional<T> getOptionalValue(String propertyName, Class<T> propertyType) {
45+
return delegate.getOptionalValue(toSubsetPropertyName(propertyName), propertyType);
46+
}
47+
48+
@Override
49+
public <T> Optional<List<T>> getOptionalValues(String propertyName, Class<T> propertyType) {
50+
return delegate.getOptionalValues(toSubsetPropertyName(propertyName), propertyType);
51+
}
52+
53+
@Override
54+
public Iterable<String> getPropertyNames() {
55+
return StreamSupport.stream(delegate.getPropertyNames().spliterator(), false)
56+
.map(this::chopSubsetPropertyName)
57+
.filter(Objects::nonNull)
58+
.collect(Collectors.toSet());
59+
}
60+
61+
@Override
62+
public Iterable<ConfigSource> getConfigSources() {
63+
return delegate.getConfigSources();
64+
}
65+
66+
@Override
67+
public <T> Optional<Converter<T>> getConverter(Class<T> forType) {
68+
return delegate.getConverter(forType);
69+
}
70+
71+
@Override
72+
public <T> T unwrap(Class<T> type) {
73+
return delegate.unwrap(type);
74+
}
75+
76+
private String toSubsetPropertyName(String propertyName) {
77+
if (propertyName.isBlank()) {
78+
return prefix;
79+
} else {
80+
return prefix + "." + propertyName;
81+
}
82+
}
83+
84+
private String chopSubsetPropertyName(String propertyName) {
85+
if (propertyName.equalsIgnoreCase(prefix)) {
86+
return "";
87+
} else if (propertyName.startsWith(prefix + '.')) {
88+
return propertyName.substring(prefix.length() + 1);
89+
} else {
90+
return null;
91+
}
92+
}
93+
}

implementation/src/test/java/io/smallrye/config/SmallRyeConfigTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import static java.util.Collections.singletonMap;
77
import static java.util.stream.Collectors.toSet;
88
import static java.util.stream.StreamSupport.stream;
9+
import static org.assertj.core.api.Assertions.assertThat;
910
import static org.junit.jupiter.api.Assertions.assertEquals;
1011
import static org.junit.jupiter.api.Assertions.assertFalse;
1112
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -405,4 +406,20 @@ void emptyPropertyNames() {
405406

406407
assertEquals("value", config.getRawValue(""));
407408
}
409+
410+
@Test
411+
void subset() {
412+
SmallRyeConfig config = new SmallRyeConfigBuilder()
413+
.withSources(config(
414+
"app.foo", "bar",
415+
"app.foo.user", "guest",
416+
"app.foo.password", "apassword",
417+
"app.fooed.user", "wrong"))
418+
.build();
419+
Config subset = config.subset("app.foo");
420+
assertEquals("bar", subset.getValue("", String.class));
421+
assertEquals("guest", subset.getValue("user", String.class));
422+
assertEquals("apassword", subset.getValue("password", String.class));
423+
assertThat(subset.getPropertyNames()).containsExactlyInAnyOrder("", "user", "password");
424+
}
408425
}

0 commit comments

Comments
 (0)