all tests back compiling, still a few failing marked ignored

This commit is contained in:
Keith Donald 2009-07-20 22:05:28 +00:00
parent 603ffe80c8
commit dc5faec189
4 changed files with 82 additions and 103 deletions

View File

@ -240,6 +240,7 @@ public class GenericBinder implements Binder {
public GenericBindingRule(String property, Class modelClass) { public GenericBindingRule(String property, Class modelClass) {
this.modelClass = modelClass; this.modelClass = modelClass;
this.property = findPropertyDescriptor(property); this.property = findPropertyDescriptor(property);
nestedBindingRules = new HashMap<String, GenericBindingRule>();
} }
// implementing BindingContext // implementing BindingContext

View File

@ -1,6 +1,3 @@
/**
*
*/
package org.springframework.ui.binding.support; package org.springframework.ui.binding.support;
import java.beans.PropertyDescriptor; import java.beans.PropertyDescriptor;
@ -9,6 +6,7 @@ import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable; import java.lang.reflect.TypeVariable;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -51,7 +49,7 @@ public class PropertyBinding implements Binding {
private Map<Integer, ListElementBinding> listElementBindings; private Map<Integer, ListElementBinding> listElementBindings;
private Class<?> elementType; private Class<?> elementType;
public PropertyBinding(PropertyDescriptor property, Object object, BindingContext bindingContext) { public PropertyBinding(PropertyDescriptor property, Object object, BindingContext bindingContext) {
this.property = property; this.property = property;
this.object = object; this.object = object;
@ -148,7 +146,7 @@ public class PropertyBinding implements Binding {
} catch (ConversionFailedException e) { } catch (ConversionFailedException e) {
this.sourceValue = sourceValue; this.sourceValue = sourceValue;
invalidSourceValueCause = e; invalidSourceValueCause = e;
status = BindingStatus.INVALID_SOURCE_VALUE; status = BindingStatus.INVALID_SOURCE_VALUE;
} }
} }
} }
@ -267,7 +265,7 @@ public class PropertyBinding implements Binding {
public Class<?> getValueType() { public Class<?> getValueType() {
return property.getPropertyType(); return property.getPropertyType();
} }
public TypeDescriptor<?> getValueTypeDescriptor() { public TypeDescriptor<?> getValueTypeDescriptor() {
return new TypeDescriptor(new MethodParameter(property.getReadMethod(), -1)); return new TypeDescriptor(new MethodParameter(property.getReadMethod(), -1));
} }
@ -281,7 +279,7 @@ public class PropertyBinding implements Binding {
public Binding getBinding(String property) { public Binding getBinding(String property) {
assertScalarProperty(); assertScalarProperty();
if (getValue() == null) { if (getValue() == null) {
createValue(); getModel().setValue(newValue(getValueType()));
} }
return bindingContext.getBinding(property, getValue()); return bindingContext.getBinding(property, getValue());
} }
@ -292,6 +290,10 @@ public class PropertyBinding implements Binding {
public Binding getListElementBinding(int index) { public Binding getListElementBinding(int index) {
assertListProperty(); assertListProperty();
if (index < 0) {
throw new IllegalArgumentException("Invalid index " + index);
}
growListIfNecessary(index);
ListElementBinding binding = listElementBindings.get(index); ListElementBinding binding = listElementBindings.get(index);
if (binding == null) { if (binding == null) {
binding = new ListElementBinding(index); binding = new ListElementBinding(index);
@ -327,35 +329,24 @@ public class PropertyBinding implements Binding {
return format(value, formatter); return format(value, formatter);
} }
// subclassing hooks
protected Formatter getFormatter() {
return bindingContext.getFormatter();
}
// internal helpers
private String format(Object value, Formatter formatter) { private String format(Object value, Formatter formatter) {
Class<?> formattedType = getFormattedObjectType(formatter.getClass()); Class<?> formattedType = getFormattedObjectType(formatter.getClass());
value = bindingContext.getTypeConverter().convert(value, formattedType); value = bindingContext.getTypeConverter().convert(value, formattedType);
return formatter.format(value, getLocale()); return formatter.format(value, getLocale());
} }
// internal helpers
protected Formatter getFormatter() {
return bindingContext.getFormatter();
}
private Locale getLocale() { private Locale getLocale() {
return LocaleContextHolder.getLocale(); return LocaleContextHolder.getLocale();
} }
private void createValue() {
try {
Object value = getModel().getValueType().newInstance();
getModel().setValue(value);
} catch (InstantiationException e) {
throw new IllegalStateException("Could not lazily instantiate object of type ["
+ getModel().getValueType().getName() + "] to access property" + property, e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not lazily instantiate object of type ["
+ getModel().getValueType().getName() + "] to access property" + property, e);
}
}
private Class getFormattedObjectType(Class formatterClass) { private Class getFormattedObjectType(Class formatterClass) {
Class classToIntrospect = formatterClass; Class classToIntrospect = formatterClass;
while (classToIntrospect != null) { while (classToIntrospect != null) {
@ -431,12 +422,43 @@ public class PropertyBinding implements Binding {
return property.getWriteMethod() != null; return property.getWriteMethod() != null;
} }
private void growListIfNecessary(int index) {
List list = (List) getValue();
if (list == null) {
getModel().setValue(newListValue(getValueType()));
list = (List) getValue();
}
if (index >= list.size()) {
for (int i = list.size(); i <= index; i++) {
list.add(newValue(elementType));
}
}
}
private Object newListValue(Class<?> type) {
if (type.isInterface()) {
return newValue(ArrayList.class);
} else {
return newValue(type);
}
}
private Object newValue(Class<?> type) {
try {
return type.newInstance();
} catch (InstantiationException e) {
throw new IllegalStateException("Could not instantiate element of type [" + type.getName() + "]", e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not instantiate element of type [" + type.getName() + "]", e);
}
}
static abstract class AbstractAlert implements Alert { static abstract class AbstractAlert implements Alert {
public String toString() { public String toString() {
return getCode() + " - " + getMessage(); return getCode() + " - " + getMessage();
} }
} }
class ListElementBinding extends PropertyBinding { class ListElementBinding extends PropertyBinding {
private int index; private int index;
@ -444,13 +466,12 @@ public class PropertyBinding implements Binding {
public ListElementBinding(int index) { public ListElementBinding(int index) {
super(property, object, bindingContext); super(property, object, bindingContext);
this.index = index; this.index = index;
growListIfNecessary();
} }
protected Formatter getFormatter() { protected Formatter getFormatter() {
return bindingContext.getElementFormatter(); return bindingContext.getElementFormatter();
} }
public Model getModel() { public Model getModel() {
return new Model() { return new Model() {
public Object getValue() { public Object getValue() {
@ -464,7 +485,7 @@ public class PropertyBinding implements Binding {
return getValue().getClass(); return getValue().getClass();
} }
} }
public TypeDescriptor<?> getValueTypeDescriptor() { public TypeDescriptor<?> getValueTypeDescriptor() {
return TypeDescriptor.valueOf(getValueType()); return TypeDescriptor.valueOf(getValueType());
} }
@ -474,34 +495,12 @@ public class PropertyBinding implements Binding {
} }
}; };
} }
// internal helpers // internal helpers
private void growListIfNecessary() {
if (index >= getList().size()) {
for (int i = getList().size(); i <= index; i++) {
addValue();
}
}
}
private List getList() { private List getList() {
return (List) PropertyBinding.this.getValue(); return (List) PropertyBinding.this.getValue();
} }
private void addValue() {
try {
Object value = getValueType().newInstance();
getList().add(value);
} catch (InstantiationException e) {
throw new IllegalStateException("Could not lazily instantiate model of type ["
+ getValueType().getName() + "] to grow List", e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Could not lazily instantiate model of type ["
+ getValueType().getName() + "] to grow List", e);
}
}
} }
} }

View File

@ -15,8 +15,11 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import junit.framework.Assert;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.ui.binding.Binding; import org.springframework.ui.binding.Binding;
@ -50,11 +53,6 @@ public class GenericBinderTests {
LocaleContextHolder.setLocale(null); LocaleContextHolder.setLocale(null);
} }
@Test
public void testPlaceholder() {
}
@Test @Test
public void bindSingleValuesWithDefaultTypeConverterConversion() { public void bindSingleValuesWithDefaultTypeConverterConversion() {
GenericBinder binder = new GenericBinder(bean); GenericBinder binder = new GenericBinder(bean);
@ -192,6 +190,7 @@ public class GenericBinderTests {
assertEquals("Please enter an integer in format ### for the integer field; you entered bogus", b.getStatusAlert().getMessage()); assertEquals("Please enter an integer in format ### for the integer field; you entered bogus", b.getStatusAlert().getMessage());
} }
@SuppressWarnings("unchecked")
@Test @Test
public void getBindingMultiValued() { public void getBindingMultiValued() {
Binding b = binder.getBinding("foos"); Binding b = binder.getBinding("foos");
@ -223,25 +222,22 @@ public class GenericBinderTests {
assertEquals(FooEnum.BAZ, b.getValue()); assertEquals(FooEnum.BAZ, b.getValue());
} }
/*
@Test @Test
public void getBindingMultiValuedTypeConversionFailure() { public void getBindingMultiValuedTypeConversionFailure() {
binder.addBinding("foos");
Binding b = binder.getBinding("foos"); Binding b = binder.getBinding("foos");
assertTrue(b.isIndexable()); assertTrue(b.isList());
assertEquals(0, b.getCollectionValues().length); assertEquals(null, b.getValue());
BindingResult result = b.setValue(new String[] { "BAR", "BOGUS", "BOOP" }); b.applySourceValue(new String[] { "BAR", "BOGUS", "BOOP" });
assertTrue(result.isFailure()); assertEquals(BindingStatus.INVALID_SOURCE_VALUE, b.getStatus());
assertEquals("conversionFailed", result.getAlert().getCode()); assertEquals("typeMismatch", b.getStatusAlert().getCode());
} }
@Test @Test
public void bindToList() { public void bindToList() {
binder.addBinding("addresses");
Map<String, String[]> values = new LinkedHashMap<String, String[]>(); Map<String, String[]> values = new LinkedHashMap<String, String[]>();
values.put("addresses", new String[] { "4655 Macy Lane:Melbourne:FL:35452", "1234 Rostock Circle:Palm Bay:FL:32901", "1977 Bel Aire Estates:Coker:AL:12345" }); values.put("addresses", new String[] { "4655 Macy Lane:Melbourne:FL:35452", "1234 Rostock Circle:Palm Bay:FL:32901", "1977 Bel Aire Estates:Coker:AL:12345" });
binder.bind(values); binder.bind(values);
Assert.assertEquals(3, bean.addresses.size()); assertEquals(3, bean.addresses.size());
assertEquals("4655 Macy Lane", bean.addresses.get(0).street); assertEquals("4655 Macy Lane", bean.addresses.get(0).street);
assertEquals("Melbourne", bean.addresses.get(0).city); assertEquals("Melbourne", bean.addresses.get(0).city);
assertEquals("FL", bean.addresses.get(0).state); assertEquals("FL", bean.addresses.get(0).state);
@ -250,7 +246,6 @@ public class GenericBinderTests {
@Test @Test
public void bindToListElements() { public void bindToListElements() {
binder.addBinding("addresses");
Map<String, String> values = new LinkedHashMap<String, String>(); Map<String, String> values = new LinkedHashMap<String, String>();
values.put("addresses[0]", "4655 Macy Lane:Melbourne:FL:35452"); values.put("addresses[0]", "4655 Macy Lane:Melbourne:FL:35452");
values.put("addresses[1]", "1234 Rostock Circle:Palm Bay:FL:32901"); values.put("addresses[1]", "1234 Rostock Circle:Palm Bay:FL:32901");
@ -265,11 +260,12 @@ public class GenericBinderTests {
@Test @Test
public void bindToListSingleString() { public void bindToListSingleString() {
binder.addBinding("addresses"); GenericFormatterRegistry formatterRegistry = new GenericFormatterRegistry();
binder.registerFormatter(new GenericCollectionPropertyType(List.class, Address.class), new AddressListFormatter()); formatterRegistry.add(new GenericCollectionPropertyType(List.class, Address.class), new AddressListFormatter());
binder.setFormatterRegistry(formatterRegistry);
Map<String, String> values = new LinkedHashMap<String, String>(); 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"); 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); binder.bind(values);
Assert.assertEquals(3, bean.addresses.size()); Assert.assertEquals(3, bean.addresses.size());
assertEquals("4655 Macy Lane", bean.addresses.get(0).street); assertEquals("4655 Macy Lane", bean.addresses.get(0).street);
assertEquals("Melbourne", bean.addresses.get(0).city); assertEquals("Melbourne", bean.addresses.get(0).city);
@ -288,8 +284,6 @@ public class GenericBinderTests {
@Test @Test
@Ignore @Ignore
public void bindToListSingleStringNoListFormatter() { public void bindToListSingleStringNoListFormatter() {
binder.addBinding("addresses");
//binder.registerFormatter(new GenericCollectionPropertyType(List.class, Address.class), new AddressListFormatter());
Map<String, String> values = new LinkedHashMap<String, String>(); 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"); 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); BindingResults results = binder.bind(values);
@ -310,8 +304,9 @@ public class GenericBinderTests {
@Test @Test
public void getListAsSingleString() { public void getListAsSingleString() {
binder.addBinding("addresses"); GenericFormatterRegistry formatterRegistry = new GenericFormatterRegistry();
binder.registerFormatter(new GenericCollectionPropertyType(List.class, Address.class), new AddressListFormatter()); formatterRegistry.add(new GenericCollectionPropertyType(List.class, Address.class), new AddressListFormatter());
binder.setFormatterRegistry(formatterRegistry);
Address address1 = new Address(); Address address1 = new Address();
address1.setStreet("s1"); address1.setStreet("s1");
address1.setCity("c1"); address1.setCity("c1");
@ -326,14 +321,13 @@ public class GenericBinderTests {
addresses.add(address1); addresses.add(address1);
addresses.add(address2); addresses.add(address2);
bean.addresses = addresses; bean.addresses = addresses;
String value = binder.getBinding("addresses").getValue(); String value = binder.getBinding("addresses").getRenderValue();
assertEquals("s1:c1:st1:z1,s2:c2:st2:z2,", value); assertEquals("s1:c1:st1:z1,s2:c2:st2:z2,", value);
} }
@Test @Test
@Ignore @Ignore
public void getListAsSingleStringNoFormatter() { public void getListAsSingleStringNoFormatter() {
binder.addBinding("addresses");
Address address1 = new Address(); Address address1 = new Address();
address1.setStreet("s1"); address1.setStreet("s1");
address1.setCity("c1"); address1.setCity("c1");
@ -348,26 +342,17 @@ public class GenericBinderTests {
addresses.add(address1); addresses.add(address1);
addresses.add(address2); addresses.add(address2);
bean.addresses = addresses; bean.addresses = addresses;
String value = binder.getBinding("addresses").getValue(); String value = binder.getBinding("addresses").getRenderValue();
assertEquals("s1:c1:st1:z1,s2:c2:st2:z2,", value); assertEquals("s1:c1:st1:z1,s2:c2:st2:z2,", value);
} }
@Test @Test
@Ignore
public void bindToListHandleNullValueInNestedPath() { public void bindToListHandleNullValueInNestedPath() {
binder.addBinding("addresses.street");
binder.addBinding("addresses.city");
binder.addBinding("addresses.state");
binder.addBinding("addresses.zip");
Map<String, String> values = new LinkedHashMap<String, String>(); Map<String, String> values = new LinkedHashMap<String, String>();
// EL configured with some options from SpelExpressionParserConfiguration:
// (see where Binder creates the parser)
// - new addresses List is created if null // - new addresses List is created if null
// - new entries automatically built if List is currently too short - all new entries // - new entries automatically built if List is currently too short - all new entries
// are new instances of the type of the list entry, they are not null. // are new instances of the type of the list entry, they are not null.
// not currently doing anything for maps or arrays
values.put("addresses[0].street", "4655 Macy Lane"); values.put("addresses[0].street", "4655 Macy Lane");
values.put("addresses[0].city", "Melbourne"); values.put("addresses[0].city", "Melbourne");
values.put("addresses[0].state", "FL"); values.put("addresses[0].state", "FL");
@ -386,6 +371,7 @@ public class GenericBinderTests {
values.put("addresses[5].zip", "32901"); values.put("addresses[5].zip", "32901");
BindingResults results = binder.bind(values); BindingResults results = binder.bind(values);
System.out.println(results);
Assert.assertEquals(6, bean.addresses.size()); Assert.assertEquals(6, bean.addresses.size());
Assert.assertEquals("Palm Bay", bean.addresses.get(1).city); Assert.assertEquals("Palm Bay", bean.addresses.get(1).city);
Assert.assertNotNull(bean.addresses.get(2)); Assert.assertNotNull(bean.addresses.get(2));
@ -393,8 +379,8 @@ public class GenericBinderTests {
} }
@Test @Test
@Ignore
public void bindToMap() { public void bindToMap() {
binder.addBinding("favoriteFoodsByGroup");
Map<String, String[]> values = new LinkedHashMap<String, String[]>(); Map<String, String[]> values = new LinkedHashMap<String, String[]>();
values.put("favoriteFoodsByGroup", new String[] { "DAIRY=Milk", "FRUIT=Peaches", "MEAT=Ham" }); values.put("favoriteFoodsByGroup", new String[] { "DAIRY=Milk", "FRUIT=Peaches", "MEAT=Ham" });
BindingResults results = binder.bind(values); BindingResults results = binder.bind(values);
@ -405,8 +391,8 @@ public class GenericBinderTests {
} }
@Test @Test
@Ignore
public void bindToMapElements() { public void bindToMapElements() {
binder.addBinding("favoriteFoodsByGroup");
Map<String, String> values = new LinkedHashMap<String, String>(); Map<String, String> values = new LinkedHashMap<String, String>();
values.put("favoriteFoodsByGroup['DAIRY']", "Milk"); values.put("favoriteFoodsByGroup['DAIRY']", "Milk");
values.put("favoriteFoodsByGroup['FRUIT']", "Peaches"); values.put("favoriteFoodsByGroup['FRUIT']", "Peaches");
@ -420,7 +406,6 @@ public class GenericBinderTests {
@Test @Test
public void bindToMapSingleString() { public void bindToMapSingleString() {
binder.addBinding("favoriteFoodsByGroup");
Map<String, String> values = new LinkedHashMap<String, String>(); Map<String, String> values = new LinkedHashMap<String, String>();
values.put("favoriteFoodsByGroup", "DAIRY=Milk FRUIT=Peaches MEAT=Ham"); values.put("favoriteFoodsByGroup", "DAIRY=Milk FRUIT=Peaches MEAT=Ham");
BindingResults results = binder.bind(values); BindingResults results = binder.bind(values);
@ -433,22 +418,17 @@ public class GenericBinderTests {
@Test @Test
@Ignore @Ignore
public void getMapAsSingleString() { public void getMapAsSingleString() {
binder.addBinding("favoriteFoodsByGroup");
Map<FoodGroup, String> foods = new LinkedHashMap<FoodGroup, String>(); Map<FoodGroup, String> foods = new LinkedHashMap<FoodGroup, String>();
foods.put(FoodGroup.DAIRY, "Milk"); foods.put(FoodGroup.DAIRY, "Milk");
foods.put(FoodGroup.FRUIT, "Peaches"); foods.put(FoodGroup.FRUIT, "Peaches");
foods.put(FoodGroup.MEAT, "Ham"); foods.put(FoodGroup.MEAT, "Ham");
bean.favoriteFoodsByGroup = foods; bean.favoriteFoodsByGroup = foods;
String value = binder.getBinding("favoriteFoodsByGroup").getValue(); String value = binder.getBinding("favoriteFoodsByGroup").getRenderValue();
assertEquals("DAIRY=Milk FRUIT=Peaches MEAT=Ham", value); assertEquals("DAIRY=Milk FRUIT=Peaches MEAT=Ham", value);
} }
@Test @Test
public void bindToNullObjectPath() { public void bindToNullObjectPath() {
binder.addBinding("primaryAddress.street");
binder.addBinding("primaryAddress.city");
binder.addBinding("primaryAddress.state");
binder.addBinding("primaryAddress.zip");
Map<String, String> values = new LinkedHashMap<String, String>(); Map<String, String> values = new LinkedHashMap<String, String>();
values.put("primaryAddress.city", "Melbourne"); values.put("primaryAddress.city", "Melbourne");
binder.bind(values); binder.bind(values);
@ -457,11 +437,10 @@ public class GenericBinderTests {
@Test @Test
public void formatPossibleValue() { public void formatPossibleValue() {
binder.addBinding("currency").formatWith(new CurrencyFormatter()); binder.bindingRule("currency").formatWith(new CurrencyFormatter());
Binding b = binder.getBinding("currency"); Binding b = binder.getBinding("currency");
assertEquals("$5.00", b.format(new BigDecimal("5"))); assertEquals("$5.00", b.formatValue(new BigDecimal("5")));
} }
*/
public static enum FooEnum { public static enum FooEnum {
BAR, BAZ, BOOP; BAR, BAZ, BOOP;

View File

@ -32,7 +32,7 @@ import java.util.TreeSet;
* @author Keith Donald * @author Keith Donald
* @since 3.0 * @since 3.0
*/ */
class ConversionUtils { public class ConversionUtils {
/** /**
* Get the java.util.Collection implementation class that should be used for the given target collection type. * Get the java.util.Collection implementation class that should be used for the given target collection type.