diff --git a/implementation/src/main/java/io/smallrye/config/ConfigMappingInterface.java b/implementation/src/main/java/io/smallrye/config/ConfigMappingInterface.java index 7275ca9e7..4e39ce595 100644 --- a/implementation/src/main/java/io/smallrye/config/ConfigMappingInterface.java +++ b/implementation/src/main/java/io/smallrye/config/ConfigMappingInterface.java @@ -40,7 +40,6 @@ protected ConfigMappingInterface computeValue(final Class type) { private final String className; private final ConfigMappingInterface[] superTypes; private final Property[] properties; - private final Map propertiesByName; private final ToStringMethod toStringMethod; ConfigMappingInterface(final Class interfaceType, final ConfigMappingInterface[] superTypes, @@ -50,12 +49,10 @@ protected ConfigMappingInterface computeValue(final Class type) { this.superTypes = superTypes; List filteredProperties = new ArrayList<>(); - Map propertiesByName = new HashMap<>(); ToStringMethod toStringMethod = null; for (Property property : properties) { if (!property.isToStringMethod()) { filteredProperties.add(property); - propertiesByName.put(property.getMethod().getName(), property); } else { toStringMethod = (ToStringMethod) property; } @@ -65,7 +62,6 @@ protected ConfigMappingInterface computeValue(final Class type) { } this.properties = filteredProperties.toArray(new Property[0]); - this.propertiesByName = propertiesByName; this.toStringMethod = toStringMethod; } @@ -89,64 +85,29 @@ public Class getInterfaceType() { return interfaceType; } - /** - * Get the number of supertypes which define configuration properties. Implemented interfaces which do not - * define any configuration properties and whose supertypes in turn do not define any configuration properties - * are not counted. - * - * @return the number of supertypes - */ - int getSuperTypeCount() { - return superTypes.length; - } - public ConfigMappingInterface[] getSuperTypes() { return superTypes; } - /** - * Get the supertype at the given index, which must be greater than or equal to zero and less than the value returned - * by {@link #getSuperTypeCount()}. - * - * @param index the index - * @return the supertype definition - * @throws IndexOutOfBoundsException if {@code index} is invalid - */ - ConfigMappingInterface getSuperType(int index) throws IndexOutOfBoundsException { - if (index < 0 || index >= superTypes.length) - throw new IndexOutOfBoundsException(); - return superTypes[index]; - } - public Property[] getProperties() { return properties; } - /** - * Get the number of properties defined on this type (excluding supertypes). - * - * @return the number of properties - */ - int getPropertyCount() { - return properties.length; - } - - /** - * Get the property definition at the given index, which must be greater than or equal to zero and less than the - * value returned by {@link #getPropertyCount()}. - * - * @param index the index - * @return the property definition - * @throws IndexOutOfBoundsException if {@code index} is invalid - */ - Property getProperty(int index) throws IndexOutOfBoundsException { - if (index < 0 || index >= properties.length) - throw new IndexOutOfBoundsException(); - return properties[index]; - } - - Property getProperty(final String name) { - return propertiesByName.get(name); + public Property[] getProperties(boolean includeSuper) { + if (includeSuper) { + Map properties = new HashMap<>(); + for (ConfigMappingInterface superType : superTypes) { + for (Property property : superType.getProperties()) { + properties.put(property.getMethod().getName(), property); + } + } + for (Property property : getProperties()) { + properties.put(property.getMethod().getName(), property); + } + return properties.values().toArray(new Property[0]); + } else { + return getProperties(); + } } public boolean hasNamingStrategy() { diff --git a/implementation/src/main/java/io/smallrye/config/ConfigMappings.java b/implementation/src/main/java/io/smallrye/config/ConfigMappings.java index f274c52de..6b4056d7a 100644 --- a/implementation/src/main/java/io/smallrye/config/ConfigMappings.java +++ b/implementation/src/main/java/io/smallrye/config/ConfigMappings.java @@ -48,9 +48,6 @@ public String apply(final String path) { } }; ConfigMappingInterface configMapping = ConfigMappingLoader.getConfigMapping(configClass.getKlass()); - for (ConfigMappingInterface superType : configMapping.getSuperTypes()) { - getProperties(new GroupProperty(null, null, superType), configMapping.getNamingStrategy(), path, properties); - } getProperties(new GroupProperty(null, null, configMapping), configMapping.getNamingStrategy(), path, properties); return properties; } @@ -73,30 +70,7 @@ public static Set getKeys(final ConfigClassWithPrefix configClass) { } public static Map getDefaults(final ConfigClassWithPrefix configClass) { - Function path = new Function<>() { - @Override - public String apply(final String path) { - return configClass.getPrefix().isEmpty() && !path.isEmpty() ? path.substring(1) - : configClass.getPrefix() + path; - } - }; - ConfigMappingInterface configMapping = ConfigMappingLoader.getConfigMapping(configClass.getKlass()); Map defaults = new HashMap<>(); - - for (ConfigMappingInterface superType : configMapping.getSuperTypes()) { - Map, Map>> properties = new HashMap<>(); - getProperties(new GroupProperty(null, null, superType), configMapping.getNamingStrategy(), path, properties); - for (Map.Entry, Map>> mappingEntry : properties.entrySet()) { - for (Map.Entry> prefixEntry : mappingEntry.getValue().entrySet()) { - for (Map.Entry propertyEntry : prefixEntry.getValue().entrySet()) { - if (propertyEntry.getValue().hasDefaultValue()) { - defaults.put(propertyEntry.getKey(), propertyEntry.getValue().getDefaultValue()); - } - } - } - } - } - Map, Map>> properties = getProperties(configClass); for (Map.Entry entry : properties.get(configClass.getKlass()).get(configClass.getPrefix()) .entrySet()) { @@ -154,7 +128,7 @@ private static void getProperties( final Map, Map>> properties, final Map groupProperties) { - for (Property property : groupProperty.getGroupType().getProperties()) { + for (Property property : groupProperty.getGroupType().getProperties(true)) { getProperty(property, namingStrategy, path, properties, groupProperties); } } diff --git a/implementation/src/test/java/io/smallrye/config/ConfigMappingDefaultsTest.java b/implementation/src/test/java/io/smallrye/config/ConfigMappingDefaultsTest.java index ab9e0372b..cd32cc854 100644 --- a/implementation/src/test/java/io/smallrye/config/ConfigMappingDefaultsTest.java +++ b/implementation/src/test/java/io/smallrye/config/ConfigMappingDefaultsTest.java @@ -1,5 +1,7 @@ package io.smallrye.config; +import static io.smallrye.config.ConfigMappingDefaultsTest.S3BuildTimeConfig.AsyncHttpClientBuildTimeConfig.AsyncClientType.NETTY; +import static io.smallrye.config.ConfigMappingDefaultsTest.S3BuildTimeConfig.SyncHttpClientBuildTimeConfig.SyncClientType.URL; import static io.smallrye.config.ConfigMappings.getDefaults; import static io.smallrye.config.ConfigMappings.ConfigClassWithPrefix.configClassWithPrefix; import static io.smallrye.config.KeyValuesConfigSource.config; @@ -13,6 +15,7 @@ import java.util.Map; import java.util.Optional; import java.util.OptionalInt; +import java.util.Set; import org.junit.jupiter.api.Test; @@ -601,4 +604,73 @@ interface MapDefaults { @WithDefault("foo,bar") Map> map(); } + + @Test + void groupParentDefaults() { + SmallRyeConfig config = new SmallRyeConfigBuilder() + .withMapping(S3BuildTimeConfig.class) + .build(); + + S3BuildTimeConfig mapping = config.getConfigMapping(S3BuildTimeConfig.class); + assertEquals(URL, mapping.syncClient().type()); + assertEquals(NETTY, mapping.asyncClient().type()); + assertIterableEquals(Set.of("default"), mapping.devservices().buckets()); + assertFalse(mapping.devservices().shared()); + assertEquals("localstack", mapping.devservices().serviceName()); + } + + @ConfigMapping(prefix = "quarkus.s3") + public interface S3BuildTimeConfig extends HasSdkBuildTimeConfig { + SyncHttpClientBuildTimeConfig syncClient(); + + AsyncHttpClientBuildTimeConfig asyncClient(); + + S3DevServicesBuildTimeConfig devservices(); + + interface SyncHttpClientBuildTimeConfig { + @WithDefault(value = "url") + SyncClientType type(); + + enum SyncClientType { + URL, + APACHE + } + } + + interface AsyncHttpClientBuildTimeConfig { + @WithDefault(value = "netty") + AsyncClientType type(); + + enum AsyncClientType { + NETTY, + AWS_CRT + } + } + + interface S3DevServicesBuildTimeConfig extends DevServicesBuildTimeConfig { + @WithDefault(value = "default") + Set buckets(); + } + } + + public interface HasSdkBuildTimeConfig { + @WithParentName + SdkBuildTimeConfig sdk(); + } + + public interface SdkBuildTimeConfig { + Optional> interceptors(); + } + + public interface DevServicesBuildTimeConfig { + Optional enabled(); + + @WithDefault(value = "false") + boolean shared(); + + @WithDefault(value = "localstack") + String serviceName(); + + Map containerProperties(); + } }