Browse Source

moved applyIndexedObject internal, now invoked inside forObject static factory method

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@4346 50f2f4bb-b051-0410-bef5-90022cba6387
pull/1/merge
Keith Donald 15 years ago
parent
commit
c9789d3a37
  1. 1
      org.springframework.core/src/main/java/org/springframework/core/convert/ConversionException.java
  2. 1
      org.springframework.core/src/main/java/org/springframework/core/convert/ConversionFailedException.java
  3. 116
      org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java
  4. 3
      org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToCollectionConverter.java
  5. 2
      org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToArrayConverter.java
  6. 5
      org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToCollectionConverter.java
  7. 2
      org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToObjectConverter.java
  8. 3
      org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultConversionService.java
  9. 8
      org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java
  10. 5
      org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToMapConverter.java
  11. 3
      org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollectionConverter.java
  12. 4
      org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java
  13. 2
      org.springframework.core/src/main/java/org/springframework/core/convert/support/PropertyTypeDescriptor.java
  14. 3
      org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollectionConverter.java
  15. 2
      org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToEnumConverterFactory.java
  16. 6
      org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java

1
org.springframework.core/src/main/java/org/springframework/core/convert/ConversionException.java

@ -24,6 +24,7 @@ import org.springframework.core.NestedRuntimeException; @@ -24,6 +24,7 @@ import org.springframework.core.NestedRuntimeException;
* @author Keith Donald
* @since 3.0
*/
@SuppressWarnings("serial")
public abstract class ConversionException extends NestedRuntimeException {
/**

1
org.springframework.core/src/main/java/org/springframework/core/convert/ConversionFailedException.java

@ -25,6 +25,7 @@ import org.springframework.util.ObjectUtils; @@ -25,6 +25,7 @@ import org.springframework.util.ObjectUtils;
* @author Juergen Hoeller
* @since 3.0
*/
@SuppressWarnings("serial")
public final class ConversionFailedException extends ConversionException {
private final TypeDescriptor sourceType;

116
org.springframework.core/src/main/java/org/springframework/core/convert/TypeDescriptor.java

@ -138,10 +138,11 @@ public class TypeDescriptor { @@ -138,10 +138,11 @@ public class TypeDescriptor {
return NULL;
}
if (object instanceof Collection<?>) {
return new TypeDescriptor(object.getClass(), CollectionUtils.findCommonElementType((Collection<?>) object));
return new TypeDescriptor(object.getClass(), findCommonElement((Collection<?>) object));
}
else if (object instanceof Map<?, ?>) {
return new TypeDescriptor(object.getClass(), CollectionUtils.findCommonElementType(((Map<?, ?>) object).keySet()), CollectionUtils.findCommonElementType(((Map<?, ?>) object).values()));
Map<?, ?> map = (Map<?, ?>) object;
return new TypeDescriptor(map.getClass(), findCommonElement(map.keySet()), findCommonElement(map.values()));
}
else {
return valueOf(object.getClass());
@ -341,37 +342,6 @@ public class TypeDescriptor { @@ -341,37 +342,6 @@ public class TypeDescriptor {
public MethodParameter getMethodParameter() {
return methodParameter;
}
/**
* Create a copy of this nested type descriptor and apply the specific type information from the indexed value, if necessary.
* Used to support collection and map indexing scenarios, where the indexer has a reference to the indexed type descriptor but needs to ensure its type actually represents the indexed object type.
* This is necessary to support type conversion during collection and map binding operations where generic information may not be available.
*/
public TypeDescriptor applyIndexedObject(Object object) {
if (object == null) {
return this;
}
if (isCollection() && Object.class.equals(getElementType())) {
Collection<?> collection = (Collection<?>) object;
if (collection.size() > 0) {
return new TypeDescriptor(object.getClass(), CollectionUtils.findCommonElementType((Collection<?>) object), methodParameter, field, fieldNestingLevel, annotations);
} else {
return this;
}
}
else if (isMap() && Object.class.equals(getMapKeyType()) && Object.class.equals(getMapValueType())) {
Map<?, ?> map = (Map<?, ?>) object;
if (map.size() > 0) {
return new TypeDescriptor(object.getClass(), CollectionUtils.findCommonElementType(((Map<?, ?>) object).keySet()),
CollectionUtils.findCommonElementType(((Map<?, ?>) object).values()), methodParameter, field, fieldNestingLevel, annotations);
} else {
return this;
}
}
else {
return this;
}
}
// extending Object
@ -544,6 +514,20 @@ public class TypeDescriptor { @@ -544,6 +514,20 @@ public class TypeDescriptor {
methodParameter.increaseNestingLevel();
return methodParameter;
}
private static Object findCommonElement(Collection<?> values) {
Object candidate = null;
for (Object value : values) {
if (value != null) {
if (candidate == null) {
candidate = value;
} else if (candidate.getClass() != value.getClass()) {
return null;
}
}
}
return candidate;
}
// internal constructors
@ -555,46 +539,44 @@ public class TypeDescriptor { @@ -555,46 +539,44 @@ public class TypeDescriptor {
this.type = type;
}
private TypeDescriptor(Class<?> collectionType, Class<?> elementType) {
this.type = collectionType;
if (elementType == null) {
elementType = Object.class;
}
this.elementType = TypeDescriptor.valueOf(elementType);
private TypeDescriptor(Class<?> nestedType, Field field, int nestingLevel) {
this.type = nestedType;
this.field = field;
this.fieldNestingLevel = nestingLevel;
}
private TypeDescriptor(Class<?> mapType, Class<?> keyType, Class<?> valueType) {
public TypeDescriptor(Class<?> mapType, Object commonKey, Object commonValue) {
this.type = mapType;
if (keyType == null) {
keyType = Object.class;
}
if (valueType == null) {
valueType = Object.class;
}
this.mapKeyType = TypeDescriptor.valueOf(keyType);
this.mapValueType = TypeDescriptor.valueOf(valueType);
this.mapKeyType = applyIndexedObject(commonKey);
this.mapValueType = applyIndexedObject(commonValue);
}
private TypeDescriptor(Class<?> collectionType, Class<?> elementType, MethodParameter methodParameter, Field field, int fieldNestingLevel, Annotation[] annotations) {
this(collectionType, elementType);
this.methodParameter = methodParameter;
this.field = field;
this.fieldNestingLevel = fieldNestingLevel;
this.annotations = annotations;
}
private TypeDescriptor(Class<?> mapType, Class<?> keyType, Class<?> valueType, MethodParameter methodParameter, Field field, int fieldNestingLevel, Annotation[] annotations) {
this(mapType, keyType, valueType);
this.methodParameter = methodParameter;
this.field = field;
this.fieldNestingLevel = fieldNestingLevel;
this.annotations = annotations;
public TypeDescriptor(Class<?> collectionType, Object commonElement) {
this.type = collectionType;
this.elementType = applyIndexedObject(commonElement);
}
private TypeDescriptor(Class<?> nestedType, Field field, int nestingLevel) {
this.type = nestedType;
this.field = field;
this.fieldNestingLevel = nestingLevel;
private TypeDescriptor applyIndexedObject(Object object) {
if (object == null) {
return TypeDescriptor.valueOf(Object.class);
}
if (object instanceof Collection<?>) {
Collection<?> collection = (Collection<?>) object;
if (collection.size() == 0) {
return TypeDescriptor.valueOf(Object.class);
}
return new TypeDescriptor(object.getClass(), findCommonElement((Collection<?>) object));
}
else if (object instanceof Map<?, ?>) {
Map<?, ?> map = (Map<?, ?>) object;
if (map.size() == 0) {
return TypeDescriptor.valueOf(Object.class);
}
return new TypeDescriptor(object.getClass(), findCommonElement(map.keySet()), findCommonElement(map.values()));
}
else {
return TypeDescriptor.valueOf(object.getClass());
}
}
}

3
org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToCollectionConverter.java

@ -52,12 +52,13 @@ final class ArrayToCollectionConverter implements ConditionalGenericConverter { @@ -52,12 +52,13 @@ final class ArrayToCollectionConverter implements ConditionalGenericConverter {
return this.conversionService.canConvert(sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor());
}
@SuppressWarnings("unchecked")
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
return null;
}
int length = Array.getLength(source);
Collection target = CollectionFactory.createCollection(targetType.getType(), length);
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), length);
for (int i = 0; i < length; i++) {
Object sourceElement = Array.get(source, i);
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor());

2
org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToArrayConverter.java

@ -64,7 +64,7 @@ final class CollectionToArrayConverter implements ConditionalGenericConverter { @@ -64,7 +64,7 @@ final class CollectionToArrayConverter implements ConditionalGenericConverter {
Object array = Array.newInstance(targetType.getElementType(), sourceCollection.size());
int i = 0;
for (Object sourceElement : sourceCollection) {
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor().applyIndexedObject(sourceElement), targetType.getElementTypeDescriptor());
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor());
Array.set(array, i++, targetElement);
}
return array;

5
org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToCollectionConverter.java

@ -57,14 +57,15 @@ final class CollectionToCollectionConverter implements ConditionalGenericConvert @@ -57,14 +57,15 @@ final class CollectionToCollectionConverter implements ConditionalGenericConvert
return this.conversionService.canConvert(sourceElementType, targetElementType);
}
@SuppressWarnings("unchecked")
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
return null;
}
Collection<?> sourceCollection = (Collection<?>) source;
Collection target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), sourceCollection.size());
for (Object sourceElement : sourceCollection) {
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor().applyIndexedObject(sourceElement), targetType.getElementTypeDescriptor());
Object targetElement = this.conversionService.convert(sourceElement, sourceType.getElementTypeDescriptor(), targetType.getElementTypeDescriptor());
target.add(targetElement);
}
return target;

2
org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToObjectConverter.java

@ -59,7 +59,7 @@ final class CollectionToObjectConverter implements ConditionalGenericConverter { @@ -59,7 +59,7 @@ final class CollectionToObjectConverter implements ConditionalGenericConverter {
return null;
}
Object firstElement = sourceCollection.iterator().next();
return this.conversionService.convert(firstElement, sourceType.getElementTypeDescriptor().applyIndexedObject(firstElement), targetType);
return this.conversionService.convert(firstElement, sourceType.getElementTypeDescriptor(), targetType);
}
}

3
org.springframework.core/src/main/java/org/springframework/core/convert/support/DefaultConversionService.java

@ -16,9 +16,6 @@ @@ -16,9 +16,6 @@
package org.springframework.core.convert.support;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.ConverterRegistry;
/**
* A specialization of {@link GenericConversionService} configured by default with
* converters appropriate for most applications.

8
org.springframework.core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java

@ -481,10 +481,10 @@ public class GenericConversionService implements ConversionService, ConverterReg @@ -481,10 +481,10 @@ public class GenericConversionService implements ConversionService, ConverterReg
private final ConvertiblePair typeInfo;
private final Converter converter;
private final Converter<Object, Object> converter;
public ConverterAdapter(ConvertiblePair typeInfo, Converter<?, ?> converter) {
this.converter = converter;
this.converter = (Converter<Object, Object>) converter;
this.typeInfo = typeInfo;
}
@ -511,10 +511,10 @@ public class GenericConversionService implements ConversionService, ConverterReg @@ -511,10 +511,10 @@ public class GenericConversionService implements ConversionService, ConverterReg
private final ConvertiblePair typeInfo;
private final ConverterFactory converterFactory;
private final ConverterFactory<Object, Object> converterFactory;
public ConverterFactoryAdapter(ConvertiblePair typeInfo, ConverterFactory<?, ?> converterFactory) {
this.converterFactory = converterFactory;
this.converterFactory = (ConverterFactory<Object, Object>) converterFactory;
this.typeInfo = typeInfo;
}

5
org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToMapConverter.java

@ -55,6 +55,7 @@ final class MapToMapConverter implements ConditionalGenericConverter { @@ -55,6 +55,7 @@ final class MapToMapConverter implements ConditionalGenericConverter {
TypeDescriptor targetValueType = targetType.getMapValueTypeDescriptor();
if (Object.class.equals(sourceKeyType.getType()) && Object.class.equals(sourceValueType.getType())
|| Object.class.equals(targetKeyType.getType()) && Object.class.equals(targetValueType.getType())) {
// catches the empty map case
return true;
}
return this.conversionService.canConvert(sourceType.getMapKeyTypeDescriptor(), targetType.getMapKeyTypeDescriptor()) &&
@ -78,8 +79,8 @@ final class MapToMapConverter implements ConditionalGenericConverter { @@ -78,8 +79,8 @@ final class MapToMapConverter implements ConditionalGenericConverter {
for (Map.Entry<Object, Object> entry : sourceMap.entrySet()) {
Object sourceKey = entry.getKey();
Object sourceValue = entry.getValue();
Object targetKey = this.conversionService.convert(sourceKey, sourceType.getMapKeyTypeDescriptor().applyIndexedObject(sourceKey), targetType.getMapKeyTypeDescriptor());
Object targetValue = this.conversionService.convert(sourceValue, sourceType.getMapValueTypeDescriptor().applyIndexedObject(sourceValue), targetType.getMapValueTypeDescriptor());
Object targetKey = this.conversionService.convert(sourceKey, sourceType.getMapKeyTypeDescriptor(), targetType.getMapKeyTypeDescriptor());
Object targetValue = this.conversionService.convert(sourceValue, sourceType.getMapValueTypeDescriptor(), targetType.getMapValueTypeDescriptor());
targetMap.put(targetKey, targetValue);
}
}

3
org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollectionConverter.java

@ -49,11 +49,12 @@ final class ObjectToCollectionConverter implements ConditionalGenericConverter { @@ -49,11 +49,12 @@ final class ObjectToCollectionConverter implements ConditionalGenericConverter {
return this.conversionService.canConvert(sourceType, targetType.getElementTypeDescriptor());
}
@SuppressWarnings("unchecked")
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
return null;
}
Collection target = CollectionFactory.createCollection(targetType.getType(), 1);
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), 1);
TypeDescriptor elementType = targetType.getElementTypeDescriptor();
// Avoid potential recursion...
if (!Collection.class.isAssignableFrom(elementType.getType())) {

4
org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToObjectConverter.java

@ -44,8 +44,8 @@ import org.springframework.util.ReflectionUtils; @@ -44,8 +44,8 @@ import org.springframework.util.ReflectionUtils;
final class ObjectToObjectConverter implements ConditionalGenericConverter {
public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {
Class source = sourceType.getObjectType();
Class target = targetType.getObjectType();
Class<?> source = sourceType.getObjectType();
Class<?> target = targetType.getObjectType();
return (!source.equals(target) && hasValueOfMethodOrConstructor(target, source));
}

2
org.springframework.core/src/main/java/org/springframework/core/convert/support/PropertyTypeDescriptor.java

@ -20,11 +20,9 @@ import java.beans.PropertyDescriptor; @@ -20,11 +20,9 @@ import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.core.GenericCollectionTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.util.ReflectionUtils;

3
org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollectionConverter.java

@ -48,13 +48,14 @@ final class StringToCollectionConverter implements ConditionalGenericConverter { @@ -48,13 +48,14 @@ final class StringToCollectionConverter implements ConditionalGenericConverter {
return this.conversionService.canConvert(sourceType, targetType.getElementTypeDescriptor());
}
@SuppressWarnings("unchecked")
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
return null;
}
String string = (String) source;
String[] fields = StringUtils.commaDelimitedListToStringArray(string);
Collection target = CollectionFactory.createCollection(targetType.getType(), fields.length);
Collection<Object> target = CollectionFactory.createCollection(targetType.getType(), fields.length);
for (String sourceElement : fields) {
Object targetElement = this.conversionService.convert(sourceElement.trim(), sourceType, targetType.getElementTypeDescriptor());
target.add(targetElement);

2
org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToEnumConverterFactory.java

@ -25,7 +25,7 @@ import org.springframework.core.convert.converter.ConverterFactory; @@ -25,7 +25,7 @@ import org.springframework.core.convert.converter.ConverterFactory;
* @author Keith Donald
* @since 3.0
*/
@SuppressWarnings("unchecked")
@SuppressWarnings({ "unchecked", "rawtypes" })
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {

6
org.springframework.expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java

@ -93,7 +93,7 @@ public class Indexer extends SpelNodeImpl { @@ -93,7 +93,7 @@ public class Indexer extends SpelNodeImpl {
Object possiblyConvertedKey = index;
possiblyConvertedKey = state.convertValue(index, targetObjectTypeDescriptor.getMapKeyTypeDescriptor());
Object o = ((Map<?, ?>) targetObject).get(possiblyConvertedKey);
return new TypedValue(o, targetObjectTypeDescriptor.getMapValueTypeDescriptor().applyIndexedObject(o));
return new TypedValue(o, targetObjectTypeDescriptor.getMapValueTypeDescriptor());
}
if (targetObject == null) {
@ -105,7 +105,7 @@ public class Indexer extends SpelNodeImpl { @@ -105,7 +105,7 @@ public class Indexer extends SpelNodeImpl {
int idx = (Integer)state.convertValue(index, TypeDescriptor.valueOf(Integer.class));
if (targetObject.getClass().isArray()) {
Object arrayElement = accessArrayElement(targetObject, idx);
return new TypedValue(arrayElement, targetObjectTypeDescriptor.getElementTypeDescriptor().applyIndexedObject(arrayElement));
return new TypedValue(arrayElement, targetObjectTypeDescriptor.getElementTypeDescriptor());
} else if (targetObject instanceof Collection) {
Collection c = (Collection) targetObject;
if (idx >= c.size()) {
@ -116,7 +116,7 @@ public class Indexer extends SpelNodeImpl { @@ -116,7 +116,7 @@ public class Indexer extends SpelNodeImpl {
int pos = 0;
for (Object o : c) {
if (pos == idx) {
return new TypedValue(o, targetObjectTypeDescriptor.getElementTypeDescriptor().applyIndexedObject(o));
return new TypedValue(o, targetObjectTypeDescriptor.getElementTypeDescriptor());
}
pos++;
}

Loading…
Cancel
Save