Added binder factory; simplified public binder api
This commit is contained in:
parent
9b7e9942db
commit
5828010bae
|
|
@ -17,15 +17,11 @@ package org.springframework.ui.binding;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.ui.format.AnnotationFormatterFactory;
|
|
||||||
import org.springframework.ui.format.Formatter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds user-entered values to properties of a model object.
|
* Binds user-entered values to properties of a model object.
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see #configureBinding(BindingConfiguration)
|
* @see #bind(Map)
|
||||||
* @see #bind(UserValues)
|
|
||||||
*/
|
*/
|
||||||
public interface Binder {
|
public interface Binder {
|
||||||
|
|
||||||
|
|
@ -35,41 +31,6 @@ public interface Binder {
|
||||||
*/
|
*/
|
||||||
Object getModel();
|
Object getModel();
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures if this binder is <i>strict</i>; a strict binder requires all bindings to be registered explicitly using {@link #configureBinding(BindingConfiguration)}.
|
|
||||||
* An <i>optimistic</i> binder will implicitly create bindings as required to support {@link #bind(UserValues)} operations.
|
|
||||||
* Default is optimistic.
|
|
||||||
* @param strict strict binder status
|
|
||||||
*/
|
|
||||||
void setStrict(boolean strict);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new binding.
|
|
||||||
* @param configuration the binding configuration
|
|
||||||
* @return the new binding created from the configuration provided
|
|
||||||
*/
|
|
||||||
Binding configureBinding(BindingConfiguration configuration);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a Formatter that will format property values of type <code>propertyType</coe>.
|
|
||||||
* @param propertyType the property type
|
|
||||||
* @param formatter the formatter
|
|
||||||
*/
|
|
||||||
void registerFormatter(Class<?> propertyType, Formatter<?> formatter);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a AnnotationFormatterFactory that will format values of properties annotated with a specific annotation.
|
|
||||||
* @param factory the annotation formatter factory
|
|
||||||
*/
|
|
||||||
void registerFormatterFactory(AnnotationFormatterFactory<?, ?> factory);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the registry of Formatters to query when no explicit Formatter has been registered for a Binding.
|
|
||||||
* Allows Formatters to be applied by property type and by property annotation.
|
|
||||||
* @param registry the formatter registry
|
|
||||||
*/
|
|
||||||
void setFormatterRegistry(FormatterRegistry registry);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the binding for the property.
|
* Returns the binding for the property.
|
||||||
* @param property the property path
|
* @param property the property path
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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.binding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory for model Binders.
|
||||||
|
* @author Keith Donald
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public interface BinderFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Binder for the model
|
||||||
|
* @param model the model
|
||||||
|
* @return the binder
|
||||||
|
*/
|
||||||
|
Binder getBinder(Object model);
|
||||||
|
}
|
||||||
|
|
@ -21,7 +21,7 @@ import org.springframework.ui.alert.Alert;
|
||||||
* The result of a bind operation.
|
* The result of a bind operation.
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see Binder#bind(UserValues)
|
* @see Binder#bind(Map)
|
||||||
* @see Binding#setValue(Object)
|
* @see Binding#setValue(Object)
|
||||||
*/
|
*/
|
||||||
public interface BindingResult {
|
public interface BindingResult {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
package org.springframework.ui.binding.support;
|
||||||
|
|
||||||
|
import java.beans.BeanInfo;
|
||||||
|
import java.beans.IntrospectionException;
|
||||||
|
import java.beans.Introspector;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
|
import org.springframework.ui.binding.Bound;
|
||||||
|
import org.springframework.ui.binding.Model;
|
||||||
|
|
||||||
|
class AnnotatedModelBinderConfigurer {
|
||||||
|
|
||||||
|
public void configure(GenericBinder binder) {
|
||||||
|
Class<?> modelClass = binder.getModel().getClass();
|
||||||
|
Model m = AnnotationUtils.findAnnotation(modelClass, Model.class);
|
||||||
|
if (m != null) {
|
||||||
|
binder.setStrict(m.strictBinding());
|
||||||
|
}
|
||||||
|
if (binder.isStrict()) {
|
||||||
|
BeanInfo beanInfo;
|
||||||
|
try {
|
||||||
|
beanInfo = Introspector.getBeanInfo(modelClass);
|
||||||
|
} catch (IntrospectionException e) {
|
||||||
|
throw new IllegalStateException("Unable to introspect model " + binder.getModel(), e);
|
||||||
|
}
|
||||||
|
// TODO do we have to still flush introspector cache here?
|
||||||
|
for (PropertyDescriptor prop : beanInfo.getPropertyDescriptors()) {
|
||||||
|
Method getter = prop.getReadMethod();
|
||||||
|
Bound b = AnnotationUtils.getAnnotation(getter, Bound.class);
|
||||||
|
if (b != null) {
|
||||||
|
// TODO should we wire formatter here if using a format annotation - an optimization?
|
||||||
|
binder.configureBinding(new BindingConfiguration(prop.getName(), null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -13,9 +13,9 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.ui.binding;
|
package org.springframework.ui.binding.support;
|
||||||
|
|
||||||
import org.springframework.ui.binding.support.GenericBinder;
|
import org.springframework.ui.binding.Binding;
|
||||||
import org.springframework.ui.format.Formatter;
|
import org.springframework.ui.format.Formatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springframework.ui.binding;
|
package org.springframework.ui.binding.support;
|
||||||
|
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.ui.format.AnnotationFormatterFactory;
|
import org.springframework.ui.format.AnnotationFormatterFactory;
|
||||||
|
|
@ -53,11 +53,8 @@ import org.springframework.ui.alert.Alert;
|
||||||
import org.springframework.ui.alert.Severity;
|
import org.springframework.ui.alert.Severity;
|
||||||
import org.springframework.ui.binding.Binder;
|
import org.springframework.ui.binding.Binder;
|
||||||
import org.springframework.ui.binding.Binding;
|
import org.springframework.ui.binding.Binding;
|
||||||
import org.springframework.ui.binding.BindingConfiguration;
|
|
||||||
import org.springframework.ui.binding.BindingResult;
|
import org.springframework.ui.binding.BindingResult;
|
||||||
import org.springframework.ui.binding.BindingResults;
|
import org.springframework.ui.binding.BindingResults;
|
||||||
import org.springframework.ui.binding.FormatterRegistry;
|
|
||||||
import org.springframework.ui.format.AnnotationFormatterFactory;
|
|
||||||
import org.springframework.ui.format.Formatter;
|
import org.springframework.ui.format.Formatter;
|
||||||
import org.springframework.ui.message.MessageBuilder;
|
import org.springframework.ui.message.MessageBuilder;
|
||||||
import org.springframework.ui.message.ResolvableArgument;
|
import org.springframework.ui.message.ResolvableArgument;
|
||||||
|
|
@ -109,14 +106,30 @@ public class GenericBinder implements Binder {
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this binder strict?
|
||||||
|
* A strict binder requires all bindings to be registered explicitly using {@link #configureBinding(BindingConfiguration)}.
|
||||||
|
*/
|
||||||
public boolean isStrict() {
|
public boolean isStrict() {
|
||||||
return strict;
|
return strict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures if this binder is <i>strict</i>.
|
||||||
|
* A strict binder requires all bindings to be registered explicitly using {@link #configureBinding(BindingConfiguration)}.
|
||||||
|
* An <i>optimistic</i> binder will implicitly create bindings as required to support {@link #bind(UserValues)} operations.
|
||||||
|
* Default is optimistic.
|
||||||
|
* @param strict strict binder status
|
||||||
|
*/
|
||||||
public void setStrict(boolean strict) {
|
public void setStrict(boolean strict) {
|
||||||
this.strict = strict;
|
this.strict = strict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the registry of Formatters to query when no explicit Formatter has been registered for a Binding.
|
||||||
|
* Allows Formatters to be applied by property type and by property annotation.
|
||||||
|
* @param registry the formatter registry
|
||||||
|
*/
|
||||||
public void setFormatterRegistry(FormatterRegistry formatterRegistry) {
|
public void setFormatterRegistry(FormatterRegistry formatterRegistry) {
|
||||||
Assert.notNull(formatterRegistry, "The FormatterRegistry is required");
|
Assert.notNull(formatterRegistry, "The FormatterRegistry is required");
|
||||||
this.formatterRegistry = formatterRegistry;
|
this.formatterRegistry = formatterRegistry;
|
||||||
|
|
@ -127,6 +140,7 @@ public class GenericBinder implements Binder {
|
||||||
* @param messageSource the message source
|
* @param messageSource the message source
|
||||||
*/
|
*/
|
||||||
public void setMessageSource(MessageSource messageSource) {
|
public void setMessageSource(MessageSource messageSource) {
|
||||||
|
Assert.notNull(messageSource, "The MessageSource is required");
|
||||||
this.messageSource = messageSource;
|
this.messageSource = messageSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,9 +152,15 @@ public class GenericBinder implements Binder {
|
||||||
* @see EvaluationContext#getTypeConverter()
|
* @see EvaluationContext#getTypeConverter()
|
||||||
*/
|
*/
|
||||||
public void setTypeConverter(TypeConverter typeConverter) {
|
public void setTypeConverter(TypeConverter typeConverter) {
|
||||||
|
Assert.notNull(messageSource, "The TypeConverter is required");
|
||||||
this.typeConverter = typeConverter;
|
this.typeConverter = typeConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures a new binding on this binder.
|
||||||
|
* @param configuration the binding configuration
|
||||||
|
* @return the new binding created from the configuration provided
|
||||||
|
*/
|
||||||
public Binding configureBinding(BindingConfiguration configuration) {
|
public Binding configureBinding(BindingConfiguration configuration) {
|
||||||
Binding binding;
|
Binding binding;
|
||||||
try {
|
try {
|
||||||
|
|
@ -152,14 +172,6 @@ public class GenericBinder implements Binder {
|
||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerFormatter(Class<?> propertyType, Formatter<?> formatter) {
|
|
||||||
formatterRegistry.add(propertyType, formatter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerFormatterFactory(AnnotationFormatterFactory<?, ?> factory) {
|
|
||||||
formatterRegistry.add(factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Binding getBinding(String property) {
|
public Binding getBinding(String property) {
|
||||||
Binding binding = bindings.get(property);
|
Binding binding = bindings.get(property);
|
||||||
if (binding == null && !strict) {
|
if (binding == null && !strict) {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.core.GenericTypeResolver;
|
import org.springframework.core.GenericTypeResolver;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.ui.binding.FormatterRegistry;
|
|
||||||
import org.springframework.ui.format.AnnotationFormatterFactory;
|
import org.springframework.ui.format.AnnotationFormatterFactory;
|
||||||
import org.springframework.ui.format.Formatter;
|
import org.springframework.ui.format.Formatter;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import java.util.Map;
|
||||||
* @see #setDefaultPrefix(String)
|
* @see #setDefaultPrefix(String)
|
||||||
* @see #setPresentPrefix(String)
|
* @see #setPresentPrefix(String)
|
||||||
*/
|
*/
|
||||||
public class WebBinder extends GenericBinder {
|
class WebBinder extends GenericBinder {
|
||||||
|
|
||||||
private String defaultPrefix = "!";
|
private String defaultPrefix = "!";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package org.springframework.ui.binding.support;
|
||||||
|
|
||||||
|
import org.springframework.ui.binding.Binder;
|
||||||
|
import org.springframework.ui.binding.BinderFactory;
|
||||||
|
|
||||||
|
public class WebBinderFactory implements BinderFactory {
|
||||||
|
|
||||||
|
public Binder getBinder(Object model) {
|
||||||
|
WebBinder binder = new WebBinder(model);
|
||||||
|
new AnnotatedModelBinderConfigurer().configure(binder);
|
||||||
|
return binder;
|
||||||
|
}
|
||||||
|
|
||||||
|
// internal helpers
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -15,24 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package org.springframework.ui.lifecycle;
|
package org.springframework.ui.lifecycle;
|
||||||
|
|
||||||
import java.beans.BeanInfo;
|
|
||||||
import java.beans.IntrospectionException;
|
|
||||||
import java.beans.Introspector;
|
|
||||||
import java.beans.PropertyDescriptor;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
|
||||||
import org.springframework.ui.alert.AlertContext;
|
import org.springframework.ui.alert.AlertContext;
|
||||||
import org.springframework.ui.binding.BindingConfiguration;
|
import org.springframework.ui.binding.Binder;
|
||||||
import org.springframework.ui.binding.BindingResult;
|
import org.springframework.ui.binding.BindingResult;
|
||||||
import org.springframework.ui.binding.BindingResults;
|
import org.springframework.ui.binding.BindingResults;
|
||||||
import org.springframework.ui.binding.Bound;
|
|
||||||
import org.springframework.ui.binding.FormatterRegistry;
|
|
||||||
import org.springframework.ui.binding.Model;
|
|
||||||
import org.springframework.ui.binding.support.WebBinder;
|
|
||||||
import org.springframework.ui.validation.Validator;
|
import org.springframework.ui.validation.Validator;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the bind and validate lifecycle for web (HTTP) environments.
|
* Implementation of the bind and validate lifecycle for web (HTTP) environments.
|
||||||
|
|
@ -41,7 +30,7 @@ import org.springframework.util.StringUtils;
|
||||||
*/
|
*/
|
||||||
public class WebBindAndValidateLifecycle {
|
public class WebBindAndValidateLifecycle {
|
||||||
|
|
||||||
private final WebBinder binder;
|
private final Binder binder;
|
||||||
|
|
||||||
private final AlertContext alertContext;
|
private final AlertContext alertContext;
|
||||||
|
|
||||||
|
|
@ -49,19 +38,13 @@ public class WebBindAndValidateLifecycle {
|
||||||
|
|
||||||
private Validator validator;
|
private Validator validator;
|
||||||
|
|
||||||
public WebBindAndValidateLifecycle(Object model, AlertContext alertContext) {
|
public WebBindAndValidateLifecycle(Binder binder, AlertContext alertContext) {
|
||||||
this.binder = new WebBinder(model);
|
this.binder = binder;
|
||||||
// TODO this doesn't belong in here
|
|
||||||
configure(binder, model);
|
|
||||||
this.alertContext = alertContext;
|
this.alertContext = alertContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFormatterRegistry(FormatterRegistry registry) {
|
public void execute(Map<String, ? extends Object> sourceValues) {
|
||||||
binder.setFormatterRegistry(registry);
|
BindingResults bindingResults = binder.bind(sourceValues);
|
||||||
}
|
|
||||||
|
|
||||||
public void execute(Map<String, ? extends Object> userMap) {
|
|
||||||
BindingResults bindingResults = binder.bind(userMap);
|
|
||||||
if (validator != null && validationDecider.shouldValidateAfter(bindingResults)) {
|
if (validator != null && validationDecider.shouldValidateAfter(bindingResults)) {
|
||||||
// TODO get validation results
|
// TODO get validation results
|
||||||
validator.validate(binder.getModel(), bindingResults.successes().properties());
|
validator.validate(binder.getModel(), bindingResults.successes().properties());
|
||||||
|
|
@ -83,35 +66,4 @@ public class WebBindAndValidateLifecycle {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal helpers
|
|
||||||
|
|
||||||
private void configure(WebBinder binder, Object model) {
|
|
||||||
Model m = AnnotationUtils.findAnnotation(model.getClass(), Model.class);
|
|
||||||
if (m != null) {
|
|
||||||
if (StringUtils.hasText(m.value())) {
|
|
||||||
// TODO model name setting
|
|
||||||
//binder.setModelName(m.value());
|
|
||||||
}
|
|
||||||
binder.setStrict(m.strictBinding());
|
|
||||||
}
|
|
||||||
if (binder.isStrict()) {
|
|
||||||
BeanInfo beanInfo;
|
|
||||||
try {
|
|
||||||
beanInfo = Introspector.getBeanInfo(model.getClass());
|
|
||||||
} catch (IntrospectionException e) {
|
|
||||||
throw new IllegalStateException("Unable to introspect model " + model, e);
|
|
||||||
}
|
|
||||||
// TODO do we have to still flush introspector cache here?
|
|
||||||
for (PropertyDescriptor prop : beanInfo.getPropertyDescriptors()) {
|
|
||||||
Method getter = prop.getReadMethod();
|
|
||||||
Bound b = AnnotationUtils.getAnnotation(getter, Bound.class);
|
|
||||||
if (b != null) {
|
|
||||||
// TODO should we wire formatter here if using a format annotation - an optimization?
|
|
||||||
binder.configureBinding(new BindingConfiguration(prop.getName(), null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO @Bound fields
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import org.junit.Before;
|
||||||
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;
|
||||||
import org.springframework.ui.binding.BindingConfiguration;
|
|
||||||
import org.springframework.ui.binding.BindingResult;
|
import org.springframework.ui.binding.BindingResult;
|
||||||
import org.springframework.ui.binding.BindingResults;
|
import org.springframework.ui.binding.BindingResults;
|
||||||
import org.springframework.ui.format.AnnotationFormatterFactory;
|
import org.springframework.ui.format.AnnotationFormatterFactory;
|
||||||
|
|
@ -104,21 +103,27 @@ public class GenericBinderTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindSingleValueWithFormatterRegistedByType() throws ParseException {
|
public void bindSingleValueWithFormatterRegistedByType() throws ParseException {
|
||||||
binder.registerFormatter(Date.class, new DateFormatter());
|
GenericFormatterRegistry registry = new GenericFormatterRegistry();
|
||||||
|
registry.add(Date.class, new DateFormatter());
|
||||||
|
binder.setFormatterRegistry(registry);
|
||||||
binder.bind(Collections.singletonMap("date", "2009-06-01"));
|
binder.bind(Collections.singletonMap("date", "2009-06-01"));
|
||||||
assertEquals(new DateFormatter().parse("2009-06-01", Locale.US), bean.getDate());
|
assertEquals(new DateFormatter().parse("2009-06-01", Locale.US), bean.getDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindSingleValueWithFormatterRegisteredByAnnotation() throws ParseException {
|
public void bindSingleValueWithFormatterRegisteredByAnnotation() throws ParseException {
|
||||||
binder.registerFormatter(CurrencyFormat.class, new CurrencyFormatter());
|
GenericFormatterRegistry registry = new GenericFormatterRegistry();
|
||||||
|
registry.add(CurrencyFormat.class, new CurrencyFormatter());
|
||||||
|
binder.setFormatterRegistry(registry);
|
||||||
binder.bind(Collections.singletonMap("currency", "$23.56"));
|
binder.bind(Collections.singletonMap("currency", "$23.56"));
|
||||||
assertEquals(new BigDecimal("23.56"), bean.getCurrency());
|
assertEquals(new BigDecimal("23.56"), bean.getCurrency());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindSingleValueWithnAnnotationFormatterFactoryRegistered() throws ParseException {
|
public void bindSingleValueWithnAnnotationFormatterFactoryRegistered() throws ParseException {
|
||||||
binder.registerFormatterFactory(new CurrencyAnnotationFormatterFactory());
|
GenericFormatterRegistry registry = new GenericFormatterRegistry();
|
||||||
|
registry.add(new CurrencyAnnotationFormatterFactory());
|
||||||
|
binder.setFormatterRegistry(registry);
|
||||||
binder.bind(Collections.singletonMap("currency", "$23.56"));
|
binder.bind(Collections.singletonMap("currency", "$23.56"));
|
||||||
assertEquals(new BigDecimal("23.56"), bean.getCurrency());
|
assertEquals(new BigDecimal("23.56"), bean.getCurrency());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,6 @@ import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
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.Binder;
|
|
||||||
import org.springframework.ui.binding.BindingConfiguration;
|
|
||||||
import org.springframework.ui.binding.BindingResults;
|
import org.springframework.ui.binding.BindingResults;
|
||||||
import org.springframework.ui.format.date.DateFormatter;
|
import org.springframework.ui.format.date.DateFormatter;
|
||||||
import org.springframework.ui.format.number.CurrencyFormat;
|
import org.springframework.ui.format.number.CurrencyFormat;
|
||||||
|
|
@ -25,7 +23,7 @@ public class WebBinderTests {
|
||||||
|
|
||||||
TestBean bean = new TestBean();
|
TestBean bean = new TestBean();
|
||||||
|
|
||||||
Binder binder = new WebBinder(bean);
|
WebBinder binder = new WebBinder(bean);
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
|
|
@ -39,7 +37,9 @@ public class WebBinderTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindUserValuesCreatedFromUserMap() throws ParseException {
|
public void bindUserValuesCreatedFromUserMap() throws ParseException {
|
||||||
binder.registerFormatter(CurrencyFormat.class, new CurrencyFormatter());
|
GenericFormatterRegistry registry = new GenericFormatterRegistry();
|
||||||
|
registry.add(CurrencyFormat.class, new CurrencyFormatter());
|
||||||
|
binder.setFormatterRegistry(registry);
|
||||||
binder.configureBinding(new BindingConfiguration("date", new DateFormatter()));
|
binder.configureBinding(new BindingConfiguration("date", new DateFormatter()));
|
||||||
Map<String, String> userMap = new LinkedHashMap<String, String>();
|
Map<String, String> userMap = new LinkedHashMap<String, String>();
|
||||||
userMap.put("string", "test");
|
userMap.put("string", "test");
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,8 @@ import org.springframework.ui.alert.Severity;
|
||||||
import org.springframework.ui.alert.support.DefaultAlertContext;
|
import org.springframework.ui.alert.support.DefaultAlertContext;
|
||||||
import org.springframework.ui.binding.Bound;
|
import org.springframework.ui.binding.Bound;
|
||||||
import org.springframework.ui.binding.Model;
|
import org.springframework.ui.binding.Model;
|
||||||
import org.springframework.ui.binding.support.GenericFormatterRegistry;
|
import org.springframework.ui.binding.support.WebBinderFactory;
|
||||||
import org.springframework.ui.format.number.CurrencyFormat;
|
import org.springframework.ui.format.number.CurrencyFormat;
|
||||||
import org.springframework.ui.format.number.IntegerFormatter;
|
|
||||||
|
|
||||||
public class WebBindAndValidateLifecycleTests {
|
public class WebBindAndValidateLifecycleTests {
|
||||||
|
|
||||||
|
|
@ -30,7 +29,7 @@ public class WebBindAndValidateLifecycleTests {
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
model = new TestBean();
|
model = new TestBean();
|
||||||
alertContext = new DefaultAlertContext();
|
alertContext = new DefaultAlertContext();
|
||||||
lifecycle = new WebBindAndValidateLifecycle(model, alertContext);
|
lifecycle = new WebBindAndValidateLifecycle(new WebBinderFactory().getBinder(model), alertContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -55,52 +54,6 @@ public class WebBindAndValidateLifecycleTests {
|
||||||
assertEquals("Failed to bind to property 'integer'; user value 'bogus' could not be converted to property type [java.lang.Integer]", alertContext.getAlerts("integer").get(0).getMessage());
|
assertEquals("Failed to bind to property 'integer'; user value 'bogus' could not be converted to property type [java.lang.Integer]", alertContext.getAlerts("integer").get(0).getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExecuteLifecycleInvalidFormatBindingErrors() {
|
|
||||||
Map<String, Object> userMap = new HashMap<String, Object>();
|
|
||||||
GenericFormatterRegistry registry = new GenericFormatterRegistry();
|
|
||||||
registry.add(Integer.class, new IntegerFormatter());
|
|
||||||
lifecycle.setFormatterRegistry(registry);
|
|
||||||
userMap.put("string", "test");
|
|
||||||
userMap.put("integer", "bogus");
|
|
||||||
userMap.put("foo", "BAR");
|
|
||||||
lifecycle.execute(userMap);
|
|
||||||
assertEquals(1, alertContext.getAlerts().size());
|
|
||||||
assertEquals(Severity.ERROR, alertContext.getAlerts("integer").get(0).getSeverity());
|
|
||||||
assertEquals("Failed to bind to property 'integer'; the user value 'bogus' has an invalid format and could no be parsed", alertContext.getAlerts("integer").get(0).getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExecuteLifecycleAnnotatedModel() {
|
|
||||||
TestAnnotatedBean model = new TestAnnotatedBean();
|
|
||||||
lifecycle = new WebBindAndValidateLifecycle(model, alertContext);
|
|
||||||
Map<String, Object> userMap = new HashMap<String, Object>();
|
|
||||||
GenericFormatterRegistry registry = new GenericFormatterRegistry();
|
|
||||||
registry.add(Integer.class, new IntegerFormatter());
|
|
||||||
lifecycle.setFormatterRegistry(registry);
|
|
||||||
userMap.put("editable", "foo");
|
|
||||||
lifecycle.execute(userMap);
|
|
||||||
assertEquals(0, alertContext.getAlerts().size());
|
|
||||||
assertEquals("foo", model.getEditable());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExecuteLifecycleAnnotatedModelNonEditableBindingAttempt() {
|
|
||||||
TestAnnotatedBean model = new TestAnnotatedBean();
|
|
||||||
lifecycle = new WebBindAndValidateLifecycle(model, alertContext);
|
|
||||||
Map<String, Object> userMap = new HashMap<String, Object>();
|
|
||||||
GenericFormatterRegistry registry = new GenericFormatterRegistry();
|
|
||||||
registry.add(Integer.class, new IntegerFormatter());
|
|
||||||
lifecycle.setFormatterRegistry(registry);
|
|
||||||
userMap.put("editable", "foo");
|
|
||||||
userMap.put("nonEditable", "whatev");
|
|
||||||
lifecycle.execute(userMap);
|
|
||||||
assertEquals(1, alertContext.getAlerts().size());
|
|
||||||
assertEquals("foo", model.getEditable());
|
|
||||||
assertEquals(null, model.getNotEditable());
|
|
||||||
assertEquals("noSuchBinding", alertContext.getAlerts("nonEditable").get(0).getCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum FooEnum {
|
public static enum FooEnum {
|
||||||
BAR, BAZ, BOOP;
|
BAR, BAZ, BOOP;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue