diff --git a/org.springframework.context/src/main/java/org/springframework/format/FormatterRegistry.java b/org.springframework.context/src/main/java/org/springframework/format/FormatterRegistry.java
index 319eb029534..a31cfa17ebf 100644
--- a/org.springframework.context/src/main/java/org/springframework/format/FormatterRegistry.java
+++ b/org.springframework.context/src/main/java/org/springframework/format/FormatterRegistry.java
@@ -31,21 +31,7 @@ public interface FormatterRegistry extends ConverterRegistry {
/**
* Adds a Formatter to format fields of a specific type.
- * The Formatter will delegate to the specified printer for printing and the specified parser for parsing.
- *
- * On print, if the Printer's type T is declared and fieldType is not assignable to T,
- * a coersion to T will be attempted before delegating to printer to print a field value.
- * On parse, if the object returned by the Parser is not assignable to the runtime field type,
- * a coersion to the field type will be attempted before returning the parsed field value.
- * @param fieldType the field type to format
- * @param formatter the formatter to add
- */
- void addFormatterForFieldType(Class> fieldType, Printer> printer, Parser> parser);
-
- /**
- * Adds a Formatter to format fields of a specific type.
- *
- * On print, if the Formatter's type T is declared and fieldType is not assignable to T,
+ *
On print, if the Formatter's type T is declared and fieldType is not assignable to T,
* a coersion to T will be attempted before delegating to formatter to print a field value.
* On parse, if the parsed object returned by formatter is not assignable to the runtime field type,
* a coersion to the field type will be attempted before returning the parsed field value.
@@ -54,6 +40,20 @@ public interface FormatterRegistry extends ConverterRegistry {
*/
void addFormatterForFieldType(Class> fieldType, Formatter> formatter);
+ /**
+ * Adds a Printer/Parser pair to format fields of a specific type.
+ * The formatter will delegate to the specified printer for printing
+ * and the specified parser for parsing.
+ *
On print, if the Printer's type T is declared and As a general rule for runtime-retained annotations (e.g. for transaction
- * control, authorization or service exposure), always use the lookup methods on
- * this class (e.g., {@link #findAnnotation(Method, Class)},
- * {@link #getAnnotation(Method, Class)}, and {@link #getAnnotations(Method)})
- * instead of the plain annotation lookup methods in the JDK. You can still
- * explicitly choose between lookup on the given class level only
- * ({@link #getAnnotation(Method, Class)}) and lookup in the entire inheritance
- * hierarchy of the given method ({@link #findAnnotation(Method, Class)}).
+ * As a general rule for runtime-retained annotations (e.g. for transaction control, authorization or service
+ * exposure), always use the lookup methods on this class (e.g., {@link #findAnnotation(Method, Class)}, {@link
+ * #getAnnotation(Method, Class)}, and {@link #getAnnotations(Method)}) instead of the plain annotation lookup
+ * methods in the JDK. You can still explicitly choose between lookup on the given class level only ({@link
+ * #getAnnotation(Method, Class)}) and lookup in the entire inheritance hierarchy of the given method ({@link
+ * #findAnnotation(Method, Class)}).
*
* @author Rob Harrop
* @author Juergen Hoeller
@@ -51,8 +48,7 @@ import org.springframework.util.Assert;
public abstract class AnnotationUtils {
/** The attribute name for annotations with a single element */
- static final String VALUE = "value";
-
+ static final String VALUE = "value";
/**
* Get all {@link Annotation Annotations} from the supplied {@link Method}.
@@ -66,8 +62,7 @@ public abstract class AnnotationUtils {
}
/**
- * Get a single {@link Annotation} of Correctly handles bridge {@link Method Methods} generated by the compiler.
* @param method the method to look for annotations on
* @param annotationType the annotation class to look for
@@ -89,11 +84,9 @@ public abstract class AnnotationUtils {
}
/**
- * Get a single {@link Annotation} of Annotations on methods are not inherited by default, so we need to handle
- * this explicitly.
+ * Get a single {@link Annotation} of Annotations on methods are not inherited by default, so we need to handle this explicitly.
* @param method the method to look for annotations on
* @param annotationType the annotation class to look for
* @return the annotation found, or This method explicitly handles class-level annotations which are
- * not declared as {@link java.lang.annotation.Inherited inherited}
- * as well as annotations on interfaces.
- * The algorithm operates as follows: Searches for an annotation on the given
- * class and returns it if found. Else searches all interfaces that the given
- * class declares, returning the annotation from the first matching candidate,
- * if any. Else proceeds with introspection of the superclass of the given class,
- * checking the superclass itself; if no annotation found there, proceeds with
- * the interfaces that the superclass declares. Recursing up through the entire
- * superclass hierarchy if no match is found.
+ * Find a single {@link Annotation} of This method explicitly
+ * handles class-level annotations which are not declared as {@link java.lang.annotation.Inherited inherited} as
+ * well as annotations on interfaces. The algorithm operates as follows: Searches for an annotation on the given
+ * class and returns it if found. Else searches all interfaces that the given class declares, returning the annotation
+ * from the first matching candidate, if any. Else proceeds with introspection of the superclass of the given class,
+ * checking the superclass itself; if no annotation found there, proceeds with the interfaces that the superclass
+ * declares. Recursing up through the entire superclass hierarchy if no match is found.
* @param clazz the class to look for annotations on
* @param annotationType the annotation class to look for
* @return the annotation found, or If the supplied The standard {@link Class} API does not provide a mechanism for
- * determining which class in an inheritance hierarchy actually declares an
- * {@link Annotation}, so we need to handle this explicitly.
+ * Find the first {@link Class} in the inheritance hierarchy of the specified If the supplied The standard {@link Class} API does not provide a
+ * mechanism for determining which class in an inheritance hierarchy actually declares an {@link Annotation}, so we
+ * need to handle this explicitly.
* @param annotationType the Class object corresponding to the annotation type
- * @param clazz the Class object corresponding to the class on which to
- * check for the annotation, or Note: This method does not determine if the annotation
- * is {@link java.lang.annotation.Inherited inherited}. For greater clarity
- * regarding inherited annotations, consider using
- * {@link #isAnnotationInherited(Class, Class)} instead.
+ * Determine whether an annotation for the specified Note: This method does not determine if the annotation is
+ * {@link java.lang.annotation.Inherited inherited}. For greater clarity regarding inherited
+ * annotations, consider using {@link #isAnnotationInherited(Class, Class)} instead.
* @param annotationType the Class object corresponding to the annotation type
- * @param clazz the Class object corresponding to the class on which to
- * check for the annotation
- * @return If the supplied If the supplied Applies a rule that determines if a converter between a set of
+ * {@link #getConvertibleTypes() convertible types} matches given a client request to
+ * convert between a source field of convertible type S and a target field of convertible type T.
+ *
+ * Often used to selectively match custom conversion logic based on the presence of
+ * a field or class-level characteristic, such as an annotation or method. For example,
+ * when converting from a String field to a Date field, an implementation might return
+ * As another example, when converting from a String field to an Account field,
+ * an implementation might return true if the target Account class defines a
+ * fieldType is not assignable to T,
+ * a coersion to T will be attempted before delegating to printer to print a field value.
+ * On parse, if the object returned by the Parser is not assignable to the runtime field type,
+ * a coersion to the field type will be attempted before returning the parsed field value.
+ * @param fieldType the field type to format
+ * @param printer the printing part of the formatter
+ * @param parser the parsing part of the formatter
+ */
+ void addFormatterForFieldType(Class> fieldType, Printer> printer, Parser> parser);
+
/**
* Adds a Formatter to format fields annotated with a specific format annotation.
* @param annotationFormatterFactory the annotation formatter factory to add
diff --git a/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java b/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java
index 4b316c72e6c..654699bc9c2 100644
--- a/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java
+++ b/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java
@@ -17,6 +17,7 @@
package org.springframework.format.support;
import java.lang.annotation.Annotation;
+import java.util.Collections;
import java.util.Set;
import org.springframework.context.i18n.LocaleContextHolder;
@@ -41,19 +42,18 @@ import org.springframework.format.Printer;
* @author Juergen Hoeller
* @since 3.0
*/
-public class FormattingConversionService extends GenericConversionService
- implements FormatterRegistry {
-
- public void addFormatterForFieldType(Class> fieldType, Printer> printer, Parser> parser) {
- addGenericConverter(new PrinterConverter(fieldType, printer, this));
- addGenericConverter(new ParserConverter(fieldType, parser, this));
- }
+public class FormattingConversionService extends GenericConversionService implements FormatterRegistry {
public void addFormatterForFieldType(Class> fieldType, Formatter> formatter) {
addGenericConverter(new PrinterConverter(fieldType, formatter, this));
addGenericConverter(new ParserConverter(fieldType, formatter, this));
}
+ public void addFormatterForFieldType(Class> fieldType, Printer> printer, Parser> parser) {
+ addGenericConverter(new PrinterConverter(fieldType, printer, this));
+ addGenericConverter(new ParserConverter(fieldType, parser, this));
+ }
+
@SuppressWarnings("unchecked")
public void addFormatterForFieldAnnotation(final AnnotationFormatterFactory annotationFormatterFactory) {
final Class extends Annotation> annotationType = (Class extends Annotation>)
@@ -68,8 +68,8 @@ public class FormattingConversionService extends GenericConversionService
for (final Class> fieldType : fieldTypes) {
addGenericConverter(new ConditionalGenericConverter() {
- public Class>[][] getConvertibleTypes() {
- return new Class>[][] {{fieldType, String.class}};
+ public SetannotationType from the
- * supplied {@link Method}.
+ * Get a single {@link Annotation} of annotationType from the supplied {@link Method}.
* annotationType from the
- * supplied {@link Method}, traversing its super methods if no annotation
- * can be found on the given method itself.
- * annotationType from the supplied {@link Method},
+ * traversing its super methods if no annotation can be found on the given method itself.
+ * null if none found
@@ -101,8 +94,8 @@ public abstract class AnnotationUtils {
public static A findAnnotation(Method method, Class annotationType) {
A annotation = getAnnotation(method, annotationType);
Class> cl = method.getDeclaringClass();
- if(annotation == null) {
- annotation = searchForAnnotationOnInterfaces(method, annotationType, cl.getInterfaces());
+ if (annotation == null) {
+ annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
}
while (annotation == null) {
cl = cl.getSuperclass();
@@ -112,8 +105,8 @@ public abstract class AnnotationUtils {
try {
Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes());
annotation = getAnnotation(equivalentMethod, annotationType);
- if(annotation == null) {
- annotation = searchForAnnotationOnInterfaces(method, annotationType, cl.getInterfaces());
+ if (annotation == null) {
+ annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());
}
}
catch (NoSuchMethodException ex) {
@@ -123,9 +116,9 @@ public abstract class AnnotationUtils {
return annotation;
}
- private static A searchForAnnotationOnInterfaces(Method method, Class annotationType, Class[] ifaces) {
+ private static A searchOnInterfaces(Method method, Class annotationType, Class[] ifcs) {
A annotation = null;
- for (Class> iface : ifaces) {
+ for (Class> iface : ifcs) {
Method equivalentMethod = null;
try {
equivalentMethod = iface.getDeclaredMethod(method.getName(), method.getParameterTypes());
@@ -142,19 +135,14 @@ public abstract class AnnotationUtils {
}
/**
- * Find a single {@link Annotation} of annotationType from the
- * supplied {@link Class}, traversing its interfaces and super classes
- * if no annotation can be found on the given class itself.
- * annotationType from the supplied {@link Class}, traversing its
+ * interfaces and super classes if no annotation can be found on the given class itself. null if none found
@@ -187,24 +175,18 @@ public abstract class AnnotationUtils {
}
/**
- * Find the first {@link Class} in the inheritance hierarchy of the
- * specified clazz (including the specified
- * clazz itself) which declares an annotation for the
- * specified annotationType, or null if not
- * found. If the supplied clazz is null,
- * null will be returned.
- * clazz is an interface, only the interface
- * itself will be checked; the inheritance hierarchy for interfaces will not
- * be traversed.
- * clazz (including the
+ * specified clazz itself) which declares an annotation for the specified annotationType, or
+ * null if not found. If the supplied clazz is null, null will be
+ * returned. clazz is an interface, only the interface itself will be checked; the
+ * inheritance hierarchy for interfaces will not be traversed. null.
- * @return the first {@link Class} in the inheritance hierarchy of the
- * specified clazz which declares an annotation for the specified
- * annotationType, or null if not found.
+ * @param clazz the Class object corresponding to the class on which to check for the annotation, or
+ * null.
+ * @return the first {@link Class} in the inheritance hierarchy of the specified clazz which
+ * declares an annotation for the specified annotationType, or null if not found.
* @see Class#isAnnotationPresent(Class)
* @see Class#getDeclaredAnnotations()
*/
@@ -213,23 +195,21 @@ public abstract class AnnotationUtils {
if (clazz == null || clazz.equals(Object.class)) {
return null;
}
- return (isAnnotationDeclaredLocally(annotationType, clazz)) ?
- clazz : findAnnotationDeclaringClass(annotationType, clazz.getSuperclass());
+ return (isAnnotationDeclaredLocally(annotationType, clazz)) ? clazz :
+ findAnnotationDeclaringClass(annotationType, clazz.getSuperclass());
}
/**
- * Determine whether an annotation for the specified annotationType
- * is declared locally on the supplied clazz.
- * The supplied {@link Class} object may represent any type.
- * annotationType is
+ * declared locally on the supplied clazz. The supplied {@link Class}
+ * may represent any type.
+ * true if an annotation for the specified
- * annotationType is declared locally on the supplied clazz
+ * @param clazz the Class object corresponding to the class on which to check for the annotation
+ * @return true if an annotation for the specified annotationType
+ * is declared locally on the supplied clazz
* @see Class#getDeclaredAnnotations()
* @see #isAnnotationInherited(Class, Class)
*/
@@ -247,22 +227,17 @@ public abstract class AnnotationUtils {
}
/**
- * Determine whether an annotation for the specified annotationType
- * is present on the supplied clazz and is
- * {@link java.lang.annotation.Inherited inherited}
- * (i.e., not declared locally for the class).
- * clazz is an interface, only the interface
- * itself will be checked. In accord with standard meta-annotation
- * semantics, the inheritance hierarchy for interfaces will not be
- * traversed. See the {@link java.lang.annotation.Inherited JavaDoc} for the
- * @Inherited meta-annotation for further details regarding annotation
- * inheritance.
+ * Determine whether an annotation for the specified annotationType is present
+ * on the supplied clazz and is {@link java.lang.annotation.Inherited inherited}
+ * i.e., not declared locally for the class).
+ * clazz is an interface, only the interface itself will be checked.
+ * In accordance with standard meta-annotation semantics, the inheritance hierarchy for interfaces
+ * will not be traversed. See the {@link java.lang.annotation.Inherited JavaDoc} for the
+ * @Inherited meta-annotation for further details regarding annotation inheritance.
* @param annotationType the Class object corresponding to the annotation type
- * @param clazz the Class object corresponding to the class on which to
- * check for the annotation
- * @return true if an annotation for the specified
- * annotationType is present on the supplied clazz
- * and is {@link java.lang.annotation.Inherited inherited}
+ * @param clazz the Class object corresponding to the class on which to check for the annotation
+ * @return true if an annotation for the specified annotationType is present
+ * on the supplied clazz and is {@link java.lang.annotation.Inherited inherited}
* @see Class#isAnnotationPresent(Class)
* @see #isAnnotationDeclaredLocally(Class, Class)
*/
@@ -273,11 +248,10 @@ public abstract class AnnotationUtils {
}
/**
- * Retrieve the given annotation's attributes as a Map,
- * preserving all attribute types as-is.
+ * Retrieve the given annotation's attributes as a Map, preserving all attribute types as-is.
* @param annotation the annotation to retrieve the attributes for
- * @return the Map of annotation attributes, with attribute names as keys
- * and corresponding attribute values as values
+ * @return the Map of annotation attributes, with attribute names as keys and
+ * corresponding attribute values as values
*/
public static Map"value"
- * attribute of a single-element Annotation, given an annotation instance.
+ * Retrieve the value of the "value" attribute of a
+ * single-element Annotation, given an annotation instance.
* @param annotation the annotation instance from which to retrieve the value
* @return the attribute value, or null if not found
* @see #getValue(Annotation, String)
@@ -334,12 +307,11 @@ public abstract class AnnotationUtils {
}
/**
- * Retrieve the value of a named Annotation attribute, given an
- * annotation instance.
- * @see #getValue(Annotation)
+ * Retrieve the value of a named Annotation attribute, given an annotation instance.
* @param annotation the annotation instance from which to retrieve the value
* @param attributeName the name of the attribute value to retrieve
* @return the attribute value, or null if not found
+ * @see #getValue(Annotation)
*/
public static Object getValue(Annotation annotation, String attributeName) {
try {
@@ -352,11 +324,9 @@ public abstract class AnnotationUtils {
}
/**
- * Retrieve the default value of the
- * "value" attribute of a single-element
- * Annotation, given an annotation instance.
- * @param annotation the annotation instance from which to retrieve
- * the default value
+ * Retrieve the default value of the "value" attribute
+ * of a single-element Annotation, given an annotation instance.
+ * @param annotation the annotation instance from which to retrieve the default value
* @return the default value, or null if not found
* @see #getDefaultValue(Annotation, String)
*/
@@ -365,13 +335,10 @@ public abstract class AnnotationUtils {
}
/**
- * Retrieve the default value of a named Annotation attribute,
- * given an annotation instance.
- * @param annotation the annotation instance from which to retrieve
- * the default value
+ * Retrieve the default value of a named Annotation attribute, given an annotation instance.
+ * @param annotation the annotation instance from which to retrieve the default value
* @param attributeName the name of the attribute value to retrieve
- * @return the default value of the named attribute, or null
- * if not found.
+ * @return the default value of the named attribute, or null if not found.
* @see #getDefaultValue(Class, String)
*/
public static Object getDefaultValue(Annotation annotation, String attributeName) {
@@ -379,11 +346,9 @@ public abstract class AnnotationUtils {
}
/**
- * Retrieve the default value of the
- * "value" attribute of a single-element
- * Annotation, given the {@link Class annotation type}.
- * @param annotationType the annotation type for which the
- * default value should be retrieved
+ * Retrieve the default value of the "value" attribute
+ * of a single-element Annotation, given the {@link Class annotation type}.
+ * @param annotationType the annotation type for which the default value should be retrieved
* @return the default value, or null if not found
* @see #getDefaultValue(Class, String)
*/
@@ -392,13 +357,10 @@ public abstract class AnnotationUtils {
}
/**
- * Retrieve the default value of a named Annotation attribute,
- * given the {@link Class annotation type}.
- * @param annotationType the annotation type for which the
- * default value should be retrieved
+ * Retrieve the default value of a named Annotation attribute, given the {@link Class annotation type}.
+ * @param annotationType the annotation type for which the default value should be retrieved
* @param attributeName the name of the attribute value to retrieve.
- * @return the default value of the named attribute, or null
- * if not found
+ * @return the default value of the named attribute, or null if not found
* @see #getDefaultValue(Annotation, String)
*/
public static Object getDefaultValue(Class extends Annotation> annotationType, String attributeName) {
diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConditionalGenericConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConditionalGenericConverter.java
index faed1dba17e..7fbf43f2e12 100644
--- a/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConditionalGenericConverter.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/convert/converter/ConditionalGenericConverter.java
@@ -20,21 +20,32 @@ import org.springframework.core.convert.TypeDescriptor;
/**
* A generic converter that conditionally executes.
- * Applies a rule that determines if a converter between a set of {@link #getConvertibleTypes() convertible types} matches given a client request to convert between a source field of convertible type S and a target field of convertible type T.
- * Often used to selectively match custom conversion logic based on the presence of a field or class-level characteristic, such as an annotation or method.
- * For example, when converting from a String field to a Date field, an implementation might return true if the target field has also been annotated with @DateTimeFormat.
- * As another example, when converting from a String field to an Account field, an implementation might return true if the target Account class defines a public static findAccount(String) method.
+ *
+ * true if the target field has also been annotated with @DateTimeFormat.
+ *
+ * public static findAccount(String) method.
+ *
* @author Keith Donald
* @since 3.0
*/
public interface ConditionalGenericConverter extends GenericConverter {
/**
- * Should the Converter from sourceType to targetType currently under consideration be selected?
+ * Should the converter from sourceType to targetType
+ * currently under consideration be selected?
* @param sourceType the type descriptor of the field we are converting from
* @param targetType 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
+}