Add protected YamlProcessor.getFlattenedMap method
Add a protected getFlattenedMap method to the YamlProcessor that subclasses can use to flatten a source Map so that it has the same entries as the Properties, but retains order. Issue: SPR-12499
This commit is contained in:
parent
83ecf5ca1d
commit
87f1512e88
|
@ -212,7 +212,7 @@ public abstract class YamlProcessor {
|
||||||
|
|
||||||
private boolean process(Map<String, Object> map, MatchCallback callback) {
|
private boolean process(Map<String, Object> map, MatchCallback callback) {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
assignProperties(properties, map, null);
|
properties.putAll(getFlattenedMap(map));
|
||||||
|
|
||||||
if (this.documentMatchers.isEmpty()) {
|
if (this.documentMatchers.isEmpty()) {
|
||||||
if (this.logger.isDebugEnabled()) {
|
if (this.logger.isDebugEnabled()) {
|
||||||
|
@ -247,8 +247,23 @@ public abstract class YamlProcessor {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assignProperties(Properties properties, Map<String, Object> input, String path) {
|
/**
|
||||||
for (Entry<String, Object> entry : input.entrySet()) {
|
* Return a flattened version of the given map, recursively following any nested Map
|
||||||
|
* or Collection values. Entries from the resulting map retain the same order as the
|
||||||
|
* source. When called with the Map from a {@link MatchCallback} the result will
|
||||||
|
* contain the same values as the {@link MatchCallback} Properties.
|
||||||
|
* @param source the source map
|
||||||
|
* @return a flattened map
|
||||||
|
* @since 4.2.3
|
||||||
|
*/
|
||||||
|
protected final Map<String, Object> getFlattenedMap(Map<String, Object> source) {
|
||||||
|
Map<String, Object> result = new LinkedHashMap<String, Object>();
|
||||||
|
buildFlattenedMap(result, source, null);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, String path) {
|
||||||
|
for (Entry<String, Object> entry : source.entrySet()) {
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
if (StringUtils.hasText(path)) {
|
if (StringUtils.hasText(path)) {
|
||||||
if (key.startsWith("[")) {
|
if (key.startsWith("[")) {
|
||||||
|
@ -260,13 +275,13 @@ public abstract class YamlProcessor {
|
||||||
}
|
}
|
||||||
Object value = entry.getValue();
|
Object value = entry.getValue();
|
||||||
if (value instanceof String) {
|
if (value instanceof String) {
|
||||||
properties.put(key, value);
|
result.put(key, value);
|
||||||
}
|
}
|
||||||
else if (value instanceof Map) {
|
else if (value instanceof Map) {
|
||||||
// Need a compound key
|
// Need a compound key
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, Object> map = (Map<String, Object>) value;
|
Map<String, Object> map = (Map<String, Object>) value;
|
||||||
assignProperties(properties, map, key);
|
buildFlattenedMap(result, map, key);
|
||||||
}
|
}
|
||||||
else if (value instanceof Collection) {
|
else if (value instanceof Collection) {
|
||||||
// Need a compound key
|
// Need a compound key
|
||||||
|
@ -274,12 +289,12 @@ public abstract class YamlProcessor {
|
||||||
Collection<Object> collection = (Collection<Object>) value;
|
Collection<Object> collection = (Collection<Object>) value;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Object object : collection) {
|
for (Object object : collection) {
|
||||||
assignProperties(properties,
|
buildFlattenedMap(result,
|
||||||
Collections.singletonMap("[" + (count++) + "]", object), key);
|
Collections.singletonMap("[" + (count++) + "]", object), key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
properties.put(key, value == null ? "" : value);
|
result.put(key, value == null ? "" : value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.beans.factory.config;
|
package org.springframework.beans.factory.config;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@ -23,7 +24,6 @@ import org.junit.Test;
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
import org.yaml.snakeyaml.parser.ParserException;
|
import org.yaml.snakeyaml.parser.ParserException;
|
||||||
import org.yaml.snakeyaml.scanner.ScannerException;
|
import org.yaml.snakeyaml.scanner.ScannerException;
|
||||||
|
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
@ -135,4 +135,24 @@ public class YamlProcessorTests {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void flattenedMapIsSameAsPropertiesButOrdered() {
|
||||||
|
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) {
|
||||||
|
assertEquals("bucket", properties.get("bar.spam"));
|
||||||
|
assertEquals(2, properties.size());
|
||||||
|
Map<String, Object> flattenedMap = processor.getFlattenedMap(map);
|
||||||
|
assertEquals("bucket", flattenedMap.get("bar.spam"));
|
||||||
|
assertEquals(2, flattenedMap.size());
|
||||||
|
assertTrue(flattenedMap instanceof LinkedHashMap);
|
||||||
|
Map<String, Object> bar = (Map<String, Object>) map.get("bar");
|
||||||
|
assertEquals("bucket", bar.get("spam"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue