formatter simplifications from code review

This commit is contained in:
Keith Donald
2008-03-26 03:47:54 +00:00
parent 0965f93c97
commit b1b7de9a30
28 changed files with 325 additions and 715 deletions

View File

@@ -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);
}
}

View File

@@ -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 };
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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");
}
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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");
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}