|
|
|
@ -1,5 +1,5 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
* Copyright 2002-2016 the original author or authors. |
|
|
|
* Copyright 2002-2018 the original author or authors. |
|
|
|
* |
|
|
|
* |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -16,7 +16,6 @@ |
|
|
|
|
|
|
|
|
|
|
|
package org.springframework.expression.spel; |
|
|
|
package org.springframework.expression.spel; |
|
|
|
|
|
|
|
|
|
|
|
import java.util.EmptyStackException; |
|
|
|
|
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
|
|
|
|
@ -36,6 +35,7 @@ import static org.junit.Assert.*; |
|
|
|
* Tests for the expression state object - some features are not yet exploited in the language (eg nested scopes) |
|
|
|
* Tests for the expression state object - some features are not yet exploited in the language (eg nested scopes) |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Andy Clement |
|
|
|
* @author Andy Clement |
|
|
|
|
|
|
|
* @author Juergen Hoeller |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class ExpressionStateTests extends AbstractExpressionTests { |
|
|
|
public class ExpressionStateTests extends AbstractExpressionTests { |
|
|
|
|
|
|
|
|
|
|
|
@ -43,7 +43,7 @@ public class ExpressionStateTests extends AbstractExpressionTests { |
|
|
|
public void testConstruction() { |
|
|
|
public void testConstruction() { |
|
|
|
EvaluationContext context = TestScenarioCreator.getTestEvaluationContext(); |
|
|
|
EvaluationContext context = TestScenarioCreator.getTestEvaluationContext(); |
|
|
|
ExpressionState state = new ExpressionState(context); |
|
|
|
ExpressionState state = new ExpressionState(context); |
|
|
|
assertEquals(context,state.getEvaluationContext()); |
|
|
|
assertEquals(context, state.getEvaluationContext()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Local variables are in variable scopes which come and go during evaluation. Normal variables are
|
|
|
|
// Local variables are in variable scopes which come and go during evaluation. Normal variables are
|
|
|
|
@ -58,107 +58,107 @@ public class ExpressionStateTests extends AbstractExpressionTests { |
|
|
|
|
|
|
|
|
|
|
|
state.setLocalVariable("foo",34); |
|
|
|
state.setLocalVariable("foo",34); |
|
|
|
value = state.lookupLocalVariable("foo"); |
|
|
|
value = state.lookupLocalVariable("foo"); |
|
|
|
assertEquals(34,value); |
|
|
|
assertEquals(34, value); |
|
|
|
|
|
|
|
|
|
|
|
state.setLocalVariable("foo",null); |
|
|
|
state.setLocalVariable("foo", null); |
|
|
|
value = state.lookupLocalVariable("foo"); |
|
|
|
value = state.lookupLocalVariable("foo"); |
|
|
|
assertEquals(null,value); |
|
|
|
assertEquals(null, value); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testVariables() { |
|
|
|
public void testVariables() { |
|
|
|
ExpressionState state = getState(); |
|
|
|
ExpressionState state = getState(); |
|
|
|
TypedValue typedValue = state.lookupVariable("foo"); |
|
|
|
TypedValue typedValue = state.lookupVariable("foo"); |
|
|
|
assertEquals(TypedValue.NULL,typedValue); |
|
|
|
assertEquals(TypedValue.NULL, typedValue); |
|
|
|
|
|
|
|
|
|
|
|
state.setVariable("foo",34); |
|
|
|
state.setVariable("foo",34); |
|
|
|
typedValue = state.lookupVariable("foo"); |
|
|
|
typedValue = state.lookupVariable("foo"); |
|
|
|
assertEquals(34,typedValue.getValue()); |
|
|
|
assertEquals(34, typedValue.getValue()); |
|
|
|
assertEquals(Integer.class,typedValue.getTypeDescriptor().getType()); |
|
|
|
assertEquals(Integer.class, typedValue.getTypeDescriptor().getType()); |
|
|
|
|
|
|
|
|
|
|
|
state.setVariable("foo","abc"); |
|
|
|
state.setVariable("foo","abc"); |
|
|
|
typedValue = state.lookupVariable("foo"); |
|
|
|
typedValue = state.lookupVariable("foo"); |
|
|
|
assertEquals("abc",typedValue.getValue()); |
|
|
|
assertEquals("abc", typedValue.getValue()); |
|
|
|
assertEquals(String.class,typedValue.getTypeDescriptor().getType()); |
|
|
|
assertEquals(String.class, typedValue.getTypeDescriptor().getType()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testNoVariableInteference() { |
|
|
|
public void testNoVariableInteference() { |
|
|
|
ExpressionState state = getState(); |
|
|
|
ExpressionState state = getState(); |
|
|
|
TypedValue typedValue = state.lookupVariable("foo"); |
|
|
|
TypedValue typedValue = state.lookupVariable("foo"); |
|
|
|
assertEquals(TypedValue.NULL,typedValue); |
|
|
|
assertEquals(TypedValue.NULL, typedValue); |
|
|
|
|
|
|
|
|
|
|
|
state.setLocalVariable("foo",34); |
|
|
|
state.setLocalVariable("foo",34); |
|
|
|
typedValue = state.lookupVariable("foo"); |
|
|
|
typedValue = state.lookupVariable("foo"); |
|
|
|
assertEquals(TypedValue.NULL,typedValue); |
|
|
|
assertEquals(TypedValue.NULL, typedValue); |
|
|
|
|
|
|
|
|
|
|
|
state.setVariable("goo","hello"); |
|
|
|
state.setVariable("goo", "hello"); |
|
|
|
assertNull(state.lookupLocalVariable("goo")); |
|
|
|
assertNull(state.lookupLocalVariable("goo")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testLocalVariableNestedScopes() { |
|
|
|
public void testLocalVariableNestedScopes() { |
|
|
|
ExpressionState state = getState(); |
|
|
|
ExpressionState state = getState(); |
|
|
|
assertEquals(null,state.lookupLocalVariable("foo")); |
|
|
|
assertEquals(null, state.lookupLocalVariable("foo")); |
|
|
|
|
|
|
|
|
|
|
|
state.setLocalVariable("foo",12); |
|
|
|
state.setLocalVariable("foo",12); |
|
|
|
assertEquals(12,state.lookupLocalVariable("foo")); |
|
|
|
assertEquals(12, state.lookupLocalVariable("foo")); |
|
|
|
|
|
|
|
|
|
|
|
state.enterScope(null); |
|
|
|
state.enterScope(null); |
|
|
|
assertEquals(12,state.lookupLocalVariable("foo")); // found in upper scope
|
|
|
|
assertEquals(12, state.lookupLocalVariable("foo")); // found in upper scope
|
|
|
|
|
|
|
|
|
|
|
|
state.setLocalVariable("foo","abc"); |
|
|
|
state.setLocalVariable("foo","abc"); |
|
|
|
assertEquals("abc",state.lookupLocalVariable("foo")); // found in nested scope
|
|
|
|
assertEquals("abc", state.lookupLocalVariable("foo")); // found in nested scope
|
|
|
|
|
|
|
|
|
|
|
|
state.exitScope(); |
|
|
|
state.exitScope(); |
|
|
|
assertEquals(12,state.lookupLocalVariable("foo")); // found in nested scope
|
|
|
|
assertEquals(12, state.lookupLocalVariable("foo")); // found in nested scope
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testRootContextObject() { |
|
|
|
public void testRootContextObject() { |
|
|
|
ExpressionState state = getState(); |
|
|
|
ExpressionState state = getState(); |
|
|
|
assertEquals(Inventor.class,state.getRootContextObject().getValue().getClass()); |
|
|
|
assertEquals(Inventor.class, state.getRootContextObject().getValue().getClass()); |
|
|
|
|
|
|
|
|
|
|
|
// although the root object is being set on the evaluation context, the value in the 'state' remains what it was when constructed
|
|
|
|
// although the root object is being set on the evaluation context, the value in the 'state' remains what it was when constructed
|
|
|
|
((StandardEvaluationContext) state.getEvaluationContext()).setRootObject(null); |
|
|
|
((StandardEvaluationContext) state.getEvaluationContext()).setRootObject(null); |
|
|
|
assertEquals(Inventor.class,state.getRootContextObject().getValue().getClass()); |
|
|
|
assertEquals(Inventor.class, state.getRootContextObject().getValue().getClass()); |
|
|
|
// assertEquals(null, state.getRootContextObject().getValue());
|
|
|
|
// assertEquals(null, state.getRootContextObject().getValue());
|
|
|
|
|
|
|
|
|
|
|
|
state = new ExpressionState(new StandardEvaluationContext()); |
|
|
|
state = new ExpressionState(new StandardEvaluationContext()); |
|
|
|
assertEquals(TypedValue.NULL,state.getRootContextObject()); |
|
|
|
assertEquals(TypedValue.NULL, state.getRootContextObject()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
((StandardEvaluationContext)state.getEvaluationContext()).setRootObject(null); |
|
|
|
((StandardEvaluationContext) state.getEvaluationContext()).setRootObject(null); |
|
|
|
assertEquals(null,state.getRootContextObject().getValue()); |
|
|
|
assertEquals(null, state.getRootContextObject().getValue()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testActiveContextObject() { |
|
|
|
public void testActiveContextObject() { |
|
|
|
ExpressionState state = getState(); |
|
|
|
ExpressionState state = getState(); |
|
|
|
assertEquals(state.getRootContextObject().getValue(),state.getActiveContextObject().getValue()); |
|
|
|
assertEquals(state.getRootContextObject().getValue(), state.getActiveContextObject().getValue()); |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
state.popActiveContextObject(); |
|
|
|
state.popActiveContextObject(); |
|
|
|
fail("stack should be empty..."); |
|
|
|
fail("stack should be empty..."); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (EmptyStackException ese) { |
|
|
|
catch (IllegalStateException ese) { |
|
|
|
// success
|
|
|
|
// success
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
state.pushActiveContextObject(new TypedValue(34)); |
|
|
|
state.pushActiveContextObject(new TypedValue(34)); |
|
|
|
assertEquals(34,state.getActiveContextObject().getValue()); |
|
|
|
assertEquals(34, state.getActiveContextObject().getValue()); |
|
|
|
|
|
|
|
|
|
|
|
state.pushActiveContextObject(new TypedValue("hello")); |
|
|
|
state.pushActiveContextObject(new TypedValue("hello")); |
|
|
|
assertEquals("hello",state.getActiveContextObject().getValue()); |
|
|
|
assertEquals("hello", state.getActiveContextObject().getValue()); |
|
|
|
|
|
|
|
|
|
|
|
state.popActiveContextObject(); |
|
|
|
state.popActiveContextObject(); |
|
|
|
assertEquals(34,state.getActiveContextObject().getValue()); |
|
|
|
assertEquals(34, state.getActiveContextObject().getValue()); |
|
|
|
|
|
|
|
|
|
|
|
state.popActiveContextObject(); |
|
|
|
state.popActiveContextObject(); |
|
|
|
assertEquals(state.getRootContextObject().getValue(),state.getActiveContextObject().getValue()); |
|
|
|
assertEquals(state.getRootContextObject().getValue(), state.getActiveContextObject().getValue()); |
|
|
|
|
|
|
|
|
|
|
|
state = new ExpressionState(new StandardEvaluationContext()); |
|
|
|
state = new ExpressionState(new StandardEvaluationContext()); |
|
|
|
assertEquals(TypedValue.NULL,state.getActiveContextObject()); |
|
|
|
assertEquals(TypedValue.NULL, state.getActiveContextObject()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
@ -167,14 +167,14 @@ public class ExpressionStateTests extends AbstractExpressionTests { |
|
|
|
assertNull(state.lookupLocalVariable("foo")); |
|
|
|
assertNull(state.lookupLocalVariable("foo")); |
|
|
|
|
|
|
|
|
|
|
|
state.enterScope("foo",34); |
|
|
|
state.enterScope("foo",34); |
|
|
|
assertEquals(34,state.lookupLocalVariable("foo")); |
|
|
|
assertEquals(34, state.lookupLocalVariable("foo")); |
|
|
|
|
|
|
|
|
|
|
|
state.enterScope(null); |
|
|
|
state.enterScope(null); |
|
|
|
state.setLocalVariable("foo",12); |
|
|
|
state.setLocalVariable("foo", 12); |
|
|
|
assertEquals(12,state.lookupLocalVariable("foo")); |
|
|
|
assertEquals(12, state.lookupLocalVariable("foo")); |
|
|
|
|
|
|
|
|
|
|
|
state.exitScope(); |
|
|
|
state.exitScope(); |
|
|
|
assertEquals(34,state.lookupLocalVariable("foo")); |
|
|
|
assertEquals(34, state.lookupLocalVariable("foo")); |
|
|
|
|
|
|
|
|
|
|
|
state.exitScope(); |
|
|
|
state.exitScope(); |
|
|
|
assertNull(state.lookupLocalVariable("goo")); |
|
|
|
assertNull(state.lookupLocalVariable("goo")); |
|
|
|
@ -187,8 +187,8 @@ public class ExpressionStateTests extends AbstractExpressionTests { |
|
|
|
// supplied should override root on context
|
|
|
|
// supplied should override root on context
|
|
|
|
ExpressionState state = new ExpressionState(ctx,new TypedValue("i am a string")); |
|
|
|
ExpressionState state = new ExpressionState(ctx,new TypedValue("i am a string")); |
|
|
|
TypedValue stateRoot = state.getRootContextObject(); |
|
|
|
TypedValue stateRoot = state.getRootContextObject(); |
|
|
|
assertEquals(String.class,stateRoot.getTypeDescriptor().getType()); |
|
|
|
assertEquals(String.class, stateRoot.getTypeDescriptor().getType()); |
|
|
|
assertEquals("i am a string",stateRoot.getValue()); |
|
|
|
assertEquals("i am a string", stateRoot.getValue()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
@ -198,17 +198,17 @@ public class ExpressionStateTests extends AbstractExpressionTests { |
|
|
|
assertNull(state.lookupLocalVariable("goo")); |
|
|
|
assertNull(state.lookupLocalVariable("goo")); |
|
|
|
|
|
|
|
|
|
|
|
Map<String,Object> m = new HashMap<>(); |
|
|
|
Map<String,Object> m = new HashMap<>(); |
|
|
|
m.put("foo",34); |
|
|
|
m.put("foo", 34); |
|
|
|
m.put("goo","abc"); |
|
|
|
m.put("goo", "abc"); |
|
|
|
|
|
|
|
|
|
|
|
state.enterScope(m); |
|
|
|
state.enterScope(m); |
|
|
|
assertEquals(34,state.lookupLocalVariable("foo")); |
|
|
|
assertEquals(34, state.lookupLocalVariable("foo")); |
|
|
|
assertEquals("abc",state.lookupLocalVariable("goo")); |
|
|
|
assertEquals("abc", state.lookupLocalVariable("goo")); |
|
|
|
|
|
|
|
|
|
|
|
state.enterScope(null); |
|
|
|
state.enterScope(null); |
|
|
|
state.setLocalVariable("foo",12); |
|
|
|
state.setLocalVariable("foo",12); |
|
|
|
assertEquals(12,state.lookupLocalVariable("foo")); |
|
|
|
assertEquals(12, state.lookupLocalVariable("foo")); |
|
|
|
assertEquals("abc",state.lookupLocalVariable("goo")); |
|
|
|
assertEquals("abc", state.lookupLocalVariable("goo")); |
|
|
|
|
|
|
|
|
|
|
|
state.exitScope(); |
|
|
|
state.exitScope(); |
|
|
|
state.exitScope(); |
|
|
|
state.exitScope(); |
|
|
|
@ -217,7 +217,7 @@ public class ExpressionStateTests extends AbstractExpressionTests { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testOperators() throws Exception { |
|
|
|
public void testOperators() { |
|
|
|
ExpressionState state = getState(); |
|
|
|
ExpressionState state = getState(); |
|
|
|
try { |
|
|
|
try { |
|
|
|
state.operate(Operation.ADD,1,2); |
|
|
|
state.operate(Operation.ADD,1,2); |
|
|
|
@ -225,7 +225,7 @@ public class ExpressionStateTests extends AbstractExpressionTests { |
|
|
|
} |
|
|
|
} |
|
|
|
catch (EvaluationException ee) { |
|
|
|
catch (EvaluationException ee) { |
|
|
|
SpelEvaluationException sEx = (SpelEvaluationException)ee; |
|
|
|
SpelEvaluationException sEx = (SpelEvaluationException)ee; |
|
|
|
assertEquals(SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES,sEx.getMessageCode()); |
|
|
|
assertEquals(SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES, sEx.getMessageCode()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
@ -234,28 +234,28 @@ public class ExpressionStateTests extends AbstractExpressionTests { |
|
|
|
} |
|
|
|
} |
|
|
|
catch (EvaluationException ee) { |
|
|
|
catch (EvaluationException ee) { |
|
|
|
SpelEvaluationException sEx = (SpelEvaluationException)ee; |
|
|
|
SpelEvaluationException sEx = (SpelEvaluationException)ee; |
|
|
|
assertEquals(SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES,sEx.getMessageCode()); |
|
|
|
assertEquals(SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES, sEx.getMessageCode()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testComparator() { |
|
|
|
public void testComparator() { |
|
|
|
ExpressionState state = getState(); |
|
|
|
ExpressionState state = getState(); |
|
|
|
assertEquals(state.getEvaluationContext().getTypeComparator(),state.getTypeComparator()); |
|
|
|
assertEquals(state.getEvaluationContext().getTypeComparator(), state.getTypeComparator()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testTypeLocator() throws EvaluationException { |
|
|
|
public void testTypeLocator() throws EvaluationException { |
|
|
|
ExpressionState state = getState(); |
|
|
|
ExpressionState state = getState(); |
|
|
|
assertNotNull(state.getEvaluationContext().getTypeLocator()); |
|
|
|
assertNotNull(state.getEvaluationContext().getTypeLocator()); |
|
|
|
assertEquals(Integer.class,state.findType("java.lang.Integer")); |
|
|
|
assertEquals(Integer.class, state.findType("java.lang.Integer")); |
|
|
|
try { |
|
|
|
try { |
|
|
|
state.findType("someMadeUpName"); |
|
|
|
state.findType("someMadeUpName"); |
|
|
|
fail("Should have failed to find it"); |
|
|
|
fail("Should have failed to find it"); |
|
|
|
} |
|
|
|
} |
|
|
|
catch (EvaluationException ee) { |
|
|
|
catch (EvaluationException ee) { |
|
|
|
SpelEvaluationException sEx = (SpelEvaluationException)ee; |
|
|
|
SpelEvaluationException sEx = (SpelEvaluationException)ee; |
|
|
|
assertEquals(SpelMessage.TYPE_NOT_FOUND,sEx.getMessageCode()); |
|
|
|
assertEquals(SpelMessage.TYPE_NOT_FOUND, sEx.getMessageCode()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -263,16 +263,16 @@ public class ExpressionStateTests extends AbstractExpressionTests { |
|
|
|
public void testTypeConversion() throws EvaluationException { |
|
|
|
public void testTypeConversion() throws EvaluationException { |
|
|
|
ExpressionState state = getState(); |
|
|
|
ExpressionState state = getState(); |
|
|
|
String s = (String) state.convertValue(34, TypeDescriptor.valueOf(String.class)); |
|
|
|
String s = (String) state.convertValue(34, TypeDescriptor.valueOf(String.class)); |
|
|
|
assertEquals("34",s); |
|
|
|
assertEquals("34", s); |
|
|
|
|
|
|
|
|
|
|
|
s = (String)state.convertValue(new TypedValue(34), TypeDescriptor.valueOf(String.class)); |
|
|
|
s = (String)state.convertValue(new TypedValue(34), TypeDescriptor.valueOf(String.class)); |
|
|
|
assertEquals("34",s); |
|
|
|
assertEquals("34", s); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
@Test |
|
|
|
public void testPropertyAccessors() { |
|
|
|
public void testPropertyAccessors() { |
|
|
|
ExpressionState state = getState(); |
|
|
|
ExpressionState state = getState(); |
|
|
|
assertEquals(state.getEvaluationContext().getPropertyAccessors(),state.getPropertyAccessors()); |
|
|
|
assertEquals(state.getEvaluationContext().getPropertyAccessors(), state.getPropertyAccessors()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
|