conversion service helper tests - part 1
This commit is contained in:
@@ -32,7 +32,7 @@ public class ConversionExecutionException extends ConversionException {
|
||||
/**
|
||||
* The source type we tried to convert the value from.
|
||||
*/
|
||||
private TypeDescriptor sourceType;
|
||||
private Class<?> sourceType;
|
||||
|
||||
/**
|
||||
* The target type we tried to convert the value to.
|
||||
@@ -46,7 +46,7 @@ public class ConversionExecutionException extends ConversionException {
|
||||
* @param targetType the value's target type
|
||||
* @param cause the cause of the conversion failure
|
||||
*/
|
||||
public ConversionExecutionException(Object value, TypeDescriptor sourceType, TypeDescriptor targetType, Throwable cause) {
|
||||
public ConversionExecutionException(Object value, Class<?> sourceType, TypeDescriptor targetType, Throwable cause) {
|
||||
super(defaultMessage(value, sourceType, targetType, cause), cause);
|
||||
this.value = value;
|
||||
this.sourceType = sourceType;
|
||||
@@ -60,7 +60,7 @@ public class ConversionExecutionException extends ConversionException {
|
||||
* @param targetType the value's target type
|
||||
* @param message a descriptive message of what went wrong.
|
||||
*/
|
||||
public ConversionExecutionException(Object value, TypeDescriptor sourceType, TypeDescriptor targetType, String message) {
|
||||
public ConversionExecutionException(Object value, Class<?> sourceType, TypeDescriptor targetType, String message) {
|
||||
super(message);
|
||||
this.value = value;
|
||||
this.sourceType = sourceType;
|
||||
@@ -77,7 +77,7 @@ public class ConversionExecutionException extends ConversionException {
|
||||
/**
|
||||
* Returns the source type we tried to convert the value from.
|
||||
*/
|
||||
public TypeDescriptor getSourceType() {
|
||||
public Class<?> getSourceType() {
|
||||
return sourceType;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public class ConversionExecutionException extends ConversionException {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
private static String defaultMessage(Object value, TypeDescriptor sourceType, TypeDescriptor targetType, Throwable cause) {
|
||||
private static String defaultMessage(Object value, Class<?> sourceType, TypeDescriptor targetType, Throwable cause) {
|
||||
return "Unable to convert value " + StylerUtils.style(value) + " from type [" + sourceType.getName()
|
||||
+ "] to type [" + targetType.getName() + "]; reason = '" + cause.getMessage() + "'";
|
||||
}
|
||||
|
||||
@@ -25,6 +25,14 @@ package org.springframework.core.convert;
|
||||
*/
|
||||
public interface ConversionService {
|
||||
|
||||
/**
|
||||
* Returns true if objects of sourceType can be converted to targetType.
|
||||
* @param source the source to convert from (may be null)
|
||||
* @param targetType the target type to convert to
|
||||
* @return true if a conversion can be performed, false if not
|
||||
*/
|
||||
public boolean canConvert(Class<?> sourceType, TypeDescriptor targetType);
|
||||
|
||||
/**
|
||||
* Returns true if the source can be converted to targetType.
|
||||
* @param source the source to convert from (may be null)
|
||||
|
||||
@@ -17,40 +17,41 @@ package org.springframework.core.convert.service;
|
||||
|
||||
import org.springframework.core.convert.ConversionExecutionException;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
abstract class AbstractCollectionConverter implements ConversionExecutor {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
private TypeDescriptor sourceCollectionType;
|
||||
|
||||
private TypeDescriptor targetCollectionType;
|
||||
|
||||
private GenericConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
public AbstractCollectionConverter(TypeDescriptor sourceCollectionType, TypeDescriptor targetCollectionType, GenericConversionService conversionService) {
|
||||
public AbstractCollectionConverter(TypeDescriptor sourceCollectionType, TypeDescriptor targetCollectionType, ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
this.sourceCollectionType = sourceCollectionType;
|
||||
this.targetCollectionType = targetCollectionType;
|
||||
this.conversionService = conversionService;
|
||||
this.elementConverter = createElementConverter();
|
||||
}
|
||||
|
||||
private ConversionExecutor createElementConverter() {
|
||||
Class<?> sourceElementType = getSourceType().getElementType();
|
||||
Class<?> targetElementType = getTargetType().getElementType();
|
||||
return (sourceElementType != null && targetElementType != null) ? conversionService.getElementConverter(sourceElementType, targetElementType) : null;
|
||||
}
|
||||
|
||||
protected TypeDescriptor getSourceType() {
|
||||
return sourceCollectionType;
|
||||
Class<?> sourceElementType = sourceCollectionType.getElementType();
|
||||
Class<?> targetElementType = targetCollectionType.getElementType();
|
||||
if (sourceElementType != null && targetElementType != null) {
|
||||
elementConverter = conversionService.getConversionExecutor(sourceElementType, TypeDescriptor.valueOf(targetElementType));
|
||||
} else {
|
||||
elementConverter = NoOpConversionExecutor.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
protected TypeDescriptor getTargetType() {
|
||||
return targetCollectionType;
|
||||
protected Class<?> getTargetCollectionType() {
|
||||
return targetCollectionType.getType();
|
||||
}
|
||||
|
||||
protected Class<?> getTargetElementType() {
|
||||
return targetCollectionType.getElementType();
|
||||
}
|
||||
|
||||
protected GenericConversionService getConversionService() {
|
||||
protected ConversionService getConversionService() {
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
@@ -62,7 +63,7 @@ abstract class AbstractCollectionConverter implements ConversionExecutor {
|
||||
try {
|
||||
return doExecute(source);
|
||||
} catch (Exception e) {
|
||||
throw new ConversionExecutionException(source, sourceCollectionType, targetCollectionType, e);
|
||||
throw new ConversionExecutionException(source, sourceCollectionType.getType(), targetCollectionType, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,9 +33,10 @@ class ArrayToArray extends AbstractCollectionConverter {
|
||||
super(sourceArrayType, targetArrayType, conversionService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object doExecute(Object sourceArray) throws Exception {
|
||||
int length = Array.getLength(sourceArray);
|
||||
Object targetArray = Array.newInstance(getTargetType().getElementType(), length);
|
||||
Object targetArray = Array.newInstance(getTargetElementType(), length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object value = Array.get(sourceArray, i);
|
||||
Array.set(targetArray, i, getElementConverter().execute(value));
|
||||
|
||||
@@ -45,16 +45,12 @@ class ArrayToCollection extends AbstractCollectionConverter {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object doExecute(Object sourceArray) throws Exception {
|
||||
Class implClass = CollectionConversionUtils.getImpl(getTargetType().getType());
|
||||
Class implClass = CollectionConversionUtils.getImpl(getTargetCollectionType());
|
||||
Collection collection = (Collection) implClass.newInstance();
|
||||
int length = Array.getLength(sourceArray);
|
||||
ConversionExecutor converter = getElementConverter();
|
||||
ConversionExecutor elementConverter = getElementConverter();
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object value = Array.get(sourceArray, i);
|
||||
if (converter != null) {
|
||||
value = converter.execute(value);
|
||||
}
|
||||
collection.add(value);
|
||||
collection.add(elementConverter.execute(Array.get(sourceArray, i)));
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.core.convert.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -24,7 +25,7 @@ import java.util.TreeSet;
|
||||
|
||||
class CollectionConversionUtils {
|
||||
|
||||
static Class<?> getImpl(Class<?> targetClass) {
|
||||
public static Class<?> getImpl(Class<?> targetClass) {
|
||||
if (targetClass.isInterface()) {
|
||||
if (List.class.equals(targetClass)) {
|
||||
return ArrayList.class;
|
||||
@@ -32,6 +33,8 @@ class CollectionConversionUtils {
|
||||
return LinkedHashSet.class;
|
||||
} else if (SortedSet.class.equals(targetClass)) {
|
||||
return TreeSet.class;
|
||||
} else if (Collection.class.equals(targetClass)) {
|
||||
return ArrayList.class;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported collection interface [" + targetClass.getName() + "]");
|
||||
}
|
||||
|
||||
@@ -46,19 +46,30 @@ class CollectionToArray extends AbstractCollectionConverter {
|
||||
@Override
|
||||
protected Object doExecute(Object source) throws Exception {
|
||||
Collection<?> collection = (Collection<?>) source;
|
||||
Class<?> targetComponentType = getTargetType().getElementType();
|
||||
Object array = Array.newInstance(targetComponentType, collection.size());
|
||||
Object array = Array.newInstance(getTargetElementType(), collection.size());
|
||||
int i = 0;
|
||||
ConversionExecutor converter = getElementConverter();
|
||||
ConversionExecutor elementConverter = getElementConverter(collection);
|
||||
for (Iterator<?> it = collection.iterator(); it.hasNext(); i++) {
|
||||
Object value = it.next();
|
||||
if (converter == null) {
|
||||
converter = getConversionService().getElementConverter(value.getClass(), targetComponentType);
|
||||
}
|
||||
value = converter.execute(value);
|
||||
value = elementConverter.execute(value);
|
||||
Array.set(array, i, value);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private ConversionExecutor getElementConverter(Collection<?> target) {
|
||||
ConversionExecutor elementConverter = getElementConverter();
|
||||
if (elementConverter == NoOpConversionExecutor.INSTANCE && !target.isEmpty()) {
|
||||
Iterator<?> it = target.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object value = it.next();
|
||||
if (value != null) {
|
||||
elementConverter = getConversionService().getConversionExecutor(value.getClass(), TypeDescriptor.valueOf(getTargetElementType()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return elementConverter;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,13 +37,13 @@ class CollectionToCollection extends AbstractCollectionConverter {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object doExecute(Object source) throws Exception {
|
||||
Collection sourceCollection = (Collection) source;
|
||||
Class targetCollectionType = getTargetType().getType();
|
||||
Class targetCollectionType = getTargetCollectionType();
|
||||
Class implClass = CollectionConversionUtils.getImpl(targetCollectionType);
|
||||
Collection targetCollection = (Collection) implClass.newInstance();
|
||||
ConversionExecutor elementConverter = getElementConverter();
|
||||
Class elementType;
|
||||
if (elementConverter == null) {
|
||||
elementType = getTargetType().getElementType();
|
||||
elementType = getTargetElementType();
|
||||
} else {
|
||||
elementType = null;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ class CollectionToCollection extends AbstractCollectionConverter {
|
||||
while (it.hasNext()) {
|
||||
Object value = it.next();
|
||||
if (elementConverter == null && elementType != null) {
|
||||
elementConverter = getConversionService().getElementConverter(value.getClass(), elementType);
|
||||
elementConverter = getConversionService().getConversionExecutor(value.getClass(), TypeDescriptor.valueOf(elementType));
|
||||
}
|
||||
value = elementConverter.execute(value);
|
||||
targetCollection.add(value);
|
||||
|
||||
@@ -158,6 +158,10 @@ public class GenericConversionService implements ConversionService {
|
||||
|
||||
// implementing ConversionService
|
||||
|
||||
public boolean canConvert(Class<?> source, TypeDescriptor targetType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean canConvert(Object source, TypeDescriptor targetType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class MapToMap implements ConversionExecutor {
|
||||
}
|
||||
return targetMap;
|
||||
} catch (Exception e) {
|
||||
throw new ConversionExecutionException(source, sourceType, targetType, e);
|
||||
throw new ConversionExecutionException(source, sourceType.getType(), targetType, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2004-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.core.convert.service;
|
||||
|
||||
import org.springframework.core.convert.ConversionExecutionException;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
|
||||
class NoOpConversionExecutor implements ConversionExecutor {
|
||||
|
||||
public static final ConversionExecutor INSTANCE = new NoOpConversionExecutor();
|
||||
|
||||
private NoOpConversionExecutor() {
|
||||
|
||||
}
|
||||
|
||||
public Object execute(Object source) throws ConversionExecutionException {
|
||||
return source;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,9 +30,9 @@ class StaticConversionExecutor implements ConversionExecutor {
|
||||
|
||||
private final Converter converter;
|
||||
|
||||
public StaticConversionExecutor(TypeDescriptor sourceClass, TypeDescriptor targetClass, Converter converter) {
|
||||
this.sourceType = sourceClass;
|
||||
this.targetType = targetClass;
|
||||
public StaticConversionExecutor(TypeDescriptor sourceType, TypeDescriptor targetType, Converter converter) {
|
||||
this.sourceType = sourceType;
|
||||
this.targetType = targetType;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ class StaticConversionExecutor implements ConversionExecutor {
|
||||
return null;
|
||||
}
|
||||
if (sourceType != null && !sourceType.isInstance(source)) {
|
||||
throw new ConversionExecutionException(source, sourceType, targetType, "Source object "
|
||||
throw new ConversionExecutionException(source, sourceType.getType(), targetType, "Source object "
|
||||
+ source + " to convert is expected to be an instance of [" + sourceType.getName() + "]");
|
||||
}
|
||||
try {
|
||||
return converter.convert(source);
|
||||
} catch (Exception e) {
|
||||
throw new ConversionExecutionException(source, sourceType, targetType, e);
|
||||
throw new ConversionExecutionException(source, sourceType.getType(), targetType, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,13 +41,13 @@ class StaticSuperConversionExecutor implements ConversionExecutor {
|
||||
return null;
|
||||
}
|
||||
if (!sourceType.isInstance(source)) {
|
||||
throw new ConversionExecutionException(source, sourceType, targetType, "Source object "
|
||||
throw new ConversionExecutionException(source, sourceType.getType(), targetType, "Source object "
|
||||
+ source + " to convert is expected to be an instance of [" + sourceType.getName() + "]");
|
||||
}
|
||||
try {
|
||||
return converter.convert(source, targetType.getType());
|
||||
} catch (Exception e) {
|
||||
throw new ConversionExecutionException(source, sourceType, targetType, e);
|
||||
throw new ConversionExecutionException(source, sourceType.getType(), targetType, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.springframework.core.convert.service;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
public class ArrayToArrayTests {
|
||||
|
||||
@Test
|
||||
public void testArrayToArrayConversion() {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
ArrayToArray c = new ArrayToArray(TypeDescriptor.valueOf(String[].class), TypeDescriptor.valueOf(Integer[].class), service);
|
||||
Integer[] result = (Integer[]) c.execute(new String[] { "1", "2", "3" });
|
||||
assertEquals(new Integer(1), result[0]);
|
||||
assertEquals(new Integer(2), result[1]);
|
||||
assertEquals(new Integer(3), result[2]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.springframework.core.convert.service;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
public class ArrayToCollectionTests {
|
||||
|
||||
@Test
|
||||
public void testArrayToCollectionConversion() throws Exception {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
ArrayToCollection c = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), new TypeDescriptor(getClass().getField("bindTarget")), service);
|
||||
List result = (List) c.execute(new String[] { "1", "2", "3" });
|
||||
assertEquals(new Integer(1), result.get(0));
|
||||
assertEquals(new Integer(2), result.get(1));
|
||||
assertEquals(new Integer(3), result.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayToSetConversion() throws Exception {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
ArrayToCollection c = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), new TypeDescriptor(getClass().getField("setTarget")), service);
|
||||
Set result = (Set) c.execute(new String[] { "1" });
|
||||
assertEquals("1", result.iterator().next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayToSortedSetConversion() throws Exception {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
ArrayToCollection c = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), new TypeDescriptor(getClass().getField("sortedSetTarget")), service);
|
||||
SortedSet result = (SortedSet) c.execute(new String[] { "1" });
|
||||
assertEquals(new Integer(1), result.iterator().next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayToCollectionImplConversion() throws Exception {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
ArrayToCollection c = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), new TypeDescriptor(getClass().getField("implTarget")), service);
|
||||
LinkedList result = (LinkedList) c.execute(new String[] { "1" });
|
||||
assertEquals("1", result.iterator().next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayToNonGenericCollectionConversionNullElement() throws Exception {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
ArrayToCollection c = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), new TypeDescriptor(getClass().getField("listTarget")), service);
|
||||
List result = (List) c.execute(new Integer[] { null, new Integer(1) });
|
||||
assertEquals(null, result.get(0));
|
||||
assertEquals(new Integer(1), result.get(1));
|
||||
}
|
||||
|
||||
public Collection<Integer> bindTarget;
|
||||
public List listTarget;
|
||||
public Set setTarget;
|
||||
public SortedSet<Integer> sortedSetTarget;
|
||||
public LinkedList<String> implTarget;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.springframework.core.convert.service;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
public class CollectionToArrayTests {
|
||||
|
||||
@Test
|
||||
public void testCollectionToArrayConversion() throws Exception {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
CollectionToArray c = new CollectionToArray(new TypeDescriptor(getClass().getField("bindTarget")),
|
||||
TypeDescriptor.valueOf(Integer[].class), service);
|
||||
bindTarget.add("1");
|
||||
bindTarget.add("2");
|
||||
bindTarget.add("3");
|
||||
Integer[] result = (Integer[]) c.execute(bindTarget);
|
||||
assertEquals(new Integer(1), result[0]);
|
||||
assertEquals(new Integer(2), result[1]);
|
||||
assertEquals(new Integer(3), result[2]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCollectionToArrayConversionNoGenericInfo() throws Exception {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
CollectionToArray c = new CollectionToArray(TypeDescriptor.valueOf(Collection.class), TypeDescriptor
|
||||
.valueOf(Integer[].class), service);
|
||||
bindTarget.add("1");
|
||||
bindTarget.add("2");
|
||||
bindTarget.add("3");
|
||||
Integer[] result = (Integer[]) c.execute(bindTarget);
|
||||
assertEquals(new Integer(1), result[0]);
|
||||
assertEquals(new Integer(2), result[1]);
|
||||
assertEquals(new Integer(3), result[2]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCollectionToArrayConversionNoGenericInfoNullElement() throws Exception {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
CollectionToArray c = new CollectionToArray(TypeDescriptor.valueOf(Collection.class), TypeDescriptor
|
||||
.valueOf(Integer[].class), service);
|
||||
bindTarget.add(null);
|
||||
bindTarget.add("1");
|
||||
bindTarget.add("2");
|
||||
bindTarget.add("3");
|
||||
Integer[] result = (Integer[]) c.execute(bindTarget);
|
||||
assertEquals(null, result[0]);
|
||||
assertEquals(new Integer(1), result[1]);
|
||||
assertEquals(new Integer(2), result[2]);
|
||||
assertEquals(new Integer(3), result[3]);
|
||||
}
|
||||
|
||||
public Collection<String> bindTarget = new ArrayList<String>();
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user