Added AnnotatioFormatterFactory allowing Formatters to be created from property @Annotation values; polish
This commit is contained in:
parent
534871e6f6
commit
65c90c56c0
|
|
@ -2,6 +2,9 @@ package org.springframework.ui.binding;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.lang.reflect.TypeVariable;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -10,8 +13,11 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.context.expression.MapAccessor;
|
import org.springframework.context.expression.MapAccessor;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
import org.springframework.core.GenericTypeResolver;
|
||||||
import org.springframework.core.convert.TypeConverter;
|
import org.springframework.core.convert.TypeConverter;
|
||||||
import org.springframework.core.convert.TypeDescriptor;
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
|
import org.springframework.core.convert.converter.Converter;
|
||||||
|
import org.springframework.core.convert.converter.ConverterFactory;
|
||||||
import org.springframework.core.convert.support.DefaultTypeConverter;
|
import org.springframework.core.convert.support.DefaultTypeConverter;
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
import org.springframework.expression.EvaluationException;
|
import org.springframework.expression.EvaluationException;
|
||||||
|
|
@ -22,6 +28,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParserConfiguration;
|
import org.springframework.expression.spel.standard.SpelExpressionParserConfiguration;
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
import org.springframework.expression.spel.support.StandardTypeConverter;
|
import org.springframework.expression.spel.support.StandardTypeConverter;
|
||||||
|
import org.springframework.ui.format.AnnotationFormatterFactory;
|
||||||
import org.springframework.ui.format.Formatter;
|
import org.springframework.ui.format.Formatter;
|
||||||
|
|
||||||
public class Binder<T> {
|
public class Binder<T> {
|
||||||
|
|
@ -32,9 +39,9 @@ public class Binder<T> {
|
||||||
|
|
||||||
private Map<String, Binding> bindings;
|
private Map<String, Binding> bindings;
|
||||||
|
|
||||||
private Map<Class<?>, Formatter<?>> typeFormatters = new HashMap<Class<?>, Formatter<?>>();
|
private Map<Class, Formatter> typeFormatters = new HashMap<Class, Formatter>();
|
||||||
|
|
||||||
private Map<Class<?>, Formatter<?>> annotationFormatters = new HashMap<Class<?>, Formatter<?>>();
|
private Map<Class, AnnotationFormatterFactory> annotationFormatters = new HashMap<Class, AnnotationFormatterFactory>();
|
||||||
|
|
||||||
private ExpressionParser expressionParser;
|
private ExpressionParser expressionParser;
|
||||||
|
|
||||||
|
|
@ -44,10 +51,6 @@ public class Binder<T> {
|
||||||
|
|
||||||
private static Formatter defaultFormatter = new Formatter() {
|
private static Formatter defaultFormatter = new Formatter() {
|
||||||
|
|
||||||
public Class<?> getFormattedObjectType() {
|
|
||||||
return String.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String format(Object object, Locale locale) {
|
public String format(Object object, Locale locale) {
|
||||||
if (object == null) {
|
if (object == null) {
|
||||||
return "";
|
return "";
|
||||||
|
|
@ -92,16 +95,18 @@ public class Binder<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(Formatter<?> formatter, Class<?> propertyType) {
|
public void add(Formatter<?> formatter, Class<?> propertyType) {
|
||||||
if (propertyType == null) {
|
|
||||||
propertyType = formatter.getFormattedObjectType();
|
|
||||||
}
|
|
||||||
if (propertyType.isAnnotation()) {
|
if (propertyType.isAnnotation()) {
|
||||||
annotationFormatters.put(propertyType, formatter);
|
annotationFormatters.put(propertyType, new SimpleAnnotationFormatterFactory(formatter));
|
||||||
} else {
|
} else {
|
||||||
typeFormatters.put(propertyType, formatter);
|
typeFormatters.put(propertyType, formatter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO determine Annotation type from factory using reflection
|
||||||
|
public void add(AnnotationFormatterFactory<?, ?> factory) {
|
||||||
|
annotationFormatters.put(getAnnotationType(factory), factory);
|
||||||
|
}
|
||||||
|
|
||||||
public T getModel() {
|
public T getModel() {
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
@ -152,12 +157,13 @@ public class Binder<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValue(String formatted) {
|
public void setValue(String formatted) {
|
||||||
setValue(parse(formatted));
|
setValue(parse(formatted, getFormatter()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String format(Object selectableValue) {
|
public String format(Object selectableValue) {
|
||||||
Formatter formatter = getFormatter();
|
Formatter formatter = getFormatter();
|
||||||
selectableValue = typeConverter.convert(selectableValue, formatter.getFormattedObjectType());
|
Class<?> formattedType = getFormattedObjectType(formatter);
|
||||||
|
selectableValue = typeConverter.convert(selectableValue, formattedType);
|
||||||
return formatter.format(selectableValue, LocaleContextHolder.getLocale());
|
return formatter.format(selectableValue, LocaleContextHolder.getLocale());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,9 +198,14 @@ public class Binder<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValues(String[] formattedValues) {
|
public void setValues(String[] formattedValues) {
|
||||||
Object values = Array.newInstance(getFormatter().getFormattedObjectType(), formattedValues.length);
|
Formatter formatter = getFormatter();
|
||||||
|
Class parsedType = getFormattedObjectType(formatter);
|
||||||
|
if (parsedType == null) {
|
||||||
|
parsedType = String.class;
|
||||||
|
}
|
||||||
|
Object values = Array.newInstance(parsedType, formattedValues.length);
|
||||||
for (int i = 0; i < formattedValues.length; i++) {
|
for (int i = 0; i < formattedValues.length; i++) {
|
||||||
Array.set(values, i, parse(formattedValues[i]));
|
Array.set(values, i, parse(formattedValues[i], formatter));
|
||||||
}
|
}
|
||||||
setValue(values);
|
setValue(values);
|
||||||
}
|
}
|
||||||
|
|
@ -205,14 +216,15 @@ public class Binder<T> {
|
||||||
|
|
||||||
// internal helpers
|
// internal helpers
|
||||||
|
|
||||||
private Object parse(String formatted) {
|
private Object parse(String formatted, Formatter formatter) {
|
||||||
try {
|
try {
|
||||||
return getFormatter().parse(formatted, LocaleContextHolder.getLocale());
|
return formatter.parse(formatted, LocaleContextHolder.getLocale());
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new IllegalArgumentException("Invalid format " + formatted, e);
|
throw new IllegalArgumentException("Invalid format " + formatted, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private Formatter getFormatter() {
|
private Formatter getFormatter() {
|
||||||
if (formatter != null) {
|
if (formatter != null) {
|
||||||
return formatter;
|
return formatter;
|
||||||
|
|
@ -224,9 +236,9 @@ public class Binder<T> {
|
||||||
} else {
|
} else {
|
||||||
Annotation[] annotations = getAnnotations();
|
Annotation[] annotations = getAnnotations();
|
||||||
for (Annotation a : annotations) {
|
for (Annotation a : annotations) {
|
||||||
formatter = annotationFormatters.get(a.annotationType());
|
AnnotationFormatterFactory factory = annotationFormatters.get(a.annotationType());
|
||||||
if (formatter != null) {
|
if (factory != null) {
|
||||||
return formatter;
|
return factory.getFormatter(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return defaultFormatter;
|
return defaultFormatter;
|
||||||
|
|
@ -276,4 +288,66 @@ public class Binder<T> {
|
||||||
context.setTypeConverter(new StandardTypeConverter(typeConverter));
|
context.setTypeConverter(new StandardTypeConverter(typeConverter));
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Class getAnnotationType(AnnotationFormatterFactory factory) {
|
||||||
|
Class classToIntrospect = factory.getClass();
|
||||||
|
while (classToIntrospect != null) {
|
||||||
|
Type[] genericInterfaces = classToIntrospect.getGenericInterfaces();
|
||||||
|
for (Type genericInterface : genericInterfaces) {
|
||||||
|
if (genericInterface instanceof ParameterizedType) {
|
||||||
|
ParameterizedType pInterface = (ParameterizedType) genericInterface;
|
||||||
|
if (AnnotationFormatterFactory.class.isAssignableFrom((Class) pInterface.getRawType())) {
|
||||||
|
return getParameterClass(pInterface.getActualTypeArguments()[0], factory.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classToIntrospect = classToIntrospect.getSuperclass();
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unable to extract Annotation type A argument from AnnotationFormatterFactory ["
|
||||||
|
+ factory.getClass().getName() + "]; does the factory parameterize the <A> generic type?");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Class getFormattedObjectType(Formatter formatter) {
|
||||||
|
// TODO consider caching this info
|
||||||
|
Class classToIntrospect = formatter.getClass();
|
||||||
|
while (classToIntrospect != null) {
|
||||||
|
Type[] genericInterfaces = classToIntrospect.getGenericInterfaces();
|
||||||
|
for (Type genericInterface : genericInterfaces) {
|
||||||
|
if (genericInterface instanceof ParameterizedType) {
|
||||||
|
ParameterizedType pInterface = (ParameterizedType) genericInterface;
|
||||||
|
if (Formatter.class.isAssignableFrom((Class) pInterface.getRawType())) {
|
||||||
|
return getParameterClass(pInterface.getActualTypeArguments()[0], formatter.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classToIntrospect = classToIntrospect.getSuperclass();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Class getParameterClass(Type parameterType, Class converterClass) {
|
||||||
|
if (parameterType instanceof TypeVariable) {
|
||||||
|
parameterType = GenericTypeResolver.resolveTypeVariable((TypeVariable) parameterType, converterClass);
|
||||||
|
}
|
||||||
|
if (parameterType instanceof Class) {
|
||||||
|
return (Class) parameterType;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unable to obtain the java.lang.Class for parameterType [" + parameterType
|
||||||
|
+ "] on Formatter [" + converterClass.getName() + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
static class SimpleAnnotationFormatterFactory implements AnnotationFormatterFactory {
|
||||||
|
|
||||||
|
private Formatter formatter;
|
||||||
|
|
||||||
|
public SimpleAnnotationFormatterFactory(Formatter formatter) {
|
||||||
|
this.formatter = formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Formatter getFormatter(Annotation annotation) {
|
||||||
|
return formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package org.springframework.ui.format;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
|
||||||
|
public interface AnnotationFormatterFactory<A extends Annotation, T> {
|
||||||
|
Formatter<T> getFormatter(A annotation);
|
||||||
|
}
|
||||||
|
|
@ -50,10 +50,6 @@ public class DateFormatter implements Formatter<Date> {
|
||||||
this.pattern = pattern;
|
this.pattern = pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<Date> getFormattedObjectType() {
|
|
||||||
return Date.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String format(Date date, Locale locale) {
|
public String format(Date date, Locale locale) {
|
||||||
if (date == null) {
|
if (date == null) {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,6 @@ import java.util.Locale;
|
||||||
*/
|
*/
|
||||||
public interface Formatter<T> {
|
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.
|
* Format the object of type T for display.
|
||||||
* @param object the object to format
|
* @param object the object to format
|
||||||
|
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 org.springframework.core.convert.converter.Converter;
|
|
||||||
import org.springframework.core.convert.converter.ConverterRegistry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A factory for adapting formatting and parsing logic in a {@link Formatter} to the {@link Converter} contract.
|
|
||||||
* @author Keith Donald
|
|
||||||
*/
|
|
||||||
public class FormatterConverterFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register converter adapters for the formatter.
|
|
||||||
* An adapter will be registered for formatting to String as well as parsing from String.
|
|
||||||
* @param <T> The type of formatter
|
|
||||||
* @param formatter the formatter
|
|
||||||
* @param registry the converter registry
|
|
||||||
*/
|
|
||||||
public static <T> void add(Formatter<T> formatter,
|
|
||||||
ConverterRegistry registry) {
|
|
||||||
registry.add(new FormattingConverter<T>(formatter));
|
|
||||||
registry.add(new ParsingConverter<T>(formatter));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the Formatter/converter adapters previously registered for the formatted type.
|
|
||||||
* @param <T> the formatted type
|
|
||||||
* @param formattedType the formatted type
|
|
||||||
* @param registry the converter registry
|
|
||||||
*/
|
|
||||||
public static <T> void remove(Class<T> formattedType,
|
|
||||||
ConverterRegistry registry) {
|
|
||||||
registry.removeConverter(formattedType, String.class);
|
|
||||||
registry.removeConverter(String.class, formattedType);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 org.springframework.context.i18n.LocaleContextHolder;
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
|
||||||
|
|
||||||
class FormattingConverter<T> implements Converter<T, String> {
|
|
||||||
|
|
||||||
private Formatter<T> formatter;
|
|
||||||
|
|
||||||
public FormattingConverter(Formatter<T> formatter) {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.ParseException;
|
|
||||||
|
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
|
||||||
|
|
||||||
class ParsingConverter<T> implements Converter<String, T> {
|
|
||||||
|
|
||||||
private Formatter<T> formatter;
|
|
||||||
|
|
||||||
public ParsingConverter(Formatter<T> formatter) {
|
|
||||||
this.formatter = formatter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T convert(String source) throws ParseException {
|
|
||||||
return formatter.parse(source, LocaleContextHolder.getLocale());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package org.springframework.ui.format.number;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.springframework.ui.format.AnnotationFormatterFactory;
|
||||||
|
import org.springframework.ui.format.Formatter;
|
||||||
|
|
||||||
|
public class CurrencyAnnotationFormatterFactory implements AnnotationFormatterFactory<CurrencyFormat, BigDecimal> {
|
||||||
|
public Formatter<BigDecimal> getFormatter(CurrencyFormat annotation) {
|
||||||
|
return new CurrencyFormatter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.springframework.ui.format.number;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A annotation to apply to a BigDecimal property to have property values formatted as currency using a {@link CurrencyFormatter}.
|
||||||
|
* @author Keith Donald
|
||||||
|
*/
|
||||||
|
@Target( { ElementType.METHOD, ElementType.FIELD })
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface CurrencyFormat {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -38,10 +38,6 @@ public class CurrencyFormatter implements Formatter<BigDecimal> {
|
||||||
|
|
||||||
private boolean lenient;
|
private boolean lenient;
|
||||||
|
|
||||||
public Class<BigDecimal> getFormattedObjectType() {
|
|
||||||
return BigDecimal.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String format(BigDecimal decimal, Locale locale) {
|
public String format(BigDecimal decimal, Locale locale) {
|
||||||
if (decimal == null) {
|
if (decimal == null) {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produces NumberFormat instances that format currency values.
|
* Produces NumberFormat instances that format currency values.
|
||||||
*
|
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @see NumberFormat
|
* @see NumberFormat
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,6 @@ public class DecimalFormatter implements Formatter<BigDecimal> {
|
||||||
initDefaults();
|
initDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<BigDecimal> getFormattedObjectType() {
|
|
||||||
return BigDecimal.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DecimalFormatter(String pattern) {
|
public DecimalFormatter(String pattern) {
|
||||||
initDefaults();
|
initDefaults();
|
||||||
formatFactory.setPattern(pattern);
|
formatFactory.setPattern(pattern);
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,6 @@ public class IntegerFormatter implements Formatter<Long> {
|
||||||
|
|
||||||
private boolean lenient;
|
private boolean lenient;
|
||||||
|
|
||||||
public Class<Long> getFormattedObjectType() {
|
|
||||||
return Long.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String format(Long integer, Locale locale) {
|
public String format(Long integer, Locale locale) {
|
||||||
if (integer == null) {
|
if (integer == null) {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,6 @@ public class PercentFormatter implements Formatter<BigDecimal> {
|
||||||
|
|
||||||
private boolean lenient;
|
private boolean lenient;
|
||||||
|
|
||||||
public Class<BigDecimal> getFormattedObjectType() {
|
|
||||||
return BigDecimal.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String format(BigDecimal decimal, Locale locale) {
|
public String format(BigDecimal decimal, Locale locale) {
|
||||||
if (decimal == null) {
|
if (decimal == null) {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
@ -22,6 +20,8 @@ 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.format.DateFormatter;
|
import org.springframework.ui.format.DateFormatter;
|
||||||
|
import org.springframework.ui.format.number.CurrencyAnnotationFormatterFactory;
|
||||||
|
import org.springframework.ui.format.number.CurrencyFormat;
|
||||||
import org.springframework.ui.format.number.CurrencyFormatter;
|
import org.springframework.ui.format.number.CurrencyFormatter;
|
||||||
import org.springframework.ui.format.number.IntegerFormatter;
|
import org.springframework.ui.format.number.IntegerFormatter;
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ public class BinderTests {
|
||||||
|
|
||||||
// TODO should update error context, not throw exception
|
// TODO should update error context, not throw exception
|
||||||
@Test(expected=IllegalArgumentException.class)
|
@Test(expected=IllegalArgumentException.class)
|
||||||
public void bindSingleValuesWithDefaultTypeCoversionFailures() {
|
public void bindSingleValuesWithDefaultTypeCoversionFailure() {
|
||||||
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||||
Map<String, String> propertyValues = new HashMap<String, String>();
|
Map<String, String> propertyValues = new HashMap<String, String>();
|
||||||
propertyValues.put("string", "test");
|
propertyValues.put("string", "test");
|
||||||
|
|
@ -62,7 +62,7 @@ public class BinderTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindSingleValuePropertyFormatterParsing() 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()));
|
||||||
Map<String, String> propertyValues = new HashMap<String, String>();
|
Map<String, String> propertyValues = new HashMap<String, String>();
|
||||||
|
|
@ -82,7 +82,7 @@ public class BinderTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindSingleValueTypeFormatterParsing() 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);
|
||||||
Map<String, String> propertyValues = new HashMap<String, String>();
|
Map<String, String> propertyValues = new HashMap<String, String>();
|
||||||
|
|
@ -92,9 +92,19 @@ public class BinderTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bindSingleValueAnnotationFormatterParsing() 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(), Currency.class);
|
binder.add(new CurrencyFormatter(), CurrencyFormat.class);
|
||||||
|
Map<String, String> propertyValues = new HashMap<String, String>();
|
||||||
|
propertyValues.put("currency", "$23.56");
|
||||||
|
binder.bind(propertyValues);
|
||||||
|
assertEquals(new BigDecimal("23.56"), binder.getModel().getCurrency());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bindSingleValueWithnAnnotationFormatterFactoryRegistered() throws ParseException {
|
||||||
|
Binder<TestBean> binder = new Binder<TestBean>(new TestBean());
|
||||||
|
binder.add(new CurrencyAnnotationFormatterFactory());
|
||||||
Map<String, String> propertyValues = new HashMap<String, String>();
|
Map<String, String> propertyValues = new HashMap<String, String>();
|
||||||
propertyValues.put("currency", "$23.56");
|
propertyValues.put("currency", "$23.56");
|
||||||
binder.bind(propertyValues);
|
binder.bind(propertyValues);
|
||||||
|
|
@ -261,7 +271,7 @@ public class BinderTests {
|
||||||
this.foo = foo;
|
this.foo = foo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Currency
|
@CurrencyFormat
|
||||||
public BigDecimal getCurrency() {
|
public BigDecimal getCurrency() {
|
||||||
return currency;
|
return currency;
|
||||||
}
|
}
|
||||||
|
|
@ -288,11 +298,6 @@ public class BinderTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
public @interface Currency {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Address {
|
public static class Address {
|
||||||
private String street;
|
private String street;
|
||||||
private String city;
|
private String city;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
package org.springframework.ui.message.support;
|
package org.springframework.ui.message.support;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
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.support.StaticMessageSource;
|
import org.springframework.context.support.StaticMessageSource;
|
||||||
import org.springframework.ui.message.Message;
|
import org.springframework.ui.message.Message;
|
||||||
import org.springframework.ui.message.MessageBuilder;
|
import org.springframework.ui.message.MessageBuilder;
|
||||||
|
|
@ -24,6 +26,12 @@ public class DefaultMessageContextTests {
|
||||||
messageSource.addMessage("invalidFormat", Locale.US, "{0} must be in format {1}");
|
messageSource.addMessage("invalidFormat", Locale.US, "{0} must be in format {1}");
|
||||||
messageSource.addMessage("mathForm.decimalField", Locale.US, "Decimal Field");
|
messageSource.addMessage("mathForm.decimalField", Locale.US, "Decimal Field");
|
||||||
context = new DefaultMessageContext(messageSource);
|
context = new DefaultMessageContext(messageSource);
|
||||||
|
LocaleContextHolder.setLocale(Locale.US);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
LocaleContextHolder.setLocale(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue