diff --git a/spring-binding/src/main/java/org/springframework/binding/method/Parameter.java b/spring-binding/src/main/java/org/springframework/binding/method/Parameter.java index e1d49f83..e6f65798 100644 --- a/spring-binding/src/main/java/org/springframework/binding/method/Parameter.java +++ b/spring-binding/src/main/java/org/springframework/binding/method/Parameter.java @@ -61,7 +61,7 @@ public class Parameter { } /** - * Returns the method name. + * Returns the parameter name. */ public Expression getName() { return name; diff --git a/spring-binding/src/main/java/org/springframework/binding/method/TextToMethodSignature.java b/spring-binding/src/main/java/org/springframework/binding/method/TextToMethodSignature.java index c1f89f04..ab77b827 100644 --- a/spring-binding/src/main/java/org/springframework/binding/method/TextToMethodSignature.java +++ b/spring-binding/src/main/java/org/springframework/binding/method/TextToMethodSignature.java @@ -19,6 +19,7 @@ import org.springframework.binding.convert.ConversionContext; import org.springframework.binding.convert.ConversionException; import org.springframework.binding.convert.ConversionService; import org.springframework.binding.convert.support.ConversionServiceAwareConverter; +import org.springframework.binding.expression.Expression; import org.springframework.util.StringUtils; /** @@ -33,13 +34,15 @@ import org.springframework.util.StringUtils; * the method to invoke, where the method is expected to have parameters * delimited by a comma. In this example, the method has two parameters. The * type is either the fully-qualified class of the argument OR a known type - * alias. The name is the logical name of the argument, which is used during - * data binding to retrieve the argument value. + * alias OR left out althogether. The name is the logical name of the argument, + * which is used during data binding to retrieve the argument value + * (typically an expression). * * * @see MethodSignature * * @author Keith Donald + * @author Erwin Vervaet */ public class TextToMethodSignature extends ConversionServiceAwareConverter { @@ -83,14 +86,18 @@ public class TextToMethodSignature extends ConversionServiceAwareConverter { String[] paramArray = StringUtils.commaDelimitedListToStringArray(delimParamList); Parameters params = new Parameters(paramArray.length); for (int i = 0; i < paramArray.length; i++) { + // param could be of the form "type name", "name", "type ${name}" or "${name}" String param = paramArray[i].trim(); - String[] typeAndName = StringUtils.split(param, " "); - if (typeAndName != null && typeAndName.length == 2) { - Class type = (Class)converterFor(String.class, Class.class).execute(typeAndName[0]); - params.add(new Parameter(type, parseExpression(typeAndName[1].trim()))); + int space = param.indexOf(' '); + if (space == -1 || space > param.indexOf('$')) { + // "name" or "${name}" + params.add(new Parameter(null, parseExpression(param))); } else { - params.add(new Parameter(null, parseExpression(param))); + // "type name" or "type ${name}" + Class type = (Class)fromStringTo(Class.class).execute(param.substring(0, space).trim()); + Expression name = parseExpression(param.substring(space + 1).trim()); + params.add(new Parameter(type, name)); } } return new MethodSignature(methodName, params); diff --git a/spring-binding/src/test/java/org/springframework/binding/method/TextToMethodSignatureTests.java b/spring-binding/src/test/java/org/springframework/binding/method/TextToMethodSignatureTests.java new file mode 100644 index 00000000..c5a9fdde --- /dev/null +++ b/spring-binding/src/test/java/org/springframework/binding/method/TextToMethodSignatureTests.java @@ -0,0 +1,97 @@ +/* + * 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.method; + +import junit.framework.TestCase; + +import org.springframework.binding.convert.support.DefaultConversionService; +import org.springframework.binding.convert.support.TextToExpression; +import org.springframework.binding.expression.support.OgnlExpressionParser; + +/** + * Test case for {@link TextToMethodSignature}. + * + * @author Erwin Vervaet + */ +public class TextToMethodSignatureTests extends TestCase { + + private TextToMethodSignature converter; + + protected void setUp() throws Exception { + DefaultConversionService conversionService = new DefaultConversionService(); + conversionService.addConverter(new TextToExpression(new OgnlExpressionParser())); + converter = new TextToMethodSignature(conversionService); + } + + public void testParseNoArguments() { + MethodSignature signature = (MethodSignature)converter.convert("foo"); + assertEquals("foo", signature.getMethodName()); + assertEquals(0, signature.getParameters().size()); + + signature = (MethodSignature)converter.convert("foo"); + assertEquals("foo", signature.getMethodName()); + assertEquals(0, signature.getParameters().size()); + } + + public void testSingleArgument() { + MethodSignature signature = (MethodSignature)converter.convert("foo(${flowScope.bar})"); + assertEquals("foo", signature.getMethodName()); + assertEquals(1, signature.getParameters().size()); + assertNull(signature.getParameters().getParameter(0).getType()); + assertEquals("flowScope.bar", signature.getParameters().getParameter(0).getName().toString()); + + signature = (MethodSignature)converter.convert("foo(${'Foo' + flowScope.bar})"); + assertEquals("foo", signature.getMethodName()); + assertEquals(1, signature.getParameters().size()); + assertEquals("\"Foo\" + flowScope.bar", signature.getParameters().getParameter(0).getName().toString()); + } + + public void testSingleArgumentWithType() { + MethodSignature signature = (MethodSignature)converter.convert("foo(java.lang.String ${flowScope.bar})"); + assertEquals("foo", signature.getMethodName()); + assertEquals(1, signature.getParameters().size()); + assertEquals(String.class, signature.getParameters().getParameter(0).getType()); + assertEquals("flowScope.bar", signature.getParameters().getParameter(0).getName().toString()); + + signature = (MethodSignature)converter.convert("foo(long ${flowScope.bar})"); + assertEquals("foo", signature.getMethodName()); + assertEquals(1, signature.getParameters().size()); + assertEquals(Long.class, signature.getParameters().getParameter(0).getType()); + assertEquals("flowScope.bar", signature.getParameters().getParameter(0).getName().toString()); + } + + public void testMultipleArguments() { + MethodSignature signature = (MethodSignature)converter.convert( + "foo(${flowScope.bar}, ${externalContext.requestParameterMap.test})"); + assertEquals("foo", signature.getMethodName()); + assertEquals(2, signature.getParameters().size()); + assertNull(signature.getParameters().getParameter(0).getType()); + assertEquals("flowScope.bar", signature.getParameters().getParameter(0).getName().toString()); + assertNull(signature.getParameters().getParameter(1).getType()); + assertEquals("externalContext.requestParameterMap.test", signature.getParameters().getParameter(1).getName().toString()); + } + + public void testMultipleArgumentsWithType() { + MethodSignature signature = (MethodSignature)converter.convert( + "foo(long ${flowScope.bar}, java.lang.String ${externalContext.requestParameterMap.test})"); + assertEquals("foo", signature.getMethodName()); + assertEquals(2, signature.getParameters().size()); + assertEquals(Long.class, signature.getParameters().getParameter(0).getType()); + assertEquals("flowScope.bar", signature.getParameters().getParameter(0).getName().toString()); + assertEquals(String.class, signature.getParameters().getParameter(1).getType()); + assertEquals("externalContext.requestParameterMap.test", signature.getParameters().getParameter(1).getName().toString()); + } +}