initial data binder commit; dateformatter
This commit is contained in:
@@ -0,0 +1,282 @@
|
||||
package org.springframework.ui.binding;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Array;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.convert.TypeConverter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.DefaultTypeConverter;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionException;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeConverter;
|
||||
import org.springframework.ui.format.Formatter;
|
||||
|
||||
public class Binder<T> {
|
||||
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
private T model;
|
||||
|
||||
private Map<String, Binding> bindings;
|
||||
|
||||
private Map<Class<?>, Formatter<?>> typeFormatters = new HashMap<Class<?>, Formatter<?>>();
|
||||
|
||||
private Map<Annotation, Formatter<?>> annotationFormatters = new HashMap<Annotation, Formatter<?>>();
|
||||
|
||||
private ExpressionParser expressionParser;
|
||||
|
||||
private TypeConverter typeConverter;
|
||||
|
||||
private boolean optimisticBinding = true;
|
||||
|
||||
private static Formatter<?> defaultFormatter = new Formatter<?>() {
|
||||
|
||||
public Class<?> getFormattedObjectType() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public String format(Object object, Locale locale) {
|
||||
if (object == null) {
|
||||
return "";
|
||||
} else {
|
||||
return object.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public Object parse(String formatted, Locale locale)
|
||||
throws ParseException {
|
||||
if (formatted == "") {
|
||||
return null;
|
||||
} else {
|
||||
return formatted;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public Binder(T model) {
|
||||
this.model = model;
|
||||
bindings = new HashMap<String, Binding>();
|
||||
expressionParser = new SpelExpressionParser();
|
||||
typeConverter = new DefaultTypeConverter();
|
||||
}
|
||||
|
||||
public Binding add(BindingConfiguration binding) {
|
||||
Binding newBinding;
|
||||
try {
|
||||
newBinding = new BindingImpl(binding);
|
||||
} catch (org.springframework.expression.ParseException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
bindings.put(binding.getProperty(), newBinding);
|
||||
return newBinding;
|
||||
}
|
||||
|
||||
public void add(Formatter<?> formatter, Class<?> propertyType) {
|
||||
if (propertyType == null) {
|
||||
propertyType = formatter.getFormattedObjectType();
|
||||
}
|
||||
typeFormatters.put(propertyType, formatter);
|
||||
}
|
||||
|
||||
public void add(Formatter<?> formatter, Annotation propertyAnnotation) {
|
||||
annotationFormatters.put(propertyAnnotation, formatter);
|
||||
}
|
||||
|
||||
public T getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public Binding getBinding(String property) {
|
||||
Binding binding = bindings.get(property);
|
||||
if (binding == null && optimisticBinding) {
|
||||
return add(new BindingConfiguration(property, null, false));
|
||||
} else {
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
|
||||
public void bind(Map<String, ? extends Object> propertyValues) {
|
||||
for (Map.Entry<String, ? extends Object> entry : propertyValues
|
||||
.entrySet()) {
|
||||
Binding binding = getBinding(entry.getKey());
|
||||
Object value = entry.getValue();
|
||||
if (value instanceof String[]) {
|
||||
binding.setValues((String[])value);
|
||||
} else if (value instanceof String) {
|
||||
binding.setValue((String)entry.getValue());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Illegal argument " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BindingImpl implements Binding {
|
||||
|
||||
private Expression property;
|
||||
|
||||
private Formatter formatter;
|
||||
|
||||
private boolean required;
|
||||
|
||||
public BindingImpl(BindingConfiguration config)
|
||||
throws org.springframework.expression.ParseException {
|
||||
property = expressionParser.parseExpression(config.getProperty());
|
||||
formatter = config.getFormatter();
|
||||
required = config.isRequired();
|
||||
}
|
||||
|
||||
public String getFormattedValue() {
|
||||
try {
|
||||
return format(property.getValue(createEvaluationContext()));
|
||||
} catch (ExpressionException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setValue(String formatted) {
|
||||
Object value = parse(formatted);
|
||||
assertRequired(value);
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
public String format(Object possibleValue) {
|
||||
Formatter formatter = getFormatter();
|
||||
possibleValue = typeConverter.convert(possibleValue, formatter.getFormattedObjectType());
|
||||
return formatter.format(possibleValue, LocaleContextHolder.getLocale());
|
||||
}
|
||||
|
||||
public boolean isCollection() {
|
||||
TypeDescriptor<?> type = TypeDescriptor.valueOf(getValueType());
|
||||
return type.isCollection() || type.isArray();
|
||||
}
|
||||
|
||||
public String[] getFormattedValues() {
|
||||
Object multiValue;
|
||||
try {
|
||||
multiValue = property.getValue(createEvaluationContext());
|
||||
} catch (EvaluationException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
if (multiValue == null) {
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
TypeDescriptor<?> type = TypeDescriptor.valueOf(multiValue.getClass());
|
||||
String[] formattedValues;
|
||||
if (type.isCollection()) {
|
||||
Collection<?> values = ((Collection<?>)multiValue);
|
||||
formattedValues = (String[]) Array.newInstance(String.class, values.size());
|
||||
copy(values, formattedValues);
|
||||
} else if (type.isArray()) {
|
||||
formattedValues = (String[]) Array.newInstance(String.class, Array.getLength(multiValue));
|
||||
copy((Iterable<?>) multiValue, formattedValues);
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return formattedValues;
|
||||
}
|
||||
|
||||
public void setValues(String[] formattedValues) {
|
||||
Object values = Array.newInstance(getFormatter().getFormattedObjectType(), formattedValues.length);
|
||||
for (int i = 0; i < formattedValues.length; i++) {
|
||||
Array.set(values, i, parse(formattedValues[i]));
|
||||
}
|
||||
setValue(values);
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
public Messages getMessages() {
|
||||
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());
|
||||
} catch (ParseException e) {
|
||||
throw new IllegalArgumentException("Invalid format " + formatted, e);
|
||||
}
|
||||
}
|
||||
|
||||
private Formatter getFormatter() {
|
||||
if (formatter != null) {
|
||||
return formatter;
|
||||
} else {
|
||||
Class<?> type = getValueType();
|
||||
Formatter<?> formatter = typeFormatters.get(type);
|
||||
if (formatter != null) {
|
||||
return formatter;
|
||||
} else {
|
||||
Annotation[] annotations = getAnnotations();
|
||||
for (Annotation a : annotations) {
|
||||
formatter = annotationFormatters.get(a);
|
||||
if (formatter != null) {
|
||||
return formatter;
|
||||
}
|
||||
}
|
||||
return defaultFormatter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> getValueType() {
|
||||
try {
|
||||
// TODO Spring EL currently returns null here when value is null - not correct
|
||||
return property.getValueType(createEvaluationContext());
|
||||
} catch (EvaluationException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Annotation[] getAnnotations() {
|
||||
// TODO Spring EL presently gives us no way to get this information
|
||||
return new Annotation[0];
|
||||
}
|
||||
|
||||
private void copy(Iterable values, String[] formattedValues) {
|
||||
int i = 0;
|
||||
for (Object value : values) {
|
||||
formattedValues[i] = format(value);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
private void setValue(Object values) {
|
||||
try {
|
||||
property.setValue(createEvaluationContext(), values);
|
||||
} catch (ExpressionException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private EvaluationContext createEvaluationContext() {
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
context.setRootObject(model);
|
||||
context.addPropertyAccessor(new MapAccessor());
|
||||
context.setTypeConverter(new StandardTypeConverter(typeConverter));
|
||||
return context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.springframework.ui.binding;
|
||||
|
||||
public interface Binding {
|
||||
|
||||
// single-value properties
|
||||
|
||||
String getFormattedValue();
|
||||
|
||||
void setValue(String formatted);
|
||||
|
||||
String format(Object possibleValue);
|
||||
|
||||
// multi-value properties
|
||||
|
||||
boolean isCollection();
|
||||
|
||||
String[] getFormattedValues();
|
||||
|
||||
void setValues(String[] formattedValues);
|
||||
|
||||
// validation metadata
|
||||
|
||||
boolean isRequired();
|
||||
|
||||
Messages getMessages();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.springframework.ui.binding;
|
||||
|
||||
import org.springframework.ui.format.Formatter;
|
||||
|
||||
public class BindingConfiguration {
|
||||
|
||||
private String property;
|
||||
|
||||
private Formatter<?> formatter;
|
||||
|
||||
private boolean required;
|
||||
|
||||
public BindingConfiguration(String property, Formatter<?> formatter, boolean required) {
|
||||
this.property = property;
|
||||
this.formatter = formatter;
|
||||
this.required = required;
|
||||
}
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public Formatter<?> getFormatter() {
|
||||
return formatter;
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.springframework.ui.binding;
|
||||
|
||||
public interface Message {
|
||||
|
||||
String getText();
|
||||
|
||||
String getSeverity();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.springframework.ui.binding;
|
||||
|
||||
public interface MessageCriteria {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.springframework.ui.binding;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface Messages {
|
||||
|
||||
int getCount();
|
||||
|
||||
Severity getMaximumSeverity();
|
||||
|
||||
List<Message> getAll();
|
||||
|
||||
List<Message> getBySeverity(Severity severity);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.springframework.ui.binding;
|
||||
|
||||
public enum Severity {
|
||||
INFO, WARNING, ERROR;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2004-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.ui.format;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* A formatter for {@link Date} types.
|
||||
* Allows the configuration of an explicit date pattern and locale.
|
||||
* @see SimpleDateFormat
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class DateFormatter implements Formatter<Date> {
|
||||
|
||||
private static Log logger = LogFactory.getLog(DateFormatter.class);
|
||||
|
||||
/**
|
||||
* The default date pattern.
|
||||
*/
|
||||
private static final String DEFAULT_PATTERN = "yyyy-MM-dd";
|
||||
|
||||
private String pattern;
|
||||
|
||||
/**
|
||||
* Sets the pattern to use to format date values.
|
||||
* If not specified, the default pattern 'yyyy-MM-dd' is used.
|
||||
* @param pattern the date formatting pattern
|
||||
*/
|
||||
public void setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public Class<Date> getFormattedObjectType() {
|
||||
return Date.class;
|
||||
}
|
||||
|
||||
public String format(Date date, Locale locale) {
|
||||
if (date == null) {
|
||||
return "";
|
||||
}
|
||||
return getDateFormat(locale).format(date);
|
||||
}
|
||||
|
||||
public Date parse(String formatted, Locale locale) throws ParseException {
|
||||
if (formatted.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
return getDateFormat(locale).parse(formatted);
|
||||
}
|
||||
|
||||
// subclassing hookings
|
||||
|
||||
protected DateFormat getDateFormat(Locale locale) {
|
||||
DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT, locale);
|
||||
format.setLenient(false);
|
||||
if (format instanceof SimpleDateFormat) {
|
||||
String pattern = determinePattern(this.pattern);
|
||||
((SimpleDateFormat) format).applyPattern(pattern);
|
||||
} else {
|
||||
logger.warn("Unable to apply format pattern '" + pattern
|
||||
+ "'; Returned DateFormat is not a SimpleDateFormat");
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private String determinePattern(String pattern) {
|
||||
return pattern != null ? pattern : DEFAULT_PATTERN;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,6 +25,12 @@ import java.util.Locale;
|
||||
*/
|
||||
public interface Formatter<T> {
|
||||
|
||||
/**
|
||||
* Returns the type of object this formatter can format.
|
||||
* @return the formatted object type
|
||||
*/
|
||||
Class<T> getFormattedObjectType();
|
||||
|
||||
/**
|
||||
* Format the object of type T for display.
|
||||
* @param object the object to format
|
||||
|
||||
@@ -26,6 +26,14 @@ class FormattingConverter<T> implements Converter<T, String> {
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
public Class<T> getSourceType() {
|
||||
return formatter.getFormattedObjectType();
|
||||
}
|
||||
|
||||
public Class<String> getTargetType() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
public String convert(T source) {
|
||||
return formatter.format(source, LocaleContextHolder.getLocale());
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@ public class CurrencyFormatter implements Formatter<BigDecimal> {
|
||||
|
||||
private boolean lenient;
|
||||
|
||||
public Class<BigDecimal> getFormattedObjectType() {
|
||||
return BigDecimal.class;
|
||||
}
|
||||
|
||||
public String format(BigDecimal decimal, Locale locale) {
|
||||
if (decimal == null) {
|
||||
return "";
|
||||
@@ -66,5 +70,5 @@ public class CurrencyFormatter implements Formatter<BigDecimal> {
|
||||
decimal = decimal.setScale(format.getMaximumFractionDigits(), format.getRoundingMode());
|
||||
return decimal;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
package org.springframework.ui.binding;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
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.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ui.format.DateFormatter;
|
||||
import org.springframework.ui.format.number.CurrencyFormatter;
|
||||
|
||||
public class BinderTests {
|
||||
|
||||
@Test
|
||||
public void bindSingleValuesWithDefaultTypeConverterConversion() {
|
||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||
Map<String, String> propertyValues = new HashMap<String, String>();
|
||||
propertyValues.put("string", "test");
|
||||
propertyValues.put("integer", "3");
|
||||
propertyValues.put("foo", "BAR");
|
||||
binder.bind(propertyValues);
|
||||
assertEquals("test", binder.getModel().getString());
|
||||
assertEquals(3, binder.getModel().getInteger());
|
||||
assertEquals(FooEnum.BAR, binder.getModel().getFoo());
|
||||
}
|
||||
|
||||
// TODO should update error context, not throw exception
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void bindSingleValuesWithDefaultTypeCoversionFailures() {
|
||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||
Map<String, String> propertyValues = new HashMap<String, String>();
|
||||
propertyValues.put("string", "test");
|
||||
propertyValues.put("integer", "bogus");
|
||||
propertyValues.put("foo", "bogus");
|
||||
binder.bind(propertyValues);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindSingleValuePropertyFormatterParsing() throws ParseException {
|
||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||
binder.add(new BindingConfiguration("date", new DateFormatter(), false));
|
||||
Map<String, String> propertyValues = new HashMap<String, String>();
|
||||
propertyValues.put("date", "2009-06-01");
|
||||
binder.bind(propertyValues);
|
||||
assertEquals(new DateFormatter().parse("2009-06-01", Locale.US), binder.getModel().getDate());
|
||||
}
|
||||
|
||||
// TODO should update error context, not throw exception
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void bindSingleValuePropertyFormatterParseException() {
|
||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||
binder.add(new BindingConfiguration("date", new DateFormatter(), false));
|
||||
Map<String, String> propertyValues = new HashMap<String, String>();
|
||||
propertyValues.put("date", "bogus");
|
||||
binder.bind(propertyValues);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void bindSingleValueTypeFormatterParsing() throws ParseException {
|
||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||
binder.add(new DateFormatter(), Date.class);
|
||||
Map<String, String> propertyValues = new HashMap<String, String>();
|
||||
propertyValues.put("date", "2009-06-01");
|
||||
// TODO presently fails because Spring EL does not obtain property valueType using property metadata
|
||||
// instead it relies on value itself being not null
|
||||
// talk to andy about this
|
||||
binder.bind(propertyValues);
|
||||
assertEquals(new DateFormatter().parse("2009-06-01", Locale.US), binder.getModel().getDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void bindSingleValueAnnotationFormatterParsing() throws ParseException {
|
||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||
binder.add(new CurrencyFormatter(), Currency.class);
|
||||
Map<String, String> propertyValues = new HashMap<String, String>();
|
||||
propertyValues.put("currency", "$23.56");
|
||||
// TODO presently fails because Spring EL does not obtain property valueType using property metadata
|
||||
// instead it relies on value itself being not null
|
||||
// talk to andy about this
|
||||
binder.bind(propertyValues);
|
||||
assertEquals(new BigDecimal("23.56"), binder.getModel().getCurrency());
|
||||
}
|
||||
|
||||
@Test
|
||||
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());
|
||||
b.setValue("5");
|
||||
assertEquals("5", b.getFormattedValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBindingCustomFormatter() {
|
||||
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());
|
||||
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("");
|
||||
}
|
||||
|
||||
@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);
|
||||
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();
|
||||
assertEquals(3, values.length);
|
||||
assertEquals("BAR", values[0]);
|
||||
assertEquals("BAZ", values[1]);
|
||||
assertEquals("BOOP", values[2]);
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void getBindingMultiValuedTypeConversionError() {
|
||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||
Binding b = binder.getBinding("foos");
|
||||
assertTrue(b.isCollection());
|
||||
assertEquals(0, b.getFormattedValues().length);
|
||||
b.setValues(new String[] { "BAR", "BOGUS", "BOOP" });
|
||||
}
|
||||
|
||||
public static enum FooEnum {
|
||||
BAR, BAZ, BOOP;
|
||||
}
|
||||
|
||||
public static class TestBean {
|
||||
private String string;
|
||||
private int integer;
|
||||
private Date date;
|
||||
private FooEnum foo;
|
||||
private BigDecimal currency;
|
||||
private List<FooEnum> foos = new ArrayList<FooEnum>();
|
||||
|
||||
public String getString() {
|
||||
return string;
|
||||
}
|
||||
|
||||
public void setString(String string) {
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
public int getInteger() {
|
||||
return integer;
|
||||
}
|
||||
|
||||
public void setInteger(int integer) {
|
||||
this.integer = integer;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public FooEnum getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
public void setFoo(FooEnum foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
public BigDecimal getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
@Currency
|
||||
public void setCurrency(BigDecimal currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
public List<FooEnum> getFoos() {
|
||||
return foos;
|
||||
}
|
||||
|
||||
public void setFoos(List<FooEnum> foos) {
|
||||
this.foos = foos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public @interface Currency {
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user