aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristof Rabensteiner <christof.rabensteiner@iaik.tugraz.at>2019-05-16 10:01:43 +0200
committerChristof Rabensteiner <christof.rabensteiner@iaik.tugraz.at>2019-05-16 10:01:43 +0200
commitf193a2165d9261c2bd3413339c954a8bba829a93 (patch)
tree79595af29ba8c74f1abf79b213367e9d9b515078
parent5e6304ee003285793c0992a81e424969a2a6af88 (diff)
downloadmoa-zs-f193a2165d9261c2bd3413339c954a8bba829a93.tar.gz
moa-zs-f193a2165d9261c2bd3413339c954a8bba829a93.tar.bz2
moa-zs-f193a2165d9261c2bd3413339c954a8bba829a93.zip
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.
-rw-r--r--src/main/java/at/gv/egiz/moazs/config/DeliveryRequestAugmenterConfig.java33
-rw-r--r--src/main/java/at/gv/egiz/moazs/config/PreprocessConfig.java43
-rw-r--r--src/main/java/at/gv/egiz/moazs/preprocess/ConfigProfileGenerator.java129
-rw-r--r--src/main/java/at/gv/egiz/moazs/preprocess/MapToConfigConverter.java29
-rw-r--r--src/main/java/at/gv/egiz/moazs/preprocess/SpringPropertiesFacade.java39
-rw-r--r--src/test/java/at/gv/egiz/moazs/ConfigProfileGeneratorTest.java135
6 files changed, 327 insertions, 81 deletions
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<String, ConfigType> 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<String, ConfigType> 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<String, ConfigType> 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<String> 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<String, ConfigType> mergeProfiles(Map<String, ConfigType> 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<String, String> 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<String> 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);
+ }
+}
diff --git a/src/test/java/at/gv/egiz/moazs/ConfigProfileGeneratorTest.java b/src/test/java/at/gv/egiz/moazs/ConfigProfileGeneratorTest.java
new file mode 100644
index 0000000..c0ff96c
--- /dev/null
+++ b/src/test/java/at/gv/egiz/moazs/ConfigProfileGeneratorTest.java
@@ -0,0 +1,135 @@
+package at.gv.egiz.moazs;
+
+import at.gv.egiz.moazs.preprocess.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.Map;
+
+import static at.gv.egiz.moazs.preprocess.ConfigProfileGenerator.configProfileGeneratorBuilder;
+import static at.gv.zustellung.app2mzs.xsd.ConfigType.configTypeBuilder;
+import static org.mockito.ArgumentMatchers.any;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ConfigProfileGeneratorTest {
+
+ private static final String PREFIX = "prefix";
+ private static final String DEFAULT = "default";
+
+ @Mock
+ private ConfigProfileMerger merger;
+
+ @Mock
+ private ConfigProfileValidator validator;
+
+ @Mock
+ private SpringPropertiesFacade properties;
+
+ @Mock
+ private MapToConfigConverter converter;
+
+ @Test
+ public void assembleDefaultProfile() {
+ var propMap = Map.of(
+ PREFIX + "." + DEFAULT + ".property-a", "value-a",
+ PREFIX + "." + DEFAULT + ".property-b", "value-b",
+ PREFIX + "." + DEFAULT + ".property-c", "value-c");
+ var generator = setupMocksAndBuilder(propMap).build();
+
+ var profiles = generator.generate();
+
+ verify(converter).convert(Map.of(
+ "property-a", "value-a",
+ "property-b", "value-b",
+ "property-c", "value-c"));
+ assertThat(profiles.keySet()).containsExactlyInAnyOrder(DEFAULT);
+ }
+
+ @Test
+ public void assembleEmptyDefault() {
+ var propMap = Map.of(PREFIX + "." + DEFAULT, "");
+ var generator = setupMocksAndBuilder(propMap).build();
+
+ var profiles = generator.generate();
+
+ verifyZeroInteractions(converter);
+ assertThat(profiles.keySet()).isEmpty();
+ }
+
+ @Test
+ public void assembleNoProfiles() {
+ var propMap = Map.of("unrelatedpropertyname", "unrelatedvalue");
+ var generator = setupMocksAndBuilder(propMap).build();
+
+ var profiles = generator.generate();
+
+ verifyZeroInteractions(converter);
+ assertThat(profiles.keySet()).isEmpty();
+ }
+
+ @Test
+ public void assembleMultipleProfiles() {
+ var propMap = Map.of(
+ PREFIX + "." + DEFAULT+ ".property-a", "value-a",
+ PREFIX + "." + DEFAULT+ ".property-b", "value-b",
+ PREFIX + "." + "profile-1.property-c", "value-c",
+ PREFIX + "." + "profile-2.property-d", "value-d");
+
+ var generator = setupMocksAndBuilder(propMap).build();
+
+ var profiles = generator.generate();
+
+ verify(converter).convert(Map.of("property-a", "value-a", "property-b", "value-b"));
+ verify(converter).convert(Map.of("property-c", "value-c"));
+ verify(converter).convert(Map.of("property-d", "value-d"));
+ assertThat(profiles.keySet()).containsExactlyInAnyOrder(DEFAULT, "profile-1", "profile-2");
+ }
+
+ @Test(expected = MoaZSException.class)
+ public void cancelAtIncompleteDefaultProfile() {
+ var propMap = Map.of(PREFIX + "." + DEFAULT + ".property-a", "value-a");
+ var generator = setupMocksAndBuilder(propMap).build();
+ when(validator.isComplete(any())).thenReturn(false);
+
+ generator.generate();
+ }
+
+ @Test
+ public void continueAtIncompleteDefaultWhenVerificationDisabled() {
+ var propMap = Map.of(PREFIX + "." + DEFAULT + ".property-a", "value-a");
+
+ when(validator.isComplete(any())).thenReturn(false);
+
+ var generator = setupMocksAndBuilder(propMap)
+ .withVerifyCompletenessOfDefaultConfiguration(false)
+ .build();
+
+ var profiles = generator.generate();
+
+ verify(converter).convert(Map.of("property-a", "value-a"));
+ assertThat(profiles.keySet()).containsExactlyInAnyOrder(DEFAULT);
+ }
+
+ private ConfigProfileGenerator.ConfigProfileGeneratorBuilder setupMocksAndBuilder(Map<String, String> propMap) {
+ when(properties.getPropertyNames()).thenReturn(propMap.keySet().stream());
+ when(properties.getProperty(any())).thenAnswer(i -> propMap.get(i.getArgument(0)));
+ when(merger.merge(any(), any())).thenAnswer(i -> i.getArgument(0));
+ when(validator.isComplete(any())).thenReturn(true);
+ when(converter.convert(any())).thenReturn(configTypeBuilder().build());
+
+ return configProfileGeneratorBuilder()
+ .withProperties(properties)
+ .withConverter(converter)
+ .withValidator(validator)
+ .withMerger(merger)
+ .withDefaultConfigKey(DEFAULT)
+ .withProfilePrefix(PREFIX)
+ .withVerifyCompletenessOfDefaultConfiguration(true);
+ }
+
+}