From cbf9b6801e471ba250fb5908e02231af99d6009d Mon Sep 17 00:00:00 2001 From: Jon Brisbin Date: Mon, 18 Apr 2011 09:48:03 -0500 Subject: [PATCH] DATADOC-98 - Deal with multi-dimensional arrays as property types. --- .../data/mapping/MappingBeanHelper.java | 299 +++++++++--------- .../data/util/ArrayTypeDiscoverer.java | 2 +- 2 files changed, 159 insertions(+), 142 deletions(-) diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/MappingBeanHelper.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/MappingBeanHelper.java index 0be10d80a..fca548392 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/MappingBeanHelper.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/MappingBeanHelper.java @@ -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 * @author Oliver Gierke */ public abstract class MappingBeanHelper { - protected static GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService(); - protected static SpelExpressionParser parser = new SpelExpressionParser(); - protected static Set> simpleTypes = Collections.newSetFromMap(new ConcurrentHashMap, Boolean>()); + protected static GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService(); + protected static SpelExpressionParser parser = new SpelExpressionParser(); + protected static Set> simpleTypes = Collections.newSetFromMap(new ConcurrentHashMap, 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> getSimpleTypes() { - return simpleTypes; - } + public static Set> 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 constructInstance(PersistentEntity entity, - PreferredConstructor.ParameterValueProvider provider) { - return constructInstance(entity, provider, new StandardEvaluationContext()); - } + public static T constructInstance(PersistentEntity entity, + PreferredConstructor.ParameterValueProvider provider) { + return constructInstance(entity, provider, new StandardEvaluationContext()); + } - public static T constructInstance(PersistentEntity entity, - PreferredConstructor.ParameterValueProvider provider, - EvaluationContext spelCtx) { + @SuppressWarnings({"unchecked"}) + public static T constructInstance(PersistentEntity entity, + PreferredConstructor.ParameterValueProvider provider, + EvaluationContext spelCtx) { - PreferredConstructor constructor = entity.getPreferredConstructor(); - if (null == constructor) { - try { - return BeanUtils.instantiateClass(entity.getType()); - } catch (BeanInstantiationException e) { - throw new MappingInstantiationException(e.getMessage(), e); - } - } + PreferredConstructor constructor = entity.getPreferredConstructor(); + if (null == constructor) { + try { + Class 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 params = new LinkedList(); - 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 params = new LinkedList(); + 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 getProperty(Object from, - PersistentProperty property, - Class 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 getProperty(Object from, + PersistentProperty property, + Class 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; + } + } } diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/util/ArrayTypeDiscoverer.java b/spring-data-commons-core/src/main/java/org/springframework/data/util/ArrayTypeDiscoverer.java index c715aff29..414453cad 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/util/ArrayTypeDiscoverer.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/util/ArrayTypeDiscoverer.java @@ -15,7 +15,7 @@ public class ArrayTypeDiscoverer extends TypeDiscoverer { /** * @param type - * @param typeVariableMap + * @param parent * @param parent */ protected ArrayTypeDiscoverer(GenericArrayType type, TypeDiscoverer parent) {