@SuppressWarnings("unchecked") private Map<?, ?> convertToTypedMap( Map<?, ?> original, String propertyName, Class<?> requiredType, TypeDescriptor typeDescriptor) { 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 keyType = typeDescriptor.getMapKeyTypeDescriptor(); TypeDescriptor valueType = typeDescriptor.getMapValueTypeDescriptor(); if (keyType == null && valueType == null && originalAllowed && !this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) { return original; } Iterator<?> it; try { it = original.entrySet().iterator(); if (it == null) { if (logger.isDebugEnabled()) { logger.debug( "Map of type [" + original.getClass().getName() + "] returned null Iterator - injecting original Map as-is"); } return original; } } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug( "Cannot access Map of type [" + original.getClass().getName() + "] - injecting original Map as-is: " + ex); } return original; } Map<Object, Object> convertedCopy; try { if (approximable) { convertedCopy = CollectionFactory.createApproximateMap(original, original.size()); } else { convertedCopy = (Map<Object, Object>) ReflectionUtils.accessibleConstructor(requiredType).newInstance(); } } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug( "Cannot create copy of Map type [" + original.getClass().getName() + "] - injecting original Map as-is: " + ex); } return original; } while (it.hasNext()) { Map.Entry<?, ?> entry = (Map.Entry<?, ?>) it.next(); Object key = entry.getKey(); Object value = entry.getValue(); String keyedPropertyName = buildKeyedPropertyName(propertyName, key); Object convertedKey = convertIfNecessary( keyedPropertyName, null, key, (keyType != null ? keyType.getType() : null), keyType); Object convertedValue = convertIfNecessary( keyedPropertyName, null, value, (valueType != null ? valueType.getType() : null), valueType); 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); } return original; } originalAllowed = originalAllowed && (key == convertedKey) && (value == convertedValue); } return (originalAllowed ? original : convertedCopy); }
@SuppressWarnings("unchecked") private Collection<?> convertToTypedCollection( Collection<?> original, String propertyName, Class<?> requiredType, TypeDescriptor typeDescriptor) { 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 elementType = typeDescriptor.getElementTypeDescriptor(); if (elementType == null && originalAllowed && !this.propertyEditorRegistry.hasCustomEditorForElement(null, propertyName)) { return original; } Iterator<?> it; try { it = original.iterator(); if (it == null) { if (logger.isDebugEnabled()) { logger.debug( "Collection of type [" + original.getClass().getName() + "] returned null Iterator - injecting original Collection as-is"); } return original; } } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug( "Cannot access Collection of type [" + original.getClass().getName() + "] - injecting original Collection as-is: " + ex); } return original; } Collection<Object> convertedCopy; try { if (approximable) { convertedCopy = CollectionFactory.createApproximateCollection(original, original.size()); } else { convertedCopy = (Collection<Object>) ReflectionUtils.accessibleConstructor(requiredType).newInstance(); } } catch (Throwable ex) { if (logger.isDebugEnabled()) { logger.debug( "Cannot create copy of Collection type [" + original.getClass().getName() + "] - injecting original Collection as-is: " + ex); } return original; } int i = 0; for (; it.hasNext(); i++) { Object element = it.next(); String indexedPropertyName = buildIndexedPropertyName(propertyName, i); Object convertedElement = convertIfNecessary( indexedPropertyName, null, element, (elementType != null ? elementType.getType() : null), elementType); 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); } return original; } originalAllowed = originalAllowed && (element == convertedElement); } return (originalAllowed ? original : convertedCopy); }