@ -105,8 +105,7 @@ public final class ResolvableType implements Serializable {
private boolean isResolved = false ;
private boolean isResolved = false ;
/ * *
/ * *
* Late binding stored copy of the resolved value ( valid when { @link # isResolved } is
* Late binding stored copy of the resolved value ( valid when { @link # isResolved } is true ) .
* true ) .
* /
* /
private Class < ? > resolved ;
private Class < ? > resolved ;
@ -116,7 +115,6 @@ public final class ResolvableType implements Serializable {
private final ResolvableType componentType ;
private final ResolvableType componentType ;
/ * *
/ * *
* Private constructor used to create a new { @link ResolvableType } .
* Private constructor used to create a new { @link ResolvableType } .
* @param type the underlying java type ( may only be { @code null } for { @link # NONE } )
* @param type the underlying java type ( may only be { @code null } for { @link # NONE } )
@ -131,13 +129,25 @@ public final class ResolvableType implements Serializable {
/ * *
/ * *
* Return the underling j ava { @link Type } being managed . With the exception of
* Return the underling J ava { @link Type } being managed . With the exception of
* the { @link # NONE } constant , this method will never return { @code null } .
* the { @link # NONE } constant , this method will never return { @code null } .
* /
* /
public Type getType ( ) {
public Type getType ( ) {
return this . type ;
return this . type ;
}
}
/ * *
* Return the underlying Java { @link Class } being managed , if available ;
* otherwise { @code null } .
* /
public Class < ? > getRawClass ( ) {
Type rawType = this . type ;
if ( rawType instanceof ParameterizedType ) {
rawType = ( ( ParameterizedType ) rawType ) . getRawType ( ) ;
}
return ( rawType instanceof Class ? ( Class ) rawType : null ) ;
}
/ * *
/ * *
* Determines if this { @code ResolvableType } is assignable from the specified
* Determines if this { @code ResolvableType } is assignable from the specified
* { @code type } . Attempts to follow the same rules as the Java compiler , considering
* { @code type } . Attempts to follow the same rules as the Java compiler , considering
@ -161,8 +171,7 @@ public final class ResolvableType implements Serializable {
// Deal with array by delegating to the component type
// Deal with array by delegating to the component type
if ( isArray ( ) ) {
if ( isArray ( ) ) {
return ( type . isArray ( ) & & getComponentType ( ) . isAssignableFrom (
return ( type . isArray ( ) & & getComponentType ( ) . isAssignableFrom ( type . getComponentType ( ) ) ) ;
type . getComponentType ( ) ) ) ;
}
}
// Deal with wildcard bounds
// Deal with wildcard bounds
@ -171,8 +180,8 @@ public final class ResolvableType implements Serializable {
// in the from X is assignable to <? extends Number>
// in the from X is assignable to <? extends Number>
if ( typeBounds ! = null ) {
if ( typeBounds ! = null ) {
return ( ourBounds ! = null & & ourBounds . isSameKind ( typeBounds )
return ( ourBounds ! = null & & ourBounds . isSameKind ( typeBounds ) & &
& & ourBounds . isAssignableFrom ( typeBounds . getBounds ( ) ) ) ;
ourBounds . isAssignableFrom ( typeBounds . getBounds ( ) ) ) ;
}
}
// in the form <? extends Number> is assignable to X ...
// in the form <? extends Number> is assignable to X ...
@ -189,8 +198,7 @@ public final class ResolvableType implements Serializable {
// Recursively check each generic
// Recursively check each generic
for ( int i = 0 ; i < getGenerics ( ) . length ; i + + ) {
for ( int i = 0 ; i < getGenerics ( ) . length ; i + + ) {
rtn & = getGeneric ( i ) . isAssignableFrom (
rtn & = getGeneric ( i ) . isAssignableFrom ( type . as ( resolve ( Object . class ) ) . getGeneric ( i ) , true ) ;
type . as ( resolve ( Object . class ) ) . getGeneric ( i ) , true ) ;
}
}
return rtn ;
return rtn ;
@ -228,8 +236,7 @@ public final class ResolvableType implements Serializable {
return forType ( componentType , this . variableResolver ) ;
return forType ( componentType , this . variableResolver ) ;
}
}
if ( this . type instanceof GenericArrayType ) {
if ( this . type instanceof GenericArrayType ) {
return forType ( ( ( GenericArrayType ) this . type ) . getGenericComponentType ( ) ,
return forType ( ( ( GenericArrayType ) this . type ) . getGenericComponentType ( ) , this . variableResolver ) ;
this . variableResolver ) ;
}
}
return resolveType ( ) . getComponentType ( ) ;
return resolveType ( ) . getComponentType ( ) ;
}
}
@ -291,7 +298,7 @@ public final class ResolvableType implements Serializable {
* @see # getInterfaces ( )
* @see # getInterfaces ( )
* /
* /
public ResolvableType getSuperType ( ) {
public ResolvableType getSuperType ( ) {
final Class < ? > resolved = resolve ( ) ;
Class < ? > resolved = resolve ( ) ;
if ( resolved = = null | | resolved . getGenericSuperclass ( ) = = null ) {
if ( resolved = = null | | resolved . getGenericSuperclass ( ) = = null ) {
return NONE ;
return NONE ;
}
}
@ -305,7 +312,7 @@ public final class ResolvableType implements Serializable {
* @see # getSuperType ( )
* @see # getSuperType ( )
* /
* /
public ResolvableType [ ] getInterfaces ( ) {
public ResolvableType [ ] getInterfaces ( ) {
final Class < ? > resolved = resolve ( ) ;
Class < ? > resolved = resolve ( ) ;
if ( resolved = = null | | ObjectUtils . isEmpty ( resolved . getGenericInterfaces ( ) ) ) {
if ( resolved = = null | | ObjectUtils . isEmpty ( resolved . getGenericInterfaces ( ) ) ) {
return EMPTY_TYPES_ARRAY ;
return EMPTY_TYPES_ARRAY ;
}
}
@ -321,6 +328,35 @@ public final class ResolvableType implements Serializable {
return ( getGenerics ( ) . length > 0 ) ;
return ( getGenerics ( ) . length > 0 ) ;
}
}
/ * *
* Determine whether the underlying type has unresolvable generics :
* either through an unresolvable type variable on the type itself
* or through implementing a generic interface in a raw fashion ,
* i . e . without substituting that interface ' s type variables .
* The result will be { @code true } only in those two scenarios .
* /
public boolean hasUnresolvableGenerics ( ) {
ResolvableType [ ] generics = getGenerics ( ) ;
for ( ResolvableType generic : generics ) {
if ( generic . resolve ( ) = = null ) {
return true ;
}
}
Class < ? > resolved = resolve ( ) ;
Type [ ] ifcs = resolved . getGenericInterfaces ( ) ;
for ( Type ifc : ifcs ) {
if ( ifc instanceof Class ) {
if ( forClass ( ( Class ) ifc ) . hasGenerics ( ) ) {
return true ;
}
}
}
if ( resolved . getGenericSuperclass ( ) ! = null ) {
return getSuperType ( ) . hasUnresolvableGenerics ( ) ;
}
return false ;
}
/ * *
/ * *
* Return a { @link ResolvableType } for the specified nesting level . See
* Return a { @link ResolvableType } for the specified nesting level . See
* { @link # getNested ( int , Map ) } for details .
* { @link # getNested ( int , Map ) } for details .
@ -362,8 +398,7 @@ public final class ResolvableType implements Serializable {
while ( result ! = ResolvableType . NONE & & ! result . hasGenerics ( ) ) {
while ( result ! = ResolvableType . NONE & & ! result . hasGenerics ( ) ) {
result = result . getSuperType ( ) ;
result = result . getSuperType ( ) ;
}
}
Integer index = ( typeIndexesPerLevel = = null ? null
Integer index = ( typeIndexesPerLevel ! = null ? typeIndexesPerLevel . get ( i ) : null ) ;
: typeIndexesPerLevel . get ( i ) ) ;
index = ( index = = null ? result . getGenerics ( ) . length - 1 : index ) ;
index = ( index = = null ? result . getGenerics ( ) . length - 1 : index ) ;
result = result . getGeneric ( index ) ;
result = result . getGeneric ( index ) ;
}
}
@ -515,10 +550,8 @@ public final class ResolvableType implements Serializable {
* it cannot be serialized .
* it cannot be serialized .
* /
* /
ResolvableType resolveType ( ) {
ResolvableType resolveType ( ) {
if ( this . type instanceof ParameterizedType ) {
if ( this . type instanceof ParameterizedType ) {
return forType ( ( ( ParameterizedType ) this . type ) . getRawType ( ) ,
return forType ( ( ( ParameterizedType ) this . type ) . getRawType ( ) , this . variableResolver ) ;
this . variableResolver ) ;
}
}
if ( this . type instanceof WildcardType ) {
if ( this . type instanceof WildcardType ) {
@ -535,7 +568,7 @@ public final class ResolvableType implements Serializable {
// Try default variable resolution
// Try default variable resolution
if ( this . variableResolver ! = null ) {
if ( this . variableResolver ! = null ) {
ResolvableType resolved = this . variableResolver . resolveVariable ( variable ) ;
ResolvableType resolved = this . variableResolver . resolveVariable ( variable ) ;
if ( resolved ! = null ) {
if ( resolved ! = null ) {
return resolved ;
return resolved ;
}
}
}
}
@ -555,7 +588,6 @@ public final class ResolvableType implements Serializable {
}
}
private ResolvableType resolveVariable ( TypeVariable < ? > variable ) {
private ResolvableType resolveVariable ( TypeVariable < ? > variable ) {
if ( this . type instanceof TypeVariable ) {
if ( this . type instanceof TypeVariable ) {
return resolveType ( ) . resolveVariable ( variable ) ;
return resolveType ( ) . resolveVariable ( variable ) ;
}
}
@ -571,8 +603,7 @@ public final class ResolvableType implements Serializable {
}
}
if ( parameterizedType . getOwnerType ( ) ! = null ) {
if ( parameterizedType . getOwnerType ( ) ! = null ) {
return forType ( parameterizedType . getOwnerType ( ) ,
return forType ( parameterizedType . getOwnerType ( ) , this . variableResolver ) . resolveVariable ( variable ) ;
this . variableResolver ) . resolveVariable ( variable ) ;
}
}
}
}
@ -627,7 +658,7 @@ public final class ResolvableType implements Serializable {
}
}
/ * *
/ * *
* Custom serialization support for { @value # NONE } .
* Custom serialization support for { @link # NONE } .
* /
* /
private Object readResolve ( ) throws ObjectStreamException {
private Object readResolve ( ) throws ObjectStreamException {
return ( this . type = = null ? NONE : this ) ;
return ( this . type = = null ? NONE : this ) ;
@ -640,22 +671,7 @@ public final class ResolvableType implements Serializable {
if ( this = = NONE ) {
if ( this = = NONE ) {
return null ;
return null ;
}
}
return new DefaultVariableResolver ( ) ;
return new VariableResolver ( ) {
private static final long serialVersionUID = 1L ;
@Override
public ResolvableType resolveVariable ( TypeVariable < ? > variable ) {
return ResolvableType . this . resolveVariable ( variable ) ;
}
@Override
public Object getSource ( ) {
return ResolvableType . this ;
}
} ;
}
}
private static boolean variableResolverSourceEquals ( VariableResolver o1 , VariableResolver o2 ) {
private static boolean variableResolverSourceEquals ( VariableResolver o1 , VariableResolver o2 ) {
@ -842,8 +858,7 @@ public final class ResolvableType implements Serializable {
* @see # forMethodParameter ( Method , int , Class )
* @see # forMethodParameter ( Method , int , Class )
* @see # forMethodParameter ( MethodParameter )
* @see # forMethodParameter ( MethodParameter )
* /
* /
public static ResolvableType forMethodParameter ( Method method , int parameterIndex ,
public static ResolvableType forMethodParameter ( Method method , int parameterIndex , Class < ? > implementationClass ) {
Class < ? > implementationClass ) {
Assert . notNull ( method , "Method must not be null" ) ;
Assert . notNull ( method , "Method must not be null" ) ;
MethodParameter methodParameter = new MethodParameter ( method , parameterIndex ) ;
MethodParameter methodParameter = new MethodParameter ( method , parameterIndex ) ;
methodParameter . setContainingClass ( implementationClass ) ;
methodParameter . setContainingClass ( implementationClass ) ;
@ -858,8 +873,7 @@ public final class ResolvableType implements Serializable {
* /
* /
public static ResolvableType forMethodParameter ( MethodParameter methodParameter ) {
public static ResolvableType forMethodParameter ( MethodParameter methodParameter ) {
Assert . notNull ( methodParameter , "MethodParameter must not be null" ) ;
Assert . notNull ( methodParameter , "MethodParameter must not be null" ) ;
ResolvableType owner = forType ( methodParameter . getContainingClass ( ) ) . as (
ResolvableType owner = forType ( methodParameter . getContainingClass ( ) ) . as ( methodParameter . getDeclaringClass ( ) ) ;
methodParameter . getDeclaringClass ( ) ) ;
return forType ( SerializableTypeWrapper . forMethodParameter ( methodParameter ) ,
return forType ( SerializableTypeWrapper . forMethodParameter ( methodParameter ) ,
owner . asVariableResolver ( ) ) . getNested ( methodParameter . getNestingLevel ( ) ,
owner . asVariableResolver ( ) ) . getNested ( methodParameter . getNestingLevel ( ) ,
methodParameter . typeIndexesPerLevel ) ;
methodParameter . typeIndexesPerLevel ) ;
@ -877,15 +891,13 @@ public final class ResolvableType implements Serializable {
}
}
/ * *
/ * *
* Return a { @link ResolvableType } for the specified { @link Class } with pre - declared
* Return a { @link ResolvableType } for the specified { @link Class } with pre - declared generics .
* generics .
* @param sourceClass the source class
* @param sourceClass the source class
* @param generics the generics of the class
* @param generics the generics of the class
* @return a { @link ResolvableType } for the specific class and generics
* @return a { @link ResolvableType } for the specific class and generics
* @see # forClassWithGenerics ( Class , ResolvableType . . . )
* @see # forClassWithGenerics ( Class , ResolvableType . . . )
* /
* /
public static ResolvableType forClassWithGenerics ( Class < ? > sourceClass ,
public static ResolvableType forClassWithGenerics ( Class < ? > sourceClass , Class < ? > . . . generics ) {
Class < ? > . . . generics ) {
Assert . notNull ( sourceClass , "Source class must not be null" ) ;
Assert . notNull ( sourceClass , "Source class must not be null" ) ;
Assert . notNull ( generics , "Generics must not be null" ) ;
Assert . notNull ( generics , "Generics must not be null" ) ;
ResolvableType [ ] resolvableGenerics = new ResolvableType [ generics . length ] ;
ResolvableType [ ] resolvableGenerics = new ResolvableType [ generics . length ] ;
@ -896,44 +908,17 @@ public final class ResolvableType implements Serializable {
}
}
/ * *
/ * *
* Return a { @link ResolvableType } for the specified { @link Class } with pre - declared
* Return a { @link ResolvableType } for the specified { @link Class } with pre - declared generics .
* generics .
* @param sourceClass the source class
* @param sourceClass the source class
* @param generics the generics of the class
* @param generics the generics of the class
* @return a { @link ResolvableType } for the specific class and generics
* @return a { @link ResolvableType } for the specific class and generics
* @see # forClassWithGenerics ( Class , Class . . . )
* @see # forClassWithGenerics ( Class , Class . . . )
* /
* /
public static ResolvableType forClassWithGenerics ( Class < ? > sourceClass ,
public static ResolvableType forClassWithGenerics ( Class < ? > sourceClass , ResolvableType . . . generics ) {
final ResolvableType . . . generics ) {
Assert . notNull ( sourceClass , "Source class must not be null" ) ;
Assert . notNull ( sourceClass , "Source class must not be null" ) ;
Assert . notNull ( generics , "Generics must not be null" ) ;
Assert . notNull ( generics , "Generics must not be null" ) ;
final TypeVariable < ? > [ ] typeVariables = sourceClass . getTypeParameters ( ) ;
TypeVariable < ? > [ ] typeVariables = sourceClass . getTypeParameters ( ) ;
Assert . isTrue ( typeVariables . length = = generics . length ,
return forType ( sourceClass , new TypeVariablesVariableResolver ( typeVariables , generics ) ) ;
"Missmatched number of generics specified" ) ;
VariableResolver variableResolver = new VariableResolver ( ) {
private static final long serialVersionUID = 1L ;
@Override
public ResolvableType resolveVariable ( TypeVariable < ? > variable ) {
for ( int i = 0 ; i < typeVariables . length ; i + + ) {
if ( typeVariables [ i ] . equals ( variable ) ) {
return generics [ i ] ;
}
}
return null ;
}
@Override
public Object getSource ( ) {
return generics ;
}
} ;
return forType ( sourceClass , variableResolver ) ;
}
}
/ * *
/ * *
@ -948,9 +933,8 @@ public final class ResolvableType implements Serializable {
}
}
/ * *
/ * *
* Return a { @link ResolvableType } for the specified { @link Type } backed by the
* Return a { @link ResolvableType } for the specified { @link Type } backed by the given
* given owner type . NOTE : The resulting { @link ResolvableType } may not be
* owner type . NOTE : The resulting { @link ResolvableType } may not be { @link Serializable } .
* { @link Serializable } .
* @param type the source type or { @code null }
* @param type the source type or { @code null }
* @param owner the owner type used to resolve variables
* @param owner the owner type used to resolve variables
* @return a { @link ResolvableType } for the specified { @link Type } and owner
* @return a { @link ResolvableType } for the specified { @link Type } and owner
@ -972,7 +956,7 @@ public final class ResolvableType implements Serializable {
* @return a { @link ResolvableType } for the specified { @link Type } and { @link VariableResolver }
* @return a { @link ResolvableType } for the specified { @link Type } and { @link VariableResolver }
* /
* /
static ResolvableType forType ( Type type , VariableResolver variableResolver ) {
static ResolvableType forType ( Type type , VariableResolver variableResolver ) {
if ( type = = null ) {
if ( type = = null ) {
return NONE ;
return NONE ;
}
}
// Check the cache, we may have a ResolvableType that may have already been resolved
// Check the cache, we may have a ResolvableType that may have already been resolved
@ -1002,7 +986,51 @@ public final class ResolvableType implements Serializable {
* @return the resolved variable or { @code null }
* @return the resolved variable or { @code null }
* /
* /
ResolvableType resolveVariable ( TypeVariable < ? > variable ) ;
ResolvableType resolveVariable ( TypeVariable < ? > variable ) ;
}
@SuppressWarnings ( "serial" )
private class DefaultVariableResolver implements VariableResolver {
@Override
public ResolvableType resolveVariable ( TypeVariable < ? > variable ) {
return ResolvableType . this . resolveVariable ( variable ) ;
}
@Override
public Object getSource ( ) {
return ResolvableType . this ;
}
}
@SuppressWarnings ( "serial" )
private static class TypeVariablesVariableResolver implements VariableResolver {
private final TypeVariable [ ] typeVariables ;
private final ResolvableType [ ] generics ;
public TypeVariablesVariableResolver ( TypeVariable [ ] typeVariables , ResolvableType [ ] generics ) {
Assert . isTrue ( typeVariables . length = = generics . length , "Mismatched number of generics specified" ) ;
this . typeVariables = typeVariables ;
this . generics = generics ;
}
@Override
public ResolvableType resolveVariable ( TypeVariable < ? > variable ) {
for ( int i = 0 ; i < this . typeVariables . length ; i + + ) {
if ( this . typeVariables [ i ] . equals ( variable ) ) {
return this . generics [ i ] ;
}
}
return null ;
}
@Override
public Object getSource ( ) {
return this . generics ;
}
}
}
@ -1016,12 +1044,12 @@ public final class ResolvableType implements Serializable {
private final ResolvableType [ ] bounds ;
private final ResolvableType [ ] bounds ;
/ * *
/ * *
* Private constructor to create a new { @link WildcardBounds } instance .
* Internal constructor to create a new { @link WildcardBounds } instance .
* @param kind the kind of bounds
* @param kind the kind of bounds
* @param bounds the bounds
* @param bounds the bounds
* @see # get ( ResolvableType )
* @see # get ( ResolvableType )
* /
* /
private WildcardBounds ( Kind kind , ResolvableType [ ] bounds ) {
public WildcardBounds ( Kind kind , ResolvableType [ ] bounds ) {
this . kind = kind ;
this . kind = kind ;
this . bounds = bounds ;
this . bounds = bounds ;
}
}
@ -1079,8 +1107,7 @@ public final class ResolvableType implements Serializable {
Type [ ] bounds = boundsType = = Kind . UPPER ? wildcardType . getUpperBounds ( ) : wildcardType . getLowerBounds ( ) ;
Type [ ] bounds = boundsType = = Kind . UPPER ? wildcardType . getUpperBounds ( ) : wildcardType . getLowerBounds ( ) ;
ResolvableType [ ] resolvableBounds = new ResolvableType [ bounds . length ] ;
ResolvableType [ ] resolvableBounds = new ResolvableType [ bounds . length ] ;
for ( int i = 0 ; i < bounds . length ; i + + ) {
for ( int i = 0 ; i < bounds . length ; i + + ) {
resolvableBounds [ i ] = ResolvableType . forType ( bounds [ i ] ,
resolvableBounds [ i ] = ResolvableType . forType ( bounds [ i ] , type . variableResolver ) ;
type . variableResolver ) ;
}
}
return new WildcardBounds ( boundsType , resolvableBounds ) ;
return new WildcardBounds ( boundsType , resolvableBounds ) ;
}
}
@ -1089,7 +1116,6 @@ public final class ResolvableType implements Serializable {
* The various kinds of bounds .
* The various kinds of bounds .
* /
* /
static enum Kind { UPPER , LOWER }
static enum Kind { UPPER , LOWER }
}
}
}
}