Skip to content

Commit

Permalink
Improve relocates and fallbacks (#1130)
Browse files Browse the repository at this point in the history
  • Loading branch information
radcortez authored Mar 9, 2024
1 parent 55ac71e commit cce0c4e
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,15 @@ public ConfigValue getValue(final ConfigSourceInterceptorContext context, final
ConfigValue fallbackValue = context.proceed(map);
// Check which one comes from a higher ordinal source
if (configValue != null && fallbackValue != null) {
return CONFIG_SOURCE_COMPARATOR.compare(configValue, fallbackValue) >= 0 ? configValue : fallbackValue;
return CONFIG_SOURCE_COMPARATOR.compare(configValue, fallbackValue) >= 0 ? configValue
: fallbackValue.withName(name);
} else {
return configValue != null ? configValue : fallbackValue;
if (configValue != null) {
return configValue;
} else if (fallbackValue != null) {
return fallbackValue.withName(name);
}
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,15 @@ public ConfigValue getValue(final ConfigSourceInterceptorContext context, final
ConfigValue configValue = context.proceed(name);
// Check which one comes from a higher ordinal source
if (relocateValue != null && configValue != null) {
return CONFIG_SOURCE_COMPARATOR.compare(relocateValue, configValue) >= 0 ? relocateValue : configValue;
return CONFIG_SOURCE_COMPARATOR.compare(relocateValue, configValue) >= 0 ? relocateValue
: configValue.withName(map);
} else {
return relocateValue != null ? relocateValue : configValue;
if (relocateValue != null) {
return relocateValue;
} else if (configValue != null) {
return configValue.withName(map);
}
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ public Iterable<String> getPropertyNames() {
*/
@Experimental("Retrieve an updated list of all configuration property names")
public Iterable<String> getLatestPropertyNames() {
return configSources.getPropertyNames().get(true);
return configSources.getPropertyNames().latest();
}

/**
Expand Down Expand Up @@ -913,19 +913,18 @@ class PropertyNames implements Serializable {

Iterable<String> get() {
if (names.isEmpty()) {
return get(true);
return latest();
}
return names;
}

Iterable<String> get(boolean latest) {
if (latest) {
names.clear();
Iterator<String> namesIterator = interceptorChain.iterateNames();
while (namesIterator.hasNext()) {
names.add(namesIterator.next());
}
Iterable<String> latest() {
names.clear();
Iterator<String> namesIterator = interceptorChain.iterateNames();
while (namesIterator.hasNext()) {
names.add(namesIterator.next());
}
names.remove(ConfigSource.CONFIG_ORDINAL);
return Collections.unmodifiableSet(names);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.smallrye.config;

import static io.smallrye.config.ConfigMappings.mappedProperties;
import static io.smallrye.config.ConfigMappings.ConfigClassWithPrefix.configClassWithPrefix;
import static io.smallrye.config.KeyValuesConfigSource.config;
import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE;
Expand All @@ -19,6 +20,7 @@
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
import java.util.stream.Collectors;

import org.eclipse.microprofile.config.Config;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -59,7 +61,7 @@ void fallbackEmpty() {
.withSources(config("mp.jwt.token.header", "")).build();

ConfigValue configValue = (ConfigValue) config.getConfigValue("smallrye.jwt.token.header");
assertEquals("smallrye.jwt.token.header", configValue.getName());
assertEquals("mp.jwt.token.header", configValue.getName());
assertEquals("Authorization", configValue.getValue());
}

Expand Down Expand Up @@ -187,9 +189,9 @@ void fallbackPropertyNameToProfile() {

ConfigValue value = config.getConfigValue("new");
assertEquals("5678", value.getValue());
assertEquals("old", value.getName());
assertEquals("new", value.getName());
assertEquals("dev", value.getProfile());
assertEquals("%dev.old", value.getNameProfiled());
assertEquals("%dev.new", value.getNameProfiled());
}

@Test
Expand All @@ -212,7 +214,7 @@ public Iterator<String> iterateNames(final ConfigSourceInterceptorContext contex
hierarchyCandidates.add("child." + name.substring(7));
}
}
names.addAll(ConfigMappings.mappedProperties(configClassWithPrefix(Child.class), hierarchyCandidates));
names.addAll(mappedProperties(configClassWithPrefix(Child.class), hierarchyCandidates));
return names.iterator();
}
};
Expand Down Expand Up @@ -294,6 +296,102 @@ interface Nested {
}
}

@Test
void relocateMapping() {
SmallRyeConfig config = new SmallRyeConfigBuilder()
.addDefaultInterceptors()
.withInterceptors(new RelocateConfigSourceInterceptor(name -> name.replaceFirst("old", "new")))
.withSources(config("config_ordinal", "1",
"reloc.old.value", "old",
"reloc.old.list[0]", "old", "reloc.old.list[1]", "old",
"reloc.old.map.key", "old", "reloc.old.map.old", "old"))
.withSources(config("config_ordinal", "2",
"reloc.new.value", "new",
"reloc.new.list[0]", "new",
"reloc.new.map.key", "new", "reloc.old.map.new", "new"))
.withMapping(RelocateMapping.class)
.build();

RelocateMapping mapping = config.getConfigMapping(RelocateMapping.class);

assertEquals("new", mapping.value());
// TODO - Maps and Lists are merged. Is this what we want? Related with https://github.com/quarkusio/quarkus/issues/38786
assertEquals(2, mapping.list().size());
assertEquals("new", mapping.list().get(0));
assertEquals("old", mapping.list().get(1));
assertEquals(3, mapping.map().size());
assertEquals("new", mapping.map().get("key"));
assertEquals("new", mapping.map().get("new"));
assertEquals("old", mapping.map().get("old"));

Set<String> properties = stream(config.getPropertyNames().spliterator(), false).collect(Collectors.toSet());
Set<String> mappedProperties = mappedProperties(configClassWithPrefix(RelocateMapping.class), properties);
properties.removeAll(mappedProperties);
Set<String> relocateProperties = new HashSet<>();
for (String property : properties) {
if (mappedProperties.contains(property)) {
ConfigValue configValue = config.getConfigValue(property);
relocateProperties.add(configValue.getName());
}
}
properties.removeAll(relocateProperties);
}

@Test
void fallbackMapping() {
SmallRyeConfig config = new SmallRyeConfigBuilder()
.addDefaultInterceptors()
.withInterceptors(new RelocateConfigSourceInterceptor(name -> name.replaceFirst("old", "new")))
.withInterceptors(new FallbackConfigSourceInterceptor(name -> name.replaceFirst("new", "old")))
.withSources(config(
"fall.old.value", "old",
"fall.old.list[0]", "old", "fall.old.list[1]", "old",
"fall.old.map.key", "old", "fall.old.map.old", "old"))
.withMapping(FallbackMapping.class)
.build();

FallbackMapping mapping = config.getConfigMapping(FallbackMapping.class);

assertEquals("old", mapping.value());
assertEquals(2, mapping.list().size());
assertEquals("old", mapping.list().get(0));
assertEquals("old", mapping.list().get(1));
assertEquals(2, mapping.map().size());
assertEquals("old", mapping.map().get("key"));
assertEquals("old", mapping.map().get("old"));

Set<String> properties = stream(config.getPropertyNames().spliterator(), false).collect(Collectors.toSet());
Set<String> mappedProperties = mappedProperties(configClassWithPrefix(FallbackMapping.class), properties);
properties.removeAll(mappedProperties);
Set<String> fallbackProperties = new HashSet<>();
for (String property : properties) {
ConfigValue configValue = config.getConfigValue(property);
if (mappedProperties.contains(configValue.getName())) {
fallbackProperties.add(property);
}
}
properties.removeAll(fallbackProperties);
assertTrue(properties.isEmpty());
}

@ConfigMapping(prefix = "reloc.old")
interface RelocateMapping {
String value();

List<String> list();

Map<String, String> map();
}

@ConfigMapping(prefix = "fall.new")
interface FallbackMapping {
String value();

List<String> list();

Map<String, String> map();
}

private static SmallRyeConfig buildConfig(String... keyValues) {
return builder(Collections.emptySet(), keyValues).build();
}
Expand Down

0 comments on commit cce0c4e

Please sign in to comment.