diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/AbstractMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/AbstractMongoConverter.java index 411a6fa5a..4919efbc7 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/AbstractMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/AbstractMongoConverter.java @@ -26,6 +26,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -33,8 +34,10 @@ import org.bson.types.ObjectId; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.GenericTypeResolver; import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.TypeDescriptor; 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.GenericConversionService; @@ -64,6 +67,7 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali this.conversionService = conversionService == null ? ConversionServiceFactory.createDefaultConversionService() : conversionService; this.conversionService.removeConvertible(Object.class, String.class); + registerConverter(CustomToStringConverter.INSTANCE); } /** @@ -107,19 +111,33 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali * @param converter */ private void registerConverter(Object converter) { - Class[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), Converter.class); - if (MONGO_TYPES.contains(arguments[1]) || MONGO_TYPES.contains(arguments[0])) { - customTypeMapping.add(new ConvertiblePair(arguments[0], arguments[1])); + + if (converter instanceof GenericConverter) { + customTypeMapping.addAll(((GenericConverter) converter).getConvertibleTypes()); + } else { + Class[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), Converter.class); + if (MONGO_TYPES.contains(arguments[1]) || MONGO_TYPES.contains(arguments[0])) { + customTypeMapping.add(new ConvertiblePair(arguments[0], arguments[1])); + } } + 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 (converter instanceof GenericConverter) { + this.conversionService.addConverter((GenericConverter) converter); + added = true; + } + if (!added) { throw new IllegalArgumentException("Given set contains element that is neither Converter nor ConverterFactory!"); } @@ -222,4 +240,19 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali } return newDbl; } + + + private enum CustomToStringConverter implements GenericConverter { + INSTANCE; + + public Set getConvertibleTypes() { + ConvertiblePair localeToString = new ConvertiblePair(Locale.class, String.class); + ConvertiblePair booleanToString = new ConvertiblePair(Character.class, String.class); + return new HashSet(Arrays.asList(localeToString, booleanToString)); + } + + public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { + return source.toString(); + } + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java index 67b6ec725..9309b7587 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java @@ -559,7 +559,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App */ private void writeSimpleInternal(String key, Object value, DBObject dbObject) { - Object valueToSet = value.getClass().isEnum() ? ((Enum) value).name() : value; + Class customTarget = getCustomTarget(value.getClass(), null); + + Object valueToSet = null; + if (customTarget != null) { + valueToSet = conversionService.convert(value, customTarget); + } else { + valueToSet = value.getClass().isEnum() ? ((Enum) value).name() : value; + } dbObject.put(key, valueToSet); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java index a6d090bfe..463936946 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java @@ -269,6 +269,21 @@ public class MappingMongoConverterUnitTests { } + @Test + public void convertsLocalesOutOfTheBox() { + LocaleWrapper wrapper = new LocaleWrapper(); + wrapper.locale = Locale.US; + + DBObject dbObject = new BasicDBObject(); + converter.write(wrapper, dbObject); + + Object localeField = dbObject.get("locale"); + assertThat(localeField, is(String.class)); + assertThat((String) localeField, is("en_US")); + + LocaleWrapper read = converter.read(LocaleWrapper.class, dbObject); + assertThat(read.locale, is(Locale.US)); + } class ClassWithEnumProperty { @@ -307,6 +322,10 @@ public class MappingMongoConverterUnitTests { List contacts; } + class LocaleWrapper { + Locale locale; + } + private class LocalDateToDateConverter implements Converter { public Date convert(LocalDate source) {