more tests, minor fixes. some findbugs issues addressed.

This commit is contained in:
Andy Clement 2009-04-09 22:03:38 +00:00
parent a9f4eeeabf
commit 00cecd0dd0
18 changed files with 862 additions and 406 deletions

View File

@ -29,6 +29,8 @@ public class TypedValue {
private Object value;
private TypeDescriptor typeDescriptor;
public static final TypedValue NULL_TYPED_VALUE = new TypedValue(null, TypeDescriptor.NULL_TYPE_DESCRIPTOR);
/**
* Create a TypedValue for a simple object. The type descriptor is inferred

View File

@ -52,9 +52,10 @@ public class ExpressionState {
this.relatedContext = context;
createVariableScope();
}
// create an empty top level VariableScope
private void createVariableScope() {
this.variableScopes.add(new VariableScope()); // create an empty top level VariableScope
this.variableScopes.add(new VariableScope());
}
/**
@ -64,9 +65,10 @@ public class ExpressionState {
if (this.contextObjects.isEmpty()) {
TypedValue rootObject = this.relatedContext.getRootObject();
if (rootObject == null) {
return new TypedValue(rootObject,TypeDescriptor.NULL_TYPE_DESCRIPTOR);
return TypedValue.NULL_TYPED_VALUE;
} else {
return rootObject;
}
return rootObject;
}
return this.contextObjects.peek();
}
@ -80,7 +82,12 @@ public class ExpressionState {
}
public TypedValue getRootContextObject() {
return this.relatedContext.getRootObject();
TypedValue root = this.relatedContext.getRootObject();
if (root == null) {
return TypedValue.NULL_TYPED_VALUE;
} else {
return root;
}
}
public void setVariable(String name, Object value) {
@ -89,7 +96,11 @@ public class ExpressionState {
public TypedValue lookupVariable(String name) {
Object value = this.relatedContext.lookupVariable(name);
return new TypedValue(value,TypeDescriptor.forObject(value));
if (value==null) {
return TypedValue.NULL_TYPED_VALUE;
} else {
return new TypedValue(value,TypeDescriptor.forObject(value));
}
}
public TypeComparator getTypeComparator() {
@ -108,13 +119,10 @@ public class ExpressionState {
return this.relatedContext.getTypeConverter().convertValue(value.getValue(), targetTypeDescriptor);
}
// public <T> T convertValue(TypedValue value, Class<T> targetType) throws EvaluationException {
// return this.relatedContext.getTypeConverter().convertValue(value, targetType);
// }
/**
/*
* A new scope is entered when a function is invoked
*/
public void enterScope(Map<String, Object> argMap) {
this.variableScopes.push(new VariableScope(argMap));
}
@ -167,7 +175,6 @@ public class ExpressionState {
* A new scope is entered when a function is called and it is used to hold the parameters to the function call. If the names
* of the parameters clash with those in a higher level scope, those in the higher level scope will not be accessible whilst
* the function is executing. When the function returns the scope is exited.
*
*/
private static class VariableScope {

View File

@ -17,7 +17,6 @@
package org.springframework.expression.spel.ast;
import org.antlr.runtime.Token;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.TypedValue;
/**
@ -26,20 +25,18 @@ import org.springframework.expression.TypedValue;
*/
public class NullLiteral extends Literal {
private static final TypedValue NULL_TYPED_VALUE = new TypedValue(null,TypeDescriptor.NULL_TYPE_DESCRIPTOR);
public NullLiteral(Token payload) {
super(payload);
}
@Override
public TypedValue getLiteralValue() {
return NULL_TYPED_VALUE;
return TypedValue.NULL_TYPED_VALUE;
}
@Override
public String toString() {
return null;
return "null";
}
}

View File

@ -48,7 +48,7 @@ public class Projection extends SpelNodeImpl {
TypedValue op = state.getActiveContextObject();
Object operand = op.getValue();
TypeDescriptor operandTypeDescriptor = op.getTypeDescriptor();
// TypeDescriptor operandTypeDescriptor = op.getTypeDescriptor();
// When the input is a map, we push a special context object on the stack
// before calling the specified operation. This special context object
@ -58,9 +58,10 @@ public class Projection extends SpelNodeImpl {
if (operand instanceof Map) {
Map<?, ?> mapdata = (Map<?, ?>) operand;
List<Object> result = new ArrayList<Object>();
for (Object k : mapdata.keySet()) {
mapdata.entrySet();
for (Map.Entry entry : mapdata.entrySet()) {
try {
state.pushActiveContextObject(new TypedValue(new KeyValuePair(k, mapdata.get(k)),TypeDescriptor.valueOf(KeyValuePair.class)));
state.pushActiveContextObject(new TypedValue(new KeyValuePair(entry.getKey(), entry.getValue()),TypeDescriptor.valueOf(KeyValuePair.class)));
result.add(getChild(0).getValueInternal(state).getValue());
} finally {
state.popActiveContextObject();

View File

@ -63,10 +63,10 @@ public class Selection extends SpelNodeImpl {
// TODO don't lose generic info for the new map
Map<Object,Object> result = new HashMap<Object,Object>();
Object lastKey = null;
for (Object k : mapdata.keySet()) {
for (Map.Entry entry : mapdata.entrySet()) {
try {
lastKey = k;
KeyValuePair kvp = new KeyValuePair(k,mapdata.get(k));
lastKey = entry.getKey();
KeyValuePair kvp = new KeyValuePair(entry.getKey(),entry.getValue());
TypedValue kvpair = new TypedValue(kvp,TypeDescriptor.valueOf(KeyValuePair.class));
state.pushActiveContextObject(kvpair);
Object o = selectionCriteria.getValueInternal(state).getValue();
@ -90,9 +90,9 @@ public class Selection extends SpelNodeImpl {
return new TypedValue(null,TypeDescriptor.NULL_TYPE_DESCRIPTOR);
}
if (variant == LAST) {
Object lastValue = result.get(lastKey);
Map resultMap = new HashMap();
resultMap.put(lastKey,result.get(lastKey));
Object lastValue = result.get(lastKey);
resultMap.put(lastKey,lastValue);
return new TypedValue(resultMap,TypeDescriptor.valueOf(Map.class));
}
return new TypedValue(result,op.getTypeDescriptor());

View File

@ -57,8 +57,7 @@ class ReflectiveConstructorExecutor implements ConstructorExecutor {
c.setAccessible(true);
}
return new TypedValue(c.newInstance(arguments),TypeDescriptor.valueOf(c.getClass()));
}
catch (Exception ex) {
} catch (Exception ex) {
throw new AccessException("Problem invoking constructor: " + c, ex);
}
}

View File

@ -333,6 +333,9 @@ public class ReflectivePropertyResolver implements PropertyAccessor {
if (this == other) {
return true;
}
if (!(other instanceof CacheKey)) {
return false;
}
CacheKey otherKey = (CacheKey) other;
return (this.clazz.equals(otherKey.clazz) && this.name.equals(otherKey.name));
}

View File

@ -34,9 +34,8 @@ public class StandardTypeComparator implements TypeComparator {
// If one is null, check if the other is
if (left == null) {
return right == null ? 0 : 1;
}
else if (right == null) {
return left == null ? 0 : -1;
} else if (right == null) {
return -1; // left cannot be null
}
// Basic number comparisons

View File

@ -23,57 +23,8 @@ package org.springframework.expression.spel;
*/
public class ConstructorInvocationTests extends ExpressionTestCase {
// Some tests commented out as language support has been removed for now
// public void testPrimitiveTypeArrayConstructors() {
// evaluate("new int[]{1,2,3,4}.count()", 4, Integer.class);
// evaluate("new boolean[]{true,false,true}.count()", 3, Integer.class);
// evaluate("new char[]{'a','b','c'}.count()", 3, Integer.class);
// evaluate("new long[]{1,2,3,4,5}.count()", 5, Integer.class);
// evaluate("new short[]{2,3,4,5,6}.count()", 5, Integer.class);
// evaluate("new double[]{1d,2d,3d,4d}.count()", 4, Integer.class);
// evaluate("new float[]{1f,2f,3f,4f}.count()", 4, Integer.class);
// evaluate("new byte[]{1,2,3,4}.count()", 4, Integer.class);
// }
// public void testPrimitiveTypeArrayConstructorsElements() {
// evaluate("new int[]{1,2,3,4}[0]", 1, Integer.class);
// evaluate("new boolean[]{true,false,true}[0]", true, Boolean.class);
// evaluate("new char[]{'a','b','c'}[0]", 'a', Character.class);
// evaluate("new long[]{1,2,3,4,5}[0]", 1L, Long.class);
// evaluate("new short[]{2,3,4,5,6}[0]", (short) 2, Short.class);
// evaluate("new double[]{1d,2d,3d,4d}[0]", (double) 1, Double.class);
// evaluate("new float[]{1f,2f,3f,4f}[0]", (float) 1, Float.class);
// evaluate("new byte[]{1,2,3,4}[0]", (byte) 1, Byte.class);
// }
// public void testErrorCases() {
// evaluateAndCheckError("new char[7]{'a','c','d','e'}", SpelMessages.INITIALIZER_LENGTH_INCORRECT);
// evaluateAndCheckError("new char[3]{'a','c','d','e'}", SpelMessages.INITIALIZER_LENGTH_INCORRECT);
// evaluateAndCheckError("new char[2]{'hello','world'}", SpelMessages.TYPE_CONVERSION_ERROR);
// evaluateAndCheckError("new String('a','c','d')", SpelMessages.CONSTRUCTOR_NOT_FOUND);
// }
// public void testTypeArrayConstructors() {
// evaluate("new String[]{'a','b','c','d'}[1]", "b", String.class);
// evaluateAndCheckError("new String[]{'a','b','c','d'}.size()", SpelMessages.METHOD_NOT_FOUND, 30, "size()",
// "java.lang.String[]");
// evaluateAndCheckError("new String[]{'a','b','c','d'}.juggernaut", SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, 30,
// "juggernaut", "java.lang.String[]");
// evaluate("new String[]{'a','b','c','d'}.length", 4, Integer.class);
// }
// public void testMultiDimensionalArrays() {
// evaluate(
// "new String[3,4]",
// "[Ljava.lang.String;[3]{java.lang.String[4]{null,null,null,null},java.lang.String[4]{null,null,null,null},java.lang.String[4]{null,null,null,null}}"
// ,
// new String[3][4].getClass());
// }
public void testTypeConstructors() {
evaluate("new String('hello world')", "hello world", String.class);
// evaluate("new String(new char[]{'h','e','l','l','o'})", "hello", String.class);
}
public void testNonExistentType() {

View File

@ -43,5 +43,55 @@ public class DefaultComparatorUnitTests extends TestCase {
assertTrue(comparator.compare(1.0f, 1) == 0);
assertTrue(comparator.compare(2.0f, 1) > 0);
assertTrue(comparator.compare(1L, 2) < 0);
assertTrue(comparator.compare(1L, 1) == 0);
assertTrue(comparator.compare(2L, 1) > 0);
assertTrue(comparator.compare(1, 2L) < 0);
assertTrue(comparator.compare(1, 1L) == 0);
assertTrue(comparator.compare(2, 1L) > 0);
assertTrue(comparator.compare(1L, 2L) < 0);
assertTrue(comparator.compare(1L, 1L) == 0);
assertTrue(comparator.compare(2L, 1L) > 0);
}
public void testNulls() throws EvaluationException {
TypeComparator comparator = new StandardTypeComparator();
assertTrue(comparator.compare(null,"abc")>0);
assertTrue(comparator.compare(null,null)==0);
assertTrue(comparator.compare("abc",null)<0);
}
public void testObjects() throws EvaluationException {
TypeComparator comparator = new StandardTypeComparator();
assertTrue(comparator.compare("a","a")==0);
assertTrue(comparator.compare("a","b")<0);
assertTrue(comparator.compare("b","a")>0);
try {
comparator.compare("a",3);
fail("Should have failed");
} catch (EvaluationException ee) {
SpelException sEx = (SpelException)ee;
assertEquals(SpelMessages.NOT_COMPARABLE,sEx.getMessageUnformatted());
}
try {
comparator.compare(2,"b");
fail("Should have failed");
} catch (EvaluationException ee) {
SpelException sEx = (SpelException)ee;
assertEquals(SpelMessages.NOT_COMPARABLE,sEx.getMessageUnformatted());
}
}
public void testCanCompare() throws EvaluationException {
TypeComparator comparator = new StandardTypeComparator();
assertTrue(comparator.canCompare(null,1));
assertTrue(comparator.canCompare(1,null));
assertTrue(comparator.canCompare(2,1));
assertTrue(comparator.canCompare("abc","def"));
assertFalse(comparator.canCompare("abc",3));
}
}

View File

@ -16,21 +16,16 @@
package org.springframework.expression.spel;
import java.util.ArrayList;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.support.StandardEvaluationContext;
/**
* Tests the evaluation of real expressions in a real context.
*
* Node: Some tests commented out as language support has been removed
*
* @author Andy Clement
*/
public class EvaluationTests extends ExpressionTestCase {
// relational operators: lt, le, gt, ge, eq, ne
public void testRelOperatorGT01() {
evaluate("3 > 6", "false", Boolean.class);
}
@ -51,48 +46,10 @@ public class EvaluationTests extends ExpressionTestCase {
evaluate("3 >= 3", "true", Boolean.class);
}
// public void testRelOperatorsIn01() {
// evaluate("3 in {1,2,3,4,5}", "true", Boolean.class);
// }
// public void testRelOperatorsIn02() {
// evaluate("name in {null, \"Nikola Tesla\"}", "true", Boolean.class);
// evaluate("name in {null, \"Anonymous\"}", "false", Boolean.class);
// }
//
public void testRelOperatorsBetween01() {
evaluate("1 between listOneFive", "true", Boolean.class);
// evaluate("1 between {1, 5}", "true", Boolean.class); // no inline list building at the moment
}
//
// public void testRelOperatorsBetween02() {
// evaluate("'efg' between {'abc', 'xyz'}", "true", Boolean.class);
// }
//
public void testRelOperatorsBetweenErrors01() {
evaluateAndCheckError("1 between T(String)", SpelMessages.BETWEEN_RIGHT_OPERAND_MUST_BE_TWO_ELEMENT_LIST, 12);
}
//
// public void testRelOperatorsBetweenErrors02() {
// evaluateAndCheckError("'abc' between {5,7}", SpelMessages.NOT_COMPARABLE, 6);
// }
public void testRelOperatorsBetweenErrors03() {
evaluateAndCheckError("1 between listOfNumbersUpToTen", SpelMessages.BETWEEN_RIGHT_OPERAND_MUST_BE_TWO_ELEMENT_LIST, 10);
}
public void testRelOperatorsIs01() {
evaluate("'xyz' instanceof T(int)", "false", Boolean.class);
}
// public void testRelOperatorsIs02() {
// evaluate("{1, 2, 3, 4, 5} instanceof T(List)", "true", Boolean.class);
// }
//
// public void testRelOperatorsIs03() {
// evaluate("{1, 2, 3, 4, 5} instanceof T(List)", "true", Boolean.class);
// }
public void testRelOperatorsIs04() {
evaluate("null instanceof T(String)", "false", Boolean.class);
}
@ -132,9 +89,8 @@ public class EvaluationTests extends ExpressionTestCase {
// property access
public void testPropertyField01() {
evaluate("name", "Nikola Tesla", String.class, false); // not writable because (1) name is private (2) there is
// no
// setter, only a getter
evaluate("name", "Nikola Tesla", String.class, false);
// not writable because (1) name is private (2) there is no setter, only a getter
evaluateAndCheckError("madeup", SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, 0, "madeup",
"org.springframework.expression.spel.testresources.Inventor");
}
@ -157,59 +113,11 @@ public class EvaluationTests extends ExpressionTestCase {
evaluate("echo(name)", "Nikola Tesla", String.class);
}
// inline list creation
// public void testInlineListCreation01() {
// evaluate("{1, 2, 3, 4, 5}", "[1, 2, 3, 4, 5]", ArrayList.class);
// }
//
// public void testInlineListCreation02() {
// evaluate("{'abc', 'xyz'}", "[abc, xyz]", ArrayList.class);
// }
//
// // inline map creation
// public void testInlineMapCreation01() {
// evaluate("#{'key1':'Value 1', 'today':'Monday'}", "{key1=Value 1, today=Monday}", HashMap.class);
// }
//
// public void testInlineMapCreation02() {
// evaluate("#{1:'January', 2:'February', 3:'March'}.size()", 3, Integer.class);// "{2=February, 1=January,
// // 3=March}", HashMap.class);
// }
//
// public void testInlineMapCreation03() {
// evaluate("#{'key1':'Value 1', 'today':'Monday'}['key1']", "Value 1", String.class);
// }
//
// public void testInlineMapCreation04() {
// evaluate("#{1:'January', 2:'February', 3:'March'}[3]", "March", String.class);
// }
//
// public void testInlineMapCreation05() {
// evaluate("#{1:'January', 2:'February', 3:'March'}.get(2)", "February", String.class);
// }
//
// // set construction
// public void testSetConstruction01() {
// evaluate("new HashSet().addAll({'a','b','c'})", "true", Boolean.class);
// }
// constructors
public void testConstructorInvocation01() {
evaluate("new String('hello')", "hello", String.class);
}
// public void testConstructorInvocation02() {
// evaluate("new String[3]", "java.lang.String[3]{null,null,null}", String[].class);
// }
// public void testConstructorInvocation03() {
// evaluateAndCheckError("new String[]", SpelMessages.NO_SIZE_OR_INITIALIZER_FOR_ARRAY_CONSTRUCTION, 4);
// }
// public void testConstructorInvocation04() {
// evaluateAndCheckError("new String[3]{'abc',3,'def'}", SpelMessages.INCORRECT_ELEMENT_TYPE_FOR_ARRAY, 4);
// }
public void testConstructorInvocation05() {
evaluate("new java.lang.String('foobar')", "foobar", String.class);
}
@ -229,16 +137,6 @@ public class EvaluationTests extends ExpressionTestCase {
assertEquals("new String('wibble')",expr.toStringAST());
}
// array construction
// public void testArrayConstruction01() {
// evaluate("new int[] {1, 2, 3, 4, 5}", "int[5]{1,2,3,4,5}", int[].class);
// }
// public void testArrayConstruction02() {
// evaluate("new String[] {'abc', 'xyz'}", "java.lang.String[2]{abc,xyz}", String[].class);
// }
// unary expressions
public void testUnaryMinus01() {
evaluate("-5", "-5", Integer.class);
@ -251,153 +149,11 @@ public class EvaluationTests extends ExpressionTestCase {
public void testUnaryNot01() {
evaluate("!true", "false", Boolean.class);
}
// collection processors
// from spring.net: count,sum,max,min,average,sort,orderBy,distinct,nonNull
// public void testProcessorsCount01() {
// evaluate("new String[] {'abc','def','xyz'}.count()", "3", Integer.class);
// }
//
// public void testProcessorsCount02() {
// evaluate("new int[] {1,2,3}.count()", "3", Integer.class);
// }
//
// public void testProcessorsMax01() {
// evaluate("new int[] {1,2,3}.max()", "3", Integer.class);
// }
//
// public void testProcessorsMin01() {
// evaluate("new int[] {1,2,3}.min()", "1", Integer.class);
// }
//
// public void testProcessorsKeys01() {
// evaluate("#{1:'January', 2:'February', 3:'March'}.keySet().sort()", "[1, 2, 3]", ArrayList.class);
// }
//
// public void testProcessorsValues01() {
// evaluate("#{1:'January', 2:'February', 3:'March'}.values().sort()", "[February, January, March]",
// ArrayList.class);
// }
//
// public void testProcessorsAverage01() {
// evaluate("new int[] {1,2,3}.average()", "2", Integer.class);
// }
//
// public void testProcessorsSort01() {
// evaluate("new int[] {3,2,1}.sort()", "int[3]{1,2,3}", int[].class);
// }
//
// public void testCollectionProcessorsNonNull01() {
// evaluate("{'a','b',null,'d',null}.nonnull()", "[a, b, d]", ArrayList.class);
// }
//
// public void testCollectionProcessorsDistinct01() {
// evaluate("{'a','b','a','d','e'}.distinct()", "[a, b, d, e]", ArrayList.class);
// }
// projection and selection
public void testProjection01() {
evaluate("listOfNumbersUpToTen.!{#this<5?'y':'n'}","[y, y, y, y, n, n, n, n, n, n]",ArrayList.class);
// inline list creation not supported at the moment
// evaluate("{1,2,3,4,5,6,7,8,9,10}.!{#isEven(#this)}", "[n, y, n, y, n, y, n, y, n, y]", ArrayList.class);
}
public void testProjection02() {
// inline map creation not supported at the moment
// evaluate("#{'a':'y','b':'n','c':'y'}.!{value=='y'?key:null}.nonnull().sort()", "[a, c]", ArrayList.class);
evaluate("mapOfNumbersUpToTen.!{key>5?value:null}", "[null, null, null, null, null, six, seven, eight, nine, ten]", ArrayList.class);
}
// public void testProjection03() {
// evaluate("{1,2,3,4,5,6,7,8,9,10}.!{#this>5}",
// "[false, false, false, false, false, true, true, true, true, true]", ArrayList.class);
// }
// public void testProjection04() {
// evaluate("{1,2,3,4,5,6,7,8,9,10}.!{$index>5?'y':'n'}", "[n, n, n, n, n, n, y, y, y, y]", ArrayList.class);
// }
public void testProjection05() {
evaluateAndCheckError("'abc'.!{true}", SpelMessages.PROJECTION_NOT_SUPPORTED_ON_TYPE);
}
public void testProjection06() throws Exception {
SpelExpression expr = (SpelExpression)parser.parseExpression("'abc'.!{true}");
assertEquals("'abc'.!{true}",expr.toStringAST());
assertFalse(expr.isWritable(new StandardEvaluationContext()));
}
//public void testSelection01() {
// inline list creation not supported:
// evaluate("{1,2,3,4,5,6,7,8,9,10}.?{#isEven(#this) == 'y'}", "[2, 4, 6, 8, 10]", ArrayList.class);
//}
public void testSelection02() {
evaluate("testMap.keySet().?{#this matches '.*o.*'}", "[monday]", ArrayList.class);
evaluate("testMap.keySet().?{#this matches '.*r.*'}.contains('saturday')", "true", Boolean.class);
evaluate("testMap.keySet().?{#this matches '.*r.*'}.size()", "3", Integer.class);
}
public void testSelectionError_NonBooleanSelectionCriteria() {
evaluateAndCheckError("listOfNumbersUpToTen.?{'nonboolean'}",
SpelMessages.RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN);
}
// public void testSelectionUsingIndex() {
// evaluate("{1,2,3,4,5,6,7,8,9,10}.?{$index > 5 }", "[7, 8, 9, 10]", ArrayList.class);
// }
public void testSelection03() {
evaluate("mapOfNumbersUpToTen.?{key>5}.size()", "5", Integer.class);
}
public void testSelection04() {
evaluateAndCheckError("mapOfNumbersUpToTen.?{'hello'}.size()",SpelMessages.RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN);
}
public void testSelectionFirst01() {
evaluate("listOfNumbersUpToTen.^{#isEven(#this) == 'y'}", "2", Integer.class);
}
public void testSelectionFirst02() {
evaluate("mapOfNumbersUpToTen.^{key>5}.size()", "1", Integer.class);
}
public void testSelectionLast01() {
evaluate("listOfNumbersUpToTen.${#isEven(#this) == 'y'}", "10", Integer.class);
}
public void testSelectionLast02() {
evaluate("mapOfNumbersUpToTen.${key>5}.size()", "1", Integer.class);
}
public void testSelectionAST() throws Exception {
SpelExpression expr = (SpelExpression)parser.parseExpression("'abc'.^{true}");
assertEquals("'abc'.^{true}",expr.toStringAST());
assertFalse(expr.isWritable(new StandardEvaluationContext()));
expr = (SpelExpression)parser.parseExpression("'abc'.?{true}");
assertEquals("'abc'.?{true}",expr.toStringAST());
assertFalse(expr.isWritable(new StandardEvaluationContext()));
expr = (SpelExpression)parser.parseExpression("'abc'.${true}");
assertEquals("'abc'.${true}",expr.toStringAST());
assertFalse(expr.isWritable(new StandardEvaluationContext()));
}
// assignment
public void testAssignmentToVariables01() {
evaluate("#var1='value1'", "value1", String.class);
}
// Ternary operator
// public void testTernaryOperator01() {
// evaluate("{1}.#isEven(#this[0]) == 'y'?'it is even':'it is odd'", "it is odd", String.class);
// }
//
// public void testTernaryOperator02() {
// evaluate("{2}.#isEven(#this[0]) == 'y'?'it is even':'it is odd'", "it is even", String.class);
// }
public void testTernaryOperator01() {
evaluate("2>4?1:2",2,Integer.class);
}
@ -414,15 +170,6 @@ public class EvaluationTests extends ExpressionTestCase {
Expression expr = parser.parseExpression("1>2?3:4");
assertFalse(expr.isWritable(eContext));
}
// Indexer
// public void testCutProcessor01() {
// evaluate("{1,2,3,4,5}.cut(1,3)", "[2, 3, 4]", ArrayList.class);
// }
//
// public void testCutProcessor02() {
// evaluate("{1,2,3,4,5}.cut(3,1)", "[4, 3, 2]", ArrayList.class);
// }
public void testIndexer03() {
evaluate("'christian'[8]", "n", String.class);
@ -432,36 +179,6 @@ public class EvaluationTests extends ExpressionTestCase {
evaluateAndCheckError("new org.springframework.expression.spel.testresources.Inventor().inventions[1]",SpelMessages.CANNOT_INDEX_INTO_NULL_VALUE);
}
// Bean references
// public void testReferences01() {
// evaluate("@(apple).name", "Apple", String.class, true);
// }
//
// public void testReferences02() {
// evaluate("@(fruits:banana).name", "Banana", String.class, true);
// }
//
// public void testReferences03() {
// evaluate("@(a.b.c)", null, null);
// } // null - no context, a.b.c treated as name
//
// public void testReferences05() {
// evaluate("@(a/b/c:orange).name", "Orange", String.class, true);
// }
//
// public void testReferences06() {
// evaluate("@(apple).color.getRGB() == T(java.awt.Color).green.getRGB()", "true", Boolean.class);
// }
//
// public void testReferences07() {
// evaluate("@(apple).color.getRGB().equals(T(java.awt.Color).green.getRGB())", "true", Boolean.class);
// }
// value is not public, it is accessed through getRGB()
// public void testStaticRef01() {
// evaluate("T(Color).green.value!=0", "true", Boolean.class);
// }
public void testStaticRef02() {
evaluate("T(java.awt.Color).green.getRGB()!=0", "true", Boolean.class);
}
@ -479,42 +196,6 @@ public class EvaluationTests extends ExpressionTestCase {
evaluate("#reverseString('hello')", "olleh", String.class);
}
//
// public void testLambda02() {
// evaluate("(#max={|x,y| $x > $y ? $x : $y };true)", "true", Boolean.class);
// }
//
// public void testLambdaMax() {
// evaluate("(#max = {|x,y| $x > $y ? $x : $y }; #max(5,25))", "25", Integer.class);
// }
//
// public void testLambdaFactorial01() {
// evaluate("(#fact = {|n| $n <= 1 ? 1 : $n * #fact($n-1) }; #fact(5))", "120", Integer.class);
// }
//
// public void testLambdaFactorial02() {
// evaluate("(#fact = {|n| $n <= 1 ? 1 : #fact($n-1) * $n }; #fact(5))", "120", Integer.class);
// }
//
// public void testLambdaAlphabet01() {
// evaluate("(#alpha = {|l,s| $l>'z'?$s:#alpha($l+1,$s+$l)};#alphabet={||#alpha('a','')}; #alphabet())",
// "abcdefghijklmnopqrstuvwxyz", String.class);
// }
//
// public void testLambdaAlphabet02() {
// evaluate("(#alphabet = {|l,s| $l>'z'?$s:#alphabet($l+1,$s+$l)};#alphabet('a',''))",
// "abcdefghijklmnopqrstuvwxyz", String.class);
// }
//
// public void testLambdaDelegation01() {
// evaluate("(#sqrt={|n| T(Math).sqrt($n)};#delegate={|f,n| $f($n)};#delegate(#sqrt,4))", "2.0", Double.class);
// }
//
// public void testVariableReferences() {
// evaluate("(#answer=42;#answer)", "42", Integer.class, true);
// evaluate("($answer=42;$answer)", "42", Integer.class, true);
// }
// type references
public void testTypeReferences01() {
evaluate("T(java.lang.String)", "class java.lang.String", Class.class);
@ -556,6 +237,5 @@ public class EvaluationTests extends ExpressionTestCase {
evaluateAndAskForReturnType("3*4+5", (short) 17, Short.class);
evaluateAndAskForReturnType("3*4+5", "17", String.class);
}
}

View File

@ -0,0 +1,241 @@
/*
* Copyright 2002-2009 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.expression.spel;
import java.util.HashMap;
import java.util.Map;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.Operation;
import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.testresources.Inventor;
/**
* Tests for the expression state object - some features are not yet exploited in the language (eg nested scopes)
*
* @author Andy Clement
*/
public class ExpressionStateTests extends ExpressionTestCase {
public void testConstruction() {
EvaluationContext context = TestScenarioCreator.getTestEvaluationContext();
ExpressionState state = new ExpressionState(context);
assertEquals(context,state.getEvaluationContext());
}
// Local variables are in variable scopes which come and go during evaluation. Normal variables are
// accessible through the evaluation context
public void testLocalVariables() {
ExpressionState state = getState();
Object value = state.lookupLocalVariable("foo");
assertNull(value);
state.setLocalVariable("foo",34);
value = state.lookupLocalVariable("foo");
assertEquals(34,value);
state.setLocalVariable("foo",null);
value = state.lookupLocalVariable("foo");
assertEquals(null,value);
}
public void testVariables() {
ExpressionState state = getState();
TypedValue typedValue = state.lookupVariable("foo");
assertEquals(TypedValue.NULL_TYPED_VALUE,typedValue);
state.setVariable("foo",34);
typedValue = state.lookupVariable("foo");
assertEquals(34,typedValue.getValue());
assertEquals(Integer.class,typedValue.getTypeDescriptor().getType());
state.setVariable("foo","abc");
typedValue = state.lookupVariable("foo");
assertEquals("abc",typedValue.getValue());
assertEquals(String.class,typedValue.getTypeDescriptor().getType());
}
public void testNoVariableInteference() {
ExpressionState state = getState();
TypedValue typedValue = state.lookupVariable("foo");
assertEquals(TypedValue.NULL_TYPED_VALUE,typedValue);
state.setLocalVariable("foo",34);
typedValue = state.lookupVariable("foo");
assertEquals(TypedValue.NULL_TYPED_VALUE,typedValue);
state.setVariable("goo","hello");
assertNull(state.lookupLocalVariable("goo"));
}
public void testLocalVariableNestedScopes() {
ExpressionState state = getState();
assertEquals(null,state.lookupLocalVariable("foo"));
state.setLocalVariable("foo",12);
assertEquals(12,state.lookupLocalVariable("foo"));
state.enterScope(null);
assertEquals(12,state.lookupLocalVariable("foo")); // found in upper scope
state.setLocalVariable("foo","abc");
assertEquals("abc",state.lookupLocalVariable("foo")); // found in nested scope
state.exitScope();
assertEquals(12,state.lookupLocalVariable("foo")); // found in nested scope
}
public void testRootContextObject() {
ExpressionState state = getState();
assertEquals(Inventor.class,state.getRootContextObject().getValue().getClass());
state.getEvaluationContext().setRootObject(null);
assertEquals(null,state.getRootContextObject().getValue());
state = new ExpressionState(new StandardEvaluationContext());
assertEquals(TypedValue.NULL_TYPED_VALUE,state.getRootContextObject());
}
public void testActiveContextObject() {
ExpressionState state = getState();
assertEquals(state.getRootContextObject().getValue(),state.getActiveContextObject().getValue());
state.pushActiveContextObject(new TypedValue(34));
assertEquals(34,state.getActiveContextObject().getValue());
state.pushActiveContextObject(new TypedValue("hello"));
assertEquals("hello",state.getActiveContextObject().getValue());
state.popActiveContextObject();
assertEquals(34,state.getActiveContextObject().getValue());
state.popActiveContextObject();
assertEquals(state.getRootContextObject().getValue(),state.getActiveContextObject().getValue());
state = new ExpressionState(new StandardEvaluationContext());
assertEquals(TypedValue.NULL_TYPED_VALUE,state.getActiveContextObject());
}
public void testPopulatedNestedScopes() {
ExpressionState state = getState();
assertNull(state.lookupLocalVariable("foo"));
state.enterScope("foo",34);
assertEquals(34,state.lookupLocalVariable("foo"));
state.enterScope(null);
state.setLocalVariable("foo",12);
assertEquals(12,state.lookupLocalVariable("foo"));
state.exitScope();
assertEquals(34,state.lookupLocalVariable("foo"));
state.exitScope();
assertNull(state.lookupLocalVariable("goo"));
}
public void testPopulatedNestedScopesMap() {
ExpressionState state = getState();
assertNull(state.lookupLocalVariable("foo"));
assertNull(state.lookupLocalVariable("goo"));
Map<String,Object> m = new HashMap<String,Object>();
m.put("foo",34);
m.put("goo","abc");
state.enterScope(m);
assertEquals(34,state.lookupLocalVariable("foo"));
assertEquals("abc",state.lookupLocalVariable("goo"));
state.enterScope(null);
state.setLocalVariable("foo",12);
assertEquals(12,state.lookupLocalVariable("foo"));
assertEquals("abc",state.lookupLocalVariable("goo"));
state.exitScope();
state.exitScope();
assertNull(state.lookupLocalVariable("foo"));
assertNull(state.lookupLocalVariable("goo"));
}
public void testOperators() throws Exception {
ExpressionState state = getState();
try {
state.operate(Operation.ADD,1,2);
fail("should have failed");
} catch (EvaluationException ee) {
SpelException sEx = (SpelException)ee;
assertEquals(SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES,sEx.getMessageUnformatted());
}
try {
state.operate(Operation.ADD,null,null);
fail("should have failed");
} catch (EvaluationException ee) {
SpelException sEx = (SpelException)ee;
assertEquals(SpelMessages.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES,sEx.getMessageUnformatted());
}
}
public void testComparator() {
ExpressionState state = getState();
assertEquals(state.getEvaluationContext().getTypeComparator(),state.getTypeComparator());
}
public void testTypeLocator() throws EvaluationException {
ExpressionState state = getState();
assertNotNull(state.getEvaluationContext().getTypeLocator());
assertEquals(Integer.class,state.findType("java.lang.Integer"));
try {
state.findType("someMadeUpName");
fail("Should have failed to find it");
} catch (EvaluationException ee) {
SpelException sEx = (SpelException)ee;
assertEquals(SpelMessages.TYPE_NOT_FOUND,sEx.getMessageUnformatted());
}
}
public void testTypeConversion() throws EvaluationException {
ExpressionState state = getState();
String s = (String)state.convertValue(34,TypeDescriptor.valueOf(String.class));
assertEquals("34",s);
s = (String)state.convertValue(new TypedValue(34),TypeDescriptor.valueOf(String.class));
assertEquals("34",s);
}
public void testPropertyAccessors() {
ExpressionState state = getState();
assertEquals(state.getEvaluationContext().getPropertyAccessors(),state.getPropertyAccessors());
}
/**
* @return a new ExpressionState
*/
private ExpressionState getState() {
EvaluationContext context = TestScenarioCreator.getTestEvaluationContext();
ExpressionState state = new ExpressionState(context);
return state;
}
}

View File

@ -15,6 +15,10 @@
*/
package org.springframework.expression.spel;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import org.springframework.expression.ParseException;
import org.springframework.expression.spel.ast.FormatHelper;
/**
@ -38,8 +42,33 @@ public class HelperTests extends ExpressionTestCase {
assertEquals("boo()",FormatHelper.formatMethodForMessage("boo"));
}
// public void testReflectionHelper01() {
// ReflectionHelper.convertArguments(parameterTypes, isVarargs, converter, arguments)
//// ReflectionHelper.setupArgumentsForVarargsInvocation(;, args)
// }
public void testUtilities() throws ParseException {
SpelExpression expr = (SpelExpression)parser.parseExpression("3+4+5+6+7-2");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
SpelUtilities.printAbstractSyntaxTree(ps, expr);
ps.flush();
String s = baos.toString();
// ===> Expression '3+4+5+6+7-2' - AST start
// OperatorMinus value:(((((3 + 4) + 5) + 6) + 7) - 2) #children:2
// OperatorPlus value:((((3 + 4) + 5) + 6) + 7) #children:2
// OperatorPlus value:(((3 + 4) + 5) + 6) #children:2
// OperatorPlus value:((3 + 4) + 5) #children:2
// OperatorPlus value:(3 + 4) #children:2
// CompoundExpression value:3
// IntLiteral value:3
// CompoundExpression value:4
// IntLiteral value:4
// CompoundExpression value:5
// IntLiteral value:5
// CompoundExpression value:6
// IntLiteral value:6
// CompoundExpression value:7
// IntLiteral value:7
// CompoundExpression value:2
// IntLiteral value:2
// ===> Expression '3+4+5+6+7-2' - AST end
assertTrue(s.indexOf("===> Expression '3+4+5+6+7-2' - AST start")!=-1);
assertTrue(s.indexOf(" OperatorPlus value:((((3 + 4) + 5) + 6) + 7) #children:2")!=-1);
}
}

View File

@ -0,0 +1,395 @@
/*
* Copyright 2002-2009 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.expression.spel;
import java.util.ArrayList;
import org.springframework.expression.spel.support.StandardEvaluationContext;
/**
* These are tests for language features that are not yet considered 'live'. Either missing implementation, or documentation.
*
* Where implementation is missing the tests are commented out.
*
* @author Andy Clement
*/
public class InProgressTests extends ExpressionTestCase {
// Constructor invocation
// public void testPrimitiveTypeArrayConstructors() {
// evaluate("new int[]{1,2,3,4}.count()", 4, Integer.class);
// evaluate("new boolean[]{true,false,true}.count()", 3, Integer.class);
// evaluate("new char[]{'a','b','c'}.count()", 3, Integer.class);
// evaluate("new long[]{1,2,3,4,5}.count()", 5, Integer.class);
// evaluate("new short[]{2,3,4,5,6}.count()", 5, Integer.class);
// evaluate("new double[]{1d,2d,3d,4d}.count()", 4, Integer.class);
// evaluate("new float[]{1f,2f,3f,4f}.count()", 4, Integer.class);
// evaluate("new byte[]{1,2,3,4}.count()", 4, Integer.class);
// }
// public void testPrimitiveTypeArrayConstructorsElements() {
// evaluate("new int[]{1,2,3,4}[0]", 1, Integer.class);
// evaluate("new boolean[]{true,false,true}[0]", true, Boolean.class);
// evaluate("new char[]{'a','b','c'}[0]", 'a', Character.class);
// evaluate("new long[]{1,2,3,4,5}[0]", 1L, Long.class);
// evaluate("new short[]{2,3,4,5,6}[0]", (short) 2, Short.class);
// evaluate("new double[]{1d,2d,3d,4d}[0]", (double) 1, Double.class);
// evaluate("new float[]{1f,2f,3f,4f}[0]", (float) 1, Float.class);
// evaluate("new byte[]{1,2,3,4}[0]", (byte) 1, Byte.class);
// }
// public void testErrorCases() {
// evaluateAndCheckError("new char[7]{'a','c','d','e'}", SpelMessages.INITIALIZER_LENGTH_INCORRECT);
// evaluateAndCheckError("new char[3]{'a','c','d','e'}", SpelMessages.INITIALIZER_LENGTH_INCORRECT);
// evaluateAndCheckError("new char[2]{'hello','world'}", SpelMessages.TYPE_CONVERSION_ERROR);
// evaluateAndCheckError("new String('a','c','d')", SpelMessages.CONSTRUCTOR_NOT_FOUND);
// }
// public void testTypeArrayConstructors() {
// evaluate("new String[]{'a','b','c','d'}[1]", "b", String.class);
// evaluateAndCheckError("new String[]{'a','b','c','d'}.size()", SpelMessages.METHOD_NOT_FOUND, 30, "size()",
// "java.lang.String[]");
// evaluateAndCheckError("new String[]{'a','b','c','d'}.juggernaut", SpelMessages.PROPERTY_OR_FIELD_NOT_FOUND, 30,
// "juggernaut", "java.lang.String[]");
// evaluate("new String[]{'a','b','c','d'}.length", 4, Integer.class);
// }
// public void testMultiDimensionalArrays() {
// evaluate(
// "new String[3,4]",
// "[Ljava.lang.String;[3]{java.lang.String[4]{null,null,null,null},java.lang.String[4]{null,null,null,null},java.lang.String[4]{null,null,null,null}}"
// ,
// new String[3][4].getClass());
// }
// evaluate("new String(new char[]{'h','e','l','l','o'})", "hello", String.class);
// public void testRelOperatorsIn01() {
// evaluate("3 in {1,2,3,4,5}", "true", Boolean.class);
// }
// public void testRelOperatorsIn02() {
// evaluate("name in {null, \"Nikola Tesla\"}", "true", Boolean.class);
// evaluate("name in {null, \"Anonymous\"}", "false", Boolean.class);
// }
//
public void testRelOperatorsBetween01() {
evaluate("1 between listOneFive", "true", Boolean.class);
// evaluate("1 between {1, 5}", "true", Boolean.class); // no inline list building at the moment
}
//
// public void testRelOperatorsBetween02() {
// evaluate("'efg' between {'abc', 'xyz'}", "true", Boolean.class);
// }
//
public void testRelOperatorsBetweenErrors01() {
evaluateAndCheckError("1 between T(String)", SpelMessages.BETWEEN_RIGHT_OPERAND_MUST_BE_TWO_ELEMENT_LIST, 12);
}
//
// public void testRelOperatorsBetweenErrors02() {
// evaluateAndCheckError("'abc' between {5,7}", SpelMessages.NOT_COMPARABLE, 6);
// }
public void testRelOperatorsBetweenErrors03() {
evaluateAndCheckError("1 between listOfNumbersUpToTen", SpelMessages.BETWEEN_RIGHT_OPERAND_MUST_BE_TWO_ELEMENT_LIST, 10);
}
// Lambda calculations
//
// public void testLambda02() {
// evaluate("(#max={|x,y| $x > $y ? $x : $y };true)", "true", Boolean.class);
// }
//
// public void testLambdaMax() {
// evaluate("(#max = {|x,y| $x > $y ? $x : $y }; #max(5,25))", "25", Integer.class);
// }
//
// public void testLambdaFactorial01() {
// evaluate("(#fact = {|n| $n <= 1 ? 1 : $n * #fact($n-1) }; #fact(5))", "120", Integer.class);
// }
//
// public void testLambdaFactorial02() {
// evaluate("(#fact = {|n| $n <= 1 ? 1 : #fact($n-1) * $n }; #fact(5))", "120", Integer.class);
// }
//
// public void testLambdaAlphabet01() {
// evaluate("(#alpha = {|l,s| $l>'z'?$s:#alpha($l+1,$s+$l)};#alphabet={||#alpha('a','')}; #alphabet())",
// "abcdefghijklmnopqrstuvwxyz", String.class);
// }
//
// public void testLambdaAlphabet02() {
// evaluate("(#alphabet = {|l,s| $l>'z'?$s:#alphabet($l+1,$s+$l)};#alphabet('a',''))",
// "abcdefghijklmnopqrstuvwxyz", String.class);
// }
//
// public void testLambdaDelegation01() {
// evaluate("(#sqrt={|n| T(Math).sqrt($n)};#delegate={|f,n| $f($n)};#delegate(#sqrt,4))", "2.0", Double.class);
// }
//
// public void testVariableReferences() {
// evaluate("(#answer=42;#answer)", "42", Integer.class, true);
// evaluate("($answer=42;$answer)", "42", Integer.class, true);
// }
//
//
// public void testRelOperatorsIs02() {
// evaluate("{1, 2, 3, 4, 5} instanceof T(List)", "true", Boolean.class);
// }
//
// public void testRelOperatorsIs03() {
// evaluate("{1, 2, 3, 4, 5} instanceof T(List)", "true", Boolean.class);
// }
//
// inline list creation
// public void testInlineListCreation01() {
// evaluate("{1, 2, 3, 4, 5}", "[1, 2, 3, 4, 5]", ArrayList.class);
// }
//
// public void testInlineListCreation02() {
// evaluate("{'abc', 'xyz'}", "[abc, xyz]", ArrayList.class);
// }
//
// // inline map creation
// public void testInlineMapCreation01() {
// evaluate("#{'key1':'Value 1', 'today':'Monday'}", "{key1=Value 1, today=Monday}", HashMap.class);
// }
//
// public void testInlineMapCreation02() {
// evaluate("#{1:'January', 2:'February', 3:'March'}.size()", 3, Integer.class);// "{2=February, 1=January,
// // 3=March}", HashMap.class);
// }
//
// public void testInlineMapCreation03() {
// evaluate("#{'key1':'Value 1', 'today':'Monday'}['key1']", "Value 1", String.class);
// }
//
// public void testInlineMapCreation04() {
// evaluate("#{1:'January', 2:'February', 3:'March'}[3]", "March", String.class);
// }
//
// public void testInlineMapCreation05() {
// evaluate("#{1:'January', 2:'February', 3:'March'}.get(2)", "February", String.class);
// }
//
// // set construction
// public void testSetConstruction01() {
// evaluate("new HashSet().addAll({'a','b','c'})", "true", Boolean.class);
// }
//
// public void testConstructorInvocation02() {
// evaluate("new String[3]", "java.lang.String[3]{null,null,null}", String[].class);
// }
//
// public void testConstructorInvocation03() {
// evaluateAndCheckError("new String[]", SpelMessages.NO_SIZE_OR_INITIALIZER_FOR_ARRAY_CONSTRUCTION, 4);
// }
//
// public void testConstructorInvocation04() {
// evaluateAndCheckError("new String[3]{'abc',3,'def'}", SpelMessages.INCORRECT_ELEMENT_TYPE_FOR_ARRAY, 4);
// }
// // array construction
// public void testArrayConstruction01() {
// evaluate("new int[] {1, 2, 3, 4, 5}", "int[5]{1,2,3,4,5}", int[].class);
// }
// public void testArrayConstruction02() {
// evaluate("new String[] {'abc', 'xyz'}", "java.lang.String[2]{abc,xyz}", String[].class);
// }
// collection processors
// from spring.net: count,sum,max,min,average,sort,orderBy,distinct,nonNull
// public void testProcessorsCount01() {
// evaluate("new String[] {'abc','def','xyz'}.count()", "3", Integer.class);
// }
//
// public void testProcessorsCount02() {
// evaluate("new int[] {1,2,3}.count()", "3", Integer.class);
// }
//
// public void testProcessorsMax01() {
// evaluate("new int[] {1,2,3}.max()", "3", Integer.class);
// }
//
// public void testProcessorsMin01() {
// evaluate("new int[] {1,2,3}.min()", "1", Integer.class);
// }
//
// public void testProcessorsKeys01() {
// evaluate("#{1:'January', 2:'February', 3:'March'}.keySet().sort()", "[1, 2, 3]", ArrayList.class);
// }
//
// public void testProcessorsValues01() {
// evaluate("#{1:'January', 2:'February', 3:'March'}.values().sort()", "[February, January, March]",
// ArrayList.class);
// }
//
// public void testProcessorsAverage01() {
// evaluate("new int[] {1,2,3}.average()", "2", Integer.class);
// }
//
// public void testProcessorsSort01() {
// evaluate("new int[] {3,2,1}.sort()", "int[3]{1,2,3}", int[].class);
// }
//
// public void testCollectionProcessorsNonNull01() {
// evaluate("{'a','b',null,'d',null}.nonnull()", "[a, b, d]", ArrayList.class);
// }
//
// public void testCollectionProcessorsDistinct01() {
// evaluate("{'a','b','a','d','e'}.distinct()", "[a, b, d, e]", ArrayList.class);
// }
//
// public void testProjection03() {
// evaluate("{1,2,3,4,5,6,7,8,9,10}.!{#this>5}",
// "[false, false, false, false, false, true, true, true, true, true]", ArrayList.class);
// }
//
// public void testProjection04() {
// evaluate("{1,2,3,4,5,6,7,8,9,10}.!{$index>5?'y':'n'}", "[n, n, n, n, n, n, y, y, y, y]", ArrayList.class);
// }
// Bean references
// public void testReferences01() {
// evaluate("@(apple).name", "Apple", String.class, true);
// }
//
// public void testReferences02() {
// evaluate("@(fruits:banana).name", "Banana", String.class, true);
// }
//
// public void testReferences03() {
// evaluate("@(a.b.c)", null, null);
// } // null - no context, a.b.c treated as name
//
// public void testReferences05() {
// evaluate("@(a/b/c:orange).name", "Orange", String.class, true);
// }
//
// public void testReferences06() {
// evaluate("@(apple).color.getRGB() == T(java.awt.Color).green.getRGB()", "true", Boolean.class);
// }
//
// public void testReferences07() {
// evaluate("@(apple).color.getRGB().equals(T(java.awt.Color).green.getRGB())", "true", Boolean.class);
// }
//
// value is not public, it is accessed through getRGB()
// public void testStaticRef01() {
// evaluate("T(Color).green.value!=0", "true", Boolean.class);
// }
// Indexer
// public void testCutProcessor01() {
// evaluate("{1,2,3,4,5}.cut(1,3)", "[2, 3, 4]", ArrayList.class);
// }
//
// public void testCutProcessor02() {
// evaluate("{1,2,3,4,5}.cut(3,1)", "[4, 3, 2]", ArrayList.class);
// }
// Ternary operator
// public void testTernaryOperator01() {
// evaluate("{1}.#isEven(#this[0]) == 'y'?'it is even':'it is odd'", "it is odd", String.class);
// }
//
// public void testTernaryOperator02() {
// evaluate("{2}.#isEven(#this[0]) == 'y'?'it is even':'it is odd'", "it is even", String.class);
// }
// public void testSelectionUsingIndex() {
// evaluate("{1,2,3,4,5,6,7,8,9,10}.?{$index > 5 }", "[7, 8, 9, 10]", ArrayList.class);
// }
//public void testSelection01() {
// inline list creation not supported:
// evaluate("{1,2,3,4,5,6,7,8,9,10}.?{#isEven(#this) == 'y'}", "[2, 4, 6, 8, 10]", ArrayList.class);
//}
// projection and selection
public void testProjection01() {
evaluate("listOfNumbersUpToTen.!{#this<5?'y':'n'}","[y, y, y, y, n, n, n, n, n, n]",ArrayList.class);
// inline list creation not supported at the moment
// evaluate("{1,2,3,4,5,6,7,8,9,10}.!{#isEven(#this)}", "[n, y, n, y, n, y, n, y, n, y]", ArrayList.class);
}
public void testProjection02() {
// inline map creation not supported at the moment
// evaluate("#{'a':'y','b':'n','c':'y'}.!{value=='y'?key:null}.nonnull().sort()", "[a, c]", ArrayList.class);
evaluate("mapOfNumbersUpToTen.!{key>5?value:null}", "[null, null, null, null, null, six, seven, eight, nine, ten]", ArrayList.class);
}
public void testProjection05() {
evaluateAndCheckError("'abc'.!{true}", SpelMessages.PROJECTION_NOT_SUPPORTED_ON_TYPE);
}
public void testProjection06() throws Exception {
SpelExpression expr = (SpelExpression)parser.parseExpression("'abc'.!{true}");
assertEquals("'abc'.!{true}",expr.toStringAST());
assertFalse(expr.isWritable(new StandardEvaluationContext()));
}
public void testSelection02() {
evaluate("testMap.keySet().?{#this matches '.*o.*'}", "[monday]", ArrayList.class);
evaluate("testMap.keySet().?{#this matches '.*r.*'}.contains('saturday')", "true", Boolean.class);
evaluate("testMap.keySet().?{#this matches '.*r.*'}.size()", "3", Integer.class);
}
public void testSelectionError_NonBooleanSelectionCriteria() {
evaluateAndCheckError("listOfNumbersUpToTen.?{'nonboolean'}",
SpelMessages.RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN);
}
public void testSelection03() {
evaluate("mapOfNumbersUpToTen.?{key>5}.size()", "5", Integer.class);
}
public void testSelection04() {
evaluateAndCheckError("mapOfNumbersUpToTen.?{'hello'}.size()",SpelMessages.RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN);
}
public void testSelectionFirst01() {
evaluate("listOfNumbersUpToTen.^{#isEven(#this) == 'y'}", "2", Integer.class);
}
public void testSelectionFirst02() {
evaluate("mapOfNumbersUpToTen.^{key>5}.size()", "1", Integer.class);
}
public void testSelectionLast01() {
evaluate("listOfNumbersUpToTen.${#isEven(#this) == 'y'}", "10", Integer.class);
}
public void testSelectionLast02() {
evaluate("mapOfNumbersUpToTen.${key>5}.size()", "1", Integer.class);
}
public void testSelectionAST() throws Exception {
SpelExpression expr = (SpelExpression)parser.parseExpression("'abc'.^{true}");
assertEquals("'abc'.^{true}",expr.toStringAST());
assertFalse(expr.isWritable(new StandardEvaluationContext()));
expr = (SpelExpression)parser.parseExpression("'abc'.?{true}");
assertEquals("'abc'.?{true}",expr.toStringAST());
assertFalse(expr.isWritable(new StandardEvaluationContext()));
expr = (SpelExpression)parser.parseExpression("'abc'.${true}");
assertEquals("'abc'.${true}",expr.toStringAST());
assertFalse(expr.isWritable(new StandardEvaluationContext()));
}
}

View File

@ -26,6 +26,7 @@ import org.springframework.expression.ParseException;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.testresources.PlaceOfBirth;
/**
* Tests set value expressions.
*

View File

@ -0,0 +1,55 @@
/*
* Copyright 2004-2008 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.expression.spel;
import java.util.List;
import junit.framework.TestCase;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.spel.support.StandardTypeLocator;
/**
* Unit tests for type comparison
*
* @author Andy Clement
*/
public class StandardTypeLocatorTests extends TestCase {
public void testPrimitives() throws EvaluationException {
StandardTypeLocator locator = new StandardTypeLocator();
assertEquals(Integer.class,locator.findType("java.lang.Integer"));
assertEquals(String.class,locator.findType("java.lang.String"));
List<String> prefixes = locator.getImportPrefixes();
assertEquals(2,prefixes.size());
assertTrue(prefixes.contains("java.lang"));
assertTrue(prefixes.contains("java.util"));
assertEquals(Boolean.class,locator.findType("Boolean"));
assertEquals(java.util.List.class,locator.findType("List"));
try {
locator.findType("URL");
fail("Should have failed");
} catch (EvaluationException ee) {
SpelException sEx = (SpelException)ee;
assertEquals(SpelMessages.TYPE_NOT_FOUND,sEx.getMessageUnformatted());
}
locator.registerImport("java.net");
assertEquals(java.net.URL.class,locator.findType("URL"));
}
}

View File

@ -18,6 +18,7 @@ package org.springframework.expression.spel;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.antlr.SpelAntlrExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
@ -63,6 +64,21 @@ public class TemplateExpressionParsingTests extends ExpressionTestCase {
assertEquals("The quick brown fox jumped over the lazy dog", o.toString());
}
public void testParsingSimpleTemplateExpression04() throws Exception {
SpelAntlrExpressionParser parser = new SpelAntlrExpressionParser();
Expression expr = parser.parseExpression("${'hello'} world", DEFAULT_TEMPLATE_PARSER_CONTEXT);
Object o = expr.getValue();
assertEquals("hello world", o.toString());
expr = parser.parseExpression("", DEFAULT_TEMPLATE_PARSER_CONTEXT);
o = expr.getValue();
assertEquals("", o.toString());
expr = parser.parseExpression("abc", DEFAULT_TEMPLATE_PARSER_CONTEXT);
o = expr.getValue();
assertEquals("abc", o.toString());
}
public void testCompositeStringExpression() throws Exception {
SpelAntlrExpressionParser parser = new SpelAntlrExpressionParser();
Expression ex = parser.parseExpression("hello ${'world'}", DEFAULT_TEMPLATE_PARSER_CONTEXT);
@ -74,6 +90,36 @@ public class TemplateExpressionParsingTests extends ExpressionTestCase {
assertEquals("hello ${'world'}", ex.getExpressionString());
assertFalse(ex.isWritable(new StandardEvaluationContext()));
}
public void testParsingNormalExpressionThroughTemplateParser() throws Exception {
Expression expr = parser.parseExpression("1+2+3");
assertEquals(6,expr.getValue());
expr = parser.parseExpression("1+2+3",null);
assertEquals(6,expr.getValue());
}
public void testErrorCases() throws Exception {
try {
parser.parseExpression("hello ${'world'", DEFAULT_TEMPLATE_PARSER_CONTEXT);
fail("Should have failed");
} catch (ParseException pe) {
assertEquals("No ending suffix '}' for expression starting at character 6: ${'world'",pe.getMessage());
assertEquals("hello ${'world'",pe.getExpressionString());
}
try {
parser.parseExpression("hello ${'wibble'${'world'}", DEFAULT_TEMPLATE_PARSER_CONTEXT);
fail("Should have failed");
} catch (ParseException pe) {
assertEquals("No ending suffix '}' for expression starting at character 6: ${'wibble'${'world'}",pe.getMessage());
}
try {
parser.parseExpression("hello ${} world", DEFAULT_TEMPLATE_PARSER_CONTEXT);
fail("Should have failed");
} catch (ParseException pe) {
assertEquals("No expression defined within delimiter '${}' at character 6",pe.getMessage());
}
}
private void checkString(String expectedString, Object value) {
if (!(value instanceof String)) {