diff --git a/spring-binding/src/main/java/org/springframework/binding/convert/support/TextToExpression.java b/spring-binding/src/main/java/org/springframework/binding/convert/support/TextToExpression.java
index 747c3d87..cad1e67b 100644
--- a/spring-binding/src/main/java/org/springframework/binding/convert/support/TextToExpression.java
+++ b/spring-binding/src/main/java/org/springframework/binding/convert/support/TextToExpression.java
@@ -60,6 +60,6 @@ public class TextToExpression extends AbstractConverter {
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
String expressionString = (String) source;
- return expressionParser.parseExpression(expressionString, Object.class, Object.class, null);
+ return expressionParser.parseExpression(expressionString, null);
}
}
\ No newline at end of file
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/EvaluationAttempt.java b/spring-binding/src/main/java/org/springframework/binding/expression/EvaluationAttempt.java
index 76777a2e..dc95d4a2 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/EvaluationAttempt.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/EvaluationAttempt.java
@@ -18,44 +18,37 @@ package org.springframework.binding.expression;
import org.springframework.core.style.ToStringCreator;
/**
- * A simple holder for information about an evaluation attempt.
+ * A simple holder for information about an expression evaluation attempt.
*
* @author Keith Donald
*/
public class EvaluationAttempt {
- /**
- * The expression that attempted to evaluate.
- */
private Expression expression;
-
- /**
- * The target object being evaluated.
- */
- private Object target;
+ private Object context;
/**
* Create an evaluation attempt.
* @param expression the expression that failed to evaluate
- * @param target the target of the expression
+ * @param context the context of the expression evaluation
*/
- public EvaluationAttempt(Expression expression, Object target) {
+ public EvaluationAttempt(Expression expression, Object context) {
this.expression = expression;
- this.target = target;
+ this.context = context;
}
/**
- * Returns the expression that attempted to evaluate.
+ * Returns the expression that attempted an evaluation.
*/
public Expression getExpression() {
return expression;
}
/**
- * Returns the target object upon which evaluation was attempted.
+ * Returns the context object in which expression evaluation was attempted.
*/
- public Object getTarget() {
- return target;
+ public Object getContext() {
+ return context;
}
public String toString() {
@@ -63,6 +56,6 @@ public class EvaluationAttempt {
}
protected ToStringCreator createToString(ToStringCreator creator) {
- return creator.append("expression", expression).append("target", target);
+ return creator.append("expression", expression).append("context", context);
}
}
\ No newline at end of file
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/EvaluationException.java b/spring-binding/src/main/java/org/springframework/binding/expression/EvaluationException.java
index bde5e58b..14cc817a 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/EvaluationException.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/EvaluationException.java
@@ -36,7 +36,7 @@ public class EvaluationException extends NestedRuntimeException {
*/
public EvaluationException(EvaluationAttempt evaluationAttempt, Throwable cause) {
super("Expression " + evaluationAttempt
- + " failed - make sure the expression is evaluatable on the target object", cause);
+ + " failed - make sure the expression is evaluatable in the context provided", cause);
this.evaluationAttempt = evaluationAttempt;
}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/Expression.java b/spring-binding/src/main/java/org/springframework/binding/expression/Expression.java
index e98e32d6..bf6fcb6d 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/Expression.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/Expression.java
@@ -24,19 +24,18 @@ package org.springframework.binding.expression;
public interface Expression {
/**
- * Evaluate the expression encapsulated by this evaluator against the provided target object and return the result
- * of the evaluation.
- * @param target the target of the expression
+ * Evaluate this expression in the provided context and return the result of evaluation.
+ * @param context the context to evaluate this expression in
* @return the evaluation result
* @throws EvaluationException an exception occured during evaluation
*/
- public Object getValue(Object target) throws EvaluationException;
+ public Object getValue(Object context) throws EvaluationException;
/**
- * Evaluate this expression against the target object to set its value to the value provided.
- * @param target the target object
+ * Set this expression in the provided context to the value provided.
+ * @param context the context to apply this value to
* @param value the new value to be set
* @throws EvaluationException an exception occurred during evaluation
*/
- public void setValue(Object target, Object value) throws EvaluationException;
+ public void setValue(Object context, Object value) throws EvaluationException;
}
\ No newline at end of file
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionParser.java
index d14367cf..14f69011 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionParser.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionParser.java
@@ -24,30 +24,20 @@ package org.springframework.binding.expression;
public interface ExpressionParser {
/**
- * Is the provided expression string an "eval" expression: meaning an expression that validates to a dynamic value,
- * and not a literal expression? "Eval" expressions are normally enclosed in delimiters like #{}, where literal
- * expressions are not delimited.
- *
- * TODO - candidate for removal in a future milestone: is this really needed?
+ * Is the provided string an explicitly delimited expression this parser knows how to parse? For example, this
+ * method might return true if the string provided is enclosed in ${}.
* @param string the string
- * @return true if the expression is an eval expression string, false otherwise.
+ * @return true if the string is a delimited expression, false otherwise.
*/
- public boolean isEvalExpressionString(String string);
-
+ public boolean isDelimitedExpression(String string);
+
/**
* Parse the provided expression string, returning an expression evaluator capable of evaluating it.
- * @param expressionString the parseable expression string; cannot be null
- * @param expressionTargetType the class of target object this expression can successfully evaluate; for example,
- * Map.class for an expression that is expected to evaluate against Maps.
- * @param expectedEvaluationResultType the class of object this expression is expected to return or set: for
- * example, Boolean.class for an expression that is expected to get or set a boolean value. Typically
- * used to facilitate type conversion by the expression evaluator; for example, if a evaluated expression equates to
- * a String value 'true', with an expected Boolean result the string value could be converted to a typed Boolean
- * value (required). If the type of the evaluation result cannot be determined, use Object.class.
- * @param expressionVariables variables providing aliases for this expression during evaluation (optional).
+ * @param expressionString the parseable expression string; cannot be null (required)
+ * @param context a context used to set attributes that influence expression parsing routine (optional)
* @return the evaluator for the parsed expression
* @throws ParserException an exception occurred during parsing
*/
- public Expression parseExpression(String expressionString, Class expressionTargetType,
- Class expectedEvaluationResultType, ExpressionVariable[] expressionVariables) throws ParserException;
+ public Expression parseExpression(String expressionString, ParserContext context) throws ParserException;
+
}
\ No newline at end of file
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionVariable.java b/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionVariable.java
index 23340df3..840409b9 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionVariable.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/ExpressionVariable.java
@@ -9,17 +9,15 @@ import org.springframework.util.Assert;
public class ExpressionVariable {
private String name;
-
- private String value;
+ private Object value;
/**
* Creates a new expression variable
* @param name the name of the variable, acting as an convenient alias
* @param value the initial value of the variable
*/
- public ExpressionVariable(String name, String value) {
+ public ExpressionVariable(String name, Object value) {
Assert.hasText(name, "The expression variable must be named");
- Assert.hasText(value, "The expression variable value is required");
this.name = name;
this.value = value;
}
@@ -36,7 +34,7 @@ public class ExpressionVariable {
* Returns the expression that will be evaluated when the variable is referenced by its name in another expression.
* @return the expression value.
*/
- public String getValue() {
+ public Object getValue() {
return value;
}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ParserContext.java b/spring-binding/src/main/java/org/springframework/binding/expression/ParserContext.java
new file mode 100644
index 00000000..3810eb9c
--- /dev/null
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/ParserContext.java
@@ -0,0 +1,28 @@
+package org.springframework.binding.expression;
+
+/**
+ * Input provided to an expression parser that can influence an expression parsing/compilation routine.
+ * @author Keith Donald
+ */
+public interface ParserContext {
+
+ /**
+ * Returns the type of context object the parsed expression will evaluate in. An expression parser may use this
+ * value to install custom variable resolves for that particular type of context.
+ * @return the evaluation context type
+ */
+ public Class getEvaluationContextType();
+
+ /**
+ * Returns the expected type of object returned from evaluating the parsed expression. An expression parser may use
+ * this value to coerce an raw evaluation result before it is returned.
+ * @return the expected evaluation result type
+ */
+ public Class getExpectedEvaluationResultType();
+
+ /**
+ * Returns additional expression variables or aliases that can be referenced during expression evaluation. An
+ * expression parser will register these variables for reference during evaluation.
+ */
+ public ExpressionVariable[] getExpressionVariables();
+}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/SetValueAttempt.java b/spring-binding/src/main/java/org/springframework/binding/expression/SetValueAttempt.java
index 24eabe4b..ebabcecd 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/SetValueAttempt.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/SetValueAttempt.java
@@ -32,11 +32,11 @@ public class SetValueAttempt extends EvaluationAttempt {
/**
* Creates a new set attempt.
* @param expression the settable expression
- * @param target the target of the expression
+ * @param context the target of the expression
* @param value the value that was attempted to be set
*/
- public SetValueAttempt(Expression expression, Object target, Object value) {
- super(expression, target);
+ public SetValueAttempt(Expression expression, Object context, Object value) {
+ super(expression, context);
this.value = value;
}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/el/DefaultELContext.java b/spring-binding/src/main/java/org/springframework/binding/expression/el/DefaultELContext.java
new file mode 100644
index 00000000..3626f0c5
--- /dev/null
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/el/DefaultELContext.java
@@ -0,0 +1,38 @@
+package org.springframework.binding.expression.el;
+
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.FunctionMapper;
+import javax.el.VariableMapper;
+
+public class DefaultELContext extends ELContext {
+
+ private VariableMapper variableMapper;
+
+ private ELResolver resolver;
+
+ private FunctionMapper functionMapper;
+
+ public DefaultELContext(ELResolver resolver, VariableMapper variableMapper, FunctionMapper functionMapper) {
+ this.resolver = resolver;
+ this.variableMapper = variableMapper;
+ this.functionMapper = functionMapper;
+ }
+
+ public static ELContext createDefaultELContext() {
+ return new DefaultELContext(new DefaultELResolver(null, null), null, null);
+ }
+
+ public ELResolver getELResolver() {
+ return resolver;
+ }
+
+ public VariableMapper getVariableMapper() {
+ return variableMapper;
+ }
+
+ public FunctionMapper getFunctionMapper() {
+ return functionMapper;
+ }
+
+}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/el/DefaultElContextFactory.java b/spring-binding/src/main/java/org/springframework/binding/expression/el/DefaultElContextFactory.java
new file mode 100644
index 00000000..a19b748b
--- /dev/null
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/el/DefaultElContextFactory.java
@@ -0,0 +1,10 @@
+package org.springframework.binding.expression.el;
+
+import javax.el.ELContext;
+import javax.el.VariableMapper;
+
+public class DefaultElContextFactory implements ELContextFactory {
+ public ELContext getELContext(Object target, VariableMapper variableMapper) {
+ return new DefaultELContext(new DefaultELResolver(target, null), variableMapper, null);
+ }
+}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpression.java b/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpression.java
index 0edddb6a..1aeea15d 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpression.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpression.java
@@ -37,21 +37,21 @@ public class ELExpression implements Expression {
this.variableMapper = variableMapper;
}
- public Object getValue(Object target) throws EvaluationException {
- ELContext ctx = elContextFactory.getELContext(target, variableMapper);
+ public Object getValue(Object context) throws EvaluationException {
+ ELContext ctx = elContextFactory.getELContext(context, variableMapper);
try {
return valueExpression.getValue(ctx);
} catch (ELException ex) {
- throw new EvaluationException(new EvaluationAttempt(this, target), ex);
+ throw new EvaluationException(new EvaluationAttempt(this, context), ex);
}
}
- public void setValue(Object target, Object value) throws EvaluationException {
- ELContext ctx = elContextFactory.getELContext(target, variableMapper);
+ public void setValue(Object context, Object value) throws EvaluationException {
+ ELContext ctx = elContextFactory.getELContext(context, variableMapper);
try {
valueExpression.setValue(ctx, value);
} catch (ELException ex) {
- throw new EvaluationException(new EvaluationAttempt(this, target), ex);
+ throw new EvaluationException(new EvaluationAttempt(this, context), ex);
}
}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpressionParser.java
index b9b569cf..bca56b1f 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpressionParser.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/el/ELExpressionParser.java
@@ -14,18 +14,27 @@ import javax.el.VariableMapper;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.binding.expression.ExpressionVariable;
+import org.springframework.binding.expression.ParserContext;
import org.springframework.binding.expression.ParserException;
+import org.springframework.binding.expression.support.NullParserContext;
+import org.springframework.util.Assert;
/**
* An expression parser that parses EL expressions.
* @author Jeremy Grelle
+ * @author Keith Donald
*/
public class ELExpressionParser implements ExpressionParser {
/**
* The expression prefix.
*/
- private static final String EXPRESSION_PREFIX = "#{";
+ private static final String EXPRESSION_PREFIX_IMMEDIATE = "${";
+
+ /**
+ * The expression prefix.
+ */
+ private static final String EXPRESSION_PREFIX_DEFERRED = "#{";
/**
* The expression suffix.
@@ -43,47 +52,63 @@ public class ELExpressionParser implements ExpressionParser {
* Creates a new EL expression parser for standalone usage.
*/
public ELExpressionParser(ExpressionFactory expressionFactory) {
- this.expressionFactory = expressionFactory;
+ init(expressionFactory);
}
/**
- * Register the ELContextFactory for expressions that evaluate the given class of target object.
- * @param expressionTargetType the expression target class
- * @param contextFactory the context factory to use for expressions that evaluate those types of targets
+ * Register the ELContextFactory for expressions that evaluate the given class of context object.
+ * @param contextType the expression context class
+ * @param contextFactory the context factory to use for expressions that evaluate those types of contexts
*/
- public void putContextFactory(Class expressionTargetType, ELContextFactory contextFactory) {
- this.contextFactories.put(expressionTargetType, contextFactory);
+ public void putContextFactory(Class contextType, ELContextFactory contextFactory) {
+ Assert.notNull(contextFactory, "The EL context factory cannot be null");
+ contextFactories.put(contextType, contextFactory);
}
- public boolean isEvalExpressionString(String expressionString) {
- return expressionString.startsWith(EXPRESSION_PREFIX) && expressionString.endsWith(EXPRESSION_SUFFIX);
+ public boolean isDelimitedExpression(String expressionString) {
+ return (expressionString.startsWith(EXPRESSION_PREFIX_DEFERRED) && expressionString.endsWith(EXPRESSION_SUFFIX))
+ || (expressionString.startsWith(EXPRESSION_PREFIX_IMMEDIATE) && expressionString
+ .endsWith(EXPRESSION_SUFFIX));
}
- public Expression parseExpression(String expressionString, Class expressionTargetType,
- Class expectedEvaluationResultType, ExpressionVariable[] expressionVariables) throws ParserException {
- if (expectedEvaluationResultType == null) {
- throw new ParserException(expressionString, "The 'expectedEvaluationResultType' argument is required; "
- + "specify Object.class if the type is unknown", new NullPointerException());
+ public Expression parseExpression(String expressionString, ParserContext context) throws ParserException {
+ if (context == null) {
+ context = NullParserContext.INSTANCE;
}
try {
- ParserELContext context = new ParserELContext();
- context.mapVariables(expressionVariables, expressionFactory);
- ValueExpression expression = expressionFactory.createValueExpression(context, expressionString,
- expectedEvaluationResultType);
- ELContextFactory contextFactory = getContextFactory(expressionTargetType, expressionString);
- return new ELExpression(contextFactory, expression, context.getVariableMapper());
- } catch (ELException ex) {
- throw new ParserException(expressionString, ex);
+ ParserELContext elContext = new ParserELContext();
+ elContext.mapVariables(context.getExpressionVariables(), expressionFactory);
+ ValueExpression expression = expressionFactory.createValueExpression(elContext, expressionString,
+ getExpectedType(context));
+ ELContextFactory contextFactory = getContextFactory(context.getEvaluationContextType(), expressionString);
+ return new ELExpression(contextFactory, expression, elContext.getVariableMapper());
+ } catch (ELException e) {
+ throw new ParserException(expressionString, e);
+ }
+ }
+
+ private Class getExpectedType(ParserContext context) {
+ Class expectedType = context.getExpectedEvaluationResultType();
+ if (expectedType != null) {
+ return expectedType;
+ } else {
+ return Object.class;
}
}
private ELContextFactory getContextFactory(Class expressionTargetType, String expressionString) {
- if (!contextFactories.containsKey(expressionTargetType)) {
- throw new ParserException(expressionString, new IllegalArgumentException(
- "No ELContextFactory registered for expressionTargetType [" + expressionTargetType + "]; "
- + "Please ensure a factory is registered for this type."));
+ if (contextFactories.containsKey(expressionTargetType)) {
+ return (ELContextFactory) contextFactories.get(expressionTargetType);
+ } else {
+ return (ELContextFactory) contextFactories.get(Object.class);
}
- return (ELContextFactory) contextFactories.get(expressionTargetType);
+ }
+
+ private void init(ExpressionFactory expressionFactory) {
+ this.expressionFactory = expressionFactory;
+ DefaultElContextFactory defaultContextFactory = new DefaultElContextFactory();
+ putContextFactory(null, defaultContextFactory);
+ putContextFactory(Object.class, defaultContextFactory);
}
private static class ParserELContext extends ELContext {
@@ -106,7 +131,8 @@ public class ELExpressionParser implements ExpressionParser {
variableMapper = new VariableMapperImpl();
for (int i = 0; i < variables.length; i++) {
ExpressionVariable var = variables[i];
- ValueExpression expr = expressionFactory.createValueExpression(this, var.getValue(), Object.class);
+ ValueExpression expr = expressionFactory.createValueExpression(this,
+ String.valueOf(var.getValue()), Object.class);
variableMapper.setVariable(var.getName(), expr);
}
}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpression.java b/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpression.java
index b1e41427..aa136b3f 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpression.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpression.java
@@ -47,15 +47,14 @@ class OgnlExpression implements Expression {
/**
* Expression variable initial values.
*/
- private ExpressionVariable[] variables;
+ private Map variableMap;;
/**
* Creates a new OGNL expression.
* @param expression the parsed expression
*/
public OgnlExpression(Object expression, ExpressionVariable[] variables) {
- this.expression = expression;
- this.variables = variables;
+ init(expression, variables);
}
public int hashCode() {
@@ -72,34 +71,43 @@ class OgnlExpression implements Expression {
return expression.equals(other.expression);
}
- public Object getValue(Object target) throws EvaluationException {
- Assert.notNull(target, "The target object to evaluate is required");
+ public Object getValue(Object context) throws EvaluationException {
try {
- return Ognl.getValue(expression, getContext(), target);
+ return Ognl.getValue(expression, variableMap, context);
} catch (OgnlException e) {
if (e.getReason() != null && e.getReason() != e) {
// unwrap the OgnlException since the actual exception is wrapped inside it
// and there is not generic (getCause) way to get to it later on
- throw new EvaluationException(new EvaluationAttempt(this, target), e.getReason());
+ throw new EvaluationException(new EvaluationAttempt(this, context), e.getReason());
} else {
- throw new EvaluationException(new EvaluationAttempt(this, target), e);
+ throw new EvaluationException(new EvaluationAttempt(this, context), e);
}
}
}
- public void setValue(Object target, Object value) {
- Assert.notNull(target, "The target object to evaluate is required");
+ public void setValue(Object context, Object value) {
+ Assert.notNull(context, "The context to set the provided value in is required");
try {
- // TODO context map
- Ognl.setValue(expression, getContext(), target, value);
+ Ognl.setValue(expression, variableMap, context, value);
} catch (OgnlException e) {
- throw new EvaluationException(new SetValueAttempt(this, target, value), e);
+ throw new EvaluationException(new SetValueAttempt(this, context, value), e);
}
}
- private Map getContext() {
+ private void init(Object expression, ExpressionVariable[] variables) {
+ this.expression = expression;
+ variableMap = createVariableMap(variables);
+ }
+
+ private Map createVariableMap(ExpressionVariable[] variables) {
if (variables != null && variables.length > 0) {
- return new HashMap(variables.length);
+ Map variableMap = new HashMap(variables.length);
+ for (int i = 0; i < variables.length; i++) {
+ ExpressionVariable var = variables[i];
+ variableMap.put(var.getName(), var.getValue());
+ }
+ System.out.println(variableMap);
+ return variableMap;
} else {
return Collections.EMPTY_MAP;
}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpressionParser.java
index e210bdcf..5e716355 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpressionParser.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/ognl/OgnlExpressionParser.java
@@ -21,9 +21,10 @@ import ognl.OgnlRuntime;
import ognl.PropertyAccessor;
import org.springframework.binding.expression.Expression;
-import org.springframework.binding.expression.ExpressionVariable;
+import org.springframework.binding.expression.ParserContext;
import org.springframework.binding.expression.ParserException;
import org.springframework.binding.expression.support.AbstractExpressionParser;
+import org.springframework.binding.expression.support.NullParserContext;
/**
* An expression parser that parses Ognl expressions.
@@ -32,10 +33,12 @@ import org.springframework.binding.expression.support.AbstractExpressionParser;
*/
public class OgnlExpressionParser extends AbstractExpressionParser {
- protected Expression doParseExpression(String expressionString, Class expressionTargetType,
- Class expectedEvaluationResultType, ExpressionVariable[] expressionVariables) throws ParserException {
+ public Expression doParseExpression(String expressionString, ParserContext context) throws ParserException {
+ if (context == null) {
+ context = NullParserContext.INSTANCE;
+ }
try {
- return new OgnlExpression(Ognl.parseExpression(expressionString), expressionVariables);
+ return new OgnlExpression(Ognl.parseExpression(expressionString), context.getExpressionVariables());
} catch (OgnlException e) {
throw new ParserException(expressionString, e);
}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java
index aa9626bb..87b59527 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/AbstractExpressionParser.java
@@ -20,7 +20,7 @@ import java.util.List;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
-import org.springframework.binding.expression.ExpressionVariable;
+import org.springframework.binding.expression.ParserContext;
import org.springframework.binding.expression.ParserException;
import org.springframework.util.Assert;
@@ -80,15 +80,13 @@ public abstract class AbstractExpressionParser implements ExpressionParser {
this.expressionSuffix = expressionSuffix;
}
- public boolean isEvalExpressionString(String string) {
+ public boolean isDelimitedExpression(String string) {
return string.startsWith(expressionPrefix) && string.endsWith(expressionSuffix);
}
- public Expression parseExpression(String expressionString, Class expressionTargetType,
- Class expectedEvaluationResultType, ExpressionVariable[] expressionVariables) throws ParserException {
+ public Expression parseExpression(String expressionString, ParserContext context) throws ParserException {
Assert.notNull(expressionString, "The expression string to parse is required");
- Expression[] expressions = parseExpressions(expressionString, expressionTargetType,
- expectedEvaluationResultType, expressionVariables);
+ Expression[] expressions = parseExpressions(expressionString, context);
if (expressions.length == 1) {
return expressions[0];
} else {
@@ -105,8 +103,7 @@ public abstract class AbstractExpressionParser implements ExpressionParser {
* @return the parsed expressions
* @throws ParserException when the expressions cannot be parsed
*/
- private Expression[] parseExpressions(String expressionString, Class expressionTargetType,
- Class expectedEvaluationResultType, ExpressionVariable[] expressionVariables) throws ParserException {
+ private Expression[] parseExpressions(String expressionString, ParserContext context) throws ParserException {
List expressions = new LinkedList();
int startIdx = 0;
while (startIdx < expressionString.length()) {
@@ -136,8 +133,7 @@ public abstract class AbstractExpressionParser implements ExpressionParser {
+ getExpressionPrefix() + getExpressionSuffix() + "' at character " + prefixIndex, null);
} else {
String expr = expressionString.substring(prefixIndex + getExpressionPrefix().length(), suffixIndex);
- expressions.add(doParseExpression(expr, expressionTargetType, expectedEvaluationResultType,
- expressionVariables));
+ expressions.add(doParseExpression(expr, context));
startIdx = suffixIndex + 1;
}
} else {
@@ -157,7 +153,7 @@ public abstract class AbstractExpressionParser implements ExpressionParser {
* @return the parsed expression
* @throws ParserException an exception occurred during parsing
*/
- protected abstract Expression doParseExpression(String expressionString, Class expressionTargetType,
- Class expectedEvaluationResultType, ExpressionVariable[] expressionVariables) throws ParserException;
+ protected abstract Expression doParseExpression(String expressionString, ParserContext context)
+ throws ParserException;
}
\ No newline at end of file
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/CollectionAddingExpression.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/CollectionAddingExpression.java
index 4950828b..2e49093d 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/support/CollectionAddingExpression.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/CollectionAddingExpression.java
@@ -43,14 +43,14 @@ public class CollectionAddingExpression implements Expression {
this.collectionExpression = collectionExpression;
}
- public Object getValue(Object target) throws EvaluationException {
- return collectionExpression.getValue(target);
+ public Object getValue(Object context) throws EvaluationException {
+ return collectionExpression.getValue(context);
}
- public void setValue(Object target, Object value) throws EvaluationException {
- Object result = getValue(target);
+ public void setValue(Object context, Object value) throws EvaluationException {
+ Object result = getValue(context);
if (result == null) {
- throw new EvaluationException(new SetValueAttempt(this, target, value), new IllegalArgumentException(
+ throw new EvaluationException(new SetValueAttempt(this, context, value), new IllegalArgumentException(
"The collection expression evaluated to a [null] reference"));
}
Assert.isInstanceOf(Collection.class, result, "Not a collection: ");
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/CompositeStringExpression.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/CompositeStringExpression.java
index 72795c28..44e53c21 100644
--- a/spring-binding/src/main/java/org/springframework/binding/expression/support/CompositeStringExpression.java
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/CompositeStringExpression.java
@@ -40,15 +40,15 @@ public class CompositeStringExpression implements Expression {
this.expressions = expressions;
}
- public Object getValue(Object target) throws EvaluationException {
+ public Object getValue(Object context) throws EvaluationException {
StringBuffer buffer = new StringBuffer(128);
for (int i = 0; i < expressions.length; i++) {
- buffer.append(expressions[i].getValue(target));
+ buffer.append(expressions[i].getValue(context));
}
return buffer.toString();
}
- public void setValue(Object target, Object value) throws EvaluationException {
+ public void setValue(Object context, Object value) throws EvaluationException {
throw new UnsupportedOperationException("Cannot set a composite string expression value");
}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/NullParserContext.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/NullParserContext.java
new file mode 100644
index 00000000..ee7c91cc
--- /dev/null
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/NullParserContext.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2004-2007 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.binding.expression.support;
+
+import org.springframework.binding.expression.ExpressionVariable;
+import org.springframework.binding.expression.ParserContext;
+
+public final class NullParserContext implements ParserContext {
+
+ public static final ParserContext INSTANCE = new NullParserContext();
+
+ private NullParserContext() {
+ }
+
+ public Class getEvaluationContextType() {
+ return null;
+ }
+
+ public Class getExpectedEvaluationResultType() {
+ return null;
+ }
+
+ public ExpressionVariable[] getExpressionVariables() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/ParserContextImpl.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/ParserContextImpl.java
new file mode 100644
index 00000000..9a50ad40
--- /dev/null
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/ParserContextImpl.java
@@ -0,0 +1,57 @@
+package org.springframework.binding.expression.support;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.springframework.binding.expression.ExpressionVariable;
+import org.springframework.binding.expression.ParserContext;
+
+public class ParserContextImpl implements ParserContext {
+
+ private Class evaluationContextType;
+
+ private Class evaluationResultType;
+
+ private List expressionVariables;
+
+ public ParserContextImpl() {
+ init();
+ }
+
+ public Class getEvaluationContextType() {
+ return evaluationContextType;
+ }
+
+ public Class getExpectedEvaluationResultType() {
+ return evaluationResultType;
+ }
+
+ public ExpressionVariable[] getExpressionVariables() {
+ return (ExpressionVariable[]) expressionVariables.toArray(new ExpressionVariable[expressionVariables.size()]);
+ }
+
+ public ParserContextImpl context(Class contextType) {
+ evaluationContextType = contextType;
+ return ParserContextImpl.this;
+ }
+
+ public ParserContextImpl expect(Class resultType) {
+ evaluationResultType = resultType;
+ return ParserContextImpl.this;
+ }
+
+ public ParserContextImpl variable(ExpressionVariable variable) {
+ expressionVariables.add(variable);
+ return ParserContextImpl.this;
+ }
+
+ public ParserContextImpl variables(ExpressionVariable[] variables) {
+ expressionVariables.addAll(Arrays.asList(variables));
+ return ParserContextImpl.this;
+ }
+
+ private void init() {
+ expressionVariables = new ArrayList();
+ }
+}
diff --git a/spring-binding/src/main/java/org/springframework/binding/mapping/MappingBuilder.java b/spring-binding/src/main/java/org/springframework/binding/mapping/MappingBuilder.java
index 7ce80446..6d0cfa6f 100644
--- a/spring-binding/src/main/java/org/springframework/binding/mapping/MappingBuilder.java
+++ b/spring-binding/src/main/java/org/springframework/binding/mapping/MappingBuilder.java
@@ -101,7 +101,7 @@ public class MappingBuilder {
* @return this, to support call-chaining
*/
public MappingBuilder source(String expressionString) {
- sourceExpression = expressionParser.parseExpression(expressionString, Object.class, Object.class, null);
+ sourceExpression = expressionParser.parseExpression(expressionString, null);
return this;
}
@@ -111,7 +111,7 @@ public class MappingBuilder {
* @return this, to support call-chaining
*/
public MappingBuilder target(String expressionString) {
- targetExpression = expressionParser.parseExpression(expressionString, Object.class, Object.class, null);
+ targetExpression = expressionParser.parseExpression(expressionString, null);
return this;
}
@@ -121,8 +121,7 @@ public class MappingBuilder {
* @return this, to support call-chaining
*/
public MappingBuilder targetCollection(String expressionString) {
- targetExpression = new CollectionAddingExpression(expressionParser.parseExpression(expressionString,
- Object.class, Object.class, null));
+ targetExpression = new CollectionAddingExpression(expressionParser.parseExpression(expressionString, null));
return this;
}
diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/el/ELExpressionParserTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/el/ELExpressionParserTests.java
index 6dfbceb6..3fafaa77 100644
--- a/spring-binding/src/test/java/org/springframework/binding/expression/el/ELExpressionParserTests.java
+++ b/spring-binding/src/test/java/org/springframework/binding/expression/el/ELExpressionParserTests.java
@@ -1,8 +1,8 @@
package org.springframework.binding.expression.el;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import javax.el.ELContext;
import javax.el.ELResolver;
@@ -14,7 +14,7 @@ import junit.framework.TestCase;
import org.jboss.el.ExpressionFactoryImpl;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionVariable;
-import org.springframework.binding.expression.ParserException;
+import org.springframework.binding.expression.support.ParserContextImpl;
public class ELExpressionParserTests extends TestCase {
@@ -24,120 +24,54 @@ public class ELExpressionParserTests extends TestCase {
parser.putContextFactory(TestBean.class, new TestELContextFactory());
}
- private static class TestELContextFactory implements ELContextFactory {
- public ELContext getELContext(final Object target, final VariableMapper variableMapper) {
- return new ELContext() {
- public ELResolver getELResolver() {
- return new DefaultELResolver(target, null);
- }
-
- public FunctionMapper getFunctionMapper() {
- return null;
- }
-
- public VariableMapper getVariableMapper() {
- return variableMapper;
- }
- };
- }
+ public void testParseSimpleEvalExpressionNoParserContext() {
+ String expressionString = "#{3 + 4}";
+ Expression exp = parser.parseExpression(expressionString, null);
+ assertEquals(new Long(7), exp.getValue(null));
}
- public void testParseEvalExpressionExpectedResultTypeNull() {
- String expressionString = "#{value}";
- Class expressionTargetType = null;
- Class expectedEvaluationResultType = null;
- ExpressionVariable[] expressionVariables = null;
- try {
- parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
- expressionVariables);
- fail("Should have failed");
- } catch (ParserException e) {
-
- }
+ public void testParseSimpleEvalExpressionNoEvalContextWithTypeCoersion() {
+ String expressionString = "#{3 + 4}";
+ Expression exp = parser.parseExpression(expressionString, new ParserContextImpl().expect(Integer.class));
+ assertEquals(new Integer(7), exp.getValue(null));
}
- public void testParseEvalExpression() {
+ public void testParseBeanEvalExpressionNoParserContext() {
String expressionString = "#{value}";
- Class expressionTargetType = TestBean.class;
- Class expectedEvaluationResultType = String.class;
- ExpressionVariable[] expressionVariables = null;
- Expression exp = parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
- expressionVariables);
- TestBean target = new TestBean();
- assertEquals("foo", exp.getValue(target));
+ Expression exp = parser.parseExpression(expressionString, null);
+ assertEquals("foo", exp.getValue(new TestBean()));
}
- public void testParseEvalExpressionNoTargetType() {
- String expressionString = "#{value}";
- Class expressionTargetType = null;
- Class expectedEvaluationResultType = Object.class;
- ExpressionVariable[] expressionVariables = null;
- try {
- parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
- expressionVariables);
- fail("Should have failed");
- } catch (ParserException e) {
-
- }
+ public void testParseEvalExpressionWithContextTypeCoersion() {
+ String expressionString = "#{maximum}";
+ Expression exp = parser.parseExpression(expressionString, new ParserContextImpl().expect(Long.class));
+ assertEquals(new Long(2), exp.getValue(new TestBean()));
}
- public void testParseEvalExpressionNotRegisteredTargetType() {
- String expressionString = "#{value}";
- Class expressionTargetType = Map.class;
- Class expectedEvaluationResultType = Object.class;
- ExpressionVariable[] expressionVariables = null;
- try {
- parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
- expressionVariables);
- fail("Should have failed");
- } catch (ParserException e) {
- }
+ public void testParseEvalExpressionWithContextCustomTestBeanResolver() {
+ String expressionString = "#{specialProperty}";
+ Expression exp = parser.parseExpression(expressionString, new ParserContextImpl().context(TestBean.class));
+ assertEquals("Custom resolver resolved this special property!", exp.getValue(new TestBean()));
}
public void testParseLiteralExpression() {
String expressionString = "value";
- Class expressionTargetType = TestBean.class;
- Class expectedEvaluationResultType = String.class;
- ExpressionVariable[] expressionVariables = null;
- Expression exp = parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
- expressionVariables);
- TestBean target = new TestBean();
- assertEquals("value", exp.getValue(target));
+ Expression exp = parser.parseExpression(expressionString, null);
+ assertEquals("value", exp.getValue(null));
}
public void testParseExpressionWithVariables() {
String expressionString = "#{value}#{max}";
- Class expressionTargetType = TestBean.class;
- Class expectedEvaluationResultType = String.class;
- ExpressionVariable[] expressionVariables = new ExpressionVariable[] { new ExpressionVariable("max",
- "#{maximum}") };
- Expression exp = parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
- expressionVariables);
+ Expression exp = parser.parseExpression(expressionString, new ParserContextImpl()
+ .variable(new ExpressionVariable("max", "#{maximum}")));
TestBean target = new TestBean();
assertEquals("foo2", exp.getValue(target));
}
- public void testParseExpressionWithVariables2() {
- String expressionString = "#{value}#{bean.encode(value)}";
- Class expressionTargetType = TestBean.class;
- Class expectedEvaluationResultType = String.class;
- ExpressionVariable[] expressionVariables = null;
- Expression exp = parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
- expressionVariables);
- TestBean target = new TestBean(new TestBean());
- assertEquals("foo!foo", exp.getValue(target));
- }
-
- public void testParseExpressionCoerceToInteger() {
- String expressionString = "#{maximum}#{max}";
- Class expressionTargetType = TestBean.class;
- Class expectedEvaluationResultType = Integer.class;
- ExpressionVariable[] expressionVariables = new ExpressionVariable[] { new ExpressionVariable("max",
- "#{maximum}") };
- Expression exp = parser.parseExpression(expressionString, expressionTargetType, expectedEvaluationResultType,
- expressionVariables);
- TestBean target = new TestBean();
- assertEquals(new Integer(22), exp.getValue(target));
+ public void testParseImmediateEvalExpression() {
+ String expressionString = "${3 + 4}";
+ Expression exp = parser.parseExpression(expressionString, null);
+ assertEquals(new Long(7), exp.getValue(null));
}
public static class TestBean {
@@ -187,6 +121,52 @@ public class ELExpressionParserTests extends TestCase {
public void setMaximum(int maximum) {
this.maximum = maximum;
}
-
}
+
+ private static class TestELContextFactory implements ELContextFactory {
+ public ELContext getELContext(final Object target, final VariableMapper variableMapper) {
+ return new ELContext() {
+ public ELResolver getELResolver() {
+ return new ELResolver() {
+ public Class getCommonPropertyType(ELContext arg0, Object arg1) {
+ return Object.class;
+ }
+
+ public Iterator getFeatureDescriptors(ELContext arg0, Object arg1) {
+ return null;
+ }
+
+ public Class getType(ELContext arg0, Object arg1, Object arg2) {
+ return String.class;
+ }
+
+ public Object getValue(ELContext arg0, Object arg1, Object arg2) {
+ if (arg1 == null && arg2.equals("specialProperty")) {
+ return "Custom resolver resolved this special property!";
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public boolean isReadOnly(ELContext arg0, Object arg1, Object arg2) {
+ return true;
+ }
+
+ public void setValue(ELContext arg0, Object arg1, Object arg2, Object arg3) {
+ throw new UnsupportedOperationException("Not supported");
+ }
+ };
+ }
+
+ public FunctionMapper getFunctionMapper() {
+ return null;
+ }
+
+ public VariableMapper getVariableMapper() {
+ return variableMapper;
+ }
+ };
+ }
+ }
+
}
diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/ognl/OgnlExpressionParserTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/ognl/OgnlExpressionParserTests.java
index 150bd611..365a4cab 100644
--- a/spring-binding/src/test/java/org/springframework/binding/expression/ognl/OgnlExpressionParserTests.java
+++ b/spring-binding/src/test/java/org/springframework/binding/expression/ognl/OgnlExpressionParserTests.java
@@ -18,7 +18,9 @@ package org.springframework.binding.expression.ognl;
import junit.framework.TestCase;
import org.springframework.binding.expression.Expression;
+import org.springframework.binding.expression.ExpressionVariable;
import org.springframework.binding.expression.ParserException;
+import org.springframework.binding.expression.support.ParserContextImpl;
/**
* Unit tests for {@link org.springframework.binding.expression.ognl.OgnlExpressionParser}.
@@ -31,21 +33,21 @@ public class OgnlExpressionParserTests extends TestCase {
public void testParseSimple() {
String exp = "${flag}";
- Expression e = parser.parseExpression(exp, null, null, null);
+ Expression e = parser.parseExpression(exp, null);
assertNotNull(e);
Boolean b = (Boolean) e.getValue(bean);
assertFalse(b.booleanValue());
}
public void testParseEmpty() {
- Expression e = parser.parseExpression("", null, null, null);
+ Expression e = parser.parseExpression("", null);
assertNotNull(e);
assertEquals("", e.getValue(bean));
}
public void testParseComposite() {
String exp = "hello ${flag} ${flag} ${flag}";
- Expression e = parser.parseExpression(exp, null, null, null);
+ Expression e = parser.parseExpression(exp, null);
assertNotNull(e);
String str = (String) e.getValue(bean);
assertEquals("hello false false false", str);
@@ -54,7 +56,7 @@ public class OgnlExpressionParserTests extends TestCase {
public void testEnclosedCompositeNotSupported() {
String exp = "${hello ${flag} ${flag} ${flag}}";
try {
- parser.parseExpression(exp, null, null, null);
+ parser.parseExpression(exp, null);
fail("Should've failed - not intended use");
} catch (ParserException e) {
}
@@ -62,13 +64,13 @@ public class OgnlExpressionParserTests extends TestCase {
public void testSyntaxError1() {
try {
- parser.parseExpression("${", null, null, null);
+ parser.parseExpression("${", null);
fail();
} catch (ParserException e) {
}
try {
String exp = "hello ${flag} ${abcd defg";
- parser.parseExpression(exp, null, null, null);
+ parser.parseExpression(exp, null);
fail("Should've failed - not intended use");
} catch (ParserException e) {
}
@@ -76,13 +78,13 @@ public class OgnlExpressionParserTests extends TestCase {
public void testSyntaxError2() {
try {
- parser.parseExpression("${}", null, null, null);
+ parser.parseExpression("${}", null);
fail("Should've failed - not intended use");
} catch (ParserException e) {
}
try {
String exp = "hello ${flag} ${}";
- parser.parseExpression(exp, null, null, null);
+ parser.parseExpression(exp, null);
fail("Should've failed - not intended use");
} catch (ParserException e) {
}
@@ -90,24 +92,28 @@ public class OgnlExpressionParserTests extends TestCase {
public void testCollectionConstructionSyntax() {
// lists
- parser.parseExpression("name in {null, \"Untitled\"}", null, null, null);
- parser.parseExpression("${name in {null, \"Untitled\"}}", null, null, null);
+ parser.parseExpression("name in {null, \"Untitled\"}", null);
+ parser.parseExpression("${name in {null, \"Untitled\"}}", null);
// native arrays
- parser.parseExpression("new int[] {1, 2, 3}", null, null, null);
- parser.parseExpression("${new int[] {1, 2, 3}}", null, null, null);
+ parser.parseExpression("new int[] {1, 2, 3}", null);
+ parser.parseExpression("${new int[] {1, 2, 3}}", null);
// maps
- parser.parseExpression("#{ 'foo' : 'foo value', 'bar' : 'bar value' }", null, null, null);
- parser.parseExpression("${#{ 'foo' : 'foo value', 'bar' : 'bar value' }}", null, null, null);
- parser.parseExpression("#@java.util.LinkedHashMap@{ 'foo' : 'foo value', 'bar' : 'bar value' }", null, null,
- null);
- parser.parseExpression("${#@java.util.LinkedHashMap@{ 'foo' : 'foo value', 'bar' : 'bar value' }}", null, null,
- null);
+ parser.parseExpression("#{ 'foo' : 'foo value', 'bar' : 'bar value' }", null);
+ parser.parseExpression("${#{ 'foo' : 'foo value', 'bar' : 'bar value' }}", null);
+ parser.parseExpression("#@java.util.LinkedHashMap@{ 'foo' : 'foo value', 'bar' : 'bar value' }", null);
+ parser.parseExpression("${#@java.util.LinkedHashMap@{ 'foo' : 'foo value', 'bar' : 'bar value' }}", null);
// complex examples
- parser.parseExpression("b,#{1:2}", null, null, null);
- parser.parseExpression("${b,#{1:2}}", null, null, null);
- parser.parseExpression("a${b,#{1:2},e}f${g,#{3:4},j}k", null, null, null);
+ parser.parseExpression("b,#{1:2}", null);
+ parser.parseExpression("${b,#{1:2}}", null);
+ parser.parseExpression("a${b,#{1:2},e}f${g,#{3:4},j}k", null);
+ }
+
+ public void testVariables() {
+ Expression exp = parser.parseExpression("${#var}", new ParserContextImpl().variable(new ExpressionVariable(
+ "var", new Integer(1))));
+ assertEquals(new Integer(1), exp.getValue(bean));
}
}
\ No newline at end of file