@@ -195,28 +195,32 @@ else if (requiredType.isArray()) {
195195 // Array required -> apply appropriate conversion of elements.
196196 return (T ) convertToTypedArray (convertedValue , propertyName , requiredType .getComponentType ());
197197 }
198- else if (convertedValue instanceof Collection && CollectionFactory . isApproximableCollectionType ( requiredType ) ) {
198+ else if (convertedValue instanceof Collection ) {
199199 // Convert elements to target type, if determined.
200- convertedValue = convertToTypedCollection ((Collection ) convertedValue , propertyName , methodParam );
200+ convertedValue = convertToTypedCollection (
201+ (Collection ) convertedValue , propertyName , requiredType , methodParam );
201202 }
202- else if (convertedValue instanceof Map && CollectionFactory . isApproximableMapType ( requiredType ) ) {
203+ else if (convertedValue instanceof Map ) {
203204 // Convert keys and values to respective target type, if determined.
204- convertedValue = convertToTypedMap ((Map ) convertedValue , propertyName , methodParam );
205+ convertedValue = convertToTypedMap (
206+ (Map ) convertedValue , propertyName , requiredType , methodParam );
205207 }
206208 else if (convertedValue instanceof String && !requiredType .isInstance (convertedValue )) {
207- try {
208- Constructor strCtor = requiredType .getConstructor (String .class );
209- return (T ) BeanUtils .instantiateClass (strCtor , convertedValue );
210- }
211- catch (NoSuchMethodException ex ) {
212- // proceed with field lookup
213- if (logger .isTraceEnabled ()) {
214- logger .trace ("No String constructor found on type [" + requiredType .getName () + "]" , ex );
209+ if (!requiredType .isInterface () && !requiredType .isEnum ()) {
210+ try {
211+ Constructor strCtor = requiredType .getConstructor (String .class );
212+ return (T ) BeanUtils .instantiateClass (strCtor , convertedValue );
215213 }
216- }
217- catch (Exception ex ) {
218- if (logger .isTraceEnabled ()) {
219- logger .trace ("Construction via String failed for type [" + requiredType .getName () + "]" , ex );
214+ catch (NoSuchMethodException ex ) {
215+ // proceed with field lookup
216+ if (logger .isTraceEnabled ()) {
217+ logger .trace ("No String constructor found on type [" + requiredType .getName () + "]" , ex );
218+ }
219+ }
220+ catch (Exception ex ) {
221+ if (logger .isDebugEnabled ()) {
222+ logger .debug ("Construction via String failed for type [" + requiredType .getName () + "]" , ex );
223+ }
220224 }
221225 }
222226 String trimmedValue = ((String ) convertedValue ).trim ();
@@ -431,18 +435,8 @@ else if (input.getClass().isArray()) {
431435
432436 @ SuppressWarnings ("unchecked" )
433437 protected Collection convertToTypedCollection (
434- Collection original , String propertyName , MethodParameter methodParam ) {
435-
436- Class elementType = null ;
437- if (methodParam != null ) {
438- elementType = GenericCollectionTypeResolver .getCollectionParameterType (methodParam );
439- }
440- if (elementType == null &&
441- !this .propertyEditorRegistry .hasCustomEditorForElement (null , propertyName )) {
442- return original ;
443- }
438+ Collection original , String propertyName , Class requiredType , MethodParameter methodParam ) {
444439
445- Collection convertedCopy ;
446440 Iterator it ;
447441 try {
448442 it = original .iterator ();
@@ -453,7 +447,6 @@ protected Collection convertToTypedCollection(
453447 }
454448 return original ;
455449 }
456- convertedCopy = CollectionFactory .createApproximateCollection (original , original .size ());
457450 }
458451 catch (Throwable ex ) {
459452 if (logger .isDebugEnabled ()) {
@@ -462,7 +455,34 @@ protected Collection convertToTypedCollection(
462455 }
463456 return original ;
464457 }
465- boolean actuallyConverted = false ;
458+
459+ Collection convertedCopy ;
460+ try {
461+ if (CollectionFactory .isApproximableCollectionType (requiredType )) {
462+ convertedCopy = CollectionFactory .createApproximateCollection (original , original .size ());
463+ }
464+ else {
465+ convertedCopy = (Collection ) requiredType .newInstance ();
466+ }
467+ }
468+ catch (Throwable ex ) {
469+ if (logger .isDebugEnabled ()) {
470+ logger .debug ("Cannot create copy of Collection type [" + original .getClass ().getName () +
471+ "] - injecting original Collection as-is" , ex );
472+ }
473+ return original ;
474+ }
475+
476+ boolean originalAllowed = requiredType .isInstance (original );
477+ Class elementType = null ;
478+ if (methodParam != null ) {
479+ elementType = GenericCollectionTypeResolver .getCollectionParameterType (methodParam );
480+ }
481+ if (elementType == null && originalAllowed &&
482+ !this .propertyEditorRegistry .hasCustomEditorForElement (null , propertyName )) {
483+ return original ;
484+ }
485+
466486 int i = 0 ;
467487 for (; it .hasNext (); i ++) {
468488 Object element = it .next ();
@@ -476,25 +496,13 @@ protected Collection convertToTypedCollection(
476496 methodParam .decreaseNestingLevel ();
477497 }
478498 convertedCopy .add (convertedElement );
479- actuallyConverted = actuallyConverted || (element ! = convertedElement );
499+ originalAllowed = originalAllowed && (element = = convertedElement );
480500 }
481- return (actuallyConverted ? convertedCopy : original );
501+ return (originalAllowed ? original : convertedCopy );
482502 }
483503
484504 @ SuppressWarnings ("unchecked" )
485- protected Map convertToTypedMap (Map original , String propertyName , MethodParameter methodParam ) {
486- Class keyType = null ;
487- Class valueType = null ;
488- if (methodParam != null ) {
489- keyType = GenericCollectionTypeResolver .getMapKeyParameterType (methodParam );
490- valueType = GenericCollectionTypeResolver .getMapValueParameterType (methodParam );
491- }
492- if (keyType == null && valueType == null &&
493- !this .propertyEditorRegistry .hasCustomEditorForElement (null , propertyName )) {
494- return original ;
495- }
496-
497- Map convertedCopy ;
505+ protected Map convertToTypedMap (Map original , String propertyName , Class requiredType , MethodParameter methodParam ) {
498506 Iterator it ;
499507 try {
500508 it = original .entrySet ().iterator ();
@@ -505,7 +513,6 @@ protected Map convertToTypedMap(Map original, String propertyName, MethodParamet
505513 }
506514 return original ;
507515 }
508- convertedCopy = CollectionFactory .createApproximateMap (original , original .size ());
509516 }
510517 catch (Throwable ex ) {
511518 if (logger .isDebugEnabled ()) {
@@ -514,7 +521,36 @@ protected Map convertToTypedMap(Map original, String propertyName, MethodParamet
514521 }
515522 return original ;
516523 }
517- boolean actuallyConverted = false ;
524+
525+ Map convertedCopy ;
526+ try {
527+ if (CollectionFactory .isApproximableMapType (requiredType )) {
528+ convertedCopy = CollectionFactory .createApproximateMap (original , original .size ());
529+ }
530+ else {
531+ convertedCopy = (Map ) requiredType .newInstance ();
532+ }
533+ }
534+ catch (Throwable ex ) {
535+ if (logger .isDebugEnabled ()) {
536+ logger .debug ("Cannot create copy of Map type [" + original .getClass ().getName () +
537+ "] - injecting original Map as-is" , ex );
538+ }
539+ return original ;
540+ }
541+
542+ boolean originalAllowed = requiredType .isInstance (original );
543+ Class keyType = null ;
544+ Class valueType = null ;
545+ if (methodParam != null ) {
546+ keyType = GenericCollectionTypeResolver .getMapKeyParameterType (methodParam );
547+ valueType = GenericCollectionTypeResolver .getMapValueParameterType (methodParam );
548+ }
549+ if (keyType == null && valueType == null && originalAllowed &&
550+ !this .propertyEditorRegistry .hasCustomEditorForElement (null , propertyName )) {
551+ return original ;
552+ }
553+
518554 while (it .hasNext ()) {
519555 Map .Entry entry = (Map .Entry ) it .next ();
520556 Object key = entry .getKey ();
@@ -533,9 +569,9 @@ protected Map convertToTypedMap(Map original, String propertyName, MethodParamet
533569 methodParam .decreaseNestingLevel ();
534570 }
535571 convertedCopy .put (convertedKey , convertedValue );
536- actuallyConverted = actuallyConverted || (key != convertedKey ) || (value ! = convertedValue );
572+ originalAllowed = originalAllowed && (key == convertedKey ) && (value = = convertedValue );
537573 }
538- return (actuallyConverted ? convertedCopy : original );
574+ return (originalAllowed ? original : convertedCopy );
539575 }
540576
541577 private String buildIndexedPropertyName (String propertyName , int index ) {
0 commit comments