expression parser uses context's ConversionService by default

This commit is contained in:
Juergen Hoeller 2009-09-07 18:37:59 +00:00
parent efaf76b46f
commit 7123e4f81e
6 changed files with 80 additions and 77 deletions

View File

@ -23,11 +23,14 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanExpressionException;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.core.convert.ConversionService;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.support.StandardTypeConverter;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.util.Assert;
/**
@ -96,7 +99,7 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver {
/**
* Specify the EL parser to use for expression parsing.
* <p>Default is a {@link org.springframework.expression.spel.SpelExpressionParser},
* <p>Default is a {@link org.springframework.expression.spel.standard.SpelExpressionParser},
* compatible with standard Unified EL style expression syntax.
*/
public void setExpressionParser(ExpressionParser expressionParser) {
@ -119,6 +122,11 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver {
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
sec.addPropertyAccessor(new BeanFactoryAccessor());
sec.addPropertyAccessor(new MapAccessor());
sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
if (conversionService != null) {
sec.setTypeConverter(new StandardTypeConverter(conversionService));
}
customizeEvaluationContext(sec);
this.evaluationCache.put(evalContext, sec);
}

View File

@ -21,11 +21,11 @@ import java.util.List;
/**
* Expressions are executed in an evaluation context. It is in this context that references
* are resolved when encountered during expression evaluation.
*
* There is a default implementation of the EvaluationContext,
*
* <p>There is a default implementation of the EvaluationContext,
* {@link org.springframework.expression.spel.support.StandardEvaluationContext}
* that can be extended, rather than having to implement everything.
*
*
* @author Andy Clement
* @author Juergen Hoeller
* @since 3.0
@ -36,27 +36,6 @@ public interface EvaluationContext {
* @return the root context object against which unqualified properties/methods/etc should be resolved
*/
TypedValue getRootObject();
/**
* @param rootObject the root object against which unqualified properties/methods/etc should be resolved
*/
void setRootObject(Object object);
/**
* Set a named variable within this execution context to a specified value.
* @param name variable to set
* @param value value to be placed in the variable
*/
void setVariable(String name, Object value);
/**
* Look up a named variable within this execution context.
* @param name variable to lookup
* @return the value of the variable
*/
Object lookupVariable(String name);
/**
* @return a list of resolvers that will be asked in turn to locate a constructor
@ -78,20 +57,34 @@ public interface EvaluationContext {
*/
TypeLocator getTypeLocator();
/**
* @return a type comparator for comparing pairs of objects for equality.
*/
TypeComparator getTypeComparator();
/**
* @return a type converter that can convert (or coerce) a value from one type to another.
*/
TypeConverter getTypeConverter();
/**
* @return a type comparator for comparing pairs of objects for equality.
*/
TypeComparator getTypeComparator();
/**
* @return an operator overloader that may support mathematical operations between more than the standard set of
* types
*/
OperatorOverloader getOperatorOverloader();
/**
* Set a named variable within this evaluation context to a specified value.
* @param name variable to set
* @param value value to be placed in the variable
*/
void setVariable(String name, Object value);
/**
* Look up a named variable within this evaluation context.
* @param name variable to lookup
* @return the value of the variable
*/
Object lookupVariable(String name);
}

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.expression.spel;
import java.util.HashMap;
@ -36,7 +37,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParserConfigur
* communicate state. This is in contrast to the EvaluationContext, which is shared amongst expression evaluations, and
* any changes to it will be seen by other expressions or any code that chooses to ask questions of the context.
*
* It also acts as a place for to define common utility routines that the various Ast nodes might need.
* <p>It also acts as a place for to define common utility routines that the various Ast nodes might need.
*
* @author Andy Clement
* @since 3.0
@ -75,7 +76,8 @@ public class ExpressionState {
TypedValue rootObject = this.relatedContext.getRootObject();
if (rootObject == null) {
return TypedValue.NULL_TYPED_VALUE;
} else {
}
else {
return rootObject;
}
}
@ -94,7 +96,8 @@ public class ExpressionState {
TypedValue root = this.relatedContext.getRootObject();
if (root == null) {
return TypedValue.NULL_TYPED_VALUE;
} else {
}
else {
return root;
}
}
@ -105,10 +108,11 @@ public class ExpressionState {
public TypedValue lookupVariable(String name) {
Object value = this.relatedContext.lookupVariable(name);
if (value==null) {
if (value == null) {
return TypedValue.NULL_TYPED_VALUE;
} else {
return new TypedValue(value,TypeDescriptor.forObject(value));
}
else {
return new TypedValue(value, TypeDescriptor.forObject(value));
}
}

View File

@ -47,8 +47,6 @@ public class StandardEvaluationContext implements EvaluationContext {
private TypedValue rootObject;
private final Map<String, Object> variables = new HashMap<String, Object>();
private final List<ConstructorResolver> constructorResolvers = new ArrayList<ConstructorResolver>();
private final List<MethodResolver> methodResolvers = new ArrayList<MethodResolver>();
@ -57,12 +55,15 @@ public class StandardEvaluationContext implements EvaluationContext {
private TypeLocator typeLocator = new StandardTypeLocator();
private TypeComparator typeComparator = new StandardTypeComparator();
private TypeConverter typeConverter = new StandardTypeConverter();
private TypeComparator typeComparator = new StandardTypeComparator();
private OperatorOverloader operatorOverloader = new StandardOperatorOverloader();
private final Map<String, Object> variables = new HashMap<String, Object>();
public StandardEvaluationContext() {
this.methodResolvers.add(new ReflectiveMethodResolver());
this.constructorResolvers.add(new ReflectiveConstructorResolver());
@ -74,34 +75,19 @@ public class StandardEvaluationContext implements EvaluationContext {
setRootObject(rootObject);
}
public void setRootObject(Object rootObject) {
this.rootObject = new TypedValue(rootObject,TypeDescriptor.forObject(rootObject));
this.rootObject = new TypedValue(rootObject, TypeDescriptor.forObject(rootObject));
}
public void setRootObject(Object rootObject, TypeDescriptor typeDescriptor) {
this.rootObject = new TypedValue(rootObject,typeDescriptor);
this.rootObject = new TypedValue(rootObject, typeDescriptor);
}
public TypedValue getRootObject() {
return this.rootObject;
}
public void setVariable(String name, Object value) {
this.variables.put(name, value);
}
public void setVariables(Map<String,Object> variables) {
this.variables.putAll(variables);
}
public void registerFunction(String name, Method method) {
this.variables.put(name, method);
}
public Object lookupVariable(String name) {
return this.variables.get(name);
}
public void addConstructorResolver(ConstructorResolver resolver) {
this.constructorResolvers.add(this.constructorResolvers.size() - 1, resolver);
}
@ -135,15 +121,6 @@ public class StandardEvaluationContext implements EvaluationContext {
return this.typeLocator;
}
public void setTypeComparator(TypeComparator typeComparator) {
Assert.notNull(typeComparator, "TypeComparator must not be null");
this.typeComparator = typeComparator;
}
public TypeComparator getTypeComparator() {
return this.typeComparator;
}
public void setTypeConverter(TypeConverter typeConverter) {
Assert.notNull(typeConverter, "TypeConverter must not be null");
this.typeConverter = typeConverter;
@ -153,6 +130,15 @@ public class StandardEvaluationContext implements EvaluationContext {
return this.typeConverter;
}
public void setTypeComparator(TypeComparator typeComparator) {
Assert.notNull(typeComparator, "TypeComparator must not be null");
this.typeComparator = typeComparator;
}
public TypeComparator getTypeComparator() {
return this.typeComparator;
}
public void setOperatorOverloader(OperatorOverloader operatorOverloader) {
Assert.notNull(operatorOverloader, "OperatorOverloader must not be null");
this.operatorOverloader = operatorOverloader;
@ -162,4 +148,20 @@ public class StandardEvaluationContext implements EvaluationContext {
return this.operatorOverloader;
}
public void setVariable(String name, Object value) {
this.variables.put(name, value);
}
public void setVariables(Map<String,Object> variables) {
this.variables.putAll(variables);
}
public void registerFunction(String name, Method method) {
this.variables.put(name, method);
}
public Object lookupVariable(String name) {
return this.variables.get(name);
}
}

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.expression.spel;
import java.util.HashMap;
@ -29,7 +30,6 @@ 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)
*
@ -47,7 +47,6 @@ public class ExpressionStateTests extends ExpressionTestCase {
// Local variables are in variable scopes which come and go during evaluation. Normal variables are
// accessible through the evaluation context
@Test
public void testLocalVariables() {
ExpressionState state = getState();
@ -62,7 +61,6 @@ public class ExpressionStateTests extends ExpressionTestCase {
state.setLocalVariable("foo",null);
value = state.lookupLocalVariable("foo");
Assert.assertEquals(null,value);
}
@Test
@ -119,8 +117,8 @@ public class ExpressionStateTests extends ExpressionTestCase {
ExpressionState state = getState();
Assert.assertEquals(Inventor.class,state.getRootContextObject().getValue().getClass());
state.getEvaluationContext().setRootObject(null);
Assert.assertEquals(null,state.getRootContextObject().getValue());
((StandardEvaluationContext) state.getEvaluationContext()).setRootObject(null);
Assert.assertEquals(null, state.getRootContextObject().getValue());
state = new ExpressionState(new StandardEvaluationContext());
Assert.assertEquals(TypedValue.NULL_TYPED_VALUE,state.getRootContextObject());
@ -259,4 +257,5 @@ public class ExpressionStateTests extends ExpressionTestCase {
ExpressionState state = new ExpressionState(context);
return state;
}
}

View File

@ -48,8 +48,6 @@ public class SpelDocumentationTests extends ExpressionTestCase {
static Inventor tesla ;
static Inventor pupin ;
static {
GregorianCalendar c = new GregorianCalendar();
@ -115,7 +113,7 @@ public class SpelDocumentationTests extends ExpressionTestCase {
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("name");
EvaluationContext context = new StandardEvaluationContext();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setRootObject(tesla);
String name = (String) exp.getValue(context);
@ -124,10 +122,9 @@ public class SpelDocumentationTests extends ExpressionTestCase {
@Test
public void testEqualityCheck() throws Exception {
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setRootObject(tesla);
Expression exp = parser.parseExpression("name == 'Nikola Tesla'");