basic conversion service impl; still need super converters, custom converters, and conversion of generic collection elements
This commit is contained in:
parent
c1f3ec0c5b
commit
3a7b4bf1b0
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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 java.lang.reflect.Array;
|
||||
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
|
||||
/**
|
||||
* Special one-way converter that converts from a source array to a target array. Supports type conversion of the
|
||||
* individual array elements; for example, the ability to convert a String[] to an Integer[]. Mainly used internally by
|
||||
* {@link ConversionService} implementations.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class ArrayToArray implements SuperConverter {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new array-to-array converter.
|
||||
* @param conversionService the service to use to lookup conversion executors for individual array elements
|
||||
* dynamically
|
||||
*/
|
||||
public ArrayToArray(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array-to-array converter.
|
||||
* @param elementConverter a specific conversion executor to use to convert elements in the source array to elements
|
||||
* in the target array.
|
||||
*/
|
||||
public ArrayToArray(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Class getSourceClass() {
|
||||
return Object[].class;
|
||||
}
|
||||
|
||||
public Class getSuperTargetClass() {
|
||||
return Object[].class;
|
||||
}
|
||||
|
||||
public Object convert(Object source, Class targetClass) throws Exception {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
Class sourceComponentType = source.getClass().getComponentType();
|
||||
Class targetComponentType = targetClass.getComponentType();
|
||||
int length = Array.getLength(source);
|
||||
Object targetArray = Array.newInstance(targetComponentType, length);
|
||||
ConversionExecutor converter = getElementConverter(sourceComponentType, targetComponentType);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object value = Array.get(source, i);
|
||||
Array.set(targetArray, i, converter.execute(value));
|
||||
}
|
||||
return targetArray;
|
||||
}
|
||||
|
||||
public Object convertBack(Object target) throws Exception {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
private ConversionExecutor getElementConverter(Class sourceComponentType, Class targetComponentType) {
|
||||
if (elementConverter != null) {
|
||||
return elementConverter;
|
||||
} else {
|
||||
return conversionService.getConversionExecutor(sourceComponentType, targetComponentType);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* 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 java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
|
||||
/**
|
||||
* Special converter that converts from a source array to a target collection. Supports the selection of an
|
||||
* "approximate" collection implementation when a target collection interface such as <code>List.class</code> is
|
||||
* specified. Supports type conversion of array elements when a concrete parameterized collection class is provided,
|
||||
* such as <code>IntegerList<Integer>.class</code>.
|
||||
*
|
||||
* Note that type erasure prevents arbitrary access to generic collection element type information at runtime,
|
||||
* preventing the ability to convert elements for collections declared as properties.
|
||||
*
|
||||
* Mainly used internally by {@link ConversionService} implementations.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class ArrayToCollection implements SuperConverter {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new array to collection converter.
|
||||
* @param conversionService the conversion service to use to lookup the converter to apply to array elements added
|
||||
* to the target collection
|
||||
*/
|
||||
public ArrayToCollection(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array to collection converter.
|
||||
* @param elementConverter A specific converter to use on array elements when adding them to the target collection
|
||||
*/
|
||||
public ArrayToCollection(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Object convert(Object source, Class targetClass) throws Exception {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
Class collectionImplClass = getCollectionImplClass(targetClass);
|
||||
Constructor constructor = collectionImplClass.getConstructor((Class[]) null);
|
||||
Collection collection = (Collection) constructor.newInstance((Object[]) null);
|
||||
ConversionExecutor converter = getArrayElementConverter(source, targetClass);
|
||||
int length = Array.getLength(source);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object value = Array.get(source, i);
|
||||
if (converter != null) {
|
||||
value = converter.execute(value);
|
||||
}
|
||||
collection.add(value);
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
public Object convertBack(Object target) throws Exception {
|
||||
throw new UnsupportedOperationException("Should never be called");
|
||||
}
|
||||
|
||||
public Object convertBack(Object target, Class sourceClass) throws Exception {
|
||||
if (target == null) {
|
||||
return null;
|
||||
}
|
||||
Collection collection = (Collection) target;
|
||||
Object array = Array.newInstance(sourceClass.getComponentType(), collection.size());
|
||||
int i = 0;
|
||||
for (Iterator it = collection.iterator(); it.hasNext(); i++) {
|
||||
Object value = it.next();
|
||||
if (value != null) {
|
||||
ConversionExecutor converter;
|
||||
if (elementConverter != null) {
|
||||
converter = elementConverter;
|
||||
} else {
|
||||
converter = conversionService.getConversionExecutor(value.getClass(), sourceClass
|
||||
.getComponentType());
|
||||
}
|
||||
value = converter.execute(value);
|
||||
}
|
||||
Array.set(array, i, value);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private Class getCollectionImplClass(Class targetClass) {
|
||||
if (targetClass.isInterface()) {
|
||||
if (List.class.equals(targetClass)) {
|
||||
return ArrayList.class;
|
||||
} else if (Set.class.equals(targetClass)) {
|
||||
return LinkedHashSet.class;
|
||||
} else if (SortedSet.class.equals(targetClass)) {
|
||||
return TreeSet.class;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported collection interface [" + targetClass.getName() + "]");
|
||||
}
|
||||
} else {
|
||||
return targetClass;
|
||||
}
|
||||
}
|
||||
|
||||
private ConversionExecutor getArrayElementConverter(Object source, Class targetClass) {
|
||||
if (elementConverter != null) {
|
||||
return elementConverter;
|
||||
} else {
|
||||
Class elementType = GenericCollectionTypeResolver.getCollectionType(targetClass);
|
||||
if (elementType != null) {
|
||||
Class componentType = source.getClass().getComponentType();
|
||||
return conversionService.getConversionExecutor(componentType, elementType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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 java.lang.reflect.Array;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
|
||||
/**
|
||||
* Special converter that converts from a source array to a target collection. Supports the selection of an
|
||||
* "approximate" collection implementation when a target collection interface such as <code>List.class</code> is
|
||||
* specified. Supports type conversion of array elements when a concrete parameterized collection class is provided,
|
||||
* such as <code>IntegerList<Integer>.class</code>.
|
||||
*
|
||||
* Note that type erasure prevents arbitrary access to generic collection element type information at runtime,
|
||||
* preventing the ability to convert elements for collections declared as properties.
|
||||
*
|
||||
* Mainly used internally by {@link ConversionService} implementations.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class CollectionToArray implements SuperConverter {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new array to collection converter.
|
||||
* @param conversionService the conversion service to use to lookup the converter to apply to array elements added
|
||||
* to the target collection
|
||||
*/
|
||||
public CollectionToArray(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array to collection converter.
|
||||
* @param elementConverter A specific converter to use on array elements when adding them to the target collection
|
||||
*/
|
||||
public CollectionToArray(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Object convert(Object source, Class targetClass) throws Exception {
|
||||
Collection collection = (Collection) source;
|
||||
Object array = Array.newInstance(targetClass.getComponentType(), collection.size());
|
||||
int i = 0;
|
||||
for (Iterator it = collection.iterator(); it.hasNext(); i++) {
|
||||
Object value = it.next();
|
||||
if (value != null) {
|
||||
ConversionExecutor converter;
|
||||
if (elementConverter != null) {
|
||||
converter = elementConverter;
|
||||
} else {
|
||||
converter = conversionService.getConversionExecutor(value.getClass(), targetClass
|
||||
.getComponentType());
|
||||
}
|
||||
value = converter.execute(value);
|
||||
}
|
||||
Array.set(array, i, value);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public Object convertBack(Object target) throws Exception {
|
||||
throw new UnsupportedOperationException("Should never be called");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
|
||||
/**
|
||||
* A converter that can convert from one collection type to another.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class CollectionToCollection implements SuperConverter {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new collection-to-collection converter
|
||||
* @param conversionService the conversion service to use to convert collection elements to add to the target
|
||||
* collection
|
||||
*/
|
||||
public CollectionToCollection(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new collection-to-collection converter
|
||||
* @param elementConverter a specific converter to use to convert collection elements added to the target collection
|
||||
*/
|
||||
public CollectionToCollection(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Class getSourceClass() {
|
||||
return Collection.class;
|
||||
}
|
||||
|
||||
public Class getSuperTargetClass() {
|
||||
return Collection.class;
|
||||
}
|
||||
|
||||
public Object convert(Object source, Class targetClass) throws Exception {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
Class targetCollectionImpl = getCollectionImplClass(targetClass);
|
||||
Collection targetCollection = (Collection) targetCollectionImpl.getConstructor((Class[]) null).newInstance(
|
||||
(Object[]) null);
|
||||
ConversionExecutor elementConverter = getElementConverter(source, targetClass);
|
||||
Collection sourceCollection = (Collection) source;
|
||||
Iterator it = sourceCollection.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object value = it.next();
|
||||
if (elementConverter != null) {
|
||||
value = elementConverter.execute(value);
|
||||
}
|
||||
targetCollection.add(value);
|
||||
}
|
||||
return targetCollection;
|
||||
}
|
||||
|
||||
public Object convertBack(Object target) throws Exception {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
// this code is duplicated in ArrayToCollection.java and ObjectToCollection too
|
||||
private Class getCollectionImplClass(Class targetClass) {
|
||||
if (targetClass.isInterface()) {
|
||||
if (List.class.equals(targetClass)) {
|
||||
return ArrayList.class;
|
||||
} else if (Set.class.equals(targetClass)) {
|
||||
return LinkedHashSet.class;
|
||||
} else if (SortedSet.class.equals(targetClass)) {
|
||||
return TreeSet.class;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported collection interface [" + targetClass.getName() + "]");
|
||||
}
|
||||
} else {
|
||||
return targetClass;
|
||||
}
|
||||
}
|
||||
|
||||
private ConversionExecutor getElementConverter(Object source, Class targetClass) {
|
||||
if (elementConverter != null) {
|
||||
return elementConverter;
|
||||
} else {
|
||||
Class elementType = GenericCollectionTypeResolver.getCollectionType(targetClass);
|
||||
if (elementType != null) {
|
||||
Class componentType = source.getClass().getComponentType();
|
||||
return conversionService.getConversionExecutor(componentType, elementType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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 java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.core.convert.converter.NumberToNumber;
|
||||
import org.springframework.core.convert.converter.StringToBigDecimal;
|
||||
import org.springframework.core.convert.converter.StringToBigInteger;
|
||||
import org.springframework.core.convert.converter.StringToBoolean;
|
||||
import org.springframework.core.convert.converter.StringToByte;
|
||||
import org.springframework.core.convert.converter.StringToCharacter;
|
||||
import org.springframework.core.convert.converter.StringToDouble;
|
||||
import org.springframework.core.convert.converter.StringToEnum;
|
||||
import org.springframework.core.convert.converter.StringToFloat;
|
||||
import org.springframework.core.convert.converter.StringToInteger;
|
||||
import org.springframework.core.convert.converter.StringToLocale;
|
||||
import org.springframework.core.convert.converter.StringToLong;
|
||||
import org.springframework.core.convert.converter.StringToShort;
|
||||
|
||||
/**
|
||||
* Default, local implementation of a conversion service. Will automatically register <i>from string</i> converters for
|
||||
* a number of standard Java types like Class, Number, Boolean and so on.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class DefaultConversionService extends GenericConversionService {
|
||||
|
||||
/**
|
||||
* Creates a new default conversion service, installing the default converters.
|
||||
*/
|
||||
public DefaultConversionService() {
|
||||
addDefaultConverters();
|
||||
addDefaultAliases();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all default converters to the conversion service.
|
||||
*/
|
||||
protected void addDefaultConverters() {
|
||||
addConverter(new StringToByte());
|
||||
addConverter(new StringToBoolean());
|
||||
addConverter(new StringToCharacter());
|
||||
addConverter(new StringToShort());
|
||||
addConverter(new StringToInteger());
|
||||
addConverter(new StringToLong());
|
||||
addConverter(new StringToFloat());
|
||||
addConverter(new StringToDouble());
|
||||
addConverter(new StringToBigInteger());
|
||||
addConverter(new StringToBigDecimal());
|
||||
addConverter(new StringToLocale());
|
||||
addConverter(new StringToEnum());
|
||||
addConverter(new NumberToNumber());
|
||||
addConverter(new ObjectToCollection(this));
|
||||
addConverter(new CollectionToCollection(this));
|
||||
}
|
||||
|
||||
protected void addDefaultAliases() {
|
||||
addAlias("string", String.class);
|
||||
addAlias("byte", Byte.class);
|
||||
addAlias("boolean", Boolean.class);
|
||||
addAlias("char", Character.class);
|
||||
addAlias("short", Short.class);
|
||||
addAlias("int", Integer.class);
|
||||
addAlias("long", Long.class);
|
||||
addAlias("float", Float.class);
|
||||
addAlias("double", Double.class);
|
||||
addAlias("bigInteger", BigInteger.class);
|
||||
addAlias("bigDecimal", BigDecimal.class);
|
||||
addAlias("locale", Locale.class);
|
||||
addAlias("enum", Enum.class);
|
||||
addAlias("date", Date.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* 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 java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.convert.ConversionException;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionExecutorNotFoundException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base implementation of a conversion service. Initially empty, e.g. no converters are registered by default.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class GenericConversionService implements ConversionService {
|
||||
|
||||
/**
|
||||
* An indexed map of Converters. Each Map.Entry key is a source class (S) that can be converted from. Each Map.Entry
|
||||
* value is a Map that defines the targetClass-to-Converter mappings for that source.
|
||||
*/
|
||||
private final Map sourceClassConverters = new HashMap();
|
||||
|
||||
/**
|
||||
* Indexes classes by well-known aliases.
|
||||
*/
|
||||
private final Map aliasMap = new HashMap<String, Class<?>>();
|
||||
|
||||
/**
|
||||
* An optional parent conversion service.
|
||||
*/
|
||||
private ConversionService parent;
|
||||
|
||||
/**
|
||||
* Returns the parent of this conversion service. Could be null.
|
||||
*/
|
||||
public ConversionService getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parent of this conversion service. This is optional.
|
||||
*/
|
||||
public void setParent(ConversionService parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Converter with this conversion service.
|
||||
* @param converter the converter to register
|
||||
*/
|
||||
public void addConverter(Converter converter) {
|
||||
List typeInfo = getTypeInfo(converter);
|
||||
Class sourceClass = (Class) typeInfo.get(0);
|
||||
Class targetClass = (Class) typeInfo.get(1);
|
||||
// index forward
|
||||
Map sourceMap = getSourceMap(sourceClass);
|
||||
sourceMap.put(targetClass, converter);
|
||||
// index reverse
|
||||
sourceMap = getSourceMap(targetClass);
|
||||
sourceMap.put(sourceClass, new ReverseConverter(converter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the SuperConverter with this conversion service.
|
||||
* @param converter the super converter to register
|
||||
*/
|
||||
public void addConverter(SuperConverter converter) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a convenient alias for the target type. {@link #getClassForAlias(String)} can then be used to lookup the type
|
||||
* given the alias.
|
||||
* @see #getClassForAlias(String)
|
||||
*/
|
||||
public void addAlias(String alias, Class targetType) {
|
||||
aliasMap.put(alias, targetType);
|
||||
}
|
||||
|
||||
public Object executeConversion(Object source, Class targetClass) throws ConversionExecutorNotFoundException,
|
||||
ConversionException {
|
||||
if (source != null) {
|
||||
ConversionExecutor conversionExecutor = getConversionExecutor(source.getClass(), targetClass);
|
||||
return conversionExecutor.execute(source);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Object executeConversion(String converterId, Object source, Class targetClass)
|
||||
throws ConversionExecutorNotFoundException, ConversionException {
|
||||
if (source != null) {
|
||||
ConversionExecutor conversionExecutor = getConversionExecutor(converterId, source.getClass(), targetClass);
|
||||
return conversionExecutor.execute(source);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(Class sourceClass, Class targetClass)
|
||||
throws ConversionExecutorNotFoundException {
|
||||
Assert.notNull(sourceClass, "The source class to convert from is required");
|
||||
Assert.notNull(targetClass, "The target class to convert to is required");
|
||||
if (targetClass.isAssignableFrom(sourceClass)) {
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, new NoOpConverter());
|
||||
}
|
||||
sourceClass = convertToWrapperClassIfNecessary(sourceClass);
|
||||
targetClass = convertToWrapperClassIfNecessary(targetClass);
|
||||
// special handling for arrays since they are not indexable classes
|
||||
if (sourceClass.isArray()) {
|
||||
if (targetClass.isArray()) {
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ArrayToArray(this));
|
||||
} else if (Collection.class.isAssignableFrom(targetClass)) {
|
||||
if (!targetClass.isInterface() && Modifier.isAbstract(targetClass.getModifiers())) {
|
||||
throw new IllegalArgumentException("Conversion target class [" + targetClass.getName()
|
||||
+ "] is invalid; cannot convert to abstract collection types--"
|
||||
+ "request an interface or concrete implementation instead");
|
||||
}
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ArrayToCollection(this));
|
||||
}
|
||||
}
|
||||
if (targetClass.isArray()) {
|
||||
if (Collection.class.isAssignableFrom(sourceClass)) {
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new CollectionToArray(this));
|
||||
} else {
|
||||
return new StaticSuperConversionExecutor(sourceClass, targetClass, new ObjectToArray(this));
|
||||
}
|
||||
}
|
||||
Converter converter = findRegisteredConverter(sourceClass, targetClass);
|
||||
if (converter != null) {
|
||||
// we found a converter
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, converter);
|
||||
} else {
|
||||
if (parent != null) {
|
||||
// try the parent
|
||||
return parent.getConversionExecutor(sourceClass, targetClass);
|
||||
} else {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"No ConversionExecutor found for converting from sourceClass [" + sourceClass.getName()
|
||||
+ "] to target class [" + targetClass.getName() + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(String converterId, Class sourceClass, Class targetClass)
|
||||
throws ConversionExecutorNotFoundException {
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
|
||||
public Class getClassForAlias(String name) throws IllegalArgumentException {
|
||||
Class clazz = (Class) aliasMap.get(name);
|
||||
if (clazz != null) {
|
||||
return clazz;
|
||||
} else {
|
||||
if (parent != null) {
|
||||
return parent.getClassForAlias(name);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private List getTypeInfo(Converter converter) {
|
||||
List typeInfo = new ArrayList(2);
|
||||
Class classToIntrospect = converter.getClass();
|
||||
while (classToIntrospect != null) {
|
||||
Type[] genericInterfaces = converter.getClass().getGenericInterfaces();
|
||||
for (Type genericInterface : genericInterfaces) {
|
||||
if (genericInterface instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedInterface = (ParameterizedType) genericInterface;
|
||||
if (Converter.class.equals(parameterizedInterface.getRawType())) {
|
||||
Type s = parameterizedInterface.getActualTypeArguments()[0];
|
||||
Type t = parameterizedInterface.getActualTypeArguments()[1];
|
||||
typeInfo.add(getParameterClass(s, converter.getClass()));
|
||||
typeInfo.add(getParameterClass(t, converter.getClass()));
|
||||
}
|
||||
}
|
||||
}
|
||||
classToIntrospect = classToIntrospect.getSuperclass();
|
||||
}
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
private Class<?> getParameterClass(Type parameterType, Class<?> converterClass) {
|
||||
if (parameterType instanceof TypeVariable) {
|
||||
parameterType = GenericTypeResolver.resolveTypeVariable((TypeVariable<?>) parameterType, converterClass);
|
||||
}
|
||||
if (parameterType instanceof Class) {
|
||||
return (Class<?>) parameterType;
|
||||
}
|
||||
// when would this happen?
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map getSourceMap(Class sourceClass) {
|
||||
Map sourceMap = (Map) sourceClassConverters.get(sourceClass);
|
||||
if (sourceMap == null) {
|
||||
sourceMap = new HashMap<Class<?>, Converter<?, ?>>();
|
||||
sourceClassConverters.put(sourceClass, sourceMap);
|
||||
}
|
||||
return sourceMap;
|
||||
}
|
||||
|
||||
private Class convertToWrapperClassIfNecessary(Class targetType) {
|
||||
if (targetType.isPrimitive()) {
|
||||
if (targetType.equals(int.class)) {
|
||||
return Integer.class;
|
||||
} else if (targetType.equals(short.class)) {
|
||||
return Short.class;
|
||||
} else if (targetType.equals(long.class)) {
|
||||
return Long.class;
|
||||
} else if (targetType.equals(float.class)) {
|
||||
return Float.class;
|
||||
} else if (targetType.equals(double.class)) {
|
||||
return Double.class;
|
||||
} else if (targetType.equals(byte.class)) {
|
||||
return Byte.class;
|
||||
} else if (targetType.equals(boolean.class)) {
|
||||
return Boolean.class;
|
||||
} else if (targetType.equals(char.class)) {
|
||||
return Character.class;
|
||||
} else {
|
||||
throw new IllegalStateException("Should never happen - primitive type is not a primitive?");
|
||||
}
|
||||
} else {
|
||||
return targetType;
|
||||
}
|
||||
}
|
||||
|
||||
private Converter findRegisteredConverter(Class sourceClass, Class targetClass) {
|
||||
if (sourceClass.isInterface()) {
|
||||
LinkedList classQueue = new LinkedList();
|
||||
classQueue.addFirst(sourceClass);
|
||||
while (!classQueue.isEmpty()) {
|
||||
Class currentClass = (Class) classQueue.removeLast();
|
||||
Map<Class, Converter> sourceTargetConverters = findConvertersForSource(currentClass);
|
||||
Converter converter = findTargetConverter(sourceTargetConverters, targetClass);
|
||||
if (converter != null) {
|
||||
return converter;
|
||||
}
|
||||
Class[] interfaces = currentClass.getInterfaces();
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
classQueue.addFirst(interfaces[i]);
|
||||
}
|
||||
}
|
||||
Map objectConverters = findConvertersForSource(Object.class);
|
||||
return findTargetConverter(objectConverters, targetClass);
|
||||
} else {
|
||||
LinkedList classQueue = new LinkedList();
|
||||
classQueue.addFirst(sourceClass);
|
||||
while (!classQueue.isEmpty()) {
|
||||
Class currentClass = (Class) classQueue.removeLast();
|
||||
Map sourceTargetConverters = findConvertersForSource(currentClass);
|
||||
Converter converter = findTargetConverter(sourceTargetConverters, targetClass);
|
||||
if (converter != null) {
|
||||
return converter;
|
||||
}
|
||||
if (currentClass.getSuperclass() != null) {
|
||||
classQueue.addFirst(currentClass.getSuperclass());
|
||||
}
|
||||
Class[] interfaces = currentClass.getInterfaces();
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
classQueue.addFirst(interfaces[i]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Map findConvertersForSource(Class sourceClass) {
|
||||
Map sourceConverters = (Map) sourceClassConverters.get(sourceClass);
|
||||
return sourceConverters != null ? sourceConverters : Collections.emptyMap();
|
||||
}
|
||||
|
||||
private Converter findTargetConverter(Map sourceTargetConverters, Class targetClass) {
|
||||
if (sourceTargetConverters.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return (Converter) sourceTargetConverters.get(targetClass);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.converter.Converter;
|
||||
|
||||
/**
|
||||
* Package private converter that is a "no op".
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class NoOpConverter implements Converter {
|
||||
|
||||
public Object convert(Object source) throws Exception {
|
||||
return source;
|
||||
}
|
||||
|
||||
public Object convertBack(Object target) throws Exception {
|
||||
return target;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 java.lang.reflect.Array;
|
||||
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
|
||||
/**
|
||||
* Special two-way converter that converts an object to an single-element array. Mainly used internally by
|
||||
* {@link ConversionService} implementations.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class ObjectToArray implements SuperConverter {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new object to array converter.
|
||||
* @param conversionService the conversion service to resolve the converter to use to convert the object added to
|
||||
* the target array.
|
||||
*/
|
||||
public ObjectToArray(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new object to array converter.
|
||||
* @param elementConverter a specific converter to use to convert the object added to the target array.
|
||||
*/
|
||||
public ObjectToArray(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Class getSourceClass() {
|
||||
return Object.class;
|
||||
}
|
||||
|
||||
public Class getSuperTargetClass() {
|
||||
return Object[].class;
|
||||
}
|
||||
|
||||
public Object convert(Object source, Class targetClass) throws Exception {
|
||||
Class componentType = targetClass.getComponentType();
|
||||
Object array = Array.newInstance(componentType, 1);
|
||||
ConversionExecutor converter;
|
||||
if (elementConverter != null) {
|
||||
converter = elementConverter;
|
||||
} else {
|
||||
converter = conversionService.getConversionExecutor(source.getClass(), componentType);
|
||||
}
|
||||
Array.set(array, 0, converter.execute(source));
|
||||
return array;
|
||||
}
|
||||
|
||||
public Object convertBack(Object target) throws Exception {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* 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 java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
|
||||
/**
|
||||
* Special two-way converter that converts an object to an single-element collection. Supports type conversion of the
|
||||
* individual element with parameterized collection implementations.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class ObjectToCollection implements SuperConverter {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ConversionExecutor elementConverter;
|
||||
|
||||
/**
|
||||
* Creates a new object to collection converter
|
||||
* @param conversionService the conversion service to lookup the converter to use to convert an object when adding
|
||||
* it to a target collection
|
||||
*/
|
||||
public ObjectToCollection(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new object to collection converter
|
||||
* @param elementConverter a specific converter to execute on an object when adding it to a target collection
|
||||
*/
|
||||
public ObjectToCollection(ConversionExecutor elementConverter) {
|
||||
this.elementConverter = elementConverter;
|
||||
}
|
||||
|
||||
public Class getSourceClass() {
|
||||
return Object.class;
|
||||
}
|
||||
|
||||
public Class getSuperTargetClass() {
|
||||
return Collection.class;
|
||||
}
|
||||
|
||||
public Object convert(Object source, Class targetClass) throws Exception {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
Class collectionImplClass = getCollectionImplClass(targetClass);
|
||||
Constructor constructor = collectionImplClass.getConstructor((Class[]) null);
|
||||
Collection collection = (Collection) constructor.newInstance((Object[]) null);
|
||||
ConversionExecutor converter = getElementConverter(source, targetClass);
|
||||
Object value;
|
||||
if (converter != null) {
|
||||
value = converter.execute(source);
|
||||
} else {
|
||||
value = source;
|
||||
}
|
||||
collection.add(value);
|
||||
return collection;
|
||||
}
|
||||
|
||||
public Object convertBack(Object target) throws Exception {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
// this code is duplicated in ArrayToCollection and CollectionToCollection
|
||||
private Class getCollectionImplClass(Class targetClass) {
|
||||
if (targetClass.isInterface()) {
|
||||
if (List.class.equals(targetClass)) {
|
||||
return ArrayList.class;
|
||||
} else if (Set.class.equals(targetClass)) {
|
||||
return LinkedHashSet.class;
|
||||
} else if (SortedSet.class.equals(targetClass)) {
|
||||
return TreeSet.class;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported collection interface [" + targetClass.getName() + "]");
|
||||
}
|
||||
} else {
|
||||
return targetClass;
|
||||
}
|
||||
}
|
||||
|
||||
private ConversionExecutor getElementConverter(Object source, Class targetClass) {
|
||||
if (elementConverter != null) {
|
||||
return elementConverter;
|
||||
} else {
|
||||
Class elementType = GenericCollectionTypeResolver.getCollectionType(targetClass);
|
||||
if (elementType != null) {
|
||||
Class componentType = source.getClass().getComponentType();
|
||||
return conversionService.getConversionExecutor(componentType, elementType);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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.converter.Converter;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
class ReverseConverter implements Converter {
|
||||
|
||||
private Converter converter;
|
||||
|
||||
public ReverseConverter(Converter converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public Object convert(Object source) throws Exception {
|
||||
return converter.convertBack(source);
|
||||
}
|
||||
|
||||
public Object convertBack(Object target) throws Exception {
|
||||
throw new IllegalStateException("Should not be called");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
class StaticConversionExecutor implements ConversionExecutor {
|
||||
|
||||
private final Class sourceClass;
|
||||
|
||||
private final Class targetClass;
|
||||
|
||||
private final Converter converter;
|
||||
|
||||
public StaticConversionExecutor(Class sourceClass, Class targetClass, Converter converter) {
|
||||
Assert.notNull(sourceClass, "The source class is required");
|
||||
Assert.notNull(targetClass, "The target class is required");
|
||||
Assert.notNull(converter, "The converter is required");
|
||||
this.sourceClass = sourceClass;
|
||||
this.targetClass = targetClass;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public Class getSourceClass() {
|
||||
return sourceClass;
|
||||
}
|
||||
|
||||
public Class getTargetClass() {
|
||||
return targetClass;
|
||||
}
|
||||
|
||||
public Object execute(Object source) throws ConversionExecutionException {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
if (!sourceClass.isInstance(source)) {
|
||||
throw new ConversionExecutionException(source, getSourceClass(), getTargetClass(), "Source object "
|
||||
+ source + " to convert is expected to be an instance of [" + getSourceClass().getName() + "]");
|
||||
}
|
||||
try {
|
||||
return converter.convert(source);
|
||||
} catch (Exception e) {
|
||||
throw new ConversionExecutionException(source, getSourceClass(), getTargetClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof StaticConversionExecutor)) {
|
||||
return false;
|
||||
}
|
||||
StaticConversionExecutor other = (StaticConversionExecutor) o;
|
||||
return sourceClass.equals(other.sourceClass) && targetClass.equals(other.targetClass);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return sourceClass.hashCode() + targetClass.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("sourceClass", sourceClass).append("targetClass", targetClass)
|
||||
.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright 2004-2008 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;
|
||||
import org.springframework.core.convert.converter.SuperConverter;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
class StaticSuperConversionExecutor implements ConversionExecutor {
|
||||
|
||||
private final Class sourceClass;
|
||||
|
||||
private final Class targetClass;
|
||||
|
||||
private final SuperConverter converter;
|
||||
|
||||
public StaticSuperConversionExecutor(Class sourceClass, Class targetClass, SuperConverter converter) {
|
||||
Assert.notNull(sourceClass, "The source class is required");
|
||||
Assert.notNull(targetClass, "The target class is required");
|
||||
Assert.notNull(converter, "The super converter is required");
|
||||
this.sourceClass = sourceClass;
|
||||
this.targetClass = targetClass;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public Class getSourceClass() {
|
||||
return sourceClass;
|
||||
}
|
||||
|
||||
public Class getTargetClass() {
|
||||
return targetClass;
|
||||
}
|
||||
|
||||
public Object execute(Object source) throws ConversionExecutionException {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
if (!sourceClass.isInstance(source)) {
|
||||
throw new ConversionExecutionException(source, getSourceClass(), getTargetClass(), "Source object "
|
||||
+ source + " to convert is expected to be an instance of [" + getSourceClass().getName() + "]");
|
||||
}
|
||||
try {
|
||||
return converter.convert(source, targetClass);
|
||||
} catch (Exception e) {
|
||||
throw new ConversionExecutionException(source, getSourceClass(), getTargetClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof StaticSuperConversionExecutor)) {
|
||||
return false;
|
||||
}
|
||||
StaticSuperConversionExecutor other = (StaticSuperConversionExecutor) o;
|
||||
return sourceClass.equals(other.sourceClass) && targetClass.equals(other.targetClass);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return sourceClass.hashCode() + targetClass.hashCode();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("sourceClass", sourceClass).append("targetClass", targetClass)
|
||||
.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>
|
||||
ConversionService implementation.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* 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 java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.core.convert.ConversionExecutor;
|
||||
import org.springframework.core.convert.ConversionExecutorNotFoundException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.StringToBoolean;
|
||||
|
||||
/**
|
||||
* Test case for the default conversion service.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class DefaultConversionServiceTests extends TestCase {
|
||||
|
||||
ConversionService service = new DefaultConversionService();
|
||||
|
||||
public void testConversionForwardIndex() {
|
||||
ConversionExecutor<String, Integer> executor = service.getConversionExecutor(String.class, Integer.class);
|
||||
Integer three = executor.execute("3");
|
||||
assertEquals(3, three.intValue());
|
||||
}
|
||||
|
||||
public void testConversionReverseIndex() {
|
||||
ConversionExecutor<Integer, String> executor = service.getConversionExecutor(Integer.class, String.class);
|
||||
String threeString = executor.execute(new Integer(3));
|
||||
assertEquals("3", threeString);
|
||||
}
|
||||
|
||||
public void testConversionCompatibleTypes() {
|
||||
ArrayList source = new ArrayList();
|
||||
assertSame(source, service.getConversionExecutor(ArrayList.class, List.class).execute(source));
|
||||
}
|
||||
|
||||
public void testConversionOverrideDefaultConverter() {
|
||||
Converter<String, Boolean> customConverter = new StringToBoolean("ja", "nee");
|
||||
((GenericConversionService) service).addConverter(customConverter);
|
||||
ConversionExecutor<String, Boolean> executor = service.getConversionExecutor(String.class, Boolean.class);
|
||||
assertTrue(executor.execute("ja").booleanValue());
|
||||
}
|
||||
|
||||
public void testConverterLookupTargetClassNotSupported() {
|
||||
try {
|
||||
service.getConversionExecutor(String.class, HashMap.class);
|
||||
fail("Should have thrown an exception");
|
||||
} catch (ConversionExecutorNotFoundException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testConversionToPrimitive() {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, int.class);
|
||||
Integer three = (Integer) executor.execute("3");
|
||||
assertEquals(3, three.intValue());
|
||||
}
|
||||
|
||||
public void testConversionArrayToArray() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(String[].class, Integer[].class);
|
||||
Integer[] result = (Integer[]) executor.execute(new String[] { "1", "2", "3" });
|
||||
assertEquals(new Integer(1), result[0]);
|
||||
assertEquals(new Integer(2), result[1]);
|
||||
assertEquals(new Integer(3), result[2]);
|
||||
}
|
||||
|
||||
public void testConversionArrayToPrimitiveArray() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(String[].class, int[].class);
|
||||
int[] result = (int[]) executor.execute(new String[] { "1", "2", "3" });
|
||||
assertEquals(1, result[0]);
|
||||
assertEquals(2, result[1]);
|
||||
assertEquals(3, result[2]);
|
||||
}
|
||||
|
||||
public void testConversionArrayToList() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(String[].class, List.class);
|
||||
List result = (List) executor.execute(new String[] { "1", "2", "3" });
|
||||
assertEquals("1", result.get(0));
|
||||
assertEquals("2", result.get(1));
|
||||
assertEquals("3", result.get(2));
|
||||
}
|
||||
|
||||
public void testConversionToArray() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(Collection.class, String[].class);
|
||||
List list = new ArrayList();
|
||||
list.add("1");
|
||||
list.add("2");
|
||||
list.add("3");
|
||||
String[] result = (String[]) executor.execute(list);
|
||||
assertEquals("1", result[0]);
|
||||
assertEquals("2", result[1]);
|
||||
assertEquals("3", result[2]);
|
||||
}
|
||||
|
||||
public void testConversionListToArrayWithComponentConversion() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(Collection.class, Integer[].class);
|
||||
List list = new ArrayList();
|
||||
list.add("1");
|
||||
list.add("2");
|
||||
list.add("3");
|
||||
Integer[] result = (Integer[]) executor.execute(list);
|
||||
assertEquals(new Integer(1), result[0]);
|
||||
assertEquals(new Integer(2), result[1]);
|
||||
assertEquals(new Integer(3), result[2]);
|
||||
}
|
||||
|
||||
public void testConversionArrayToConcreteList() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(String[].class, LinkedList.class);
|
||||
LinkedList result = (LinkedList) executor.execute(new String[] { "1", "2", "3" });
|
||||
assertEquals("1", result.get(0));
|
||||
assertEquals("2", result.get(1));
|
||||
assertEquals("3", result.get(2));
|
||||
}
|
||||
|
||||
public void testConversionArrayToAbstractList() {
|
||||
try {
|
||||
service.getConversionExecutor(String[].class, AbstractList.class);
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testConversionStringToArray() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, String[].class);
|
||||
String[] result = (String[]) executor.execute("1,2,3");
|
||||
assertEquals(1, result.length);
|
||||
assertEquals("1,2,3", result[0]);
|
||||
}
|
||||
|
||||
public void testConversionStringToArrayWithElementConversion() {
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, Integer[].class);
|
||||
Integer[] result = (Integer[]) executor.execute("123");
|
||||
assertEquals(1, result.length);
|
||||
assertEquals(new Integer(123), result[0]);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue