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 3a0564a8..26bf9991 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 @@ -111,8 +111,16 @@ public abstract class AbstractExpressionParser implements ExpressionParser { } } - public abstract SettableExpression parseSettableExpression(String expressionString) throws ParserException, - UnsupportedOperationException; + public final SettableExpression parseSettableExpression(String expressionString) + throws ParserException, UnsupportedOperationException { + expressionString = expressionString.trim(); + // a settable expression should just be a single expression + if (expressionString.startsWith(getExpressionPrefix()) && expressionString.endsWith(getExpressionSuffix())) { + expressionString = expressionString.substring(getExpressionPrefix().length(), + expressionString.length() - getExpressionSuffix().length()); + } + return doParseSettableExpression(expressionString); + } /** * Helper that parses given expression string using the configured parser. @@ -183,13 +191,28 @@ public abstract class AbstractExpressionParser implements ExpressionParser { } return (Expression[]) expressions.toArray(new Expression[expressions.size()]); } + + // template methods /** * Template method for parsing a filtered expression string. Subclasses should * override. * @param expressionString the expression string * @return the parsed expression + * @throws ParserException an exception occured during parsing */ - protected abstract Expression doParseExpression(String expressionString); + protected abstract Expression doParseExpression(String expressionString) throws ParserException; + + /** + * Template method for parsing a filtered settable expression string. Subclasses + * should override. + * @param expressionString the expression string + * @return the parsed expression + * @throws ParserException an exception occured during parsing + * @throws UnsupportedOperationException this parser does not support + * settable expressions + */ + protected abstract SettableExpression doParseSettableExpression(String expressionString) + throws ParserException, UnsupportedOperationException; } \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/BeanWrapperExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/BeanWrapperExpressionParser.java index 980c16a4..8a4ebe38 100644 --- a/spring-binding/src/main/java/org/springframework/binding/expression/support/BeanWrapperExpressionParser.java +++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/BeanWrapperExpressionParser.java @@ -22,7 +22,7 @@ import org.springframework.binding.expression.SettableExpression; /** * An expression parser that parses bean wrapper expressions. * - * @author Keith + * @author Keith Donald */ public class BeanWrapperExpressionParser extends AbstractExpressionParser { @@ -30,7 +30,7 @@ public class BeanWrapperExpressionParser extends AbstractExpressionParser { return parseSettableExpression(expressionString); } - public SettableExpression parseSettableExpression(String expressionString) throws ParserException { + public SettableExpression doParseSettableExpression(String expressionString) throws ParserException { return new BeanWrapperExpression(expressionString); } } \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/OgnlExpression.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/OgnlExpression.java index 65757697..3f6d2fd4 100644 --- a/spring-binding/src/main/java/org/springframework/binding/expression/support/OgnlExpression.java +++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/OgnlExpression.java @@ -60,8 +60,7 @@ class OgnlExpression implements SettableExpression { if (!(o instanceof OgnlExpression)) { return false; } - // as late as Ognl 2.6.7, their expression objects don't implement - // equals + // as late as Ognl 2.6.7, their expression objects don't implement equals // so this always returns false OgnlExpression other = (OgnlExpression) o; return expression.equals(other.expression); diff --git a/spring-binding/src/main/java/org/springframework/binding/expression/support/OgnlExpressionParser.java b/spring-binding/src/main/java/org/springframework/binding/expression/support/OgnlExpressionParser.java index b08aa5be..9783e875 100644 --- a/spring-binding/src/main/java/org/springframework/binding/expression/support/OgnlExpressionParser.java +++ b/spring-binding/src/main/java/org/springframework/binding/expression/support/OgnlExpressionParser.java @@ -35,7 +35,7 @@ public class OgnlExpressionParser extends AbstractExpressionParser { return parseSettableExpression(expressionString); } - public SettableExpression parseSettableExpression(String expressionString) throws ParserException { + public SettableExpression doParseSettableExpression(String expressionString) throws ParserException { try { return new OgnlExpression(Ognl.parseExpression(expressionString)); } 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 new file mode 100644 index 00000000..5d27c0b3 --- /dev/null +++ b/spring-binding/src/test/java/org/springframework/binding/expression/support/SimpleExpressionTests.java @@ -0,0 +1,94 @@ +/* + * 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) { + } + } +} diff --git a/spring-webflow/changelog.txt b/spring-webflow/changelog.txt index e5f1e77e..5d5a58c6 100644 --- a/spring-webflow/changelog.txt +++ b/spring-webflow/changelog.txt @@ -12,6 +12,7 @@ Package org.springframework.binding * OgnlExpression now unwraps the ognl.OgnlException to make the real exception available to the caller (SWF-255). * OgnlExpressionParser now supports OGNL collection construction syntax (SWF-274). +* AbstractExpressionParser now has a doParseSettableExpression() template method. Package org.springframework.webflow.action * FormAction methods doBind() and createBinder() now declare "throws Exception".