diff --git a/org.springframework.context/src/main/java/org/springframework/ui/format/AnnotationFormatterFactory.java b/org.springframework.context/src/main/java/org/springframework/ui/format/AnnotationFormatterFactory.java index c27f33fcbf7..6c87d9741b4 100644 --- a/org.springframework.context/src/main/java/org/springframework/ui/format/AnnotationFormatterFactory.java +++ b/org.springframework.context/src/main/java/org/springframework/ui/format/AnnotationFormatterFactory.java @@ -19,14 +19,14 @@ import java.lang.annotation.Annotation; import java.util.Set; /** - * A factory that creates formatters to format values of fields annotated with a particular format {@link Annotation}. + * A factory that creates formatters to format values of fields annotated with a particular {@link Annotation}. * *
For example, a DateTimeFormatAnnotationFormatterFactory might create a formatter
- * that formats a Date objects set on properties annotated with @DateFormat.
+ * that formats Date values set on fields annotated with @DateTimeFormat.
*
* @author Keith Donald
* @since 3.0
- * @param the type of Annotation that should trigger property formatting
+ * @param the annotation type that should trigger formatting
*/
public interface AnnotationFormatterFactory {
@@ -36,17 +36,19 @@ public interface AnnotationFormatterFactory {
SetfieldType annotated with annotation.
+ * Get the Printer to print the value of a field of fieldType annotated with annotation.
+ * If the type <T> the printer accepts is not assignable to fieldType, a coersion from fieldType to <T> will be attempted before the Printer is invoked.
* @param annotation the annotation instance
- * @param fieldType the type of property being annotated
+ * @param fieldType the type of field that was annotated
* @return the printer
*/
Printer> getPrinter(A annotation, Class> fieldType);
/**
- * Get the Parser to parse the printed value of a property of fieldType annotated with annotation.
+ * Get the Parser to parse a submitted value for a field of fieldType annotated with annotation.
+ * If the object the parser returns is not assignable to fieldType, a coersion to fieldType will be attempted before the field is set.
* @param annotation the annotation instance
- * @param fieldType the type of field being annotated
+ * @param fieldType the type of field that was annotated
* @return the parser
*/
Parser> getParser(A annotation, Class> fieldType);
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/format/FormatterRegistry.java b/org.springframework.context/src/main/java/org/springframework/ui/format/FormatterRegistry.java
index 38864d1de91..33a82ce67cc 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/format/FormatterRegistry.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/format/FormatterRegistry.java
@@ -15,6 +15,8 @@
*/
package org.springframework.ui.format;
+import java.lang.annotation.Annotation;
+
import org.springframework.core.convert.converter.ConverterRegistry;
/**
@@ -54,12 +56,12 @@ public interface FormatterRegistry {
* Adds a Formatter to format fields annotated with a specific format annotation.
* @param annotationFormatterFactory the annotation formatter factory to add
*/
- void addFormatterForFieldAnnotation(AnnotationFormatterFactory> annotationFormatterFactory);
+ void addFormatterForFieldAnnotation(AnnotationFormatterFactory extends Annotation> annotationFormatterFactory);
/**
* Returns the registry of Converters that coerse field values to types required by Formatters.
- * Allows clients to register their own custom converters.
- * For example, a date/time formatting configuration might expect a java.util.Date field value to be converted to a Long for formatting.
+ * Allows clients to register their own custom converters directly.
+ * For example, a date/time formatting configuration might expect a java.util.Date field value to be coersed to a Long for formatting.
* Registering a simpler DateToLongConverter allievates the need to register multiple formatters for closely related types.
* @return the converter registry, allowing new Converters to be registered
*/
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/format/FormattingService.java b/org.springframework.context/src/main/java/org/springframework/ui/format/FormattingService.java
deleted file mode 100644
index 91f58c1d3d9..00000000000
--- a/org.springframework.context/src/main/java/org/springframework/ui/format/FormattingService.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2002-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;
-
-import org.springframework.core.convert.TypeDescriptor;
-
-/**
- * A service interface for formatting localized field values.
- * This is the entry point into the ui.format system.
- *
- * @author Keith Donald
- * @since 3.0
- */
-public interface FormattingService {
-
- /**
- * Print the field value for display in the locale.
- * @param fieldValue the field value
- * @param fieldType the field type
- * @param locale the user's locale
- * @return the printed string
- */
- String print(Object fieldValue, TypeDescriptor fieldType, Locale locale);
-
- /**
- * Parse the the value submitted by the user.
- * @param submittedValue the submitted field value
- * @param fieldType the field type
- * @param locale the user's locale
- * @return the parsed field value
- */
- Object parse(String submittedValue, TypeDescriptor fieldType, Locale locale) throws ParseException;
-
-}
diff --git a/org.springframework.context/src/main/java/org/springframework/ui/format/jodatime/AbstractDateTimeAnnotationFormatterFactory.java b/org.springframework.context/src/main/java/org/springframework/ui/format/jodatime/AbstractDateTimeAnnotationFormatterFactory.java
index 65c2bca7254..6c48799f408 100644
--- a/org.springframework.context/src/main/java/org/springframework/ui/format/jodatime/AbstractDateTimeAnnotationFormatterFactory.java
+++ b/org.springframework.context/src/main/java/org/springframework/ui/format/jodatime/AbstractDateTimeAnnotationFormatterFactory.java
@@ -41,7 +41,7 @@ abstract class AbstractDateTimeAnnotationFormatterFactory
private final Set@DateTimeFormat.
+ * @author Keith Donald
+ * @since 3.0
+ */
+public interface ConditionalGenericConverter extends GenericConverter {
+
+ /**
+ * Should the conversion between sourceFieldType and targetFieldType be performed?
+ * @param sourceFieldType the type descriptor of the field we are converting from
+ * @param targetFieldType the type descriptor of the field we are converting to
+ * @return true if conversion should be performed, false otherwise
+ */
+ boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType);
+
+}
\ No newline at end of file
diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java
index 09953aa0035..2b6e1fefcd6 100644
--- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java
@@ -51,7 +51,7 @@ public class GenericConversionService implements ConversionService, ConverterReg
}
};
- private final Mapnull if no suitable converter was found
*/
protected GenericConverter getConverter(TypeDescriptor sourceType, TypeDescriptor targetType) {
- GenericConverter converter = findConverterByClassPair(sourceType.getObjectType(), targetType.getObjectType());
+ MatchableConverters matchable = findMatchableConvertersForClassPair(sourceType.getObjectType(), targetType.getObjectType());
+ GenericConverter converter = matchConverter(matchable, sourceType, targetType);
if (converter != null) {
return converter;
} else if (this.parent != null && this.parent.canConvert(sourceType, targetType)) {
@@ -273,42 +274,61 @@ public class GenericConversionService implements ConversionService, ConverterReg
// internal helpers
+ private Class>[] getRequiredTypeInfo(Object converter, Class> genericIfc) {
+ return GenericTypeResolver.resolveTypeArguments(converter.getClass(), genericIfc);
+ }
+
+ private MatchableConverters getMatchableConvertersList(Class> sourceType, Class> targetType) {
+ Map