From 00e1ebb88052848f729a4911d501c090d99aecb9 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 6 Jan 2015 15:29:29 +0100 Subject: [PATCH] DATAMONGO-1118 - Polishing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created dedicated prepareMapKey(…) method to chain calls to potentiallyConvertMapKey(…) and potentiallyEscapeMapKey(…) and make sure they always get applied in combination. Fixed initial map creation for DBRefs to apply the fixed behavior, too. Original pull request: #260. --- .../core/convert/MappingMongoConverter.java | 42 ++++++++++++++----- .../MappingMongoConverterUnitTests.java | 22 +++++----- 2 files changed, 42 insertions(+), 22 deletions(-) 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 9dd8166a3..258d41735 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 @@ -586,7 +586,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App if (conversions.isSimpleType(key.getClass())) { - String simpleKey = potentiallyEscapeMapKey(key.toString()); + String simpleKey = prepareMapKey(key.toString()); dbObject.put(simpleKey, value != null ? createDBRef(value, property) : null); } else { @@ -638,11 +638,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App protected DBObject writeMapInternal(Map obj, DBObject dbo, TypeInformation propertyType) { for (Map.Entry entry : obj.entrySet()) { + Object key = entry.getKey(); Object val = entry.getValue(); + if (conversions.isSimpleType(key.getClass())) { - String simpleKey = potentiallyEscapeMapKey(potentiallyConvertMapKey(key)); + String simpleKey = prepareMapKey(key); if (val == null || conversions.isSimpleType(val.getClass())) { writeSimpleInternal(val, dbo, simpleKey); } else if (val instanceof Collection || val.getClass().isArray()) { @@ -663,17 +665,19 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App return dbo; } - private String potentiallyConvertMapKey(Object key) { + /** + * Prepares the given {@link Map} key to be converted into a {@link String}. Will invoke potentially registered custom + * conversions and escape dots from the result as they're not supported as {@link Map} key in MongoDB. + * + * @param key must not be {@literal null}. + * @return + */ + private String prepareMapKey(Object key) { - if (key instanceof String) { - return (String) key; - } + Assert.notNull(key, "Map key must not be null!"); - if (conversions.hasCustomWriteTarget(key.getClass(), String.class)) { - return (String) getPotentiallyConvertedSimpleWrite(key); - } - - return key.toString(); + String convertedKey = potentiallyConvertMapKey(key); + return potentiallyEscapeMapKey(convertedKey); } /** @@ -698,6 +702,22 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App return source.replaceAll("\\.", mapKeyDotReplacement); } + /** + * Returns a {@link String} representation of the given {@link Map} key + * + * @param key + * @return + */ + private String potentiallyConvertMapKey(Object key) { + + if (key instanceof String) { + return (String) key; + } + + return conversions.hasCustomWriteTarget(key.getClass(), String.class) ? (String) getPotentiallyConvertedSimpleWrite(key) + : key.toString(); + } + /** * Translates the map key replacements in the given key just read with a dot in case a map key replacement has been * configured. 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 0ea164472..cfb341a9f 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 @@ -74,6 +74,7 @@ import org.springframework.data.mapping.model.MappingInstantiationException; import org.springframework.data.mongodb.core.DBObjectTestUtils; import org.springframework.data.mongodb.core.convert.DBObjectAccessorUnitTests.NestedType; import org.springframework.data.mongodb.core.convert.DBObjectAccessorUnitTests.ProjectingType; +import org.springframework.data.mongodb.core.convert.MappingMongoConverterUnitTests.ClassWithMapUsingEnumAsKey.FooBarEnum; import org.springframework.data.mongodb.core.geo.Sphere; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field; @@ -1876,6 +1877,7 @@ public class MappingMongoConverterUnitTests { * @see DATAMONGO-1118 */ @Test + @SuppressWarnings("unchecked") public void convertsMapKeyUsingCustomConverterForAndBackwards() { MappingMongoConverter converter = new MappingMongoConverter(resolver, mappingContext); @@ -1884,13 +1886,13 @@ public class MappingMongoConverterUnitTests { converter.afterPropertiesSet(); ClassWithMapUsingEnumAsKey source = new ClassWithMapUsingEnumAsKey(); - source.map = new HashMap(); + source.map = new HashMap(); source.map.put(FooBarEnum.FOO, "wohoo"); DBObject target = new BasicDBObject(); converter.write(source, target); - assertThat(converter.read(ClassWithMapUsingEnumAsKey.class, target).map, equalTo(source.map)); + assertThat(converter.read(ClassWithMapUsingEnumAsKey.class, target).map, is(source.map)); } /** @@ -1904,7 +1906,7 @@ public class MappingMongoConverterUnitTests { converter.afterPropertiesSet(); ClassWithMapUsingEnumAsKey source = new ClassWithMapUsingEnumAsKey(); - source.map = new HashMap(); + source.map = new HashMap(); source.map.put(FooBarEnum.FOO, "spring"); source.map.put(FooBarEnum.BAR, "data"); @@ -2196,11 +2198,12 @@ public class MappingMongoConverterUnitTests { } - static enum FooBarEnum { - FOO, BAR; - } - static class ClassWithMapUsingEnumAsKey { + + static enum FooBarEnum { + FOO, BAR; + } + Map map; } @@ -2209,13 +2212,13 @@ public class MappingMongoConverterUnitTests { @Override public String convert(FooBarEnum source) { + if (source == null) { return null; } return FooBarEnum.FOO.equals(source) ? "foo-enum-value" : "bar-enum-value"; } - } @ReadingConverter @@ -2237,8 +2240,5 @@ public class MappingMongoConverterUnitTests { throw new ConversionNotSupportedException(source, String.class, null); } - } - - }