From 0a6eb139c40c310a4e979d2687128a8d8aaa0886 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Sat, 26 Jun 2010 21:10:20 +0000 Subject: [PATCH] [SPR-7323] SpEL 'select last' operator now works consistently with maps. git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@3461 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../expression/spel/ast/Selection.java | 3 +- .../spel/SelectionAndProjectionTests.java | 71 ++++++++++++++++--- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Selection.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Selection.java index 0698720ff1a..657d8ab0ceb 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Selection.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Selection.java @@ -42,6 +42,7 @@ import org.springframework.util.ObjectUtils; * * @author Andy Clement * @author Mark Fisher + * @author Sam Brannen * @since 3.0 */ public class Selection extends SpelNodeImpl { @@ -73,7 +74,6 @@ public class Selection extends SpelNodeImpl { Object lastKey = null; for (Map.Entry entry : mapdata.entrySet()) { try { - lastKey = entry.getKey(); TypedValue kvpair = new TypedValue(entry,TypeDescriptor.valueOf(Map.Entry.class)); state.pushActiveContextObject(kvpair); Object o = selectionCriteria.getValueInternal(state).getValue(); @@ -84,6 +84,7 @@ public class Selection extends SpelNodeImpl { return new TypedValue(result); } result.put(entry.getKey(),entry.getValue()); + lastKey = entry.getKey(); } } else { throw new SpelEvaluationException(selectionCriteria.getStartPosition(), diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SelectionAndProjectionTests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SelectionAndProjectionTests.java index b101ab8c92f..8acf52b8151 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SelectionAndProjectionTests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SelectionAndProjectionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 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. @@ -21,17 +21,21 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.TreeMap; import org.junit.Test; - import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; /** * @author Mark Fisher + * @author Sam Brannen + * * @since 3.0 */ public class SelectionAndProjectionTests { @@ -139,6 +143,44 @@ public class SelectionAndProjectionTests { assertEquals(4, value); } + @Test + @SuppressWarnings("unchecked") + public void selectionWithMap() { + EvaluationContext context = new StandardEvaluationContext(new MapTestBean()); + ExpressionParser parser = new SpelExpressionParser(); + Expression exp = parser.parseExpression("colors.?[key.startsWith('b')]"); + + Map colorsMap = (Map) exp.getValue(context); + assertEquals(3, colorsMap.size()); + assertTrue(colorsMap.containsKey("beige")); + assertTrue(colorsMap.containsKey("blue")); + assertTrue(colorsMap.containsKey("brown")); + } + + @Test + @SuppressWarnings("unchecked") + public void selectFirstItemInMap() { + EvaluationContext context = new StandardEvaluationContext(new MapTestBean()); + ExpressionParser parser = new SpelExpressionParser(); + + Expression exp = parser.parseExpression("colors.^[key.startsWith('b')]"); + Map colorsMap = (Map) exp.getValue(context); + assertEquals(1, colorsMap.size()); + assertEquals("beige", colorsMap.keySet().iterator().next()); + } + + @Test + @SuppressWarnings("unchecked") + public void selectLastItemInMap() { + EvaluationContext context = new StandardEvaluationContext(new MapTestBean()); + ExpressionParser parser = new SpelExpressionParser(); + + Expression exp = parser.parseExpression("colors.$[key.startsWith('b')]"); + Map colorsMap = (Map) exp.getValue(context); + assertEquals(1, colorsMap.size()); + assertEquals("brown", colorsMap.keySet().iterator().next()); + } + @Test public void projectionWithList() throws Exception { Expression expression = new SpelExpressionParser().parseRaw("#testList.![wrapper.value]"); @@ -169,6 +211,23 @@ public class SelectionAndProjectionTests { assertEquals(new Integer(7), array[2]); } + static class MapTestBean { + + private final Map colors = new TreeMap(); + + MapTestBean() { + // colors.put("black", "schwarz"); + colors.put("red", "rot"); + colors.put("brown", "braun"); + colors.put("blue", "blau"); + colors.put("yellow", "gelb"); + colors.put("beige", "beige"); + } + + public Map getColors() { + return colors; + } + } static class ListTestBean { @@ -185,9 +244,8 @@ public class SelectionAndProjectionTests { } } - static class ArrayTestBean { - + private final int[] ints = new int[10]; private final Integer[] integers = new Integer[10]; @@ -208,7 +266,6 @@ public class SelectionAndProjectionTests { } } - static class IntegerTestBean { private final IntegerWrapper wrapper; @@ -234,8 +291,7 @@ public class SelectionAndProjectionTests { for (int i = 0; i < 3; i++) { if (i == 1) { array[i] = new IntegerTestBean(5.9f); - } - else { + } else { array[i] = new IntegerTestBean(i + 5); } } @@ -243,7 +299,6 @@ public class SelectionAndProjectionTests { } } - static class IntegerWrapper { private final Number value;