diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionConversionUtils.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionUtils.java similarity index 61% rename from org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionConversionUtils.java rename to org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionUtils.java index 950c395c906..31ad92f8995 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionConversionUtils.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionUtils.java @@ -17,23 +17,30 @@ package org.springframework.core.convert.support; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.SortedMap; import java.util.SortedSet; +import java.util.TreeMap; import java.util.TreeSet; /** - * Util code shared by collection converters extending from {@link AbstractCollectionConverter}. + * Conversion utility code shared by internal conversion executors in this package. + * @author Keith Donald + * @since 3.0 */ -class CollectionConversionUtils { +class ConversionUtils { /** * Get the java.util.Collection implementation class that should be used for the given target collection type. * @param targetCollectionType the target collection type, may be an interface * @return the collection impl to use */ - public static Class getImpl(Class targetCollectionType) { + @SuppressWarnings("unchecked") + public static Class getCollectionImpl(Class targetCollectionType) { if (targetCollectionType.isInterface()) { if (List.class.equals(targetCollectionType)) { return ArrayList.class; @@ -51,4 +58,24 @@ class CollectionConversionUtils { } } + /** + * Get the java.util.Map implementation class that should be used for the given target map type. + * @param targetMapType the target map type, may be an interface + * @return the map impl to use + */ + @SuppressWarnings("unchecked") + public static Class getMapImpl(Class targetMapType) { + if (targetMapType.isInterface()) { + if (Map.class.equals(targetMapType)) { + return HashMap.class; + } else if (SortedMap.class.equals(targetMapType)) { + return TreeMap.class; + } else { + throw new IllegalArgumentException("Unsupported Map interface [" + targetMapType.getName() + "]"); + } + } else { + return targetMapType; + } + } + } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapEntryConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapEntryConverter.java new file mode 100644 index 00000000000..f443b43502e --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapEntryConverter.java @@ -0,0 +1,57 @@ +/* + * 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.support; + +/** + * A helper for convertering map keys and values. + * @author Keith Donald + * @since 3.0 + */ +class MapEntryConverter { + + public static final MapEntryConverter NO_OP_INSTANCE = new MapEntryConverter(); + + private ConversionExecutor keyConverter; + + private ConversionExecutor valueConverter; + + public MapEntryConverter(ConversionExecutor keyConverter, ConversionExecutor valueConverter) { + this.keyConverter = keyConverter; + this.valueConverter = valueConverter; + } + + public Object convertKey(Object key) { + if (keyConverter != null) { + return keyConverter.execute(key); + } else { + return key; + } + } + + public Object convertValue(Object value) { + if (valueConverter != null) { + return valueConverter.execute(value); + } else { + return value; + } + } + + // internal + + private MapEntryConverter() { + } + +} \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringArray.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringArray.java new file mode 100644 index 00000000000..c11aee6f19a --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringArray.java @@ -0,0 +1,72 @@ +/* + * 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.support; + +import java.lang.reflect.Array; +import java.util.Map; + +import org.springframework.core.convert.ConversionFailedException; +import org.springframework.core.convert.TypeDescriptor; + +/** + * Converts a Map to a String array, where each element in the array + * is of the format key=value. + * @author Keith Donald + * @since 3.0 + */ +@SuppressWarnings("unchecked") +class MapToStringArray implements ConversionExecutor { + + private TypeDescriptor targetType; + + private GenericTypeConverter conversionService; + + private MapEntryConverter entryConverter; + + public MapToStringArray(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + this.targetType = targetType; + this.conversionService = conversionService; + this.entryConverter = createEntryConverter(); + } + + private MapEntryConverter createEntryConverter() { + if (targetType.isMapEntryTypeKnown()) { + ConversionExecutor keyConverter = conversionService.getConversionExecutor(targetType.getMapKeyType(), + TypeDescriptor.valueOf(String.class)); + ConversionExecutor valueConverter = conversionService.getConversionExecutor(targetType.getMapValueType(), + TypeDescriptor.valueOf(String.class)); + return new MapEntryConverter(keyConverter, valueConverter); + } else { + return MapEntryConverter.NO_OP_INSTANCE; + } + } + + public Object execute(Object source) throws ConversionFailedException { + Map sourceMap = (Map) source; + Object array = Array.newInstance(targetType.getElementType(), sourceMap.size()); + int i = 0; + for (Object entry : sourceMap.entrySet()) { + Map.Entry mapEntry = (Map.Entry) entry; + Object key = mapEntry.getKey(); + Object value = mapEntry.getValue(); + String property = entryConverter.convertKey(key) + "=" + entryConverter.convertValue(value); + Array.set(array, i, property); + i++; + } + return array; + } + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringCollection.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringCollection.java new file mode 100644 index 00000000000..f44bfbf3616 --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringCollection.java @@ -0,0 +1,47 @@ +/* + * 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.support; + +import java.util.Map; + +import org.springframework.core.convert.ConversionFailedException; +import org.springframework.core.convert.TypeDescriptor; + +/** + * Converts a Map to a String collection, where each element in the collection + * is of the format key=value. + * @author Keith Donald + * @since 3.0 + */ +@SuppressWarnings("unchecked") +class MapToStringCollection implements ConversionExecutor { + + private MapToStringArray converter; + + private ArrayToCollection collectionConverter; + + public MapToStringCollection(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + converter = new MapToStringArray(sourceType, targetType, conversionService); + collectionConverter = new ArrayToCollection(TypeDescriptor.valueOf(String[].class), targetType, conversionService); + } + + public Object execute(Object source) throws ConversionFailedException { + Map map = (Map) source; + Object array = converter.execute(map); + return collectionConverter.execute(array); + } + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArray.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArray.java new file mode 100644 index 00000000000..5174114274c --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArray.java @@ -0,0 +1,47 @@ +/* + * 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.support; + +import java.lang.reflect.Array; + +import org.springframework.core.convert.ConversionFailedException; +import org.springframework.core.convert.TypeDescriptor; + +/** + * Converts an object to a single-element array. + * @author Keith Donald + * @since 3.0 + */ +@SuppressWarnings("unchecked") +class ObjectToArray implements ConversionExecutor { + + private TypeDescriptor targetArrayType; + + private ConversionExecutor elementConverter; + + public ObjectToArray(TypeDescriptor sourceObjectType, TypeDescriptor targetArrayType, + GenericTypeConverter conversionService) { + this.targetArrayType = targetArrayType; + this.elementConverter = conversionService.getConversionExecutor(sourceObjectType.getType(), TypeDescriptor.valueOf(targetArrayType.getElementType())); + } + + public Object execute(Object source) throws ConversionFailedException { + Object array = Array.newInstance(targetArrayType.getType(), 1); + Array.set(array, 0, elementConverter.execute(source)); + return array; + } + +} \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollection.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollection.java new file mode 100644 index 00000000000..9cec59f2792 --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollection.java @@ -0,0 +1,69 @@ +/* + * 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.support; + +import java.util.Collection; + +import org.springframework.core.convert.ConversionFailedException; +import org.springframework.core.convert.TypeDescriptor; + +/** + * Converts an object to a single-element collection. + * @author Keith Donald + * @since 3.0 + */ +@SuppressWarnings("unchecked") +class ObjectToCollection implements ConversionExecutor { + + private TypeDescriptor sourceObjectType; + + private TypeDescriptor targetCollectionType; + + private GenericTypeConverter typeConverter; + + private ConversionExecutor elementConverter; + + public ObjectToCollection(TypeDescriptor sourceObjectType, TypeDescriptor targetCollectionType, + GenericTypeConverter typeConverter) { + this.sourceObjectType = sourceObjectType; + this.targetCollectionType = targetCollectionType; + this.typeConverter = typeConverter; + initElementConverter(); + } + + public Object execute(Object source) throws ConversionFailedException { + Class implClass = ConversionUtils.getCollectionImpl(targetCollectionType.getType()); + Collection collection; + try { + collection = (Collection) implClass.newInstance(); + } catch (InstantiationException e) { + throw new ConversionFailedException(source, sourceObjectType.getType(), targetCollectionType.getType(), e); + } catch (IllegalAccessException e) { + throw new ConversionFailedException(source, sourceObjectType.getType(), targetCollectionType.getType(), e); + } + collection.add(elementConverter.execute(source)); + return collection; + } + + private void initElementConverter() { + Class elementType = targetCollectionType.getElementType(); + if (elementType != null) { + this.elementConverter = typeConverter.getConversionExecutor(sourceObjectType.getType(), TypeDescriptor.valueOf(elementType)); + } else { + this.elementConverter = NoOpConversionExecutor.INSTANCE; + } + } +} \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringCollectionToMap.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringCollectionToMap.java new file mode 100644 index 00000000000..594bdd96d15 --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringCollectionToMap.java @@ -0,0 +1,43 @@ +/* + * 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.support; + +import java.util.Collection; + +import org.springframework.core.convert.ConversionFailedException; +import org.springframework.core.convert.TypeDescriptor; + +/** + * Converts a String collection to a Map. + * Each element in the collection must be formatted as key=value. + * @author Keith Donald + * @since 3.0 + */ +@SuppressWarnings("unchecked") +class StringCollectionToMap implements ConversionExecutor { + + private StringArrayToMap converter; + + public StringCollectionToMap(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + converter = new StringArrayToMap(sourceType, targetType, conversionService); + } + + public Object execute(Object source) throws ConversionFailedException { + Collection collection = (Collection) source; + return converter.execute(collection.toArray()); + } + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/NoOpConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArray.java similarity index 56% rename from org.springframework.core/src/main/java/org/springframework/core/convert/support/NoOpConverter.java rename to org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArray.java index 8d5a5a754c9..fad8d5d57cb 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/NoOpConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArray.java @@ -1,40 +1,39 @@ -/* - * 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.support; - -import org.springframework.core.convert.converter.Converter; - -/** - * A converter that does nothing. Access singleton at {@link #INSTANCE}. - * @author Keith Donald - */ -@SuppressWarnings("unchecked") -class NoOpConverter implements Converter { - - public static final Converter INSTANCE = new NoOpConverter(); - - private NoOpConverter() { - - } - - public Object convert(Object source) throws Exception { - return source; - } - - public Object convertBack(Object target) throws Exception { - return target; - } -} \ No newline at end of file +/* + * 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.support; + +import org.springframework.core.convert.TypeDescriptor; + +/** + * Converts a comma-delimited string to an array. + * @author Keith Donald + * @since 3.0 + */ +@SuppressWarnings("unchecked") +class StringToArray implements ConversionExecutor { + + private ArrayToArray converter; + + public StringToArray(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + converter = new ArrayToArray(TypeDescriptor.valueOf(String[].class), targetType, conversionService); + } + + public Object execute(Object source) { + String string = (String) source; + String[] fields = string.split(","); + return converter.execute(fields); + } +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollection.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollection.java new file mode 100644 index 00000000000..42fee8070f8 --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollection.java @@ -0,0 +1,41 @@ +/* + * 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.support; + +import org.springframework.core.convert.ConversionFailedException; +import org.springframework.core.convert.TypeDescriptor; + +/** + * Converts a comma-delimited string to a collection. + * @author Keith Donald + * @since 3.0 + */ +@SuppressWarnings("unchecked") +class StringToCollection implements ConversionExecutor { + + private ArrayToCollection converter; + + public StringToCollection(TypeDescriptor sourceType, TypeDescriptor targetType, GenericTypeConverter conversionService) { + converter = new ArrayToCollection(sourceType, targetType, conversionService); + } + + public Object execute(Object source) throws ConversionFailedException { + String string = (String) source; + String[] fields = string.split(","); + return converter.execute(fields); + } + +}