ConfigObserver { public <T> ConfigObserver onPrefixedOptionalValue(String prefix, ConfigListener.Transformer<T> transformer, ConfigValueListener<Optional<T>> listener) { return onConfigChange(new ConfigListener() { @Override public void onConfigChanged(Set<String> changedKeys, ConfigMap newConfiguration) { if (changeIncludes(changedKeys, prefix)) { applyConfiguration( listener, newConfiguration.subMap(prefix).map(c -> transform(c, transformer)) ); } } }); } ConfigObserver(String applicationName);  ConfigObserver(File configDirectory, String applicationName);  ConfigObserver(File configDirectory, String applicationName, List<String> profiles);  ConfigObserver(ConfigLoader configLoader); ConfigObserver onConfigChange(ConfigListener listener); ConfigObserver onSingleConfigValue(String key, Function<String, T> transformer, T defaultValue, ConfigValueListener<T> listener); ConfigObserver onStringValue(String key, String defaultValue, ConfigValueListener<String> listener); ConfigObserver onIntValue(String key, int defaultValue, ConfigValueListener<Integer> listener); ConfigObserver onLongValue(String key, long defaultValue, ConfigValueListener<Long> listener); ConfigObserver onInetSocketAddress(String key, int defaultPort, ConfigValueListener<InetSocketAddress> listener); ConfigObserver onInetSocketAddress(String key, InetSocketAddress defaultAddress, ConfigValueListener<InetSocketAddress> listener); ConfigObserver onDurationValue(String key, Duration defaultValue, ConfigValueListener<Duration> listener); ConfigObserver onStringListValue(String key, String defaultValue, ConfigValueListener<List<String>> listener); ConfigObserver onPrefixedValue(String prefix, ConfigValueListener<Map<String, String>> listener); ConfigObserver onPrefixedValue(String prefix, ConfigListener.Transformer<T> transformer, ConfigValueListener<T> listener); ConfigObserver onPrefixedOptionalValue(String prefix, ConfigListener.Transformer<T> transformer, ConfigValueListener<Optional<T>> listener); ConfigObserver onPrefixedOptionalValue(String prefix, ConfigValueListener<Optional<Map<String, String>>> listener); void updateConfiguration(Map<String, String> newConfiguration);  }
@Test public void shouldSupportMissingValuesWithPrefix() { AtomicReference<Optional<Credentials>> credentials = new AtomicReference<>(Optional.empty()); writeConfigLines("somethingElse.username=someuser"); observer.onPrefixedOptionalValue("credentials", Credentials::new, credentials::set); assertThat(credentials.get()).isEmpty(); writeConfigLines("credentials.username=someuser2", "credentials.password=secret"); assertThat(credentials.get()).get().isEqualToComparingFieldByField(new Credentials("someuser2", "secret")); writeConfigLines("somethingElse.username=someuser"); assertThat(credentials.get()).isEmpty(); }
@Test public void shouldTransformWithPrefix() { AtomicReference<Optional<Credentials>> credentials = new AtomicReference<>(Optional.empty()); writeConfigLines("credentials.username=someuser"); observer.onPrefixedOptionalValue("credentials", Credentials::new, credentials::set); assertThat(credentials.get()).get().isEqualToComparingFieldByField(new Credentials("someuser", null)); writeConfigLines("credentials.username=someuser2", "credentials.password=secret"); assertThat(credentials.get()).get().isEqualToComparingFieldByField(new Credentials("someuser2", "secret")); }
@Test public void shouldReadOptionalValue() { AtomicReference<Optional<Map<String, String>>> credentials = new AtomicReference<>(Optional.empty()); writeConfigLines("credentials.username=someuser"); observer.onPrefixedOptionalValue("credentials", credentials::set); assertThat(credentials.get()).get().isEqualTo(Map.of("username", "someuser")); }