Polish ConfigurationPropertySource support

Improve ConfigurationPropertySource support by reworking some of the
stream calls based on advice offered by Tagir Valeev from JetBrains.

Also improved ConfigurationPropertySource.containsDescendantOf so that
it returns an enum rather than an Optional<Boolean> (again based on
feedback from Tagir).

See gh-9000
pull/9145/head
Phillip Webb 8 years ago
parent fa4de13519
commit d969ebad07

@ -36,6 +36,7 @@ import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName; import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource; import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources; import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.context.properties.source.ConfigurationPropertyState;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.format.support.DefaultFormattingConversionService;
@ -309,8 +310,8 @@ public class Binder {
private boolean isUnbindableBean(ConfigurationPropertyName name, Bindable<?> target, private boolean isUnbindableBean(ConfigurationPropertyName name, Bindable<?> target,
Context context) { Context context) {
if (context.streamSources().map((s) -> s.containsDescendantOf(name).orElse(false)) if (context.streamSources().anyMatch((s) -> s
.anyMatch(Boolean.TRUE::equals)) { .containsDescendantOf(name) == ConfigurationPropertyState.PRESENT)) {
// We know there are properties to bind so we can't bypass anything // We know there are properties to bind so we can't bypass anything
return false; return false;
} }
@ -324,8 +325,8 @@ public class Binder {
private boolean containsNoDescendantOf(Stream<ConfigurationPropertySource> sources, private boolean containsNoDescendantOf(Stream<ConfigurationPropertySource> sources,
ConfigurationPropertyName name) { ConfigurationPropertyName name) {
return sources.map((s) -> s.containsDescendantOf(name).orElse(true)) return sources.allMatch(
.allMatch(Boolean.FALSE::equals); (s) -> s.containsDescendantOf(name) == ConfigurationPropertyState.ABSENT);
} }
/** /**

@ -27,6 +27,7 @@ import java.util.function.Supplier;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName; import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertyState;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
/** /**
@ -40,9 +41,8 @@ class JavaBeanBinder implements BeanBinder {
@Override @Override
public <T> T bind(ConfigurationPropertyName name, Bindable<T> target, public <T> T bind(ConfigurationPropertyName name, Bindable<T> target,
BindContext context, BeanPropertyBinder propertyBinder) { BindContext context, BeanPropertyBinder propertyBinder) {
boolean hasKnownBindableProperties = context.streamSources() boolean hasKnownBindableProperties = context.streamSources().anyMatch((
.map((s) -> s.containsDescendantOf(name).orElse(false)) s) -> s.containsDescendantOf(name) == ConfigurationPropertyState.PRESENT);
.anyMatch(Boolean.TRUE::equals);
Bean<T> bean = Bean.get(target, hasKnownBindableProperties); Bean<T> bean = Bean.get(target, hasKnownBindableProperties);
if (bean == null) { if (bean == null) {
return null; return null;

@ -16,8 +16,6 @@
package org.springframework.boot.context.properties.source; package org.springframework.boot.context.properties.source;
import java.util.Optional;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
@ -53,14 +51,21 @@ class AliasedConfigurationPropertySource implements ConfigurationPropertySource
} }
@Override @Override
public Optional<Boolean> containsDescendantOf(ConfigurationPropertyName name) { public ConfigurationPropertyState containsDescendantOf(
ConfigurationPropertyName name) {
Assert.notNull(name, "Name must not be null"); Assert.notNull(name, "Name must not be null");
Optional<Boolean> result = this.source.containsDescendantOf(name); ConfigurationPropertyState result = this.source.containsDescendantOf(name);
if (result != ConfigurationPropertyState.ABSENT) {
return result;
}
for (ConfigurationPropertyName alias : getAliases().getAliases(name)) { for (ConfigurationPropertyName alias : getAliases().getAliases(name)) {
Optional<Boolean> aliasResult = this.source.containsDescendantOf(alias); ConfigurationPropertyState aliasResult = this.source
result = result.flatMap((r) -> aliasResult.flatMap(a -> Optional.of(r || a))); .containsDescendantOf(alias);
if (aliasResult != ConfigurationPropertyState.ABSENT) {
return aliasResult;
}
} }
return result; return ConfigurationPropertyState.ABSENT;
} }
protected ConfigurationPropertySource getSource() { protected ConfigurationPropertySource getSource() {

@ -16,7 +16,6 @@
package org.springframework.boot.context.properties.source; package org.springframework.boot.context.properties.source;
import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
import org.springframework.boot.origin.OriginTrackedValue; import org.springframework.boot.origin.OriginTrackedValue;
@ -42,25 +41,15 @@ public interface ConfigurationPropertySource {
ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name); ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name);
/** /**
* Optionally returns if the source contains any descendants of the specified name. * Returns if the source contains any descendants of the specified name. May return
* <ul> * {@link ConfigurationPropertyState#PRESENT} or
* <li>A result of {@code true} means that there is at least on property in the source * {@link ConfigurationPropertyState#ABSENT} if an answer can be determined or
* with a name that's an * {@link ConfigurationPropertyState#UNKNOWN} if it's not possible to determine a
* {@link ConfigurationPropertyName#isAncestorOf(ConfigurationPropertyName) ancestor} * definitive answer.
* of {@code name}.</li>
* <li>A result of {@code false} means that that there are no properties in the source
* with a name that's an
* {@link ConfigurationPropertyName#isAncestorOf(ConfigurationPropertyName) ancestor}
* of {@code name}.</li>
* <li>A result of {@code empty} means it is not possible to determine up determine if
* there's a property in the source with a name that's an
* {@link ConfigurationPropertyName#isAncestorOf(ConfigurationPropertyName) ancestor}
* of {@code name}.
* </ul>
* @param name the name to check * @param name the name to check
* @return an optional boolean determining if a descendant is contained in the source * @return if the source contains any descendants
*/ */
Optional<Boolean> containsDescendantOf(ConfigurationPropertyName name); ConfigurationPropertyState containsDescendantOf(ConfigurationPropertyName name);
/** /**
* Return a filtered variant of this source, containing only names that match the * Return a filtered variant of this source, containing only names that match the

@ -0,0 +1,70 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.context.properties.source;
import java.util.function.Predicate;
import org.springframework.util.Assert;
/**
* The state of content from a {@link ConfigurationPropertySource}.
*
* @author Phillip Webb
* @since 2.0.0
*/
public enum ConfigurationPropertyState {
/**
* The {@link ConfigurationPropertySource} has at least one matching
* {@link ConfigurationProperty}.
*/
PRESENT,
/**
* The {@link ConfigurationPropertySource} has no matching
* {@link ConfigurationProperty ConfigurationProperties}.
*/
ABSENT,
/**
* It's not possible to determine if {@link ConfigurationPropertySource} has matching
* {@link ConfigurationProperty ConfigurationProperties} or not.
*/
UNKNOWN;
/**
* Search the given iterable using a predicate to determine if content is
* {@link #PRESENT} or {@link #ABSENT}.
* @param <T> the data type
* @param source the source iterable to search
* @param predicate the predicate used to test for presence
* @return {@link #PRESENT} if the iterable contains a matching item, otherwise
* {@link #ABSENT}.
*/
static <T> ConfigurationPropertyState search(Iterable<T> source,
Predicate<T> predicate) {
Assert.notNull(source, "Source must not be null");
Assert.notNull(predicate, "Predicate must not be null");
for (T item : source) {
if (predicate.test(item)) {
return PRESENT;
}
}
return ABSENT;
}
}

@ -16,7 +16,6 @@
package org.springframework.boot.context.properties.source; package org.springframework.boot.context.properties.source;
import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -49,10 +48,13 @@ class FilteredConfigurationPropertiesSource implements ConfigurationPropertySour
} }
@Override @Override
public Optional<Boolean> containsDescendantOf(ConfigurationPropertyName name) { public ConfigurationPropertyState containsDescendantOf(ConfigurationPropertyName name) {
// We can't be sure a contained descendant won't be filtered ConfigurationPropertyState result = this.source.containsDescendantOf(name);
return this.source.containsDescendantOf(name) if (result == ConfigurationPropertyState.PRESENT) {
.flatMap((result) -> result ? Optional.empty() : Optional.of(result)); // We can't be sure a contained descendant won't be filtered
return ConfigurationPropertyState.UNKNOWN;
}
return result;
} }
protected ConfigurationPropertySource getSource() { protected ConfigurationPropertySource getSource() {

@ -16,7 +16,6 @@
package org.springframework.boot.context.properties.source; package org.springframework.boot.context.properties.source;
import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
@ -48,8 +47,8 @@ class FilteredIterableConfigurationPropertiesSource
} }
@Override @Override
public Optional<Boolean> containsDescendantOf(ConfigurationPropertyName name) { public ConfigurationPropertyState containsDescendantOf(ConfigurationPropertyName name) {
return Optional.of(stream().anyMatch(name::isAncestorOf)); return ConfigurationPropertyState.search(this, name::isAncestorOf);
} }
} }

@ -17,7 +17,6 @@
package org.springframework.boot.context.properties.source; package org.springframework.boot.context.properties.source;
import java.util.Iterator; import java.util.Iterator;
import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -62,8 +61,8 @@ public interface IterableConfigurationPropertySource
Stream<ConfigurationPropertyName> stream(); Stream<ConfigurationPropertyName> stream();
@Override @Override
default Optional<Boolean> containsDescendantOf(ConfigurationPropertyName name) { default ConfigurationPropertyState containsDescendantOf(ConfigurationPropertyName name) {
return Optional.of(stream().anyMatch(name::isAncestorOf)); return ConfigurationPropertyState.search(this, name::isAncestorOf);
} }
@Override @Override

@ -20,7 +20,6 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import org.springframework.boot.env.RandomValuePropertySource; import org.springframework.boot.env.RandomValuePropertySource;
@ -62,7 +61,7 @@ class SpringConfigurationPropertySource implements ConfigurationPropertySource {
private final PropertyMapper mapper; private final PropertyMapper mapper;
private final Function<ConfigurationPropertyName, Optional<Boolean>> containsDescendantOfMethod; private final Function<ConfigurationPropertyName, ConfigurationPropertyState> containsDescendantOfMethod;
/** /**
* Create a new {@link SpringConfigurationPropertySource} implementation. * Create a new {@link SpringConfigurationPropertySource} implementation.
@ -73,13 +72,13 @@ class SpringConfigurationPropertySource implements ConfigurationPropertySource {
*/ */
SpringConfigurationPropertySource(PropertySource<?> propertySource, SpringConfigurationPropertySource(PropertySource<?> propertySource,
PropertyMapper mapper, PropertyMapper mapper,
Function<ConfigurationPropertyName, Optional<Boolean>> containsDescendantOfMethod) { Function<ConfigurationPropertyName, ConfigurationPropertyState> containsDescendantOfMethod) {
Assert.notNull(propertySource, "PropertySource must not be null"); Assert.notNull(propertySource, "PropertySource must not be null");
Assert.notNull(mapper, "Mapper must not be null"); Assert.notNull(mapper, "Mapper must not be null");
this.propertySource = propertySource; this.propertySource = propertySource;
this.mapper = new ExceptionSwallowingPropertyMapper(mapper); this.mapper = new ExceptionSwallowingPropertyMapper(mapper);
this.containsDescendantOfMethod = (containsDescendantOfMethod != null this.containsDescendantOfMethod = (containsDescendantOfMethod != null
? containsDescendantOfMethod : (n) -> Optional.empty()); ? containsDescendantOfMethod : (n) -> ConfigurationPropertyState.UNKNOWN);
} }
@Override @Override
@ -90,7 +89,7 @@ class SpringConfigurationPropertySource implements ConfigurationPropertySource {
} }
@Override @Override
public Optional<Boolean> containsDescendantOf(ConfigurationPropertyName name) { public ConfigurationPropertyState containsDescendantOf(ConfigurationPropertyName name) {
return this.containsDescendantOfMethod.apply(name); return this.containsDescendantOfMethod.apply(name);
} }
@ -173,11 +172,11 @@ class SpringConfigurationPropertySource implements ConfigurationPropertySource {
return source; return source;
} }
private static Function<ConfigurationPropertyName, Optional<Boolean>> getContainsDescendantOfMethod( private static Function<ConfigurationPropertyName, ConfigurationPropertyState> getContainsDescendantOfMethod(
PropertySource<?> source) { PropertySource<?> source) {
if (source instanceof RandomValuePropertySource) { if (source instanceof RandomValuePropertySource) {
return (name) -> Optional return (name) -> (name.isAncestorOf(RANDOM) || name.equals(RANDOM)
.of(name.isAncestorOf(RANDOM) || name.equals(RANDOM)); ? ConfigurationPropertyState.PRESENT : ConfigurationPropertyState.ABSENT);
} }
return null; return null;
} }

@ -20,7 +20,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.EnumerablePropertySource;
@ -88,8 +87,8 @@ class SpringIterableConfigurationPropertySource extends SpringConfigurationPrope
} }
@Override @Override
public Optional<Boolean> containsDescendantOf(ConfigurationPropertyName name) { public ConfigurationPropertyState containsDescendantOf(ConfigurationPropertyName name) {
return Optional.of(stream().anyMatch(name::isAncestorOf)); return ConfigurationPropertyState.search(this, name::isAncestorOf);
} }
private List<ConfigurationPropertyName> getConfigurationPropertyNames() { private List<ConfigurationPropertyName> getConfigurationPropertyNames() {

@ -16,8 +16,6 @@
package org.springframework.boot.context.properties.source; package org.springframework.boot.context.properties.source;
import java.util.Optional;
import org.junit.Test; import org.junit.Test;
import org.mockito.Answers; import org.mockito.Answers;
@ -57,56 +55,65 @@ public class AliasedConfigurationPropertySourceTests {
} }
@Test @Test
public void containsDescendantOfWhenSourceReturnsEmptyShouldReturnEmpty() public void containsDescendantOfWhenSourceReturnsUnknownShouldReturnUnknown()
throws Exception { throws Exception {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo"); ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, ConfigurationPropertySource source = mock(ConfigurationPropertySource.class,
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
given(source.containsDescendantOf(name)).willReturn(Optional.empty()); given(source.containsDescendantOf(name))
.willReturn(ConfigurationPropertyState.UNKNOWN);
ConfigurationPropertySource aliased = source ConfigurationPropertySource aliased = source
.withAliases(new ConfigurationPropertyNameAliases("foo.bar", "foo.bar1")); .withAliases(new ConfigurationPropertyNameAliases("foo.bar", "foo.bar1"));
assertThat(aliased.containsDescendantOf(name)).isEmpty(); assertThat(aliased.containsDescendantOf(name))
.isEqualTo(ConfigurationPropertyState.UNKNOWN);
} }
@Test @Test
public void containsDescendantOfWhenAliasReturnsEmptyShouldReturnEmpty() public void containsDescendantOfWhenSourceReturnsPresentShouldReturnPresent()
throws Exception { throws Exception {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo"); ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, ConfigurationPropertySource source = mock(ConfigurationPropertySource.class,
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
given(source.containsDescendantOf(name)).willReturn(Optional.of(true)); given(source.containsDescendantOf(name))
.willReturn(ConfigurationPropertyState.PRESENT);
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar"))) given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
.willReturn(Optional.empty()); .willReturn(ConfigurationPropertyState.UNKNOWN);
ConfigurationPropertySource aliased = source ConfigurationPropertySource aliased = source
.withAliases(new ConfigurationPropertyNameAliases("foo", "bar")); .withAliases(new ConfigurationPropertyNameAliases("foo.bar", "foo.bar1"));
assertThat(aliased.containsDescendantOf(name)).isEmpty(); assertThat(aliased.containsDescendantOf(name))
.isEqualTo(ConfigurationPropertyState.PRESENT);
} }
@Test @Test
public void containsDescendantOfWhenAllAreFalseShouldReturnFalse() throws Exception { public void containsDescendantOfWhenAllAreAbsentShouldReturnAbsent()
throws Exception {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo"); ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, ConfigurationPropertySource source = mock(ConfigurationPropertySource.class,
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
given(source.containsDescendantOf(name)).willReturn(Optional.of(false)); given(source.containsDescendantOf(name))
.willReturn(ConfigurationPropertyState.ABSENT);
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar"))) given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
.willReturn(Optional.of(false)); .willReturn(ConfigurationPropertyState.ABSENT);
ConfigurationPropertySource aliased = source ConfigurationPropertySource aliased = source
.withAliases(new ConfigurationPropertyNameAliases("foo", "bar")); .withAliases(new ConfigurationPropertyNameAliases("foo", "bar"));
assertThat(aliased.containsDescendantOf(name)).contains(false); assertThat(aliased.containsDescendantOf(name))
.isEqualTo(ConfigurationPropertyState.ABSENT);
} }
@Test @Test
public void containsDescendantOfWhenAnyIsTrueShouldReturnTrue() throws Exception { public void containsDescendantOfWhenAnyIsPresentShouldReturnPresent()
throws Exception {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo"); ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, ConfigurationPropertySource source = mock(ConfigurationPropertySource.class,
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
given(source.containsDescendantOf(name)).willReturn(Optional.of(false)); given(source.containsDescendantOf(name))
.willReturn(ConfigurationPropertyState.ABSENT);
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar"))) given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
.willReturn(Optional.of(true)); .willReturn(ConfigurationPropertyState.PRESENT);
ConfigurationPropertySource aliased = source ConfigurationPropertySource aliased = source
.withAliases(new ConfigurationPropertyNameAliases("foo", "bar")); .withAliases(new ConfigurationPropertyNameAliases("foo", "bar"));
assertThat(aliased.containsDescendantOf(name)).contains(true); assertThat(aliased.containsDescendantOf(name))
.isEqualTo(ConfigurationPropertyState.PRESENT);
} }
private Object getValue(ConfigurationPropertySource source, String name) { private Object getValue(ConfigurationPropertySource source, String name) {

@ -0,0 +1,69 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.context.properties.source;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ConfigurationPropertyState}.
*
* @author Phillip Webb
*/
public class ConfigurationPropertyStateTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void searchWhenIterableIsNullShouldThrowException() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Source must not be null");
ConfigurationPropertyState.search(null, (e) -> true);
}
@Test
public void searchWhenPredicateIsNullShouldThrowException() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Predicate must not be null");
ConfigurationPropertyState.search(Collections.emptyList(), null);
}
@Test
public void searchWhenContainsItemShouldReturnPresent() {
List<String> source = Arrays.asList("a", "b", "c");
ConfigurationPropertyState result = ConfigurationPropertyState.search(source,
"b"::equals);
assertThat(result).isEqualTo(ConfigurationPropertyState.PRESENT);
}
@Test
public void searchWhenContainsNoItemShouldReturnAbsent() {
List<String> source = Arrays.asList("a", "x", "c");
ConfigurationPropertyState result = ConfigurationPropertyState.search(source,
"b"::equals);
assertThat(result).isEqualTo(ConfigurationPropertyState.ABSENT);
}
}

@ -17,7 +17,6 @@
package org.springframework.boot.context.properties.source; package org.springframework.boot.context.properties.source;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@ -74,9 +73,11 @@ public class FilteredConfigurationPropertiesSourceTests {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo"); ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, ConfigurationPropertySource source = mock(ConfigurationPropertySource.class,
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
given(source.containsDescendantOf(name)).willReturn(Optional.empty()); given(source.containsDescendantOf(name))
.willReturn(ConfigurationPropertyState.UNKNOWN);
ConfigurationPropertySource filtered = source.filter((n) -> true); ConfigurationPropertySource filtered = source.filter((n) -> true);
assertThat(filtered.containsDescendantOf(name)).isEmpty(); assertThat(filtered.containsDescendantOf(name))
.isEqualTo(ConfigurationPropertyState.UNKNOWN);
} }
@Test @Test
@ -85,9 +86,11 @@ public class FilteredConfigurationPropertiesSourceTests {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo"); ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, ConfigurationPropertySource source = mock(ConfigurationPropertySource.class,
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
given(source.containsDescendantOf(name)).willReturn(Optional.of(false)); given(source.containsDescendantOf(name))
.willReturn(ConfigurationPropertyState.ABSENT);
ConfigurationPropertySource filtered = source.filter((n) -> true); ConfigurationPropertySource filtered = source.filter((n) -> true);
assertThat(filtered.containsDescendantOf(name)).contains(false); assertThat(filtered.containsDescendantOf(name))
.isEqualTo(ConfigurationPropertyState.ABSENT);
} }
@Test @Test
@ -96,9 +99,11 @@ public class FilteredConfigurationPropertiesSourceTests {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo"); ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, ConfigurationPropertySource source = mock(ConfigurationPropertySource.class,
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS)); withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
given(source.containsDescendantOf(name)).willReturn(Optional.of(true)); given(source.containsDescendantOf(name))
.willReturn(ConfigurationPropertyState.PRESENT);
ConfigurationPropertySource filtered = source.filter((n) -> true); ConfigurationPropertySource filtered = source.filter((n) -> true);
assertThat(filtered.containsDescendantOf(name)).isEmpty(); assertThat(filtered.containsDescendantOf(name))
.isEqualTo(ConfigurationPropertyState.UNKNOWN);
} }
protected final ConfigurationPropertySource createTestSource() { protected final ConfigurationPropertySource createTestSource() {

@ -51,9 +51,9 @@ public class FilteredIterableConfigurationPropertiesSourceTests
source.put("faf.bar[0]", "1"); source.put("faf.bar[0]", "1");
IterableConfigurationPropertySource filtered = source.filter(this::noBrackets); IterableConfigurationPropertySource filtered = source.filter(this::noBrackets);
assertThat(filtered.containsDescendantOf(ConfigurationPropertyName.of("foo"))) assertThat(filtered.containsDescendantOf(ConfigurationPropertyName.of("foo")))
.contains(true); .isEqualTo(ConfigurationPropertyState.PRESENT);
assertThat(filtered.containsDescendantOf(ConfigurationPropertyName.of("faf"))) assertThat(filtered.containsDescendantOf(ConfigurationPropertyName.of("faf")))
.contains(false); .isEqualTo(ConfigurationPropertyState.ABSENT);
} }
private boolean noBrackets(ConfigurationPropertyName name) { private boolean noBrackets(ConfigurationPropertyName name) {

@ -19,7 +19,6 @@ package org.springframework.boot.context.properties.source;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.springframework.boot.origin.MockOrigin; import org.springframework.boot.origin.MockOrigin;
@ -99,8 +98,9 @@ public class MockConfigurationPropertySource
} }
@Override @Override
public Optional<Boolean> containsDescendantOf(ConfigurationPropertyName name) { public ConfigurationPropertyState containsDescendantOf(
return Optional.empty(); ConfigurationPropertyName name) {
return ConfigurationPropertyState.UNKNOWN;
} }
} }

@ -122,7 +122,7 @@ public class SpringConfigurationPropertySourceTests {
SpringConfigurationPropertySource adapter = new SpringConfigurationPropertySource( SpringConfigurationPropertySource adapter = new SpringConfigurationPropertySource(
propertySource, DefaultPropertyMapper.INSTANCE, null); propertySource, DefaultPropertyMapper.INSTANCE, null);
assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("foo"))) assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("foo")))
.isEmpty(); .isEqualTo(ConfigurationPropertyState.UNKNOWN);
} }
@Test @Test

@ -165,11 +165,11 @@ public class SpringIterableConfigurationPropertySourceTests {
SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource( SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
propertySource, DefaultPropertyMapper.INSTANCE); propertySource, DefaultPropertyMapper.INSTANCE);
assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("foo"))) assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("foo")))
.contains(true); .isEqualTo(ConfigurationPropertyState.PRESENT);
assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("faf"))) assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("faf")))
.contains(false); .isEqualTo(ConfigurationPropertyState.ABSENT);
assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("fof"))) assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("fof")))
.contains(false); .isEqualTo(ConfigurationPropertyState.ABSENT);
} }
/** /**

Loading…
Cancel
Save