Reduce ConfigurationPropertyName garbage
Update the `ConfigurationPropertyNameBuilder` to reduce the number of objects created. Fixes gh-9022
This commit is contained in:
parent
19f166a56f
commit
d6099bafa3
|
@ -23,6 +23,7 @@ import java.util.regex.Pattern;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Element;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Element;
|
||||||
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyNameBuilder.ElementValueProcessor;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
@ -62,7 +63,7 @@ public final class ConfigurationPropertyName
|
||||||
null, new Element());
|
null, new Element());
|
||||||
|
|
||||||
private static final ConfigurationPropertyNameBuilder BUILDER = new ConfigurationPropertyNameBuilder(
|
private static final ConfigurationPropertyNameBuilder BUILDER = new ConfigurationPropertyNameBuilder(
|
||||||
Pattern.compile("[a-z]([a-z0-9\\-])*"));
|
ElementValueProcessor.identity().withValidName());
|
||||||
|
|
||||||
private final ConfigurationPropertyName parent;
|
private final ConfigurationPropertyName parent;
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ public final class ConfigurationPropertyName
|
||||||
|
|
||||||
ConfigurationPropertyName(ConfigurationPropertyName parent, Element element) {
|
ConfigurationPropertyName(ConfigurationPropertyName parent, Element element) {
|
||||||
Assert.notNull(element, "Element must not be null");
|
Assert.notNull(element, "Element must not be null");
|
||||||
this.parent = parent;
|
this.parent = (parent == EMPTY ? null : parent);
|
||||||
this.element = element;
|
this.element = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,7 +208,7 @@ public final class ConfigurationPropertyName
|
||||||
* @return a new {@link ConfigurationPropertyName}
|
* @return a new {@link ConfigurationPropertyName}
|
||||||
*/
|
*/
|
||||||
public ConfigurationPropertyName appendIndex(int index) {
|
public ConfigurationPropertyName appendIndex(int index) {
|
||||||
return append("[" + index + "]");
|
return BUILDER.from(this, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -217,7 +218,7 @@ public final class ConfigurationPropertyName
|
||||||
*/
|
*/
|
||||||
public ConfigurationPropertyName append(String element) {
|
public ConfigurationPropertyName append(String element) {
|
||||||
if (StringUtils.hasLength(element)) {
|
if (StringUtils.hasLength(element)) {
|
||||||
return BUILDER.from(this).append(element).build();
|
return BUILDER.from(this, element);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +237,7 @@ public final class ConfigurationPropertyName
|
||||||
if (StringUtils.isEmpty(name)) {
|
if (StringUtils.isEmpty(name)) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
}
|
}
|
||||||
return BUILDER.from(name, '.').build();
|
return BUILDER.from(name, '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -257,7 +258,7 @@ public final class ConfigurationPropertyName
|
||||||
|
|
||||||
Element(String value) {
|
Element(String value) {
|
||||||
Assert.notNull(value, "Value must not be null");
|
Assert.notNull(value, "Value must not be null");
|
||||||
this.indexed = (value.startsWith("[") && value.endsWith("]"));
|
this.indexed = isIndexed(value);
|
||||||
value = (this.indexed ? value.substring(1, value.length() - 1) : value);
|
value = (this.indexed ? value.substring(1, value.length() - 1) : value);
|
||||||
if (!this.indexed) {
|
if (!this.indexed) {
|
||||||
validate(value);
|
validate(value);
|
||||||
|
@ -331,6 +332,10 @@ public final class ConfigurationPropertyName
|
||||||
return this.value[form.ordinal()];
|
return this.value[form.ordinal()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isIndexed(String value) {
|
||||||
|
return value.startsWith("[") && value.endsWith("]");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,16 +17,15 @@
|
||||||
package org.springframework.boot.context.properties.source;
|
package org.springframework.boot.context.properties.source;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Element;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Element;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Form;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Form;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder class that can be used to create {@link ConfigurationPropertyName
|
* Builder class that can be used to create {@link ConfigurationPropertyName
|
||||||
|
@ -39,64 +38,40 @@ import org.springframework.util.CollectionUtils;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
* @since 2.0.0
|
|
||||||
* @see ConfigurationPropertyName
|
* @see ConfigurationPropertyName
|
||||||
*/
|
*/
|
||||||
public class ConfigurationPropertyNameBuilder {
|
class ConfigurationPropertyNameBuilder {
|
||||||
|
|
||||||
|
private static final Element INDEX_ZERO_ELEMENT = new Element("[0]");
|
||||||
|
|
||||||
private final ElementValueProcessor processor;
|
private final ElementValueProcessor processor;
|
||||||
|
|
||||||
private final List<Element> elements;
|
private final Map<String, ConfigurationPropertyName> nameCache = new ConcurrentReferenceHashMap<>();
|
||||||
|
|
||||||
/**
|
ConfigurationPropertyNameBuilder() {
|
||||||
* Create a new {@link ConfigurationPropertyNameBuilder} instance.
|
this(ElementValueProcessor.identity());
|
||||||
*/
|
|
||||||
public ConfigurationPropertyNameBuilder() {
|
|
||||||
this(ElementValueProcessor.empty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
ConfigurationPropertyNameBuilder(ElementValueProcessor processor) {
|
||||||
* Create a new {@link ConfigurationPropertyNameBuilder} instance that enforces a
|
|
||||||
* {@link Pattern} on all element values.
|
|
||||||
* @param elementValuePattern the element value pattern to enforce
|
|
||||||
*/
|
|
||||||
public ConfigurationPropertyNameBuilder(Pattern elementValuePattern) {
|
|
||||||
this(ElementValueProcessor.empty().withPatternCheck(elementValuePattern));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new {@link ConfigurationPropertyNameBuilder} with the specified
|
|
||||||
* {@link ElementValueProcessor}.
|
|
||||||
* @param processor the element value processor.
|
|
||||||
*/
|
|
||||||
public ConfigurationPropertyNameBuilder(ElementValueProcessor processor) {
|
|
||||||
Assert.notNull(processor, "Processor must not be null");
|
Assert.notNull(processor, "Processor must not be null");
|
||||||
this.processor = processor;
|
this.processor = processor;
|
||||||
this.elements = Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal constructor used to create new builders.
|
* Build using the specified name split up into elements using a known separator. For
|
||||||
* @param processor the element value processor.
|
* example {@code from("foo.bar", '.')} will return a new builder containing the
|
||||||
* @param elements the elements built so far
|
* elements "{@code foo}" and "{@code bar}". Any element in square brackets will be
|
||||||
*/
|
* considered "indexed" and will not be considered for splitting.
|
||||||
private ConfigurationPropertyNameBuilder(ElementValueProcessor processor,
|
|
||||||
List<Element> elements) {
|
|
||||||
this.processor = processor;
|
|
||||||
this.elements = elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start building using the specified name split up into elements using a known
|
|
||||||
* separator. For example {@code from("foo.bar", '.')} will return a new builder
|
|
||||||
* containing the elements "{@code foo}" and "{@code bar}". Any element in square
|
|
||||||
* brackets will be considered "indexed" and will not be considered for splitting.
|
|
||||||
* @param name the name build from
|
* @param name the name build from
|
||||||
* @param separator the separator
|
* @param separator the separator
|
||||||
* @return a builder with elements populated from the name
|
* @return a builder with elements populated from the name
|
||||||
*/
|
*/
|
||||||
public ConfigurationPropertyNameBuilder from(String name, char separator) {
|
public ConfigurationPropertyName from(String name, char separator) {
|
||||||
Assert.notNull(name, "Name must not be null");
|
Assert.notNull(name, "Name must not be null");
|
||||||
|
ConfigurationPropertyName result = this.nameCache.get(name);
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
List<Element> elements = new ArrayList<>();
|
List<Element> elements = new ArrayList<>();
|
||||||
StringBuilder value = new StringBuilder(name.length());
|
StringBuilder value = new StringBuilder(name.length());
|
||||||
boolean indexed = false;
|
boolean indexed = false;
|
||||||
|
@ -124,8 +99,10 @@ public class ConfigurationPropertyNameBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addElement(elements, value);
|
addElement(elements, value);
|
||||||
return from(elements.stream().filter(Objects::nonNull)
|
result = from(elements.stream().filter(Objects::nonNull)
|
||||||
.filter((e) -> !e.getValue(Form.UNIFORM).isEmpty()).iterator());
|
.filter((e) -> !e.getValue(Form.UNIFORM).isEmpty()).iterator());
|
||||||
|
this.nameCache.put(name, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addElement(List<Element> elements, StringBuilder value) {
|
private void addElement(List<Element> elements, StringBuilder value) {
|
||||||
|
@ -135,74 +112,32 @@ public class ConfigurationPropertyNameBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private ConfigurationPropertyName from(Iterator<Element> elements) {
|
||||||
* Return a new {@link ConfigurationPropertyNameBuilder} starting with the specified
|
ConfigurationPropertyName name = null;
|
||||||
* elements.
|
while (elements.hasNext()) {
|
||||||
* @param elements the elements that the new builder should contain
|
name = new ConfigurationPropertyName(name, elements.next());
|
||||||
* @return a new initialized builder instance
|
}
|
||||||
*/
|
Assert.state(name != null, "At least one element must be defined");
|
||||||
public ConfigurationPropertyNameBuilder from(Iterable<Element> elements) {
|
return name;
|
||||||
return from(elements.iterator());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public ConfigurationPropertyName from(ConfigurationPropertyName parent, int index) {
|
||||||
* Return a new {@link ConfigurationPropertyNameBuilder} starting with the specified
|
if (index == 0) {
|
||||||
* elements.
|
return new ConfigurationPropertyName(parent, INDEX_ZERO_ELEMENT);
|
||||||
* @param elements the elements that the new builder should contain
|
}
|
||||||
* @return a new initialized builder instance
|
return from(parent, "[" + index + "]");
|
||||||
*/
|
|
||||||
public ConfigurationPropertyNameBuilder from(Iterator<Element> elements) {
|
|
||||||
Assert.state(CollectionUtils.isEmpty(this.elements),
|
|
||||||
"Existing elements must not be present");
|
|
||||||
return new ConfigurationPropertyNameBuilder(this.processor, toList(elements));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Element> toList(Iterator<Element> iterator) {
|
public ConfigurationPropertyName from(ConfigurationPropertyName parent,
|
||||||
List<Element> list = new ArrayList<>();
|
String elementValue) {
|
||||||
while (iterator.hasNext()) {
|
return new ConfigurationPropertyName(parent, buildElement(elementValue));
|
||||||
list.add(iterator.next());
|
|
||||||
}
|
|
||||||
if (isRoot(list)) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isRoot(List<Element> list) {
|
|
||||||
return (list.size() == 1 && list.get(0).getValue(Form.ORIGINAL).isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a new builder containing the elements built so far appended with the
|
|
||||||
* specified element value.
|
|
||||||
* @param elementValue the element value to append
|
|
||||||
* @return a new builder instance
|
|
||||||
*/
|
|
||||||
public ConfigurationPropertyNameBuilder append(String elementValue) {
|
|
||||||
Assert.notNull(elementValue, "ElementValue must not be null");
|
|
||||||
List<Element> elements = new ArrayList<>(this.elements);
|
|
||||||
elements.add(buildElement(elementValue));
|
|
||||||
return new ConfigurationPropertyNameBuilder(this.processor, elements);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Element buildElement(String value) {
|
private Element buildElement(String value) {
|
||||||
return new Element(this.processor.apply(value));
|
return new Element(this.processor.apply(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a new {@link ConfigurationPropertyName} from the elements contained in this
|
|
||||||
* builder.
|
|
||||||
* @return a new {@link ConfigurationPropertyName}.
|
|
||||||
*/
|
|
||||||
public ConfigurationPropertyName build() {
|
|
||||||
ConfigurationPropertyName name = null;
|
|
||||||
for (Element element : this.elements) {
|
|
||||||
name = new ConfigurationPropertyName(name, element);
|
|
||||||
}
|
|
||||||
Assert.state(name != null, "At least one element must be defined");
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An processor that will be applied to element values. Can be used to manipulate or
|
* An processor that will be applied to element values. Can be used to manipulate or
|
||||||
* restrict the values that are used.
|
* restrict the values that are used.
|
||||||
|
@ -218,32 +153,37 @@ public class ConfigurationPropertyNameBuilder {
|
||||||
*/
|
*/
|
||||||
String apply(String value) throws RuntimeException;
|
String apply(String value) throws RuntimeException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend this processor with a {@link Pattern} regular expression check.
|
|
||||||
* @param pattern the patter to check
|
|
||||||
* @return an element processor that additionally checks against the pattern
|
|
||||||
*/
|
|
||||||
default ElementValueProcessor withPatternCheck(Pattern pattern) {
|
|
||||||
Assert.notNull(pattern, "Pattern must not be null");
|
|
||||||
return (value) -> {
|
|
||||||
value = apply(value);
|
|
||||||
Element element = new Element(value);
|
|
||||||
Assert.isTrue(element.isIndexed() || pattern.matcher(value).matches(),
|
|
||||||
"Element value '" + value + "' is not valid (" + pattern
|
|
||||||
+ " does not match)");
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an empty {@link ElementValueProcessor} that simply returns the original
|
* Return an empty {@link ElementValueProcessor} that simply returns the original
|
||||||
* value unchanged.
|
* value unchanged.
|
||||||
* @return an empty {@link ElementValueProcessor}.
|
* @return an empty {@link ElementValueProcessor}.
|
||||||
*/
|
*/
|
||||||
static ElementValueProcessor empty() {
|
static ElementValueProcessor identity() {
|
||||||
return (value) -> value;
|
return (value) -> value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend this processor with a to enforce standard element name rules.
|
||||||
|
* @return an element processor that additionally enforces a valid name
|
||||||
|
*/
|
||||||
|
default ElementValueProcessor withValidName() {
|
||||||
|
return (value) -> {
|
||||||
|
value = apply(value);
|
||||||
|
if (!Element.isIndexed(value)) {
|
||||||
|
for (int i = 0; i < value.length(); i++) {
|
||||||
|
char ch = value.charAt(i);
|
||||||
|
boolean isAlpha = ch >= 'a' && ch <= 'z';
|
||||||
|
boolean isNumeric = ch >= '0' && ch <= '9';
|
||||||
|
if (i == 0 && !isAlpha || !(isAlpha || isNumeric || ch == '-')) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Element value '" + value + "' is not valid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ class DefaultPropertyMapper implements PropertyMapper {
|
||||||
private List<PropertyMapping> tryMap(String propertySourceName) {
|
private List<PropertyMapping> tryMap(String propertySourceName) {
|
||||||
try {
|
try {
|
||||||
ConfigurationPropertyName convertedName = this.nameBuilder
|
ConfigurationPropertyName convertedName = this.nameBuilder
|
||||||
.from(propertySourceName, '.').build();
|
.from(propertySourceName, '.');
|
||||||
PropertyMapping o = new PropertyMapping(propertySourceName, convertedName);
|
PropertyMapping o = new PropertyMapping(propertySourceName, convertedName);
|
||||||
return Collections.singletonList(o);
|
return Collections.singletonList(o);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ class SystemEnvironmentPropertyMapper implements PropertyMapper {
|
||||||
|
|
||||||
private ConfigurationPropertyName convertName(String propertySourceName) {
|
private ConfigurationPropertyName convertName(String propertySourceName) {
|
||||||
try {
|
try {
|
||||||
return this.nameBuilder.from(propertySourceName, '_').build();
|
return this.nameBuilder.from(propertySourceName, '_');
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
|
|
||||||
package org.springframework.boot.context.properties.source;
|
package org.springframework.boot.context.properties.source;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
|
@ -27,7 +27,6 @@ import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Element;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName.Element;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyNameBuilder.ElementValueProcessor;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyNameBuilder.ElementValueProcessor;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@ -44,13 +43,6 @@ public class ConfigurationPropertyNameBuilderTests {
|
||||||
|
|
||||||
private ConfigurationPropertyNameBuilder builder;
|
private ConfigurationPropertyNameBuilder builder;
|
||||||
|
|
||||||
@Test
|
|
||||||
public void createWhenPatternIsNullShouldThrowException() throws Exception {
|
|
||||||
this.thrown.expect(IllegalArgumentException.class);
|
|
||||||
this.thrown.expectMessage("Pattern must not be null");
|
|
||||||
this.builder = new ConfigurationPropertyNameBuilder((Pattern) null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createWhenElementProcessorIsNullShouldThrowException() throws Exception {
|
public void createWhenElementProcessorIsNullShouldThrowException() throws Exception {
|
||||||
this.thrown.expect(IllegalArgumentException.class);
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
@ -62,39 +54,31 @@ public class ConfigurationPropertyNameBuilderTests {
|
||||||
public void buildShouldCreateName() throws Exception {
|
public void buildShouldCreateName() throws Exception {
|
||||||
this.builder = new ConfigurationPropertyNameBuilder();
|
this.builder = new ConfigurationPropertyNameBuilder();
|
||||||
ConfigurationPropertyName expected = ConfigurationPropertyName.of("foo.bar.baz");
|
ConfigurationPropertyName expected = ConfigurationPropertyName.of("foo.bar.baz");
|
||||||
ConfigurationPropertyName name = this.builder.from("foo.bar.baz", '.').build();
|
ConfigurationPropertyName name = this.builder.from("foo.bar.baz", '.');
|
||||||
assertThat(name.toString()).isEqualTo(expected.toString());
|
assertThat(name.toString()).isEqualTo(expected.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildShouldValidateUsingPattern() {
|
public void buildShouldValidateProcessor() {
|
||||||
Pattern pattern = Pattern.compile("[a-z]([a-z0-9\\-])*");
|
this.builder = new ConfigurationPropertyNameBuilder(
|
||||||
this.builder = new ConfigurationPropertyNameBuilder(pattern);
|
ElementValueProcessor.identity().withValidName());
|
||||||
this.thrown.expect(IllegalArgumentException.class);
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
this.thrown.expectMessage("Element value 'foo@!' is not valid");
|
this.thrown.expectMessage("Element value 'foo@!' is not valid");
|
||||||
this.builder.from("foo@!.bar", '.').build();
|
this.builder.from("foo@!.bar", '.');
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void buildWhenHasNoElementsShouldThrowException() throws Exception {
|
|
||||||
this.builder = new ConfigurationPropertyNameBuilder();
|
|
||||||
this.thrown.expect(IllegalStateException.class);
|
|
||||||
this.thrown.expectMessage("At least one element must be defined");
|
|
||||||
this.builder.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildShouldUseElementProcessor() throws Exception {
|
public void buildShouldUseElementProcessor() throws Exception {
|
||||||
this.builder = new ConfigurationPropertyNameBuilder(
|
this.builder = new ConfigurationPropertyNameBuilder(
|
||||||
value -> value.replace("-", ""));
|
value -> value.replace("-", ""));
|
||||||
ConfigurationPropertyName name = this.builder.from("FOO_THE-BAR", '_').build();
|
ConfigurationPropertyName name = this.builder.from("FOO_THE-BAR", '_');
|
||||||
assertThat(name.toString()).isEqualTo("foo.thebar");
|
assertThat(name.toString()).isEqualTo("foo.thebar");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fromNameShouldSetElements() throws Exception {
|
public void fromNameShouldSetElements() throws Exception {
|
||||||
this.builder = new ConfigurationPropertyNameBuilder();
|
this.builder = new ConfigurationPropertyNameBuilder();
|
||||||
ConfigurationPropertyName name = this.builder.from("foo.bar", '.').build();
|
ConfigurationPropertyName name = this.builder.from("foo.bar", '.');
|
||||||
assertThat(name.toString()).isEqualTo("foo.bar");
|
assertThat(name.toString()).isEqualTo("foo.bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,19 +93,11 @@ public class ConfigurationPropertyNameBuilderTests {
|
||||||
.isEqualTo(elements("foo", "[bar]", "baz"));
|
.isEqualTo(elements("foo", "[bar]", "baz"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void fromNameWhenHasExistingShouldSetNewElements() throws Exception {
|
|
||||||
this.thrown.expect(IllegalStateException.class);
|
|
||||||
this.thrown.expectMessage("Existing elements must not be present");
|
|
||||||
new ConfigurationPropertyNameBuilder().from("foo.bar", '.').from("baz", '.')
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void appendShouldAppendElement() throws Exception {
|
public void appendShouldAppendElement() throws Exception {
|
||||||
this.builder = new ConfigurationPropertyNameBuilder();
|
this.builder = new ConfigurationPropertyNameBuilder();
|
||||||
ConfigurationPropertyName name = this.builder.from("foo.bar", '.').append("baz")
|
ConfigurationPropertyName parent = this.builder.from("foo.bar", '.');
|
||||||
.build();
|
ConfigurationPropertyName name = this.builder.from(parent, "baz");
|
||||||
assertThat(name.toString()).isEqualTo("foo.bar.baz");
|
assertThat(name.toString()).isEqualTo("foo.bar.baz");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,10 +105,12 @@ public class ConfigurationPropertyNameBuilderTests {
|
||||||
return Arrays.stream(elements).map(Element::new).collect(Collectors.toList());
|
return Arrays.stream(elements).map(Element::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private List<Element> getElements(String name) {
|
private List<Element> getElements(String name) {
|
||||||
ConfigurationPropertyNameBuilder builder = this.builder.from(name, '.');
|
List<Element> elements = new ArrayList<>();
|
||||||
return (List<Element>) ReflectionTestUtils.getField(builder, "elements");
|
for (Element element : this.builder.from(name, '.')) {
|
||||||
|
elements.add(element);
|
||||||
|
}
|
||||||
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue