Support consistent ordering of string adapting properties

This commit introduces support for consistent ordering of Properties
created by CollectionFactory.createStringAdaptingProperties().

Specifically, the created Properties instance sorts properties
alphanumerically based on their keys.

Closes gh-23081
This commit is contained in:
Sam Brannen 2019-06-04 14:47:43 +03:00
parent 3a8388ec8d
commit 410f204168
2 changed files with 28 additions and 9 deletions

View File

@ -17,6 +17,7 @@
package org.springframework.beans.factory.config;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
@ -25,6 +26,7 @@ import org.yaml.snakeyaml.scanner.ScannerException;
import org.springframework.core.io.ByteArrayResource;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -33,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
*
* @author Dave Syer
* @author Juergen Hoeller
* @author Sam Brannen
*/
public class YamlProcessorTests {
@ -107,17 +110,27 @@ 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("cat: dog\nfoo: bar\nbar:\n spam: bucket".getBytes()));
this.processor.process((properties, map) -> {
assertThat(properties.get("bar.spam")).isEqualTo("bucket");
assertThat(properties).hasSize(2);
Map<String, Object> flattenedMap = processor.getFlattenedMap(map);
assertThat(flattenedMap).isInstanceOf(LinkedHashMap.class);
assertThat(properties).hasSize(3);
assertThat(flattenedMap).hasSize(3);
assertThat(properties.get("bar.spam")).isEqualTo("bucket");
assertThat(flattenedMap.get("bar.spam")).isEqualTo("bucket");
assertThat(flattenedMap.size()).isEqualTo(2);
boolean condition = flattenedMap instanceof LinkedHashMap;
assertThat(condition).isTrue();
Map<String, Object> bar = (Map<String, Object>) map.get("bar");
assertThat(bar.get("spam")).isEqualTo("bucket");
List<Object> keysFromProperties = properties.keySet().stream().collect(toList());
List<Object> keysFromFlattenedMap = flattenedMap.keySet().stream().collect(toList());
assertThat(keysFromProperties).containsExactlyInAnyOrderElementsOf(keysFromFlattenedMap);
// Keys in the Properties object are sorted.
assertThat(keysFromProperties).containsExactly("bar.spam", "cat", "foo");
// But the flattened map retains the order from the input.
assertThat(keysFromFlattenedMap).containsExactly("cat", "foo", "bar.spam");
});
}

View File

@ -329,14 +329,18 @@ public final class CollectionFactory {
}
/**
* Create a variant of {@code java.util.Properties} that automatically adapts
* non-String values to String representations on {@link Properties#getProperty}.
* Create a variant of {@link java.util.Properties} that automatically adapts
* non-String values to String representations in {@link Properties#getProperty}.
* <p>In addition, the returned {@code Properties} instance sorts properties
* alphanumerically based on their keys.
* @return a new {@code Properties} instance
* @since 4.3.4
* @see #createSortedProperties(boolean)
* @see #createSortedProperties(Properties, boolean)
*/
@SuppressWarnings("serial")
public static Properties createStringAdaptingProperties() {
return new Properties() {
return new SortedProperties(false) {
@Override
@Nullable
public String getProperty(String key) {
@ -359,6 +363,7 @@ public final class CollectionFactory {
* storing properties in a file
* @return a new {@code Properties} instance
* @since 5.2
* @see #createStringAdaptingProperties()
* @see #createSortedProperties(Properties, boolean)
*/
public static Properties createSortedProperties(boolean omitComments) {
@ -384,6 +389,7 @@ public final class CollectionFactory {
* storing properties in a file
* @return a new {@code Properties} instance
* @since 5.2
* @see #createStringAdaptingProperties()
* @see #createSortedProperties(boolean)
*/
public static Properties createSortedProperties(Properties properties, boolean omitComments) {