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 9da46304c..a0f10db00 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 @@ -19,6 +19,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.EnumMap; +import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -794,7 +796,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App * @param sourceValue must not be {@literal null}. * @return the converted {@link Collection} or array, will never be {@literal null}. */ - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "null" }) private Object readCollectionOrArray(TypeInformation targetType, BasicDBList sourceValue, Object parent) { Assert.notNull(targetType); @@ -807,11 +809,20 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class; - Collection items = targetType.getType().isArray() ? new ArrayList() : CollectionFactory - .createCollection(collectionType, sourceValue.size()); TypeInformation componentType = targetType.getComponentType(); Class rawComponentType = componentType == null ? null : componentType.getType(); + Collection items; + + if (targetType.getType().isArray()) { + items = new ArrayList(); + } else if (EnumSet.class.isAssignableFrom(collectionType)) { + Assert.notNull(rawComponentType, "Component type must not be null for enum sets!"); + items = EnumSet.noneOf(rawComponentType.asSubclass(Enum.class)); + } else { + items = CollectionFactory.createCollection(collectionType, sourceValue.size()); + } + for (int i = 0; i < sourceValue.size(); i++) { Object dbObjItem = sourceValue.get(i); @@ -836,31 +847,43 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App * @param dbObject * @return */ - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "null", "rawtypes" }) protected Map readMap(TypeInformation type, DBObject dbObject, Object parent) { Assert.notNull(dbObject); Class mapType = typeMapper.readType(dbObject, type).getType(); - Map map = CollectionFactory.createMap(mapType, dbObject.keySet().size()); + + TypeInformation keyType = type.getComponentType(); + Class rawKeyType = keyType == null ? null : keyType.getType(); + + TypeInformation valueType = type.getMapValueType(); + Class rawValueType = valueType == null ? null : valueType.getType(); + + Map map; + + if (EnumMap.class.isAssignableFrom(mapType)) { + Assert.notNull(keyType, "Key type must nut be null for enum maps!"); + map = new EnumMap(rawKeyType.asSubclass(Enum.class)); + } else { + map = CollectionFactory.createMap(mapType, dbObject.keySet().size()); + } + Map sourceMap = dbObject.toMap(); for (Entry entry : sourceMap.entrySet()) { + if (typeMapper.isTypeKey(entry.getKey())) { continue; } Object key = potentiallyUnescapeMapKey(entry.getKey()); - TypeInformation keyTypeInformation = type.getComponentType(); - if (keyTypeInformation != null) { - Class keyType = keyTypeInformation.getType(); - key = conversionService.convert(key, keyType); + if (rawKeyType != null) { + key = conversionService.convert(key, rawKeyType); } Object value = entry.getValue(); - TypeInformation valueType = type.getMapValueType(); - Class rawValueType = valueType == null ? null : valueType.getType(); if (value instanceof DBObject) { map.put(key, read(valueType, (DBObject) value, parent)); 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 0c2bb85ab..bc5a7fb08 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 @@ -28,6 +28,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.EnumMap; +import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -1454,6 +1456,37 @@ public class MappingMongoConverterUnitTests { assertThat(dbList.get(0), instanceOf(String.class)); } + /** + * @see DATAMONGO-833 + */ + @Test + public void readsEnumSetCorrectly() { + + BasicDBList enumSet = new BasicDBList(); + enumSet.add("SECOND"); + DBObject dbObject = new BasicDBObject("enumSet", enumSet); + + ClassWithEnumProperty result = converter.read(ClassWithEnumProperty.class, dbObject); + + assertThat(result.enumSet, is(instanceOf(EnumSet.class))); + assertThat(result.enumSet.size(), is(1)); + assertThat(result.enumSet, hasItem(SampleEnum.SECOND)); + } + + /** + * @see DATAMONGO-833 + */ + @Test + public void readsEnumMapCorrectly() { + + BasicDBObject enumMap = new BasicDBObject("FIRST", "Dave"); + ClassWithEnumProperty result = converter.read(ClassWithEnumProperty.class, new BasicDBObject("enumMap", enumMap)); + + assertThat(result.enumMap, is(instanceOf(EnumMap.class))); + assertThat(result.enumMap.size(), is(1)); + assertThat(result.enumMap.get(SampleEnum.FIRST), is("Dave")); + } + static class GenericType { T content; } @@ -1462,6 +1495,8 @@ public class MappingMongoConverterUnitTests { SampleEnum sampleEnum; List enums; + EnumSet enumSet; + EnumMap enumMap; } static enum SampleEnum {