From 53993f836b48346c796f067a8fae1a177a4c6247 Mon Sep 17 00:00:00 2001 From: Neil Gabbadon Date: Thu, 3 Jul 2014 16:58:24 -0400 Subject: [PATCH] Changed collection parser to used LinkedHashMap and LinkedList to maintain order of keys when expressing maps and lists inline. --- .../org/mvel2/ast/InlineCollectionNode.java | 8 ++-- .../java/org/mvel2/util/CollectionParser.java | 13 +++---- .../tests/core/InlineCollectionsTests.java | 38 +++++++++++++++++++ 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/mvel2/ast/InlineCollectionNode.java b/src/main/java/org/mvel2/ast/InlineCollectionNode.java index f2b0b9c5..4aa7f86d 100644 --- a/src/main/java/org/mvel2/ast/InlineCollectionNode.java +++ b/src/main/java/org/mvel2/ast/InlineCollectionNode.java @@ -28,8 +28,8 @@ import org.mvel2.util.CollectionParser; import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -123,7 +123,7 @@ private void parseGraph(boolean compile, Class type, ParserContext pCtx) { private Object execGraph(Object o, Class type, Object ctx, VariableResolverFactory factory) { if (o instanceof List) { - ArrayList list = new ArrayList(((List) o).size()); + LinkedList list = new LinkedList(); for (Object item : (List) o) { list.add(execGraph(item, type, ctx, factory)); @@ -132,7 +132,7 @@ private Object execGraph(Object o, Class type, Object ctx, VariableResolverFacto return list; } else if (o instanceof Map) { - HashMap map = new HashMap(); + LinkedHashMap map = new LinkedHashMap(); for (Object item : ((Map) o).keySet()) { map.put(execGraph(item, type, ctx, factory), execGraph(((Map) o).get(item), type, ctx, factory)); diff --git a/src/main/java/org/mvel2/util/CollectionParser.java b/src/main/java/org/mvel2/util/CollectionParser.java index 6e973501..173008ff 100644 --- a/src/main/java/org/mvel2/util/CollectionParser.java +++ b/src/main/java/org/mvel2/util/CollectionParser.java @@ -23,10 +23,7 @@ import org.mvel2.ParserContext; import org.mvel2.compiler.ExecutableStatement; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static org.mvel2.util.ParseTools.*; @@ -94,7 +91,7 @@ public Object parseCollection(char[] property, int start, int offset, boolean su private Object parseCollection(boolean subcompile) { if (end - start == 0) { - if (type == LIST) return new ArrayList(); + if (type == LIST) return new LinkedList(); else return EMPTY_ARRAY; } @@ -107,10 +104,10 @@ private Object parseCollection(boolean subcompile) { switch (type) { case ARRAY: case LIST: - list = new ArrayList(); + list = new LinkedList(); break; case MAP: - map = new HashMap(); + map = new LinkedHashMap(); break; } } @@ -188,7 +185,7 @@ else if (cursor < end) { case ':': if (type != MAP) { - map = new HashMap(); + map = new LinkedHashMap(); type = MAP; } curr = createStringTrimmed(property, st, cursor - st); diff --git a/src/test/java/org/mvel2/tests/core/InlineCollectionsTests.java b/src/test/java/org/mvel2/tests/core/InlineCollectionsTests.java index 6e8968f4..884b28ae 100644 --- a/src/test/java/org/mvel2/tests/core/InlineCollectionsTests.java +++ b/src/test/java/org/mvel2/tests/core/InlineCollectionsTests.java @@ -13,6 +13,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.LinkedHashSet; public class InlineCollectionsTests extends AbstractTest { public void testListCreation2() { @@ -360,4 +362,40 @@ public void testElementToList() { } + public void testInlineCollectionOrderOfKeys() { + + Set keys = new LinkedHashSet(); + keys.add("a"); + keys.add("b"); + keys.add("c"); + keys.add("d"); + keys.add("e"); + + String mvelSource = "[ 'a' : 1, 'b' : 2, 'c' : 3, 'd' : 4, 'e' : 5 ]"; + Map eval = (Map) MVEL.eval(mvelSource); + + assertTrue(hasSameOrder(keys, eval.keySet())); + } + + private Boolean hasSameOrder(Set a, Set b) { + + // Check if they have same values + if (!a.equals(b)) { + return false; + } + + String[] aArray = a.toArray(new String[a.size()]); + String[] bArray = b.toArray(new String[b.size()]); + + // Check keys to make sure order is the same + for (int i=0; i < aArray.length; i ++) { + if (!aArray[i].equals(bArray[i])) { + return false; + } + } + + return true; + } + + }