@ -431,14 +431,6 @@ public class GenericConversionService implements ConfigurableConversionService {
* /
* /
private static class Converters {
private static class Converters {
private static final Set < Class < ? > > IGNORED_CLASSES ;
static {
Set < Class < ? > > ignored = new HashSet < Class < ? > > ( ) ;
ignored . add ( Object . class ) ;
ignored . add ( Object [ ] . class ) ;
IGNORED_CLASSES = Collections . unmodifiableSet ( ignored ) ;
}
private final Set < GenericConverter > globalConverters =
private final Set < GenericConverter > globalConverters =
new LinkedHashSet < GenericConverter > ( ) ;
new LinkedHashSet < GenericConverter > ( ) ;
@ -483,12 +475,13 @@ public class GenericConversionService implements ConfigurableConversionService {
* /
* /
public GenericConverter find ( TypeDescriptor sourceType , TypeDescriptor targetType ) {
public GenericConverter find ( TypeDescriptor sourceType , TypeDescriptor targetType ) {
// Search the full type hierarchy
// Search the full type hierarchy
List < TypeDescriptor > sourceCandidates = getTypeHierarchy ( sourceType ) ;
List < Class < ? > > sourceCandidates = getClassHierarchy ( sourceType . getType ( ) ) ;
List < TypeDescriptor > targetCandidates = getTypeHierarchy ( targetType ) ;
List < Class < ? > > targetCandidates = getClassHierarchy ( targetType . getType ( ) ) ;
for ( TypeDescriptor sourceCandidate : sourceCandidates ) {
for ( Class < ? > sourceCandidate : sourceCandidates ) {
for ( TypeDescriptor targetCandidate : targetCandidates ) {
for ( Class < ? > targetCandidate : targetCandidates ) {
ConvertiblePair convertiblePair = new ConvertiblePair ( sourceCandidate , targetCandidate ) ;
GenericConverter converter = getRegisteredConverter (
GenericConverter converter = getRegisteredConverter (
sourceType , targetType , sourceCandidate , targetCandidate ) ;
sourceType , targetType , convertiblePair ) ;
if ( converter ! = null ) {
if ( converter ! = null ) {
return converter ;
return converter ;
}
}
@ -497,12 +490,11 @@ public class GenericConversionService implements ConfigurableConversionService {
return null ;
return null ;
}
}
private GenericConverter getRegisteredConverter ( TypeDescriptor sourceType , TypeDescriptor targetType ,
private GenericConverter getRegisteredConverter ( TypeDescriptor sourceType ,
TypeDescriptor sourceCandidate , TypeDescriptor targetCandidate ) {
TypeDescriptor targetType , ConvertiblePair convertiblePair ) {
// Check specifically registered converters
// Check specifically registered converters
ConvertersForPair convertersForPair = converters . get ( new ConvertiblePair (
ConvertersForPair convertersForPair = converters . get ( convertiblePair ) ;
sourceCandidate . getType ( ) , targetCandidate . getType ( ) ) ) ;
GenericConverter converter = convertersForPair = = null ? null
GenericConverter converter = convertersForPair = = null ? null
: convertersForPair . getConverter ( sourceType , targetType ) ;
: convertersForPair . getConverter ( sourceType , targetType ) ;
if ( converter ! = null ) {
if ( converter ! = null ) {
@ -512,7 +504,7 @@ public class GenericConversionService implements ConfigurableConversionService {
// Check ConditionalGenericConverter that match all types
// Check ConditionalGenericConverter that match all types
for ( GenericConverter globalConverter : this . globalConverters ) {
for ( GenericConverter globalConverter : this . globalConverters ) {
if ( ( ( ConditionalConverter ) globalConverter ) . matches (
if ( ( ( ConditionalConverter ) globalConverter ) . matches (
sourceCandidate , targetCandidat e ) ) {
sourceType , targetTyp e ) ) {
return globalConverter ;
return globalConverter ;
}
}
}
}
@ -526,44 +518,38 @@ public class GenericConversionService implements ConfigurableConversionService {
* @return an ordered list of all classes that the given type extends or
* @return an ordered list of all classes that the given type extends or
* implements .
* implements .
* /
* /
private List < TypeDescriptor > getTypeHierarchy ( TypeDescriptor type ) {
private List < Class < ? > > getClassHierarchy ( Class < ? > type ) {
if ( type . isPrimitive ( ) ) {
List < Class < ? > > hierarchy = new ArrayList < Class < ? > > ( 20 ) ;
type = TypeDescriptor . valueOf ( type . getObjectType ( ) ) ;
Set < Class < ? > > visited = new HashSet < Class < ? > > ( 20 ) ;
}
addToClassHierarchy ( 0 , ClassUtils . resolvePrimitiveIfNecessary ( type ) , false , hierarchy , visited ) ;
Set < TypeDescriptor > typeHierarchy = new LinkedHashSet < TypeDescriptor > ( ) ;
boolean array = type . isArray ( ) ;
collectTypeHierarchy ( typeHierarchy , type ) ;
int i = 0 ;
if ( type . isArray ( ) ) {
while ( i < hierarchy . size ( ) ) {
typeHierarchy . add ( TypeDescriptor . valueOf ( Object [ ] . class ) ) ;
Class < ? > candidate = hierarchy . get ( i ) ;
}
candidate = ( array ? candidate . getComponentType ( )
typeHierarchy . add ( TypeDescriptor . valueOf ( Object . class ) ) ;
: ClassUtils . resolvePrimitiveIfNecessary ( candidate ) ) ;
return new ArrayList < TypeDescriptor > ( typeHierarchy ) ;
Class < ? > superclass = candidate . getSuperclass ( ) ;
}
if ( candidate . getSuperclass ( ) ! = null & & superclass ! = Object . class ) {
addToClassHierarchy ( i + 1 , candidate . getSuperclass ( ) , array , hierarchy , visited ) ;
private void collectTypeHierarchy ( Set < TypeDescriptor > typeHierarchy ,
TypeDescriptor type ) {
if ( type ! = null & & ! IGNORED_CLASSES . contains ( type . getType ( ) ) ) {
if ( typeHierarchy . add ( type ) ) {
Class < ? > superclass = type . getType ( ) . getSuperclass ( ) ;
if ( type . isArray ( ) ) {
superclass = ClassUtils . resolvePrimitiveIfNecessary ( superclass ) ;
}
collectTypeHierarchy ( typeHierarchy , createRelated ( type , superclass ) ) ;
for ( Class < ? > implementsInterface : type . getType ( ) . getInterfaces ( ) ) {
collectTypeHierarchy ( typeHierarchy , createRelated ( type , implementsInterface ) ) ;
}
}
}
for ( Class < ? > implementedInterface : candidate . getInterfaces ( ) ) {
addToClassHierarchy ( hierarchy . size ( ) , implementedInterface , array , hierarchy , visited ) ;
}
i + + ;
}
}
addToClassHierarchy ( hierarchy . size ( ) , Object . class , array , hierarchy , visited ) ;
addToClassHierarchy ( hierarchy . size ( ) , Object . class , false , hierarchy , visited ) ;
return hierarchy ;
}
}
private TypeDescriptor createRelated ( TypeDescriptor type , Class < ? > relatedType ) {
private void addToClassHierarchy ( int index , Class < ? > type , boolean asArray ,
if ( relatedType = = null & & type . isArray ( ) ) {
List < Class < ? > > hierarchy , Set < Class < ? > > visited ) {
relatedType = Array . newInstance ( relatedType , 0 ) . getClass ( ) ;
if ( asArray ) {
type = Array . newInstance ( type , 0 ) . getClass ( ) ;
}
}
if ( ! type . getType ( ) . equals ( relatedT ype) ) {
if ( visited . add ( t ype) ) {
return type . upcast ( relatedT ype) ;
hierarchy . add ( index , t ype) ;
}
}
return null ;
}
}
@Override
@Override