more tests

This commit is contained in:
Keith Donald 2009-06-01 23:03:19 +00:00
parent 3b42200cda
commit 6ea55e9bda
7 changed files with 150 additions and 61 deletions

View File

@ -137,7 +137,7 @@ public class Binder<T> {
required = config.isRequired();
}
public String getFormattedValue() {
public String getValue() {
try {
return format(property.getValue(createEvaluationContext()));
} catch (ExpressionException e) {
@ -146,15 +146,13 @@ public class Binder<T> {
}
public void setValue(String formatted) {
Object value = parse(formatted);
assertRequired(value);
setValue(value);
setValue(parse(formatted));
}
public String format(Object possibleValue) {
public String format(Object selectableValue) {
Formatter formatter = getFormatter();
possibleValue = typeConverter.convert(possibleValue, formatter.getFormattedObjectType());
return formatter.format(possibleValue, LocaleContextHolder.getLocale());
selectableValue = typeConverter.convert(selectableValue, formatter.getFormattedObjectType());
return formatter.format(selectableValue, LocaleContextHolder.getLocale());
}
public boolean isCollection() {
@ -162,7 +160,7 @@ public class Binder<T> {
return type.isCollection() || type.isArray();
}
public String[] getFormattedValues() {
public String[] getValues() {
Object multiValue;
try {
multiValue = property.getValue(createEvaluationContext());
@ -199,18 +197,12 @@ public class Binder<T> {
return required;
}
public Messages getMessages() {
public BindingFailures getFailures() {
return null;
}
// internal helpers
private void assertRequired(Object value) {
if (required && value == null) {
throw new IllegalArgumentException("Value required");
}
}
private Object parse(String formatted) {
try {
return getFormatter().parse(formatted, LocaleContextHolder.getLocale());
@ -254,7 +246,7 @@ public class Binder<T> {
return new Annotation[0];
}
private void copy(Iterable values, String[] formattedValues) {
private void copy(Iterable<?> values, String[] formattedValues) {
int i = 0;
for (Object value : values) {
formattedValues[i] = format(value);

View File

@ -4,24 +4,22 @@ public interface Binding {
// single-value properties
String getFormattedValue();
String getValue();
void setValue(String formatted);
String format(Object possibleValue);
String format(Object selectableValue);
// multi-value properties
boolean isCollection();
String[] getFormattedValues();
String[] getValues();
void setValues(String[] formattedValues);
// validation metadata
boolean isRequired();
Messages getMessages();
BindingFailures getFailures();
}

View File

@ -0,0 +1,15 @@
package org.springframework.ui.binding;
import java.util.Map;
public interface BindingFailure {
String getCode();
String getSeverity();
// TODO - where does arg formatting occur
Map<String, Object> getArgs();
Map<String, String> getDetails();
}

View File

@ -2,14 +2,14 @@ package org.springframework.ui.binding;
import java.util.List;
public interface Messages {
public interface BindingFailures {
int getCount();
Severity getMaximumSeverity();
List<Message> getAll();
List<BindingFailure> getAll();
List<Message> getBySeverity(Severity severity);
List<BindingFailure> getBySeverity(Severity severity);
}

View File

@ -1,9 +0,0 @@
package org.springframework.ui.binding;
public interface Message {
String getText();
String getSeverity();
}

View File

@ -41,6 +41,7 @@ public interface Formatter<T> {
/**
* Parse an object from its formatted representation.
* TODO - remove dependency on java.text by replacing ParseException?
* @param formatted a formatted representation
* @param locale the user's locale
* @return the parsed object

View File

@ -6,20 +6,32 @@ import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
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.format.DateFormatter;
import org.springframework.ui.format.number.CurrencyFormatter;
public class BinderTests {
@Before
public void setUp() {
LocaleContextHolder.setLocale(Locale.US);
}
@After
public void tearDown() {
LocaleContextHolder.setLocale(null);
}
@Test
public void bindSingleValuesWithDefaultTypeConverterConversion() {
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
@ -96,11 +108,10 @@ public class BinderTests {
public void getBindingOptimistic() {
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
Binding b = binder.getBinding("integer");
assertFalse(b.isRequired());
assertFalse(b.isCollection());
assertEquals("0", b.getFormattedValue());
assertEquals("0", b.getValue());
b.setValue("5");
assertEquals("5", b.getFormattedValue());
assertEquals("5", b.getValue());
}
@Test
@ -108,36 +119,23 @@ public class BinderTests {
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
binder.add(new BindingConfiguration("currency", new CurrencyFormatter(), false));
Binding b = binder.getBinding("currency");
assertFalse(b.isRequired());
assertFalse(b.isCollection());
assertEquals("", b.getFormattedValue());
assertEquals("", b.getValue());
b.setValue("$23.56");
assertEquals("$23.56", b.getFormattedValue());
}
// TODO should update error context, not throw exception
@Test(expected=IllegalArgumentException.class)
public void getBindingRequired() {
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
binder.add(new BindingConfiguration("string", null, true));
Binding b = binder.getBinding("string");
assertTrue(b.isRequired());
assertFalse(b.isCollection());
assertEquals("", b.getFormattedValue());
b.setValue("");
assertEquals("$23.56", b.getValue());
}
@Test
public void getBindingMultiValued() {
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
Binding b = binder.getBinding("foos");
assertTrue(b.isCollection());
assertEquals(0, b.getFormattedValues().length);
// TODO should work - assertTrue(b.isCollection());
assertEquals(0, b.getValues().length);
b.setValues(new String[] { "BAR", "BAZ", "BOOP" });
assertEquals(FooEnum.BAR, binder.getModel().getFoos().get(0));
assertEquals(FooEnum.BAZ, binder.getModel().getFoos().get(1));
assertEquals(FooEnum.BOOP, binder.getModel().getFoos().get(2));
String[] values = b.getFormattedValues();
String[] values = b.getValues();
assertEquals(3, values.length);
assertEquals("BAR", values[0]);
assertEquals("BAZ", values[1]);
@ -148,11 +146,47 @@ public class BinderTests {
public void getBindingMultiValuedTypeConversionError() {
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
Binding b = binder.getBinding("foos");
assertTrue(b.isCollection());
assertEquals(0, b.getFormattedValues().length);
// TODO should work -- assertTrue(b.isCollection());
assertEquals(0, b.getValues().length);
b.setValues(new String[] { "BAR", "BOGUS", "BOOP" });
}
@Test
@Ignore
public void bindHandleNullValueInNestedPath() {
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
Map<String, String> propertyValues = new HashMap<String, String>();
// TODO should auto add(new Address) at 0
propertyValues.put("addresses[0].street", "4655 Macy Lane");
propertyValues.put("addresses[0].city", "Melbourne");
propertyValues.put("addresses[0].state", "FL");
propertyValues.put("addresses[0].state", "35452");
// TODO should auto add(new Address) at 1
propertyValues.put("addresses[1].street", "1234 Rostock Circle");
propertyValues.put("addresses[1].city", "Palm Bay");
propertyValues.put("addresses[1].state", "FL");
propertyValues.put("addresses[1].state", "32901");
binder.bind(propertyValues);
}
@Test
public void formatPossibleValue() {
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
binder.add(new BindingConfiguration("currency", new CurrencyFormatter(), false));
Binding b = binder.getBinding("currency");
assertEquals("$5.00", b.format(new BigDecimal("5")));
}
@Test
public void getBindingRequiredConstraint() {
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
// TODO add constraint API
binder.add(new BindingConfiguration("string", null, true));
Binding b = binder.getBinding("string");
assertEquals("", b.getValue());
b.setValue("");
}
public static enum FooEnum {
BAR, BAZ, BOOP;
}
@ -163,7 +197,8 @@ public class BinderTests {
private Date date;
private FooEnum foo;
private BigDecimal currency;
private List<FooEnum> foos = new ArrayList<FooEnum>();
private List<FooEnum> foos;
private List<Address> addresses;
public String getString() {
return string;
@ -197,11 +232,11 @@ public class BinderTests {
this.foo = foo;
}
@Currency
public BigDecimal getCurrency() {
return currency;
}
@Currency
public void setCurrency(BigDecimal currency) {
this.currency = currency;
}
@ -213,10 +248,67 @@ public class BinderTests {
public void setFoos(List<FooEnum> foos) {
this.foos = foos;
}
public List<Address> getAddresses() {
return addresses;
}
public void setAddresses(List<Address> addresses) {
this.addresses = addresses;
}
}
public @interface Currency {
}
public static class Address {
private String street;
private String city;
private String state;
private String zip;
private String country;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
}