Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate defaults and properties for all super types #1073

Merged
merged 1 commit into from
Dec 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, Property> propertiesByName;
private final ToStringMethod toStringMethod;

ConfigMappingInterface(final Class<?> interfaceType, final ConfigMappingInterface[] superTypes,
Expand All @@ -50,12 +49,10 @@ protected ConfigMappingInterface computeValue(final Class<?> type) {
this.superTypes = superTypes;

List<Property> filteredProperties = new ArrayList<>();
Map<String, Property> 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;
}
Expand All @@ -65,7 +62,6 @@ protected ConfigMappingInterface computeValue(final Class<?> type) {
}

this.properties = filteredProperties.toArray(new Property[0]);
this.propertiesByName = propertiesByName;
this.toStringMethod = toStringMethod;
}

Expand All @@ -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<String, Property> 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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -73,30 +70,7 @@ public static Set<String> getKeys(final ConfigClassWithPrefix configClass) {
}

public static Map<String, String> getDefaults(final ConfigClassWithPrefix configClass) {
Function<String, String> 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<String, String> defaults = new HashMap<>();

for (ConfigMappingInterface superType : configMapping.getSuperTypes()) {
Map<Class<?>, Map<String, Map<String, Property>>> properties = new HashMap<>();
getProperties(new GroupProperty(null, null, superType), configMapping.getNamingStrategy(), path, properties);
for (Map.Entry<Class<?>, Map<String, Map<String, Property>>> mappingEntry : properties.entrySet()) {
for (Map.Entry<String, Map<String, Property>> prefixEntry : mappingEntry.getValue().entrySet()) {
for (Map.Entry<String, Property> propertyEntry : prefixEntry.getValue().entrySet()) {
if (propertyEntry.getValue().hasDefaultValue()) {
defaults.put(propertyEntry.getKey(), propertyEntry.getValue().getDefaultValue());
}
}
}
}
}

Map<Class<?>, Map<String, Map<String, Property>>> properties = getProperties(configClass);
for (Map.Entry<String, Property> entry : properties.get(configClass.getKlass()).get(configClass.getPrefix())
.entrySet()) {
Expand Down Expand Up @@ -154,7 +128,7 @@ private static void getProperties(
final Map<Class<?>, Map<String, Map<String, Property>>> properties,
final Map<String, Property> groupProperties) {

for (Property property : groupProperty.getGroupType().getProperties()) {
for (Property property : groupProperty.getGroupType().getProperties(true)) {
getProperty(property, namingStrategy, path, properties, groupProperties);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -601,4 +604,73 @@ interface MapDefaults {
@WithDefault("foo,bar")
Map<String, List<String>> 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<String> buckets();
}
}

public interface HasSdkBuildTimeConfig {
@WithParentName
SdkBuildTimeConfig sdk();
}

public interface SdkBuildTimeConfig {
Optional<List<String>> interceptors();
}

public interface DevServicesBuildTimeConfig {
Optional<Boolean> enabled();

@WithDefault(value = "false")
boolean shared();

@WithDefault(value = "localstack")
String serviceName();

Map<String, String> containerProperties();
}
}
Loading