Skip to content

Commit

Permalink
introduced EmbeddedValueResolverAware callback interface for convenie…
Browse files Browse the repository at this point in the history
…nt placeholder resolution
  • Loading branch information
jhoeller committed Jun 7, 2010
1 parent 8446fd1 commit 392accd
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 87 deletions.
Original file line number Diff line number Diff line change
@@ -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);

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@

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}
Expand Down Expand Up @@ -86,6 +89,10 @@ public Object run() {
}

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);
}
Expand All @@ -104,4 +111,18 @@ public Object postProcessAfterInitialization(Object bean, String beanName) {
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);
}
}

}
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -31,12 +31,14 @@
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.
Expand All @@ -46,9 +48,12 @@
* @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() {
Expand All @@ -64,11 +69,20 @@ public JodaDateTimeFormatAnnotationFormatterFactory() {
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)) {
Expand All @@ -92,24 +106,26 @@ public Parser<DateTime> getParser(DateTimeFormat annotation, Class<?> fieldType)
}


// 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();
Expand All @@ -122,8 +138,4 @@ else if (iso == ISO.TIME) {
}
}

private DateTimeFormatter forStyle(String style) {
return org.joda.time.format.DateTimeFormat.forStyle(style);
}

}
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -22,13 +22,15 @@
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;
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.
Expand All @@ -37,46 +39,52 @@
* @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 Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
return configureFormatterFrom(annotation, fieldType);

public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.embeddedValueResolver = resolver;
}
public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
return configureFormatterFrom(annotation, fieldType);

protected String resolveEmbeddedValue(String value) {
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
}


// internal helpers
public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
return configureFormatterFrom(annotation);
}

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;
public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
return configureFormatterFrom(annotation);
}

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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -23,6 +23,7 @@
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;
Expand All @@ -35,6 +36,7 @@
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
Expand All @@ -44,7 +46,22 @@
* @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));
Expand All @@ -61,16 +78,14 @@ public void addFormatterForFieldAnnotation(final AnnotationFormatterFactory anno
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() {
Expand Down Expand Up @@ -119,6 +134,7 @@ public String toString() {
}
}


private static final class FieldFormatterKey {

private final Annotation annotation;
Expand Down Expand Up @@ -147,11 +163,11 @@ public boolean equals(Object o) {
}

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;
Expand Down Expand Up @@ -191,6 +207,7 @@ public String toString() {
}
}


private static class ParserConverter implements GenericConverter {

private Class<?> fieldType;
Expand Down Expand Up @@ -230,7 +247,6 @@ public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor t
public String toString() {
return String.class.getName() + " -> " + this.fieldType.getName() + ": " + this.parser;
}

}

}
Loading

0 comments on commit 392accd

Please sign in to comment.