polish
This commit is contained in:
parent
04115a4ff4
commit
78b4254d39
|
|
@ -74,7 +74,6 @@ public class Binder<T> {
|
||||||
private boolean strict = false;
|
private boolean strict = false;
|
||||||
|
|
||||||
private static Formatter defaultFormatter = new Formatter() {
|
private static Formatter defaultFormatter = new Formatter() {
|
||||||
|
|
||||||
public String format(Object object, Locale locale) {
|
public String format(Object object, Locale locale) {
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
return "";
|
return "";
|
||||||
|
|
@ -182,14 +181,8 @@ public class Binder<T> {
|
||||||
public List<BindingResult> bind(List<UserValue> userValues) {
|
public List<BindingResult> bind(List<UserValue> userValues) {
|
||||||
List<BindingResult> results = new ArrayList<BindingResult>(userValues.size());
|
List<BindingResult> results = new ArrayList<BindingResult>(userValues.size());
|
||||||
for (UserValue value : userValues) {
|
for (UserValue value : userValues) {
|
||||||
Binding binding = getBinding(value.getProperty());
|
BindingImpl binding = (BindingImpl) getBinding(value.getProperty());
|
||||||
if (value.isString()) {
|
results.add(binding.setValue(value.getValue()));
|
||||||
results.add(binding.setValue((String) value.getValue()));
|
|
||||||
} else if (value.isStringArray()) {
|
|
||||||
results.add(binding.setValues((String[]) value.getValue()));
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Illegal argument " + value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
@ -205,6 +198,8 @@ public class Binder<T> {
|
||||||
formatter = config.getFormatter();
|
formatter = config.getFormatter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// implementing Binding
|
||||||
|
|
||||||
public String getValue() {
|
public String getValue() {
|
||||||
Object value;
|
Object value;
|
||||||
try {
|
try {
|
||||||
|
|
@ -215,24 +210,16 @@ public class Binder<T> {
|
||||||
return format(value);
|
return format(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BindingResult setValue(String formatted) {
|
public BindingResult setValue(Object value) {
|
||||||
Formatter formatter;
|
if (value instanceof String) {
|
||||||
try {
|
return setStringValue((String) value);
|
||||||
formatter = getFormatter();
|
} else if (value instanceof String[]) {
|
||||||
} catch (EvaluationException e) {
|
return setStringValues((String[]) value);
|
||||||
// could occur the property was not found or is not readable
|
} else {
|
||||||
// TODO probably should not handle all EL failures, only type conversion & property not found?
|
return setObjectValue(value);
|
||||||
return new ExpressionEvaluationErrorResult(property.getExpressionString(), formatted, e);
|
|
||||||
}
|
}
|
||||||
Object parsed;
|
|
||||||
try {
|
|
||||||
parsed = formatter.parse(formatted, LocaleContextHolder.getLocale());
|
|
||||||
} catch (ParseException e) {
|
|
||||||
return new InvalidFormatResult(property.getExpressionString(), formatted, e);
|
|
||||||
}
|
|
||||||
return setValue(parsed, formatted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String format(Object selectableValue) {
|
public String format(Object selectableValue) {
|
||||||
Formatter formatter;
|
Formatter formatter;
|
||||||
try {
|
try {
|
||||||
|
|
@ -256,7 +243,7 @@ public class Binder<T> {
|
||||||
return typeDesc.isCollection() || typeDesc.isArray();
|
return typeDesc.isCollection() || typeDesc.isArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getValues() {
|
public String[] getCollectionValues() {
|
||||||
Object multiValue;
|
Object multiValue;
|
||||||
try {
|
try {
|
||||||
multiValue = property.getValue(createEvaluationContext());
|
multiValue = property.getValue(createEvaluationContext());
|
||||||
|
|
@ -281,7 +268,27 @@ public class Binder<T> {
|
||||||
return formattedValues;
|
return formattedValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BindingResult setValues(String[] formatted) {
|
// internal helpers
|
||||||
|
|
||||||
|
private BindingResult setStringValue(String formatted) {
|
||||||
|
Formatter formatter;
|
||||||
|
try {
|
||||||
|
formatter = getFormatter();
|
||||||
|
} catch (EvaluationException e) {
|
||||||
|
// could occur the property was not found or is not readable
|
||||||
|
// TODO probably should not handle all EL failures, only type conversion & property not found?
|
||||||
|
return new ExpressionEvaluationErrorResult(property.getExpressionString(), formatted, e);
|
||||||
|
}
|
||||||
|
Object parsed;
|
||||||
|
try {
|
||||||
|
parsed = formatter.parse(formatted, LocaleContextHolder.getLocale());
|
||||||
|
} catch (ParseException e) {
|
||||||
|
return new InvalidFormatResult(property.getExpressionString(), formatted, e);
|
||||||
|
}
|
||||||
|
return setValue(parsed, formatted);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BindingResult setStringValues(String[] formatted) {
|
||||||
Formatter formatter;
|
Formatter formatter;
|
||||||
try {
|
try {
|
||||||
formatter = getFormatter();
|
formatter = getFormatter();
|
||||||
|
|
@ -306,8 +313,10 @@ public class Binder<T> {
|
||||||
}
|
}
|
||||||
return setValue(parsed, formatted);
|
return setValue(parsed, formatted);
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal helpers
|
private BindingResult setObjectValue(Object value) {
|
||||||
|
return setValue(value, value);
|
||||||
|
}
|
||||||
|
|
||||||
private Formatter getFormatter() throws EvaluationException {
|
private Formatter getFormatter() throws EvaluationException {
|
||||||
if (formatter != null) {
|
if (formatter != null) {
|
||||||
|
|
@ -346,12 +355,12 @@ public class Binder<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private BindingResult setValue(Object parsed, Object formatted) {
|
private BindingResult setValue(Object parsedValue, Object userValue) {
|
||||||
try {
|
try {
|
||||||
property.setValue(createEvaluationContext(), parsed);
|
property.setValue(createEvaluationContext(), parsedValue);
|
||||||
return new SuccessResult(property.getExpressionString(), formatted);
|
return new SuccessResult(property.getExpressionString(), userValue);
|
||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
return new ExpressionEvaluationErrorResult(property.getExpressionString(), formatted, e);
|
return new ExpressionEvaluationErrorResult(property.getExpressionString(), userValue, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,24 +17,22 @@ package org.springframework.ui.binding;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A binding between a user interface element and a model property.
|
* A binding between a user interface element and a model property.
|
||||||
* TODO - consider having setValue accept Object to allow for binding special objects like arrays & multi-part files
|
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
*/
|
*/
|
||||||
public interface Binding {
|
public interface Binding {
|
||||||
|
|
||||||
// single-value properties
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The formatted value to display in the user interface.
|
* The formatted value to display in the user interface.
|
||||||
*/
|
*/
|
||||||
String getValue();
|
String getValue();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the model property value a from user-entered value.
|
* Set the property associated with this binding to the value provided.
|
||||||
* @param formatted the value entered by the user
|
* The value may be a formatted String, a formatted String[] if a collection binding, or an Object of a type that can be coersed to the underlying property type.
|
||||||
|
* @param value the new value to bind
|
||||||
*/
|
*/
|
||||||
BindingResult setValue(String formatted);
|
BindingResult setValue(Object value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a candidate model property value for display in the user interface.
|
* Formats a candidate model property value for display in the user interface.
|
||||||
* @param selectableValue a possible value
|
* @param selectableValue a possible value
|
||||||
|
|
@ -42,11 +40,9 @@ public interface Binding {
|
||||||
*/
|
*/
|
||||||
String format(Object selectableValue);
|
String format(Object selectableValue);
|
||||||
|
|
||||||
// multi-value properties
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this binding associated with a collection or array property?
|
* Is this binding associated with a collection or array property?
|
||||||
* If so, a client should call {@link #getValues()} to display property values in the user interface.
|
* If so, a client should call {@link #getCollectionValues()} to display property values in the user interface.
|
||||||
* A client should call {@link #setValues(String[])} to set model property values from user-entered/selected values.
|
* A client should call {@link #setValues(String[])} to set model property values from user-entered/selected values.
|
||||||
*/
|
*/
|
||||||
boolean isCollection();
|
boolean isCollection();
|
||||||
|
|
@ -54,12 +50,6 @@ public interface Binding {
|
||||||
/**
|
/**
|
||||||
* When a collection binding, the formatted values to display in the user interface.
|
* When a collection binding, the formatted values to display in the user interface.
|
||||||
*/
|
*/
|
||||||
String[] getValues();
|
String[] getCollectionValues();
|
||||||
|
|
||||||
/**
|
|
||||||
* When a collection binding, sets the model property values a from user-entered/selected values.
|
|
||||||
* @param formattedValues the values entered by the user
|
|
||||||
*/
|
|
||||||
BindingResult setValues(String[] formatted);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +73,7 @@ public class UserValue {
|
||||||
* @param value the actual user-entered value
|
* @param value the actual user-entered value
|
||||||
* @return the singleton user value list
|
* @return the singleton user value list
|
||||||
*/
|
*/
|
||||||
public static List<UserValue> singleton(String property, Object value) {
|
public static List<UserValue> single(String property, Object value) {
|
||||||
List<UserValue> values = new ArrayList<UserValue>(1);
|
List<UserValue> values = new ArrayList<UserValue>(1);
|
||||||
values.add(new UserValue(property, value));
|
values.add(new UserValue(property, value));
|
||||||
return values;
|
return values;
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ public class BinderTests {
|
||||||
public void bindSingleValuePropertyFormatter() throws ParseException {
|
public void bindSingleValuePropertyFormatter() throws ParseException {
|
||||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||||
binder.add(new BindingConfiguration("date", new DateFormatter()));
|
binder.add(new BindingConfiguration("date", new DateFormatter()));
|
||||||
binder.bind(UserValue.singleton("date", "2009-06-01"));
|
binder.bind(UserValue.single("date", "2009-06-01"));
|
||||||
assertEquals(new DateFormatter().parse("2009-06-01", Locale.US), binder.getModel().getDate());
|
assertEquals(new DateFormatter().parse("2009-06-01", Locale.US), binder.getModel().getDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,14 +93,14 @@ public class BinderTests {
|
||||||
public void bindSingleValuePropertyFormatterParseException() {
|
public void bindSingleValuePropertyFormatterParseException() {
|
||||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||||
binder.add(new BindingConfiguration("date", new DateFormatter()));
|
binder.add(new BindingConfiguration("date", new DateFormatter()));
|
||||||
binder.bind(UserValue.singleton("date", "bogus"));
|
binder.bind(UserValue.single("date", "bogus"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindSingleValueWithFormatterRegistedByType() throws ParseException {
|
public void bindSingleValueWithFormatterRegistedByType() throws ParseException {
|
||||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||||
binder.add(new DateFormatter(), Date.class);
|
binder.add(new DateFormatter(), Date.class);
|
||||||
binder.bind(UserValue.singleton("date", "2009-06-01"));
|
binder.bind(UserValue.single("date", "2009-06-01"));
|
||||||
assertEquals(new DateFormatter().parse("2009-06-01", Locale.US), binder.getModel().getDate());
|
assertEquals(new DateFormatter().parse("2009-06-01", Locale.US), binder.getModel().getDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,7 +108,7 @@ public class BinderTests {
|
||||||
public void bindSingleValueWithFormatterRegisteredByAnnotation() throws ParseException {
|
public void bindSingleValueWithFormatterRegisteredByAnnotation() throws ParseException {
|
||||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||||
binder.add(new CurrencyFormatter(), CurrencyFormat.class);
|
binder.add(new CurrencyFormatter(), CurrencyFormat.class);
|
||||||
binder.bind(UserValue.singleton("currency", "$23.56"));
|
binder.bind(UserValue.single("currency", "$23.56"));
|
||||||
assertEquals(new BigDecimal("23.56"), binder.getModel().getCurrency());
|
assertEquals(new BigDecimal("23.56"), binder.getModel().getCurrency());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,14 +116,14 @@ public class BinderTests {
|
||||||
public void bindSingleValueWithnAnnotationFormatterFactoryRegistered() throws ParseException {
|
public void bindSingleValueWithnAnnotationFormatterFactoryRegistered() throws ParseException {
|
||||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||||
binder.add(new CurrencyAnnotationFormatterFactory());
|
binder.add(new CurrencyAnnotationFormatterFactory());
|
||||||
binder.bind(UserValue.singleton("currency", "$23.56"));
|
binder.bind(UserValue.single("currency", "$23.56"));
|
||||||
assertEquals(new BigDecimal("23.56"), binder.getModel().getCurrency());
|
assertEquals(new BigDecimal("23.56"), binder.getModel().getCurrency());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindSingleValuePropertyNotFound() throws ParseException {
|
public void bindSingleValuePropertyNotFound() throws ParseException {
|
||||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||||
List<BindingResult> results = binder.bind(UserValue.singleton("bogus", "2009-06-01"));
|
List<BindingResult> results = binder.bind(UserValue.single("bogus", "2009-06-01"));
|
||||||
assertEquals(1, results.size());
|
assertEquals(1, results.size());
|
||||||
assertTrue(results.get(0).isError());
|
assertTrue(results.get(0).isError());
|
||||||
assertEquals("propertyNotFound", results.get(0).getErrorCode());
|
assertEquals("propertyNotFound", results.get(0).getErrorCode());
|
||||||
|
|
@ -181,12 +181,12 @@ public class BinderTests {
|
||||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||||
Binding b = binder.getBinding("foos");
|
Binding b = binder.getBinding("foos");
|
||||||
assertTrue(b.isCollection());
|
assertTrue(b.isCollection());
|
||||||
assertEquals(0, b.getValues().length);
|
assertEquals(0, b.getCollectionValues().length);
|
||||||
b.setValues(new String[] { "BAR", "BAZ", "BOOP" });
|
b.setValue(new String[] { "BAR", "BAZ", "BOOP" });
|
||||||
assertEquals(FooEnum.BAR, binder.getModel().getFoos().get(0));
|
assertEquals(FooEnum.BAR, binder.getModel().getFoos().get(0));
|
||||||
assertEquals(FooEnum.BAZ, binder.getModel().getFoos().get(1));
|
assertEquals(FooEnum.BAZ, binder.getModel().getFoos().get(1));
|
||||||
assertEquals(FooEnum.BOOP, binder.getModel().getFoos().get(2));
|
assertEquals(FooEnum.BOOP, binder.getModel().getFoos().get(2));
|
||||||
String[] values = b.getValues();
|
String[] values = b.getCollectionValues();
|
||||||
assertEquals(3, values.length);
|
assertEquals(3, values.length);
|
||||||
assertEquals("BAR", values[0]);
|
assertEquals("BAR", values[0]);
|
||||||
assertEquals("BAZ", values[1]);
|
assertEquals("BAZ", values[1]);
|
||||||
|
|
@ -198,8 +198,8 @@ public class BinderTests {
|
||||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||||
Binding b = binder.getBinding("foos");
|
Binding b = binder.getBinding("foos");
|
||||||
assertTrue(b.isCollection());
|
assertTrue(b.isCollection());
|
||||||
assertEquals(0, b.getValues().length);
|
assertEquals(0, b.getCollectionValues().length);
|
||||||
BindingResult result = b.setValues(new String[] { "BAR", "BOGUS", "BOOP" });
|
BindingResult result = b.setValue(new String[] { "BAR", "BOGUS", "BOOP" });
|
||||||
assertTrue(result.isError());
|
assertTrue(result.isError());
|
||||||
assertTrue(result.getErrorCause() instanceof EvaluationException);
|
assertTrue(result.getErrorCause() instanceof EvaluationException);
|
||||||
assertEquals("typeConversionFailure", result.getErrorCode());
|
assertEquals("typeConversionFailure", result.getErrorCode());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue