diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToStringConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToStringConverter.java new file mode 100644 index 00000000000..722b2d466b7 --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ArrayToStringConverter.java @@ -0,0 +1,53 @@ +/* + * Copyright 2002-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.Arrays; +import java.util.Collections; +import java.util.Set; + +import org.springframework.core.convert.TypeDescriptor; +import org.springframework.core.convert.converter.ConditionalGenericConverter; +import org.springframework.util.ObjectUtils; + +/** + * Converts from an array to a String. + * + * @author Keith Donald + * @since 3.0 + */ +final class ArrayToStringConverter implements ConditionalGenericConverter { + + private final CollectionToStringConverter helperConverter; + + public ArrayToStringConverter(GenericConversionService conversionService) { + this.helperConverter = new CollectionToStringConverter(conversionService); + } + + public Set getConvertibleTypes() { + return Collections.singleton(new ConvertiblePair(Object[].class, String.class)); + } + + public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { + return this.helperConverter.matches(sourceType, targetType); + } + + public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { + return this.helperConverter.convert(Arrays.asList(ObjectUtils.toObjectArray(source)), sourceType, targetType); + } + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToObjectConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToObjectConverter.java index 4f59c048150..1f9fcbcdf3b 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToObjectConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToObjectConverter.java @@ -16,7 +16,6 @@ package org.springframework.core.convert.support; -import static org.springframework.core.convert.support.ConversionUtils.getElementType; import static org.springframework.core.convert.support.ConversionUtils.invokeConverter; import java.util.Collection; @@ -36,8 +35,6 @@ import org.springframework.core.convert.converter.GenericConverter; */ final class CollectionToObjectConverter implements ConditionalGenericConverter { - private static final String DELIMITER = ","; - private final GenericConversionService conversionService; public CollectionToObjectConverter(GenericConversionService conversionService) { @@ -58,60 +55,21 @@ final class CollectionToObjectConverter implements ConditionalGenericConverter { } Collection sourceCollection = (Collection) source; if (sourceCollection.size() == 0) { - if (targetType.typeEquals(String.class)) { - return ""; - } else { - return null; - } + return null; } else { - if (targetType.typeEquals(String.class)) { - TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor(); - if (sourceElementType == TypeDescriptor.NULL) { - sourceElementType = getElementType(sourceCollection); - } - if (sourceElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetType)) { - StringBuilder string = new StringBuilder(); - int i = 0; - for (Object element : sourceCollection) { - if (i > 0) { - string.append(DELIMITER); - } - string.append(element); - i++; - } - return string.toString(); - } else { - GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetType); - if (converter == null) { - throw new ConverterNotFoundException(sourceElementType, targetType); - } - StringBuilder string = new StringBuilder(); - int i = 0; - for (Object sourceElement : sourceCollection) { - if (i > 0) { - string.append(DELIMITER); - } - Object targetElement = invokeConverter(converter, sourceElement, sourceElementType, targetType); - string.append(targetElement); - i++; - } - return string.toString(); - } + Object firstElement = sourceCollection.iterator().next(); + TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor(); + if (sourceElementType == TypeDescriptor.NULL && firstElement != null) { + sourceElementType = TypeDescriptor.valueOf(firstElement.getClass()); + } + if (sourceElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetType)) { + return firstElement; } else { - Object firstElement = sourceCollection.iterator().next(); - TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor(); - if (sourceElementType == TypeDescriptor.NULL && firstElement != null) { - sourceElementType = TypeDescriptor.valueOf(firstElement.getClass()); - } - if (sourceElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetType)) { - return firstElement; - } else { - GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetType); - if (converter == null) { - throw new ConverterNotFoundException(sourceElementType, targetType); - } - return invokeConverter(converter, firstElement, sourceElementType, targetType); + GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetType); + if (converter == null) { + throw new ConverterNotFoundException(sourceElementType, targetType); } + return invokeConverter(converter, firstElement, sourceElementType, targetType); } } } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToStringConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToStringConverter.java new file mode 100644 index 00000000000..24a9a914b28 --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/CollectionToStringConverter.java @@ -0,0 +1,97 @@ +/* + * Copyright 2002-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 static org.springframework.core.convert.support.ConversionUtils.getElementType; +import static org.springframework.core.convert.support.ConversionUtils.invokeConverter; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.TypeDescriptor; +import org.springframework.core.convert.converter.ConditionalGenericConverter; +import org.springframework.core.convert.converter.GenericConverter; + +/** + * Converts from a Collection to a String. + * + * @author Keith Donald + * @since 3.0 + */ +final class CollectionToStringConverter implements ConditionalGenericConverter { + + private static final String DELIMITER = ","; + + private final GenericConversionService conversionService; + + public CollectionToStringConverter(GenericConversionService conversionService) { + this.conversionService = conversionService; + } + + public Set getConvertibleTypes() { + return Collections.singleton(new ConvertiblePair(Collection.class, String.class)); + } + + public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { + return this.conversionService.canConvert(sourceType.getElementTypeDescriptor(), targetType); + } + + public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { + if (source == null) { + return this.conversionService.convertNullSource(sourceType, targetType); + } + Collection sourceCollection = (Collection) source; + if (sourceCollection.size() == 0) { + return ""; + } else { + TypeDescriptor sourceElementType = sourceType.getElementTypeDescriptor(); + if (sourceElementType == TypeDescriptor.NULL) { + sourceElementType = getElementType(sourceCollection); + } + if (sourceElementType == TypeDescriptor.NULL || sourceElementType.isAssignableTo(targetType)) { + StringBuilder string = new StringBuilder(); + int i = 0; + for (Object element : sourceCollection) { + if (i > 0) { + string.append(DELIMITER); + } + string.append(element); + i++; + } + return string.toString(); + } else { + GenericConverter converter = this.conversionService.getConverter(sourceElementType, targetType); + if (converter == null) { + throw new ConverterNotFoundException(sourceElementType, targetType); + } + StringBuilder string = new StringBuilder(); + int i = 0; + for (Object sourceElement : sourceCollection) { + if (i > 0) { + string.append(DELIMITER); + } + Object targetElement = invokeConverter(converter, sourceElement, sourceElementType, targetType); + string.append(targetElement); + i++; + } + return string.toString(); + } + } + } +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionServiceFactory.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionServiceFactory.java index 42261dfe3b8..a5fa4874822 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionServiceFactory.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ConversionServiceFactory.java @@ -49,27 +49,33 @@ public abstract class ConversionServiceFactory { conversionService.addGenericConverter(new ArrayToArrayConverter(conversionService)); conversionService.addGenericConverter(new ArrayToCollectionConverter(conversionService)); conversionService.addGenericConverter(new ArrayToMapConverter(conversionService)); + conversionService.addGenericConverter(new ArrayToStringConverter(conversionService)); conversionService.addGenericConverter(new ArrayToObjectConverter(conversionService)); conversionService.addGenericConverter(new CollectionToCollectionConverter(conversionService)); conversionService.addGenericConverter(new CollectionToArrayConverter(conversionService)); conversionService.addGenericConverter(new CollectionToMapConverter(conversionService)); + conversionService.addGenericConverter(new CollectionToStringConverter(conversionService)); conversionService.addGenericConverter(new CollectionToObjectConverter(conversionService)); conversionService.addGenericConverter(new MapToMapConverter(conversionService)); conversionService.addGenericConverter(new MapToArrayConverter(conversionService)); conversionService.addGenericConverter(new MapToCollectionConverter(conversionService)); + conversionService.addGenericConverter(new MapToStringConverter(conversionService)); conversionService.addGenericConverter(new MapToObjectConverter(conversionService)); + conversionService.addGenericConverter(new StringToArrayConverter(conversionService)); + conversionService.addGenericConverter(new StringToCollectionConverter(conversionService)); + conversionService.addGenericConverter(new StringToMapConverter(conversionService)); conversionService.addGenericConverter(new ObjectToArrayConverter(conversionService)); conversionService.addGenericConverter(new ObjectToCollectionConverter(conversionService)); conversionService.addGenericConverter(new ObjectToMapConverter(conversionService)); - conversionService.addConverter(new ObjectToStringConverter()); + conversionService.addConverterFactory(new CharacterToNumberFactory()); + conversionService.addConverter(new NumberToCharacterConverter()); + conversionService.addConverterFactory(new NumberToNumberConverterFactory()); conversionService.addConverter(new StringToBooleanConverter()); conversionService.addConverter(new StringToCharacterConverter()); - conversionService.addConverter(new StringToLocaleConverter()); - conversionService.addConverter(new NumberToCharacterConverter()); - conversionService.addConverterFactory(new StringToNumberConverterFactory()); conversionService.addConverterFactory(new StringToEnumConverterFactory()); - conversionService.addConverterFactory(new NumberToNumberConverterFactory()); - conversionService.addConverterFactory(new CharacterToNumberFactory()); + conversionService.addConverter(new StringToLocaleConverter()); + conversionService.addConverterFactory(new StringToNumberConverterFactory()); + conversionService.addConverter(new ObjectToStringConverter()); conversionService.addGenericConverter(new ObjectToObjectGenericConverter()); conversionService.addGenericConverter(new IdToEntityConverter(conversionService)); } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringConverter.java new file mode 100644 index 00000000000..6ced5cb5678 --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/MapToStringConverter.java @@ -0,0 +1,109 @@ +/* + * Copyright 2002-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 static org.springframework.core.convert.support.ConversionUtils.getMapEntryTypes; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Collections; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.springframework.core.convert.TypeDescriptor; +import org.springframework.core.convert.converter.ConditionalGenericConverter; + +/** + * Converts from a Map to a String. + * + * @author Keith Donald + * @since 3.0 + */ +final class MapToStringConverter implements ConditionalGenericConverter { + + private final GenericConversionService conversionService; + + public MapToStringConverter(GenericConversionService conversionService) { + this.conversionService = conversionService; + } + + public Set getConvertibleTypes() { + return Collections.singleton(new ConvertiblePair(Map.class, String.class)); + } + + public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { + return this.conversionService.canConvert(sourceType.getMapKeyTypeDescriptor(), targetType) + && this.conversionService.canConvert(sourceType.getMapValueTypeDescriptor(), targetType); + } + + public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { + if (source == null) { + return this.conversionService.convertNullSource(sourceType, targetType); + } + Map sourceMap = (Map) source; + if (sourceMap.size() == 0) { + return ""; + } else { + TypeDescriptor sourceKeyType = sourceType.getMapKeyTypeDescriptor(); + TypeDescriptor sourceValueType = sourceType.getMapValueTypeDescriptor(); + if (sourceKeyType == TypeDescriptor.NULL || sourceValueType == TypeDescriptor.NULL) { + TypeDescriptor[] sourceEntryTypes = getMapEntryTypes(sourceMap); + sourceKeyType = sourceEntryTypes[0]; + sourceValueType = sourceEntryTypes[1]; + } + boolean keysCompatible = false; + if (sourceKeyType != TypeDescriptor.NULL && sourceKeyType.isAssignableTo(targetType)) { + keysCompatible = true; + } + boolean valuesCompatible = false; + if (sourceValueType != TypeDescriptor.NULL && sourceValueType.isAssignableTo(targetType)) { + valuesCompatible = true; + } + Properties props = new Properties(); + if (keysCompatible && valuesCompatible) { + for (Object entry : sourceMap.entrySet()) { + Map.Entry mapEntry = (Map.Entry) entry; + props.setProperty((String) mapEntry.getKey(), (String) mapEntry.getValue()); + } + return store(props); + } else { + MapEntryConverter converter = new MapEntryConverter(sourceKeyType, sourceValueType, targetType, + targetType, keysCompatible, valuesCompatible, this.conversionService); + for (Object entry : sourceMap.entrySet()) { + Map.Entry mapEntry = (Map.Entry) entry; + Object key = converter.convertKey(mapEntry.getKey()); + Object value = converter.convertValue(mapEntry.getValue()); + props.setProperty((String) key, (String) value); + } + return store(props); + } + } + } + + private String store(Properties props) { + try { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + props.store(os, null); + return os.toString("ISO-8859-1"); + } catch (IOException e) { + // Should never happen. + throw new IllegalArgumentException("Failed to store [" + props + "] into String", e); + } + } + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArrayConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArrayConverter.java index 69f8561e6aa..c1b9456643d 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArrayConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToArrayConverter.java @@ -26,7 +26,6 @@ import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; import org.springframework.core.convert.converter.GenericConverter; -import org.springframework.util.StringUtils; /** * Converts from a single Object to an array. @@ -53,40 +52,19 @@ final class ObjectToArrayConverter implements ConditionalGenericConverter { public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { return this.conversionService.convertNullSource(sourceType, targetType); - } - TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); - if (sourceType.typeEquals(String.class)) { - String string = (String) source; - String[] fields = StringUtils.commaDelimitedListToStringArray(string); - if (sourceType.isAssignableTo(targetElementType)) { - return fields; - } - else { - Object target = Array.newInstance(targetElementType.getType(), fields.length); - GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); - if (converter == null) { - throw new ConverterNotFoundException(sourceType, targetElementType); - } - for (int i = 0; i < fields.length; i++) { - Array.set(target, i, invokeConverter(converter, fields[i], sourceType, targetElementType)); - } - return target; - } } - else { - Object target = Array.newInstance(targetElementType.getType(), 1); - if (sourceType.isAssignableTo(targetElementType)) { - Array.set(target, 0, source); - } - else { - GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); - if (converter == null) { - throw new ConverterNotFoundException(sourceType, targetElementType); - } - Array.set(target, 0, invokeConverter(converter, source, sourceType, targetElementType)); + TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); + Object target = Array.newInstance(targetElementType.getType(), 1); + if (sourceType.isAssignableTo(targetElementType)) { + Array.set(target, 0, source); + } else { + GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); + if (converter == null) { + throw new ConverterNotFoundException(sourceType, targetElementType); } - return target; + Array.set(target, 0, invokeConverter(converter, source, sourceType, targetElementType)); } + return target; } } \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollectionConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollectionConverter.java index 3a53d18eeed..fafc6d0b20c 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollectionConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToCollectionConverter.java @@ -27,7 +27,6 @@ import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.ConditionalGenericConverter; import org.springframework.core.convert.converter.GenericConverter; -import org.springframework.util.StringUtils; /** * Converts from a single Object to a Collection. @@ -52,48 +51,22 @@ final class ObjectToCollectionConverter implements ConditionalGenericConverter { } @SuppressWarnings("unchecked") - public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { + public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { if (source == null) { return this.conversionService.convertNullSource(sourceType, targetType); } + Collection target = CollectionFactory.createCollection(targetType.getType(), 1); TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); - if (sourceType.typeEquals(String.class)) { - String string = (String) source; - String[] fields = StringUtils.commaDelimitedListToStringArray(string); - Collection target = CollectionFactory.createCollection(targetType.getType(), fields.length); - if (targetElementType == TypeDescriptor.NULL || sourceType.isAssignableTo(targetElementType)) { - for (int i = 0; i < fields.length; i++) { - target.add(fields[i]); - } + if (targetElementType == TypeDescriptor.NULL || sourceType.isAssignableTo(targetElementType)) { + target.add(source); + } else { + GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); + if (converter == null) { + throw new ConverterNotFoundException(sourceType, targetElementType); } - else { - GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); - if (converter == null) { - throw new ConverterNotFoundException(sourceType, targetElementType); - } - for (int i = 0; i < fields.length; i++) { - String sourceElement = fields[i]; - Object targetElement = invokeConverter(converter, sourceElement, sourceType, targetElementType); - target.add(targetElement); - } - } - return target; - - } - else { - Collection target = CollectionFactory.createCollection(targetType.getType(), 1); - if (targetElementType == TypeDescriptor.NULL || sourceType.isAssignableTo(targetElementType)) { - target.add(source); - } - else { - GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); - if (converter == null) { - throw new ConverterNotFoundException(sourceType, targetElementType); - } - target.add(invokeConverter(converter, source, sourceType, targetElementType)); - } - return target; + target.add(invokeConverter(converter, source, sourceType, targetElementType)); } + return target; } } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToMapConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToMapConverter.java index 0209599aaf2..f34cee41af1 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToMapConverter.java +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/ObjectToMapConverter.java @@ -16,10 +16,8 @@ package org.springframework.core.convert.support; -import java.io.ByteArrayInputStream; import java.util.Collections; import java.util.Map; -import java.util.Properties; import java.util.Set; import org.springframework.core.CollectionFactory; @@ -45,8 +43,8 @@ final class ObjectToMapConverter implements ConditionalGenericConverter { } public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { - return this.conversionService.canConvert(sourceType, targetType.getMapKeyTypeDescriptor()) && - this.conversionService.canConvert(sourceType, targetType.getMapValueTypeDescriptor()); + return this.conversionService.canConvert(sourceType, targetType.getMapKeyTypeDescriptor()) + && this.conversionService.canConvert(sourceType, targetType.getMapValueTypeDescriptor()); } @SuppressWarnings("unchecked") @@ -54,44 +52,27 @@ final class ObjectToMapConverter implements ConditionalGenericConverter { if (source == null) { return this.conversionService.convertNullSource(sourceType, targetType); } - if (sourceType.typeEquals(String.class)) { - String string = (String) source; - return this.conversionService.convert(loadProperties(string), TypeDescriptor.valueOf(Properties.class), targetType); - } else { - Map target = CollectionFactory.createMap(targetType.getType(), 1); - TypeDescriptor targetKeyType = targetType.getMapKeyTypeDescriptor(); - TypeDescriptor targetValueType = targetType.getMapValueTypeDescriptor(); - boolean keysCompatible = false; - if (sourceType != TypeDescriptor.NULL && sourceType.isAssignableTo(targetKeyType)) { - keysCompatible = true; - } - boolean valuesCompatible = false; - if (sourceType != TypeDescriptor.NULL && sourceType.isAssignableTo(targetValueType)) { - valuesCompatible = true; - } - if (keysCompatible && valuesCompatible) { - target.put(source, source); - } else { - MapEntryConverter converter = new MapEntryConverter(sourceType, sourceType, targetKeyType, - targetValueType, keysCompatible, valuesCompatible, this.conversionService); - Object key = converter.convertKey(source); - Object value = converter.convertValue(source); - target.put(key, value); - } - return target; + Map target = CollectionFactory.createMap(targetType.getType(), 1); + TypeDescriptor targetKeyType = targetType.getMapKeyTypeDescriptor(); + TypeDescriptor targetValueType = targetType.getMapValueTypeDescriptor(); + boolean keysCompatible = false; + if (sourceType != TypeDescriptor.NULL && sourceType.isAssignableTo(targetKeyType)) { + keysCompatible = true; } - } - - private Properties loadProperties(String string) { - try { - Properties props = new Properties(); - // Must use the ISO-8859-1 encoding because Properties.load(stream) expects it. - props.load(new ByteArrayInputStream(string.getBytes("ISO-8859-1"))); - return props; - } catch (Exception e) { - // Should never happen. - throw new IllegalArgumentException("Failed to parse [" + string + "] into Properties", e); + boolean valuesCompatible = false; + if (sourceType != TypeDescriptor.NULL && sourceType.isAssignableTo(targetValueType)) { + valuesCompatible = true; + } + if (keysCompatible && valuesCompatible) { + target.put(source, source); + } else { + MapEntryConverter converter = new MapEntryConverter(sourceType, sourceType, targetKeyType, targetValueType, + keysCompatible, valuesCompatible, this.conversionService); + Object key = converter.convertKey(source); + Object value = converter.convertValue(source); + target.put(key, value); } + return target; } } diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArrayConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArrayConverter.java new file mode 100644 index 00000000000..aec1ca9606c --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToArrayConverter.java @@ -0,0 +1,76 @@ +/* + * Copyright 2002-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 static org.springframework.core.convert.support.ConversionUtils.invokeConverter; + +import java.lang.reflect.Array; +import java.util.Collections; +import java.util.Set; + +import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.TypeDescriptor; +import org.springframework.core.convert.converter.ConditionalGenericConverter; +import org.springframework.core.convert.converter.GenericConverter; +import org.springframework.util.StringUtils; + +/** + * Converts from a delimited String to an array. + * + * @author Keith Donald + * @since 3.0 + */ +final class StringToArrayConverter implements ConditionalGenericConverter { + + private final GenericConversionService conversionService; + + public StringToArrayConverter(GenericConversionService conversionService) { + this.conversionService = conversionService; + } + + public Set getConvertibleTypes() { + return Collections.singleton(new ConvertiblePair(String.class, Object[].class)); + } + + public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { + return this.conversionService.canConvert(sourceType, targetType.getElementTypeDescriptor()); + } + + public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { + if (source == null) { + return this.conversionService.convertNullSource(sourceType, targetType); + } + String string = (String) source; + String[] fields = StringUtils.commaDelimitedListToStringArray(string); + TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); + if (sourceType.isAssignableTo(targetElementType)) { + return fields; + } + else { + Object target = Array.newInstance(targetElementType.getType(), fields.length); + GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); + if (converter == null) { + throw new ConverterNotFoundException(sourceType, targetElementType); + } + for (int i = 0; i < fields.length; i++) { + Array.set(target, i, invokeConverter(converter, fields[i], sourceType, targetElementType)); + } + return target; + } + } + +} \ No newline at end of file diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollectionConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollectionConverter.java new file mode 100644 index 00000000000..d8e534929a1 --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToCollectionConverter.java @@ -0,0 +1,82 @@ +/* + * Copyright 2002-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 static org.springframework.core.convert.support.ConversionUtils.invokeConverter; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import org.springframework.core.CollectionFactory; +import org.springframework.core.convert.ConverterNotFoundException; +import org.springframework.core.convert.TypeDescriptor; +import org.springframework.core.convert.converter.ConditionalGenericConverter; +import org.springframework.core.convert.converter.GenericConverter; +import org.springframework.util.StringUtils; + +/** + * Converts from a String to a Collection. + * + * @author Keith Donald + * @since 3.0 + */ +final class StringToCollectionConverter implements ConditionalGenericConverter { + + private final GenericConversionService conversionService; + + public StringToCollectionConverter(GenericConversionService conversionService) { + this.conversionService = conversionService; + } + + public Set getConvertibleTypes() { + return Collections.singleton(new ConvertiblePair(String.class, Collection.class)); + } + + public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { + return this.conversionService.canConvert(sourceType, targetType.getElementTypeDescriptor()); + } + + @SuppressWarnings("unchecked") + public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { + if (source == null) { + return this.conversionService.convertNullSource(sourceType, targetType); + } + String string = (String) source; + String[] fields = StringUtils.commaDelimitedListToStringArray(string); + Collection target = CollectionFactory.createCollection(targetType.getType(), fields.length); + TypeDescriptor targetElementType = targetType.getElementTypeDescriptor(); + if (targetElementType == TypeDescriptor.NULL || sourceType.isAssignableTo(targetElementType)) { + for (int i = 0; i < fields.length; i++) { + target.add(fields[i]); + } + } + else { + GenericConverter converter = this.conversionService.getConverter(sourceType, targetElementType); + if (converter == null) { + throw new ConverterNotFoundException(sourceType, targetElementType); + } + for (int i = 0; i < fields.length; i++) { + String sourceElement = fields[i]; + Object targetElement = invokeConverter(converter, sourceElement, sourceType, targetElementType); + target.add(targetElement); + } + } + return target; + } + +} diff --git a/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToMapConverter.java b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToMapConverter.java new file mode 100644 index 00000000000..d2e6637aadc --- /dev/null +++ b/org.springframework.core/src/main/java/org/springframework/core/convert/support/StringToMapConverter.java @@ -0,0 +1,71 @@ +/* + * Copyright 2002-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.io.ByteArrayInputStream; +import java.util.Collections; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.springframework.core.convert.TypeDescriptor; +import org.springframework.core.convert.converter.ConditionalGenericConverter; + +/** + * Converts from a String to a Map. + * + * @author Keith Donald + * @since 3.0 + */ +final class StringToMapConverter implements ConditionalGenericConverter { + + private final GenericConversionService conversionService; + + public StringToMapConverter(GenericConversionService conversionService) { + this.conversionService = conversionService; + } + + public Set getConvertibleTypes() { + return Collections.singleton(new ConvertiblePair(String.class, Map.class)); + } + + public boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) { + return this.conversionService.canConvert(sourceType, targetType.getMapKeyTypeDescriptor()) && + this.conversionService.canConvert(sourceType, targetType.getMapValueTypeDescriptor()); + } + + public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { + if (source == null) { + return this.conversionService.convertNullSource(sourceType, targetType); + } + String string = (String) source; + return this.conversionService.convert(loadProperties(string), TypeDescriptor.valueOf(Properties.class), targetType); + } + + private Properties loadProperties(String string) { + try { + Properties props = new Properties(); + // Must use the ISO-8859-1 encoding because Properties.load(stream) expects it. + props.load(new ByteArrayInputStream(string.getBytes("ISO-8859-1"))); + return props; + } catch (Exception e) { + // Should never happen. + throw new IllegalArgumentException("Failed to parse [" + string + "] into Properties", e); + } + } + +}