@ -32,8 +32,12 @@ import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils ;
import org.springframework.beans.BeanUtils ;
import org.springframework.core.CollectionFactory ;
import org.springframework.core.CollectionFactory ;
import org.springframework.core.convert.ConversionFailedException ;
import org.springframework.core.convert.ConversionFailedException ;
import org.springframework.core.convert.ConversionService ;
import org.springframework.core.convert.TypeDescriptor ;
import org.springframework.core.convert.converter.ConditionalGenericConverter ;
import org.springframework.core.convert.converter.Converter ;
import org.springframework.core.convert.converter.Converter ;
import org.springframework.core.convert.converter.ConverterFactory ;
import org.springframework.core.convert.converter.GenericConverter ;
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair ;
import org.springframework.core.convert.support.ConversionServiceFactory ;
import org.springframework.core.convert.support.ConversionServiceFactory ;
import org.springframework.core.convert.support.GenericConversionService ;
import org.springframework.core.convert.support.GenericConversionService ;
import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor ;
import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor ;
@ -108,18 +112,8 @@ public class SimpleMongoConverter implements MongoConverter {
* Creates a { @link SimpleMongoConverter } .
* Creates a { @link SimpleMongoConverter } .
* /
* /
public SimpleMongoConverter ( ) {
public SimpleMongoConverter ( ) {
this . conversionService = ConversionServiceFactory . createDefaultConversionService ( ) ;
this . conversionService = new SimpleToStringSuppressingGenericConversionService ( ) ;
initializeConverters ( ) ;
ConversionServiceFactory . addDefaultConverters ( conversionService ) ;
}
/ * *
* Creates a new { @link SimpleMongoConverter } for the given { @link ConversionService } .
*
* @param conversionService
* /
public SimpleMongoConverter ( GenericConversionService conversionService ) {
Assert . notNull ( conversionService ) ;
this . conversionService = conversionService ;
initializeConverters ( ) ;
initializeConverters ( ) ;
}
}
@ -129,14 +123,33 @@ public class SimpleMongoConverter implements MongoConverter {
* /
* /
protected void initializeConverters ( ) {
protected void initializeConverters ( ) {
if ( ! conversionService . canConvert ( ObjectId . class , String . class ) ) {
conversionService . addConverter ( ObjectIdToStringConverter . INSTANCE ) ;
conversionService . addConverter ( ObjectIdToStringConverter . INSTANCE ) ;
conversionService . addConverter ( StringToObjectIdConverter . INSTANCE ) ;
conversionService . addConverter ( StringToObjectIdConverter . INSTANCE ) ;
}
if ( ! conversionService . canConvert ( ObjectId . class , BigInteger . class ) ) {
conversionService . addConverter ( ObjectIdToBigIntegerConverter . INSTANCE ) ;
conversionService . addConverter ( ObjectIdToBigIntegerConverter . INSTANCE ) ;
conversionService . addConverter ( BigIntegerToIdConverter . INSTANCE ) ;
conversionService . addConverter ( BigIntegerToIdConverter . INSTANCE ) ;
}
/ * *
* Sets custom { @link Converter } or { @link ConverterFactory } instances to be used .
*
* @param converters
* /
public void setConverters ( Set < ? > converters ) {
for ( Object converter : converters ) {
boolean added = false ;
if ( converter instanceof Converter ) {
this . conversionService . addConverter ( ( Converter < ? , ? > ) converter ) ;
added = true ;
}
if ( converter instanceof ConverterFactory ) {
this . conversionService . addConverterFactory ( ( ConverterFactory < ? , ? > ) converter ) ;
added = true ;
}
if ( ! added ) {
throw new IllegalArgumentException ( "Given set contains element that is neither Converter nor ConverterFactory!" ) ;
}
}
}
}
}
@ -178,7 +191,7 @@ public class SimpleMongoConverter implements MongoConverter {
}
}
} else {
} else {
if ( ! "class" . equals ( descriptor . getName ( ) ) ) {
if ( ! "class" . equals ( descriptor . getName ( ) ) ) {
LOG . warn ( "Unable to map property " + descriptor . getName ( ) + ". Skipping ." ) ;
LOG . debug ( "Skipping property " + descriptor . getName ( ) + " as it's not a mappable one ." ) ;
}
}
}
}
}
}
@ -223,6 +236,12 @@ public class SimpleMongoConverter implements MongoConverter {
writeArray ( dbo , keyToUse , ( Object [ ] ) value ) ;
writeArray ( dbo , keyToUse , ( Object [ ] ) value ) ;
return ;
return ;
}
}
if ( conversionService . canConvert ( value . getClass ( ) , String . class ) ) {
dbo . put ( keyToUse , conversionService . convert ( value , String . class ) ) ;
return ;
}
DBObject nestedDbo = new BasicDBObject ( ) ;
DBObject nestedDbo = new BasicDBObject ( ) ;
write ( value , nestedDbo ) ;
write ( value , nestedDbo ) ;
dbo . put ( keyToUse , nestedDbo ) ;
dbo . put ( keyToUse , nestedDbo ) ;
@ -492,6 +511,30 @@ public class SimpleMongoConverter implements MongoConverter {
return conversionService . convert ( id , ObjectId . class ) ;
return conversionService . convert ( id , ObjectId . class ) ;
}
}
private static class SimpleToStringSuppressingGenericConversionService extends GenericConversionService {
private static final Set < ConvertiblePair > REFERENCE = Collections . singleton ( new ConvertiblePair ( Object . class , String . class ) ) ;
/ * ( non - Javadoc )
* @see org . springframework . core . convert . support . GenericConversionService # getConverter ( org . springframework . core . convert . TypeDescriptor , org . springframework . core . convert . TypeDescriptor )
* /
@Override
protected GenericConverter getConverter ( TypeDescriptor sourceType , TypeDescriptor targetType ) {
GenericConverter converter = super . getConverter ( sourceType , targetType ) ;
if ( converter instanceof ConditionalGenericConverter ) {
Set < ConvertiblePair > convertibleTypes = ( ( ConditionalGenericConverter ) converter ) . getConvertibleTypes ( ) ;
if ( REFERENCE . equals ( convertibleTypes ) ) {
return null ;
}
}
return converter ;
}
}
/ * *
/ * *
* Simple singleton to convert { @link ObjectId } s to their { @link String } representation .
* Simple singleton to convert { @link ObjectId } s to their { @link String } representation .
*
*