YamlPropertiesFactoryBean consistently exposes String values
Issue: SPR-14737
This commit is contained in:
parent
e188b4428e
commit
74c618892e
|
@ -19,18 +19,21 @@ package org.springframework.beans.factory.config;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Factory for a Map that reads from a YAML source. YAML is a nice human-readable
|
||||
* format for configuration, and it has some useful hierarchical properties. It's
|
||||
* more or less a superset of JSON, so it has a lot of similar features. If
|
||||
* multiple resources are provided the later ones will override entries in the
|
||||
* earlier ones hierarchically - that is all entries with the same nested key of
|
||||
* type Map at any depth are merged. For example:
|
||||
* Factory for a {@code Map} that reads from a YAML source, preserving the
|
||||
* YAML-declared value types and their structure.
|
||||
*
|
||||
* <p>YAML is a nice human-readable format for configuration, and it has some
|
||||
* useful hierarchical properties. It's more or less a superset of JSON, so it
|
||||
* has a lot of similar features.
|
||||
*
|
||||
* <p>If multiple resources are provided the later ones will override entries in
|
||||
* the earlier ones hierarchically; that is, all entries with the same nested key
|
||||
* of type {@code Map} at any depth are merged. For example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* foo:
|
||||
|
@ -62,6 +65,7 @@ import org.springframework.beans.factory.InitializingBean;
|
|||
* with the value in the second, but its nested values are merged.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map<String, Object>>, InitializingBean {
|
||||
|
@ -112,13 +116,9 @@ public class YamlMapFactoryBean extends YamlProcessor implements FactoryBean<Map
|
|||
* @see #process(java.util.Map, MatchCallback)
|
||||
*/
|
||||
protected Map<String, Object> createMap() {
|
||||
final Map<String, Object> result = new LinkedHashMap<>();
|
||||
process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
merge(result, map);
|
||||
}
|
||||
});
|
||||
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
process((properties, map) -> merge(result, map));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.yaml.snakeyaml.nodes.MappingNode;
|
|||
import org.yaml.snakeyaml.parser.ParserException;
|
||||
import org.yaml.snakeyaml.reader.UnicodeReader;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
@ -45,6 +46,7 @@ import org.springframework.util.StringUtils;
|
|||
* Base class for YAML factories.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
public abstract class YamlProcessor {
|
||||
|
@ -217,7 +219,7 @@ public abstract class YamlProcessor {
|
|||
}
|
||||
|
||||
private boolean process(Map<String, Object> map, MatchCallback callback) {
|
||||
Properties properties = new Properties();
|
||||
Properties properties = CollectionFactory.createStringAdaptingProperties();
|
||||
properties.putAll(getFlattenedMap(map));
|
||||
|
||||
if (this.documentMatchers.isEmpty()) {
|
||||
|
@ -302,21 +304,23 @@ public abstract class YamlProcessor {
|
|||
}
|
||||
}
|
||||
else {
|
||||
result.put(key, value != null ? value : "");
|
||||
result.put(key, (value != null ? value : ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback interface used to process properties in a resulting map.
|
||||
* Callback interface used to process the YAML parsing results.
|
||||
*/
|
||||
public interface MatchCallback {
|
||||
|
||||
/**
|
||||
* Process the properties.
|
||||
* @param properties the properties to process
|
||||
* @param map a mutable result map
|
||||
* Process the given representation of the parsing results.
|
||||
* @param properties the properties to process (as a flattened
|
||||
* representation with indexed keys in case of a collection or map)
|
||||
* @param map the result map (preserving the original value structure
|
||||
* in the YAML document)
|
||||
*/
|
||||
void process(Properties properties, Map<String, Object> map);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -16,18 +16,27 @@
|
|||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
|
||||
/**
|
||||
* Factory for Java Properties that reads from a YAML source. YAML is a nice
|
||||
* human-readable format for configuration, and it has some useful hierarchical
|
||||
* properties. It's more or less a superset of JSON, so it has a lot of similar
|
||||
* features. The Properties created by this factory have nested paths for
|
||||
* hierarchical objects, so for instance this YAML
|
||||
* Factory for {@link java.util.Properties} that reads from a YAML source,
|
||||
* exposing a flat structure of String property values.
|
||||
*
|
||||
* <p>YAML is a nice human-readable format for configuration, and it has some
|
||||
* useful hierarchical properties. It's more or less a superset of JSON, so it
|
||||
* has a lot of similar features.
|
||||
*
|
||||
* <p><b>Note: All exposed values are of type {@code String}</b> for access through
|
||||
* the common {@link Properties#getProperty} method (e.g. in configuration property
|
||||
* resolution through {@link PropertyResourceConfigurer#setProperties(Properties)}).
|
||||
* If this is not desirable, use {@link YamlMapFactoryBean} instead.
|
||||
*
|
||||
* <p>The Properties created by this factory have nested paths for hierarchical
|
||||
* objects, so for instance this YAML
|
||||
*
|
||||
* <pre class="code">
|
||||
* environments:
|
||||
|
@ -39,7 +48,7 @@ import org.springframework.beans.factory.InitializingBean;
|
|||
* name: My Cool App
|
||||
* </pre>
|
||||
*
|
||||
* is transformed into these Properties:
|
||||
* is transformed into these properties:
|
||||
*
|
||||
* <pre class="code">
|
||||
* environments.dev.url=http://dev.bar.com
|
||||
|
@ -57,7 +66,7 @@ import org.springframework.beans.factory.InitializingBean;
|
|||
* - foo.bar.com
|
||||
* </pre>
|
||||
*
|
||||
* becomes Java Properties like this:
|
||||
* becomes properties like this:
|
||||
*
|
||||
* <pre class="code">
|
||||
* servers[0]=dev.bar.com
|
||||
|
@ -66,6 +75,7 @@ import org.springframework.beans.factory.InitializingBean;
|
|||
*
|
||||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.1
|
||||
*/
|
||||
public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryBean<Properties>, InitializingBean {
|
||||
|
@ -116,13 +126,8 @@ public class YamlPropertiesFactoryBean extends YamlProcessor implements FactoryB
|
|||
* @see #process(MatchCallback) ()
|
||||
*/
|
||||
protected Properties createProperties() {
|
||||
final Properties result = new Properties();
|
||||
process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
result.putAll(properties);
|
||||
}
|
||||
});
|
||||
Properties result = CollectionFactory.createStringAdaptingProperties();
|
||||
process((properties, map) -> result.putAll(properties));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -34,43 +34,40 @@ import static org.junit.Assert.*;
|
|||
* Tests for {@link YamlMapFactoryBean}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class YamlMapFactoryBeanTests {
|
||||
|
||||
private final YamlMapFactoryBean factory = new YamlMapFactoryBean();
|
||||
|
||||
|
||||
@Test
|
||||
public void testSetIgnoreResourceNotFound() throws Exception {
|
||||
this.factory
|
||||
.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
|
||||
this.factory.setResources(new FileSystemResource[] {new FileSystemResource(
|
||||
"non-exsitent-file.yml")});
|
||||
this.factory.setResolutionMethod(YamlMapFactoryBean.ResolutionMethod.OVERRIDE_AND_IGNORE);
|
||||
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
|
||||
assertEquals(0, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testSetBarfOnResourceNotFound() throws Exception {
|
||||
this.factory.setResources(new FileSystemResource[] {new FileSystemResource(
|
||||
"non-exsitent-file.yml")});
|
||||
this.factory.setResources(new FileSystemResource("non-exsitent-file.yml"));
|
||||
assertEquals(0, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetObject() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource[] {new ByteArrayResource(
|
||||
"foo: bar".getBytes())});
|
||||
this.factory.setResources(new ByteArrayResource("foo: bar".getBytes()));
|
||||
assertEquals(1, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testOverrideAndremoveDefaults() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource[] {
|
||||
new ByteArrayResource("foo:\n bar: spam".getBytes()),
|
||||
new ByteArrayResource("foo:\n spam: bar".getBytes())});
|
||||
public void testOverrideAndRemoveDefaults() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource("foo:\n bar: spam".getBytes()),
|
||||
new ByteArrayResource("foo:\n spam: bar".getBytes()));
|
||||
|
||||
assertEquals(1, this.factory.getObject().size());
|
||||
assertEquals(2,
|
||||
((Map<String, Object>) this.factory.getObject().get("foo")).size());
|
||||
assertEquals(2, ((Map<String, Object>) this.factory.getObject().get("foo")).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -81,20 +78,20 @@ public class YamlMapFactoryBeanTests {
|
|||
public String getDescription() {
|
||||
return "non-existent";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
throw new IOException("planned");
|
||||
}
|
||||
}, new ByteArrayResource("foo:\n spam: bar".getBytes()));
|
||||
|
||||
assertEquals(1, this.factory.getObject().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapWithPeriodsInKey() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource[] {new ByteArrayResource(
|
||||
"foo:\n ? key1.key2\n : value".getBytes())});
|
||||
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : value".getBytes()));
|
||||
Map<String, Object> map = this.factory.getObject();
|
||||
|
||||
assertEquals(1, map.size());
|
||||
assertTrue(map.containsKey("foo"));
|
||||
Object object = map.get("foo");
|
||||
|
@ -105,10 +102,24 @@ public class YamlMapFactoryBeanTests {
|
|||
assertEquals("value", sub.get("key1.key2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapWithIntegerValue() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource("foo:\n ? key1.key2\n : 3".getBytes()));
|
||||
Map<String, Object> map = this.factory.getObject();
|
||||
|
||||
assertEquals(1, map.size());
|
||||
assertTrue(map.containsKey("foo"));
|
||||
Object object = map.get("foo");
|
||||
assertTrue(object instanceof LinkedHashMap);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> sub = (Map<String, Object>) object;
|
||||
assertTrue(sub.containsKey("key1.key2"));
|
||||
assertEquals(Integer.valueOf(3), sub.get("key1.key2"));
|
||||
}
|
||||
|
||||
@Test(expected = ParserException.class)
|
||||
public void testDuplicateKey() throws Exception {
|
||||
this.factory.setResources(new ByteArrayResource[] {new ByteArrayResource(
|
||||
"mymap:\n foo: bar\nmymap:\n bar: foo".getBytes())});
|
||||
this.factory.setResources(new ByteArrayResource("mymap:\n foo: bar\nmymap:\n bar: foo".getBytes()));
|
||||
this.factory.getObject().get("mymap");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -13,6 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.factory.config;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
@ -24,6 +25,7 @@ import org.junit.Test;
|
|||
import org.junit.rules.ExpectedException;
|
||||
import org.yaml.snakeyaml.parser.ParserException;
|
||||
import org.yaml.snakeyaml.scanner.ScannerException;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
@ -33,34 +35,38 @@ import static org.springframework.beans.factory.config.YamlProcessor.*;
|
|||
* Tests for {@link YamlProcessor}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class YamlProcessorTests {
|
||||
|
||||
private final YamlProcessor processor = new YamlProcessor() {
|
||||
};
|
||||
private final YamlProcessor processor = new YamlProcessor() {};
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
|
||||
@Test
|
||||
public void arrayConvertedToIndexedBeanReference() {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo: bar\nbar: [1,2,3]".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar: [1,2,3]".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals(1, properties.get("bar[0]"));
|
||||
assertEquals(2, properties.get("bar[1]"));
|
||||
assertEquals(3, properties.get("bar[2]"));
|
||||
assertEquals(4, properties.size());
|
||||
assertEquals("bar", properties.get("foo"));
|
||||
assertEquals("bar", properties.getProperty("foo"));
|
||||
assertEquals(1, properties.get("bar[0]"));
|
||||
assertEquals("1", properties.getProperty("bar[0]"));
|
||||
assertEquals(2, properties.get("bar[1]"));
|
||||
assertEquals("2", properties.getProperty("bar[1]"));
|
||||
assertEquals(3, properties.get("bar[2]"));
|
||||
assertEquals("3", properties.getProperty("bar[2]"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringResource() throws Exception {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo # a document that is a literal".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo # a document that is a literal".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
|
@ -71,8 +77,7 @@ public class YamlProcessorTests {
|
|||
|
||||
@Test
|
||||
public void testBadDocumentStart() throws Exception {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo # a document\nbar: baz".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo # a document\nbar: baz".getBytes()));
|
||||
this.exception.expect(ParserException.class);
|
||||
this.exception.expectMessage("line 2, column 1");
|
||||
this.processor.process(new MatchCallback() {
|
||||
|
@ -84,8 +89,7 @@ public class YamlProcessorTests {
|
|||
|
||||
@Test
|
||||
public void testBadResource() throws Exception {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo: bar\ncd\nspam:\n foo: baz".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\ncd\nspam:\n foo: baz".getBytes()));
|
||||
this.exception.expect(ScannerException.class);
|
||||
this.exception.expectMessage("line 3, column 1");
|
||||
this.processor.process(new MatchCallback() {
|
||||
|
@ -97,8 +101,7 @@ public class YamlProcessorTests {
|
|||
|
||||
@Test
|
||||
public void mapConvertedToIndexedBeanReference() {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
|
@ -111,8 +114,7 @@ public class YamlProcessorTests {
|
|||
|
||||
@Test
|
||||
public void integerKeyBehaves() {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo: bar\n1: bar".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\n1: bar".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
|
@ -124,10 +126,8 @@ public class YamlProcessorTests {
|
|||
|
||||
@Test
|
||||
public void integerDeepKeyBehaves() {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo:\n 1: bar".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo:\n 1: bar".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
assertEquals("bar", properties.get("foo[1]"));
|
||||
|
@ -139,8 +139,7 @@ public class YamlProcessorTests {
|
|||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void flattenedMapIsSameAsPropertiesButOrdered() {
|
||||
this.processor.setResources(new ByteArrayResource(
|
||||
"foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
this.processor.setResources(new ByteArrayResource("foo: bar\nbar:\n spam: bucket".getBytes()));
|
||||
this.processor.process(new MatchCallback() {
|
||||
@Override
|
||||
public void process(Properties properties, Map<String, Object> map) {
|
||||
|
@ -155,4 +154,5 @@ public class YamlProcessorTests {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
@ -38,12 +38,14 @@ import static org.springframework.beans.factory.config.YamlProcessor.*;
|
|||
* Tests for {@link YamlPropertiesFactoryBean}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class YamlPropertiesFactoryBeanTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
|
||||
@Test
|
||||
public void testLoadResource() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
|
@ -113,8 +115,8 @@ public class YamlPropertiesFactoryBeanTests {
|
|||
factory.setDocumentMatchers(new DocumentMatcher() {
|
||||
@Override
|
||||
public MatchStatus matches(Properties properties) {
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
|
@ -134,8 +136,8 @@ public class YamlPropertiesFactoryBeanTests {
|
|||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
|
@ -156,8 +158,8 @@ public class YamlPropertiesFactoryBeanTests {
|
|||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
|
@ -178,8 +180,8 @@ public class YamlPropertiesFactoryBeanTests {
|
|||
if (!properties.containsKey("foo")) {
|
||||
return MatchStatus.ABSTAIN;
|
||||
}
|
||||
return "bag".equals(properties.getProperty("foo")) ? MatchStatus.FOUND
|
||||
: MatchStatus.NOT_FOUND;
|
||||
return ("bag".equals(properties.getProperty("foo")) ?
|
||||
MatchStatus.FOUND : MatchStatus.NOT_FOUND);
|
||||
}
|
||||
});
|
||||
Properties properties = factory.getObject();
|
||||
|
@ -200,8 +202,7 @@ public class YamlPropertiesFactoryBeanTests {
|
|||
@Test
|
||||
public void testLoadNull() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource("foo: bar\nspam:"
|
||||
.getBytes()));
|
||||
factory.setResources(new ByteArrayResource("foo: bar\nspam:".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo"), equalTo("bar"));
|
||||
assertThat(properties.getProperty("spam"), equalTo(""));
|
||||
|
@ -210,20 +211,28 @@ public class YamlPropertiesFactoryBeanTests {
|
|||
@Test
|
||||
public void testLoadArrayOfString() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource("foo:\n- bar\n- baz"
|
||||
.getBytes()));
|
||||
factory.setResources(new ByteArrayResource("foo:\n- bar\n- baz".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo[0]"), equalTo("bar"));
|
||||
assertThat(properties.getProperty("foo[1]"), equalTo("baz"));
|
||||
assertThat(properties.get("foo"), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadArrayOfInteger() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource("foo:\n- 1\n- 2".getBytes()));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo[0]"), equalTo("1"));
|
||||
assertThat(properties.getProperty("foo[1]"), equalTo("2"));
|
||||
assertThat(properties.get("foo"), is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadArrayOfObject() throws Exception {
|
||||
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
|
||||
factory.setResources(new ByteArrayResource(
|
||||
"foo:\n- bar:\n spam: crap\n- baz\n- one: two\n three: four"
|
||||
.getBytes()
|
||||
"foo:\n- bar:\n spam: crap\n- baz\n- one: two\n three: four".getBytes()
|
||||
));
|
||||
Properties properties = factory.getObject();
|
||||
assertThat(properties.getProperty("foo[0].bar.spam"), equalTo("crap"));
|
||||
|
@ -239,8 +248,7 @@ public class YamlPropertiesFactoryBeanTests {
|
|||
Yaml yaml = new Yaml();
|
||||
Map<String, ?> map = yaml.loadAs("foo: bar\nspam:\n foo: baz", Map.class);
|
||||
assertThat(map.get("foo"), equalTo((Object) "bar"));
|
||||
assertThat(((Map<String, Object>) map.get("spam")).get("foo"),
|
||||
equalTo((Object) "baz"));
|
||||
assertThat(((Map<String, Object>) map.get("spam")).get("foo"), equalTo((Object) "baz"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
|
@ -41,12 +42,9 @@ import org.springframework.util.MultiValueMap;
|
|||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Factory for collections that is aware of Java 5, Java 6, and Spring
|
||||
* collection types.
|
||||
* Factory for collections that is aware of Java 5, Java 6, and Spring collection types.
|
||||
*
|
||||
* <p>Mainly for internal use within the framework.
|
||||
* <p>The goal of this class is to avoid runtime dependencies on a specific
|
||||
* Java version, while nevertheless using the best collection implementation
|
||||
* that is available at runtime.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
|
@ -325,6 +323,23 @@ public abstract class CollectionFactory {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a variant of {@code java.util.Properties} that automatically adapts
|
||||
* non-String values to String representations on {@link Properties#getProperty}.
|
||||
* @return a new {@code Properties} instance
|
||||
* @since 4.3.4
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static Properties createStringAdaptingProperties() {
|
||||
return new Properties() {
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
Object value = get(key);
|
||||
return (value != null ? value.toString() : null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast the given type to a subtype of {@link Enum}.
|
||||
* @param enumType the enum type, never {@code null}
|
||||
|
|
|
@ -110,10 +110,10 @@ public abstract class CollectionUtils {
|
|||
if (props != null) {
|
||||
for (Enumeration<?> en = props.propertyNames(); en.hasMoreElements();) {
|
||||
String key = (String) en.nextElement();
|
||||
Object value = props.getProperty(key);
|
||||
Object value = props.get(key);
|
||||
if (value == null) {
|
||||
// Potentially a non-String value...
|
||||
value = props.get(key);
|
||||
// Allow for defaults fallback or potentially overridden accessor...
|
||||
value = props.getProperty(key);
|
||||
}
|
||||
map.put((K) key, (V) value);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue