DATAREDIS-509 - Fix handling of primitive arrays in MappingRedisConverter.

We now correctly convert arrays of primitive values.

Original pull request: #196.
This commit is contained in:
Christoph Strobl
2016-05-06 14:49:33 +02:00
committed by Mark Paluch
parent f2cee266e3
commit 16b692c899
4 changed files with 64 additions and 9 deletions

View File

@@ -17,11 +17,11 @@ package org.springframework.data.redis.core.convert;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
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;
@@ -426,7 +426,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
persistentProperty.getTypeInformation().getComponentType(), sink);
} else if (property.getClass().isArray()) {
writeCollection(keyspace, propertyStringPath, Arrays.asList((Object[]) property),
writeCollection(keyspace, propertyStringPath, CollectionUtils.arrayToList(property),
persistentProperty.getTypeInformation().getComponentType(), sink);
} else {
@@ -592,7 +592,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
}
}
return isArray ? target.toArray((Object[]) Array.newInstance(valueType, target.size())) : target;
return isArray ? toArray(target, collectionType, valueType) : target;
}
/**
@@ -749,6 +749,30 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
return conversionService.convert(source, type);
}
/**
* Converts a given {@link Collection} into an array considering primitive types.
*
* @param source {@link Collection} of values to be added to the array.
* @param arrayType {@link Class} of array.
* @param valueType to be used for conversion before setting the actual value.
* @return
*/
private Object toArray(Collection<Object> source, Class<?> arrayType, Class<?> valueType) {
if (!ClassUtils.isPrimitiveArray(arrayType)) {
return source.toArray((Object[]) Array.newInstance(valueType, source.size()));
}
Object targetArray = Array.newInstance(valueType, source.size());
Iterator<Object> iterator = source.iterator();
int i = 0;
while (iterator.hasNext()) {
Array.set(targetArray, i, conversionService.convert(iterator.next(), valueType));
i++;
}
return targetArray;
}
/**
* Set {@link CustomConversions} to be applied.
*

View File

@@ -15,10 +15,8 @@
*/
package org.springframework.data.redis.core.convert;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -39,6 +37,7 @@ import org.springframework.data.redis.core.mapping.RedisPersistentEntity;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
/**
* {@link IndexResolver} implementation considering properties annotated with {@link Indexed} or paths set up in
@@ -124,17 +123,18 @@ public class PathIndexResolver implements IndexResolver {
if (Iterable.class.isAssignableFrom(propertyValue.getClass())) {
iterable = (Iterable) propertyValue;
} else if (propertyValue.getClass().isArray()) {
iterable = Arrays.asList((Object[]) propertyValue);
iterable = CollectionUtils.arrayToList(propertyValue);
} else {
throw new RuntimeException("Don't know how to handle " + propertyValue.getClass() + " type of collection");
throw new RuntimeException(
"Don't know how to handle " + propertyValue.getClass() + " type of collection");
}
for (Object listValue : iterable) {
if (listValue != null) {
TypeInformation<?> typeToUse = updateTypeHintForActualValue(typeHint, listValue);
indexes.addAll(
doResolveIndexesFor(keyspace, currentPath, typeToUse.getActualType(), persistentProperty, listValue));
indexes.addAll(doResolveIndexesFor(keyspace, currentPath, typeToUse.getActualType(), persistentProperty,
listValue));
}
}
}

View File

@@ -167,6 +167,7 @@ public class ConversionTestEntities {
Object[] arrayOfObject;
String[] arrayOfSimpleTypes;
Species[] arrayOfCompexTypes;
int[] arrayOfPrimitives;
}
static class TypeWithObjectValueTypes {

View File

@@ -1581,6 +1581,36 @@ public class MappingRedisConverterUnitTests {
assertThat(result.list.get(2), instanceOf(Date.class));
}
/**
* @see DATAREDIS-509
*/
@Test
public void writeHandlesArraysOfPrimitivesProperly() {
Map<String, String> source = new LinkedHashMap<String, String>();
source.put("arrayOfPrimitives.[0]", "1");
source.put("arrayOfPrimitives.[1]", "2");
source.put("arrayOfPrimitives.[2]", "3");
WithArrays target = read(WithArrays.class, source);
assertThat(target.arrayOfPrimitives[0], is(1));
assertThat(target.arrayOfPrimitives[1], is(2));
assertThat(target.arrayOfPrimitives[2], is(3));
}
/**
* @see DATAREDIS-509
*/
@Test
public void readHandlesArraysOfPrimitivesProperly() {
WithArrays source = new WithArrays();
source.arrayOfPrimitives = new int[] { 1, 2, 3 };
assertThat(write(source).getBucket(), isBucket().containingUtf8String("arrayOfPrimitives.[0]", "1")
.containingUtf8String("arrayOfPrimitives.[1]", "2").containingUtf8String("arrayOfPrimitives.[2]", "3"));
}
private RedisData write(Object source) {
RedisData rdo = new RedisData();