SWF-443 - Enhance MethodInvoker to allow type conversion on a method result.

This commit is contained in:
Jeremy Grelle
2008-01-25 21:47:17 +00:00
parent 856f9ce201
commit ea3135f62f
3 changed files with 45 additions and 17 deletions

View File

@@ -26,17 +26,18 @@ import org.springframework.core.style.StylerUtils;
import org.springframework.util.CachingMapDecorator;
/**
* A helper for invoking typed methods on abritrary objects, with support for argument value type conversion from values
* retrieved from a argument attribute source.
* A helper for invoking typed methods on arbitrary objects, with support for argument value type conversion from values
* retrieved from an argument attribute source, and conversion of the result to a desired type.
*
* @author Keith Donald
* @author Jeremy Grelle
*/
public class MethodInvoker {
private static final Log logger = LogFactory.getLog(MethodInvoker.class);
/**
* Conversion service for converting arguments to the neccessary type if required.
* Conversion service for converting arguments to the necessary type if required.
*/
private ConversionService conversionService = new DefaultConversionService();
@@ -90,7 +91,7 @@ public class MethodInvoker {
+ StylerUtils.style(arguments) + " on bean [" + bean + "]");
}
Object returnValue = method.invoke(bean, arguments);
Object returnValue = applyTypeConversion(method.invoke(bean, arguments), signature.getDesiredResultType());
if (logger.isDebugEnabled()) {
logger.debug("Invoked method with signature [" + key + "] returned value [" + returnValue + "]");
}
@@ -103,16 +104,16 @@ public class MethodInvoker {
}
/**
* Apply type conversion on the event parameter if neccessary
* Apply type conversion on the supplied value
*
* @param parameterValue the raw argument value
* @param targetType the target type for the matching method argument
* @return the converted method argument
* @param value the raw value to be converted
* @param targetType the target type for the conversion
* @return the converted result
*/
protected Object applyTypeConversion(Object parameterValue, Class targetType) {
if (parameterValue == null || targetType == null) {
return parameterValue;
protected Object applyTypeConversion(Object value, Class targetType) {
if (value == null || targetType == null) {
return value;
}
return conversionService.getConversionExecutor(parameterValue.getClass(), targetType).execute(parameterValue);
return conversionService.getConversionExecutor(value.getClass(), targetType).execute(value);
}
}

View File

@@ -24,6 +24,7 @@ import org.springframework.util.Assert;
* {@link MethodInvoker method invoker attempt}.
*
* @author Keith Donald
* @author Jeremy Grelle
*/
public class MethodSignature {
@@ -37,12 +38,17 @@ public class MethodSignature {
*/
private Parameters parameters;
/**
* The desired result type of the method invocation
*/
private Class desiredResultType;
/**
* Creates a method signature with no parameters.
* @param methodName the name of the method
*/
public MethodSignature(String methodName) {
this(methodName, Parameters.NONE);
this(methodName, Parameters.NONE, null);
}
/**
@@ -51,19 +57,21 @@ public class MethodSignature {
* @param parameter the method parameter
*/
public MethodSignature(String methodName, Parameter parameter) {
this(methodName, new Parameters(parameter));
this(methodName, new Parameters(parameter), null);
}
/**
* Creates a method signature with a list of parameters.
* @param methodName the name of the method
* @param parameters the method parameters
* @param desiredResultType the desired result type of the method invocation
*/
public MethodSignature(String methodName, Parameters parameters) {
public MethodSignature(String methodName, Parameters parameters, Class desiredResultType) {
Assert.notNull(methodName, "The method name is required");
Assert.notNull(parameters, "The parameters are required");
this.methodName = methodName;
this.parameters = parameters;
this.desiredResultType = desiredResultType;
}
/**
@@ -80,6 +88,14 @@ public class MethodSignature {
return parameters;
}
/**
* Returns the desired result type of the method invocation
* @return the desired result type
*/
public Class getDesiredResultType() {
return desiredResultType;
}
public boolean equals(Object obj) {
if (!(obj instanceof MethodSignature)) {
return false;

View File

@@ -23,6 +23,7 @@ import org.springframework.binding.expression.support.StaticExpression;
* Unit tests for {@link org.springframework.binding.method.MethodInvoker}.
*
* @author Erwin Vervaet
* @author Jeremy Grelle
*/
public class MethodInvokerTests extends TestCase {
@@ -55,17 +56,23 @@ public class MethodInvokerTests extends TestCase {
Parameters parameters = new Parameters();
Bean bean = new Bean();
parameters.add(new Parameter(Bean.class, new StaticExpression(bean)));
MethodSignature method = new MethodSignature("testBeanArg", parameters);
MethodSignature method = new MethodSignature("testBeanArg", parameters, null);
assertSame(bean, methodInvoker.invoke(method, new TestObject(), null));
}
public void testPrimitiveArg() {
Parameters parameters = new Parameters();
parameters.add(new Parameter(Boolean.class, new StaticExpression(Boolean.TRUE)));
MethodSignature method = new MethodSignature("testPrimitiveArg", parameters);
MethodSignature method = new MethodSignature("testPrimitiveArg", parameters, null);
assertEquals(Boolean.TRUE, methodInvoker.invoke(method, new TestObject(), null));
}
public void testResultConversion() {
Parameters parameters = Parameters.NONE;
MethodSignature method = new MethodSignature("testConvertResult", parameters, Class.class);
assertEquals(Object.class, methodInvoker.invoke(method, new TestObject(), null));
}
private static class TestObject {
public void test() {
@@ -76,6 +83,10 @@ public class MethodInvokerTests extends TestCase {
return bean;
}
public String testConvertResult() {
return "java.lang.Object";
}
public boolean testPrimitiveArg(boolean primitive) {
return primitive;
}