From a5328da460dd8d06752034e12eeb904a57310edb Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Thu, 28 Jul 2011 13:29:32 +0200 Subject: [PATCH] Added handling of BigInteger. Added converter to handle BigInteger values. Adapted id handling to try converting and object to String before taking the id as is. Made custom converter implementations safe against invocations with null. --- .../core/convert/AbstractMongoConverter.java | 8 +++++ .../core/convert/MappingMongoConverter.java | 6 ++-- .../mongodb/core/convert/MongoConverters.java | 29 +++++++++++++++---- .../MappingMongoConverterUnitTests.java | 19 ++++++++++++ 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java index 4dc9c500b..51fdb5e57 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java @@ -29,8 +29,10 @@ import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.ConversionServiceFactory; import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToObjectIdConverter; +import org.springframework.data.mongodb.core.convert.MongoConverters.BigIntegerToStringConverter; import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToBigIntegerConverter; import org.springframework.data.mongodb.core.convert.MongoConverters.ObjectIdToStringConverter; +import org.springframework.data.mongodb.core.convert.MongoConverters.StringToBigIntegerConverter; import org.springframework.data.mongodb.core.convert.MongoConverters.StringToObjectIdConverter; import com.mongodb.BasicDBList; @@ -87,6 +89,12 @@ public abstract class AbstractMongoConverter implements MongoConverter, Initiali if (!conversionService.canConvert(BigInteger.class, ObjectId.class)) { conversionService.addConverter(BigIntegerToObjectIdConverter.INSTANCE); } + if (!conversionService.canConvert(BigInteger.class, String.class)) { + conversionService.addConverter(BigIntegerToStringConverter.INSTANCE); + } + if (!conversionService.canConvert(String.class, BigInteger.class)) { + conversionService.addConverter(StringToBigIntegerConverter.INSTANCE); + } conversions.registerConvertersIn(conversionService); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java index c350e0b74..a5e749a38 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java @@ -357,10 +357,10 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App final MongoPersistentProperty idProperty = entity.getIdProperty(); if (!dbo.containsField("_id") && null != idProperty) { Object idObj = null; - Class[] targetClasses = new Class[] { ObjectId.class, Object.class }; - for (Class targetClasse : targetClasses) { + Class[] targetClasses = new Class[] { ObjectId.class, String.class, Object.class }; + for (Class targetClass : targetClasses) { try { - idObj = wrapper.getProperty(idProperty, targetClasse, useFieldAccessOnly); + idObj = wrapper.getProperty(idProperty, targetClass, useFieldAccessOnly); if (null != idObj) { break; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java index 355410246..bd5608976 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoConverters.java @@ -20,6 +20,7 @@ import java.math.BigInteger; import org.bson.types.ObjectId; import org.springframework.core.convert.converter.Converter; +import org.springframework.util.StringUtils; /** * Wrapper class to contain useful converters for the usage with Mongo. @@ -44,7 +45,7 @@ abstract class MongoConverters { INSTANCE; public String convert(ObjectId id) { - return id.toString(); + return id == null ? null : id.toString(); } } @@ -57,7 +58,7 @@ abstract class MongoConverters { INSTANCE; public ObjectId convert(String source) { - return new ObjectId(source); + return StringUtils.hasText(source) ? new ObjectId(source) : null; } } @@ -70,7 +71,7 @@ abstract class MongoConverters { INSTANCE; public BigInteger convert(ObjectId source) { - return new BigInteger(source.toString(), 16); + return source == null ? null : new BigInteger(source.toString(), 16); } } @@ -83,7 +84,7 @@ abstract class MongoConverters { INSTANCE; public ObjectId convert(BigInteger source) { - return new ObjectId(source.toString(16)); + return source == null ? null : new ObjectId(source.toString(16)); } } @@ -92,7 +93,7 @@ abstract class MongoConverters { INSTANCE; public String convert(BigDecimal source) { - return source.toString(); + return source == null ? null : source.toString(); } } @@ -100,7 +101,23 @@ abstract class MongoConverters { INSTANCE; public BigDecimal convert(String source) { - return new BigDecimal(source); + return StringUtils.hasText(source) ? new BigDecimal(source) : null; + } + } + + public static enum BigIntegerToStringConverter implements Converter { + INSTANCE; + + public String convert(BigInteger source) { + return source == null ? null : source.toString(); + } + } + + public static enum StringToBigIntegerConverter implements Converter { + INSTANCE; + + public BigInteger convert(String source) { + return StringUtils.hasText(source) ? new BigInteger(source) : null; } } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index 1781f5e0d..d993fdf47 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -20,6 +20,7 @@ import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.math.BigDecimal; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -40,6 +41,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.core.convert.converter.Converter; +import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.convert.CustomConversions; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -508,6 +510,18 @@ public class MappingMongoConverterUnitTests { assertThat(((DBObject) map).keySet(), hasItem("en_US")); } + @Test + public void writesBigIntegerIdCorrectly() { + + ClassWithBigIntegerId foo = new ClassWithBigIntegerId(); + foo.id = BigInteger.valueOf(23L); + + DBObject result = new BasicDBObject(); + converter.write(foo, result); + + assertThat(result.get("_id"), is(instanceOf(String.class))); + } + class GenericType { T content; } @@ -571,6 +585,11 @@ public class MappingMongoConverterUnitTests { Locale locale; } + class ClassWithBigIntegerId { + @Id + BigInteger id; + } + private class LocalDateToDateConverter implements Converter { public Date convert(LocalDate source) {