DATADOC-98 - Deal with multi-dimensional arrays as property types.
This commit is contained in:
@@ -16,6 +16,17 @@
|
||||
|
||||
package org.springframework.data.mapping;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -30,168 +41,174 @@ import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class MappingBeanHelper {
|
||||
|
||||
protected static GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
|
||||
protected static SpelExpressionParser parser = new SpelExpressionParser();
|
||||
protected static Set<Class<?>> simpleTypes = Collections.newSetFromMap(new ConcurrentHashMap<Class<?>, Boolean>());
|
||||
protected static GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
|
||||
protected static SpelExpressionParser parser = new SpelExpressionParser();
|
||||
protected static Set<Class<?>> simpleTypes = Collections.newSetFromMap(new ConcurrentHashMap<Class<?>, Boolean>());
|
||||
|
||||
static {
|
||||
simpleTypes.add(boolean.class);
|
||||
simpleTypes.add(boolean[].class);
|
||||
simpleTypes.add(long.class);
|
||||
simpleTypes.add(long[].class);
|
||||
simpleTypes.add(short.class);
|
||||
simpleTypes.add(short[].class);
|
||||
simpleTypes.add(int.class);
|
||||
simpleTypes.add(int[].class);
|
||||
simpleTypes.add(byte.class);
|
||||
simpleTypes.add(byte[].class);
|
||||
simpleTypes.add(float.class);
|
||||
simpleTypes.add(float[].class);
|
||||
simpleTypes.add(double.class);
|
||||
simpleTypes.add(double[].class);
|
||||
simpleTypes.add(char.class);
|
||||
simpleTypes.add(char[].class);
|
||||
simpleTypes.add(Boolean.class);
|
||||
simpleTypes.add(Long.class);
|
||||
simpleTypes.add(Short.class);
|
||||
simpleTypes.add(Integer.class);
|
||||
simpleTypes.add(Byte.class);
|
||||
simpleTypes.add(Float.class);
|
||||
simpleTypes.add(Double.class);
|
||||
simpleTypes.add(Character.class);
|
||||
simpleTypes.add(String.class);
|
||||
simpleTypes.add(java.util.Date.class);
|
||||
simpleTypes.add(Locale.class);
|
||||
simpleTypes.add(Class.class);
|
||||
}
|
||||
static {
|
||||
simpleTypes.add(boolean.class);
|
||||
simpleTypes.add(boolean[].class);
|
||||
simpleTypes.add(long.class);
|
||||
simpleTypes.add(long[].class);
|
||||
simpleTypes.add(short.class);
|
||||
simpleTypes.add(short[].class);
|
||||
simpleTypes.add(int.class);
|
||||
simpleTypes.add(int[].class);
|
||||
simpleTypes.add(byte.class);
|
||||
simpleTypes.add(byte[].class);
|
||||
simpleTypes.add(float.class);
|
||||
simpleTypes.add(float[].class);
|
||||
simpleTypes.add(double.class);
|
||||
simpleTypes.add(double[].class);
|
||||
simpleTypes.add(char.class);
|
||||
simpleTypes.add(char[].class);
|
||||
simpleTypes.add(Boolean.class);
|
||||
simpleTypes.add(Long.class);
|
||||
simpleTypes.add(Short.class);
|
||||
simpleTypes.add(Integer.class);
|
||||
simpleTypes.add(Byte.class);
|
||||
simpleTypes.add(Float.class);
|
||||
simpleTypes.add(Double.class);
|
||||
simpleTypes.add(Character.class);
|
||||
simpleTypes.add(String.class);
|
||||
simpleTypes.add(java.util.Date.class);
|
||||
simpleTypes.add(Locale.class);
|
||||
simpleTypes.add(Class.class);
|
||||
}
|
||||
|
||||
public static GenericConversionService getConversionService() {
|
||||
return conversionService;
|
||||
}
|
||||
public static GenericConversionService getConversionService() {
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
public static void setConversionService(GenericConversionService conversionService) {
|
||||
MappingBeanHelper.conversionService = conversionService;
|
||||
}
|
||||
public static void setConversionService(GenericConversionService conversionService) {
|
||||
MappingBeanHelper.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public static Set<Class<?>> getSimpleTypes() {
|
||||
return simpleTypes;
|
||||
}
|
||||
public static Set<Class<?>> getSimpleTypes() {
|
||||
return simpleTypes;
|
||||
}
|
||||
|
||||
public static boolean isSimpleType(Class<?> type) {
|
||||
for (Class<?> clazz : simpleTypes) {
|
||||
if (type == clazz || type.isAssignableFrom(clazz)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return type.isEnum();
|
||||
}
|
||||
public static boolean isSimpleType(Class<?> type) {
|
||||
for (Class<?> clazz : simpleTypes) {
|
||||
if (type == clazz || type.isAssignableFrom(clazz)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return type.isEnum();
|
||||
}
|
||||
|
||||
public static <T> T constructInstance(PersistentEntity<T> entity,
|
||||
PreferredConstructor.ParameterValueProvider provider) {
|
||||
return constructInstance(entity, provider, new StandardEvaluationContext());
|
||||
}
|
||||
public static <T> T constructInstance(PersistentEntity<T> entity,
|
||||
PreferredConstructor.ParameterValueProvider provider) {
|
||||
return constructInstance(entity, provider, new StandardEvaluationContext());
|
||||
}
|
||||
|
||||
public static <T> T constructInstance(PersistentEntity<T> entity,
|
||||
PreferredConstructor.ParameterValueProvider provider,
|
||||
EvaluationContext spelCtx) {
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public static <T> T constructInstance(PersistentEntity<T> entity,
|
||||
PreferredConstructor.ParameterValueProvider provider,
|
||||
EvaluationContext spelCtx) {
|
||||
|
||||
PreferredConstructor<T> constructor = entity.getPreferredConstructor();
|
||||
if (null == constructor) {
|
||||
try {
|
||||
return BeanUtils.instantiateClass(entity.getType());
|
||||
} catch (BeanInstantiationException e) {
|
||||
throw new MappingInstantiationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
PreferredConstructor<T> constructor = entity.getPreferredConstructor();
|
||||
if (null == constructor) {
|
||||
try {
|
||||
Class<T> clazz = entity.getType();
|
||||
if (clazz.isArray()) {
|
||||
Class<?> ctype = clazz;
|
||||
int dims = 0;
|
||||
while (ctype.isArray()) {
|
||||
ctype = ctype.getComponentType();
|
||||
dims++;
|
||||
}
|
||||
return (T) Array.newInstance(clazz, dims);
|
||||
} else {
|
||||
return BeanUtils.instantiateClass(entity.getType());
|
||||
}
|
||||
} catch (BeanInstantiationException e) {
|
||||
throw new MappingInstantiationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
List<Object> params = new LinkedList<Object>();
|
||||
if (null != provider && constructor.getParameters().size() > 0) {
|
||||
for (PreferredConstructor.Parameter parameter : constructor.getParameters()) {
|
||||
Value v = parameter.getValue();
|
||||
Object obj;
|
||||
if (null != v) {
|
||||
Expression x = parser.parseExpression(v.value());
|
||||
obj = x.getValue(spelCtx);
|
||||
} else {
|
||||
obj = provider.getParameterValue(parameter);
|
||||
}
|
||||
params.add(obj);
|
||||
}
|
||||
}
|
||||
List<Object> params = new LinkedList<Object>();
|
||||
if (null != provider && constructor.getParameters().size() > 0) {
|
||||
for (PreferredConstructor.Parameter parameter : constructor.getParameters()) {
|
||||
Value v = parameter.getValue();
|
||||
Object obj;
|
||||
if (null != v) {
|
||||
Expression x = parser.parseExpression(v.value());
|
||||
obj = x.getValue(spelCtx);
|
||||
} else {
|
||||
obj = provider.getParameterValue(parameter);
|
||||
}
|
||||
params.add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
T obj = null;
|
||||
try {
|
||||
obj = BeanUtils.instantiateClass(constructor.getConstructor(), params.toArray());
|
||||
} catch (BeanInstantiationException e) {
|
||||
throw new MappingInstantiationException(e.getMessage(), e);
|
||||
}
|
||||
T obj = null;
|
||||
try {
|
||||
obj = BeanUtils.instantiateClass(constructor.getConstructor(), params.toArray());
|
||||
} catch (BeanInstantiationException e) {
|
||||
throw new MappingInstantiationException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static void setProperty(Object on,
|
||||
PersistentProperty property,
|
||||
Object value)
|
||||
throws IllegalAccessException, InvocationTargetException {
|
||||
setProperty(on, property, value, false);
|
||||
}
|
||||
public static void setProperty(Object on,
|
||||
PersistentProperty property,
|
||||
Object value)
|
||||
throws IllegalAccessException, InvocationTargetException {
|
||||
setProperty(on, property, value, false);
|
||||
}
|
||||
|
||||
public static void setProperty(Object on,
|
||||
PersistentProperty property,
|
||||
Object value,
|
||||
boolean fieldAccessOnly)
|
||||
throws IllegalAccessException, InvocationTargetException {
|
||||
public static void setProperty(Object on,
|
||||
PersistentProperty property,
|
||||
Object value,
|
||||
boolean fieldAccessOnly)
|
||||
throws IllegalAccessException, InvocationTargetException {
|
||||
|
||||
Field field = property.getField();
|
||||
Method setter = (null != property.getPropertyDescriptor() ? property.getPropertyDescriptor().getWriteMethod() : null);
|
||||
if (fieldAccessOnly || null == setter) {
|
||||
if (null != value && value.getClass().isAssignableFrom(field.getType())) {
|
||||
field.set(on, value);
|
||||
} else {
|
||||
field.set(on, conversionService.convert(value, field.getType()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
Field field = property.getField();
|
||||
Method setter = (null != property.getPropertyDescriptor() ? property.getPropertyDescriptor().getWriteMethod() : null);
|
||||
if (fieldAccessOnly || null == setter) {
|
||||
if (null != value && value.getClass().isAssignableFrom(field.getType())) {
|
||||
field.set(on, value);
|
||||
} else {
|
||||
field.set(on, conversionService.convert(value, field.getType()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Class<?>[] paramTypes = setter.getParameterTypes();
|
||||
if (null != value && paramTypes.length > 0 && !value.getClass().isAssignableFrom(paramTypes[0])) {
|
||||
setter.invoke(on, conversionService.convert(value, paramTypes[0]));
|
||||
} else {
|
||||
setter.invoke(on, value);
|
||||
}
|
||||
}
|
||||
Class<?>[] paramTypes = setter.getParameterTypes();
|
||||
if (null != value && paramTypes.length > 0 && !value.getClass().isAssignableFrom(paramTypes[0])) {
|
||||
setter.invoke(on, conversionService.convert(value, paramTypes[0]));
|
||||
} else {
|
||||
setter.invoke(on, value);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public static <T> T getProperty(Object from,
|
||||
PersistentProperty property,
|
||||
Class<T> type,
|
||||
boolean fieldAccessOnly)
|
||||
throws IllegalAccessException, InvocationTargetException {
|
||||
Object obj;
|
||||
Field field = property.getField();
|
||||
Method getter = (null != property.getPropertyDescriptor() ? property.getPropertyDescriptor().getReadMethod() : null);
|
||||
if (fieldAccessOnly || null == getter) {
|
||||
obj = field.get(from);
|
||||
} else {
|
||||
obj = getter.invoke(from);
|
||||
}
|
||||
if (null != obj && !obj.getClass().isAssignableFrom(type)) {
|
||||
return conversionService.convert(obj, type);
|
||||
} else {
|
||||
return (T) obj;
|
||||
}
|
||||
}
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public static <T> T getProperty(Object from,
|
||||
PersistentProperty property,
|
||||
Class<T> type,
|
||||
boolean fieldAccessOnly)
|
||||
throws IllegalAccessException, InvocationTargetException {
|
||||
Object obj;
|
||||
Field field = property.getField();
|
||||
Method getter = (null != property.getPropertyDescriptor() ? property.getPropertyDescriptor().getReadMethod() : null);
|
||||
if (fieldAccessOnly || null == getter) {
|
||||
obj = field.get(from);
|
||||
} else {
|
||||
obj = getter.invoke(from);
|
||||
}
|
||||
if (null != obj && !obj.getClass().isAssignableFrom(type)) {
|
||||
return conversionService.convert(obj, type);
|
||||
} else {
|
||||
return (T) obj;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public class ArrayTypeDiscoverer extends TypeDiscoverer {
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* @param typeVariableMap
|
||||
* @param parent
|
||||
* @param parent
|
||||
*/
|
||||
protected ArrayTypeDiscoverer(GenericArrayType type, TypeDiscoverer parent) {
|
||||
|
||||
Reference in New Issue
Block a user