DATAREDIS-768 - Polishing.
Added test with decimal and date map keys to verify those are flattened out correctly using the converters registered and updated documentation to point out limitation of map keys to simple types. Original Pull Request: #312
This commit is contained in:
@@ -21,8 +21,17 @@ import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -799,7 +808,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
continue;
|
||||
}
|
||||
|
||||
String currentPath = path + ".[" + entry.getKey() + "]";
|
||||
String currentPath = path + ".[" + mapMapKey(entry.getKey()) + "]";
|
||||
|
||||
if (!ClassUtils.isAssignable(mapValueType, entry.getValue().getClass())) {
|
||||
throw new MappingException(
|
||||
@@ -814,6 +823,15 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
private String mapMapKey(Object key) {
|
||||
|
||||
if (conversionService.canConvert(key.getClass(), byte[].class)) {
|
||||
return new String(conversionService.convert(key, byte[].class));
|
||||
}
|
||||
|
||||
return conversionService.convert(key, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path
|
||||
* @param mapType
|
||||
@@ -836,22 +854,8 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
continue;
|
||||
}
|
||||
|
||||
String regex = "^(" + Pattern.quote(path) + "\\.\\[)(.*?)(\\])";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
|
||||
Matcher matcher = pattern.matcher(entry.getKey());
|
||||
if (!matcher.find()) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Cannot extract map value for key '%s' in path '%s'.", entry.getKey(), path));
|
||||
}
|
||||
Object key = matcher.group(2);
|
||||
|
||||
Object key = extractMapKeyForPath(path, entry.getKey(), keyType);
|
||||
Class<?> typeToUse = getTypeHint(path + ".[" + key + "]", source.getBucket(), valueType);
|
||||
|
||||
if (!keyType.isAssignableFrom(key.getClass())) {
|
||||
key = conversionService.convert(key, keyType);
|
||||
}
|
||||
|
||||
target.put(key, fromBytes(entry.getValue(), typeToUse));
|
||||
}
|
||||
|
||||
@@ -876,16 +880,6 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
|
||||
for (String key : keys) {
|
||||
|
||||
String regex = "^(" + Pattern.quote(path) + "\\.\\[)(.*?)(\\])";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
|
||||
Matcher matcher = pattern.matcher(key);
|
||||
if (!matcher.find()) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Cannot extract map value for key '%s' in path '%s'.", key, path));
|
||||
}
|
||||
Object mapKey = matcher.group(2);
|
||||
|
||||
Bucket partial = source.getBucket().extract(key);
|
||||
|
||||
byte[] typeInfo = partial.get(key + "." + TYPE_HINT_ALIAS);
|
||||
@@ -893,18 +887,35 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
partial.put(TYPE_HINT_ALIAS, typeInfo);
|
||||
}
|
||||
|
||||
if (!keyType.isAssignableFrom(mapKey.getClass())) {
|
||||
mapKey = conversionService.convert(mapKey, keyType);
|
||||
}
|
||||
|
||||
Object value = readInternal(key, valueType, new RedisData(partial));
|
||||
|
||||
Object mapKey = extractMapKeyForPath(path, key, keyType);
|
||||
target.put(mapKey, value);
|
||||
}
|
||||
|
||||
return target.isEmpty() ? null : target;
|
||||
}
|
||||
|
||||
private Object extractMapKeyForPath(String path, String key, Class<?> targetType) {
|
||||
|
||||
String regex = "^(" + Pattern.quote(path) + "\\.\\[)(.*?)(\\])";
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
|
||||
Matcher matcher = pattern.matcher(key);
|
||||
if (!matcher.find()) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Cannot extract map value for key '%s' in path '%s'.", key, path));
|
||||
}
|
||||
|
||||
Object mapKey = matcher.group(2);
|
||||
|
||||
if (ClassUtils.isAssignable(targetType, mapKey.getClass())) {
|
||||
return mapKey;
|
||||
}
|
||||
|
||||
return conversionService.convert(toBytes(mapKey), targetType);
|
||||
}
|
||||
|
||||
private Class<?> getTypeHint(String path, Bucket bucket, Class<?> fallback) {
|
||||
|
||||
byte[] typeInfo = bucket.get(path + "." + TYPE_HINT_ALIAS);
|
||||
|
||||
Reference in New Issue
Block a user