25 changed files with 1227 additions and 0 deletions
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
|
||||
/** |
||||
* A factory that creates {@link Formatter formatters} to format property values on properties annotated with a particular format {@link Annotation}. |
||||
* For example, a <code>CurrencyAnnotationFormatterFactory</code> might create a <code>Formatter</code> that formats a <code>BigDecimal</code> value set on a property annotated with <code>@CurrencyFormat</code>. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
* @param <A> The type of Annotation this factory uses to create Formatter instances |
||||
* @param <T> The type of Object Formatters created by this factory format |
||||
*/ |
||||
public interface AnnotationFormatterFactory<A extends Annotation, T> { |
||||
|
||||
/** |
||||
* Get the Formatter that will format the value of the property annotated with the provided annotation. |
||||
* The annotation instance can contain properties that may be used to configure the Formatter that is returned. |
||||
* @param annotation the annotation instance |
||||
* @return the Formatter to use to format values of properties annotated with the annotation. |
||||
*/ |
||||
Formatter<T> getFormatter(A annotation); |
||||
} |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
/** |
||||
* A type that can be formatted as a String for display in a UI. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
*/ |
||||
@Target({ElementType.TYPE}) |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Documented |
||||
public @interface Formatted { |
||||
|
||||
/** |
||||
* The Formatter that handles the formatting. |
||||
*/ |
||||
Class<?> value(); |
||||
} |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format; |
||||
|
||||
import java.text.ParseException; |
||||
import java.util.Locale; |
||||
|
||||
/** |
||||
* Formats objects of type T for display. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
* @param <T> the type of object this formatter can format |
||||
*/ |
||||
public interface Formatter<T> { |
||||
|
||||
/** |
||||
* Format the object of type T for display. |
||||
* @param object the object to format |
||||
* @param locale the user's locale |
||||
* @return the formatted display string |
||||
*/ |
||||
String format(T object, Locale locale); |
||||
|
||||
/** |
||||
* Parse an object from its formatted representation. |
||||
* @param formatted a formatted representation |
||||
* @param locale the user's locale |
||||
* @return the parsed object |
||||
* @throws ParseException when a parse exception occurs |
||||
*/ |
||||
T parse(String formatted, Locale locale) throws ParseException; |
||||
} |
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
|
||||
import org.springframework.core.convert.TypeDescriptor; |
||||
|
||||
/** |
||||
* A shared registry of Formatters. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
*/ |
||||
public interface FormatterRegistry { |
||||
|
||||
/** |
||||
* Adds a Formatter to this registry indexed by <T>. |
||||
* Calling getFormatter(<T>.class) returns <code>formatter</code>. |
||||
* @param formatter the formatter |
||||
* @param <T> the type of object the formatter formats |
||||
*/ |
||||
<T> void add(Formatter<T> formatter); |
||||
|
||||
/** |
||||
* Adds a Formatter to this registry indexed by objectType. |
||||
* Use this add method when objectType differs from <T>. |
||||
* Calling getFormatter(objectType) returns a decorator that wraps the targetFormatter. |
||||
* On format, the decorator first coerses the instance of objectType to <T>, then delegates to <code>targetFormatter</code> to format the value. |
||||
* On parse, the decorator first delegates to the formatter to parse a <T>, then coerses the parsed value to objectType. |
||||
* @param objectType the object type |
||||
* @param targetFormatter the target formatter |
||||
* @param <T> the type of object the target formatter formats |
||||
*/ |
||||
<T> void add(Class<?> objectType, Formatter<T> targetFormatter); |
||||
|
||||
/** |
||||
* Adds a AnnotationFormatterFactory that will format values of properties annotated with a specific annotation. |
||||
* @param factory the annotation formatter factory |
||||
*/ |
||||
<A extends Annotation, T> void add(AnnotationFormatterFactory<A, T> factory); |
||||
|
||||
/** |
||||
* Get the Formatter for the type. |
||||
* @return the Formatter, or <code>null</code> if none is registered |
||||
*/ |
||||
Formatter getFormatter(TypeDescriptor type); |
||||
|
||||
} |
@ -0,0 +1,145 @@
@@ -0,0 +1,145 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format; |
||||
|
||||
import java.lang.annotation.Annotation; |
||||
import java.lang.reflect.ParameterizedType; |
||||
import java.lang.reflect.Type; |
||||
import java.lang.reflect.TypeVariable; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
import org.springframework.core.GenericTypeResolver; |
||||
import org.springframework.core.annotation.AnnotationUtils; |
||||
import org.springframework.core.convert.TypeDescriptor; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* A generic implementation of {@link FormatterRegistry} suitable for use in most binding environments. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
* @see #add(Class, Formatter) |
||||
* @see #add(AnnotationFormatterFactory) |
||||
*/ |
||||
@SuppressWarnings("unchecked") |
||||
public class GenericFormatterRegistry implements FormatterRegistry { |
||||
|
||||
private Map<Class, Formatter> typeFormatters = new ConcurrentHashMap<Class, Formatter>(); |
||||
|
||||
private Map<Class, AnnotationFormatterFactory> annotationFormatters = new HashMap<Class, AnnotationFormatterFactory>(); |
||||
|
||||
public <T> void add(Formatter<T> formatter) { |
||||
// TODO
|
||||
} |
||||
|
||||
public <T> void add(Class<?> objectType, Formatter<T> formatter) { |
||||
if (objectType.isAnnotation()) { |
||||
annotationFormatters.put(objectType, new SimpleAnnotationFormatterFactory(formatter)); |
||||
} else { |
||||
typeFormatters.put(objectType, formatter); |
||||
} |
||||
} |
||||
|
||||
public <A extends Annotation, T> void add(AnnotationFormatterFactory<A, T> factory) { |
||||
annotationFormatters.put(getAnnotationType(factory), factory); |
||||
} |
||||
|
||||
public Formatter<?> getFormatter(TypeDescriptor type) { |
||||
Assert.notNull(type, "The TypeDescriptor is required"); |
||||
Annotation[] annotations = type.getAnnotations(); |
||||
for (Annotation a : annotations) { |
||||
AnnotationFormatterFactory factory = annotationFormatters.get(a.annotationType()); |
||||
if (factory != null) { |
||||
return factory.getFormatter(a); |
||||
} |
||||
} |
||||
return getFormatter(type.getType()); |
||||
} |
||||
|
||||
// internal helpers
|
||||
|
||||
private Formatter<?> getFormatter(Class<?> type) { |
||||
Assert.notNull(type, "The Class of the object to format is required"); |
||||
Formatter formatter = typeFormatters.get(type); |
||||
if (formatter != null) { |
||||
return formatter; |
||||
} else { |
||||
Formatted formatted = AnnotationUtils.findAnnotation(type, Formatted.class); |
||||
if (formatted != null) { |
||||
Class formatterClass = formatted.value(); |
||||
try { |
||||
formatter = (Formatter) formatterClass.newInstance(); |
||||
} catch (InstantiationException e) { |
||||
throw new IllegalStateException( |
||||
"Formatter referenced by @Formatted annotation does not have default constructor", e); |
||||
} catch (IllegalAccessException e) { |
||||
throw new IllegalStateException( |
||||
"Formatter referenced by @Formatted annotation does not have public constructor", e); |
||||
} |
||||
typeFormatters.put(type, formatter); |
||||
return formatter; |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
private Class getAnnotationType(AnnotationFormatterFactory factory) { |
||||
Class classToIntrospect = factory.getClass(); |
||||
while (classToIntrospect != null) { |
||||
Type[] genericInterfaces = classToIntrospect.getGenericInterfaces(); |
||||
for (Type genericInterface : genericInterfaces) { |
||||
if (genericInterface instanceof ParameterizedType) { |
||||
ParameterizedType pInterface = (ParameterizedType) genericInterface; |
||||
if (AnnotationFormatterFactory.class.isAssignableFrom((Class) pInterface.getRawType())) { |
||||
return getParameterClass(pInterface.getActualTypeArguments()[0], factory.getClass()); |
||||
} |
||||
} |
||||
} |
||||
classToIntrospect = classToIntrospect.getSuperclass(); |
||||
} |
||||
throw new IllegalArgumentException( |
||||
"Unable to extract Annotation type A argument from AnnotationFormatterFactory [" |
||||
+ factory.getClass().getName() + "]; does the factory parameterize the <A> generic type?"); |
||||
} |
||||
|
||||
private Class getParameterClass(Type parameterType, Class converterClass) { |
||||
if (parameterType instanceof TypeVariable) { |
||||
parameterType = GenericTypeResolver.resolveTypeVariable((TypeVariable) parameterType, converterClass); |
||||
} |
||||
if (parameterType instanceof Class) { |
||||
return (Class) parameterType; |
||||
} |
||||
throw new IllegalArgumentException("Unable to obtain the java.lang.Class for parameterType [" + parameterType |
||||
+ "] on Formatter [" + converterClass.getName() + "]"); |
||||
} |
||||
|
||||
private static class SimpleAnnotationFormatterFactory implements AnnotationFormatterFactory { |
||||
|
||||
private Formatter formatter; |
||||
|
||||
public SimpleAnnotationFormatterFactory(Formatter formatter) { |
||||
this.formatter = formatter; |
||||
} |
||||
|
||||
public Formatter getFormatter(Annotation annotation) { |
||||
return formatter; |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format.date; |
||||
|
||||
import java.text.DateFormat; |
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.Date; |
||||
import java.util.Locale; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.ui.format.Formatter; |
||||
|
||||
/** |
||||
* A formatter for {@link Date} types. |
||||
* Allows the configuration of an explicit date pattern and locale. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
* @see SimpleDateFormat |
||||
*/ |
||||
public class DateFormatter implements Formatter<Date> { |
||||
|
||||
private static Log logger = LogFactory.getLog(DateFormatter.class); |
||||
|
||||
/** |
||||
* The default date pattern. |
||||
*/ |
||||
private static final String DEFAULT_PATTERN = "yyyy-MM-dd"; |
||||
|
||||
private String pattern; |
||||
|
||||
/** |
||||
* Sets the pattern to use to format date values. |
||||
* If not specified, the default pattern 'yyyy-MM-dd' is used. |
||||
* @param pattern the date formatting pattern |
||||
*/ |
||||
public void setPattern(String pattern) { |
||||
this.pattern = pattern; |
||||
} |
||||
|
||||
public String format(Date date, Locale locale) { |
||||
if (date == null) { |
||||
return ""; |
||||
} |
||||
return getDateFormat(locale).format(date); |
||||
} |
||||
|
||||
public Date parse(String formatted, Locale locale) throws ParseException { |
||||
if (formatted.length() == 0) { |
||||
return null; |
||||
} |
||||
return getDateFormat(locale).parse(formatted); |
||||
} |
||||
|
||||
// subclassing hookings
|
||||
|
||||
protected DateFormat getDateFormat(Locale locale) { |
||||
DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT, locale); |
||||
format.setLenient(false); |
||||
if (format instanceof SimpleDateFormat) { |
||||
String pattern = determinePattern(this.pattern); |
||||
((SimpleDateFormat) format).applyPattern(pattern); |
||||
} else { |
||||
logger.warn("Unable to apply format pattern '" + pattern |
||||
+ "'; Returned DateFormat is not a SimpleDateFormat"); |
||||
} |
||||
return format; |
||||
} |
||||
|
||||
// internal helpers
|
||||
|
||||
private String determinePattern(String pattern) { |
||||
return pattern != null ? pattern : DEFAULT_PATTERN; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
/** |
||||
* Formatters for <code>java.util.Date</code> fields. |
||||
*/ |
||||
package org.springframework.ui.format.date; |
||||
|
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format.number; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
/** |
||||
* A annotation to apply to a BigDecimal property to have its value formatted as currency amount using a {@link CurrencyFormatter}. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
*/ |
||||
@Target( { ElementType.METHOD, ElementType.FIELD }) |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Documented |
||||
public @interface CurrencyFormat { |
||||
|
||||
} |
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format.number; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.math.RoundingMode; |
||||
import java.text.NumberFormat; |
||||
import java.text.ParseException; |
||||
import java.text.ParsePosition; |
||||
import java.util.Locale; |
||||
|
||||
import org.springframework.ui.format.Formatter; |
||||
|
||||
/** |
||||
* A BigDecimal formatter for currency values. |
||||
* Delegates to {@link NumberFormat#getCurrencyInstance(Locale)}. |
||||
* Configures BigDecimal parsing so there is no loss of precision. |
||||
* Sets the scale of parsed BigDecimal values to {@link NumberFormat#getMaximumFractionDigits()}. |
||||
* Applies {@link RoundingMode#DOWN} to parsed values. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
*/ |
||||
public class CurrencyFormatter implements Formatter<BigDecimal> { |
||||
|
||||
private CurrencyNumberFormatFactory currencyFormatFactory = new CurrencyNumberFormatFactory(); |
||||
|
||||
private boolean lenient; |
||||
|
||||
public String format(BigDecimal decimal, Locale locale) { |
||||
if (decimal == null) { |
||||
return ""; |
||||
} |
||||
NumberFormat format = currencyFormatFactory.getNumberFormat(locale); |
||||
return format.format(decimal); |
||||
} |
||||
|
||||
public BigDecimal parse(String formatted, Locale locale) |
||||
throws ParseException { |
||||
if (formatted.length() == 0) { |
||||
return null; |
||||
} |
||||
NumberFormat format = currencyFormatFactory.getNumberFormat(locale); |
||||
ParsePosition position = new ParsePosition(0); |
||||
BigDecimal decimal = (BigDecimal) format.parse(formatted, position); |
||||
if (position.getErrorIndex() != -1) { |
||||
throw new ParseException(formatted, position.getIndex()); |
||||
} |
||||
if (!lenient) { |
||||
if (formatted.length() != position.getIndex()) { |
||||
// indicates a part of the string that was not parsed
|
||||
throw new ParseException(formatted, position.getIndex()); |
||||
} |
||||
} |
||||
decimal = decimal.setScale(format.getMaximumFractionDigits(), format.getRoundingMode()); |
||||
return decimal; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format.number; |
||||
|
||||
import java.math.RoundingMode; |
||||
import java.text.DecimalFormat; |
||||
import java.text.NumberFormat; |
||||
import java.util.Locale; |
||||
|
||||
/** |
||||
* Produces NumberFormat instances that format currency values. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
* @see NumberFormat |
||||
*/ |
||||
final class CurrencyNumberFormatFactory extends NumberFormatFactory { |
||||
|
||||
private RoundingMode roundingMode = RoundingMode.DOWN; |
||||
|
||||
public NumberFormat getNumberFormat(Locale locale) { |
||||
DecimalFormat format = (DecimalFormat) NumberFormat.getCurrencyInstance(locale); |
||||
format.setParseBigDecimal(true); |
||||
format.setRoundingMode(roundingMode); |
||||
return format; |
||||
} |
||||
} |
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format.number; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.text.NumberFormat; |
||||
import java.text.ParseException; |
||||
import java.text.ParsePosition; |
||||
import java.util.Locale; |
||||
|
||||
import org.springframework.ui.format.Formatter; |
||||
|
||||
/** |
||||
* A BigDecimal formatter for decimal values. |
||||
* Delegates to {@link NumberFormat#getInstance(Locale)}. |
||||
* Configures BigDecimal parsing so there is no loss in precision. |
||||
* Allows configuration over the decimal number pattern; see {@link #DecimalFormatter(String)}. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
*/ |
||||
public class DecimalFormatter implements Formatter<BigDecimal> { |
||||
|
||||
private DefaultNumberFormatFactory formatFactory = new DefaultNumberFormatFactory(); |
||||
|
||||
private boolean lenient; |
||||
|
||||
public DecimalFormatter() { |
||||
initDefaults(); |
||||
} |
||||
|
||||
public DecimalFormatter(String pattern) { |
||||
initDefaults(); |
||||
formatFactory.setPattern(pattern); |
||||
} |
||||
|
||||
public String format(BigDecimal decimal, Locale locale) { |
||||
if (decimal == null) { |
||||
return ""; |
||||
} |
||||
NumberFormat format = formatFactory.getNumberFormat(locale); |
||||
return format.format(decimal); |
||||
} |
||||
|
||||
public BigDecimal parse(String formatted, Locale locale) |
||||
throws ParseException { |
||||
if (formatted.length() == 0) { |
||||
return null; |
||||
} |
||||
NumberFormat format = formatFactory.getNumberFormat(locale); |
||||
ParsePosition position = new ParsePosition(0); |
||||
BigDecimal decimal = (BigDecimal) format.parse(formatted, position); |
||||
if (position.getErrorIndex() != -1) { |
||||
throw new ParseException(formatted, position.getIndex()); |
||||
} |
||||
if (!lenient) { |
||||
if (formatted.length() != position.getIndex()) { |
||||
// indicates a part of the string that was not parsed
|
||||
throw new ParseException(formatted, position.getIndex()); |
||||
} |
||||
} |
||||
return decimal; |
||||
} |
||||
|
||||
private void initDefaults() { |
||||
formatFactory.setParseBigDecimal(true); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,80 @@
@@ -0,0 +1,80 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format.number; |
||||
|
||||
import java.text.DecimalFormat; |
||||
import java.text.NumberFormat; |
||||
import java.util.Locale; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
/** |
||||
* Works with a general purpose {@link DecimalFormat} instance returned by calling |
||||
* {@link NumberFormat#getInstance(Locale)} by default. |
||||
* @author Keith Donald |
||||
* @see NumberFormat |
||||
* @see DecimalFormat |
||||
* @since 3.0 |
||||
*/ |
||||
class DefaultNumberFormatFactory extends NumberFormatFactory { |
||||
|
||||
private static Log logger = LogFactory.getLog(DefaultNumberFormatFactory.class); |
||||
|
||||
private String pattern; |
||||
|
||||
private Boolean parseBigDecimal; |
||||
|
||||
/** |
||||
* Sets the pattern to use to format number values. |
||||
* If not specified, the default DecimalFormat pattern is used. |
||||
* @param pattern the format pattern |
||||
* @see DecimalFormat#applyPattern(String) |
||||
*/ |
||||
public void setPattern(String pattern) { |
||||
this.pattern = pattern; |
||||
} |
||||
|
||||
/** |
||||
* Sets whether the format should always parse a big decimal. |
||||
* @param parseBigDecimal the big decimal parse status |
||||
* @see DecimalFormat#setParseBigDecimal(boolean) |
||||
*/ |
||||
public void setParseBigDecimal(boolean parseBigDecimal) { |
||||
this.parseBigDecimal = parseBigDecimal; |
||||
} |
||||
|
||||
public NumberFormat getNumberFormat(Locale locale) { |
||||
NumberFormat format = NumberFormat.getInstance(locale); |
||||
if (pattern != null) { |
||||
if (format instanceof DecimalFormat) { |
||||
((DecimalFormat) format).applyPattern(pattern); |
||||
} else { |
||||
logger.warn("Unable to apply format pattern '" + pattern |
||||
+ "'; Returned NumberFormat is not a DecimalFormat"); |
||||
} |
||||
} |
||||
if (parseBigDecimal != null) { |
||||
if (format instanceof DecimalFormat) { |
||||
((DecimalFormat) format).setParseBigDecimal(parseBigDecimal); |
||||
} else { |
||||
logger.warn("Unable to call setParseBigDecimal; not a DecimalFormat"); |
||||
} |
||||
} |
||||
return format; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,65 @@
@@ -0,0 +1,65 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format.number; |
||||
|
||||
import java.text.NumberFormat; |
||||
import java.text.ParseException; |
||||
import java.text.ParsePosition; |
||||
import java.util.Locale; |
||||
|
||||
import org.springframework.ui.format.Formatter; |
||||
|
||||
/** |
||||
* A Long formatter for whole integer values. |
||||
* Delegates to {@link NumberFormat#getIntegerInstance(Locale)}. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
*/ |
||||
public class IntegerFormatter implements Formatter<Long> { |
||||
|
||||
private IntegerNumberFormatFactory formatFactory = new IntegerNumberFormatFactory(); |
||||
|
||||
private boolean lenient; |
||||
|
||||
public String format(Long integer, Locale locale) { |
||||
if (integer == null) { |
||||
return ""; |
||||
} |
||||
NumberFormat format = formatFactory.getNumberFormat(locale); |
||||
return format.format(integer); |
||||
} |
||||
|
||||
public Long parse(String formatted, Locale locale) |
||||
throws ParseException { |
||||
if (formatted.length() == 0) { |
||||
return null; |
||||
} |
||||
NumberFormat format = formatFactory.getNumberFormat(locale); |
||||
ParsePosition position = new ParsePosition(0); |
||||
Long integer = (Long) format.parse(formatted, position); |
||||
if (position.getErrorIndex() != -1) { |
||||
throw new ParseException(formatted, position.getIndex()); |
||||
} |
||||
if (!lenient) { |
||||
if (formatted.length() != position.getIndex()) { |
||||
// indicates a part of the string that was not parsed
|
||||
throw new ParseException(formatted, position.getIndex()); |
||||
} |
||||
} |
||||
return integer; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format.number; |
||||
|
||||
import java.text.NumberFormat; |
||||
import java.util.Locale; |
||||
|
||||
/** |
||||
* Produces NumberFormat instances that format integer values. |
||||
* @author Keith Donald |
||||
* @see NumberFormat |
||||
* @since 3.0 |
||||
*/ |
||||
final class IntegerNumberFormatFactory extends NumberFormatFactory { |
||||
public NumberFormat getNumberFormat(Locale locale) { |
||||
return NumberFormat.getIntegerInstance(locale); |
||||
} |
||||
} |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format.number; |
||||
|
||||
import java.text.NumberFormat; |
||||
import java.util.Locale; |
||||
|
||||
/** |
||||
* A factory for {@link NumberFormat} objects. |
||||
* Conceals the complexity associated with configuring, constructing, and/or caching number format instances. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
*/ |
||||
abstract class NumberFormatFactory { |
||||
|
||||
/** |
||||
* Factory method that returns a fully-configured {@link NumberFormat} instance to use to format an object for |
||||
* display. |
||||
* @return the number format |
||||
*/ |
||||
public abstract NumberFormat getNumberFormat(Locale locale); |
||||
|
||||
} |
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format.number; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.text.NumberFormat; |
||||
import java.text.ParseException; |
||||
import java.text.ParsePosition; |
||||
import java.util.Locale; |
||||
|
||||
import org.springframework.ui.format.Formatter; |
||||
|
||||
/** |
||||
* A BigDecimal formatter for percent values. |
||||
* Delegates to {@link NumberFormat#getPercentInstance(Locale)}. |
||||
* Configures BigDecimal parsing so there is no loss in precision. |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
*/ |
||||
public class PercentFormatter implements Formatter<BigDecimal> { |
||||
|
||||
private PercentNumberFormatFactory percentFormatFactory = new PercentNumberFormatFactory(); |
||||
|
||||
private boolean lenient; |
||||
|
||||
public String format(BigDecimal decimal, Locale locale) { |
||||
if (decimal == null) { |
||||
return ""; |
||||
} |
||||
NumberFormat format = percentFormatFactory.getNumberFormat(locale); |
||||
return format.format(decimal); |
||||
} |
||||
|
||||
public BigDecimal parse(String formatted, Locale locale) |
||||
throws ParseException { |
||||
if (formatted.length() == 0) { |
||||
return null; |
||||
} |
||||
NumberFormat format = percentFormatFactory.getNumberFormat(locale); |
||||
ParsePosition position = new ParsePosition(0); |
||||
BigDecimal decimal = (BigDecimal) format.parse(formatted, position); |
||||
if (position.getErrorIndex() != -1) { |
||||
throw new ParseException(formatted, position.getIndex()); |
||||
} |
||||
if (!lenient) { |
||||
if (formatted.length() != position.getIndex()) { |
||||
// indicates a part of the string that was not parsed
|
||||
throw new ParseException(formatted, position.getIndex()); |
||||
} |
||||
} |
||||
return decimal; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
/* |
||||
* Copyright 2004-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.ui.format.number; |
||||
|
||||
import java.text.DecimalFormat; |
||||
import java.text.NumberFormat; |
||||
import java.util.Locale; |
||||
|
||||
/** |
||||
* Produces NumberFormat instances that format percent values. |
||||
* @see NumberFormat |
||||
* @author Keith Donald |
||||
* @since 3.0 |
||||
*/ |
||||
final class PercentNumberFormatFactory extends NumberFormatFactory { |
||||
public NumberFormat getNumberFormat(Locale locale) { |
||||
DecimalFormat format = (DecimalFormat) NumberFormat.getPercentInstance(locale); |
||||
format.setParseBigDecimal(true); |
||||
return format; |
||||
} |
||||
} |
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
/** |
||||
* Formatters for <code>java.lang.Number</code> properties. |
||||
*/ |
||||
package org.springframework.ui.format.number; |
||||
|
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
/** |
||||
* A SPI for defining Formatters to format field model values for display in a UI. |
||||
*/ |
||||
package org.springframework.ui.format; |
||||
|
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
package org.springframework.ui.format; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
|
||||
import java.util.Locale; |
||||
|
||||
import org.junit.Before; |
||||
import org.junit.Ignore; |
||||
import org.junit.Test; |
||||
import org.springframework.core.convert.TypeDescriptor; |
||||
import org.springframework.ui.format.number.IntegerFormatter; |
||||
|
||||
public class GenericFormatterRegistryTests { |
||||
|
||||
private GenericFormatterRegistry registry; |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
registry = new GenericFormatterRegistry(); |
||||
} |
||||
|
||||
@Test |
||||
@Ignore |
||||
public void testAdd() { |
||||
registry.add(new IntegerFormatter()); |
||||
Formatter formatter = registry.getFormatter(typeDescriptor(Long.class)); |
||||
String formatted = formatter.format(new Long(3), Locale.US); |
||||
assertEquals("3", formatted); |
||||
} |
||||
|
||||
@Test |
||||
@Ignore |
||||
public void testAddByOtherObjectType() { |
||||
registry.add(Integer.class, new IntegerFormatter()); |
||||
Formatter formatter = registry.getFormatter(typeDescriptor(Integer.class)); |
||||
String formatted = formatter.format(new Integer(3), Locale.US); |
||||
assertEquals("3", formatted); |
||||
} |
||||
|
||||
@Test |
||||
@Ignore |
||||
public void testAddAnnotationFormatterFactory() { |
||||
} |
||||
|
||||
private static TypeDescriptor typeDescriptor(Class<?> clazz) { |
||||
return TypeDescriptor.valueOf(clazz); |
||||
} |
||||
} |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
package org.springframework.ui.format.date; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
|
||||
import java.text.ParseException; |
||||
import java.util.Calendar; |
||||
import java.util.Locale; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.ui.format.date.DateFormatter; |
||||
|
||||
public class DateFormatterTests { |
||||
|
||||
private DateFormatter formatter = new DateFormatter(); |
||||
|
||||
@Test |
||||
public void formatValue() { |
||||
Calendar cal = Calendar.getInstance(Locale.US); |
||||
cal.clear(); |
||||
cal.set(Calendar.YEAR, 2009); |
||||
cal.set(Calendar.MONTH, Calendar.JUNE); |
||||
cal.set(Calendar.DAY_OF_MONTH, 1); |
||||
assertEquals("2009-06-01", formatter.format(cal.getTime(), Locale.US)); |
||||
} |
||||
|
||||
@Test |
||||
public void parseValue() throws ParseException { |
||||
Calendar cal = Calendar.getInstance(Locale.US); |
||||
cal.clear(); |
||||
cal.set(Calendar.YEAR, 2009); |
||||
cal.set(Calendar.MONTH, Calendar.JUNE); |
||||
cal.set(Calendar.DAY_OF_MONTH, 1); |
||||
assertEquals(cal.getTime(), formatter.parse("2009-06-01", Locale.US)); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
package org.springframework.ui.format.number; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.text.ParseException; |
||||
import java.util.Locale; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.ui.format.number.CurrencyFormatter; |
||||
|
||||
public class CurrencyFormatterTests { |
||||
|
||||
private CurrencyFormatter formatter = new CurrencyFormatter(); |
||||
|
||||
@Test |
||||
public void formatValue() { |
||||
assertEquals("$23.00", formatter.format(new BigDecimal("23"), Locale.US)); |
||||
} |
||||
|
||||
@Test |
||||
public void parseValue() throws ParseException { |
||||
assertEquals(new BigDecimal("23.56"), formatter.parse("$23.56", Locale.US)); |
||||
} |
||||
|
||||
@Test |
||||
public void parseEmptyValue() throws ParseException { |
||||
assertEquals(null, formatter.parse("", Locale.US)); |
||||
} |
||||
|
||||
@Test(expected = ParseException.class) |
||||
public void parseBogusValue() throws ParseException { |
||||
formatter.parse("bogus", Locale.US); |
||||
} |
||||
|
||||
@Test |
||||
public void parseValueDefaultRoundDown() throws ParseException { |
||||
assertEquals(new BigDecimal("23.56"), formatter.parse("$23.567", Locale.US)); |
||||
} |
||||
|
||||
@Test |
||||
public void parseWholeValue() throws ParseException { |
||||
assertEquals(new BigDecimal("23.00"), formatter.parse("$23", Locale.US)); |
||||
} |
||||
|
||||
@Test(expected=ParseException.class) |
||||
public void parseValueNotLenientFailure() throws ParseException { |
||||
formatter.parse("$23.56bogus", Locale.US); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
package org.springframework.ui.format.number; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.text.ParseException; |
||||
import java.util.Locale; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.ui.format.number.DecimalFormatter; |
||||
|
||||
public class DecimalFormatterTests { |
||||
|
||||
private DecimalFormatter formatter = new DecimalFormatter(); |
||||
|
||||
@Test |
||||
public void formatValue() { |
||||
assertEquals("23.56", formatter.format(new BigDecimal("23.56"), Locale.US)); |
||||
} |
||||
|
||||
@Test |
||||
public void parseValue() throws ParseException { |
||||
assertEquals(new BigDecimal("23.56"), formatter.parse("23.56", Locale.US)); |
||||
} |
||||
|
||||
@Test |
||||
public void parseEmptyValue() throws ParseException { |
||||
assertEquals(null, formatter.parse("", Locale.US)); |
||||
} |
||||
|
||||
@Test(expected = ParseException.class) |
||||
public void parseBogusValue() throws ParseException { |
||||
formatter.parse("bogus", Locale.US); |
||||
} |
||||
|
||||
@Test(expected = ParseException.class) |
||||
public void parsePercentValueNotLenientFailure() throws ParseException { |
||||
formatter.parse("23.56bogus", Locale.US); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
package org.springframework.ui.format.number; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
|
||||
import java.text.ParseException; |
||||
import java.util.Locale; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.ui.format.number.IntegerFormatter; |
||||
|
||||
public class IntegerFormatterTests { |
||||
|
||||
private IntegerFormatter formatter = new IntegerFormatter(); |
||||
|
||||
@Test |
||||
public void formatValue() { |
||||
assertEquals("23", formatter.format(23L, Locale.US)); |
||||
} |
||||
|
||||
@Test |
||||
public void parseValue() throws ParseException { |
||||
assertEquals((Long) 2356L, formatter.parse("2356", Locale.US)); |
||||
} |
||||
|
||||
@Test |
||||
public void parseEmptyValue() throws ParseException { |
||||
assertEquals(null, formatter.parse("", Locale.US)); |
||||
} |
||||
|
||||
@Test(expected = ParseException.class) |
||||
public void parseBogusValue() throws ParseException { |
||||
formatter.parse("bogus", Locale.US); |
||||
} |
||||
|
||||
@Test(expected = ParseException.class) |
||||
public void parsePercentValueNotLenientFailure() throws ParseException { |
||||
formatter.parse("23.56", Locale.US); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
package org.springframework.ui.format.number; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.text.ParseException; |
||||
import java.util.Locale; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.ui.format.number.PercentFormatter; |
||||
|
||||
public class PercentFormatterTests { |
||||
|
||||
private PercentFormatter formatter = new PercentFormatter(); |
||||
|
||||
@Test |
||||
public void formatValue() { |
||||
assertEquals("23%", formatter.format(new BigDecimal(".23"), Locale.US)); |
||||
} |
||||
|
||||
@Test |
||||
public void parseValue() throws ParseException { |
||||
assertEquals(new BigDecimal(".2356"), formatter.parse("23.56%", |
||||
Locale.US)); |
||||
} |
||||
|
||||
@Test |
||||
public void parseEmptyValue() throws ParseException { |
||||
assertEquals(null, formatter.parse("", Locale.US)); |
||||
} |
||||
|
||||
@Test(expected = ParseException.class) |
||||
public void parseBogusValue() throws ParseException { |
||||
formatter.parse("bogus", Locale.US); |
||||
} |
||||
|
||||
@Test(expected = ParseException.class) |
||||
public void parsePercentValueNotLenientFailure() throws ParseException { |
||||
formatter.parse("23.56%bogus", Locale.US); |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue