From f193a2165d9261c2bd3413339c954a8bba829a93 Mon Sep 17 00:00:00 2001 From: Christof Rabensteiner Date: Thu, 16 May 2019 10:01:43 +0200 Subject: Refactor and Test ConfigProfileGenerator Refactor - Add Builder to ConfigProfileGenerator. Reason: Constructor had too many arguments. - Move Conversion from Map to Config from ConfigProfileGenerator into dedicated 'ConvertMapToConfig' Class; Reason: I expect additional configuration properties and I don't want those changes to affect the ConfigProfileGenerator (or it's test cases) - Move Access to Spring's env into facade to simplify ConfigProfileGenerator. --- .../config/DeliveryRequestAugmenterConfig.java | 33 ------ .../at/gv/egiz/moazs/config/PreprocessConfig.java | 43 +++++++ .../moazs/preprocess/ConfigProfileGenerator.java | 129 +++++++++++++-------- .../moazs/preprocess/MapToConfigConverter.java | 29 +++++ .../moazs/preprocess/SpringPropertiesFacade.java | 39 +++++++ 5 files changed, 192 insertions(+), 81 deletions(-) delete mode 100644 src/main/java/at/gv/egiz/moazs/config/DeliveryRequestAugmenterConfig.java create mode 100644 src/main/java/at/gv/egiz/moazs/config/PreprocessConfig.java create mode 100644 src/main/java/at/gv/egiz/moazs/preprocess/MapToConfigConverter.java create mode 100644 src/main/java/at/gv/egiz/moazs/preprocess/SpringPropertiesFacade.java (limited to 'src/main') diff --git a/src/main/java/at/gv/egiz/moazs/config/DeliveryRequestAugmenterConfig.java b/src/main/java/at/gv/egiz/moazs/config/DeliveryRequestAugmenterConfig.java deleted file mode 100644 index 01d13f5..0000000 --- a/src/main/java/at/gv/egiz/moazs/config/DeliveryRequestAugmenterConfig.java +++ /dev/null @@ -1,33 +0,0 @@ -package at.gv.egiz.moazs.config; - -import at.gv.egiz.moazs.preprocess.ConfigProfileGenerator; -import at.gv.egiz.moazs.preprocess.ConfigProfileMerger; -import at.gv.egiz.moazs.preprocess.ConfigProfileValidator; -import at.gv.zustellung.app2mzs.xsd.ConfigType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.ConfigurableEnvironment; - -import java.util.Map; - -@Configuration -public class DeliveryRequestAugmenterConfig { - - @Bean - @Autowired - public Map deliveryRequestConfigs(ConfigProfileGenerator generator) { - return generator.generate(); - } - - @Value("${verify-completeness-of-default-delivery-request-configuration:true}") - private boolean verifyCompletenessOfDefaultConfiguration; - - @Bean - @Autowired - public ConfigProfileGenerator configProfileGenerator(ConfigurableEnvironment env, ConfigProfileMerger merger, ConfigProfileValidator validator) { - return new ConfigProfileGenerator(env, merger, verifyCompletenessOfDefaultConfiguration, validator); - } - -} diff --git a/src/main/java/at/gv/egiz/moazs/config/PreprocessConfig.java b/src/main/java/at/gv/egiz/moazs/config/PreprocessConfig.java new file mode 100644 index 0000000..ce40691 --- /dev/null +++ b/src/main/java/at/gv/egiz/moazs/config/PreprocessConfig.java @@ -0,0 +1,43 @@ +package at.gv.egiz.moazs.config; + +import at.gv.egiz.moazs.preprocess.*; +import at.gv.zustellung.app2mzs.xsd.ConfigType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Map; + +import static at.gv.egiz.moazs.preprocess.ConfigProfileGenerator.configProfileGeneratorBuilder; + +@Configuration +public class PreprocessConfig { + + @Bean + @Autowired + public Map deliveryRequestConfigs(ConfigProfileGenerator generator) { + return generator.generate(); + } + + @Value("${verify-completeness-of-default-delivery-request-configuration:true}") + private boolean verifyCompletenessOfDefaultConfiguration; + + @Bean + @Autowired + public ConfigProfileGenerator configProfileGenerator( + SpringPropertiesFacade properties, + MapToConfigConverter converter, + ConfigProfileValidator validator, + ConfigProfileMerger merger) { + + return configProfileGeneratorBuilder() + .withProperties(properties) + .withConverter(converter) + .withValidator(validator) + .withMerger(merger) + .withVerifyCompletenessOfDefaultConfiguration(verifyCompletenessOfDefaultConfiguration) + .build(); + } + +} diff --git a/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java b/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java index 1d79eb8..0b4bc19 100644 --- a/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java +++ b/src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java @@ -4,35 +4,22 @@ import at.gv.egiz.moazs.MoaZSException; import at.gv.zustellung.app2mzs.xsd.ConfigType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.core.env.*; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import static at.gv.zustellung.app2mzs.xsd.ConfigType.configTypeBuilder; -import static at.gv.zustellung.app2mzs.xsd.ServerType.serverTypeBuilder; import static java.util.stream.Collectors.*; -import static java.util.stream.Collectors.toMap; public class ConfigProfileGenerator { private static final Logger LOGGER = LoggerFactory.getLogger(ConfigProfileGenerator.class); - private static final String PROFILE_PREFIX = "delivery-request-configuration-profiles."; - private static final String TNVZ_REQUEST_KEY = "perform-query-person-request"; - private static final String MSG_URL_KEY = "msg.url"; - private static final String DEFAULT_CONFIG_KEY = "default"; - private final boolean verifyCompletenessOfDefaultConfiguration; private static final String PROFILE_NOT_COMPLETE_WARNING_MESSAGE = "The default values for a incoming " + "mzs:DeliveryRequest/Config element could not be extracted from configuration because some values were " + "missing."; - private static final String PROFILE_NOT_COMPLETE_ERROR_MESSAGE = PROFILE_NOT_COMPLETE_WARNING_MESSAGE + " " + "Please verify that all default values are present (e.g. through application.{properties,yaml} " + "or System parameters). Otherwise, deactivate 'verify-completeness-of-default-delivery-request-configuration' " + @@ -40,21 +27,39 @@ public class ConfigProfileGenerator { "mzs:DeliveryRequest/Config needs to be configured completely *for each delivery request* in order to guarantee " + "availability."; - private final ConfigurableEnvironment env; - private final ConfigProfileMerger merger; + private final SpringPropertiesFacade properties; + private final MapToConfigConverter converter; private final ConfigProfileValidator validator; + private final ConfigProfileMerger merger; + private final boolean verifyCompletenessOfDefaultConfiguration; + private final String profilePrefix; + private final String defaultConfigKey; - public ConfigProfileGenerator(ConfigurableEnvironment env, ConfigProfileMerger merger, - boolean verifyCompletenessOfDefaultConfiguration, ConfigProfileValidator validator) { - this.env = env; + public static ConfigProfileGeneratorBuilder configProfileGeneratorBuilder() { + return new ConfigProfileGeneratorBuilder(); + } + + private ConfigProfileGenerator( + SpringPropertiesFacade properties, + MapToConfigConverter converter, + ConfigProfileValidator validator, + ConfigProfileMerger merger, + boolean verifyCompletenessOfDefaultConfiguration, + String profilePrefix, + String defaultConfigKey) { this.merger = merger; - this.verifyCompletenessOfDefaultConfiguration = verifyCompletenessOfDefaultConfiguration; this.validator = validator; + this.properties = properties; + this.converter = converter; + this.verifyCompletenessOfDefaultConfiguration = verifyCompletenessOfDefaultConfiguration; + this.profilePrefix = profilePrefix; + this.defaultConfigKey = defaultConfigKey; } + public Map generate() { - var groupedKeys = getStreamOfPropertyKeysFromEnv() + var groupedKeys = properties.getPropertyNames() .filter(this::isConfigurationProfileProperty) .map(this::removePrefix) .filter(this::hasPrefix) @@ -63,7 +68,7 @@ public class ConfigProfileGenerator { var profiles = groupedKeys.entrySet().stream() .collect(toMap(Entry::getKey, this::createConfigFromEnv)); - var defaultProfile = profiles.get(DEFAULT_CONFIG_KEY); + var defaultProfile = profiles.get(defaultConfigKey); if (!validator.isComplete(defaultProfile)) { if (verifyCompletenessOfDefaultConfiguration) @@ -80,20 +85,8 @@ public class ConfigProfileGenerator { return name.indexOf('.') != -1; } - // @author pedorro - // inspired by https://stackoverflow.com/questions/23506471/spring-access-all-environment-properties-as-a-map-or-properties-object/42521523#42521523 - private Stream getStreamOfPropertyKeysFromEnv() { - - MutablePropertySources propSrcs = env.getPropertySources(); - - return StreamSupport.stream(propSrcs.spliterator(), false) - .filter(ps -> ps instanceof EnumerablePropertySource) - .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()) - .flatMap(Arrays::stream); - } - private boolean isConfigurationProfileProperty(String propName) { - return propName.startsWith(PROFILE_PREFIX); + return propName.startsWith(profilePrefix + "."); } private String keepPrefix(String name) { @@ -112,26 +105,15 @@ public class ConfigProfileGenerator { entry.getValue().stream() .forEach(key -> { - var assembledKey = PROFILE_PREFIX + '.' + profile + '.' + key; - var value = env.getProperty(assembledKey); + var assembledKey = profilePrefix + '.' + profile + '.' + key; + var value = properties.getProperty(assembledKey); values.put(key, value); }); - var server = serverTypeBuilder() - .withZUSEUrlID(values.get(MSG_URL_KEY)) - .build(); + return converter.convert(values); - Boolean performQueryPersonRequest = values.get(TNVZ_REQUEST_KEY) == null - ? null : Boolean.getBoolean(values.get(TNVZ_REQUEST_KEY)); - - return configTypeBuilder() - .withPerformQueryPersonRequest(performQueryPersonRequest) - .withServer(server) - .build(); } - - private Map mergeProfiles(Map profiles, ConfigType defaultProfile) { return profiles.entrySet().stream() .collect(toUnmodifiableMap( @@ -139,4 +121,55 @@ public class ConfigProfileGenerator { e -> merger.merge(e.getValue(), defaultProfile))); } + public static class ConfigProfileGeneratorBuilder { + private SpringPropertiesFacade properties; + private MapToConfigConverter converter; + private ConfigProfileValidator validator; + private ConfigProfileMerger merger; + private boolean verifyCompletenessOfDefaultConfiguration = true; + private String profilePrefix = "delivery-request-configuration-profiles"; + private String defaultConfigKey = "default"; + + + public ConfigProfileGeneratorBuilder withProperties(SpringPropertiesFacade properties) { + this.properties = properties; + return this; + } + + public ConfigProfileGeneratorBuilder withConverter(MapToConfigConverter converter) { + this.converter = converter; + return this; + } + + public ConfigProfileGeneratorBuilder withValidator(ConfigProfileValidator validator) { + this.validator = validator; + return this; + } + + public ConfigProfileGeneratorBuilder withMerger(ConfigProfileMerger merger) { + this.merger = merger; + return this; + } + + public ConfigProfileGeneratorBuilder withVerifyCompletenessOfDefaultConfiguration(boolean verifyCompletenessOfDefaultConfiguration) { + this.verifyCompletenessOfDefaultConfiguration = verifyCompletenessOfDefaultConfiguration; + return this; + } + + public ConfigProfileGeneratorBuilder withProfilePrefix(String profilePrefix) { + this.profilePrefix = profilePrefix; + return this; + } + + public ConfigProfileGeneratorBuilder withDefaultConfigKey(String defaultConfigKey) { + this.defaultConfigKey = defaultConfigKey; + return this; + } + + public ConfigProfileGenerator build() { + if(properties == null || converter == null || validator == null || merger == null || profilePrefix == null || defaultConfigKey == null) + throw new IllegalArgumentException("Cannot build ConfigProfileGenerator: One or more arguments are null."); + return new ConfigProfileGenerator(properties, converter, validator, merger, verifyCompletenessOfDefaultConfiguration, profilePrefix, defaultConfigKey); + } + } } diff --git a/src/main/java/at/gv/egiz/moazs/preprocess/MapToConfigConverter.java b/src/main/java/at/gv/egiz/moazs/preprocess/MapToConfigConverter.java new file mode 100644 index 0000000..ef7cff1 --- /dev/null +++ b/src/main/java/at/gv/egiz/moazs/preprocess/MapToConfigConverter.java @@ -0,0 +1,29 @@ +package at.gv.egiz.moazs.preprocess; + +import at.gv.zustellung.app2mzs.xsd.ConfigType; +import org.springframework.stereotype.Component; + +import java.util.Map; + +import static at.gv.zustellung.app2mzs.xsd.ServerType.serverTypeBuilder; + +@Component +public class MapToConfigConverter { + + private static final String TNVZ_REQUEST_KEY = "perform-query-person-request"; + private static final String MSG_URL_KEY = "msg.url"; + + public ConfigType convert(Map values) { + var server = serverTypeBuilder() + .withZUSEUrlID(values.get(MSG_URL_KEY)) + .build(); + + Boolean performQueryPersonRequest = values.get(TNVZ_REQUEST_KEY) == null + ? null : Boolean.getBoolean(values.get(TNVZ_REQUEST_KEY)); + + return ConfigType.configTypeBuilder() + .withPerformQueryPersonRequest(performQueryPersonRequest) + .withServer(server) + .build(); + } +} diff --git a/src/main/java/at/gv/egiz/moazs/preprocess/SpringPropertiesFacade.java b/src/main/java/at/gv/egiz/moazs/preprocess/SpringPropertiesFacade.java new file mode 100644 index 0000000..4cce7e0 --- /dev/null +++ b/src/main/java/at/gv/egiz/moazs/preprocess/SpringPropertiesFacade.java @@ -0,0 +1,39 @@ +package at.gv.egiz.moazs.preprocess; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +@Component +public class SpringPropertiesFacade { + + @Autowired + private ConfigurableEnvironment env; + + /** + * Collect all properties from Spring environment and return them as a stream. + * + * inspired by https://stackoverflow.com/questions/23506471/spring-access-all-environment-properties-as-a-map-or-properties-object/42521523#42521523 + * @author pedorro + * @return + */ + public Stream getPropertyNames() { + + MutablePropertySources propSrcs = env.getPropertySources(); + + return StreamSupport.stream(propSrcs.spliterator(), false) + .filter(ps -> ps instanceof EnumerablePropertySource) + .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()) + .flatMap(Arrays::stream); + } + + public String getProperty(String name) { + return env.getProperty(name); + } +} -- cgit v1.2.3