Browse Source

binding string to list

pull/23217/head
Keith Donald 17 years ago
parent
commit
2be6ce0407
  1. 53
      org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericBinder.java
  2. 67
      org.springframework.context/src/test/java/org/springframework/ui/binding/support/GenericBinderTests.java

53
org.springframework.context/src/main/java/org/springframework/ui/binding/support/GenericBinder.java

@ -29,6 +29,8 @@ import java.util.Locale; @@ -29,6 +29,8 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.MessageSource;
import org.springframework.context.expression.MapAccessor;
import org.springframework.context.i18n.LocaleContextHolder;
@ -350,7 +352,7 @@ public class GenericBinder implements Binder { @@ -350,7 +352,7 @@ public class GenericBinder implements Binder {
public String format(Object selectableValue) {
Formatter formatter = getFormatter();
Class<?> formattedType = getFormattedObjectType(formatter);
Class<?> formattedType = getFormattedObjectType(formatter.getClass());
selectableValue = typeConverter.convert(selectableValue, formattedType);
return formatter.format(selectableValue, LocaleContextHolder.getLocale());
}
@ -404,7 +406,8 @@ public class GenericBinder implements Binder { @@ -404,7 +406,8 @@ public class GenericBinder implements Binder {
private BindingResult setStringValue(String formatted) {
Object parsed;
try {
parsed = getFormatter().parse(formatted, LocaleContextHolder.getLocale());
Formatter formatter = getFormatter();
parsed = formatter.parse(formatted, LocaleContextHolder.getLocale());
} catch (ParseException e) {
return new InvalidFormat(property.getExpressionString(), formatted, e);
}
@ -413,7 +416,7 @@ public class GenericBinder implements Binder { @@ -413,7 +416,7 @@ public class GenericBinder implements Binder {
private BindingResult setStringValues(String[] formatted) {
Formatter formatter = getFormatter();
Class parsedType = getFormattedObjectType(formatter);
Class parsedType = getFormattedObjectType(formatter.getClass());
if (parsedType == null) {
parsedType = String.class;
}
@ -466,36 +469,38 @@ public class GenericBinder implements Binder { @@ -466,36 +469,38 @@ public class GenericBinder implements Binder {
return new EvaluationError(property.getExpressionString(), userValue, e);
}
}
private Class getFormattedObjectType(Formatter formatter) {
private Class getFormattedObjectType(Class formatterClass) {
// TODO consider caching this info
Class classToIntrospect = formatter.getClass();
Class classToIntrospect = formatterClass;
while (classToIntrospect != null) {
Type[] genericInterfaces = classToIntrospect.getGenericInterfaces();
for (Type genericInterface : genericInterfaces) {
if (genericInterface instanceof ParameterizedType) {
ParameterizedType pInterface = (ParameterizedType) genericInterface;
if (Formatter.class.isAssignableFrom((Class) pInterface.getRawType())) {
return getParameterClass(pInterface.getActualTypeArguments()[0], formatter.getClass());
Type[] ifcs = classToIntrospect.getGenericInterfaces();
for (Type ifc : ifcs) {
if (ifc instanceof ParameterizedType) {
ParameterizedType paramIfc = (ParameterizedType) ifc;
Type rawType = paramIfc.getRawType();
if (Formatter.class.equals(rawType)) {
Type arg = paramIfc.getActualTypeArguments()[0];
if (arg instanceof TypeVariable) {
arg = GenericTypeResolver.resolveTypeVariable((TypeVariable) arg, formatterClass);
}
if (arg instanceof Class) {
return (Class) arg;
}
}
else if (ApplicationListener.class.isAssignableFrom((Class) rawType)) {
return getFormattedObjectType((Class) rawType);
}
}
else if (ApplicationListener.class.isAssignableFrom((Class) ifc)) {
return getFormattedObjectType((Class) ifc);
}
}
classToIntrospect = classToIntrospect.getSuperclass();
}
return null;
}
private Class getParameterClass(Type parameterType, Class converterClass) {
if (parameterType instanceof TypeVariable) {
parameterType = GenericTypeResolver.resolveTypeVariable((TypeVariable) parameterType, converterClass);
}
if (parameterType instanceof Class) {
return (Class) parameterType;
}
throw new IllegalArgumentException("Unable to obtain the java.lang.Class for parameterType [" + parameterType
+ "] on Formatter [" + converterClass.getName() + "]");
}
}
static class DefaultFormatter implements Formatter {
@ -736,6 +741,8 @@ public class GenericBinder implements Binder { @@ -736,6 +741,8 @@ public class GenericBinder implements Binder {
Throwable cause = accessException.getCause();
if (cause instanceof SpelEvaluationException
&& ((SpelEvaluationException) cause).getMessageCode() == SpelMessage.TYPE_CONVERSION_ERROR) {
// TODO this could be a ConverterExecutorNotFoundException if no suitable converter was found
cause.getCause().printStackTrace();
ConversionFailedException failure = (ConversionFailedException) cause.getCause();
MessageBuilder builder = new MessageBuilder(messageSource);
builder.code("conversionFailed");

67
org.springframework.context/src/test/java/org/springframework/ui/binding/support/GenericBinderTests.java

@ -6,6 +6,7 @@ import static org.junit.Assert.assertTrue; @@ -6,6 +6,7 @@ import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
@ -17,6 +18,7 @@ import junit.framework.Assert; @@ -17,6 +18,7 @@ import junit.framework.Assert;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.ui.binding.Binding;
@ -253,6 +255,49 @@ public class GenericBinderTests { @@ -253,6 +255,49 @@ public class GenericBinderTests {
assertEquals("35452", bean.addresses.get(0).zip);
}
@Test
public void bindToListSingleString() {
binder.addBinding("addresses").formatWith(new AddressListFormatter());
Map<String, String> values = new LinkedHashMap<String, String>();
values.put("addresses", "4655 Macy Lane:Melbourne:FL:35452,1234 Rostock Circle:Palm Bay:FL:32901,1977 Bel Aire Estates:Coker:AL:12345");
BindingResults results = binder.bind(values);
System.out.println(results);
Assert.assertEquals(3, bean.addresses.size());
assertEquals("4655 Macy Lane", bean.addresses.get(0).street);
assertEquals("Melbourne", bean.addresses.get(0).city);
assertEquals("FL", bean.addresses.get(0).state);
assertEquals("35452", bean.addresses.get(0).zip);
assertEquals("1234 Rostock Circle", bean.addresses.get(1).street);
assertEquals("Palm Bay", bean.addresses.get(1).city);
assertEquals("FL", bean.addresses.get(1).state);
assertEquals("32901", bean.addresses.get(1).zip);
assertEquals("1977 Bel Aire Estates", bean.addresses.get(2).street);
assertEquals("Coker", bean.addresses.get(2).city);
assertEquals("AL", bean.addresses.get(2).state);
assertEquals("12345", bean.addresses.get(2).zip);
}
@Test
public void getCollectionAsSingleValue() {
binder.addBinding("addresses").formatWith(new AddressListFormatter());
Address address1 = new Address();
address1.setStreet("s1");
address1.setCity("c1");
address1.setState("st1");
address1.setZip("z1");
Address address2 = new Address();
address2.setStreet("s2");
address2.setCity("c2");
address2.setState("st2");
address2.setZip("z2");
List<Address> addresses = new ArrayList<Address>(2);
addresses.add(address1);
addresses.add(address2);
bean.addresses = addresses;
String value = binder.getBinding("addresses").getValue();
assertEquals("s1:c1:st1:z1,s2:c2:st2:z2,", value);
}
@Test
public void bindToListHandleNullValueInNestedPath() {
binder.addBinding("addresses.street");
@ -403,6 +448,28 @@ public class GenericBinderTests { @@ -403,6 +448,28 @@ public class GenericBinderTests {
}
public static class AddressListFormatter implements Formatter<List<Address>> {
public String format(List<Address> addresses, Locale locale) {
StringBuilder builder = new StringBuilder();
for (Address address : addresses) {
builder.append(new AddressFormatter().format(address, locale));
builder.append(",");
}
return builder.toString();
}
public List<Address> parse(String formatted, Locale locale) throws ParseException {
String[] fields = formatted.split(",");
List<Address> addresses = new ArrayList<Address>(fields.length);
for (String field : fields) {
addresses.add(new AddressFormatter().parse(field, locale));
}
return addresses;
}
}
@Formatted(AddressFormatter.class)
public static class Address {
private String street;

Loading…
Cancel
Save