diff --git a/spring-binding/ivy.xml b/spring-binding/ivy.xml
index 57318a52..f42591d1 100644
--- a/spring-binding/ivy.xml
+++ b/spring-binding/ivy.xml
@@ -13,12 +13,14 @@
+
+
-
+
diff --git a/spring-binding/project.properties b/spring-binding/project.properties
index 60d3db3a..9e7817fe 100644
--- a/spring-binding/project.properties
+++ b/spring-binding/project.properties
@@ -7,5 +7,5 @@ project.base.version=1.1-SNAPSHOT
#project.version=${project.base.version}
#ivy.status=release
-javac.source=1.3
-javac.target=1.3
+javac.source=1.4
+javac.target=1.4
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/DefaultELResolver.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/DefaultELResolver.java
new file mode 100644
index 00000000..932ec12a
--- /dev/null
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/DefaultELResolver.java
@@ -0,0 +1,77 @@
+package org.springframework.binding.expression.support;
+
+import javax.el.ArrayELResolver;
+import javax.el.BeanELResolver;
+import javax.el.CompositeELResolver;
+import javax.el.ELContext;
+import javax.el.ListELResolver;
+import javax.el.MapELResolver;
+import javax.el.ResourceBundleELResolver;
+
+import org.springframework.binding.collection.MapAdaptable;
+import org.springframework.util.Assert;
+
+/**
+ * A generic ELResolver to be used as a default when no other ELResolvers have been
+ * configured by the client application.
+ *
+ * This implementation will resolve the first part of the expression to
+ * the pre-configured base object, and will then delegate through the
+ * chain of standard resolvers for the rest of the expression.
+ *
+ * Note - Requires Java 5 or higher due to the use of generics in the API's basic resolvers.
+ *
+ * @author Jeremy Grelle
+ *
+ */
+public class DefaultELResolver extends CompositeELResolver {
+
+ private Object target;
+
+ public DefaultELResolver() {
+ configureResolvers();
+ }
+
+ public Class getType(ELContext context, Object base, Object property) {
+ return super.getType(context, adaptIfNecessary(base), property);
+ }
+
+ public Object getValue(ELContext context, Object base, Object property) {
+ Assert.notNull(target,"The DefaultELResolver must have a target base property set.");
+ if (base == null) {
+ return super.getValue(context, target, property);
+ }
+ return super.getValue(context, adaptIfNecessary(base), property);
+ }
+
+ public void setValue(ELContext context, Object base, Object property, Object val) {
+ Assert.notNull(target,"The DefaultELResolver must have a target base property set.");
+ if (base == null)
+ super.setValue(context, target, property, val);
+ else
+ super.setValue(context, adaptIfNecessary(base), property, val);
+ }
+
+ public Object getTarget() {
+ return target;
+ }
+
+ public void setTarget(Object target) {
+ this.target = adaptIfNecessary(target);
+ }
+
+ private Object adaptIfNecessary(Object base) {
+ if (base instanceof MapAdaptable)
+ return ((MapAdaptable)base).asMap();
+ return base;
+ }
+
+ private void configureResolvers() {
+ add(new ArrayELResolver());
+ add(new ListELResolver());
+ add(new MapELResolver());
+ add(new ResourceBundleELResolver());
+ add(new BeanELResolver());
+ }
+
+}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/DelegatingELContext.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/DelegatingELContext.java
new file mode 100644
index 00000000..ad98c45d
--- /dev/null
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/DelegatingELContext.java
@@ -0,0 +1,132 @@
+package org.springframework.binding.expression.support;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.el.CompositeELResolver;
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.FunctionMapper;
+import javax.el.VariableMapper;
+
+/**
+ * An {@link ELContext} implementation that is meant to aggregate the {@link ELResolver}s of
+ * pre-existing {@link ELContext}s. Can also be used standalone if no other {@link ELContext}
+ * exists in the current environment.
+ *
+ * Note - Using this context standalone requires Java 5 or higher.
+ *
+ * @author Jeremy Grelle
+ *
+ */
+public class DelegatingELContext extends ELContext {
+
+ private ELResolver resolver;
+
+ private FunctionMapper functionMapper;
+
+ private VariableMapper variableMapper;
+
+ private List delegates = new ArrayList();
+
+ public ELResolver getELResolver() {
+ return resolver;
+ }
+
+ public void setELResolver(ELResolver resolver) {
+ this.resolver = resolver;
+ }
+
+ public FunctionMapper getFunctionMapper() {
+ return functionMapper;
+ }
+
+ public void setFunctionMapper(FunctionMapper functionMapper) {
+ this.functionMapper = functionMapper;
+ }
+
+ public VariableMapper getVariableMapper() {
+ return variableMapper;
+ }
+
+ public void setVariableMapper(VariableMapper variableMapper) {
+ this.variableMapper = variableMapper;
+ }
+
+ /**
+ * Add a delegate {@link ELContext}.
+ *
+ * If this context is currently configured with the {@link DefaultELResolver}, that resolver
+ * instance will be replaced with a new {@link CompositeELResolver}.
+ *
+ * The delegate's base {@link ELResolver} will be added to this context's base {@link CompositeELResolver}.
+ *
+ * @param context The {@link ELContext} whose base {@link ELResolver} needs to be included in this
+ * context's base {@link CompositeELResolver}.
+ */
+ public void addDelegate(ELContext context) {
+ delegates.add(context);
+ if (getELResolver() == null || getELResolver() instanceof DefaultELResolver) {
+ CompositeELResolver composite = new CompositeELResolver();
+ composite.add(context.getELResolver());
+ setELResolver(composite);
+ }
+ else if (getELResolver() instanceof CompositeELResolver) {
+ ((CompositeELResolver) getELResolver()).add(context.getELResolver());
+ }
+ }
+
+ public Object getContext(Class key) {
+ Object context = super.getContext(key);
+ if (context != null)
+ return context;
+
+ Iterator i = delegates.iterator();
+ while(i.hasNext())
+ {
+ ELContext delegate = (ELContext) i.next();
+ context = delegate.getContext(key);
+ if (context != null)
+ return context;
+ }
+ return null;
+ }
+
+ /**
+ * The ThreadLocal variable used to record the
+ * {@link ELContext} instance for each processing thread.
+ */
+ private static ThreadLocal instance = new ThreadLocal() {
+ protected Object initialValue() {
+ return null;
+ }
+ };
+
+ /**
+ * Return the {@link ELContext} instance for the request that is
+ * being processed by the current thread, if any.
+ */
+ public static DelegatingELContext getCurrentInstance() {
+ if (instance.get() == null)
+ setCurrentInstance(defaultInstance());
+ return ((DelegatingELContext) instance.get());
+ }
+
+ /**
+ * Set the {@link ELContext} instance for the request that is
+ * being processed by the current thread.
+ *
+ * @param context The {@link ELContext} instance for the current
+ * thread, or null if this thread no longer has an
+ * ELContext instance.
+ *
+ */
+ public static void setCurrentInstance(DelegatingELContext context) {
+ instance.set(context);
+ }
+
+ private static DelegatingELContext defaultInstance() {
+ return new DelegatingELContext();
+ }
+}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpression.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpression.java
new file mode 100644
index 00000000..18da0658
--- /dev/null
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpression.java
@@ -0,0 +1,88 @@
+package org.springframework.binding.expression.support;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.ValueExpression;
+
+import org.springframework.binding.expression.EvaluationAttempt;
+import org.springframework.binding.expression.EvaluationContext;
+import org.springframework.binding.expression.EvaluationException;
+import org.springframework.binding.expression.SettableExpression;
+
+/**
+ * Evaluates a parsed EL expression.
+ *
+ * @author Jeremy Grelle
+ */
+public class ELExpression implements SettableExpression {
+
+ ValueExpression expression;
+
+ public ELExpression(ValueExpression expression) {
+ this.expression = expression;
+ }
+
+ public void evaluateToSet(Object target, Object value, EvaluationContext context) throws EvaluationException {
+ ELContext ctx = getELContext(target);
+ try {
+ expression.setValue(ctx, value);
+ }
+ catch (ELException ex) {
+ throw new EvaluationException(new EvaluationAttempt(this, target, context), ex);
+ }
+ }
+
+ public Object evaluate(Object target, EvaluationContext context) throws EvaluationException {
+ ELContext ctx = getELContext(target);
+ try {
+ return expression.getValue(ctx);
+ }
+ catch (ELException ex) {
+ throw new EvaluationException(new EvaluationAttempt(this, target, context), ex);
+ }
+ }
+
+ protected Class getType(Object target, EvaluationContext context) throws EvaluationException{
+ ELContext ctx = getELContext(target);
+ try {
+ return expression.getType(ctx);
+ }
+ catch (ELException ex) {
+ throw new EvaluationException(new EvaluationAttempt(this, target, context), ex);
+ }
+ }
+
+ /**
+ * Retrieves the thread-bound {@link ELContext} instance, configured with a DefaultELResolver if
+ * no other resolvers have been configured.
+ *
+ * @return {@link ELContext} The thread-bound {@link ELContext} instance.
+ */
+ private ELContext getELContext(Object target) {
+ ELContext ctx = DelegatingELContext.getCurrentInstance();
+ if (ctx.getELResolver() == null)
+ ((DelegatingELContext)ctx).setELResolver(new DefaultELResolver());
+ if (ctx.getELResolver() instanceof DefaultELResolver)
+ ((DefaultELResolver)ctx.getELResolver()).setTarget(target);
+ return ctx;
+ }
+
+ public int hashCode() {
+ return expression.hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof ELExpression)) {
+ return false;
+ }
+ ELExpression other = (ELExpression) o;
+ return expression.equals(other.expression);
+ }
+
+ public String toString()
+ {
+ return expression.getExpressionString();
+ }
+
+
+}
diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpressionParser.java
new file mode 100644
index 00000000..e9d374f9
--- /dev/null
+++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/ELExpressionParser.java
@@ -0,0 +1,119 @@
+package org.springframework.binding.expression.support;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.ExpressionFactory;
+
+import org.jboss.el.ExpressionFactoryImpl;
+import org.springframework.binding.expression.Expression;
+import org.springframework.binding.expression.ExpressionParser;
+import org.springframework.binding.expression.ParserException;
+import org.springframework.binding.expression.SettableExpression;
+
+/**
+ * An expression parser that parses EL expressions. Beyond standard EL expression parsing, it
+ * makes use of the ability of the JBoss-EL implementation to parse dynamic method invocations
+ * such as foo.bar() (the EL spec currently only provides out-of-the-box support for functions).
+ *
+ * @author Jeremy Grelle
+ */
+public class ELExpressionParser implements ExpressionParser {
+
+ /**
+ * The expression prefix for deferred EL expressions.
+ */
+ private static final String DEFERRED_EL_EXPRESSION_PREFIX = "#{";
+
+ /**
+ * The expression suffix for deferred EL expressions.
+ */
+ private static final String DEFERRED_EL_EXPRESSION_SUFFIX = "}";
+
+ /**
+ * The marked expression delimiter prefix.
+ */
+ private String expressionPrefix = DEFERRED_EL_EXPRESSION_PREFIX;
+
+ /**
+ * The marked expression delimiter suffix.
+ */
+ private String expressionSuffix = DEFERRED_EL_EXPRESSION_SUFFIX;
+
+ /**
+ * The ExpressionFactory for constructing EL expressions
+ */
+ private ExpressionFactory factory = new ExpressionFactoryImpl();
+
+ public String getExpressionPrefix() {
+ return expressionPrefix;
+ }
+
+ public String getExpressionSuffix() {
+ return expressionSuffix;
+ }
+
+ /**
+ * Check whether or not given criteria are expressed as an expression.
+ */
+ public boolean isDelimitedExpression(String expressionString) {
+ int prefixIndex = expressionString.indexOf(getExpressionPrefix());
+ if (prefixIndex == -1) {
+ return false;
+ }
+ int suffixIndex = expressionString.indexOf(getExpressionSuffix(), prefixIndex);
+ if (suffixIndex == -1) {
+ return false;
+ }
+ else {
+ if (suffixIndex == prefixIndex + getExpressionPrefix().length()) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+ }
+
+ public Expression parseExpression(String expressionString) throws ParserException {
+ if (!isDelimitedExpression(expressionString)) {
+ expressionString = getExpressionPrefix() + expressionString + getExpressionSuffix();
+ }
+ return doParseExpression(expressionString);
+ }
+
+ public SettableExpression parseSettableExpression(String expressionString) throws ParserException,
+ UnsupportedOperationException {
+ if (!isDelimitedExpression(expressionString)) {
+ expressionString = getExpressionPrefix() + expressionString + getExpressionSuffix();
+ }
+ return doParseSettableExpression(expressionString);
+ }
+
+ /**
+ * Parses the expression string into an EL value expression.
+ * @param expressionString
+ * @throws ParserException
+ */
+ protected Expression doParseExpression(String expressionString) throws ParserException {
+ return doParseSettableExpression(expressionString);
+ }
+
+ /**
+ * Parses the expression string into an EL value expression.
+ * @param expressionString
+ * @throws ParserException
+ */
+ protected SettableExpression doParseSettableExpression(String expressionString) throws ParserException {
+ ELContext ctx = getELContext();
+ try {
+ return new ELExpression(factory.createValueExpression(ctx, expressionString, Object.class));
+ }
+ catch (ELException ex) {
+ throw new ParserException(expressionString, ex);
+ }
+ }
+
+ private ELContext getELContext() {
+ return DelegatingELContext.getCurrentInstance();
+ }
+}
diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/support/ELContextDelegationTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/support/ELContextDelegationTests.java
new file mode 100644
index 00000000..1a7310da
--- /dev/null
+++ b/spring-binding/src/test/java/org/springframework/binding/expression/support/ELContextDelegationTests.java
@@ -0,0 +1,106 @@
+package org.springframework.binding.expression.support;
+
+import java.util.Iterator;
+
+import javax.el.BeanELResolver;
+import javax.el.ELContext;
+import javax.el.ELResolver;
+import javax.el.FunctionMapper;
+import javax.el.VariableMapper;
+
+import junit.framework.TestCase;
+
+import org.springframework.binding.expression.ExpressionParser;
+
+/**
+ * Tests to verify the delegation behavior of ELContextImpl.
+ *
+ * @author Jeremy Grelle
+ *
+ */
+public class ELContextDelegationTests extends TestCase {
+
+ private ELContext context = new MockELContext();
+ private ExpressionParser expressionParser = new ELExpressionParser();
+ private TestBean bean;
+
+ protected void setUp() throws Exception {
+ bean = new TestBean();
+ bean.setFlag(true);
+ }
+
+ public final void testGetValueByContextDelegation()
+ {
+ DelegatingELContext internalContext = DelegatingELContext.getCurrentInstance();
+ internalContext.addDelegate(context);
+ assertEquals(Boolean.TRUE, expressionParser.parseExpression("#{bean.flag}").evaluate(bean, null));
+ assertEquals(Boolean.TRUE, expressionParser.parseExpression("#{bean.flag}").evaluate(null, null));
+ assertFalse(internalContext.getELResolver() instanceof DefaultELResolver);
+ }
+
+ private class MockELContext extends ELContext
+ {
+
+ ELResolver resolver = new MockELResolver();
+
+ public ELResolver getELResolver() {
+ return resolver;
+ }
+
+ public FunctionMapper getFunctionMapper() {
+ return null;
+ }
+
+ public VariableMapper getVariableMapper() {
+ return null;
+ }
+
+ }
+
+ private class MockELResolver extends ELResolver
+ {
+
+ public Class getCommonPropertyType(ELContext context, Object base) {
+ return null;
+ }
+
+ public Iterator getFeatureDescriptors(ELContext context, Object base) {
+ return null;
+ }
+
+ public Class getType(ELContext context, Object base, Object property) {
+ if (base != null)
+ return base.getClass();
+ return null;
+ }
+
+ public Object getValue(ELContext context, Object base, Object property) {
+ if (base == null && "bean".equals(property))
+ {
+ context.setPropertyResolved(true);
+ return bean;
+ }
+ if (base == bean)
+ {
+ return new BeanELResolver().getValue(context, base, property);
+ }
+ return null;
+ }
+
+ public boolean isReadOnly(ELContext context, Object base, Object property) {
+ return false;
+ }
+
+ public void setValue(ELContext context, Object base, Object property, Object value) {
+ if (base == null && "bean".equals(property))
+ {
+ context.setPropertyResolved(true);
+ }
+ else if (base == bean)
+ {
+ new BeanELResolver().setValue(context, base, property, value);
+ }
+ }
+
+ }
+}
diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/support/ELMethodExpressionTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/support/ELMethodExpressionTests.java
new file mode 100644
index 00000000..22b2afc3
--- /dev/null
+++ b/spring-binding/src/test/java/org/springframework/binding/expression/support/ELMethodExpressionTests.java
@@ -0,0 +1,75 @@
+package org.springframework.binding.expression.support;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.easymock.MockControl;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests to exercise the extended method invoking expression extensions of JBoss-el.
+ *
+ * @author Jeremy Grelle
+ *
+ */
+public class ELMethodExpressionTests extends TestCase {
+
+ ELExpressionParser parser = new ELExpressionParser();
+
+ Map context;
+
+ Map container;
+
+ TestMethods target;
+ MockControl targetMockControl;
+
+ protected void setUp() throws Exception {
+ context = new HashMap();
+ container = new HashMap();
+ targetMockControl = MockControl.createControl(TestMethods.class);
+ target = (TestMethods) targetMockControl.getMock();
+ context.put("container", container);
+ container.put("myObject", target);
+ }
+
+ public void testWithIntParam() {
+ String expression = "#{container.myObject.doSomethingWithInt(container.param1)}";
+ int param = 5;
+ container.put("param1", new Integer(param));
+ target.doSomethingWithInt(param);
+ targetMockControl.replay();
+
+ parser.parseExpression(expression).evaluate(context, null);
+ targetMockControl.verify();
+
+ }
+
+ public void testReturnWithIntParam() {
+ String expected = "sucess";
+ String expression = "#{container.myObject.returnStringFromInt(container.param1)}";
+ int param = 5;
+ container.put("param1", new Integer(param));
+ targetMockControl.expectAndReturn(target.returnStringFromInt(param), expected);
+ targetMockControl.replay();
+
+ String result = (String) parser.parseExpression(expression).evaluate(context, null);
+ targetMockControl.verify();
+ assertEquals(expected, result);
+ }
+
+ public void testReturnWithIntAndObject() {
+ String expected = "success";
+ String expression = "#{container.myObject.returnStringFromIntAndObject(container.param1, container.param2)}";
+ int param1 = 5;
+ container.put("param1", new Integer(param1));
+ TestBean param2 = new TestBean();
+ container.put("param2", param2);
+ targetMockControl.expectAndReturn(target.returnStringFromIntAndObject(param1, param2), expected);
+ targetMockControl.replay();
+
+ String result = (String) parser.parseExpression(expression).evaluate(context, null);
+ targetMockControl.verify();
+ assertEquals(expected, result);
+ }
+
+}
diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/support/ELMethodParsingTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/support/ELMethodParsingTests.java
new file mode 100644
index 00000000..45ab6bd4
--- /dev/null
+++ b/spring-binding/src/test/java/org/springframework/binding/expression/support/ELMethodParsingTests.java
@@ -0,0 +1,41 @@
+package org.springframework.binding.expression.support;
+
+import junit.framework.TestCase;
+
+import org.springframework.binding.expression.Expression;
+
+public class ELMethodParsingTests extends TestCase {
+
+ ELExpressionParser parser;
+
+ protected void setUp() throws Exception {
+ parser = new ELExpressionParser();
+ }
+
+ public void testEmptyMethod() {
+
+ String expStr1 = "#{foo.bar()}";
+ Expression result1 = parser.parseExpression(expStr1);
+ assertNotNull(result1);
+ assertEquals(expStr1, result1.toString());
+
+ String expStr2 = "foo.bar()";
+ Expression result2 = parser.parseExpression(expStr2);
+ assertNotNull(result2);
+ assertEquals(expStr1, result2.toString());
+ }
+
+ public void testMethodWithParams() {
+
+ String expStr1 = "#{foo.bar(moe.curly, groucho.harpo)}";
+ Expression result1 = parser.parseExpression(expStr1);
+ assertNotNull(result1);
+ assertEquals(expStr1, result1.toString());
+
+ String expStr2 = "foo.bar(moe.curly, groucho.harpo)";
+ Expression result2 = parser.parseExpression(expStr2);
+ assertNotNull(result2);
+ assertEquals(expStr1, result2.toString());
+ }
+
+}
diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/support/SimpleExpressionTests.java b/spring-binding/src/test/java/org/springframework/binding/expression/support/SimpleExpressionTests.java
index 5d27c0b3..a274e57d 100644
--- a/spring-binding/src/test/java/org/springframework/binding/expression/support/SimpleExpressionTests.java
+++ b/spring-binding/src/test/java/org/springframework/binding/expression/support/SimpleExpressionTests.java
@@ -1,94 +1,100 @@
-/*
- * 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 java.util.ArrayList;
-import java.util.List;
-
-import org.springframework.binding.expression.EvaluationException;
-import org.springframework.binding.expression.ExpressionParser;
-import org.springframework.binding.expression.ParserException;
-
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-/**
- * Tests simple expressions. Any expression language capable enough for
- * real life usage should be able to pass these tests.
- *
- * @author Erwin Vervaet
- */
-public class SimpleExpressionTests extends TestCase {
-
- private ExpressionParser expressionParser;
- private TestBean bean;
-
- public static TestSuite suite() {
- TestSuite suite = new TestSuite();
- suite.addTest(new SimpleExpressionTests("testGetValue", new OgnlExpressionParser()));
- suite.addTest(new SimpleExpressionTests("testSetValue", new OgnlExpressionParser()));
- suite.addTest(new SimpleExpressionTests("testSyntaxError", new OgnlExpressionParser()));
- suite.addTest(new SimpleExpressionTests("testGetValue", new BeanWrapperExpressionParser()));
- suite.addTest(new SimpleExpressionTests("testSetValue", new BeanWrapperExpressionParser()));
- suite.addTest(new SimpleExpressionTests("testSyntaxError", new BeanWrapperExpressionParser()));
- return suite;
- }
-
- public SimpleExpressionTests(String name, ExpressionParser expressionParser) {
- super(name);
- this.expressionParser = expressionParser;
- }
-
- protected void setUp() throws Exception {
- bean = new TestBean();
- bean.setFlag(true);
- List list = new ArrayList();
- list.add("foo");
- list.add("bar");
- bean.setList(list);
- }
-
- public void testGetValue() {
- assertEquals(Boolean.TRUE, expressionParser.parseExpression("${flag}").evaluate(bean, null));
- assertEquals(Boolean.TRUE, expressionParser.parseExpression("flag").evaluate(bean, null));
- assertSame(bean.getList(), expressionParser.parseExpression("${list}").evaluate(bean, null));
- assertEquals("foo", expressionParser.parseExpression("${list[0]}").evaluate(bean, null));
- }
-
- public void testSetValue() {
- expressionParser.parseSettableExpression("${flag}").evaluateToSet(bean, Boolean.FALSE, null);
- assertFalse(bean.isFlag());
- expressionParser.parseSettableExpression("flag").evaluateToSet(bean, Boolean.TRUE, null);
- assertTrue(bean.isFlag());
- List newList = new ArrayList();
- newList.add("boo");
- expressionParser.parseSettableExpression("${list}").evaluateToSet(bean, newList, null);
- assertSame(newList, bean.getList());
- expressionParser.parseSettableExpression("${list[0]}").evaluateToSet(bean, "baa", null);
- assertEquals("baa", bean.getList().get(0));
- }
-
- public void testSyntaxError() {
- try {
- expressionParser.parseExpression("foo(").evaluate(bean, null);
- fail("should have failed");
- }
- catch (ParserException e) {
- }
- catch (EvaluationException e) {
- }
- }
-}
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.binding.expression.EvaluationException;
+import org.springframework.binding.expression.ExpressionParser;
+import org.springframework.binding.expression.ParserException;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Tests simple expressions. Any expression language capable enough for
+ * real life usage should be able to pass these tests.
+ *
+ * @author Erwin Vervaet
+ * @author Jeremy Grelle
+ */
+public class SimpleExpressionTests extends TestCase {
+
+ private ExpressionParser expressionParser;
+ private String expressionPrefix;
+ private TestBean bean;
+
+ public static TestSuite suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new SimpleExpressionTests("testGetValue", new OgnlExpressionParser(), "$"));
+ suite.addTest(new SimpleExpressionTests("testSetValue", new OgnlExpressionParser(), "$"));
+ suite.addTest(new SimpleExpressionTests("testSyntaxError", new OgnlExpressionParser(), "$"));
+ suite.addTest(new SimpleExpressionTests("testGetValue", new BeanWrapperExpressionParser(), "$"));
+ suite.addTest(new SimpleExpressionTests("testSetValue", new BeanWrapperExpressionParser(), "$"));
+ suite.addTest(new SimpleExpressionTests("testSyntaxError", new BeanWrapperExpressionParser(), "$"));
+ suite.addTest(new SimpleExpressionTests("testGetValue", new ELExpressionParser(), "#"));
+ suite.addTest(new SimpleExpressionTests("testSetValue", new ELExpressionParser(), "#"));
+ suite.addTest(new SimpleExpressionTests("testSyntaxError", new ELExpressionParser(), "#"));
+ return suite;
+ }
+
+ public SimpleExpressionTests(String name, ExpressionParser expressionParser, String expressionPrefix) {
+ super(name);
+ this.expressionParser = expressionParser;
+ this.expressionPrefix = expressionPrefix;
+ }
+
+ protected void setUp() throws Exception {
+ bean = new TestBean();
+ bean.setFlag(true);
+ List list = new ArrayList();
+ list.add("foo");
+ list.add("bar");
+ bean.setList(list);
+ }
+
+ public void testGetValue() {
+ assertEquals(Boolean.TRUE, expressionParser.parseExpression(expressionPrefix+"{flag}").evaluate(bean, null));
+ assertEquals(Boolean.TRUE, expressionParser.parseExpression("flag").evaluate(bean, null));
+ assertSame(bean.getList(), expressionParser.parseExpression(expressionPrefix+"{list}").evaluate(bean, null));
+ assertEquals("foo", expressionParser.parseExpression(expressionPrefix+"{list[0]}").evaluate(bean, null));
+ }
+
+ public void testSetValue() {
+ expressionParser.parseSettableExpression(expressionPrefix+"{flag}").evaluateToSet(bean, Boolean.FALSE, null);
+ assertFalse(bean.isFlag());
+ expressionParser.parseSettableExpression("flag").evaluateToSet(bean, Boolean.TRUE, null);
+ assertTrue(bean.isFlag());
+ List newList = new ArrayList();
+ newList.add("boo");
+ expressionParser.parseSettableExpression(expressionPrefix+"{list}").evaluateToSet(bean, newList, null);
+ assertSame(newList, bean.getList());
+ expressionParser.parseSettableExpression(expressionPrefix+"{list[0]}").evaluateToSet(bean, "baa", null);
+ assertEquals("baa", bean.getList().get(0));
+ }
+
+ public void testSyntaxError() {
+ try {
+ expressionParser.parseExpression("foo(").evaluate(bean, null);
+ fail("should have failed");
+ }
+ catch (ParserException e) {
+ }
+ catch (EvaluationException e) {
+ }
+ }
+}
diff --git a/spring-binding/src/test/java/org/springframework/binding/expression/support/TestMethods.java b/spring-binding/src/test/java/org/springframework/binding/expression/support/TestMethods.java
new file mode 100644
index 00000000..45f75b0f
--- /dev/null
+++ b/spring-binding/src/test/java/org/springframework/binding/expression/support/TestMethods.java
@@ -0,0 +1,10 @@
+package org.springframework.binding.expression.support;
+
+public interface TestMethods {
+
+ public void doSomethingWithInt(int arg);
+
+ public String returnStringFromInt(int arg);
+
+ public String returnStringFromIntAndObject(int arg, TestBean bean);
+}