DATAMONGO-1118 - MappingMongoConverter now uses custom conversions for Map keys, too.
We now allow conversions of map keys using custom Converter implementations if the conversion target type is a String. Original pull request: #260.
This commit is contained in:
committed by
Oliver Gierke
parent
1c2964cab4
commit
c353e02b3e
@@ -646,9 +646,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
Object key = entry.getKey();
|
||||
Object val = entry.getValue();
|
||||
if (conversions.isSimpleType(key.getClass())) {
|
||||
// Don't use conversion service here as removal of ObjectToString converter results in some primitive types not
|
||||
// being convertable
|
||||
String simpleKey = potentiallyEscapeMapKey(key.toString());
|
||||
|
||||
String simpleKey = potentiallyConvertMapKey(key);
|
||||
if (val == null || conversions.isSimpleType(val.getClass())) {
|
||||
writeSimpleInternal(val, dbo, simpleKey);
|
||||
} else if (val instanceof Collection || val.getClass().isArray()) {
|
||||
@@ -669,6 +668,20 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return dbo;
|
||||
}
|
||||
|
||||
private String potentiallyConvertMapKey(Object key) {
|
||||
|
||||
String stringKey = null;
|
||||
if (key instanceof String
|
||||
|| !(conversions.hasCustomWriteTarget(key.getClass()) && conversions.getCustomWriteTarget(key.getClass())
|
||||
.equals(String.class))) {
|
||||
stringKey = key.toString();
|
||||
} else {
|
||||
stringKey = (String) getPotentiallyConvertedSimpleWrite(key);
|
||||
}
|
||||
|
||||
return potentiallyEscapeMapKey(stringKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Potentially replaces dots in the given map key with the configured map key replacement if configured or aborts
|
||||
* conversion if none is configured.
|
||||
|
||||
@@ -56,12 +56,15 @@ import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.ConversionNotSupportedException;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.annotation.TypeAlias;
|
||||
import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.geo.Box;
|
||||
import org.springframework.data.geo.Circle;
|
||||
import org.springframework.data.geo.Distance;
|
||||
@@ -1964,6 +1967,7 @@ public class MappingMongoConverterUnitTests {
|
||||
assertThat(converter.read(TypeWithLocalDateTime.class, result).date, is(reference));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1128
|
||||
*/
|
||||
@@ -2001,6 +2005,68 @@ public class MappingMongoConverterUnitTests {
|
||||
assertThat(read.localDateTime, is(Optional.of(now)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1118
|
||||
*/
|
||||
@Test
|
||||
public void convertsMapKeyUsingCustomConverterForAndBackwards() {
|
||||
|
||||
MappingMongoConverter converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
converter.setCustomConversions(new CustomConversions(Arrays.asList(new FooBarEnumToStringConverter(),
|
||||
new StringToFooNumConverter())));
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
ClassWithMapUsingEnumAsKey source = new ClassWithMapUsingEnumAsKey();
|
||||
source.map = new HashMap<MappingMongoConverterUnitTests.FooBarEnum, String>();
|
||||
source.map.put(FooBarEnum.FOO, "wohoo");
|
||||
|
||||
DBObject target = new BasicDBObject();
|
||||
converter.write(source, target);
|
||||
|
||||
assertThat(converter.read(ClassWithMapUsingEnumAsKey.class, target).map, equalTo(source.map));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1118
|
||||
*/
|
||||
@Test
|
||||
public void writesMapKeyUsingCustomConverter() {
|
||||
|
||||
MappingMongoConverter converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
converter.setCustomConversions(new CustomConversions(Arrays.asList(new FooBarEnumToStringConverter())));
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
ClassWithMapUsingEnumAsKey source = new ClassWithMapUsingEnumAsKey();
|
||||
source.map = new HashMap<MappingMongoConverterUnitTests.FooBarEnum, String>();
|
||||
source.map.put(FooBarEnum.FOO, "spring");
|
||||
source.map.put(FooBarEnum.BAR, "data");
|
||||
|
||||
DBObject target = new BasicDBObject();
|
||||
converter.write(source, target);
|
||||
|
||||
DBObject map = DBObjectTestUtils.getAsDBObject(target, "map");
|
||||
|
||||
assertThat(map.containsField("foo-enum-value"), is(true));
|
||||
assertThat(map.containsField("bar-enum-value"), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-1118
|
||||
*/
|
||||
@Test
|
||||
public void readsMapKeyUsingCustomConverter() {
|
||||
|
||||
MappingMongoConverter converter = new MappingMongoConverter(resolver, mappingContext);
|
||||
converter.setCustomConversions(new CustomConversions(Arrays.asList(new StringToFooNumConverter())));
|
||||
converter.afterPropertiesSet();
|
||||
|
||||
DBObject source = new BasicDBObject("map", new BasicDBObject("foo-enum-value", "spring"));
|
||||
|
||||
ClassWithMapUsingEnumAsKey target = converter.read(ClassWithMapUsingEnumAsKey.class, source);
|
||||
|
||||
assertThat(target.map.get(FooBarEnum.FOO), is("spring"));
|
||||
}
|
||||
|
||||
static class GenericType<T> {
|
||||
T content;
|
||||
}
|
||||
@@ -2303,4 +2369,50 @@ public class MappingMongoConverterUnitTests {
|
||||
Optional<String> string = Optional.empty();
|
||||
Optional<LocalDateTime> localDateTime = Optional.empty();
|
||||
}
|
||||
|
||||
static enum FooBarEnum {
|
||||
FOO, BAR;
|
||||
}
|
||||
|
||||
static class ClassWithMapUsingEnumAsKey {
|
||||
Map<FooBarEnum, String> map;
|
||||
}
|
||||
|
||||
@WritingConverter
|
||||
static class FooBarEnumToStringConverter implements Converter<FooBarEnum, String> {
|
||||
|
||||
@Override
|
||||
public String convert(FooBarEnum source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return FooBarEnum.FOO.equals(source) ? "foo-enum-value" : "bar-enum-value";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ReadingConverter
|
||||
static class StringToFooNumConverter implements Converter<String, FooBarEnum> {
|
||||
|
||||
@Override
|
||||
public FooBarEnum convert(String source) {
|
||||
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (source.equals("foo-enum-value")) {
|
||||
return FooBarEnum.FOO;
|
||||
}
|
||||
if (source.equals("bar-enum-value")) {
|
||||
return FooBarEnum.BAR;
|
||||
}
|
||||
|
||||
throw new ConversionNotSupportedException(source, String.class, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user