formatter improvements
This commit is contained in:
@@ -15,34 +15,37 @@
|
||||
*/
|
||||
package org.springframework.binding.convert.support;
|
||||
|
||||
import org.springframework.binding.format.FormatterFactory;
|
||||
import org.springframework.binding.convert.ConversionContext;
|
||||
import org.springframework.binding.format.FormatterRegistry;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A converter that delegates to a formatter to perform the conversion. Formatters are typically not thread safe, so we
|
||||
* use a FormatterFactory that is expected to provide us with thread-safe instances as necessary.
|
||||
* use a FormatterRegistry that is expected to provide us with instances local to the current thread.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public abstract class AbstractFormattingConverter extends AbstractConverter {
|
||||
|
||||
/**
|
||||
* The formatter factory.
|
||||
* The formatter registry.
|
||||
*/
|
||||
private FormatterFactory formatterFactory;
|
||||
private FormatterRegistry formatterRegistry;
|
||||
|
||||
/**
|
||||
* Creates a new converter that delegates to a formatter.
|
||||
* @param formatterFactory the factory to use
|
||||
* @param formatterRegistry the formatterRegistry to use
|
||||
*/
|
||||
protected AbstractFormattingConverter(FormatterFactory formatterFactory) {
|
||||
setFormatterFactory(formatterFactory);
|
||||
protected AbstractFormattingConverter(FormatterRegistry formatterRegistry) {
|
||||
Assert.notNull(formatterRegistry, "The formatter registry is required");
|
||||
this.formatterRegistry = formatterRegistry;
|
||||
}
|
||||
|
||||
protected FormatterFactory getFormatterFactory() {
|
||||
return formatterFactory;
|
||||
public FormatterRegistry getFormatterRegistry() {
|
||||
return formatterRegistry;
|
||||
}
|
||||
|
||||
public void setFormatterFactory(FormatterFactory formatterSource) {
|
||||
this.formatterFactory = formatterSource;
|
||||
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
|
||||
return getFormatterRegistry().getFormatter(targetClass).parseValue((String) source);
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ import org.springframework.util.Assert;
|
||||
* supported. If you need this capability, use a Formatter with a FormatterPropertyEditor adapter.
|
||||
*
|
||||
* @see org.springframework.binding.format.Formatter
|
||||
* @see org.springframework.binding.format.support.FormatterPropertyEditor
|
||||
* @see org.springframework.binding.format.adapters.FormatterPropertyEditor
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,10 @@ package org.springframework.binding.convert.support;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.springframework.binding.format.support.SimpleFormatterFactory;
|
||||
import org.springframework.binding.format.FormatterRegistry;
|
||||
import org.springframework.binding.format.factories.DateFormatterFactory;
|
||||
import org.springframework.binding.format.factories.NumberFormatterFactory;
|
||||
import org.springframework.binding.format.impl.FormatterRegistryImpl;
|
||||
import org.springframework.core.enums.LabeledEnum;
|
||||
|
||||
/**
|
||||
@@ -29,10 +32,16 @@ import org.springframework.core.enums.LabeledEnum;
|
||||
*/
|
||||
public class DefaultConversionService extends GenericConversionService {
|
||||
|
||||
/**
|
||||
* Returns the formatter registry used by this conversion service
|
||||
*/
|
||||
private FormatterRegistry formatterRegistry;
|
||||
|
||||
/**
|
||||
* Creates a new default conversion service, installing the default converters.
|
||||
*/
|
||||
public DefaultConversionService() {
|
||||
formatterRegistry = createDefaultFormatterRegistry();
|
||||
addDefaultConverters();
|
||||
}
|
||||
|
||||
@@ -41,11 +50,10 @@ public class DefaultConversionService extends GenericConversionService {
|
||||
*/
|
||||
protected void addDefaultConverters() {
|
||||
addConverter(new TextToClass());
|
||||
addConverter(new TextToNumber(new SimpleFormatterFactory()));
|
||||
addConverter(new TextToBoolean());
|
||||
addConverter(new TextToLabeledEnum());
|
||||
|
||||
// we're not using addDefaultAlias here for efficiency reasons
|
||||
addConverter(new TextToNumber(formatterRegistry));
|
||||
addConverter(new TextToDate(formatterRegistry));
|
||||
addAlias("string", String.class);
|
||||
addAlias("short", Short.class);
|
||||
addAlias("integer", Integer.class);
|
||||
@@ -60,4 +68,11 @@ public class DefaultConversionService extends GenericConversionService {
|
||||
addAlias("class", Class.class);
|
||||
addAlias("labeledEnum", LabeledEnum.class);
|
||||
}
|
||||
|
||||
protected FormatterRegistry createDefaultFormatterRegistry() {
|
||||
FormatterRegistryImpl registry = new FormatterRegistryImpl();
|
||||
registry.registerFormatter(new NumberFormatterFactory());
|
||||
registry.registerFormatter(new DateFormatterFactory());
|
||||
return registry;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2004-2007 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.binding.convert.support;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.binding.format.FormatterRegistry;
|
||||
|
||||
/**
|
||||
* Converts textual representations of numbers to a <code>Number</code> specialization. Delegates to a synchronized
|
||||
* formatter to parse text strings.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class TextToDate extends AbstractFormattingConverter {
|
||||
|
||||
/**
|
||||
* Create a string to number converter using given formatter factory.
|
||||
* @param formatterRegistry the formatter registry to use
|
||||
*/
|
||||
public TextToDate(FormatterRegistry formatterRegistry) {
|
||||
super(formatterRegistry);
|
||||
}
|
||||
|
||||
public Class[] getSourceClasses() {
|
||||
return new Class[] { String.class };
|
||||
}
|
||||
|
||||
public Class[] getTargetClasses() {
|
||||
return new Class[] { Date.class };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,9 +18,7 @@ package org.springframework.binding.convert.support;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.springframework.binding.convert.ConversionContext;
|
||||
import org.springframework.binding.format.FormatterFactory;
|
||||
import org.springframework.binding.format.support.SimpleFormatterFactory;
|
||||
import org.springframework.binding.format.FormatterRegistry;
|
||||
|
||||
/**
|
||||
* Converts textual representations of numbers to a <code>Number</code> specialization. Delegates to a synchronized
|
||||
@@ -30,19 +28,12 @@ import org.springframework.binding.format.support.SimpleFormatterFactory;
|
||||
*/
|
||||
public class TextToNumber extends AbstractFormattingConverter {
|
||||
|
||||
/**
|
||||
* Default constructor that uses a {@link SimpleFormatterFactory}.
|
||||
*/
|
||||
public TextToNumber() {
|
||||
super(new SimpleFormatterFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a string to number converter using given formatter factory.
|
||||
* @param formatterFactory the factory to use
|
||||
* @param formatterRegistry the formatter registry to use
|
||||
*/
|
||||
public TextToNumber(FormatterFactory formatterFactory) {
|
||||
super(formatterFactory);
|
||||
public TextToNumber(FormatterRegistry formatterRegistry) {
|
||||
super(formatterRegistry);
|
||||
}
|
||||
|
||||
public Class[] getSourceClasses() {
|
||||
@@ -53,8 +44,4 @@ public class TextToNumber extends AbstractFormattingConverter {
|
||||
return new Class[] { Integer.class, Short.class, Long.class, Float.class, Double.class, Byte.class,
|
||||
BigInteger.class, BigDecimal.class };
|
||||
}
|
||||
|
||||
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
|
||||
return getFormatterFactory().getNumberFormatter(targetClass).parseValue((String) source, targetClass);
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,10 @@ package org.springframework.binding.format;
|
||||
|
||||
/**
|
||||
* A lightweight interface for formatting a value and parsing a value from its formatted form.
|
||||
*
|
||||
* <p>
|
||||
* Note: formatters are typically not thread safe as <code>Format</code> objects aren't thread safe. In general, you
|
||||
* should not attempt to share formatters between threads.
|
||||
* </p>
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface Formatter {
|
||||
@@ -33,10 +36,9 @@ public interface Formatter {
|
||||
/**
|
||||
* Parse the formatted string representation of a value, restoring the value.
|
||||
* @param formattedString the formatted string representation
|
||||
* @param targetClass the target class to convert the formatted value to
|
||||
* @return the parsed value
|
||||
* @throws InvalidFormatException the string was in an invalid form
|
||||
*/
|
||||
public Object parseValue(String formattedString, Class targetClass) throws InvalidFormatException;
|
||||
public Object parseValue(String formattedString) throws InvalidFormatException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.springframework.binding.format;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* A context for creating a formatter instance.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface FormatterFactoryContext {
|
||||
|
||||
/**
|
||||
* The current locale.
|
||||
*/
|
||||
public Locale getLocale();
|
||||
|
||||
/**
|
||||
* The type of object of which formatting is desired.
|
||||
*/
|
||||
public Class getFormattedClass();
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2004-2007 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.binding.format;
|
||||
|
||||
/**
|
||||
* Source for shared and commonly used <code>Formatters</code>.
|
||||
* <p>
|
||||
* Note: formatters are typically not thread safe as <code>Format</code> objects aren't thread safe. In general, you
|
||||
* should not attempt to share formatters between threads.
|
||||
* </p>
|
||||
* @see java.text.Format
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface FormatterRegistry {
|
||||
|
||||
/**
|
||||
* Returns the default formatter installed for the given class of object.
|
||||
* @param clazz the type of object that will be formatted
|
||||
* @return the formatter
|
||||
*/
|
||||
public Formatter getFormatter(Class clazz);
|
||||
|
||||
/**
|
||||
* Returns the formatter for the given class of object with the given id. Use this method to query a custom
|
||||
* formatter instance for a given class of object.
|
||||
* @param id the id of the custom formatter instance; typically descriptive like "localDate"
|
||||
* @param clazz the class being formatted e.g. Date.class.
|
||||
* @return the formatter
|
||||
*/
|
||||
public Formatter getFormatter(String id, Class clazz);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.springframework.binding.format;
|
||||
|
||||
public class NoSuchFormatterException extends RuntimeException {
|
||||
|
||||
private Class formatterFormattedClass;
|
||||
|
||||
private String formatterId;
|
||||
|
||||
public NoSuchFormatterException(Class formatterFormattedClass) {
|
||||
super("No default formatter for class " + formatterFormattedClass + "; make sure a formatter is registered");
|
||||
this.formatterFormattedClass = formatterFormattedClass;
|
||||
}
|
||||
|
||||
public NoSuchFormatterException(String formatterId, Class formatterFormattedClass) {
|
||||
super("No custom formatter could be found with id '" + formatterId + "' for class " + formatterFormattedClass
|
||||
+ "; check your spelling and make sure the formatter is registered");
|
||||
this.formatterId = formatterId;
|
||||
}
|
||||
|
||||
public Class getFormatterFormattedClass() {
|
||||
return formatterFormattedClass;
|
||||
}
|
||||
|
||||
public String getFormatterId() {
|
||||
return formatterId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2007 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.binding.format;
|
||||
|
||||
import java.text.DateFormat;
|
||||
|
||||
import org.springframework.core.enums.StaticLabeledEnum;
|
||||
|
||||
/**
|
||||
* Format styles, similar to those defined by {@link java.text.DateFormat}.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class Style extends StaticLabeledEnum {
|
||||
|
||||
/**
|
||||
* See {@link java.text.DateFormat#FULL}.
|
||||
*/
|
||||
public static final Style FULL = new Style(DateFormat.FULL, "Full");
|
||||
|
||||
/**
|
||||
* See {@link java.text.DateFormat#LONG}.
|
||||
*/
|
||||
public static final Style LONG = new Style(DateFormat.LONG, "Long");
|
||||
|
||||
/**
|
||||
* See {@link java.text.DateFormat#MEDIUM}.
|
||||
*/
|
||||
public static final Style MEDIUM = new Style(DateFormat.MEDIUM, "Medium");
|
||||
|
||||
/**
|
||||
* See {@link java.text.DateFormat#SHORT}.
|
||||
*/
|
||||
public static final Style SHORT = new Style(DateFormat.SHORT, "Short");
|
||||
|
||||
/**
|
||||
* Private constructor since this is a type-safe enum.
|
||||
*/
|
||||
private Style(int code, String label) {
|
||||
super(code, label);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.binding.format.support;
|
||||
package org.springframework.binding.format.adapters;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
@@ -31,11 +31,6 @@ public class FormatterPropertyEditor extends PropertyEditorSupport {
|
||||
*/
|
||||
private Formatter formatter;
|
||||
|
||||
/**
|
||||
* The target value class (may be null).
|
||||
*/
|
||||
private Class targetClass;
|
||||
|
||||
/**
|
||||
* Creates a formatter property editor.
|
||||
* @param formatter the formatter to adapt
|
||||
@@ -44,21 +39,11 @@ public class FormatterPropertyEditor extends PropertyEditorSupport {
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a formatter property editor.
|
||||
* @param formatter the formatter to adapt
|
||||
* @param targetClass the target class for "setAsText" conversions
|
||||
*/
|
||||
public FormatterPropertyEditor(Formatter formatter, Class targetClass) {
|
||||
this.formatter = formatter;
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
public String getAsText() {
|
||||
return formatter.formatValue(getValue());
|
||||
}
|
||||
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
setValue(formatter.parseValue(text, targetClass));
|
||||
setValue(formatter.parseValue(text));
|
||||
}
|
||||
}
|
||||
@@ -13,10 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.binding.format.support;
|
||||
package org.springframework.binding.format.adapters;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
|
||||
import org.springframework.binding.format.factories.AbstractFormatter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -48,7 +49,7 @@ public class PropertyEditorFormatter extends AbstractFormatter {
|
||||
return propertyEditor.getAsText();
|
||||
}
|
||||
|
||||
protected Object doParseValue(String formattedValue, Class targetClass) {
|
||||
protected Object doParseValue(String formattedValue) {
|
||||
propertyEditor.setAsText(formattedValue);
|
||||
return propertyEditor.getValue();
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.binding.format.support;
|
||||
package org.springframework.binding.format.factories;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
@@ -42,14 +42,14 @@ public abstract class AbstractFormatter implements Formatter {
|
||||
}
|
||||
}
|
||||
|
||||
public final Object parseValue(String formattedString, Class targetClass) throws InvalidFormatException {
|
||||
public final Object parseValue(String formattedString) throws InvalidFormatException {
|
||||
try {
|
||||
if (isEmpty(formattedString)) {
|
||||
return getEmptyValue();
|
||||
}
|
||||
return doParseValue(formattedString, targetClass);
|
||||
return doParseValue(formattedString);
|
||||
} catch (ParseException ex) {
|
||||
throw new InvalidFormatException(formattedString, getExpectedFormat(targetClass), ex);
|
||||
throw new InvalidFormatException(formattedString, getExpectedFormat(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,13 +70,11 @@ public abstract class AbstractFormatter implements Formatter {
|
||||
/**
|
||||
* Template method subclasses should override to encapsulate parsing logic.
|
||||
* @param formattedString the formatted string to parse
|
||||
* @param targetClass the target class to convert the formatted value to
|
||||
* @return the parsed value
|
||||
* @throws InvalidFormatException an exception occurred parsing
|
||||
* @throws ParseException when parse exceptions occur
|
||||
*/
|
||||
protected abstract Object doParseValue(String formattedString, Class targetClass) throws InvalidFormatException,
|
||||
ParseException;
|
||||
protected abstract Object doParseValue(String formattedString) throws InvalidFormatException, ParseException;
|
||||
|
||||
/**
|
||||
* Returns the empty value (resulting from parsing an empty input string). This default implementation just returns
|
||||
@@ -89,7 +87,7 @@ public abstract class AbstractFormatter implements Formatter {
|
||||
/**
|
||||
* Returns the expected string format for the given target class. The default implementation just returns null.
|
||||
*/
|
||||
protected String getExpectedFormat(Class targetClass) {
|
||||
protected String getExpectedFormat() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.springframework.binding.format.factories;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.binding.format.Formatter;
|
||||
import org.springframework.binding.format.FormatterFactory;
|
||||
import org.springframework.binding.format.FormatterFactoryContext;
|
||||
|
||||
/**
|
||||
* Factory for date formatters.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class DateFormatterFactory implements FormatterFactory {
|
||||
|
||||
public Class getFormattedClass() {
|
||||
return Date.class;
|
||||
}
|
||||
|
||||
public Formatter createFormatter(FormatterFactoryContext context) {
|
||||
return new DateFormatter(getDateFormat(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date format to use with the formatter being created. Subclasses may override.
|
||||
* @param context the factory context
|
||||
* @return the date format
|
||||
*/
|
||||
protected DateFormat getDateFormat(FormatterFactoryContext context) {
|
||||
return DateFormat.getDateInstance(DateFormat.SHORT, context.getLocale());
|
||||
}
|
||||
|
||||
private class DateFormatter extends AbstractFormatter {
|
||||
|
||||
private DateFormat dateFormat;
|
||||
|
||||
/**
|
||||
* Constructs a date formatter that will delegate to the specified date format.
|
||||
* @param dateFormat the date format to use
|
||||
*/
|
||||
public DateFormatter(DateFormat dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
// convert from date to string
|
||||
protected String doFormatValue(Object date) {
|
||||
return dateFormat.format((Date) date);
|
||||
}
|
||||
|
||||
// convert back from string to date
|
||||
protected Object doParseValue(String formattedString) throws ParseException {
|
||||
return dateFormat.parse(formattedString);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package org.springframework.binding.format.factories;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import org.springframework.binding.format.Formatter;
|
||||
import org.springframework.binding.format.FormatterFactory;
|
||||
import org.springframework.binding.format.FormatterFactoryContext;
|
||||
import org.springframework.util.NumberUtils;
|
||||
|
||||
/**
|
||||
* Factory for number formatters.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class NumberFormatterFactory implements FormatterFactory {
|
||||
|
||||
public Class getFormattedClass() {
|
||||
return Number.class;
|
||||
}
|
||||
|
||||
public Formatter createFormatter(FormatterFactoryContext context) {
|
||||
return new NumberFormatter(getNumberFormat(context), context.getFormattedClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number format to use with the formatter being created. Subclasses may override.
|
||||
* @param context the factory context
|
||||
* @return the number format
|
||||
*/
|
||||
protected NumberFormat getNumberFormat(FormatterFactoryContext context) {
|
||||
if (context.getFormattedClass().equals(Integer.class)) {
|
||||
return NumberFormat.getIntegerInstance(context.getLocale());
|
||||
} else {
|
||||
return NumberFormat.getNumberInstance(context.getLocale());
|
||||
}
|
||||
}
|
||||
|
||||
private class NumberFormatter extends AbstractFormatter {
|
||||
|
||||
private NumberFormat numberFormat;
|
||||
|
||||
private Class targetClass;
|
||||
|
||||
/**
|
||||
* Create a new number formatter.
|
||||
* @param numberFormat the number format to use
|
||||
* @param targetClass the number class to parse into
|
||||
*/
|
||||
public NumberFormatter(NumberFormat numberFormat, Class targetClass) {
|
||||
this.numberFormat = numberFormat;
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
protected String doFormatValue(Object number) {
|
||||
if (numberFormat != null) {
|
||||
// use NumberFormat for rendering value
|
||||
return numberFormat.format(number);
|
||||
} else {
|
||||
// use toString method for rendering value
|
||||
return number.toString();
|
||||
}
|
||||
}
|
||||
|
||||
protected Object doParseValue(String text) throws IllegalArgumentException {
|
||||
if (numberFormat != null) {
|
||||
// use given NumberFormat for parsing text
|
||||
return NumberUtils.parseNumber(text, targetClass, numberFormat);
|
||||
} else {
|
||||
// use default valueOf methods for parsing text
|
||||
return NumberUtils.parseNumber(text, targetClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.springframework.binding.format.impl;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.binding.format.FormatterFactoryContext;
|
||||
|
||||
public class FormatterFactoryContextImpl implements FormatterFactoryContext {
|
||||
|
||||
private Class formattedClass;
|
||||
|
||||
private Locale locale;
|
||||
|
||||
public Class getFormattedClass() {
|
||||
return formattedClass;
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
public void setFormattedClass(Class formattedClass) {
|
||||
this.formattedClass = formattedClass;
|
||||
}
|
||||
|
||||
public void setLocale(Locale locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2004-2007 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.binding.format.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.binding.format.Formatter;
|
||||
import org.springframework.binding.format.FormatterFactory;
|
||||
import org.springframework.binding.format.FormatterRegistry;
|
||||
import org.springframework.binding.format.NoSuchFormatterException;
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.context.i18n.SimpleLocaleContext;
|
||||
|
||||
/**
|
||||
* Base class for formatter factories. Manages the locale used by the produced formatters using Spring's
|
||||
* {@link org.springframework.context.i18n.LocaleContext} system.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class FormatterRegistryImpl implements FormatterRegistry {
|
||||
|
||||
private LocaleContext localeContext = new SimpleLocaleContext(Locale.getDefault());
|
||||
|
||||
private Map formattersById = new HashMap();
|
||||
|
||||
private Map formattersByClass = new HashMap();
|
||||
|
||||
/**
|
||||
* Sets the locale context to use if no locale has been bound to the current thread. Optional. Defaults to a
|
||||
* {@link SimpleLocaleContext} holding the system default locale.
|
||||
* @param localeContext the locale context
|
||||
*/
|
||||
public void setLocaleContext(LocaleContext localeContext) {
|
||||
this.localeContext = localeContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the locale in use.
|
||||
*/
|
||||
protected Locale getLocale() {
|
||||
Locale currentLocale = LocaleContextHolder.getLocale();
|
||||
if (currentLocale != null) {
|
||||
return currentLocale;
|
||||
} else {
|
||||
return localeContext.getLocale();
|
||||
}
|
||||
}
|
||||
|
||||
public Formatter getFormatter(Class clazz) {
|
||||
FormatterFactory factory = findFormatterFactory(clazz);
|
||||
if (factory != null) {
|
||||
FormatterFactoryContextImpl context = new FormatterFactoryContextImpl();
|
||||
context.setLocale(getLocale());
|
||||
context.setFormattedClass(clazz);
|
||||
return factory.createFormatter(context);
|
||||
} else {
|
||||
throw new NoSuchFormatterException(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
public Formatter getFormatter(String id, Class clazz) {
|
||||
FormatterFactory factory = (FormatterFactory) formattersById.get(id);
|
||||
if (factory != null) {
|
||||
FormatterFactoryContextImpl context = new FormatterFactoryContextImpl();
|
||||
context.setLocale(getLocale());
|
||||
context.setFormattedClass(clazz);
|
||||
return factory.createFormatter(context);
|
||||
} else {
|
||||
throw new NoSuchFormatterException(id, clazz);
|
||||
}
|
||||
}
|
||||
|
||||
private FormatterFactory findFormatterFactory(Class clazz) {
|
||||
FormatterFactory factory = (FormatterFactory) formattersByClass.get(clazz);
|
||||
if (factory != null) {
|
||||
return factory;
|
||||
} else {
|
||||
if (clazz.getSuperclass() != Object.class) {
|
||||
return findFormatterFactory(clazz.getSuperclass());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerFormatter(String id, FormatterFactory factory) {
|
||||
formattersById.put(id, factory);
|
||||
Class formattedClass = factory.getFormattedClass();
|
||||
if (!formattersByClass.containsKey(formattedClass)) {
|
||||
formattersByClass.put(formattedClass, factory);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerFormatter(FormatterFactory factory) {
|
||||
formattersByClass.put(factory.getFormattedClass(), factory);
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2007 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.binding.format.support;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.binding.format.Formatter;
|
||||
import org.springframework.binding.format.FormatterFactory;
|
||||
import org.springframework.binding.format.Style;
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.SimpleLocaleContext;
|
||||
|
||||
/**
|
||||
* Base class for formatter factories. Manages the locale used by the produced formatters using Spring's
|
||||
* {@link org.springframework.context.i18n.LocaleContext} system.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public abstract class AbstractFormatterFactory implements FormatterFactory {
|
||||
|
||||
private LocaleContext localeContext = new SimpleLocaleContext(Locale.getDefault());
|
||||
|
||||
private Style defaultDateStyle = Style.MEDIUM;
|
||||
|
||||
private Style defaultTimeStyle = Style.MEDIUM;
|
||||
|
||||
/**
|
||||
* Sets the locale context used. Defaults to a {@link SimpleLocaleContext} holding the system default locale.
|
||||
*/
|
||||
public void setLocaleContext(LocaleContext localeContext) {
|
||||
this.localeContext = localeContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the locale in use.
|
||||
*/
|
||||
protected Locale getLocale() {
|
||||
return localeContext.getLocale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default date style. Defaults to {@link Style#MEDIUM}.
|
||||
*/
|
||||
protected Style getDefaultDateStyle() {
|
||||
return defaultDateStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default date style.
|
||||
*/
|
||||
public void setDefaultDateStyle(Style defaultDateStyle) {
|
||||
this.defaultDateStyle = defaultDateStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default time style. Defaults to {@link Style#MEDIUM}.
|
||||
*/
|
||||
public Style getDefaultTimeStyle() {
|
||||
return defaultTimeStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default time style.
|
||||
*/
|
||||
public void setDefaultTimeStyle(Style defaultTimeStyle) {
|
||||
this.defaultTimeStyle = defaultTimeStyle;
|
||||
}
|
||||
|
||||
public Formatter getDateFormatter() {
|
||||
return getDateFormatter(getDefaultDateStyle());
|
||||
}
|
||||
|
||||
public Formatter getDateTimeFormatter() {
|
||||
return getDateTimeFormatter(getDefaultDateStyle(), getDefaultTimeStyle());
|
||||
}
|
||||
|
||||
public Formatter getTimeFormatter() {
|
||||
return getTimeFormatter(getDefaultTimeStyle());
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2007 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.binding.format.support;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.binding.format.InvalidFormatException;
|
||||
|
||||
/**
|
||||
* Formatter that formats date objects.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class DateFormatter extends AbstractFormatter {
|
||||
|
||||
private DateFormat dateFormat;
|
||||
|
||||
/**
|
||||
* Constructs a date formatter that will delegate to the specified date format.
|
||||
* @param dateFormat the date format to use
|
||||
*/
|
||||
public DateFormatter(DateFormat dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
// convert from date to string
|
||||
protected String doFormatValue(Object date) {
|
||||
return dateFormat.format((Date) date);
|
||||
}
|
||||
|
||||
// convert back from string to date
|
||||
protected Object doParseValue(String formattedString, Class targetClass) throws ParseException {
|
||||
return dateFormat.parse(formattedString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to parse a date.
|
||||
*/
|
||||
public Date parseDate(String formattedString) throws InvalidFormatException {
|
||||
return (Date) parseValue(formattedString, Date.class);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2007 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.binding.format.support;
|
||||
|
||||
import org.springframework.binding.format.InvalidFormatException;
|
||||
import org.springframework.core.enums.LabeledEnum;
|
||||
import org.springframework.core.enums.LabeledEnumResolver;
|
||||
import org.springframework.core.enums.StaticLabeledEnumResolver;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Converts from string to a <cod>LabeledEnum</code> instance and back.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class LabeledEnumFormatter extends AbstractFormatter {
|
||||
|
||||
private LabeledEnumResolver labeledEnumResolver = StaticLabeledEnumResolver.instance();
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public LabeledEnumFormatter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the LabeledEnumResolver used. Defaults to {@link StaticLabeledEnumResolver}.
|
||||
*/
|
||||
public void setLabeledEnumResolver(LabeledEnumResolver labeledEnumResolver) {
|
||||
Assert.notNull(labeledEnumResolver, "The labeled enum resolver is required");
|
||||
this.labeledEnumResolver = labeledEnumResolver;
|
||||
}
|
||||
|
||||
protected String doFormatValue(Object value) {
|
||||
LabeledEnum labeledEnum = (LabeledEnum) value;
|
||||
return labeledEnum.getLabel();
|
||||
}
|
||||
|
||||
protected Object doParseValue(String formattedString, Class targetClass) throws IllegalArgumentException {
|
||||
return labeledEnumResolver.getLabeledEnumByLabel(targetClass, formattedString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to parse a LabeledEnum.
|
||||
*/
|
||||
public LabeledEnum parseLabeledEnum(String formattedString, Class enumClass) throws InvalidFormatException {
|
||||
return (LabeledEnum) parseValue(formattedString, enumClass);
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2007 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.binding.format.support;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import org.springframework.binding.format.InvalidFormatException;
|
||||
import org.springframework.util.NumberUtils;
|
||||
|
||||
/**
|
||||
* Converts from various <code>Number</code> specializations to <code>String</code> and back.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class NumberFormatter extends AbstractFormatter {
|
||||
|
||||
private NumberFormat numberFormat;
|
||||
|
||||
/**
|
||||
* Create a new number formatter.
|
||||
* @param numberFormat the number format to use
|
||||
*/
|
||||
public NumberFormatter(NumberFormat numberFormat) {
|
||||
this.numberFormat = numberFormat;
|
||||
}
|
||||
|
||||
protected String doFormatValue(Object number) {
|
||||
if (this.numberFormat != null) {
|
||||
// use NumberFormat for rendering value
|
||||
return this.numberFormat.format(number);
|
||||
} else {
|
||||
// use toString method for rendering value
|
||||
return number.toString();
|
||||
}
|
||||
}
|
||||
|
||||
protected Object doParseValue(String text, Class targetClass) throws IllegalArgumentException {
|
||||
if (this.numberFormat != null) {
|
||||
// use given NumberFormat for parsing text
|
||||
return NumberUtils.parseNumber(text, targetClass, this.numberFormat);
|
||||
} else {
|
||||
// use default valueOf methods for parsing text
|
||||
return NumberUtils.parseNumber(text, targetClass);
|
||||
}
|
||||
}
|
||||
|
||||
// convenience methods
|
||||
|
||||
public Byte parseByte(String formattedString) throws InvalidFormatException {
|
||||
return (Byte) parseValue(formattedString, Byte.class);
|
||||
}
|
||||
|
||||
public Short parseShort(String formattedString) throws InvalidFormatException {
|
||||
return (Short) parseValue(formattedString, Short.class);
|
||||
}
|
||||
|
||||
public Integer parseInteger(String formattedString) throws InvalidFormatException {
|
||||
return (Integer) parseValue(formattedString, Integer.class);
|
||||
}
|
||||
|
||||
public Long parseLong(String formattedString) throws InvalidFormatException {
|
||||
return (Long) parseValue(formattedString, Long.class);
|
||||
}
|
||||
|
||||
public Float parseFloat(String formattedString) throws InvalidFormatException {
|
||||
return (Float) parseValue(formattedString, Float.class);
|
||||
}
|
||||
|
||||
public Double parseDouble(String formattedString) throws InvalidFormatException {
|
||||
return (Double) parseValue(formattedString, Double.class);
|
||||
}
|
||||
|
||||
public BigInteger parseBigInteger(String formattedString) throws InvalidFormatException {
|
||||
return (BigInteger) parseValue(formattedString, BigInteger.class);
|
||||
}
|
||||
|
||||
public BigDecimal parseBigDecimal(String formattedString) throws InvalidFormatException {
|
||||
return (BigDecimal) parseValue(formattedString, BigDecimal.class);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2007 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.binding.format.support;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import org.springframework.binding.format.Formatter;
|
||||
import org.springframework.binding.format.Style;
|
||||
|
||||
/**
|
||||
* Simple FormatterFactory implementation.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class SimpleFormatterFactory extends AbstractFormatterFactory {
|
||||
|
||||
public Formatter getDateFormatter(Style style) {
|
||||
return new DateFormatter(SimpleDateFormat.getDateInstance(style.shortValue(), getLocale()));
|
||||
}
|
||||
|
||||
public Formatter getDateTimeFormatter(Style dateStyle, Style timeStyle) {
|
||||
return new DateFormatter(SimpleDateFormat.getDateTimeInstance(dateStyle.shortValue(), timeStyle.shortValue(),
|
||||
getLocale()));
|
||||
}
|
||||
|
||||
public Formatter getTimeFormatter(Style style) {
|
||||
return new DateFormatter(SimpleDateFormat.getTimeInstance(style.shortValue(), getLocale()));
|
||||
}
|
||||
|
||||
public Formatter getNumberFormatter(Class numberClass) {
|
||||
if (numberClass.equals(Integer.class) || numberClass.equals(int.class)) {
|
||||
return new NumberFormatter(NumberFormat.getIntegerInstance(getLocale()));
|
||||
} else {
|
||||
return new NumberFormatter(NumberFormat.getNumberInstance(getLocale()));
|
||||
}
|
||||
}
|
||||
|
||||
public Formatter getCurrencyFormatter() {
|
||||
return new NumberFormatter(NumberFormat.getCurrencyInstance(getLocale()));
|
||||
}
|
||||
|
||||
public Formatter getDateFormatter(String encodedFormat) {
|
||||
return new DateFormatter(new SimpleDateFormat(encodedFormat, getLocale()));
|
||||
}
|
||||
|
||||
public Formatter getPercentFormatter() {
|
||||
return new NumberFormatter(NumberFormat.getPercentInstance(getLocale()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user