@ -72,7 +72,7 @@ public class TypeDescriptor implements Serializable {
@@ -72,7 +72,7 @@ public class TypeDescriptor implements Serializable {
private final ResolvableType resolvableType ;
private final AnnotatedElement annotatedElement ;
private final AnnotatedElementAdapter annotatedElement ;
/ * *
@ -82,7 +82,6 @@ public class TypeDescriptor implements Serializable {
@@ -82,7 +82,6 @@ public class TypeDescriptor implements Serializable {
* @param methodParameter the method parameter
* /
public TypeDescriptor ( MethodParameter methodParameter ) {
Assert . notNull ( methodParameter , "MethodParameter must not be null" ) ;
this . resolvableType = ResolvableType . forMethodParameter ( methodParameter ) ;
this . type = this . resolvableType . resolve ( methodParameter . getParameterType ( ) ) ;
this . annotatedElement = new AnnotatedElementAdapter ( methodParameter . getParameterIndex ( ) = = - 1 ?
@ -95,7 +94,6 @@ public class TypeDescriptor implements Serializable {
@@ -95,7 +94,6 @@ public class TypeDescriptor implements Serializable {
* @param field the field
* /
public TypeDescriptor ( Field field ) {
Assert . notNull ( field , "Field must not be null" ) ;
this . resolvableType = ResolvableType . forField ( field ) ;
this . type = this . resolvableType . resolve ( field . getType ( ) ) ;
this . annotatedElement = new AnnotatedElementAdapter ( field . getAnnotations ( ) ) ;
@ -121,6 +119,7 @@ public class TypeDescriptor implements Serializable {
@@ -121,6 +119,7 @@ public class TypeDescriptor implements Serializable {
* @param resolvableType the resolvable type
* @param type the backing type ( or { @code null } if it should get resolved )
* @param annotations the type annotations
* @since 4 . 0
* /
protected TypeDescriptor ( ResolvableType resolvableType , Class < ? > type , Annotation [ ] annotations ) {
this . resolvableType = resolvableType ;
@ -211,7 +210,7 @@ public class TypeDescriptor implements Serializable {
@@ -211,7 +210,7 @@ public class TypeDescriptor implements Serializable {
}
/ * *
* Returns the name of this type : the fully qualified class name .
* Return the name of this type : the fully qualified class name .
* /
public String getName ( ) {
return ClassUtils . getQualifiedName ( getType ( ) ) ;
@ -225,7 +224,7 @@ public class TypeDescriptor implements Serializable {
@@ -225,7 +224,7 @@ public class TypeDescriptor implements Serializable {
}
/ * *
* T he annotations associated with this type descriptor , if any .
* Return t he annotations associated with this type descriptor , if any .
* @return the annotations , or an empty array if none
* /
public Annotation [ ] getAnnotations ( ) {
@ -240,6 +239,11 @@ public class TypeDescriptor implements Serializable {
@@ -240,6 +239,11 @@ public class TypeDescriptor implements Serializable {
* @return < tt > true < / tt > if the annotation is present
* /
public boolean hasAnnotation ( Class < ? extends Annotation > annotationType ) {
if ( this . annotatedElement . isEmpty ( ) ) {
// Shortcut: AnnotatedElementUtils would have to expect AnnotatedElement.getAnnotations()
// to return a copy of the array, whereas we can do it more efficiently here.
return false ;
}
return AnnotatedElementUtils . isAnnotated ( this . annotatedElement , annotationType ) ;
}
@ -251,6 +255,11 @@ public class TypeDescriptor implements Serializable {
@@ -251,6 +255,11 @@ public class TypeDescriptor implements Serializable {
* /
@SuppressWarnings ( "unchecked" )
public < T extends Annotation > T getAnnotation ( Class < T > annotationType ) {
if ( this . annotatedElement . isEmpty ( ) ) {
// Shortcut: AnnotatedElementUtils would have to expect AnnotatedElement.getAnnotations()
// to return a copy of the array, whereas we can do it more efficiently here.
return null ;
}
return AnnotatedElementUtils . getMergedAnnotation ( this . annotatedElement , annotationType ) ;
}
@ -434,37 +443,51 @@ public class TypeDescriptor implements Serializable {
@@ -434,37 +443,51 @@ public class TypeDescriptor implements Serializable {
}
@Override
public boolean equals ( Object obj ) {
if ( this = = obj ) {
public boolean equals ( Object other ) {
if ( this = = other ) {
return true ;
}
if ( ! ( obj instanceof TypeDescriptor ) ) {
if ( ! ( other instanceof TypeDescriptor ) ) {
return false ;
}
TypeDescriptor other = ( TypeDescriptor ) obj ;
if ( ! ObjectUtils . nullSafeEquals ( this . type , other . type ) ) {
TypeDescriptor otherDesc = ( TypeDescriptor ) other ;
if ( getType ( ) ! = otherDesc . getType ( ) ) {
return false ;
}
if ( getAnnotations ( ) . length ! = other . getAnnotations ( ) . length ) {
if ( ! annotationsMatch ( otherDesc ) ) {
return false ;
}
for ( Annotation ann : getAnnotations ( ) ) {
if ( ! ann . equals ( other . getAnnotation ( ann . annotationType ( ) ) ) ) {
return false ;
}
}
if ( isCollection ( ) | | isArray ( ) ) {
return ObjectUtils . nullSafeEquals ( getElementTypeDescriptor ( ) , other . getElementTypeDescriptor ( ) ) ;
return ObjectUtils . nullSafeEquals ( getElementTypeDescriptor ( ) , otherDesc . getElementTypeDescriptor ( ) ) ;
}
else if ( isMap ( ) ) {
return ObjectUtils . nullSafeEquals ( getMapKeyTypeDescriptor ( ) , other . getMapKeyTypeDescriptor ( ) ) & &
ObjectUtils . nullSafeEquals ( getMapValueTypeDescriptor ( ) , other . getMapValueTypeDescriptor ( ) ) ;
return ( ObjectUtils . nullSafeEquals ( getMapKeyTypeDescriptor ( ) , otherDesc . getMapKeyTypeDescriptor ( ) ) & &
ObjectUtils . nullSafeEquals ( getMapValueTypeDescriptor ( ) , otherDesc . getMapValueTypeDescriptor ( ) ) ) ;
}
else {
return true ;
}
}
private boolean annotationsMatch ( TypeDescriptor otherDesc ) {
Annotation [ ] anns = getAnnotations ( ) ;
Annotation [ ] otherAnns = otherDesc . getAnnotations ( ) ;
if ( anns = = otherAnns ) {
return true ;
}
if ( anns . length ! = otherAnns . length ) {
return false ;
}
if ( anns . length > 0 ) {
for ( int i = 0 ; i < anns . length ; i + + ) {
if ( anns [ i ] ! = otherAnns [ i ] ) {
return false ;
}
}
}
return true ;
}
@Override
public int hashCode ( ) {
return getType ( ) . hashCode ( ) ;
@ -480,6 +503,20 @@ public class TypeDescriptor implements Serializable {
@@ -480,6 +503,20 @@ public class TypeDescriptor implements Serializable {
return builder . toString ( ) ;
}
/ * *
* Create a new type descriptor for an object .
* < p > Use this factory method to introspect a source object before asking the
* conversion system to convert it to some another type .
* < p > If the provided object is { @code null } , returns { @code null } , else calls
* { @link # valueOf ( Class ) } to build a TypeDescriptor from the object ' s class .
* @param source the source object
* @return the type descriptor
* /
public static TypeDescriptor forObject ( Object source ) {
return ( source ! = null ? valueOf ( source . getClass ( ) ) : null ) ;
}
/ * *
* Create a new type descriptor from the given type .
* < p > Use this to instruct the conversion system to convert an object to a
@ -640,19 +677,6 @@ public class TypeDescriptor implements Serializable {
@@ -640,19 +677,6 @@ public class TypeDescriptor implements Serializable {
return nested ( new TypeDescriptor ( property ) , nestingLevel ) ;
}
/ * *
* Create a new type descriptor for an object .
* < p > Use this factory method to introspect a source object before asking the
* conversion system to convert it to some another type .
* < p > If the provided object is { @code null } , returns { @code null } , else calls
* { @link # valueOf ( Class ) } to build a TypeDescriptor from the object ' s class .
* @param source the source object
* @return the type descriptor
* /
public static TypeDescriptor forObject ( Object source ) {
return ( source ! = null ? valueOf ( source . getClass ( ) ) : null ) ;
}
private static TypeDescriptor nested ( TypeDescriptor typeDescriptor , int nestingLevel ) {
ResolvableType nested = typeDescriptor . resolvableType ;
for ( int i = 0 ; i < nestingLevel ; i + + ) {
@ -723,6 +747,10 @@ public class TypeDescriptor implements Serializable {
@@ -723,6 +747,10 @@ public class TypeDescriptor implements Serializable {
return getAnnotations ( ) ;
}
public boolean isEmpty ( ) {
return ObjectUtils . isEmpty ( this . annotations ) ;
}
@Override
public boolean equals ( Object other ) {
return ( this = = other | | ( other instanceof AnnotatedElementAdapter & &