1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.core;
18
19 import java.io.ObjectStreamException;
20 import java.io.Serializable;
21 import java.lang.reflect.Array;
22 import java.lang.reflect.Constructor;
23 import java.lang.reflect.Field;
24 import java.lang.reflect.GenericArrayType;
25 import java.lang.reflect.Method;
26 import java.lang.reflect.ParameterizedType;
27 import java.lang.reflect.Type;
28 import java.lang.reflect.TypeVariable;
29 import java.lang.reflect.WildcardType;
30 import java.util.Collection;
31 import java.util.IdentityHashMap;
32 import java.util.Map;
33
34 import org.springframework.core.SerializableTypeWrapper.FieldTypeProvider;
35 import org.springframework.core.SerializableTypeWrapper.MethodParameterTypeProvider;
36 import org.springframework.core.SerializableTypeWrapper.TypeProvider;
37 import org.springframework.util.Assert;
38 import org.springframework.util.ClassUtils;
39 import org.springframework.util.ConcurrentReferenceHashMap;
40 import org.springframework.util.ObjectUtils;
41 import org.springframework.util.StringUtils;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 @SuppressWarnings("serial")
79 public final class ResolvableType implements Serializable {
80
81
82
83
84
85 public static final ResolvableType NONE = new ResolvableType(null, null, null, null);
86
87 private static final ResolvableType[] EMPTY_TYPES_ARRAY = new ResolvableType[0];
88
89 private static final ConcurrentReferenceHashMap<ResolvableType, ResolvableType> cache =
90 new ConcurrentReferenceHashMap<ResolvableType, ResolvableType>(256);
91
92
93
94
95
96 private final Type type;
97
98
99
100
101 private final TypeProvider typeProvider;
102
103
104
105
106 private final VariableResolver variableResolver;
107
108
109
110
111 private final ResolvableType componentType;
112
113
114
115
116 private final Class<?> resolved;
117
118 private ResolvableType superType;
119
120 private ResolvableType[] interfaces;
121
122 private ResolvableType[] generics;
123
124
125
126
127
128 private ResolvableType(Type type, TypeProvider typeProvider, VariableResolver variableResolver) {
129 this.type = type;
130 this.typeProvider = typeProvider;
131 this.variableResolver = variableResolver;
132 this.componentType = null;
133 this.resolved = null;
134 }
135
136
137
138
139 private ResolvableType(
140 Type type, TypeProvider typeProvider, VariableResolver variableResolver, ResolvableType componentType) {
141
142 this.type = type;
143 this.typeProvider = typeProvider;
144 this.variableResolver = variableResolver;
145 this.componentType = componentType;
146 this.resolved = resolveClass();
147 }
148
149
150
151
152
153
154 public Type getType() {
155 return SerializableTypeWrapper.unwrap(this.type);
156 }
157
158
159
160
161
162 public Class<?> getRawClass() {
163 Type rawType = this.type;
164 if (rawType instanceof ParameterizedType) {
165 rawType = ((ParameterizedType) rawType).getRawType();
166 }
167 return (rawType instanceof Class ? (Class<?>) rawType : null);
168 }
169
170
171
172
173
174
175
176
177 public Object getSource() {
178 Object source = (this.typeProvider != null ? this.typeProvider.getSource() : null);
179 return (source != null ? source : this.type);
180 }
181
182
183
184
185
186
187
188
189
190
191
192
193 public boolean isAssignableFrom(ResolvableType other) {
194 return isAssignableFrom(other, null);
195 }
196
197 private boolean isAssignableFrom(ResolvableType other, Map<Type, Type> matchedBefore) {
198 Assert.notNull(other, "ResolvableType must not be null");
199
200
201 if (this == NONE || other == NONE) {
202 return false;
203 }
204
205
206 if (isArray()) {
207 return (other.isArray() && getComponentType().isAssignableFrom(other.getComponentType()));
208 }
209
210 if (matchedBefore != null && matchedBefore.get(this.type) == other.type) {
211 return true;
212 }
213
214
215 WildcardBounds ourBounds = WildcardBounds.get(this);
216 WildcardBounds typeBounds = WildcardBounds.get(other);
217
218
219 if (typeBounds != null) {
220 return (ourBounds != null && ourBounds.isSameKind(typeBounds) &&
221 ourBounds.isAssignableFrom(typeBounds.getBounds()));
222 }
223
224
225 if (ourBounds != null) {
226 return ourBounds.isAssignableFrom(other);
227 }
228
229
230 boolean exactMatch = (matchedBefore != null);
231 boolean checkGenerics = true;
232 Class<?> ourResolved = null;
233 if (this.type instanceof TypeVariable) {
234 TypeVariable<?> variable = (TypeVariable<?>) this.type;
235
236 if (this.variableResolver != null) {
237 ResolvableType resolved = this.variableResolver.resolveVariable(variable);
238 if (resolved != null) {
239 ourResolved = resolved.resolve();
240 }
241 }
242 if (ourResolved == null) {
243
244 if (other.variableResolver != null) {
245 ResolvableType resolved = other.variableResolver.resolveVariable(variable);
246 if (resolved != null) {
247 ourResolved = resolved.resolve();
248 checkGenerics = false;
249 }
250 }
251 }
252 if (ourResolved == null) {
253
254 exactMatch = false;
255 }
256 }
257 if (ourResolved == null) {
258 ourResolved = resolve(Object.class);
259 }
260 Class<?> otherResolved = other.resolve(Object.class);
261
262
263
264 if (exactMatch ? !ourResolved.equals(otherResolved) : !ClassUtils.isAssignable(ourResolved, otherResolved)) {
265 return false;
266 }
267
268 if (checkGenerics) {
269
270 ResolvableType[] ourGenerics = getGenerics();
271 ResolvableType[] typeGenerics = other.as(ourResolved).getGenerics();
272 if (ourGenerics.length != typeGenerics.length) {
273 return false;
274 }
275 if (matchedBefore == null) {
276 matchedBefore = new IdentityHashMap<Type, Type>(1);
277 }
278 matchedBefore.put(this.type, other.type);
279 for (int i = 0; i < ourGenerics.length; i++) {
280 if (!ourGenerics[i].isAssignableFrom(typeGenerics[i], matchedBefore)) {
281 return false;
282 }
283 }
284 }
285
286 return true;
287 }
288
289
290
291
292
293 public boolean isArray() {
294 if (this == NONE) {
295 return false;
296 }
297 return (((this.type instanceof Class && ((Class<?>) this.type).isArray())) ||
298 this.type instanceof GenericArrayType || resolveType().isArray());
299 }
300
301
302
303
304
305
306 public ResolvableType getComponentType() {
307 if (this == NONE) {
308 return NONE;
309 }
310 if (this.componentType != null) {
311 return this.componentType;
312 }
313 if (this.type instanceof Class) {
314 Class<?> componentType = ((Class<?>) this.type).getComponentType();
315 return forType(componentType, this.variableResolver);
316 }
317 if (this.type instanceof GenericArrayType) {
318 return forType(((GenericArrayType) this.type).getGenericComponentType(), this.variableResolver);
319 }
320 return resolveType().getComponentType();
321 }
322
323
324
325
326
327
328
329
330 public ResolvableType asCollection() {
331 return as(Collection.class);
332 }
333
334
335
336
337
338
339
340
341 public ResolvableType asMap() {
342 return as(Map.class);
343 }
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358 public ResolvableType as(Class<?> type) {
359 if (this == NONE) {
360 return NONE;
361 }
362 if (ObjectUtils.nullSafeEquals(resolve(), type)) {
363 return this;
364 }
365 for (ResolvableType interfaceType : getInterfaces()) {
366 ResolvableType interfaceAsType = interfaceType.as(type);
367 if (interfaceAsType != NONE) {
368 return interfaceAsType;
369 }
370 }
371 return getSuperType().as(type);
372 }
373
374
375
376
377
378
379 public ResolvableType getSuperType() {
380 Class<?> resolved = resolve();
381 if (resolved == null || resolved.getGenericSuperclass() == null) {
382 return NONE;
383 }
384 if (this.superType == null) {
385 this.superType = forType(SerializableTypeWrapper.forGenericSuperclass(resolved),
386 asVariableResolver());
387 }
388 return this.superType;
389 }
390
391
392
393
394
395
396
397 public ResolvableType[] getInterfaces() {
398 Class<?> resolved = resolve();
399 if (resolved == null || ObjectUtils.isEmpty(resolved.getGenericInterfaces())) {
400 return EMPTY_TYPES_ARRAY;
401 }
402 if (this.interfaces == null) {
403 this.interfaces = forTypes(SerializableTypeWrapper.forGenericInterfaces(resolved),
404 asVariableResolver());
405 }
406 return this.interfaces;
407 }
408
409
410
411
412
413
414 public boolean hasGenerics() {
415 return (getGenerics().length > 0);
416 }
417
418
419
420
421
422 boolean isEntirelyUnresolvable() {
423 if (this == NONE) {
424 return false;
425 }
426 ResolvableType[] generics = getGenerics();
427 for (ResolvableType generic : generics) {
428 if (!generic.isUnresolvableTypeVariable() && !generic.isWildcardWithoutBounds()) {
429 return false;
430 }
431 }
432 return true;
433 }
434
435
436
437
438
439
440
441
442 public boolean hasUnresolvableGenerics() {
443 if (this == NONE) {
444 return false;
445 }
446 ResolvableType[] generics = getGenerics();
447 for (ResolvableType generic : generics) {
448 if (generic.isUnresolvableTypeVariable() || generic.isWildcardWithoutBounds()) {
449 return true;
450 }
451 }
452 Class<?> resolved = resolve();
453 if (resolved != null) {
454 for (Type genericInterface : resolved.getGenericInterfaces()) {
455 if (genericInterface instanceof Class) {
456 if (forClass((Class<?>) genericInterface).hasGenerics()) {
457 return true;
458 }
459 }
460 }
461 return getSuperType().hasUnresolvableGenerics();
462 }
463 return false;
464 }
465
466
467
468
469
470 private boolean isUnresolvableTypeVariable() {
471 if (this.type instanceof TypeVariable) {
472 if (this.variableResolver == null) {
473 return true;
474 }
475 TypeVariable<?> variable = (TypeVariable<?>) this.type;
476 ResolvableType resolved = this.variableResolver.resolveVariable(variable);
477 if (resolved == null || resolved.isUnresolvableTypeVariable()) {
478 return true;
479 }
480 }
481 return false;
482 }
483
484
485
486
487
488 private boolean isWildcardWithoutBounds() {
489 if (this.type instanceof WildcardType) {
490 WildcardType wt = (WildcardType) this.type;
491 if (wt.getLowerBounds().length == 0) {
492 Type[] upperBounds = wt.getUpperBounds();
493 if (upperBounds.length == 0 || (upperBounds.length == 1 && Object.class.equals(upperBounds[0]))) {
494 return true;
495 }
496 }
497 }
498 return false;
499 }
500
501
502
503
504
505
506
507 public ResolvableType getNested(int nestingLevel) {
508 return getNested(nestingLevel, null);
509 }
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531 public ResolvableType getNested(int nestingLevel, Map<Integer, Integer> typeIndexesPerLevel) {
532 ResolvableType result = this;
533 for (int i = 2; i <= nestingLevel; i++) {
534 if (result.isArray()) {
535 result = result.getComponentType();
536 }
537 else {
538
539 while (result != ResolvableType.NONE && !result.hasGenerics()) {
540 result = result.getSuperType();
541 }
542 Integer index = (typeIndexesPerLevel != null ? typeIndexesPerLevel.get(i) : null);
543 index = (index == null ? result.getGenerics().length - 1 : index);
544 result = result.getGeneric(index);
545 }
546 }
547 return result;
548 }
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567 public ResolvableType getGeneric(int... indexes) {
568 try {
569 if (indexes == null || indexes.length == 0) {
570 return getGenerics()[0];
571 }
572 ResolvableType generic = this;
573 for (int index : indexes) {
574 generic = generic.getGenerics()[index];
575 }
576 return generic;
577 }
578 catch (IndexOutOfBoundsException ex) {
579 return NONE;
580 }
581 }
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596 public ResolvableType[] getGenerics() {
597 if (this == NONE) {
598 return EMPTY_TYPES_ARRAY;
599 }
600 if (this.generics == null) {
601 if (this.type instanceof Class) {
602 Class<?> typeClass = (Class<?>) this.type;
603 this.generics = forTypes(SerializableTypeWrapper.forTypeParameters(typeClass), this.variableResolver);
604 }
605 else if (this.type instanceof ParameterizedType) {
606 Type[] actualTypeArguments = ((ParameterizedType) this.type).getActualTypeArguments();
607 ResolvableType[] generics = new ResolvableType[actualTypeArguments.length];
608 for (int i = 0; i < actualTypeArguments.length; i++) {
609 generics[i] = forType(actualTypeArguments[i], this.variableResolver);
610 }
611 this.generics = generics;
612 }
613 else {
614 this.generics = resolveType().getGenerics();
615 }
616 }
617 return this.generics;
618 }
619
620
621
622
623
624
625
626
627
628 public Class<?>[] resolveGenerics() {
629 return resolveGenerics(null);
630 }
631
632
633
634
635
636
637
638
639
640
641
642 public Class<?>[] resolveGenerics(Class<?> fallback) {
643 ResolvableType[] generics = getGenerics();
644 Class<?>[] resolvedGenerics = new Class<?>[generics.length];
645 for (int i = 0; i < generics.length; i++) {
646 resolvedGenerics[i] = generics[i].resolve(fallback);
647 }
648 return resolvedGenerics;
649 }
650
651
652
653
654
655
656
657
658
659
660 public Class<?> resolveGeneric(int... indexes) {
661 return getGeneric(indexes).resolve();
662 }
663
664
665
666
667
668
669
670
671
672
673
674 public Class<?> resolve() {
675 return resolve(null);
676 }
677
678
679
680
681
682
683
684
685
686
687
688
689 public Class<?> resolve(Class<?> fallback) {
690 return (this.resolved != null ? this.resolved : fallback);
691 }
692
693 private Class<?> resolveClass() {
694 if (this.type instanceof Class || this.type == null) {
695 return (Class<?>) this.type;
696 }
697 if (this.type instanceof GenericArrayType) {
698 Class<?> resolvedComponent = getComponentType().resolve();
699 return (resolvedComponent != null ? Array.newInstance(resolvedComponent, 0).getClass() : null);
700 }
701 return resolveType().resolve();
702 }
703
704
705
706
707
708
709 ResolvableType resolveType() {
710 if (this.type instanceof ParameterizedType) {
711 return forType(((ParameterizedType) this.type).getRawType(), this.variableResolver);
712 }
713 if (this.type instanceof WildcardType) {
714 Type resolved = resolveBounds(((WildcardType) this.type).getUpperBounds());
715 if (resolved == null) {
716 resolved = resolveBounds(((WildcardType) this.type).getLowerBounds());
717 }
718 return forType(resolved, this.variableResolver);
719 }
720 if (this.type instanceof TypeVariable) {
721 TypeVariable<?> variable = (TypeVariable<?>) this.type;
722
723 if (this.variableResolver != null) {
724 ResolvableType resolved = this.variableResolver.resolveVariable(variable);
725 if (resolved != null) {
726 return resolved;
727 }
728 }
729
730 return forType(resolveBounds(variable.getBounds()), this.variableResolver);
731 }
732 return NONE;
733 }
734
735 private Type resolveBounds(Type[] bounds) {
736 if (ObjectUtils.isEmpty(bounds) || Object.class.equals(bounds[0])) {
737 return null;
738 }
739 return bounds[0];
740 }
741
742 private ResolvableType resolveVariable(TypeVariable<?> variable) {
743 if (this.type instanceof TypeVariable) {
744 return resolveType().resolveVariable(variable);
745 }
746 if (this.type instanceof ParameterizedType) {
747 ParameterizedType parameterizedType = (ParameterizedType) this.type;
748 TypeVariable<?>[] variables = resolve().getTypeParameters();
749 for (int i = 0; i < variables.length; i++) {
750 if (ObjectUtils.nullSafeEquals(variables[i].getName(), variable.getName())) {
751 Type actualType = parameterizedType.getActualTypeArguments()[i];
752 return forType(actualType, this.variableResolver);
753 }
754 }
755 if (parameterizedType.getOwnerType() != null) {
756 return forType(parameterizedType.getOwnerType(), this.variableResolver).resolveVariable(variable);
757 }
758 }
759 if (this.variableResolver != null) {
760 return this.variableResolver.resolveVariable(variable);
761 }
762 return null;
763 }
764
765
766 @Override
767 public boolean equals(Object other) {
768 if (this == other) {
769 return true;
770 }
771 if (!(other instanceof ResolvableType)) {
772 return false;
773 }
774 ResolvableType otherType = (ResolvableType) other;
775 return (ObjectUtils.nullSafeEquals(this.type, otherType.type) &&
776 ObjectUtils.nullSafeEquals(getSource(), otherType.getSource()) &&
777 variableResolverSourceEquals(otherType.variableResolver) &&
778 ObjectUtils.nullSafeEquals(this.componentType, otherType.componentType));
779 }
780
781 @Override
782 public int hashCode() {
783 int hashCode = ObjectUtils.nullSafeHashCode(this.type);
784 hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(getSource());
785 hashCode = 31 * hashCode + variableResolverSourceHashCode();
786 hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.componentType);
787 return hashCode;
788 }
789
790 private boolean variableResolverSourceEquals(VariableResolver other) {
791 if (this.variableResolver == null) {
792 return (other == null);
793 }
794 if (other == null) {
795 return false;
796 }
797 return ObjectUtils.nullSafeEquals(this.variableResolver.getSource(), other.getSource());
798 }
799
800 private int variableResolverSourceHashCode() {
801 int hashCode = 0;
802 if (this.variableResolver != null) {
803 hashCode = ObjectUtils.nullSafeHashCode(this.variableResolver.getSource());
804 }
805 return hashCode;
806 }
807
808
809
810
811 VariableResolver asVariableResolver() {
812 if (this == NONE) {
813 return null;
814 }
815 return new DefaultVariableResolver();
816 }
817
818
819
820
821 private Object readResolve() throws ObjectStreamException {
822 return (this.type == null ? NONE : this);
823 }
824
825
826
827
828
829 @Override
830 public String toString() {
831 if (isArray()) {
832 return getComponentType() + "[]";
833 }
834 if (this.resolved == null) {
835 return "?";
836 }
837 if (this.type instanceof TypeVariable) {
838 TypeVariable<?> variable = (TypeVariable<?>) this.type;
839 if (this.variableResolver == null || this.variableResolver.resolveVariable(variable) == null) {
840
841
842 return "?";
843 }
844 }
845 StringBuilder result = new StringBuilder(this.resolved.getName());
846 if (hasGenerics()) {
847 result.append('<');
848 result.append(StringUtils.arrayToDelimitedString(getGenerics(), ", "));
849 result.append('>');
850 }
851 return result.toString();
852 }
853
854
855
856
857
858
859
860
861
862
863
864
865
866 public static ResolvableType forClass(Class<?> sourceClass) {
867 Assert.notNull(sourceClass, "Source class must not be null");
868 return forType(sourceClass);
869 }
870
871
872
873
874
875
876
877
878
879
880
881
882 public static ResolvableType forClass(Class<?> sourceClass, Class<?> implementationClass) {
883 Assert.notNull(sourceClass, "Source class must not be null");
884 ResolvableType asType = forType(implementationClass).as(sourceClass);
885 return (asType == NONE ? forType(sourceClass) : asType);
886 }
887
888
889
890
891
892
893
894
895 public static ResolvableType forClassWithGenerics(Class<?> sourceClass, Class<?>... generics) {
896 Assert.notNull(sourceClass, "Source class must not be null");
897 Assert.notNull(generics, "Generics must not be null");
898 ResolvableType[] resolvableGenerics = new ResolvableType[generics.length];
899 for (int i = 0; i < generics.length; i++) {
900 resolvableGenerics[i] = forClass(generics[i]);
901 }
902 return forClassWithGenerics(sourceClass, resolvableGenerics);
903 }
904
905
906
907
908
909
910
911
912 public static ResolvableType forClassWithGenerics(Class<?> sourceClass, ResolvableType... generics) {
913 Assert.notNull(sourceClass, "Source class must not be null");
914 Assert.notNull(generics, "Generics must not be null");
915 TypeVariable<?>[] variables = sourceClass.getTypeParameters();
916 Assert.isTrue(variables.length == generics.length, "Mismatched number of generics specified");
917 return forType(sourceClass, new TypeVariablesVariableResolver(variables, generics));
918 }
919
920
921
922
923
924
925
926 public static ResolvableType forField(Field field) {
927 Assert.notNull(field, "Field must not be null");
928 return forType(null, new FieldTypeProvider(field), null);
929 }
930
931
932
933
934
935
936
937
938
939
940
941 public static ResolvableType forField(Field field, Class<?> implementationClass) {
942 Assert.notNull(field, "Field must not be null");
943 ResolvableType owner = forType(implementationClass).as(field.getDeclaringClass());
944 return forType(null, new FieldTypeProvider(field), owner.asVariableResolver());
945 }
946
947
948
949
950
951
952
953
954
955
956
957 public static ResolvableType forField(Field field, ResolvableType implementationType) {
958 Assert.notNull(field, "Field must not be null");
959 implementationType = (implementationType == null ? NONE : implementationType);
960 ResolvableType owner = implementationType.as(field.getDeclaringClass());
961 return forType(null, new FieldTypeProvider(field), owner.asVariableResolver());
962 }
963
964
965
966
967
968
969
970
971
972 public static ResolvableType forField(Field field, int nestingLevel) {
973 Assert.notNull(field, "Field must not be null");
974 return forType(null, new FieldTypeProvider(field), null).getNested(nestingLevel);
975 }
976
977
978
979
980
981
982
983
984
985
986
987
988
989 public static ResolvableType forField(Field field, int nestingLevel, Class<?> implementationClass) {
990 Assert.notNull(field, "Field must not be null");
991 ResolvableType owner = forType(implementationClass).as(field.getDeclaringClass());
992 return forType(null, new FieldTypeProvider(field), owner.asVariableResolver()).getNested(nestingLevel);
993 }
994
995
996
997
998
999
1000
1001
1002 public static ResolvableType forConstructorParameter(Constructor<?> constructor, int parameterIndex) {
1003 Assert.notNull(constructor, "Constructor must not be null");
1004 return forMethodParameter(new MethodParameter(constructor, parameterIndex));
1005 }
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018 public static ResolvableType forConstructorParameter(Constructor<?> constructor, int parameterIndex,
1019 Class<?> implementationClass) {
1020
1021 Assert.notNull(constructor, "Constructor must not be null");
1022 MethodParameter methodParameter = new MethodParameter(constructor, parameterIndex);
1023 methodParameter.setContainingClass(implementationClass);
1024 return forMethodParameter(methodParameter);
1025 }
1026
1027
1028
1029
1030
1031
1032
1033 public static ResolvableType forMethodReturnType(Method method) {
1034 Assert.notNull(method, "Method must not be null");
1035 return forMethodParameter(MethodParameter.forMethodOrConstructor(method, -1));
1036 }
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047 public static ResolvableType forMethodReturnType(Method method, Class<?> implementationClass) {
1048 Assert.notNull(method, "Method must not be null");
1049 MethodParameter methodParameter = MethodParameter.forMethodOrConstructor(method, -1);
1050 methodParameter.setContainingClass(implementationClass);
1051 return forMethodParameter(methodParameter);
1052 }
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062 public static ResolvableType forMethodParameter(Method method, int parameterIndex) {
1063 Assert.notNull(method, "Method must not be null");
1064 return forMethodParameter(new MethodParameter(method, parameterIndex));
1065 }
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078 public static ResolvableType forMethodParameter(Method method, int parameterIndex, Class<?> implementationClass) {
1079 Assert.notNull(method, "Method must not be null");
1080 MethodParameter methodParameter = new MethodParameter(method, parameterIndex);
1081 methodParameter.setContainingClass(implementationClass);
1082 return forMethodParameter(methodParameter);
1083 }
1084
1085
1086
1087
1088
1089
1090
1091 public static ResolvableType forMethodParameter(MethodParameter methodParameter) {
1092 return forMethodParameter(methodParameter, (Type) null);
1093 }
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104 public static ResolvableType forMethodParameter(MethodParameter methodParameter, ResolvableType implementationType) {
1105 Assert.notNull(methodParameter, "MethodParameter must not be null");
1106 implementationType = (implementationType == null ? forType(methodParameter.getContainingClass()) : implementationType);
1107 ResolvableType owner = implementationType.as(methodParameter.getDeclaringClass());
1108 return forType(null, new MethodParameterTypeProvider(methodParameter),
1109 owner.asVariableResolver()).getNested(methodParameter.getNestingLevel(),
1110 methodParameter.typeIndexesPerLevel);
1111 }
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121 public static ResolvableType forMethodParameter(MethodParameter methodParameter, Type targetType) {
1122 Assert.notNull(methodParameter, "MethodParameter must not be null");
1123 ResolvableType owner = forType(methodParameter.getContainingClass()).as(methodParameter.getDeclaringClass());
1124 return forType(targetType, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).
1125 getNested(methodParameter.getNestingLevel(), methodParameter.typeIndexesPerLevel);
1126 }
1127
1128
1129
1130
1131
1132
1133 public static ResolvableType forArrayComponent(ResolvableType componentType) {
1134 Assert.notNull(componentType, "componentType must not be null");
1135 Class<?> arrayClass = Array.newInstance(componentType.resolve(), 0).getClass();
1136 return new ResolvableType(arrayClass, null, null, componentType);
1137 }
1138
1139 private static ResolvableType[] forTypes(Type[] types, VariableResolver owner) {
1140 ResolvableType[] result = new ResolvableType[types.length];
1141 for (int i = 0; i < types.length; i++) {
1142 result[i] = forType(types[i], owner);
1143 }
1144 return result;
1145 }
1146
1147
1148
1149
1150
1151
1152
1153
1154 public static ResolvableType forType(Type type) {
1155 return forType(type, null, null);
1156 }
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166 public static ResolvableType forType(Type type, ResolvableType owner) {
1167 VariableResolver variableResolver = null;
1168 if (owner != null) {
1169 variableResolver = owner.asVariableResolver();
1170 }
1171 return forType(type, variableResolver);
1172 }
1173
1174
1175
1176
1177
1178
1179
1180
1181 static ResolvableType forType(Type type, VariableResolver variableResolver) {
1182 return forType(type, null, variableResolver);
1183 }
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193 static ResolvableType forType(Type type, TypeProvider typeProvider, VariableResolver variableResolver) {
1194 if (type == null && typeProvider != null) {
1195 type = SerializableTypeWrapper.forTypeProvider(typeProvider);
1196 }
1197 if (type == null) {
1198 return NONE;
1199 }
1200
1201
1202 cache.purgeUnreferencedEntries();
1203
1204
1205
1206 if (type instanceof Class) {
1207 return new ResolvableType(type, typeProvider, variableResolver, null);
1208 }
1209
1210
1211 ResolvableType key = new ResolvableType(type, typeProvider, variableResolver);
1212 ResolvableType resolvableType = cache.get(key);
1213 if (resolvableType == null) {
1214 resolvableType = new ResolvableType(type, typeProvider, variableResolver, null);
1215 cache.put(resolvableType, resolvableType);
1216 }
1217 return resolvableType;
1218 }
1219
1220
1221
1222
1223
1224 static interface VariableResolver extends Serializable {
1225
1226
1227
1228
1229 Object getSource();
1230
1231
1232
1233
1234
1235
1236 ResolvableType resolveVariable(TypeVariable<?> variable);
1237 }
1238
1239
1240 @SuppressWarnings("serial")
1241 private class DefaultVariableResolver implements VariableResolver {
1242
1243 @Override
1244 public ResolvableType resolveVariable(TypeVariable<?> variable) {
1245 return ResolvableType.this.resolveVariable(variable);
1246 }
1247
1248 @Override
1249 public Object getSource() {
1250 return ResolvableType.this;
1251 }
1252 }
1253
1254
1255 @SuppressWarnings("serial")
1256 private static class TypeVariablesVariableResolver implements VariableResolver {
1257
1258 private final TypeVariable<?>[] variables;
1259
1260 private final ResolvableType[] generics;
1261
1262 public TypeVariablesVariableResolver(TypeVariable<?>[] variables, ResolvableType[] generics) {
1263 this.variables = variables;
1264 this.generics = generics;
1265 }
1266
1267 @Override
1268 public ResolvableType resolveVariable(TypeVariable<?> variable) {
1269 for (int i = 0; i < this.variables.length; i++) {
1270 if (SerializableTypeWrapper.unwrap(this.variables[i]).equals(
1271 SerializableTypeWrapper.unwrap(variable))) {
1272 return this.generics[i];
1273 }
1274 }
1275 return null;
1276 }
1277
1278 @Override
1279 public Object getSource() {
1280 return this.generics;
1281 }
1282 }
1283
1284
1285
1286
1287
1288 private static class WildcardBounds {
1289
1290 private final Kind kind;
1291
1292 private final ResolvableType[] bounds;
1293
1294
1295
1296
1297
1298
1299
1300 public WildcardBounds(Kind kind, ResolvableType[] bounds) {
1301 this.kind = kind;
1302 this.bounds = bounds;
1303 }
1304
1305
1306
1307
1308 public boolean isSameKind(WildcardBounds bounds) {
1309 return this.kind == bounds.kind;
1310 }
1311
1312
1313
1314
1315
1316
1317 public boolean isAssignableFrom(ResolvableType... types) {
1318 for (ResolvableType bound : this.bounds) {
1319 for (ResolvableType type : types) {
1320 if (!isAssignable(bound, type)) {
1321 return false;
1322 }
1323 }
1324 }
1325 return true;
1326 }
1327
1328 private boolean isAssignable(ResolvableType source, ResolvableType from) {
1329 return (this.kind == Kind.UPPER ? source.isAssignableFrom(from) : from.isAssignableFrom(source));
1330 }
1331
1332
1333
1334
1335 public ResolvableType[] getBounds() {
1336 return this.bounds;
1337 }
1338
1339
1340
1341
1342
1343
1344
1345 public static WildcardBounds get(ResolvableType type) {
1346 ResolvableType resolveToWildcard = type;
1347 while (!(resolveToWildcard.getType() instanceof WildcardType)) {
1348 if (resolveToWildcard == NONE) {
1349 return null;
1350 }
1351 resolveToWildcard = resolveToWildcard.resolveType();
1352 }
1353 WildcardType wildcardType = (WildcardType) resolveToWildcard.type;
1354 Kind boundsType = (wildcardType.getLowerBounds().length > 0 ? Kind.LOWER : Kind.UPPER);
1355 Type[] bounds = boundsType == Kind.UPPER ? wildcardType.getUpperBounds() : wildcardType.getLowerBounds();
1356 ResolvableType[] resolvableBounds = new ResolvableType[bounds.length];
1357 for (int i = 0; i < bounds.length; i++) {
1358 resolvableBounds[i] = ResolvableType.forType(bounds[i], type.variableResolver);
1359 }
1360 return new WildcardBounds(boundsType, resolvableBounds);
1361 }
1362
1363
1364
1365
1366 static enum Kind {UPPER, LOWER}
1367 }
1368
1369 }