Skip to content

Commit 392accd

Browse files
committed
introduced EmbeddedValueResolverAware callback interface for convenient placeholder resolution
1 parent 8446fd1 commit 392accd

File tree

9 files changed

+224
-87
lines changed

9 files changed

+224
-87
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2002-2010 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.context;
18+
19+
import org.springframework.util.StringValueResolver;
20+
21+
/**
22+
* Interface to be implemented by any object that wishes to be notified of a
23+
* <b>StringValueResolver</b> for the <b> resolution of embedded definition values.
24+
*
25+
* <p>This is an alternative to a full ConfigurableBeanFactory dependency via the
26+
* ApplicationContextAware/BeanFactoryAware interfaces.
27+
*
28+
* @author Juergen Hoeller
29+
* @since 3.0.3
30+
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#resolveEmbeddedValue
31+
*/
32+
public interface EmbeddedValueResolverAware {
33+
34+
/**
35+
* Set the StringValueResolver to use for resolving embedded definition values.
36+
*/
37+
void setEmbeddedValueResolver(StringValueResolver resolver);
38+
39+
}

org.springframework.context/src/main/java/org/springframework/context/support/ApplicationContextAwareProcessor.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@
2222

2323
import org.springframework.beans.BeansException;
2424
import org.springframework.beans.factory.config.BeanPostProcessor;
25+
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
2526
import org.springframework.context.ApplicationContextAware;
2627
import org.springframework.context.ApplicationEventPublisherAware;
2728
import org.springframework.context.ConfigurableApplicationContext;
29+
import org.springframework.context.EmbeddedValueResolverAware;
2830
import org.springframework.context.MessageSourceAware;
2931
import org.springframework.context.ResourceLoaderAware;
32+
import org.springframework.util.StringValueResolver;
3033

3134
/**
3235
* {@link org.springframework.beans.factory.config.BeanPostProcessor}
@@ -86,6 +89,10 @@ public Object run() {
8689
}
8790

8891
private void invokeAwareInterfaces(Object bean) {
92+
if (bean instanceof EmbeddedValueResolverAware) {
93+
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
94+
new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
95+
}
8996
if (bean instanceof ResourceLoaderAware) {
9097
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
9198
}
@@ -104,4 +111,18 @@ public Object postProcessAfterInitialization(Object bean, String beanName) {
104111
return bean;
105112
}
106113

114+
115+
private static class EmbeddedValueResolver implements StringValueResolver {
116+
117+
private final ConfigurableBeanFactory beanFactory;
118+
119+
public EmbeddedValueResolver(ConfigurableBeanFactory beanFactory) {
120+
this.beanFactory = beanFactory;
121+
}
122+
123+
public String resolveStringValue(String strVal) {
124+
return this.beanFactory.resolveEmbeddedValue(strVal);
125+
}
126+
}
127+
107128
}

org.springframework.context/src/main/java/org/springframework/format/datetime/joda/JodaDateTimeFormatAnnotationFormatterFactory.java

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2010 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,12 +31,14 @@
3131
import org.joda.time.ReadablePartial;
3232
import org.joda.time.format.DateTimeFormatter;
3333

34+
import org.springframework.context.EmbeddedValueResolverAware;
3435
import org.springframework.format.AnnotationFormatterFactory;
3536
import org.springframework.format.Parser;
3637
import org.springframework.format.Printer;
3738
import org.springframework.format.annotation.DateTimeFormat;
3839
import org.springframework.format.annotation.DateTimeFormat.ISO;
3940
import org.springframework.util.StringUtils;
41+
import org.springframework.util.StringValueResolver;
4042

4143
/**
4244
* Formats fields annotated with the {@link DateTimeFormat} annotation.
@@ -46,9 +48,12 @@
4648
* @since 3.0
4749
* @see DateTimeFormat
4850
*/
49-
public final class JodaDateTimeFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<DateTimeFormat> {
51+
public class JodaDateTimeFormatAnnotationFormatterFactory
52+
implements AnnotationFormatterFactory<DateTimeFormat>, EmbeddedValueResolverAware {
5053

5154
private final Set<Class<?>> fieldTypes;
55+
56+
private StringValueResolver embeddedValueResolver;
5257

5358

5459
public JodaDateTimeFormatAnnotationFormatterFactory() {
@@ -64,11 +69,20 @@ public JodaDateTimeFormatAnnotationFormatterFactory() {
6469
this.fieldTypes = Collections.unmodifiableSet(rawFieldTypes);
6570
}
6671

67-
public Set<Class<?>> getFieldTypes() {
72+
public final Set<Class<?>> getFieldTypes() {
6873
return this.fieldTypes;
6974
}
7075

7176

77+
public void setEmbeddedValueResolver(StringValueResolver resolver) {
78+
this.embeddedValueResolver = resolver;
79+
}
80+
81+
protected String resolveEmbeddedValue(String value) {
82+
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
83+
}
84+
85+
7286
public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) {
7387
DateTimeFormatter formatter = configureDateTimeFormatterFrom(annotation);
7488
if (ReadableInstant.class.isAssignableFrom(fieldType)) {
@@ -92,24 +106,26 @@ public Parser<DateTime> getParser(DateTimeFormat annotation, Class<?> fieldType)
92106
}
93107

94108

95-
// internal helpers
96-
97109
private DateTimeFormatter configureDateTimeFormatterFrom(DateTimeFormat annotation) {
98110
if (StringUtils.hasLength(annotation.pattern())) {
99-
return forPattern(annotation.pattern());
111+
return forPattern(resolveEmbeddedValue(annotation.pattern()));
100112
}
101113
else if (annotation.iso() != ISO.NONE) {
102114
return forIso(annotation.iso());
103115
}
104116
else {
105-
return forStyle(annotation.style());
117+
return forStyle(resolveEmbeddedValue(annotation.style()));
106118
}
107119
}
108120

109121
private DateTimeFormatter forPattern(String pattern) {
110122
return org.joda.time.format.DateTimeFormat.forPattern(pattern);
111123
}
112-
124+
125+
private DateTimeFormatter forStyle(String style) {
126+
return org.joda.time.format.DateTimeFormat.forStyle(style);
127+
}
128+
113129
private DateTimeFormatter forIso(ISO iso) {
114130
if (iso == ISO.DATE) {
115131
return org.joda.time.format.ISODateTimeFormat.date();
@@ -122,8 +138,4 @@ else if (iso == ISO.TIME) {
122138
}
123139
}
124140

125-
private DateTimeFormatter forStyle(String style) {
126-
return org.joda.time.format.DateTimeFormat.forStyle(style);
127-
}
128-
129141
}

org.springframework.context/src/main/java/org/springframework/format/number/NumberFormatAnnotationFormatterFactory.java

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2010 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,13 +22,15 @@
2222
import java.util.HashSet;
2323
import java.util.Set;
2424

25+
import org.springframework.context.EmbeddedValueResolverAware;
2526
import org.springframework.format.AnnotationFormatterFactory;
2627
import org.springframework.format.Formatter;
2728
import org.springframework.format.Parser;
2829
import org.springframework.format.Printer;
2930
import org.springframework.format.annotation.NumberFormat;
3031
import org.springframework.format.annotation.NumberFormat.Style;
3132
import org.springframework.util.StringUtils;
33+
import org.springframework.util.StringValueResolver;
3234

3335
/**
3436
* Formats fields annotated with the {@link NumberFormat} annotation.
@@ -37,46 +39,52 @@
3739
* @since 3.0
3840
* @see NumberFormat
3941
*/
40-
public final class NumberFormatAnnotationFormatterFactory implements AnnotationFormatterFactory<NumberFormat> {
42+
public class NumberFormatAnnotationFormatterFactory
43+
implements AnnotationFormatterFactory<NumberFormat>, EmbeddedValueResolverAware {
4144

4245
private final Set<Class<?>> fieldTypes;
4346

47+
private StringValueResolver embeddedValueResolver;
48+
4449

4550
public NumberFormatAnnotationFormatterFactory() {
46-
this.fieldTypes = Collections.unmodifiableSet(createFieldTypes());
51+
Set<Class<?>> rawFieldTypes = new HashSet<Class<?>>(7);
52+
rawFieldTypes.add(Short.class);
53+
rawFieldTypes.add(Integer.class);
54+
rawFieldTypes.add(Long.class);
55+
rawFieldTypes.add(Float.class);
56+
rawFieldTypes.add(Double.class);
57+
rawFieldTypes.add(BigDecimal.class);
58+
rawFieldTypes.add(BigInteger.class);
59+
this.fieldTypes = Collections.unmodifiableSet(rawFieldTypes);
4760
}
4861

49-
50-
public Set<Class<?>> getFieldTypes() {
62+
public final Set<Class<?>> getFieldTypes() {
5163
return this.fieldTypes;
5264
}
5365

54-
public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
55-
return configureFormatterFrom(annotation, fieldType);
66+
67+
public void setEmbeddedValueResolver(StringValueResolver resolver) {
68+
this.embeddedValueResolver = resolver;
5669
}
57-
58-
public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
59-
return configureFormatterFrom(annotation, fieldType);
70+
71+
protected String resolveEmbeddedValue(String value) {
72+
return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
6073
}
6174

6275

63-
// internal helpers
76+
public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
77+
return configureFormatterFrom(annotation);
78+
}
6479

65-
private Set<Class<?>> createFieldTypes() {
66-
Set<Class<?>> fieldTypes = new HashSet<Class<?>>(7);
67-
fieldTypes.add(Short.class);
68-
fieldTypes.add(Integer.class);
69-
fieldTypes.add(Long.class);
70-
fieldTypes.add(Float.class);
71-
fieldTypes.add(Double.class);
72-
fieldTypes.add(BigDecimal.class);
73-
fieldTypes.add(BigInteger.class);
74-
return fieldTypes;
80+
public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
81+
return configureFormatterFrom(annotation);
7582
}
7683

77-
private Formatter<Number> configureFormatterFrom(NumberFormat annotation, Class<?> fieldType) {
84+
85+
private Formatter<Number> configureFormatterFrom(NumberFormat annotation) {
7886
if (StringUtils.hasLength(annotation.pattern())) {
79-
return new NumberFormatter(annotation.pattern());
87+
return new NumberFormatter(resolveEmbeddedValue(annotation.pattern()));
8088
}
8189
else {
8290
Style style = annotation.style();

org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2010 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323
import java.util.Set;
2424
import java.util.concurrent.ConcurrentHashMap;
2525

26+
import org.springframework.context.EmbeddedValueResolverAware;
2627
import org.springframework.context.i18n.LocaleContextHolder;
2728
import org.springframework.core.GenericTypeResolver;
2829
import org.springframework.core.convert.ConversionService;
@@ -35,6 +36,7 @@
3536
import org.springframework.format.FormatterRegistry;
3637
import org.springframework.format.Parser;
3738
import org.springframework.format.Printer;
39+
import org.springframework.util.StringValueResolver;
3840

3941
/**
4042
* A {@link org.springframework.core.convert.ConversionService} implementation
@@ -44,7 +46,22 @@
4446
* @author Juergen Hoeller
4547
* @since 3.0
4648
*/
47-
public class FormattingConversionService extends GenericConversionService implements FormatterRegistry {
49+
public class FormattingConversionService extends GenericConversionService
50+
implements FormatterRegistry, EmbeddedValueResolverAware {
51+
52+
private StringValueResolver embeddedValueResolver;
53+
54+
private final Map<FieldFormatterKey, GenericConverter> cachedPrinters =
55+
new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
56+
57+
private final Map<FieldFormatterKey, GenericConverter> cachedParsers =
58+
new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
59+
60+
61+
public void setEmbeddedValueResolver(StringValueResolver resolver) {
62+
this.embeddedValueResolver = resolver;
63+
}
64+
4865

4966
public void addFormatterForFieldType(Class<?> fieldType, Formatter<?> formatter) {
5067
addConverter(new PrinterConverter(fieldType, formatter, this));
@@ -61,16 +78,14 @@ public void addFormatterForFieldAnnotation(final AnnotationFormatterFactory anno
6178
final Class<? extends Annotation> annotationType = (Class<? extends Annotation>)
6279
GenericTypeResolver.resolveTypeArgument(annotationFormatterFactory.getClass(), AnnotationFormatterFactory.class);
6380
if (annotationType == null) {
64-
throw new IllegalArgumentException(
65-
"Unable to extract parameterized Annotation type argument from AnnotationFormatterFactory ["
66-
+ annotationFormatterFactory.getClass().getName()
67-
+ "]; does the factory parameterize the <A extends Annotation> generic type?");
68-
}
69-
Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes();
81+
throw new IllegalArgumentException("Unable to extract parameterized Annotation type argument from AnnotationFormatterFactory [" +
82+
annotationFormatterFactory.getClass().getName() + "]; does the factory parameterize the <A extends Annotation> generic type?");
83+
}
84+
if (this.embeddedValueResolver != null && annotationFormatterFactory instanceof EmbeddedValueResolverAware) {
85+
((EmbeddedValueResolverAware) annotationFormatterFactory).setEmbeddedValueResolver(this.embeddedValueResolver);
86+
}
7087

71-
final Map<FieldFormatterKey, GenericConverter> cachedPrinters = new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
72-
final Map<FieldFormatterKey, GenericConverter> cachedParsers = new ConcurrentHashMap<FieldFormatterKey, GenericConverter>();
73-
88+
Set<Class<?>> fieldTypes = annotationFormatterFactory.getFieldTypes();
7489
for (final Class<?> fieldType : fieldTypes) {
7590
addConverter(new ConditionalGenericConverter() {
7691
public Set<ConvertiblePair> getConvertibleTypes() {
@@ -119,6 +134,7 @@ public String toString() {
119134
}
120135
}
121136

137+
122138
private static final class FieldFormatterKey {
123139

124140
private final Annotation annotation;
@@ -147,11 +163,11 @@ public boolean equals(Object o) {
147163
}
148164

149165
public int hashCode() {
150-
return this.annotation.hashCode() + this.fieldType.hashCode();
166+
return this.annotation.hashCode() + 29 * this.fieldType.hashCode();
151167
}
152-
153168
}
154169

170+
155171
private static class PrinterConverter implements GenericConverter {
156172

157173
private Class<?> fieldType;
@@ -191,6 +207,7 @@ public String toString() {
191207
}
192208
}
193209

210+
194211
private static class ParserConverter implements GenericConverter {
195212

196213
private Class<?> fieldType;
@@ -230,7 +247,6 @@ public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor t
230247
public String toString() {
231248
return String.class.getName() + " -> " + this.fieldType.getName() + ": " + this.parser;
232249
}
233-
234250
}
235251

236252
}

0 commit comments

Comments
 (0)