diff --git a/spring-binding/src/main/java/org/springframework/binding/convert/support/AbstractFormattingConverter.java b/spring-binding/src/main/java/org/springframework/binding/convert/support/AbstractFormattingConverter.java index e2acfcac..700a5e0c 100644 --- a/spring-binding/src/main/java/org/springframework/binding/convert/support/AbstractFormattingConverter.java +++ b/spring-binding/src/main/java/org/springframework/binding/convert/support/AbstractFormattingConverter.java @@ -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); } } \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/convert/support/ConverterPropertyEditorAdapter.java b/spring-binding/src/main/java/org/springframework/binding/convert/support/ConverterPropertyEditorAdapter.java index 04f43e22..520e161a 100644 --- a/spring-binding/src/main/java/org/springframework/binding/convert/support/ConverterPropertyEditorAdapter.java +++ b/spring-binding/src/main/java/org/springframework/binding/convert/support/ConverterPropertyEditorAdapter.java @@ -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 */ diff --git a/spring-binding/src/main/java/org/springframework/binding/convert/support/DefaultConversionService.java b/spring-binding/src/main/java/org/springframework/binding/convert/support/DefaultConversionService.java index 8b995fde..82c24efe 100644 --- a/spring-binding/src/main/java/org/springframework/binding/convert/support/DefaultConversionService.java +++ b/spring-binding/src/main/java/org/springframework/binding/convert/support/DefaultConversionService.java @@ -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; + } } \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/convert/support/TextToDate.java b/spring-binding/src/main/java/org/springframework/binding/convert/support/TextToDate.java new file mode 100644 index 00000000..d422764c --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/convert/support/TextToDate.java @@ -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 Number 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 }; + } + +} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/convert/support/TextToNumber.java b/spring-binding/src/main/java/org/springframework/binding/convert/support/TextToNumber.java index cea3982a..55a162a4 100644 --- a/spring-binding/src/main/java/org/springframework/binding/convert/support/TextToNumber.java +++ b/spring-binding/src/main/java/org/springframework/binding/convert/support/TextToNumber.java @@ -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 Number 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); - } } \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/format/Formatter.java b/spring-binding/src/main/java/org/springframework/binding/format/Formatter.java index b77fa088..37285f52 100644 --- a/spring-binding/src/main/java/org/springframework/binding/format/Formatter.java +++ b/spring-binding/src/main/java/org/springframework/binding/format/Formatter.java @@ -17,7 +17,10 @@ package org.springframework.binding.format; /** * A lightweight interface for formatting a value and parsing a value from its formatted form. - * + *

+ * Note: formatters are typically not thread safe as Format objects aren't thread safe. In general, you + * should not attempt to share formatters between threads. + *

* @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; } \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/format/FormatterFactoryContext.java b/spring-binding/src/main/java/org/springframework/binding/format/FormatterFactoryContext.java new file mode 100644 index 00000000..6cc12e44 --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/format/FormatterFactoryContext.java @@ -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(); +} diff --git a/spring-binding/src/main/java/org/springframework/binding/format/FormatterRegistry.java b/spring-binding/src/main/java/org/springframework/binding/format/FormatterRegistry.java new file mode 100644 index 00000000..83aa31c5 --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/format/FormatterRegistry.java @@ -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 Formatters. + *

+ * Note: formatters are typically not thread safe as Format objects aren't thread safe. In general, you + * should not attempt to share formatters between threads. + *

+ * @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); + +} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/format/NoSuchFormatterException.java b/spring-binding/src/main/java/org/springframework/binding/format/NoSuchFormatterException.java new file mode 100644 index 00000000..7c5908be --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/format/NoSuchFormatterException.java @@ -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; + } + +} diff --git a/spring-binding/src/main/java/org/springframework/binding/format/Style.java b/spring-binding/src/main/java/org/springframework/binding/format/Style.java deleted file mode 100644 index 00e6294f..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/format/Style.java +++ /dev/null @@ -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); - } -} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/format/support/FormatterPropertyEditor.java b/spring-binding/src/main/java/org/springframework/binding/format/adapters/FormatterPropertyEditor.java similarity index 72% rename from spring-binding/src/main/java/org/springframework/binding/format/support/FormatterPropertyEditor.java rename to spring-binding/src/main/java/org/springframework/binding/format/adapters/FormatterPropertyEditor.java index d31f736f..569e6788 100644 --- a/spring-binding/src/main/java/org/springframework/binding/format/support/FormatterPropertyEditor.java +++ b/spring-binding/src/main/java/org/springframework/binding/format/adapters/FormatterPropertyEditor.java @@ -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)); } } \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/format/support/PropertyEditorFormatter.java b/spring-binding/src/main/java/org/springframework/binding/format/adapters/PropertyEditorFormatter.java similarity index 89% rename from spring-binding/src/main/java/org/springframework/binding/format/support/PropertyEditorFormatter.java rename to spring-binding/src/main/java/org/springframework/binding/format/adapters/PropertyEditorFormatter.java index 0be14d58..6cdd2996 100644 --- a/spring-binding/src/main/java/org/springframework/binding/format/support/PropertyEditorFormatter.java +++ b/spring-binding/src/main/java/org/springframework/binding/format/adapters/PropertyEditorFormatter.java @@ -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(); } diff --git a/spring-binding/src/main/java/org/springframework/binding/format/support/AbstractFormatter.java b/spring-binding/src/main/java/org/springframework/binding/format/factories/AbstractFormatter.java similarity index 84% rename from spring-binding/src/main/java/org/springframework/binding/format/support/AbstractFormatter.java rename to spring-binding/src/main/java/org/springframework/binding/format/factories/AbstractFormatter.java index 62cab78b..500c2ee0 100644 --- a/spring-binding/src/main/java/org/springframework/binding/format/support/AbstractFormatter.java +++ b/spring-binding/src/main/java/org/springframework/binding/format/factories/AbstractFormatter.java @@ -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; } diff --git a/spring-binding/src/main/java/org/springframework/binding/format/factories/DateFormatterFactory.java b/spring-binding/src/main/java/org/springframework/binding/format/factories/DateFormatterFactory.java new file mode 100644 index 00000000..f99eb921 --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/format/factories/DateFormatterFactory.java @@ -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); + } + + } + +} diff --git a/spring-binding/src/main/java/org/springframework/binding/format/factories/NumberFormatterFactory.java b/spring-binding/src/main/java/org/springframework/binding/format/factories/NumberFormatterFactory.java new file mode 100644 index 00000000..10785555 --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/format/factories/NumberFormatterFactory.java @@ -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); + } + } + } +} diff --git a/spring-binding/src/main/java/org/springframework/binding/format/impl/FormatterFactoryContextImpl.java b/spring-binding/src/main/java/org/springframework/binding/format/impl/FormatterFactoryContextImpl.java new file mode 100644 index 00000000..dcd3eeb6 --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/format/impl/FormatterFactoryContextImpl.java @@ -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; + } + +} diff --git a/spring-binding/src/main/java/org/springframework/binding/format/impl/FormatterRegistryImpl.java b/spring-binding/src/main/java/org/springframework/binding/format/impl/FormatterRegistryImpl.java new file mode 100644 index 00000000..4ab63328 --- /dev/null +++ b/spring-binding/src/main/java/org/springframework/binding/format/impl/FormatterRegistryImpl.java @@ -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); + } +} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/format/support/package.html b/spring-binding/src/main/java/org/springframework/binding/format/impl/package.html similarity index 100% rename from spring-binding/src/main/java/org/springframework/binding/format/support/package.html rename to spring-binding/src/main/java/org/springframework/binding/format/impl/package.html diff --git a/spring-binding/src/main/java/org/springframework/binding/format/support/AbstractFormatterFactory.java b/spring-binding/src/main/java/org/springframework/binding/format/support/AbstractFormatterFactory.java deleted file mode 100644 index 165e35fa..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/format/support/AbstractFormatterFactory.java +++ /dev/null @@ -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()); - } -} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/format/support/DateFormatter.java b/spring-binding/src/main/java/org/springframework/binding/format/support/DateFormatter.java deleted file mode 100644 index 646e16dd..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/format/support/DateFormatter.java +++ /dev/null @@ -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); - } -} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/format/support/LabeledEnumFormatter.java b/spring-binding/src/main/java/org/springframework/binding/format/support/LabeledEnumFormatter.java deleted file mode 100644 index 8df72740..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/format/support/LabeledEnumFormatter.java +++ /dev/null @@ -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 LabeledEnum 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); - } -} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/format/support/NumberFormatter.java b/spring-binding/src/main/java/org/springframework/binding/format/support/NumberFormatter.java deleted file mode 100644 index 2666ae62..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/format/support/NumberFormatter.java +++ /dev/null @@ -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 Number specializations to String 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); - } -} \ No newline at end of file diff --git a/spring-binding/src/main/java/org/springframework/binding/format/support/SimpleFormatterFactory.java b/spring-binding/src/main/java/org/springframework/binding/format/support/SimpleFormatterFactory.java deleted file mode 100644 index ae46ae8b..00000000 --- a/spring-binding/src/main/java/org/springframework/binding/format/support/SimpleFormatterFactory.java +++ /dev/null @@ -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())); - } -} \ No newline at end of file diff --git a/spring-binding/src/test/java/org/springframework/binding/convert/support/CompositeConversionServiceTests.java b/spring-binding/src/test/java/org/springframework/binding/convert/support/CompositeConversionServiceTests.java index 6b84c72c..6136f21e 100644 --- a/spring-binding/src/test/java/org/springframework/binding/convert/support/CompositeConversionServiceTests.java +++ b/spring-binding/src/test/java/org/springframework/binding/convert/support/CompositeConversionServiceTests.java @@ -38,7 +38,6 @@ public class CompositeConversionServiceTests extends TestCase { first.addConverter(new TextToBoolean("ja", "nee")); first.addDefaultAlias(Boolean.class); GenericConversionService second = new GenericConversionService(); - second.addConverter(new TextToNumber()); second.addConverter(new TextToBoolean()); second.addDefaultAlias(Integer.class); service = new CompositeConversionService(new ConversionService[] { first, second }); @@ -48,7 +47,6 @@ public class CompositeConversionServiceTests extends TestCase { assertNotNull(service.getConversionExecutor(String.class, Class.class)); assertNotNull(service.getConversionExecutor(String.class, Boolean.class)); assertEquals(Boolean.TRUE, service.getConversionExecutor(String.class, Boolean.class).execute("ja")); - assertNotNull(service.getConversionExecutor(String.class, Integer.class)); try { service.getConversionExecutor(String.class, Date.class); fail(); @@ -60,13 +58,11 @@ public class CompositeConversionServiceTests extends TestCase { public void testGetConversionExecutorByTargetAlias() { assertNotNull(service.getConversionExecutorByTargetAlias(String.class, "boolean")); assertEquals(Boolean.TRUE, service.getConversionExecutorByTargetAlias(String.class, "boolean").execute("ja")); - assertNotNull(service.getConversionExecutorByTargetAlias(String.class, "integer")); assertNull(service.getConversionExecutorByTargetAlias(String.class, "class")); } public void testGetConversionExecutorsForSource() { - assertEquals(new TextToClass().getTargetClasses().length + new TextToBoolean().getTargetClasses().length - + new TextToNumber().getTargetClasses().length, + assertEquals(new TextToClass().getTargetClasses().length + new TextToBoolean().getTargetClasses().length, service.getConversionExecutorsForSource(String.class).length); assertEquals(0, service.getConversionExecutorsForSource(Date.class).length); ConversionExecutor[] fromStringConversionExecutors = service.getConversionExecutorsForSource(String.class); @@ -81,7 +77,6 @@ public class CompositeConversionServiceTests extends TestCase { public void testGetClassByAlias() { assertEquals(Boolean.class, service.getClassByAlias("boolean")); - assertEquals(Integer.class, service.getClassByAlias("integer")); assertNull(service.getClassByAlias("class")); } } diff --git a/spring-binding/src/test/java/org/springframework/binding/convert/support/DefaultConversionServiceTests.java b/spring-binding/src/test/java/org/springframework/binding/convert/support/DefaultConversionServiceTests.java index 8687d31d..c96a2d0d 100644 --- a/spring-binding/src/test/java/org/springframework/binding/convert/support/DefaultConversionServiceTests.java +++ b/spring-binding/src/test/java/org/springframework/binding/convert/support/DefaultConversionServiceTests.java @@ -24,7 +24,6 @@ import junit.framework.TestCase; import org.springframework.binding.convert.ConversionException; import org.springframework.binding.convert.ConversionExecutor; import org.springframework.binding.convert.Converter; -import org.springframework.core.enums.ShortCodedLabeledEnum; /** * Test case for the default conversion service. @@ -86,31 +85,4 @@ public class DefaultConversionServiceTests extends TestCase { Integer three = (Integer) executor.execute("3"); assertEquals(3, three.intValue()); } - - public void testLabeledEnumConversionNoSuchEnum() { - DefaultConversionService service = new DefaultConversionService(); - ConversionExecutor executor = service.getConversionExecutor(String.class, MyEnum.class); - try { - executor.execute("My Invalid Label"); - fail("Should have failed"); - } catch (ConversionException e) { - } - } - - public void testValidLabeledEnumConversion() { - DefaultConversionService service = new DefaultConversionService(); - ConversionExecutor executor = service.getConversionExecutor(String.class, MyEnum.class); - MyEnum myEnum = (MyEnum) executor.execute("My Label 1"); - assertEquals(MyEnum.ONE, myEnum); - } - - public static class MyEnum extends ShortCodedLabeledEnum { - public static MyEnum ONE = new MyEnum(0, "My Label 1"); - - public static MyEnum TWO = new MyEnum(1, "My Label 2"); - - private MyEnum(int code, String label) { - super(code, label); - } - } } \ No newline at end of file diff --git a/spring-binding/src/test/java/org/springframework/binding/format/support/NumberFormatterTests.java b/spring-binding/src/test/java/org/springframework/binding/format/support/NumberFormatterTests.java deleted file mode 100644 index 51feb701..00000000 --- a/spring-binding/src/test/java/org/springframework/binding/format/support/NumberFormatterTests.java +++ /dev/null @@ -1,66 +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.util.Locale; - -import org.springframework.binding.format.Formatter; -import org.springframework.context.i18n.SimpleLocaleContext; - -import junit.framework.TestCase; - -/** - * Unit tests for {@link NumberFormatterTests}. - * - * @author Erwin Vervaet - */ -public class NumberFormatterTests extends TestCase { - - private Locale systemDefaultLocale; - - protected void setUp() throws Exception { - systemDefaultLocale = Locale.getDefault(); - } - - protected void tearDown() throws Exception { - // restore default - Locale.setDefault(systemDefaultLocale); - } - - public void testParseUsBigDecimalInUs() { - Locale.setDefault(Locale.US); - SimpleFormatterFactory formatterFactory = new SimpleFormatterFactory(); - Formatter formatter = formatterFactory.getNumberFormatter(BigDecimal.class); - assertEquals(new BigDecimal("123.45"), formatter.parseValue("123.45", BigDecimal.class)); - } - - public void testParseUsBigDecimalInGermany() { - Locale.setDefault(Locale.GERMANY); - SimpleFormatterFactory formatterFactory = new SimpleFormatterFactory(); - // we're expressing our numbers in US notation! - formatterFactory.setLocaleContext(new SimpleLocaleContext(Locale.US)); - Formatter formatter = formatterFactory.getNumberFormatter(BigDecimal.class); - assertEquals(new BigDecimal("123.45"), formatter.parseValue("123.45", BigDecimal.class)); - } - - public void testParseGermanBigDecimalInGermany() { - Locale.setDefault(Locale.GERMANY); - SimpleFormatterFactory formatterFactory = new SimpleFormatterFactory(); - Formatter formatter = formatterFactory.getNumberFormatter(BigDecimal.class); - assertEquals(new BigDecimal("123.45"), formatter.parseValue("123,45", BigDecimal.class)); - } -}