DATADOC-259 - MappingMongoConverter now converts Maps nested in Collections as well.

Fixed nested type handling in MappingMongoConverter.writeMapInternally(…). Force usage of ConversionService for simple values if read value doesn't match target type.
This commit is contained in:
Oliver Gierke
2011-09-04 13:55:28 +02:00
parent 234e04f4a3
commit 745e1f313d
2 changed files with 54 additions and 13 deletions

View File

@@ -69,14 +69,12 @@ import org.springframework.util.StringUtils;
* {@link MongoConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to
* {@link DBObject}.
*
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke
* @author Jon Brisbin
*/
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware,
TypeMapperProvider {
@SuppressWarnings("rawtypes")
private static final TypeInformation<Map> MAP_TYPE_INFORMATION = ClassTypeInformation.from(Map.class);
private static final List<Class<?>> VALID_ID_TYPES = Arrays.asList(new Class<?>[] { ObjectId.class, String.class,
BigInteger.class, byte[].class });
@@ -545,8 +543,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
dbList.add(createCollectionDBObject(asCollection(element), componentType));
} else {
BasicDBObject propDbObj = new BasicDBObject();
writeInternal(element, propDbObj,
mappingContext.getPersistentEntity(ClassTypeInformation.from(element.getClass())));
writeInternal(element, propDbObj);
addCustomTypeKeyIfNecessary(componentType, element, propDbObj);
dbList.add(propDbObj);
}
@@ -645,10 +642,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
@SuppressWarnings({ "rawtypes", "unchecked" })
private Object getPotentiallyConvertedSimpleRead(Object value, Class<?> target) {
Assert.notNull(target);
if (value == null) {
return null;
if (value == null || target == null) {
return value;
}
if (conversions.hasCustomReadTarget(value.getClass(), target)) {
@@ -658,8 +653,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
if (target.isEnum()) {
return Enum.valueOf((Class<Enum>) target, value.toString());
}
return value;
return target.isAssignableFrom(value.getClass()) ? value : conversionService.convert(value, target);
}
protected DBRef createDBRef(Object target, org.springframework.data.mongodb.core.mapping.DBRef dbref) {
@@ -810,8 +805,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
if (value instanceof DBObject) {
map.put(key, read(valueType, (DBObject) value));
} else {
valueType = valueType == null ? MAP_TYPE_INFORMATION : valueType;
map.put(key, getPotentiallyConvertedSimpleRead(value, valueType.getType()));
Class<?> valueClass = valueType == null ? null : valueType.getType();
map.put(key, getPotentiallyConvertedSimpleRead(value, valueClass));
}
}

View File

@@ -666,6 +666,51 @@ public class MappingMongoConverterUnitTests {
assertThat(doublyNestedObject, is(instanceOf(Map.class)));
assertThat((String) ((Map<?, ?>) doublyNestedObject).get("Hello"), is(equalTo("World")));
}
/**
* @see DATADOC-259
*/
@Test
public void writesListOfMapsCorrectly() {
Map<String, Locale> map = Collections.singletonMap("Foo", Locale.ENGLISH);
CollectionWrapper wrapper = new CollectionWrapper();
wrapper.listOfMaps = new ArrayList<Map<String,Locale>>();
wrapper.listOfMaps.add(map);
DBObject result = new BasicDBObject();
converter.write(wrapper, result);
BasicDBList list = (BasicDBList) result.get("listOfMaps");
assertThat(list, is(notNullValue()));
assertThat(list.size(), is(1));
DBObject dbObject = (DBObject) list.get(0);
assertThat(dbObject.containsField("Foo"), is(true));
assertThat((String) dbObject.get("Foo"), is(Locale.ENGLISH.toString()));
}
/**
* @see DATADOC-259
*/
@Test
public void readsListOfMapsCorrectly() {
DBObject map = new BasicDBObject("Foo", "en");
BasicDBList list = new BasicDBList();
list.add(map);
DBObject wrapperSource = new BasicDBObject("listOfMaps", list);
CollectionWrapper wrapper = converter.read(CollectionWrapper.class, wrapperSource);
assertThat(wrapper.listOfMaps, is(notNullValue()));
assertThat(wrapper.listOfMaps.size(), is(1));
assertThat(wrapper.listOfMaps.get(0), is(notNullValue()));
assertThat(wrapper.listOfMaps.get(0).get("Foo"), is(Locale.ENGLISH));
}
class GenericType<T> {
T content;
@@ -735,6 +780,7 @@ public class MappingMongoConverterUnitTests {
class CollectionWrapper {
List<Contact> contacts;
List<List<String>> strings;
List<Map<String, Locale>> listOfMaps;
}
class LocaleWrapper {