|
|
|
|
@ -20,6 +20,7 @@ import java.beans.PropertyEditor;
@@ -20,6 +20,7 @@ import java.beans.PropertyEditor;
|
|
|
|
|
import java.lang.reflect.Array; |
|
|
|
|
import java.lang.reflect.Constructor; |
|
|
|
|
import java.lang.reflect.Field; |
|
|
|
|
import java.lang.reflect.Modifier; |
|
|
|
|
import java.util.Collection; |
|
|
|
|
import java.util.Iterator; |
|
|
|
|
import java.util.Map; |
|
|
|
|
@ -461,10 +462,20 @@ class TypeConverterDelegate {
@@ -461,10 +462,20 @@ class TypeConverterDelegate {
|
|
|
|
|
protected Collection convertToTypedCollection( |
|
|
|
|
Collection original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) { |
|
|
|
|
|
|
|
|
|
boolean originalAllowed = requiredType.isInstance(original); |
|
|
|
|
if (!originalAllowed && !Collection.class.isAssignableFrom(requiredType)) { |
|
|
|
|
if (!Collection.class.isAssignableFrom(requiredType)) { |
|
|
|
|
return original; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
boolean approximable = CollectionFactory.isApproximableCollectionType(requiredType); |
|
|
|
|
if (!approximable && !canCreateCopy(requiredType)) { |
|
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
|
logger.debug("Custom Collection type [" + original.getClass().getName() + |
|
|
|
|
"] does not allow for creating a copy - injecting original Collection as-is"); |
|
|
|
|
} |
|
|
|
|
return original; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
boolean originalAllowed = requiredType.isInstance(original); |
|
|
|
|
typeDescriptor = typeDescriptor.narrow(original); |
|
|
|
|
TypeDescriptor elementType = typeDescriptor.getElementTypeDescriptor(); |
|
|
|
|
if (elementType == null && originalAllowed && |
|
|
|
|
@ -486,14 +497,14 @@ class TypeConverterDelegate {
@@ -486,14 +497,14 @@ class TypeConverterDelegate {
|
|
|
|
|
catch (Throwable ex) { |
|
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
|
logger.debug("Cannot access Collection of type [" + original.getClass().getName() + |
|
|
|
|
"] - injecting original Collection as-is", ex); |
|
|
|
|
"] - injecting original Collection as-is: " + ex); |
|
|
|
|
} |
|
|
|
|
return original; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Collection convertedCopy; |
|
|
|
|
try { |
|
|
|
|
if (CollectionFactory.isApproximableCollectionType(requiredType)) { |
|
|
|
|
if (approximable) { |
|
|
|
|
convertedCopy = CollectionFactory.createApproximateCollection(original, original.size()); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
@ -503,7 +514,7 @@ class TypeConverterDelegate {
@@ -503,7 +514,7 @@ class TypeConverterDelegate {
|
|
|
|
|
catch (Throwable ex) { |
|
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
|
logger.debug("Cannot create copy of Collection type [" + original.getClass().getName() + |
|
|
|
|
"] - injecting original Collection as-is", ex); |
|
|
|
|
"] - injecting original Collection as-is: " + ex); |
|
|
|
|
} |
|
|
|
|
return original; |
|
|
|
|
} |
|
|
|
|
@ -512,15 +523,15 @@ class TypeConverterDelegate {
@@ -512,15 +523,15 @@ class TypeConverterDelegate {
|
|
|
|
|
for (; it.hasNext(); i++) { |
|
|
|
|
Object element = it.next(); |
|
|
|
|
String indexedPropertyName = buildIndexedPropertyName(propertyName, i); |
|
|
|
|
Object convertedElement = convertIfNecessary( |
|
|
|
|
indexedPropertyName, null, element, elementType != null ? elementType.getType() : null , typeDescriptor.getElementTypeDescriptor()); |
|
|
|
|
Object convertedElement = convertIfNecessary(indexedPropertyName, null, element, |
|
|
|
|
(elementType != null ? elementType.getType() : null) , typeDescriptor.getElementTypeDescriptor()); |
|
|
|
|
try { |
|
|
|
|
convertedCopy.add(convertedElement); |
|
|
|
|
} |
|
|
|
|
catch (Throwable ex) { |
|
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
|
logger.debug("Collection type [" + original.getClass().getName() + |
|
|
|
|
"] seems to be read-only - injecting original Collection as-is", ex); |
|
|
|
|
"] seems to be read-only - injecting original Collection as-is: " + ex); |
|
|
|
|
} |
|
|
|
|
return original; |
|
|
|
|
} |
|
|
|
|
@ -533,10 +544,20 @@ class TypeConverterDelegate {
@@ -533,10 +544,20 @@ class TypeConverterDelegate {
|
|
|
|
|
protected Map convertToTypedMap( |
|
|
|
|
Map original, String propertyName, Class requiredType, TypeDescriptor typeDescriptor) { |
|
|
|
|
|
|
|
|
|
boolean originalAllowed = requiredType.isInstance(original); |
|
|
|
|
if (!originalAllowed && !Map.class.isAssignableFrom(requiredType)) { |
|
|
|
|
if (!Map.class.isAssignableFrom(requiredType)) { |
|
|
|
|
return original; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
boolean approximable = CollectionFactory.isApproximableMapType(requiredType); |
|
|
|
|
if (!approximable && !canCreateCopy(requiredType)) { |
|
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
|
logger.debug("Custom Map type [" + original.getClass().getName() + |
|
|
|
|
"] does not allow for creating a copy - injecting original Map as-is"); |
|
|
|
|
} |
|
|
|
|
return original; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
boolean originalAllowed = requiredType.isInstance(original); |
|
|
|
|
typeDescriptor = typeDescriptor.narrow(original); |
|
|
|
|
TypeDescriptor keyType = typeDescriptor.getMapKeyTypeDescriptor(); |
|
|
|
|
TypeDescriptor valueType = typeDescriptor.getMapValueTypeDescriptor(); |
|
|
|
|
@ -559,14 +580,14 @@ class TypeConverterDelegate {
@@ -559,14 +580,14 @@ class TypeConverterDelegate {
|
|
|
|
|
catch (Throwable ex) { |
|
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
|
logger.debug("Cannot access Map of type [" + original.getClass().getName() + |
|
|
|
|
"] - injecting original Map as-is", ex); |
|
|
|
|
"] - injecting original Map as-is: " + ex); |
|
|
|
|
} |
|
|
|
|
return original; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Map convertedCopy; |
|
|
|
|
try { |
|
|
|
|
if (CollectionFactory.isApproximableMapType(requiredType)) { |
|
|
|
|
if (approximable) { |
|
|
|
|
convertedCopy = CollectionFactory.createApproximateMap(original, original.size()); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
@ -576,7 +597,7 @@ class TypeConverterDelegate {
@@ -576,7 +597,7 @@ class TypeConverterDelegate {
|
|
|
|
|
catch (Throwable ex) { |
|
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
|
logger.debug("Cannot create copy of Map type [" + original.getClass().getName() + |
|
|
|
|
"] - injecting original Map as-is", ex); |
|
|
|
|
"] - injecting original Map as-is: " + ex); |
|
|
|
|
} |
|
|
|
|
return original; |
|
|
|
|
} |
|
|
|
|
@ -586,15 +607,17 @@ class TypeConverterDelegate {
@@ -586,15 +607,17 @@ class TypeConverterDelegate {
|
|
|
|
|
Object key = entry.getKey(); |
|
|
|
|
Object value = entry.getValue(); |
|
|
|
|
String keyedPropertyName = buildKeyedPropertyName(propertyName, key); |
|
|
|
|
Object convertedKey = convertIfNecessary(keyedPropertyName, null, key, keyType != null ? keyType.getType() : null, typeDescriptor.getMapKeyTypeDescriptor()); |
|
|
|
|
Object convertedValue = convertIfNecessary(keyedPropertyName, null, value, valueType!= null ? valueType.getType() : null, typeDescriptor.getMapValueTypeDescriptor()); |
|
|
|
|
Object convertedKey = convertIfNecessary(keyedPropertyName, null, key, |
|
|
|
|
(keyType != null ? keyType.getType() : null), typeDescriptor.getMapKeyTypeDescriptor()); |
|
|
|
|
Object convertedValue = convertIfNecessary(keyedPropertyName, null, value, |
|
|
|
|
(valueType!= null ? valueType.getType() : null), typeDescriptor.getMapValueTypeDescriptor()); |
|
|
|
|
try { |
|
|
|
|
convertedCopy.put(convertedKey, convertedValue); |
|
|
|
|
} |
|
|
|
|
catch (Throwable ex) { |
|
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
|
logger.debug("Map type [" + original.getClass().getName() + |
|
|
|
|
"] seems to be read-only - injecting original Map as-is", ex); |
|
|
|
|
"] seems to be read-only - injecting original Map as-is: " + ex); |
|
|
|
|
} |
|
|
|
|
return original; |
|
|
|
|
} |
|
|
|
|
@ -615,4 +638,9 @@ class TypeConverterDelegate {
@@ -615,4 +638,9 @@ class TypeConverterDelegate {
|
|
|
|
|
null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private boolean canCreateCopy(Class requiredType) { |
|
|
|
|
return (!requiredType.isInterface() && !Modifier.isAbstract(requiredType.getModifiers()) && |
|
|
|
|
Modifier.isPublic(requiredType.getModifiers()) && ClassUtils.hasConstructor(requiredType)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|