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 dcbc6347..f6c81900 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 @@ -10,17 +10,25 @@ public class ExpressionVariable { private String name; private String valueExpression; + private ParserContext parserContext; /** - * Creates a new expression variable - * @param name the name of the variable, acting as an convenient alias - * @param value the value expression + * Creates a new expression variable. + * @param name the name of the variable, acting as an convenient alias (required) + * @param valueExpression the value expression (required) */ - public ExpressionVariable(String name, String value) { - Assert.hasText(name, "The expression variable must be named"); - Assert.hasText(value, "The expression variable's value expression is required"); - this.name = name; - this.valueExpression = value; + public ExpressionVariable(String name, String valueExpression) { + init(name, valueExpression, null); + } + + /** + * Creates a new expression variable with a populated parser context. + * @param name the name of the variable, acting as an convenient alias (required) + * @param valueExpression the value expression (required) + * @param parserContext the parser context to use to parse the value expression (optional) + */ + public ExpressionVariable(String name, String valueExpression, ParserContext parserContext) { + init(name, valueExpression, parserContext); } /** @@ -39,6 +47,14 @@ public class ExpressionVariable { return valueExpression; } + /** + * Returns the parser context to use to parse the variable's value expression. + * @return the value expression parser context + */ + public ParserContext getParserContext() { + return parserContext; + } + public boolean equals(Object o) { if (!(o instanceof ExpressionVariable)) { return false; @@ -54,4 +70,13 @@ public class ExpressionVariable { public String toString() { return "[Expression Variable '" + name + "']"; } + + private void init(String name, String valueExpression, ParserContext parserContext) { + Assert.hasText(name, "The expression variable must be named"); + Assert.hasText(valueExpression, "The expression variable's value expression is required"); + this.name = name; + this.valueExpression = valueExpression; + this.parserContext = parserContext; + } + } diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/el/ELContextFactory.java b/spring-binding/src/main/java/org/springframework/binding/expression/el/ELContextFactory.java index 76b8347d..7b728100 100644 --- a/spring-binding/src/main/java/org/springframework/binding/expression/el/ELContextFactory.java +++ b/spring-binding/src/main/java/org/springframework/binding/expression/el/ELContextFactory.java @@ -6,6 +6,11 @@ import javax.el.ELResolver; /** * A factory for creating a EL context object that will be used to evaluate a target object of an EL expression. * + * Note this ELContextFactory is not used at parse time, only evaluation time. Therefore, factories should not be + * concerned with setting up parse-time context attributes such as the variable mapper and function mapper that play no + * part during expression evaluation. + * + * @author Keith Donald * @author Jeremy Grelle */ public interface ELContextFactory { 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 6b7b0574..983c3428 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 @@ -21,8 +21,8 @@ import org.springframework.util.Assert; /** * An expression parser that parses EL expressions. - * @author Jeremy Grelle * @author Keith Donald + * @author Jeremy Grelle */ public class ELExpressionParser implements ExpressionParser { @@ -56,10 +56,7 @@ public class ELExpressionParser implements ExpressionParser { context = NullParserContext.INSTANCE; } try { - ParserELContext elContext = new ParserELContext(); - elContext.mapVariables(context.getExpressionVariables(), expressionFactory); - ValueExpression expression = expressionFactory.createValueExpression(elContext, expressionString, - getExpectedType(context)); + ValueExpression expression = parseValueExpression(expressionString, context); ELContextFactory contextFactory = getContextFactory(context.getEvaluationContextType(), expressionString); return new ELExpression(contextFactory, expression); } catch (ELException e) { @@ -67,6 +64,12 @@ public class ELExpressionParser implements ExpressionParser { } } + private ValueExpression parseValueExpression(String expressionString, ParserContext context) throws ELException { + ParserELContext elContext = new ParserELContext(); + elContext.mapVariables(context.getExpressionVariables(), expressionFactory); + return expressionFactory.createValueExpression(elContext, expressionString, getExpectedType(context)); + } + private Class getExpectedType(ParserContext context) { Class expectedType = context.getExpectedEvaluationResultType(); if (expectedType != null) { @@ -91,7 +94,7 @@ public class ELExpressionParser implements ExpressionParser { putContextFactory(Object.class, defaultContextFactory); } - private static class ParserELContext extends ELContext { + private class ParserELContext extends ELContext { private VariableMapper variableMapper; public ELResolver getELResolver() { @@ -111,8 +114,9 @@ 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.getValueExpression(), - Object.class); + ParserContext context = var.getParserContext() != null ? var.getParserContext() + : NullParserContext.INSTANCE; + ValueExpression expr = parseValueExpression(var.getValueExpression(), context); variableMapper.setVariable(var.getName(), expr); } } 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 6f4e05eb..7319c77c 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 @@ -272,7 +272,7 @@ public class OgnlExpressionParser implements ExpressionParser { Map variableExpressions = new HashMap(variables.length, 1); for (int i = 0; i < variables.length; i++) { ExpressionVariable var = variables[i]; - variableExpressions.put(var.getName(), parseExpression(var.getValueExpression(), null)); + variableExpressions.put(var.getName(), parseExpression(var.getValueExpression(), var.getParserContext())); } return variableExpressions; }