introduced EmbeddedValueResolverAware callback interface for convenient placeholder resolution
This commit is contained in:
parent
8446fd1b26
commit
392accd910
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2002-2010 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.context;
|
||||
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by any object that wishes to be notified of a
|
||||
* <b>StringValueResolver</b> for the <b> resolution of embedded definition values.
|
||||
*
|
||||
* <p>This is an alternative to a full ConfigurableBeanFactory dependency via the
|
||||
* ApplicationContextAware/BeanFactoryAware interfaces.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0.3
|
||||
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#resolveEmbeddedValue
|
||||
*/
|
||||
public interface EmbeddedValueResolverAware {
|
||||
|
||||
/**
|
||||
* Set the StringValueResolver to use for resolving embedded definition values.
|
||||
*/
|
||||
void setEmbeddedValueResolver(StringValueResolver resolver);
|
||||
|
||||
}
|
||||
|
|
@ -22,11 +22,14 @@ import java.security.PrivilegedAction;
|
|||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.context.MessageSourceAware;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor}
|
||||
|
|
@ -86,6 +89,10 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
|
|||
}
|
||||
|
||||
private void invokeAwareInterfaces(Object bean) {
|
||||
if (bean instanceof EmbeddedValueResolverAware) {
|
||||
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
|
||||
new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
|
||||
}
|
||||
if (bean instanceof ResourceLoaderAware) {
|
||||
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
|
||||
}
|
||||
|
|
@ -104,4 +111,18 @@ class ApplicationContextAwareProcessor implements BeanPostProcessor {
|
|||
return bean;
|
||||
}
|
||||
|
||||
|
||||
private static class EmbeddedValueResolver implements StringValueResolver {
|
||||
|
||||
private final ConfigurableBeanFactory beanFactory;
|
||||
|
||||
public EmbeddedValueResolver(ConfigurableBeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public String resolveStringValue(String strVal) {
|
||||
return this.beanFactory.resolveEmbeddedValue(strVal);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 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.
|
||||
|
|
@ -31,12 +31,14 @@ import org.joda.time.ReadableInstant;
|
|||
import org.joda.time.ReadablePartial;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.format.AnnotationFormatterFactory;
|
||||
import org.springframework.format.Parser;
|
||||
import org.springframework.format.Printer;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* Formats fields annotated with the {@link DateTimeFormat} annotation.
|
||||
|
|
@ -46,9 +48,12 @@ import org.springframework.util.StringUtils;
|
|||
* @since 3.0
|
||||
* @see DateTimeFormat
|
||||
*/
|
||||
public final class JodaDateTimeFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<DateTimeFormat> {
|
||||
public class JodaDateTimeFormatAnnotationFormatterFactory
|
||||
implements AnnotationFormatterFactory<DateTimeFormat>, EmbeddedValueResolverAware {
|
||||
|
||||
private final Set<Class<?>> fieldTypes;
|
||||
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
|
||||
public JodaDateTimeFormatAnnotationFormatterFactory() {
|
||||
|
|
@ -64,11 +69,20 @@ public final class JodaDateTimeFormatAnnotationFormatterFactory implements Annot
|
|||
this.fieldTypes = Collections.unmodifiableSet(rawFieldTypes);
|
||||
}
|
||||
|
||||
public Set<Class<?>> getFieldTypes() {
|
||||
public final Set<Class<?>> getFieldTypes() {
|
||||
return this.fieldTypes;
|
||||
}
|
||||
|
||||
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.embeddedValueResolver = resolver;
|
||||
}
|
||||
|
||||
protected String resolveEmbeddedValue(String value) {
|
||||
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
|
||||
}
|
||||
|
||||
|
||||
public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) {
|
||||
DateTimeFormatter formatter = configureDateTimeFormatterFrom(annotation);
|
||||
if (ReadableInstant.class.isAssignableFrom(fieldType)) {
|
||||
|
|
@ -92,24 +106,26 @@ public final class JodaDateTimeFormatAnnotationFormatterFactory implements Annot
|
|||
}
|
||||
|
||||
|
||||
// internal helpers
|
||||
|
||||
private DateTimeFormatter configureDateTimeFormatterFrom(DateTimeFormat annotation) {
|
||||
if (StringUtils.hasLength(annotation.pattern())) {
|
||||
return forPattern(annotation.pattern());
|
||||
return forPattern(resolveEmbeddedValue(annotation.pattern()));
|
||||
}
|
||||
else if (annotation.iso() != ISO.NONE) {
|
||||
return forIso(annotation.iso());
|
||||
}
|
||||
else {
|
||||
return forStyle(annotation.style());
|
||||
return forStyle(resolveEmbeddedValue(annotation.style()));
|
||||
}
|
||||
}
|
||||
|
||||
private DateTimeFormatter forPattern(String pattern) {
|
||||
return org.joda.time.format.DateTimeFormat.forPattern(pattern);
|
||||
}
|
||||
|
||||
|
||||
private DateTimeFormatter forStyle(String style) {
|
||||
return org.joda.time.format.DateTimeFormat.forStyle(style);
|
||||
}
|
||||
|
||||
private DateTimeFormatter forIso(ISO iso) {
|
||||
if (iso == ISO.DATE) {
|
||||
return org.joda.time.format.ISODateTimeFormat.date();
|
||||
|
|
@ -122,8 +138,4 @@ public final class JodaDateTimeFormatAnnotationFormatterFactory implements Annot
|
|||
}
|
||||
}
|
||||
|
||||
private DateTimeFormatter forStyle(String style) {
|
||||
return org.joda.time.format.DateTimeFormat.forStyle(style);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 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.
|
||||
|
|
@ -22,6 +22,7 @@ import java.util.Collections;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.format.AnnotationFormatterFactory;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.Parser;
|
||||
|
|
@ -29,6 +30,7 @@ import org.springframework.format.Printer;
|
|||
import org.springframework.format.annotation.NumberFormat;
|
||||
import org.springframework.format.annotation.NumberFormat.Style;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* Formats fields annotated with the {@link NumberFormat} annotation.
|
||||
|
|
@ -37,46 +39,52 @@ import org.springframework.util.StringUtils;
|
|||
* @since 3.0
|
||||
* @see NumberFormat
|
||||
*/
|
||||
public final class NumberFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<NumberFormat> {
|
||||
public class NumberFormatAnnotationFormatterFactory
|
||||
implements AnnotationFormatterFactory<NumberFormat>, EmbeddedValueResolverAware {
|
||||
|
||||
private final Set<Class<?>> fieldTypes;
|
||||
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
|
||||
public NumberFormatAnnotationFormatterFactory() {
|
||||
this.fieldTypes = Collections.unmodifiableSet(createFieldTypes());
|
||||
Set<Class<?>> rawFieldTypes = new HashSet<Class<?>>(7);
|
||||
rawFieldTypes.add(Short.class);
|
||||
rawFieldTypes.add(Integer.class);
|
||||
rawFieldTypes.add(Long.class);
|
||||
rawFieldTypes.add(Float.class);
|
||||
rawFieldTypes.add(Double.class);
|
||||
rawFieldTypes.add(BigDecimal.class);
|
||||
rawFieldTypes.add(BigInteger.class);
|
||||
this.fieldTypes = Collections.unmodifiableSet(rawFieldTypes);
|
||||
}
|
||||
|
||||
|
||||
public Set<Class<?>> getFieldTypes() {
|
||||
public final Set<Class<?>> getFieldTypes() {
|
||||
return this.fieldTypes;
|
||||
}
|
||||
|
||||
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.embeddedValueResolver = resolver;
|
||||
}
|
||||
|
||||
protected String resolveEmbeddedValue(String value) {
|
||||
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
|
||||
}
|
||||
|
||||
|
||||
public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
|
||||
return configureFormatterFrom(annotation, fieldType);
|
||||
return configureFormatterFrom(annotation);
|
||||
}
|
||||
|
||||
public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
|
||||
return configureFormatterFrom(annotation, fieldType);
|
||||
return configureFormatterFrom(annotation);
|
||||
}
|
||||
|
||||
|
||||
// internal helpers
|
||||
|
||||
private Set<Class<?>> createFieldTypes() {
|
||||
Set<Class<?>> fieldTypes = new HashSet<Class<?>>(7);
|
||||
fieldTypes.add(Short.class);
|
||||
fieldTypes.add(Integer.class);
|
||||
fieldTypes.add(Long.class);
|
||||
fieldTypes.add(Float.class);
|
||||
fieldTypes.add(Double.class);
|
||||
fieldTypes.add(BigDecimal.class);
|
||||
fieldTypes.add(BigInteger.class);
|
||||
return fieldTypes;
|
||||
}
|
||||
|
||||
private Formatter<Number> configureFormatterFrom(NumberFormat annotation, Class<?> fieldType) {
|
||||
private Formatter<Number> configureFormatterFrom(NumberFormat annotation) {
|
||||
if (StringUtils.hasLength(annotation.pattern())) {
|
||||
return new NumberFormatter(annotation.pattern());
|
||||
return new NumberFormatter(resolveEmbeddedValue(annotation.pattern()));
|
||||
}
|
||||
else {
|
||||
Style style = annotation.style();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 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.
|
||||
|
|
@ -23,6 +23,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
|
|
@ -35,6 +36,7 @@ import org.springframework.format.Formatter;
|
|||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.format.Parser;
|
||||
import org.springframework.format.Printer;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.core.convert.ConversionService} implementation
|
||||
|
|
@ -44,7 +46,22 @@ import org.springframework.format.Printer;
|
|||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class FormattingConversionService extends GenericConversionService implements FormatterRegistry {
|
||||
public class FormattingConversionService extends GenericConversionService
|
||||
implements FormatterRegistry, EmbeddedValueResolverAware {
|
||||
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
private final Map<FieldFormatterKey, GenericConverter> cachedPrinters =
|
||||
new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
|
||||
|
||||
private final Map<FieldFormatterKey, GenericConverter> cachedParsers =
|
||||
new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
|
||||
|
||||
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.embeddedValueResolver = resolver;
|
||||
}
|
||||
|
||||
|
||||
public void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter) {
|
||||
addConverter(new PrinterConverter(fieldType, formatter, this));
|
||||
|
|
@ -61,16 +78,14 @@ public class FormattingConversionService extends GenericConversionService implem
|
|||
final Class<? extends Annotation> annotationType = (Class<? extends Annotation>)
|
||||
GenericTypeResolver.resolveTypeArgument(annotationFormatterFactory.getClass(), AnnotationFormatterFactory.class);
|
||||
if (annotationType == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unable to extract parameterized Annotation type argument from AnnotationFormatterFactory ["
|
||||
+ annotationFormatterFactory.getClass().getName()
|
||||
+ "]; does the factory parameterize the <A extends Annotation> generic type?");
|
||||
}
|
||||
Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes();
|
||||
throw new IllegalArgumentException("Unable to extract parameterized Annotation type argument from AnnotationFormatterFactory [" +
|
||||
annotationFormatterFactory.getClass().getName() + "]; does the factory parameterize the <A extends Annotation> generic type?");
|
||||
}
|
||||
if (this.embeddedValueResolver != null && annotationFormatterFactory instanceof EmbeddedValueResolverAware) {
|
||||
((EmbeddedValueResolverAware) annotationFormatterFactory).setEmbeddedValueResolver(this.embeddedValueResolver);
|
||||
}
|
||||
|
||||
final Map<FieldFormatterKey, GenericConverter> cachedPrinters = new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
|
||||
final Map<FieldFormatterKey, GenericConverter> cachedParsers = new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
|
||||
|
||||
Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes();
|
||||
for (final Class<?> fieldType : fieldTypes) {
|
||||
addConverter(new ConditionalGenericConverter() {
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
|
|
@ -119,6 +134,7 @@ public class FormattingConversionService extends GenericConversionService implem
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static final class FieldFormatterKey {
|
||||
|
||||
private final Annotation annotation;
|
||||
|
|
@ -147,11 +163,11 @@ public class FormattingConversionService extends GenericConversionService implem
|
|||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.annotation.hashCode() + this.fieldType.hashCode();
|
||||
return this.annotation.hashCode() + 29 * this.fieldType.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class PrinterConverter implements GenericConverter {
|
||||
|
||||
private Class<?> fieldType;
|
||||
|
|
@ -191,6 +207,7 @@ public class FormattingConversionService extends GenericConversionService implem
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class ParserConverter implements GenericConverter {
|
||||
|
||||
private Class<?> fieldType;
|
||||
|
|
@ -230,7 +247,6 @@ public class FormattingConversionService extends GenericConversionService implem
|
|||
public String toString() {
|
||||
return String.class.getName() + " -> " + this.fieldType.getName() + ": " + this.parser;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor;
|
|||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
|
@ -35,6 +35,7 @@ import org.springframework.scheduling.support.MethodInvokingRunnable;
|
|||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ReflectionUtils.MethodCallback;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* Bean post-processor that registers methods annotated with {@link Scheduled @Scheduled}
|
||||
|
|
@ -47,11 +48,14 @@ import org.springframework.util.ReflectionUtils.MethodCallback;
|
|||
* @see Scheduled
|
||||
* @see org.springframework.scheduling.TaskScheduler
|
||||
*/
|
||||
public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor, Ordered,
|
||||
ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, DisposableBean {
|
||||
public class ScheduledAnnotationBeanPostProcessor
|
||||
implements BeanPostProcessor, Ordered, EmbeddedValueResolverAware, ApplicationContextAware,
|
||||
ApplicationListener<ContextRefreshedEvent>, DisposableBean {
|
||||
|
||||
private Object scheduler;
|
||||
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar();
|
||||
|
|
@ -72,6 +76,10 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
|||
this.scheduler = scheduler;
|
||||
}
|
||||
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.embeddedValueResolver = resolver;
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
|
@ -102,17 +110,16 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor,
|
|||
try {
|
||||
runnable.prepare();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("failed to prepare task", e);
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("failed to prepare task", ex);
|
||||
}
|
||||
boolean processedSchedule = false;
|
||||
String errorMessage = "Exactly one of 'cron', 'fixedDelay', or 'fixedRate' is required.";
|
||||
String cron = annotation.cron();
|
||||
if (!"".equals(cron)) {
|
||||
processedSchedule = true;
|
||||
if (applicationContext instanceof ConfigurableApplicationContext) {
|
||||
cron = ((ConfigurableApplicationContext) applicationContext)
|
||||
.getBeanFactory().resolveEmbeddedValue(cron);
|
||||
if (embeddedValueResolver != null) {
|
||||
cron = embeddedValueResolver.resolveStringValue(cron);
|
||||
}
|
||||
cronTasks.put(runnable, cron);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -335,7 +335,6 @@ public class JodaTimeFormattingTests {
|
|||
@DateTimeFormat
|
||||
private DateTime dateTimeAnnotatedDefault;
|
||||
|
||||
@DateTimeFormat(style="S-")
|
||||
private Long millisAnnotated;
|
||||
|
||||
@DateTimeFormat(pattern="M/d/yy h:mm a")
|
||||
|
|
@ -480,11 +479,12 @@ public class JodaTimeFormattingTests {
|
|||
this.millis = millis;
|
||||
}
|
||||
|
||||
@DateTimeFormat(style="S-")
|
||||
public Long getMillisAnnotated() {
|
||||
return millisAnnotated;
|
||||
}
|
||||
|
||||
public void setMillisAnnotated(Long millisAnnotated) {
|
||||
public void setMillisAnnotated(@DateTimeFormat(style="S-") Long millisAnnotated) {
|
||||
this.millisAnnotated = millisAnnotated;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 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.
|
||||
|
|
@ -17,8 +17,8 @@
|
|||
package org.springframework.format.number;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Locale;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.After;
|
||||
import static org.junit.Assert.*;
|
||||
|
|
@ -31,6 +31,7 @@ import org.springframework.core.convert.support.ConversionServiceFactory;
|
|||
import org.springframework.format.annotation.NumberFormat;
|
||||
import org.springframework.format.annotation.NumberFormat.Style;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
import org.springframework.validation.DataBinder;
|
||||
|
||||
/**
|
||||
|
|
@ -46,6 +47,16 @@ public class NumberFormattingTests {
|
|||
@Before
|
||||
public void setUp() {
|
||||
ConversionServiceFactory.addDefaultConverters(conversionService);
|
||||
conversionService.setEmbeddedValueResolver(new StringValueResolver() {
|
||||
public String resolveStringValue(String strVal) {
|
||||
if ("${pattern}".equals(strVal)) {
|
||||
return "#,##.00";
|
||||
}
|
||||
else {
|
||||
return strVal;
|
||||
}
|
||||
}
|
||||
});
|
||||
conversionService.addFormatterForFieldType(Number.class, new NumberFormatter());
|
||||
conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
|
||||
LocaleContextHolder.setLocale(Locale.US);
|
||||
|
|
@ -154,7 +165,7 @@ public class NumberFormattingTests {
|
|||
@NumberFormat(style=Style.PERCENT)
|
||||
private BigDecimal percent;
|
||||
|
||||
@NumberFormat(pattern="#,##.00")
|
||||
@NumberFormat(pattern="${pattern}")
|
||||
private BigDecimal pattern;
|
||||
|
||||
@NumberFormat(pattern="#,##.00")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2010 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.
|
||||
|
|
@ -16,22 +16,24 @@
|
|||
|
||||
package org.springframework.format.support;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.junit.After;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
|
|
@ -70,7 +72,7 @@ public class FormattingConversionServiceTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testFormatFieldForTypeWithPrinterParserWithCoersion() throws ParseException {
|
||||
public void testFormatFieldForTypeWithPrinterParserWithCoercion() throws ParseException {
|
||||
formattingService.addConverter(new Converter<DateTime, LocalDate>() {
|
||||
public LocalDate convert(DateTime source) {
|
||||
return source.toLocalDate();
|
||||
|
|
@ -86,6 +88,24 @@ public class FormattingConversionServiceTests {
|
|||
|
||||
@Test
|
||||
public void testFormatFieldForAnnotation() throws Exception {
|
||||
doTestFormatFieldForAnnotation(Model.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatFieldForAnnotationWithPlaceholders() throws Exception {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
|
||||
Properties props = new Properties();
|
||||
props.setProperty("dateStyle", "S-");
|
||||
props.setProperty("datePattern", "M/d/yy");
|
||||
ppc.setProperties(props);
|
||||
context.getBeanFactory().registerSingleton("ppc", ppc);
|
||||
context.refresh();
|
||||
context.getBeanFactory().initializeBean(formattingService, "formattingService");
|
||||
doTestFormatFieldForAnnotation(ModelWithPlaceholders.class);
|
||||
}
|
||||
|
||||
private void doTestFormatFieldForAnnotation(Class<?> modelClass) throws Exception {
|
||||
formattingService.addConverter(new Converter<Date, Long>() {
|
||||
public Long convert(Date source) {
|
||||
return source.getTime();
|
||||
|
|
@ -97,34 +117,23 @@ public class FormattingConversionServiceTests {
|
|||
}
|
||||
});
|
||||
formattingService.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory());
|
||||
|
||||
String formatted = (String) formattingService.convert(new LocalDate(2009, 10, 31).toDateTimeAtCurrentTime()
|
||||
.toDate(), new TypeDescriptor(Model.class.getField("date")), TypeDescriptor.valueOf(String.class));
|
||||
.toDate(), new TypeDescriptor(modelClass.getField("date")), TypeDescriptor.valueOf(String.class));
|
||||
assertEquals("10/31/09", formatted);
|
||||
LocalDate date = new LocalDate(formattingService.convert("10/31/09", TypeDescriptor.valueOf(String.class),
|
||||
new TypeDescriptor(Model.class.getField("date"))));
|
||||
new TypeDescriptor(modelClass.getField("date"))));
|
||||
assertEquals(new LocalDate(2009, 10, 31), date);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatCollectionFieldForAnnotation() throws Exception {
|
||||
formattingService.addConverter(new Converter<Date, Long>() {
|
||||
public Long convert(Date source) {
|
||||
return source.getTime();
|
||||
}
|
||||
});
|
||||
formattingService.addConverter(new Converter<DateTime, Date>() {
|
||||
public Date convert(DateTime source) {
|
||||
return source.toDate();
|
||||
}
|
||||
});
|
||||
formattingService.addFormatterForFieldAnnotation(new JodaDateTimeFormatAnnotationFormatterFactory());
|
||||
|
||||
List<Date> dates = new ArrayList<Date>();
|
||||
dates.add(new LocalDate(2009, 10, 31).toDateTimeAtCurrentTime().toDate());
|
||||
dates.add(new LocalDate(2009, 11, 1).toDateTimeAtCurrentTime().toDate());
|
||||
dates.add(new LocalDate(2009, 11, 2).toDateTimeAtCurrentTime().toDate());
|
||||
String formatted = (String) formattingService.convert(dates, new TypeDescriptor(Model.class.getField("dates")), TypeDescriptor.valueOf(String.class));
|
||||
formatted = (String) formattingService.convert(dates,
|
||||
new TypeDescriptor(modelClass.getField("dates")), TypeDescriptor.valueOf(String.class));
|
||||
assertEquals("10/31/09,11/1/09,11/2/09", formatted);
|
||||
dates = (List<Date>) formattingService.convert("10/31/09,11/1/09,11/2/09", TypeDescriptor.valueOf(String.class), new TypeDescriptor(Model.class.getField("dates")));
|
||||
dates = (List<Date>) formattingService.convert("10/31/09,11/1/09,11/2/09",
|
||||
TypeDescriptor.valueOf(String.class), new TypeDescriptor(modelClass.getField("dates")));
|
||||
assertEquals(new LocalDate(2009, 10, 31), new LocalDate(dates.get(0)));
|
||||
assertEquals(new LocalDate(2009, 11, 1), new LocalDate(dates.get(1)));
|
||||
assertEquals(new LocalDate(2009, 11, 2), new LocalDate(dates.get(2)));
|
||||
|
|
@ -163,6 +172,7 @@ public class FormattingConversionServiceTests {
|
|||
assertNull(formattingService.convert("", TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class)));
|
||||
}
|
||||
|
||||
|
||||
private static class Model {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
|
@ -170,7 +180,20 @@ public class FormattingConversionServiceTests {
|
|||
public Date date;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@org.springframework.format.annotation.DateTimeFormat(style="S-")
|
||||
@org.springframework.format.annotation.DateTimeFormat(pattern="M/d/yy")
|
||||
public List<Date> dates;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class ModelWithPlaceholders {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@org.springframework.format.annotation.DateTimeFormat(style="${dateStyle}")
|
||||
public Date date;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@org.springframework.format.annotation.DateTimeFormat(pattern="${datePattern}")
|
||||
public List<Date> dates;
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue