formatter simplifications from code review
This commit is contained in:
@@ -1,50 +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.convert.converters;
|
||||
|
||||
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 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 registry.
|
||||
*/
|
||||
private FormatterRegistry formatterRegistry;
|
||||
|
||||
/**
|
||||
* Creates a new converter that delegates to a formatter.
|
||||
* @param formatterRegistry the formatterRegistry to use
|
||||
*/
|
||||
protected AbstractFormattingConverter(FormatterRegistry formatterRegistry) {
|
||||
Assert.notNull(formatterRegistry, "The formatter registry is required");
|
||||
this.formatterRegistry = formatterRegistry;
|
||||
}
|
||||
|
||||
public FormatterRegistry getFormatterRegistry() {
|
||||
return formatterRegistry;
|
||||
}
|
||||
|
||||
protected Object doConvert(Object source, Class targetClass, Object context) throws Exception {
|
||||
return getFormatterRegistry().getFormatter(targetClass).parseValue((String) source);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +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.convert.converters;
|
||||
|
||||
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,7 +18,7 @@ package org.springframework.binding.convert.converters;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.springframework.binding.format.FormatterRegistry;
|
||||
import org.springframework.util.NumberUtils;
|
||||
|
||||
/**
|
||||
* Converts textual representations of numbers to a <code>Number</code> specialization. Delegates to a synchronized
|
||||
@@ -26,15 +26,7 @@ import org.springframework.binding.format.FormatterRegistry;
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class TextToNumber extends AbstractFormattingConverter {
|
||||
|
||||
/**
|
||||
* Create a string to number converter using given formatter factory.
|
||||
* @param formatterRegistry the formatter registry to use
|
||||
*/
|
||||
public TextToNumber(FormatterRegistry formatterRegistry) {
|
||||
super(formatterRegistry);
|
||||
}
|
||||
public class TextToNumber extends AbstractConverter {
|
||||
|
||||
public Class[] getSourceClasses() {
|
||||
return new Class[] { String.class };
|
||||
@@ -44,4 +36,9 @@ 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, Object context) throws Exception {
|
||||
return NumberUtils.parseNumber((String) source, targetClass);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,13 +18,8 @@ package org.springframework.binding.convert.service;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.converters.TextToBoolean;
|
||||
import org.springframework.binding.convert.converters.TextToClass;
|
||||
import org.springframework.binding.convert.converters.TextToDate;
|
||||
import org.springframework.binding.convert.converters.TextToLabeledEnum;
|
||||
import org.springframework.binding.convert.converters.TextToNumber;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Default, local implementation of a conversion service. Will automatically register <i>from string</i> converters for
|
||||
@@ -37,18 +32,12 @@ public class DefaultConversionService extends GenericConversionService {
|
||||
/**
|
||||
* A singleton shared instance. Should never be modified.
|
||||
*/
|
||||
private static final DefaultConversionService SHARED_INSTANCE = new DefaultConversionService();
|
||||
|
||||
/**
|
||||
* Returns the formatter registry used by this conversion service
|
||||
*/
|
||||
private FormatterRegistry formatterRegistry;
|
||||
private static DefaultConversionService SHARED_INSTANCE;
|
||||
|
||||
/**
|
||||
* Creates a new default conversion service, installing the default converters.
|
||||
*/
|
||||
public DefaultConversionService() {
|
||||
formatterRegistry = createDefaultFormatterRegistry();
|
||||
addDefaultConverters();
|
||||
}
|
||||
|
||||
@@ -59,21 +48,16 @@ public class DefaultConversionService extends GenericConversionService {
|
||||
addConverter(new TextToClass());
|
||||
addConverter(new TextToBoolean());
|
||||
addConverter(new TextToLabeledEnum());
|
||||
addConverter(new TextToNumber(formatterRegistry));
|
||||
addConverter(new TextToDate(formatterRegistry));
|
||||
}
|
||||
|
||||
protected FormatterRegistry createDefaultFormatterRegistry() {
|
||||
FormatterRegistryImpl registry = new FormatterRegistryImpl();
|
||||
registry.registerFormatter(new NumberFormatterFactory());
|
||||
registry.registerFormatter(new DateFormatterFactory());
|
||||
return registry;
|
||||
addConverter(new TextToNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shared {@link DefaultConversionService} instance.
|
||||
*/
|
||||
public static ConversionService getSharedInstance() {
|
||||
public synchronized static ConversionService getSharedInstance() {
|
||||
if (SHARED_INSTANCE == null) {
|
||||
SHARED_INSTANCE = new DefaultConversionService();
|
||||
}
|
||||
return SHARED_INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -16,29 +16,26 @@
|
||||
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>
|
||||
* Formats objects for display.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface Formatter {
|
||||
|
||||
/**
|
||||
* Format the value.
|
||||
* @param value the value to format
|
||||
* Format the object for display.
|
||||
* @param object the object to format
|
||||
* @return the formatted string, fit for display in a UI
|
||||
* @throws IllegalArgumentException the value could not be formatted
|
||||
* @throws IllegalArgumentException if the object could not be formatted
|
||||
*/
|
||||
public String formatValue(Object value) throws IllegalArgumentException;
|
||||
public String format(Object object) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Parse the formatted string representation of a value, restoring the value.
|
||||
* Parse the formatted string representation of an object and return the object.
|
||||
* @param formattedString the formatted string representation
|
||||
* @return the parsed value
|
||||
* @throws InvalidFormatException the string was in an invalid form
|
||||
* @return the parsed object
|
||||
* @throws InvalidFormatException the formatted string was in an invalid form
|
||||
*/
|
||||
public Object parseValue(String formattedString) throws InvalidFormatException;
|
||||
public Object parse(String formattedString) throws InvalidFormatException;
|
||||
|
||||
}
|
||||
@@ -1,39 +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;
|
||||
|
||||
/**
|
||||
* A factory for creating stateful formatter instances.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public interface FormatterFactory {
|
||||
|
||||
/**
|
||||
* The type of object the returned formatters are capable of formatting. This is the most general type supported,
|
||||
* some formatters may apply specific formatting rules to subclasses of this general type.
|
||||
* @return the formatted class
|
||||
*/
|
||||
public Class getFormattedClass();
|
||||
|
||||
/**
|
||||
* Create a new formatter.
|
||||
* @param context context for formatter creation
|
||||
* @return the new formatter
|
||||
*/
|
||||
public Formatter createFormatter(FormatterFactoryContext context);
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
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();
|
||||
}
|
||||
@@ -38,9 +38,8 @@ public interface FormatterRegistry {
|
||||
* 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);
|
||||
public Formatter getFormatter(String id);
|
||||
|
||||
}
|
||||
@@ -40,10 +40,10 @@ public class FormatterPropertyEditor extends PropertyEditorSupport {
|
||||
}
|
||||
|
||||
public String getAsText() {
|
||||
return formatter.formatValue(getValue());
|
||||
return formatter.format(getValue());
|
||||
}
|
||||
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
setValue(formatter.parseValue(text));
|
||||
setValue(formatter.parse(text));
|
||||
}
|
||||
}
|
||||
@@ -17,20 +17,19 @@ package org.springframework.binding.format.adapters;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
|
||||
import org.springframework.binding.format.factories.AbstractFormatter;
|
||||
import org.springframework.binding.format.Formatter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Adapts a property editor to the formatter interface.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class PropertyEditorFormatter extends AbstractFormatter {
|
||||
public class PropertyEditorFormatter implements Formatter {
|
||||
|
||||
private PropertyEditor propertyEditor;
|
||||
|
||||
/**
|
||||
* Wrap given property editor in a formatter.
|
||||
* Wrap the given property editor in a formatter.
|
||||
*/
|
||||
public PropertyEditorFormatter(PropertyEditor propertyEditor) {
|
||||
Assert.notNull(propertyEditor, "Property editor is required");
|
||||
@@ -44,18 +43,13 @@ public class PropertyEditorFormatter extends AbstractFormatter {
|
||||
return propertyEditor;
|
||||
}
|
||||
|
||||
protected String doFormatValue(Object value) {
|
||||
public String format(Object value) {
|
||||
propertyEditor.setValue(value);
|
||||
return propertyEditor.getAsText();
|
||||
}
|
||||
|
||||
protected Object doParseValue(String formattedValue) {
|
||||
public Object parse(String formattedValue) {
|
||||
propertyEditor.setAsText(formattedValue);
|
||||
return propertyEditor.getValue();
|
||||
}
|
||||
|
||||
protected String getExpectedFormat() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,104 +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.factories;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.springframework.binding.format.Formatter;
|
||||
import org.springframework.binding.format.InvalidFormatException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Abstract base class for all formatters.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public abstract class AbstractFormatter implements Formatter {
|
||||
|
||||
/**
|
||||
* Constructs a formatter.
|
||||
*/
|
||||
protected AbstractFormatter() {
|
||||
}
|
||||
|
||||
public final String formatValue(Object value) {
|
||||
if (isEmpty(value)) {
|
||||
return getEmptyFormattedValue();
|
||||
} else {
|
||||
return doFormatValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public final Object parseValue(String formattedString) throws InvalidFormatException {
|
||||
try {
|
||||
if (isEmpty(formattedString)) {
|
||||
return getEmptyValue();
|
||||
}
|
||||
return doParseValue(formattedString);
|
||||
} catch (ParseException ex) {
|
||||
throw new InvalidFormatException(formattedString, getExpectedFormat(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method subclasses should override to encapsulate formatting logic.
|
||||
* @param value the value to format
|
||||
* @return the formatted string representation
|
||||
*/
|
||||
protected abstract String doFormatValue(Object value);
|
||||
|
||||
/**
|
||||
* Returns the formatted form of an empty value. Default implementation just returns the empty string.
|
||||
*/
|
||||
protected String getEmptyFormattedValue() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method subclasses should override to encapsulate parsing logic.
|
||||
* @param formattedString the formatted string to parse
|
||||
* @return the parsed value
|
||||
* @throws InvalidFormatException an exception occurred parsing
|
||||
* @throws ParseException when parse exceptions occur
|
||||
*/
|
||||
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
|
||||
* null.
|
||||
*/
|
||||
protected Object getEmptyValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected string format for the given target class.
|
||||
*/
|
||||
protected abstract String getExpectedFormat();
|
||||
|
||||
/**
|
||||
* Is given object <i>empty</i> (null or empty string)?
|
||||
*/
|
||||
protected boolean isEmpty(Object o) {
|
||||
if (o == null) {
|
||||
return true;
|
||||
} else if (o instanceof String) {
|
||||
return !StringUtils.hasText((String) o);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package org.springframework.binding.format.factories;
|
||||
|
||||
import org.springframework.binding.format.Formatter;
|
||||
import org.springframework.binding.format.FormatterFactory;
|
||||
import org.springframework.binding.format.FormatterFactoryContext;
|
||||
import org.springframework.binding.format.InvalidFormatException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class BooleanFormatterFactory implements FormatterFactory {
|
||||
|
||||
public Class getFormattedClass() {
|
||||
return Boolean.class;
|
||||
}
|
||||
|
||||
public Formatter createFormatter(FormatterFactoryContext context) {
|
||||
return new BooleanFormatter();
|
||||
}
|
||||
|
||||
public static class BooleanFormatter implements Formatter {
|
||||
|
||||
public String formatValue(Object value) throws IllegalArgumentException {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
if (Boolean.TRUE.equals(value)) {
|
||||
return "true";
|
||||
} else if (Boolean.FALSE.equals(value)) {
|
||||
return "false";
|
||||
} else {
|
||||
throw new IllegalArgumentException("Must be a Boolean " + value);
|
||||
}
|
||||
}
|
||||
|
||||
public Object parseValue(String formattedString) throws InvalidFormatException {
|
||||
formattedString = (formattedString != null ? formattedString.trim() : null);
|
||||
if (!StringUtils.hasText(formattedString)) {
|
||||
return null;
|
||||
}
|
||||
if (formattedString.equals("true")) {
|
||||
return Boolean.TRUE;
|
||||
} else if (formattedString.equals("false")) {
|
||||
return Boolean.FALSE;
|
||||
} else {
|
||||
throw new InvalidFormatException(formattedString, "true | false");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
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;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
||||
public static 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);
|
||||
}
|
||||
|
||||
protected String getExpectedFormat() {
|
||||
return dateFormat.toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("format", dateFormat).toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
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.core.style.ToStringCreator;
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
public static 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);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getExpectedFormat() {
|
||||
return numberFormat.toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("format", numberFormat).append("targetClass", targetClass)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.formatters;
|
||||
|
||||
import org.springframework.binding.format.Formatter;
|
||||
import org.springframework.binding.format.InvalidFormatException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class BooleanFormatter implements Formatter {
|
||||
|
||||
public String format(Object value) throws IllegalArgumentException {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
if (Boolean.TRUE.equals(value)) {
|
||||
return "true";
|
||||
} else if (Boolean.FALSE.equals(value)) {
|
||||
return "false";
|
||||
} else {
|
||||
throw new IllegalArgumentException("Must be a Boolean " + value);
|
||||
}
|
||||
}
|
||||
|
||||
public Object parse(String formattedString) throws InvalidFormatException {
|
||||
formattedString = (formattedString != null ? formattedString.trim() : null);
|
||||
if (!StringUtils.hasText(formattedString)) {
|
||||
return null;
|
||||
}
|
||||
if (formattedString.equals("true")) {
|
||||
return Boolean.TRUE;
|
||||
} else if (formattedString.equals("false")) {
|
||||
return Boolean.FALSE;
|
||||
} else {
|
||||
throw new InvalidFormatException(formattedString, "true | false");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.formatters;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.binding.format.Formatter;
|
||||
import org.springframework.binding.format.InvalidFormatException;
|
||||
|
||||
public class DateFormatter implements Formatter {
|
||||
|
||||
private String pattern;
|
||||
|
||||
private Locale locale;
|
||||
|
||||
public String getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
public void setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
public void setLocale(Locale locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
public String format(Object date) {
|
||||
return getDateFormat().format((Date) date);
|
||||
}
|
||||
|
||||
public Object parse(String formattedString) throws InvalidFormatException {
|
||||
DateFormat dateFormat = getDateFormat();
|
||||
try {
|
||||
return dateFormat.parse(formattedString);
|
||||
} catch (ParseException e) {
|
||||
throw new InvalidFormatException(formattedString, dateFormat.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected DateFormat getDateFormat() {
|
||||
if (pattern != null) {
|
||||
return new SimpleDateFormat(pattern, locale);
|
||||
} else {
|
||||
return DateFormat.getDateInstance();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.formatters;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import org.springframework.binding.format.Formatter;
|
||||
import org.springframework.binding.format.InvalidFormatException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.NumberUtils;
|
||||
|
||||
public class NumberFormatter implements Formatter {
|
||||
|
||||
private String pattern;
|
||||
|
||||
private Class numberClass;
|
||||
|
||||
public NumberFormatter(Class numberClass) {
|
||||
Assert.notNull(numberClass, "The number class is required");
|
||||
this.numberClass = numberClass;
|
||||
}
|
||||
|
||||
public void setPattern(String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
public String format(Object number) {
|
||||
if (pattern != null) {
|
||||
return getNumberFormat().format(number);
|
||||
} else {
|
||||
return number.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public Object parse(String text) throws InvalidFormatException {
|
||||
if (pattern != null) {
|
||||
return NumberUtils.parseNumber(text, numberClass, getNumberFormat());
|
||||
} else {
|
||||
return NumberUtils.parseNumber(text, numberClass);
|
||||
}
|
||||
}
|
||||
|
||||
private NumberFormat getNumberFormat() {
|
||||
return new DecimalFormat(pattern);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
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,46 @@
|
||||
package org.springframework.binding.format.registry;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.binding.format.FormatterRegistry;
|
||||
import org.springframework.binding.format.formatters.BooleanFormatter;
|
||||
import org.springframework.binding.format.formatters.DateFormatter;
|
||||
import org.springframework.binding.format.formatters.NumberFormatter;
|
||||
|
||||
public class DefaultFormatterRegistry extends FormatterRegistryImpl {
|
||||
|
||||
/**
|
||||
* A singleton shared instance. Should never be modified.
|
||||
*/
|
||||
private static DefaultFormatterRegistry SHARED_INSTANCE;
|
||||
|
||||
public DefaultFormatterRegistry() {
|
||||
registerDefaultFormatters();
|
||||
}
|
||||
|
||||
protected void registerDefaultFormatters() {
|
||||
registerFormatter(Integer.class, new NumberFormatter(Integer.class));
|
||||
registerFormatter(Long.class, new NumberFormatter(Long.class));
|
||||
registerFormatter(Short.class, new NumberFormatter(Short.class));
|
||||
registerFormatter(Float.class, new NumberFormatter(Float.class));
|
||||
registerFormatter(Double.class, new NumberFormatter(Double.class));
|
||||
registerFormatter(Byte.class, new NumberFormatter(Byte.class));
|
||||
registerFormatter(BigInteger.class, new NumberFormatter(BigInteger.class));
|
||||
registerFormatter(BigDecimal.class, new NumberFormatter(BigDecimal.class));
|
||||
registerFormatter(Boolean.class, new BooleanFormatter());
|
||||
registerFormatter(Date.class, new DateFormatter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shared {@link DefaultConversionService} instance.
|
||||
*/
|
||||
public synchronized static FormatterRegistry getSharedInstance() {
|
||||
if (SHARED_INSTANCE == null) {
|
||||
SHARED_INSTANCE = new DefaultFormatterRegistry();
|
||||
}
|
||||
return SHARED_INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -13,19 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.binding.format.impl;
|
||||
package org.springframework.binding.format.registry;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
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.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.context.i18n.SimpleLocaleContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -36,81 +31,42 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
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) {
|
||||
Assert.notNull(clazz, "The formatted class argument is required");
|
||||
clazz = convertToWrapperClassIfNecessary(clazz);
|
||||
FormatterFactory factory = findFormatterFactory(clazz);
|
||||
if (factory != null) {
|
||||
FormatterFactoryContextImpl context = new FormatterFactoryContextImpl();
|
||||
context.setLocale(getLocale());
|
||||
context.setFormattedClass(clazz);
|
||||
return factory.createFormatter(context);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return findFormatter(clazz);
|
||||
}
|
||||
|
||||
public Formatter getFormatter(String id, Class clazz) {
|
||||
public Formatter getFormatter(String id) {
|
||||
Assert.hasText(id, "The id of the custom formatter is required");
|
||||
FormatterFactory factory = (FormatterFactory) formattersById.get(id);
|
||||
if (factory != null) {
|
||||
FormatterFactoryContextImpl context = new FormatterFactoryContextImpl();
|
||||
context.setLocale(getLocale());
|
||||
context.setFormattedClass(clazz);
|
||||
return factory.createFormatter(context);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return (Formatter) formattersById.get(id);
|
||||
}
|
||||
|
||||
public void registerFormatter(String id, FormatterFactory factory) {
|
||||
// impl
|
||||
|
||||
public void registerFormatter(Class clazz, Formatter formatter) {
|
||||
Assert.notNull(formatter, "The formatter to register is required");
|
||||
formattersByClass.put(clazz, formatter);
|
||||
}
|
||||
|
||||
public void registerFormatter(String id, Formatter formatter) {
|
||||
Assert.hasText(id, "The id of the custom formatter is required");
|
||||
Assert.notNull(factory, "The formatter factory is required");
|
||||
formattersById.put(id, factory);
|
||||
Class formattedClass = factory.getFormattedClass();
|
||||
if (!formattersByClass.containsKey(formattedClass)) {
|
||||
formattersByClass.put(formattedClass, factory);
|
||||
}
|
||||
Assert.notNull(formatter, "The formatter to register is required");
|
||||
formattersById.put(id, formatter);
|
||||
}
|
||||
|
||||
public void registerFormatter(FormatterFactory factory) {
|
||||
Assert.notNull(factory, "The formatter factory is required");
|
||||
formattersByClass.put(factory.getFormattedClass(), factory);
|
||||
}
|
||||
// helpers
|
||||
|
||||
private FormatterFactory findFormatterFactory(Class clazz) {
|
||||
private Formatter findFormatter(Class clazz) {
|
||||
LinkedList classQueue = new LinkedList();
|
||||
classQueue.addFirst(clazz);
|
||||
while (!classQueue.isEmpty()) {
|
||||
clazz = (Class) classQueue.removeLast();
|
||||
FormatterFactory factory = (FormatterFactory) formattersByClass.get(clazz);
|
||||
Formatter factory = (Formatter) formattersByClass.get(clazz);
|
||||
if (factory != null) {
|
||||
return factory;
|
||||
}
|
||||
Reference in New Issue
Block a user