@@ -114,7 +114,7 @@ public final class TypeFactory
114
114
* actual generic types), we will use small cache to avoid repetitive
115
115
* resolution of core types
116
116
*/
117
- protected final LRUMap <Class <?>, JavaType > _typeCache = new LRUMap <Class <?>, JavaType >(16 , 100 );
117
+ protected final LRUMap <Object , JavaType > _typeCache = new LRUMap <Object , JavaType >(16 , 100 );
118
118
119
119
/*
120
120
/**********************************************************
@@ -380,31 +380,17 @@ public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
380
380
// our specific neeeds.
381
381
// 29-Mar-2016, tatu: See [databind#1173] (and test `TypeResolverTest`)
382
382
// for a case where this code does get invoked: not ideal
383
+ // 29-Jun-2016, tatu: As to bindings, this works for [databind#1215], but
384
+ // not certain it would reliably work... but let's hope for best for now
385
+ TypeBindings tb = _bindingsForSubtype (baseType , typeParamCount , subclass );
383
386
if (baseType .isInterface ()) {
384
- newType = baseType .refine (subclass , TypeBindings .emptyBindings (), null ,
385
- new JavaType [] { baseType });
387
+ newType = baseType .refine (subclass , tb , null , new JavaType [] { baseType });
386
388
} else {
387
- newType = baseType .refine (subclass , TypeBindings .emptyBindings (), baseType ,
388
- NO_TYPES );
389
+ newType = baseType .refine (subclass , tb , baseType , NO_TYPES );
389
390
}
390
391
// Only SimpleType returns null, but if so just resolve regularly
391
392
if (newType == null ) {
392
- // But otherwise gets bit tricky, as we need to partially resolve the type hierarchy
393
- // (hopefully passing null Class for root is ok)
394
- TypeBindings tb = null ;
395
-
396
- // 14-Apr-2016, tatu: One possible short-cut; if type parameter counts
397
- // match, chances are they ought to match. Let's take our chances...
398
- if (baseType .containedTypeCount () == typeParamCount ) {
399
- if (typeParamCount == 1 ) {
400
- tb = TypeBindings .create (subclass , baseType .containedType (0 ));
401
- } else if (typeParamCount == 2 ) {
402
- tb = TypeBindings .create (subclass , baseType .containedType (0 ),
403
- baseType .containedType (1 ));
404
- }
405
- }
406
- newType = _fromClass (null , subclass ,
407
- (tb == null ) ? TypeBindings .emptyBindings () : tb );
393
+ newType = _fromClass (null , subclass , tb );
408
394
}
409
395
} while (false );
410
396
@@ -458,6 +444,29 @@ public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
458
444
*/
459
445
}
460
446
447
+ private TypeBindings _bindingsForSubtype (JavaType baseType , int typeParamCount , Class <?> subclass )
448
+ {
449
+ // But otherwise gets bit tricky, as we need to partially resolve the type hierarchy
450
+ // (hopefully passing null Class for root is ok)
451
+ int baseCount = baseType .containedTypeCount ();
452
+ if (baseCount == typeParamCount ) {
453
+ if (typeParamCount == 1 ) {
454
+ return TypeBindings .create (subclass , baseType .containedType (0 ));
455
+ }
456
+ if (typeParamCount == 2 ) {
457
+ return TypeBindings .create (subclass , baseType .containedType (0 ),
458
+ baseType .containedType (1 ));
459
+ }
460
+ List <JavaType > types = new ArrayList <JavaType >(baseCount );
461
+ for (int i = 0 ; i < baseCount ; ++i ) {
462
+ types .add (baseType .containedType (i ));
463
+ }
464
+ return TypeBindings .create (subclass , types );
465
+ }
466
+ // Otherwise, two choices: match N first, or empty. Do latter, for now
467
+ return TypeBindings .emptyBindings ();
468
+ }
469
+
461
470
/**
462
471
* Method similar to {@link #constructSpecializedType}, but that creates a
463
472
* less-specific type of given type. Usually this is as simple as simply
@@ -1157,15 +1166,17 @@ protected JavaType _fromClass(ClassStack context, Class<?> rawType, TypeBindings
1157
1166
if (result != null ) {
1158
1167
return result ;
1159
1168
}
1160
- // Barring that, we may have recently constructed an instance:
1161
- // !!! TODO 16-Oct-2015, tatu: For now let's only cached non-parameterized; otherwise
1162
- // need better cache key
1163
- boolean cachable = (bindings == null ) || bindings .isEmpty ();
1164
- if (cachable ) {
1165
- result = _typeCache .get (rawType ); // ok, cache object is synced
1166
- if (result != null ) {
1167
- return result ;
1168
- }
1169
+ // Barring that, we may have recently constructed an instance
1170
+ final Object key ;
1171
+ if ((bindings == null ) || bindings .isEmpty ()) {
1172
+ key = rawType ;
1173
+ result = _typeCache .get (key ); // ok, cache object is synced
1174
+ } else {
1175
+ key = bindings .asKey (rawType );
1176
+ }
1177
+ result = _typeCache .get (key ); // ok, cache object is synced
1178
+ if (result != null ) {
1179
+ return result ;
1169
1180
}
1170
1181
1171
1182
// 15-Oct-2015, tatu: recursive reference?
@@ -1225,10 +1236,7 @@ else if (superClass != null) {
1225
1236
}
1226
1237
}
1227
1238
context .resolveSelfReferences (result );
1228
-
1229
- if (cachable ) {
1230
- _typeCache .putIfAbsent (rawType , result ); // cache object syncs
1231
- }
1239
+ _typeCache .putIfAbsent (key , result ); // cache object syncs
1232
1240
return result ;
1233
1241
}
1234
1242
0 commit comments