Skip to content

Commit

Permalink
DATAMONGO-1118 - MappingMongoConverter now uses custom conversions fo…
Browse files Browse the repository at this point in the history
…r 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.
  • Loading branch information
christophstrobl authored and odrotbohm committed Jan 6, 2015
1 parent 1c2964c commit c353e02
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 3 deletions.
Expand Up @@ -646,9 +646,8 @@ protected DBObject writeMapInternal(Map<Object, Object> obj, DBObject dbo, TypeI
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()) {
Expand All @@ -669,6 +668,20 @@ protected DBObject writeMapInternal(Map<Object, Object> obj, DBObject dbo, TypeI
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.
Expand Down
Expand Up @@ -56,12 +56,15 @@
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;
Expand Down Expand Up @@ -1964,6 +1967,7 @@ public void convertsJava8DateTimeTypesToDateAndBack() {
assertThat(converter.read(TypeWithLocalDateTime.class, result).date, is(reference));
}


/**
* @see DATAMONGO-1128
*/
Expand Down Expand Up @@ -2001,6 +2005,68 @@ public void readsOptionalsCorrectly() {
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;
}
Expand Down Expand Up @@ -2303,4 +2369,50 @@ static class TypeWithOptional {
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);
}

}


}

0 comments on commit c353e02

Please sign in to comment.