@@ -73,6 +73,12 @@ public class TypeDescriptor {
73
73
74
74
private Object value ;
75
75
76
+ private TypeDescriptor elementType ;
77
+
78
+ private TypeDescriptor mapKeyType ;
79
+
80
+ private TypeDescriptor mapValueType ;
81
+
76
82
/**
77
83
* Create a new type descriptor from a method or constructor parameter.
78
84
* <p>Use this constructor when a target conversion point originates from a method parameter,
@@ -233,22 +239,19 @@ public boolean isCollection() {
233
239
* Returns <code>null</code> if the type is neither an array or collection.
234
240
*/
235
241
public Class <?> getElementType () {
236
- if (isArray ()) {
237
- return getArrayComponentType ();
238
- }
239
- else if (isCollection ()) {
240
- return getCollectionElementType ();
241
- }
242
- else {
243
- return null ;
244
- }
242
+ return getElementTypeDescriptor ().getType ();
245
243
}
246
244
247
245
/**
248
246
* Return the element type as a type descriptor.
249
247
*/
250
248
public TypeDescriptor getElementTypeDescriptor () {
251
- return forElementType (getElementType ());
249
+ if (elementType != null ) {
250
+ return elementType ;
251
+ } else {
252
+ elementType = forElementType (resolveElementType ());
253
+ return elementType ;
254
+ }
252
255
}
253
256
254
257
/**
@@ -257,7 +260,8 @@ public TypeDescriptor getElementTypeDescriptor() {
257
260
* @return the element type descriptor
258
261
*/
259
262
public TypeDescriptor getElementTypeDescriptor (Object element ) {
260
- return getElementType () != null ? getElementTypeDescriptor () : TypeDescriptor .forObject (element );
263
+ TypeDescriptor elementType = getElementTypeDescriptor ();
264
+ return elementType != TypeDescriptor .NULL ? elementType : TypeDescriptor .forObject (element );
261
265
}
262
266
263
267
/**
@@ -278,63 +282,20 @@ public boolean isMapEntryTypeKnown() {
278
282
* Determine the generic key type of the wrapped Map parameter/field, if any.
279
283
* @return the generic type, or <code>null</code> if none
280
284
*/
281
- @ SuppressWarnings ("unchecked" )
282
285
public Class <?> getMapKeyType () {
283
- if (isMap ()) {
284
- if (this .field != null ) {
285
- return GenericCollectionTypeResolver .getMapKeyFieldType (this .field );
286
- }
287
- else if (this .methodParameter != null ) {
288
- return GenericCollectionTypeResolver .getMapKeyParameterType (this .methodParameter );
289
- }
290
- else if (this .value instanceof Map ) {
291
- Map map = (Map ) this .value ;
292
- if (!map .isEmpty ()) {
293
- Object key = map .keySet ().iterator ().next ();
294
- if (key != null ) {
295
- return key .getClass ();
296
- }
297
- }
298
- }
299
- return GenericCollectionTypeResolver .getMapKeyType ((Class <? extends Map >) this .type );
300
- } else {
301
- return null ;
302
- }
303
- }
304
-
305
- /**
306
- * Determine the generic value type of the wrapped Map parameter/field, if any.
307
- * @return the generic type, or <code>null</code> if none
308
- */
309
- @ SuppressWarnings ("unchecked" )
310
- public Class <?> getMapValueType () {
311
- if (isMap ()) {
312
- if (this .field != null ) {
313
- return GenericCollectionTypeResolver .getMapValueFieldType (this .field );
314
- }
315
- else if (this .methodParameter != null ) {
316
- return GenericCollectionTypeResolver .getMapValueParameterType (this .methodParameter );
317
- }
318
- else if (this .value instanceof Map ) {
319
- Map map = (Map ) this .value ;
320
- if (!map .isEmpty ()) {
321
- Object val = map .values ().iterator ().next ();
322
- if (val != null ) {
323
- return val .getClass ();
324
- }
325
- }
326
- }
327
- return GenericCollectionTypeResolver .getMapValueType ((Class <? extends Map >) this .type );
328
- } else {
329
- return null ;
330
- }
286
+ return getMapKeyTypeDescriptor ().getType ();
331
287
}
332
288
333
289
/**
334
290
* Returns map key type as a type descriptor.
335
291
*/
336
292
public TypeDescriptor getMapKeyTypeDescriptor () {
337
- return forElementType (getMapKeyType ());
293
+ if (mapKeyType != null ) {
294
+ return mapKeyType ;
295
+ } else {
296
+ mapKeyType = isMap () ? forElementType (resolveMapKeyType ()) : null ;
297
+ return mapKeyType ;
298
+ }
338
299
}
339
300
340
301
/**
@@ -343,14 +304,28 @@ public TypeDescriptor getMapKeyTypeDescriptor() {
343
304
* @return the map key type descriptor
344
305
*/
345
306
public TypeDescriptor getMapKeyTypeDescriptor (Object key ) {
346
- return getMapKeyType () != null ? getMapKeyTypeDescriptor () : TypeDescriptor .forObject (key );
307
+ TypeDescriptor keyType = getMapKeyTypeDescriptor ();
308
+ return keyType != TypeDescriptor .NULL ? keyType : TypeDescriptor .forObject (key );
309
+ }
310
+
311
+ /**
312
+ * Determine the generic value type of the wrapped Map parameter/field, if any.
313
+ * @return the generic type, or <code>null</code> if none
314
+ */
315
+ public Class <?> getMapValueType () {
316
+ return getMapValueTypeDescriptor ().getType ();
347
317
}
348
318
349
319
/**
350
320
* Returns map value type as a type descriptor.
351
321
*/
352
322
public TypeDescriptor getMapValueTypeDescriptor () {
353
- return forElementType (getMapValueType ());
323
+ if (mapValueType != null ) {
324
+ return mapValueType ;
325
+ } else {
326
+ mapValueType = isMap () ? forElementType (resolveMapValueType ()) : null ;
327
+ return mapValueType ;
328
+ }
354
329
}
355
330
356
331
/**
@@ -359,18 +334,21 @@ public TypeDescriptor getMapValueTypeDescriptor() {
359
334
* @return the map value type descriptor
360
335
*/
361
336
public TypeDescriptor getMapValueTypeDescriptor (Object value ) {
362
- return getMapValueType () != null ? getMapValueTypeDescriptor () : TypeDescriptor .forObject (value );
337
+ TypeDescriptor valueType = getMapValueTypeDescriptor ();
338
+ return valueType != TypeDescriptor .NULL ? valueType : TypeDescriptor .forObject (value );
363
339
}
364
340
365
341
/**
366
342
* Obtain the annotations associated with the wrapped parameter/field, if any.
367
343
*/
368
344
public Annotation [] getAnnotations () {
369
345
if (this .field != null ) {
346
+ // not caching
370
347
return this .field .getAnnotations ();
371
348
}
372
349
else if (this .methodParameter != null ) {
373
350
if (this .methodParameter .getParameterIndex () < 0 ) {
351
+ // not caching
374
352
return this .methodParameter .getMethodAnnotations ();
375
353
}
376
354
else {
@@ -494,12 +472,20 @@ public String toString() {
494
472
495
473
// internal helpers
496
474
497
- private Class <?> getArrayComponentType () {
498
- return getType ().getComponentType ();
475
+ private Class <?> resolveElementType () {
476
+ if (isArray ()) {
477
+ return getType ().getComponentType ();
478
+ }
479
+ else if (isCollection ()) {
480
+ return resolveCollectionElementType ();
481
+ }
482
+ else {
483
+ return null ;
484
+ }
499
485
}
500
-
486
+
501
487
@ SuppressWarnings ("unchecked" )
502
- private Class <?> getCollectionElementType () {
488
+ private Class <?> resolveCollectionElementType () {
503
489
if (this .field != null ) {
504
490
return GenericCollectionTypeResolver .getCollectionFieldType (this .field );
505
491
}
@@ -515,12 +501,47 @@ else if (this.value instanceof Collection) {
515
501
}
516
502
}
517
503
}
518
- if (this .type != null ) {
519
- return GenericCollectionTypeResolver .getCollectionType ((Class <? extends Collection >) this .type );
504
+ return type != null ? GenericCollectionTypeResolver .getCollectionType ((Class <? extends Collection >) this .type ) : null ;
505
+ }
506
+
507
+ @ SuppressWarnings ("unchecked" )
508
+ private Class <?> resolveMapKeyType () {
509
+ if (this .field != null ) {
510
+ return GenericCollectionTypeResolver .getMapKeyFieldType (this .field );
520
511
}
521
- else {
522
- return null ;
512
+ else if (this .methodParameter != null ) {
513
+ return GenericCollectionTypeResolver .getMapKeyParameterType (this .methodParameter );
514
+ }
515
+ else if (this .value instanceof Map <?, ?>) {
516
+ Map <?, ?> map = (Map <?, ?>) this .value ;
517
+ if (!map .isEmpty ()) {
518
+ Object key = map .keySet ().iterator ().next ();
519
+ if (key != null ) {
520
+ return key .getClass ();
521
+ }
522
+ }
523
+ }
524
+ return type != null ? GenericCollectionTypeResolver .getMapKeyType ((Class <? extends Map >) this .type ) : null ;
525
+ }
526
+
527
+ @ SuppressWarnings ("unchecked" )
528
+ private Class <?> resolveMapValueType () {
529
+ if (this .field != null ) {
530
+ return GenericCollectionTypeResolver .getMapValueFieldType (this .field );
531
+ }
532
+ else if (this .methodParameter != null ) {
533
+ return GenericCollectionTypeResolver .getMapValueParameterType (this .methodParameter );
534
+ }
535
+ else if (this .value instanceof Map <?, ?>) {
536
+ Map <?, ?> map = (Map <?, ?>) this .value ;
537
+ if (!map .isEmpty ()) {
538
+ Object val = map .values ().iterator ().next ();
539
+ if (val != null ) {
540
+ return val .getClass ();
541
+ }
542
+ }
523
543
}
544
+ return type != null ? GenericCollectionTypeResolver .getMapValueType ((Class <? extends Map >) this .type ) : null ;
524
545
}
525
546
526
547
/**
0 commit comments