提交 e161c93f 编写于 作者: J Juergen Hoeller

full support for formatters on array/collection elements (SPR-6504)

上级 388edd7a
......@@ -53,11 +53,12 @@ class BeanTypeDescriptor extends TypeDescriptor {
/**
* Create a new BeanTypeDescriptor for the given bean property.
* @param methodParameter the target method parameter
* @param propertyDescriptor the corresponding JavaBean PropertyDescriptor
* @param methodParameter the target method parameter
* @param type the specific type to expose (may be an array/collection element)
*/
public BeanTypeDescriptor(MethodParameter methodParameter, PropertyDescriptor propertyDescriptor) {
super(methodParameter);
public BeanTypeDescriptor(PropertyDescriptor propertyDescriptor, MethodParameter methodParameter, Class type) {
super(methodParameter, type);
this.propertyDescriptor = propertyDescriptor;
}
......
......@@ -354,13 +354,15 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
public TypeDescriptor getPropertyTypeDescriptor(String propertyName) throws BeansException {
try {
PropertyDescriptor pd = getPropertyDescriptorInternal(propertyName);
String canonicalName = PropertyAccessorUtils.getPropertyName(propertyName);
PropertyDescriptor pd = getPropertyDescriptorInternal(canonicalName);
if (pd != null) {
Class type = getPropertyType(propertyName);
if (pd.getReadMethod() != null) {
return new BeanTypeDescriptor(new MethodParameter(pd.getReadMethod(), -1), pd);
return new BeanTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), type);
}
else if (pd.getWriteMethod() != null) {
return new BeanTypeDescriptor(BeanUtils.getWriteMethodParameter(pd), pd);
return new BeanTypeDescriptor(pd, BeanUtils.getWriteMethodParameter(pd), type);
}
}
}
......@@ -579,7 +581,8 @@ public class BeanWrapperImpl extends AbstractPropertyAccessor implements BeanWra
}
}
catch (Exception ex) {
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + name, "Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path: " + ex);
throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + name,
"Could not instantiate property type [" + type.getName() + "] to auto-grow nested property path: " + ex);
}
}
......
......@@ -117,10 +117,11 @@ public abstract class AbstractPropertyBindingResult extends AbstractBindingResul
if (this.conversionService != null) {
// Try custom formatter...
TypeDescriptor td = getPropertyAccessor().getPropertyTypeDescriptor(fixedField);
return this.conversionService.convert(value, td, TypeDescriptor.valueOf(String.class));
} else {
return value;
if (td != null) {
return this.conversionService.convert(value, td, TypeDescriptor.valueOf(String.class));
}
}
return value;
}
/**
......
......@@ -18,6 +18,7 @@ package org.springframework.format.number;
import java.math.BigDecimal;
import java.util.Locale;
import java.util.List;
import org.junit.After;
import static org.junit.Assert.*;
......@@ -102,6 +103,43 @@ public class NumberFormattingTests {
assertEquals("1,25.00", binder.getBindingResult().getFieldValue("pattern"));
}
@Test
public void testPatternArrayFormatting() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("patternArray", new String[] {"1,25.00", "2,35.00"});
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("1,25.00", binder.getBindingResult().getFieldValue("patternArray[0]"));
assertEquals("2,35.00", binder.getBindingResult().getFieldValue("patternArray[1]"));
propertyValues = new MutablePropertyValues();
propertyValues.add("patternArray[0]", "1,25.00");
propertyValues.add("patternArray[1]", "2,35.00");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("1,25.00", binder.getBindingResult().getFieldValue("patternArray[0]"));
assertEquals("2,35.00", binder.getBindingResult().getFieldValue("patternArray[1]"));
}
@Test
public void testPatternListFormatting() {
MutablePropertyValues propertyValues = new MutablePropertyValues();
propertyValues.add("patternList", new String[] {"1,25.00", "2,35.00"});
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("1,25.00", binder.getBindingResult().getFieldValue("patternList[0]"));
assertEquals("2,35.00", binder.getBindingResult().getFieldValue("patternList[1]"));
propertyValues = new MutablePropertyValues();
propertyValues.add("patternList[0]", "1,25.00");
propertyValues.add("patternList[1]", "2,35.00");
binder.bind(propertyValues);
assertEquals(0, binder.getBindingResult().getErrorCount());
assertEquals("1,25.00", binder.getBindingResult().getFieldValue("patternList[0]"));
assertEquals("2,35.00", binder.getBindingResult().getFieldValue("patternList[1]"));
}
@SuppressWarnings("unused")
private static class TestBean {
......@@ -119,6 +157,12 @@ public class NumberFormattingTests {
@NumberFormat(pattern="#,##.00")
private BigDecimal pattern;
@NumberFormat(pattern="#,##.00")
private BigDecimal[] patternArray;
@NumberFormat(pattern="#,##.00")
private List[] patternList;
public Integer getNumberDefault() {
return numberDefault;
}
......@@ -159,6 +203,21 @@ public class NumberFormattingTests {
this.pattern = pattern;
}
public BigDecimal[] getPatternArray() {
return patternArray;
}
public void setPatternArray(BigDecimal[] patternArray) {
this.patternArray = patternArray;
}
public List[] getPatternList() {
return patternList;
}
public void setPatternList(List[] patternList) {
this.patternList = patternList;
}
}
}
\ No newline at end of file
}
......@@ -20,6 +20,7 @@ package org.springframework.core.convert;
* Thrown when an attempt to execute a type conversion fails.
*
* @author Keith Donald
* @author Juergen Hoeller
* @since 3.0
*/
public final class ConversionFailedException extends ConversionException {
......@@ -37,8 +38,8 @@ public final class ConversionFailedException extends ConversionException {
* @param cause the cause of the conversion failure
*/
public ConversionFailedException(TypeDescriptor sourceType, TypeDescriptor targetType, Object value, Throwable cause) {
super("Unable to convert value " + value + " from type [" + sourceType.getName() + "] to type [" +
targetType.getName() + "]; reason = '" + cause.getMessage() + "'", cause);
super("Unable to convert value " + value + " from type '" + sourceType.getName() +
"' to type '" + targetType.getName() + "'", cause);
this.sourceType = sourceType;
this.targetType = targetType;
}
......
......@@ -77,6 +77,19 @@ public class TypeDescriptor {
this.methodParameter = methodParameter;
}
/**
* Create a new type descriptor from a method or constructor parameter.
* <p>Use this constructor when a target conversion point originates from a method parameter,
* such as a setter method argument.
* @param methodParameter the MethodParameter to wrap
* @param type the specific type to expose (may be an array/collection element)
*/
protected TypeDescriptor(MethodParameter methodParameter, Class type) {
Assert.notNull(methodParameter, "MethodParameter must not be null");
this.methodParameter = methodParameter;
this.type = type;
}
/**
* Create a new type descriptor for a field.
* Use this constructor when a target conversion point originates from a field.
......@@ -158,16 +171,11 @@ public class TypeDescriptor {
}
/**
* Returns the name of this type; the fully qualified classname.
* Returns the name of this type: the fully qualified class name.
*/
public String getName() {
Class<?> type = getType();
if (type != null) {
return getType().getName();
}
else {
return null;
}
return (type != null ? ClassUtils.getQualifiedName(type) : null);
}
/**
......@@ -396,17 +404,16 @@ public class TypeDescriptor {
public String toString() {
if (this == TypeDescriptor.NULL) {
return "[TypeDescriptor.NULL]";
return "TypeDescriptor.NULL";
}
else {
StringBuilder builder = new StringBuilder();
builder.append("[TypeDescriptor ");
builder.append("TypeDescriptor ");
Annotation[] anns = getAnnotations();
for (Annotation ann : anns) {
builder.append("@").append(ann.annotationType().getName()).append(' ');
}
builder.append(getType().getName());
builder.append("]");
builder.append(ClassUtils.getQualifiedName(getType()));
return builder.toString();
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册