diff --git a/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/AbstractMapToString.java b/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/AbstractMapToString.java index 34d8e25d2..ab6d418d9 100644 --- a/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/AbstractMapToString.java +++ b/de.gebit.integrity.dsl/src/de/gebit/integrity/parameter/conversion/conversions/java/other/AbstractMapToString.java @@ -10,6 +10,8 @@ import java.util.Hashtable; import java.util.Map; import java.util.Map.Entry; +import java.util.SortedMap; +import java.util.TreeMap; import de.gebit.integrity.comparator.MapComparisonResult; import de.gebit.integrity.parameter.conversion.Conversion; @@ -51,7 +53,7 @@ public abstract class AbstractMapToString extends Conversion { * the conversion context * @return the resulting string */ - protected FormattedString convertToFormattedString(Map aSource, ConversionContext aConversionContext) + protected FormattedString convertToFormattedString(Map aSource, ConversionContext aConversionContext) throws ConversionFailedException { String tempParentMapPath = (String) aConversionContext.getProperty(MAP_PATH_PROPERTY); @@ -66,16 +68,28 @@ protected FormattedString convertToFormattedString(Map aSource, ConversionContex } nestedObjectDepthMap.put(Thread.currentThread(), tempDepth); + // In order to provide a consistent ordering of map entries in the string, we want to sort the map by natural + // key ordering + SortedMap tempSortedSource = null; + if (aSource instanceof SortedMap) { + // Either our source map is already sorted... + tempSortedSource = (SortedMap) aSource; + } else { + // ...or we need to sort it by creating a TreeMap and filling it + tempSortedSource = new TreeMap<>(aSource); + } + try { boolean tempFirst = true; - for (Entry tempEntry : ((Map) aSource).entrySet()) { + for (Entry tempEntry : ((Map) tempSortedSource).entrySet()) { String tempCurrentMapPath = (tempParentMapPath != null ? tempParentMapPath + "." : "") + tempEntry.getKey(); aConversionContext.withProperty(MAP_PATH_PROPERTY, tempCurrentMapPath); - boolean tempCurrentPathFailed = (aConversionContext.getComparisonResult() instanceof MapComparisonResult) - && ((MapComparisonResult) aConversionContext.getComparisonResult()).getFailedPaths().contains( - tempCurrentMapPath); + boolean tempCurrentPathFailed = (aConversionContext + .getComparisonResult() instanceof MapComparisonResult) + && ((MapComparisonResult) aConversionContext.getComparisonResult()).getFailedPaths() + .contains(tempCurrentMapPath); FormattedString[] tempConvertedValues = convertValueToFormattedStringArrayRecursive( tempEntry.getValue(), aConversionContext); diff --git a/de.gebit.integrity.tests/results/integrity.basic.arbitraryParameters.arbitraryParametersWithStringIdentifiers.xml b/de.gebit.integrity.tests/results/integrity.basic.arbitraryParameters.arbitraryParametersWithStringIdentifiers.xml index b5dae5c3a..9545251e0 100644 --- a/de.gebit.integrity.tests/results/integrity.basic.arbitraryParameters.arbitraryParametersWithStringIdentifiers.xml +++ b/de.gebit.integrity.tests/results/integrity.basic.arbitraryParameters.arbitraryParametersWithStringIdentifiers.xml @@ -1,29 +1,29 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/de.gebit.integrity.tests/results/integrity.basic.beans.beanToMapTestMapInVariable.xml b/de.gebit.integrity.tests/results/integrity.basic.beans.beanToMapTestMapInVariable.xml index 00ba9cc0f..a4ea83b24 100644 --- a/de.gebit.integrity.tests/results/integrity.basic.beans.beanToMapTestMapInVariable.xml +++ b/de.gebit.integrity.tests/results/integrity.basic.beans.beanToMapTestMapInVariable.xml @@ -1,33 +1,33 @@ - - - - - - - - - - - - - - - - This should succeed as well, because it's the same as the example before, but just using a map stored in a variable - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + This should succeed as well, because it's the same as the example before, but just using a map stored in a variable + + + + + + + + + + + + + + + + +