001/*
002 * Copyright 2002-2020 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.core;
018
019import java.io.Serializable;
020import java.lang.reflect.Array;
021import java.lang.reflect.Constructor;
022import java.lang.reflect.Field;
023import java.lang.reflect.GenericArrayType;
024import java.lang.reflect.Method;
025import java.lang.reflect.ParameterizedType;
026import java.lang.reflect.Type;
027import java.lang.reflect.TypeVariable;
028import java.lang.reflect.WildcardType;
029import java.util.Arrays;
030import java.util.Collection;
031import java.util.IdentityHashMap;
032import java.util.Map;
033import java.util.StringJoiner;
034
035import org.springframework.core.SerializableTypeWrapper.FieldTypeProvider;
036import org.springframework.core.SerializableTypeWrapper.MethodParameterTypeProvider;
037import org.springframework.core.SerializableTypeWrapper.TypeProvider;
038import org.springframework.lang.Nullable;
039import org.springframework.util.Assert;
040import org.springframework.util.ClassUtils;
041import org.springframework.util.ConcurrentReferenceHashMap;
042import org.springframework.util.ObjectUtils;
043import org.springframework.util.StringUtils;
044
045/**
046 * Encapsulates a Java {@link java.lang.reflect.Type}, providing access to
047 * {@link #getSuperType() supertypes}, {@link #getInterfaces() interfaces}, and
048 * {@link #getGeneric(int...) generic parameters} along with the ability to ultimately
049 * {@link #resolve() resolve} to a {@link java.lang.Class}.
050 *
051 * <p>{@code ResolvableTypes} may be obtained from {@link #forField(Field) fields},
052 * {@link #forMethodParameter(Method, int) method parameters},
053 * {@link #forMethodReturnType(Method) method returns} or
054 * {@link #forClass(Class) classes}. Most methods on this class will themselves return
055 * {@link ResolvableType ResolvableTypes}, allowing easy navigation. For example:
056 * <pre class="code">
057 * private HashMap&lt;Integer, List&lt;String&gt;&gt; myMap;
058 *
059 * public void example() {
060 *     ResolvableType t = ResolvableType.forField(getClass().getDeclaredField("myMap"));
061 *     t.getSuperType(); // AbstractMap&lt;Integer, List&lt;String&gt;&gt;
062 *     t.asMap(); // Map&lt;Integer, List&lt;String&gt;&gt;
063 *     t.getGeneric(0).resolve(); // Integer
064 *     t.getGeneric(1).resolve(); // List
065 *     t.getGeneric(1); // List&lt;String&gt;
066 *     t.resolveGeneric(1, 0); // String
067 * }
068 * </pre>
069 *
070 * @author Phillip Webb
071 * @author Juergen Hoeller
072 * @author Stephane Nicoll
073 * @since 4.0
074 * @see #forField(Field)
075 * @see #forMethodParameter(Method, int)
076 * @see #forMethodReturnType(Method)
077 * @see #forConstructorParameter(Constructor, int)
078 * @see #forClass(Class)
079 * @see #forType(Type)
080 * @see #forInstance(Object)
081 * @see ResolvableTypeProvider
082 */
083@SuppressWarnings("serial")
084public class ResolvableType implements Serializable {
085
086        /**
087         * {@code ResolvableType} returned when no value is available. {@code NONE} is used
088         * in preference to {@code null} so that multiple method calls can be safely chained.
089         */
090        public static final ResolvableType NONE = new ResolvableType(EmptyType.INSTANCE, null, null, 0);
091
092        private static final ResolvableType[] EMPTY_TYPES_ARRAY = new ResolvableType[0];
093
094        private static final ConcurrentReferenceHashMap<ResolvableType, ResolvableType> cache =
095                        new ConcurrentReferenceHashMap<>(256);
096
097
098        /**
099         * The underlying Java type being managed.
100         */
101        private final Type type;
102
103        /**
104         * Optional provider for the type.
105         */
106        @Nullable
107        private final TypeProvider typeProvider;
108
109        /**
110         * The {@code VariableResolver} to use or {@code null} if no resolver is available.
111         */
112        @Nullable
113        private final VariableResolver variableResolver;
114
115        /**
116         * The component type for an array or {@code null} if the type should be deduced.
117         */
118        @Nullable
119        private final ResolvableType componentType;
120
121        @Nullable
122        private final Integer hash;
123
124        @Nullable
125        private Class<?> resolved;
126
127        @Nullable
128        private volatile ResolvableType superType;
129
130        @Nullable
131        private volatile ResolvableType[] interfaces;
132
133        @Nullable
134        private volatile ResolvableType[] generics;
135
136
137        /**
138         * Private constructor used to create a new {@link ResolvableType} for cache key purposes,
139         * with no upfront resolution.
140         */
141        private ResolvableType(
142                        Type type, @Nullable TypeProvider typeProvider, @Nullable VariableResolver variableResolver) {
143
144                this.type = type;
145                this.typeProvider = typeProvider;
146                this.variableResolver = variableResolver;
147                this.componentType = null;
148                this.hash = calculateHashCode();
149                this.resolved = null;
150        }
151
152        /**
153         * Private constructor used to create a new {@link ResolvableType} for cache value purposes,
154         * with upfront resolution and a pre-calculated hash.
155         * @since 4.2
156         */
157        private ResolvableType(Type type, @Nullable TypeProvider typeProvider,
158                        @Nullable VariableResolver variableResolver, @Nullable Integer hash) {
159
160                this.type = type;
161                this.typeProvider = typeProvider;
162                this.variableResolver = variableResolver;
163                this.componentType = null;
164                this.hash = hash;
165                this.resolved = resolveClass();
166        }
167
168        /**
169         * Private constructor used to create a new {@link ResolvableType} for uncached purposes,
170         * with upfront resolution but lazily calculated hash.
171         */
172        private ResolvableType(Type type, @Nullable TypeProvider typeProvider,
173                        @Nullable VariableResolver variableResolver, @Nullable ResolvableType componentType) {
174
175                this.type = type;
176                this.typeProvider = typeProvider;
177                this.variableResolver = variableResolver;
178                this.componentType = componentType;
179                this.hash = null;
180                this.resolved = resolveClass();
181        }
182
183        /**
184         * Private constructor used to create a new {@link ResolvableType} on a {@link Class} basis.
185         * Avoids all {@code instanceof} checks in order to create a straight {@link Class} wrapper.
186         * @since 4.2
187         */
188        private ResolvableType(@Nullable Class<?> clazz) {
189                this.resolved = (clazz != null ? clazz : Object.class);
190                this.type = this.resolved;
191                this.typeProvider = null;
192                this.variableResolver = null;
193                this.componentType = null;
194                this.hash = null;
195        }
196
197
198        /**
199         * Return the underling Java {@link Type} being managed.
200         */
201        public Type getType() {
202                return SerializableTypeWrapper.unwrap(this.type);
203        }
204
205        /**
206         * Return the underlying Java {@link Class} being managed, if available;
207         * otherwise {@code null}.
208         */
209        @Nullable
210        public Class<?> getRawClass() {
211                if (this.type == this.resolved) {
212                        return this.resolved;
213                }
214                Type rawType = this.type;
215                if (rawType instanceof ParameterizedType) {
216                        rawType = ((ParameterizedType) rawType).getRawType();
217                }
218                return (rawType instanceof Class ? (Class<?>) rawType : null);
219        }
220
221        /**
222         * Return the underlying source of the resolvable type. Will return a {@link Field},
223         * {@link MethodParameter} or {@link Type} depending on how the {@link ResolvableType}
224         * was constructed. With the exception of the {@link #NONE} constant, this method will
225         * never return {@code null}. This method is primarily to provide access to additional
226         * type information or meta-data that alternative JVM languages may provide.
227         */
228        public Object getSource() {
229                Object source = (this.typeProvider != null ? this.typeProvider.getSource() : null);
230                return (source != null ? source : this.type);
231        }
232
233        /**
234         * Return this type as a resolved {@code Class}, falling back to
235         * {@link java.lang.Object} if no specific class can be resolved.
236         * @return the resolved {@link Class} or the {@code Object} fallback
237         * @since 5.1
238         * @see #getRawClass()
239         * @see #resolve(Class)
240         */
241        public Class<?> toClass() {
242                return resolve(Object.class);
243        }
244
245        /**
246         * Determine whether the given object is an instance of this {@code ResolvableType}.
247         * @param obj the object to check
248         * @since 4.2
249         * @see #isAssignableFrom(Class)
250         */
251        public boolean isInstance(@Nullable Object obj) {
252                return (obj != null && isAssignableFrom(obj.getClass()));
253        }
254
255        /**
256         * Determine whether this {@code ResolvableType} is assignable from the
257         * specified other type.
258         * @param other the type to be checked against (as a {@code Class})
259         * @since 4.2
260         * @see #isAssignableFrom(ResolvableType)
261         */
262        public boolean isAssignableFrom(Class<?> other) {
263                return isAssignableFrom(forClass(other), null);
264        }
265
266        /**
267         * Determine whether this {@code ResolvableType} is assignable from the
268         * specified other type.
269         * <p>Attempts to follow the same rules as the Java compiler, considering
270         * whether both the {@link #resolve() resolved} {@code Class} is
271         * {@link Class#isAssignableFrom(Class) assignable from} the given type
272         * as well as whether all {@link #getGenerics() generics} are assignable.
273         * @param other the type to be checked against (as a {@code ResolvableType})
274         * @return {@code true} if the specified other type can be assigned to this
275         * {@code ResolvableType}; {@code false} otherwise
276         */
277        public boolean isAssignableFrom(ResolvableType other) {
278                return isAssignableFrom(other, null);
279        }
280
281        private boolean isAssignableFrom(ResolvableType other, @Nullable Map<Type, Type> matchedBefore) {
282                Assert.notNull(other, "ResolvableType must not be null");
283
284                // If we cannot resolve types, we are not assignable
285                if (this == NONE || other == NONE) {
286                        return false;
287                }
288
289                // Deal with array by delegating to the component type
290                if (isArray()) {
291                        return (other.isArray() && getComponentType().isAssignableFrom(other.getComponentType()));
292                }
293
294                if (matchedBefore != null && matchedBefore.get(this.type) == other.type) {
295                        return true;
296                }
297
298                // Deal with wildcard bounds
299                WildcardBounds ourBounds = WildcardBounds.get(this);
300                WildcardBounds typeBounds = WildcardBounds.get(other);
301
302                // In the form X is assignable to <? extends Number>
303                if (typeBounds != null) {
304                        return (ourBounds != null && ourBounds.isSameKind(typeBounds) &&
305                                        ourBounds.isAssignableFrom(typeBounds.getBounds()));
306                }
307
308                // In the form <? extends Number> is assignable to X...
309                if (ourBounds != null) {
310                        return ourBounds.isAssignableFrom(other);
311                }
312
313                // Main assignability check about to follow
314                boolean exactMatch = (matchedBefore != null);  // We're checking nested generic variables now...
315                boolean checkGenerics = true;
316                Class<?> ourResolved = null;
317                if (this.type instanceof TypeVariable) {
318                        TypeVariable<?> variable = (TypeVariable<?>) this.type;
319                        // Try default variable resolution
320                        if (this.variableResolver != null) {
321                                ResolvableType resolved = this.variableResolver.resolveVariable(variable);
322                                if (resolved != null) {
323                                        ourResolved = resolved.resolve();
324                                }
325                        }
326                        if (ourResolved == null) {
327                                // Try variable resolution against target type
328                                if (other.variableResolver != null) {
329                                        ResolvableType resolved = other.variableResolver.resolveVariable(variable);
330                                        if (resolved != null) {
331                                                ourResolved = resolved.resolve();
332                                                checkGenerics = false;
333                                        }
334                                }
335                        }
336                        if (ourResolved == null) {
337                                // Unresolved type variable, potentially nested -> never insist on exact match
338                                exactMatch = false;
339                        }
340                }
341                if (ourResolved == null) {
342                        ourResolved = resolve(Object.class);
343                }
344                Class<?> otherResolved = other.toClass();
345
346                // We need an exact type match for generics
347                // List<CharSequence> is not assignable from List<String>
348                if (exactMatch ? !ourResolved.equals(otherResolved) : !ClassUtils.isAssignable(ourResolved, otherResolved)) {
349                        return false;
350                }
351
352                if (checkGenerics) {
353                        // Recursively check each generic
354                        ResolvableType[] ourGenerics = getGenerics();
355                        ResolvableType[] typeGenerics = other.as(ourResolved).getGenerics();
356                        if (ourGenerics.length != typeGenerics.length) {
357                                return false;
358                        }
359                        if (matchedBefore == null) {
360                                matchedBefore = new IdentityHashMap<>(1);
361                        }
362                        matchedBefore.put(this.type, other.type);
363                        for (int i = 0; i < ourGenerics.length; i++) {
364                                if (!ourGenerics[i].isAssignableFrom(typeGenerics[i], matchedBefore)) {
365                                        return false;
366                                }
367                        }
368                }
369
370                return true;
371        }
372
373        /**
374         * Return {@code true} if this type resolves to a Class that represents an array.
375         * @see #getComponentType()
376         */
377        public boolean isArray() {
378                if (this == NONE) {
379                        return false;
380                }
381                return ((this.type instanceof Class && ((Class<?>) this.type).isArray()) ||
382                                this.type instanceof GenericArrayType || resolveType().isArray());
383        }
384
385        /**
386         * Return the ResolvableType representing the component type of the array or
387         * {@link #NONE} if this type does not represent an array.
388         * @see #isArray()
389         */
390        public ResolvableType getComponentType() {
391                if (this == NONE) {
392                        return NONE;
393                }
394                if (this.componentType != null) {
395                        return this.componentType;
396                }
397                if (this.type instanceof Class) {
398                        Class<?> componentType = ((Class<?>) this.type).getComponentType();
399                        return forType(componentType, this.variableResolver);
400                }
401                if (this.type instanceof GenericArrayType) {
402                        return forType(((GenericArrayType) this.type).getGenericComponentType(), this.variableResolver);
403                }
404                return resolveType().getComponentType();
405        }
406
407        /**
408         * Convenience method to return this type as a resolvable {@link Collection} type.
409         * Returns {@link #NONE} if this type does not implement or extend
410         * {@link Collection}.
411         * @see #as(Class)
412         * @see #asMap()
413         */
414        public ResolvableType asCollection() {
415                return as(Collection.class);
416        }
417
418        /**
419         * Convenience method to return this type as a resolvable {@link Map} type.
420         * Returns {@link #NONE} if this type does not implement or extend
421         * {@link Map}.
422         * @see #as(Class)
423         * @see #asCollection()
424         */
425        public ResolvableType asMap() {
426                return as(Map.class);
427        }
428
429        /**
430         * Return this type as a {@link ResolvableType} of the specified class. Searches
431         * {@link #getSuperType() supertype} and {@link #getInterfaces() interface}
432         * hierarchies to find a match, returning {@link #NONE} if this type does not
433         * implement or extend the specified class.
434         * @param type the required type (typically narrowed)
435         * @return a {@link ResolvableType} representing this object as the specified
436         * type, or {@link #NONE} if not resolvable as that type
437         * @see #asCollection()
438         * @see #asMap()
439         * @see #getSuperType()
440         * @see #getInterfaces()
441         */
442        public ResolvableType as(Class<?> type) {
443                if (this == NONE) {
444                        return NONE;
445                }
446                Class<?> resolved = resolve();
447                if (resolved == null || resolved == type) {
448                        return this;
449                }
450                for (ResolvableType interfaceType : getInterfaces()) {
451                        ResolvableType interfaceAsType = interfaceType.as(type);
452                        if (interfaceAsType != NONE) {
453                                return interfaceAsType;
454                        }
455                }
456                return getSuperType().as(type);
457        }
458
459        /**
460         * Return a {@link ResolvableType} representing the direct supertype of this type.
461         * If no supertype is available this method returns {@link #NONE}.
462         * <p>Note: The resulting {@link ResolvableType} instance may not be {@link Serializable}.
463         * @see #getInterfaces()
464         */
465        public ResolvableType getSuperType() {
466                Class<?> resolved = resolve();
467                if (resolved == null) {
468                        return NONE;
469                }
470                try {
471                        Type superclass = resolved.getGenericSuperclass();
472                        if (superclass == null) {
473                                return NONE;
474                        }
475                        ResolvableType superType = this.superType;
476                        if (superType == null) {
477                                superType = forType(superclass, this);
478                                this.superType = superType;
479                        }
480                        return superType;
481                }
482                catch (TypeNotPresentException ex) {
483                        // Ignore non-present types in generic signature
484                        return NONE;
485                }
486        }
487
488        /**
489         * Return a {@link ResolvableType} array representing the direct interfaces
490         * implemented by this type. If this type does not implement any interfaces an
491         * empty array is returned.
492         * <p>Note: The resulting {@link ResolvableType} instances may not be {@link Serializable}.
493         * @see #getSuperType()
494         */
495        public ResolvableType[] getInterfaces() {
496                Class<?> resolved = resolve();
497                if (resolved == null) {
498                        return EMPTY_TYPES_ARRAY;
499                }
500                ResolvableType[] interfaces = this.interfaces;
501                if (interfaces == null) {
502                        Type[] genericIfcs = resolved.getGenericInterfaces();
503                        interfaces = new ResolvableType[genericIfcs.length];
504                        for (int i = 0; i < genericIfcs.length; i++) {
505                                interfaces[i] = forType(genericIfcs[i], this);
506                        }
507                        this.interfaces = interfaces;
508                }
509                return interfaces;
510        }
511
512        /**
513         * Return {@code true} if this type contains generic parameters.
514         * @see #getGeneric(int...)
515         * @see #getGenerics()
516         */
517        public boolean hasGenerics() {
518                return (getGenerics().length > 0);
519        }
520
521        /**
522         * Return {@code true} if this type contains unresolvable generics only,
523         * that is, no substitute for any of its declared type variables.
524         */
525        boolean isEntirelyUnresolvable() {
526                if (this == NONE) {
527                        return false;
528                }
529                ResolvableType[] generics = getGenerics();
530                for (ResolvableType generic : generics) {
531                        if (!generic.isUnresolvableTypeVariable() && !generic.isWildcardWithoutBounds()) {
532                                return false;
533                        }
534                }
535                return true;
536        }
537
538        /**
539         * Determine whether the underlying type has any unresolvable generics:
540         * either through an unresolvable type variable on the type itself
541         * or through implementing a generic interface in a raw fashion,
542         * i.e. without substituting that interface's type variables.
543         * The result will be {@code true} only in those two scenarios.
544         */
545        public boolean hasUnresolvableGenerics() {
546                if (this == NONE) {
547                        return false;
548                }
549                ResolvableType[] generics = getGenerics();
550                for (ResolvableType generic : generics) {
551                        if (generic.isUnresolvableTypeVariable() || generic.isWildcardWithoutBounds()) {
552                                return true;
553                        }
554                }
555                Class<?> resolved = resolve();
556                if (resolved != null) {
557                        try {
558                                for (Type genericInterface : resolved.getGenericInterfaces()) {
559                                        if (genericInterface instanceof Class) {
560                                                if (forClass((Class<?>) genericInterface).hasGenerics()) {
561                                                        return true;
562                                                }
563                                        }
564                                }
565                        }
566                        catch (TypeNotPresentException ex) {
567                                // Ignore non-present types in generic signature
568                        }
569                        return getSuperType().hasUnresolvableGenerics();
570                }
571                return false;
572        }
573
574        /**
575         * Determine whether the underlying type is a type variable that
576         * cannot be resolved through the associated variable resolver.
577         */
578        private boolean isUnresolvableTypeVariable() {
579                if (this.type instanceof TypeVariable) {
580                        if (this.variableResolver == null) {
581                                return true;
582                        }
583                        TypeVariable<?> variable = (TypeVariable<?>) this.type;
584                        ResolvableType resolved = this.variableResolver.resolveVariable(variable);
585                        if (resolved == null || resolved.isUnresolvableTypeVariable()) {
586                                return true;
587                        }
588                }
589                return false;
590        }
591
592        /**
593         * Determine whether the underlying type represents a wildcard
594         * without specific bounds (i.e., equal to {@code ? extends Object}).
595         */
596        private boolean isWildcardWithoutBounds() {
597                if (this.type instanceof WildcardType) {
598                        WildcardType wt = (WildcardType) this.type;
599                        if (wt.getLowerBounds().length == 0) {
600                                Type[] upperBounds = wt.getUpperBounds();
601                                if (upperBounds.length == 0 || (upperBounds.length == 1 && Object.class == upperBounds[0])) {
602                                        return true;
603                                }
604                        }
605                }
606                return false;
607        }
608
609        /**
610         * Return a {@link ResolvableType} for the specified nesting level.
611         * See {@link #getNested(int, Map)} for details.
612         * @param nestingLevel the nesting level
613         * @return the {@link ResolvableType} type, or {@code #NONE}
614         */
615        public ResolvableType getNested(int nestingLevel) {
616                return getNested(nestingLevel, null);
617        }
618
619        /**
620         * Return a {@link ResolvableType} for the specified nesting level.
621         * <p>The nesting level refers to the specific generic parameter that should be returned.
622         * A nesting level of 1 indicates this type; 2 indicates the first nested generic;
623         * 3 the second; and so on. For example, given {@code List<Set<Integer>>} level 1 refers
624         * to the {@code List}, level 2 the {@code Set}, and level 3 the {@code Integer}.
625         * <p>The {@code typeIndexesPerLevel} map can be used to reference a specific generic
626         * for the given level. For example, an index of 0 would refer to a {@code Map} key;
627         * whereas, 1 would refer to the value. If the map does not contain a value for a
628         * specific level the last generic will be used (e.g. a {@code Map} value).
629         * <p>Nesting levels may also apply to array types; for example given
630         * {@code String[]}, a nesting level of 2 refers to {@code String}.
631         * <p>If a type does not {@link #hasGenerics() contain} generics the
632         * {@link #getSuperType() supertype} hierarchy will be considered.
633         * @param nestingLevel the required nesting level, indexed from 1 for the
634         * current type, 2 for the first nested generic, 3 for the second and so on
635         * @param typeIndexesPerLevel a map containing the generic index for a given
636         * nesting level (may be {@code null})
637         * @return a {@link ResolvableType} for the nested level, or {@link #NONE}
638         */
639        public ResolvableType getNested(int nestingLevel, @Nullable Map<Integer, Integer> typeIndexesPerLevel) {
640                ResolvableType result = this;
641                for (int i = 2; i <= nestingLevel; i++) {
642                        if (result.isArray()) {
643                                result = result.getComponentType();
644                        }
645                        else {
646                                // Handle derived types
647                                while (result != ResolvableType.NONE && !result.hasGenerics()) {
648                                        result = result.getSuperType();
649                                }
650                                Integer index = (typeIndexesPerLevel != null ? typeIndexesPerLevel.get(i) : null);
651                                index = (index == null ? result.getGenerics().length - 1 : index);
652                                result = result.getGeneric(index);
653                        }
654                }
655                return result;
656        }
657
658        /**
659         * Return a {@link ResolvableType} representing the generic parameter for the
660         * given indexes. Indexes are zero based; for example given the type
661         * {@code Map<Integer, List<String>>}, {@code getGeneric(0)} will access the
662         * {@code Integer}. Nested generics can be accessed by specifying multiple indexes;
663         * for example {@code getGeneric(1, 0)} will access the {@code String} from the
664         * nested {@code List}. For convenience, if no indexes are specified the first
665         * generic is returned.
666         * <p>If no generic is available at the specified indexes {@link #NONE} is returned.
667         * @param indexes the indexes that refer to the generic parameter
668         * (may be omitted to return the first generic)
669         * @return a {@link ResolvableType} for the specified generic, or {@link #NONE}
670         * @see #hasGenerics()
671         * @see #getGenerics()
672         * @see #resolveGeneric(int...)
673         * @see #resolveGenerics()
674         */
675        public ResolvableType getGeneric(@Nullable int... indexes) {
676                ResolvableType[] generics = getGenerics();
677                if (indexes == null || indexes.length == 0) {
678                        return (generics.length == 0 ? NONE : generics[0]);
679                }
680                ResolvableType generic = this;
681                for (int index : indexes) {
682                        generics = generic.getGenerics();
683                        if (index < 0 || index >= generics.length) {
684                                return NONE;
685                        }
686                        generic = generics[index];
687                }
688                return generic;
689        }
690
691        /**
692         * Return an array of {@link ResolvableType ResolvableTypes} representing the generic parameters of
693         * this type. If no generics are available an empty array is returned. If you need to
694         * access a specific generic consider using the {@link #getGeneric(int...)} method as
695         * it allows access to nested generics and protects against
696         * {@code IndexOutOfBoundsExceptions}.
697         * @return an array of {@link ResolvableType ResolvableTypes} representing the generic parameters
698         * (never {@code null})
699         * @see #hasGenerics()
700         * @see #getGeneric(int...)
701         * @see #resolveGeneric(int...)
702         * @see #resolveGenerics()
703         */
704        public ResolvableType[] getGenerics() {
705                if (this == NONE) {
706                        return EMPTY_TYPES_ARRAY;
707                }
708                ResolvableType[] generics = this.generics;
709                if (generics == null) {
710                        if (this.type instanceof Class) {
711                                Type[] typeParams = ((Class<?>) this.type).getTypeParameters();
712                                generics = new ResolvableType[typeParams.length];
713                                for (int i = 0; i < generics.length; i++) {
714                                        generics[i] = ResolvableType.forType(typeParams[i], this);
715                                }
716                        }
717                        else if (this.type instanceof ParameterizedType) {
718                                Type[] actualTypeArguments = ((ParameterizedType) this.type).getActualTypeArguments();
719                                generics = new ResolvableType[actualTypeArguments.length];
720                                for (int i = 0; i < actualTypeArguments.length; i++) {
721                                        generics[i] = forType(actualTypeArguments[i], this.variableResolver);
722                                }
723                        }
724                        else {
725                                generics = resolveType().getGenerics();
726                        }
727                        this.generics = generics;
728                }
729                return generics;
730        }
731
732        /**
733         * Convenience method that will {@link #getGenerics() get} and
734         * {@link #resolve() resolve} generic parameters.
735         * @return an array of resolved generic parameters (the resulting array
736         * will never be {@code null}, but it may contain {@code null} elements})
737         * @see #getGenerics()
738         * @see #resolve()
739         */
740        public Class<?>[] resolveGenerics() {
741                ResolvableType[] generics = getGenerics();
742                Class<?>[] resolvedGenerics = new Class<?>[generics.length];
743                for (int i = 0; i < generics.length; i++) {
744                        resolvedGenerics[i] = generics[i].resolve();
745                }
746                return resolvedGenerics;
747        }
748
749        /**
750         * Convenience method that will {@link #getGenerics() get} and {@link #resolve()
751         * resolve} generic parameters, using the specified {@code fallback} if any type
752         * cannot be resolved.
753         * @param fallback the fallback class to use if resolution fails
754         * @return an array of resolved generic parameters
755         * @see #getGenerics()
756         * @see #resolve()
757         */
758        public Class<?>[] resolveGenerics(Class<?> fallback) {
759                ResolvableType[] generics = getGenerics();
760                Class<?>[] resolvedGenerics = new Class<?>[generics.length];
761                for (int i = 0; i < generics.length; i++) {
762                        resolvedGenerics[i] = generics[i].resolve(fallback);
763                }
764                return resolvedGenerics;
765        }
766
767        /**
768         * Convenience method that will {@link #getGeneric(int...) get} and
769         * {@link #resolve() resolve} a specific generic parameters.
770         * @param indexes the indexes that refer to the generic parameter
771         * (may be omitted to return the first generic)
772         * @return a resolved {@link Class} or {@code null}
773         * @see #getGeneric(int...)
774         * @see #resolve()
775         */
776        @Nullable
777        public Class<?> resolveGeneric(int... indexes) {
778                return getGeneric(indexes).resolve();
779        }
780
781        /**
782         * Resolve this type to a {@link java.lang.Class}, returning {@code null}
783         * if the type cannot be resolved. This method will consider bounds of
784         * {@link TypeVariable TypeVariables} and {@link WildcardType WildcardTypes} if
785         * direct resolution fails; however, bounds of {@code Object.class} will be ignored.
786         * <p>If this method returns a non-null {@code Class} and {@link #hasGenerics()}
787         * returns {@code false}, the given type effectively wraps a plain {@code Class},
788         * allowing for plain {@code Class} processing if desirable.
789         * @return the resolved {@link Class}, or {@code null} if not resolvable
790         * @see #resolve(Class)
791         * @see #resolveGeneric(int...)
792         * @see #resolveGenerics()
793         */
794        @Nullable
795        public Class<?> resolve() {
796                return this.resolved;
797        }
798
799        /**
800         * Resolve this type to a {@link java.lang.Class}, returning the specified
801         * {@code fallback} if the type cannot be resolved. This method will consider bounds
802         * of {@link TypeVariable TypeVariables} and {@link WildcardType WildcardTypes} if
803         * direct resolution fails; however, bounds of {@code Object.class} will be ignored.
804         * @param fallback the fallback class to use if resolution fails
805         * @return the resolved {@link Class} or the {@code fallback}
806         * @see #resolve()
807         * @see #resolveGeneric(int...)
808         * @see #resolveGenerics()
809         */
810        public Class<?> resolve(Class<?> fallback) {
811                return (this.resolved != null ? this.resolved : fallback);
812        }
813
814        @Nullable
815        private Class<?> resolveClass() {
816                if (this.type == EmptyType.INSTANCE) {
817                        return null;
818                }
819                if (this.type instanceof Class) {
820                        return (Class<?>) this.type;
821                }
822                if (this.type instanceof GenericArrayType) {
823                        Class<?> resolvedComponent = getComponentType().resolve();
824                        return (resolvedComponent != null ? Array.newInstance(resolvedComponent, 0).getClass() : null);
825                }
826                return resolveType().resolve();
827        }
828
829        /**
830         * Resolve this type by a single level, returning the resolved value or {@link #NONE}.
831         * <p>Note: The returned {@link ResolvableType} should only be used as an intermediary
832         * as it cannot be serialized.
833         */
834        ResolvableType resolveType() {
835                if (this.type instanceof ParameterizedType) {
836                        return forType(((ParameterizedType) this.type).getRawType(), this.variableResolver);
837                }
838                if (this.type instanceof WildcardType) {
839                        Type resolved = resolveBounds(((WildcardType) this.type).getUpperBounds());
840                        if (resolved == null) {
841                                resolved = resolveBounds(((WildcardType) this.type).getLowerBounds());
842                        }
843                        return forType(resolved, this.variableResolver);
844                }
845                if (this.type instanceof TypeVariable) {
846                        TypeVariable<?> variable = (TypeVariable<?>) this.type;
847                        // Try default variable resolution
848                        if (this.variableResolver != null) {
849                                ResolvableType resolved = this.variableResolver.resolveVariable(variable);
850                                if (resolved != null) {
851                                        return resolved;
852                                }
853                        }
854                        // Fallback to bounds
855                        return forType(resolveBounds(variable.getBounds()), this.variableResolver);
856                }
857                return NONE;
858        }
859
860        @Nullable
861        private Type resolveBounds(Type[] bounds) {
862                if (bounds.length == 0 || bounds[0] == Object.class) {
863                        return null;
864                }
865                return bounds[0];
866        }
867
868        @Nullable
869        private ResolvableType resolveVariable(TypeVariable<?> variable) {
870                if (this.type instanceof TypeVariable) {
871                        return resolveType().resolveVariable(variable);
872                }
873                if (this.type instanceof ParameterizedType) {
874                        ParameterizedType parameterizedType = (ParameterizedType) this.type;
875                        Class<?> resolved = resolve();
876                        if (resolved == null) {
877                                return null;
878                        }
879                        TypeVariable<?>[] variables = resolved.getTypeParameters();
880                        for (int i = 0; i < variables.length; i++) {
881                                if (ObjectUtils.nullSafeEquals(variables[i].getName(), variable.getName())) {
882                                        Type actualType = parameterizedType.getActualTypeArguments()[i];
883                                        return forType(actualType, this.variableResolver);
884                                }
885                        }
886                        Type ownerType = parameterizedType.getOwnerType();
887                        if (ownerType != null) {
888                                return forType(ownerType, this.variableResolver).resolveVariable(variable);
889                        }
890                }
891                if (this.type instanceof WildcardType) {
892                        ResolvableType resolved = resolveType().resolveVariable(variable);
893                        if (resolved != null) {
894                                return resolved;
895                        }
896                }
897                if (this.variableResolver != null) {
898                        return this.variableResolver.resolveVariable(variable);
899                }
900                return null;
901        }
902
903
904        @Override
905        public boolean equals(@Nullable Object other) {
906                if (this == other) {
907                        return true;
908                }
909                if (!(other instanceof ResolvableType)) {
910                        return false;
911                }
912
913                ResolvableType otherType = (ResolvableType) other;
914                if (!ObjectUtils.nullSafeEquals(this.type, otherType.type)) {
915                        return false;
916                }
917                if (this.typeProvider != otherType.typeProvider &&
918                                (this.typeProvider == null || otherType.typeProvider == null ||
919                                !ObjectUtils.nullSafeEquals(this.typeProvider.getType(), otherType.typeProvider.getType()))) {
920                        return false;
921                }
922                if (this.variableResolver != otherType.variableResolver &&
923                                (this.variableResolver == null || otherType.variableResolver == null ||
924                                !ObjectUtils.nullSafeEquals(this.variableResolver.getSource(), otherType.variableResolver.getSource()))) {
925                        return false;
926                }
927                if (!ObjectUtils.nullSafeEquals(this.componentType, otherType.componentType)) {
928                        return false;
929                }
930                return true;
931        }
932
933        @Override
934        public int hashCode() {
935                return (this.hash != null ? this.hash : calculateHashCode());
936        }
937
938        private int calculateHashCode() {
939                int hashCode = ObjectUtils.nullSafeHashCode(this.type);
940                if (this.typeProvider != null) {
941                        hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.typeProvider.getType());
942                }
943                if (this.variableResolver != null) {
944                        hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.variableResolver.getSource());
945                }
946                if (this.componentType != null) {
947                        hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.componentType);
948                }
949                return hashCode;
950        }
951
952        /**
953         * Adapts this {@link ResolvableType} to a {@link VariableResolver}.
954         */
955        @Nullable
956        VariableResolver asVariableResolver() {
957                if (this == NONE) {
958                        return null;
959                }
960                return new DefaultVariableResolver(this);
961        }
962
963        /**
964         * Custom serialization support for {@link #NONE}.
965         */
966        private Object readResolve() {
967                return (this.type == EmptyType.INSTANCE ? NONE : this);
968        }
969
970        /**
971         * Return a String representation of this type in its fully resolved form
972         * (including any generic parameters).
973         */
974        @Override
975        public String toString() {
976                if (isArray()) {
977                        return getComponentType() + "[]";
978                }
979                if (this.resolved == null) {
980                        return "?";
981                }
982                if (this.type instanceof TypeVariable) {
983                        TypeVariable<?> variable = (TypeVariable<?>) this.type;
984                        if (this.variableResolver == null || this.variableResolver.resolveVariable(variable) == null) {
985                                // Don't bother with variable boundaries for toString()...
986                                // Can cause infinite recursions in case of self-references
987                                return "?";
988                        }
989                }
990                if (hasGenerics()) {
991                        return this.resolved.getName() + '<' + StringUtils.arrayToDelimitedString(getGenerics(), ", ") + '>';
992                }
993                return this.resolved.getName();
994        }
995
996
997        // Factory methods
998
999        /**
1000         * Return a {@link ResolvableType} for the specified {@link Class},
1001         * using the full generic type information for assignability checks.
1002         * For example: {@code ResolvableType.forClass(MyArrayList.class)}.
1003         * @param clazz the class to introspect ({@code null} is semantically
1004         * equivalent to {@code Object.class} for typical use cases here)
1005         * @return a {@link ResolvableType} for the specified class
1006         * @see #forClass(Class, Class)
1007         * @see #forClassWithGenerics(Class, Class...)
1008         */
1009        public static ResolvableType forClass(@Nullable Class<?> clazz) {
1010                return new ResolvableType(clazz);
1011        }
1012
1013        /**
1014         * Return a {@link ResolvableType} for the specified {@link Class},
1015         * doing assignability checks against the raw class only (analogous to
1016         * {@link Class#isAssignableFrom}, which this serves as a wrapper for.
1017         * For example: {@code ResolvableType.forRawClass(List.class)}.
1018         * @param clazz the class to introspect ({@code null} is semantically
1019         * equivalent to {@code Object.class} for typical use cases here)
1020         * @return a {@link ResolvableType} for the specified class
1021         * @since 4.2
1022         * @see #forClass(Class)
1023         * @see #getRawClass()
1024         */
1025        public static ResolvableType forRawClass(@Nullable Class<?> clazz) {
1026                return new ResolvableType(clazz) {
1027                        @Override
1028                        public ResolvableType[] getGenerics() {
1029                                return EMPTY_TYPES_ARRAY;
1030                        }
1031                        @Override
1032                        public boolean isAssignableFrom(Class<?> other) {
1033                                return (clazz == null || ClassUtils.isAssignable(clazz, other));
1034                        }
1035                        @Override
1036                        public boolean isAssignableFrom(ResolvableType other) {
1037                                Class<?> otherClass = other.resolve();
1038                                return (otherClass != null && (clazz == null || ClassUtils.isAssignable(clazz, otherClass)));
1039                        }
1040                };
1041        }
1042
1043        /**
1044         * Return a {@link ResolvableType} for the specified base type
1045         * (interface or base class) with a given implementation class.
1046         * For example: {@code ResolvableType.forClass(List.class, MyArrayList.class)}.
1047         * @param baseType the base type (must not be {@code null})
1048         * @param implementationClass the implementation class
1049         * @return a {@link ResolvableType} for the specified base type backed by the
1050         * given implementation class
1051         * @see #forClass(Class)
1052         * @see #forClassWithGenerics(Class, Class...)
1053         */
1054        public static ResolvableType forClass(Class<?> baseType, Class<?> implementationClass) {
1055                Assert.notNull(baseType, "Base type must not be null");
1056                ResolvableType asType = forType(implementationClass).as(baseType);
1057                return (asType == NONE ? forType(baseType) : asType);
1058        }
1059
1060        /**
1061         * Return a {@link ResolvableType} for the specified {@link Class} with pre-declared generics.
1062         * @param clazz the class (or interface) to introspect
1063         * @param generics the generics of the class
1064         * @return a {@link ResolvableType} for the specific class and generics
1065         * @see #forClassWithGenerics(Class, ResolvableType...)
1066         */
1067        public static ResolvableType forClassWithGenerics(Class<?> clazz, Class<?>... generics) {
1068                Assert.notNull(clazz, "Class must not be null");
1069                Assert.notNull(generics, "Generics array must not be null");
1070                ResolvableType[] resolvableGenerics = new ResolvableType[generics.length];
1071                for (int i = 0; i < generics.length; i++) {
1072                        resolvableGenerics[i] = forClass(generics[i]);
1073                }
1074                return forClassWithGenerics(clazz, resolvableGenerics);
1075        }
1076
1077        /**
1078         * Return a {@link ResolvableType} for the specified {@link Class} with pre-declared generics.
1079         * @param clazz the class (or interface) to introspect
1080         * @param generics the generics of the class
1081         * @return a {@link ResolvableType} for the specific class and generics
1082         * @see #forClassWithGenerics(Class, Class...)
1083         */
1084        public static ResolvableType forClassWithGenerics(Class<?> clazz, ResolvableType... generics) {
1085                Assert.notNull(clazz, "Class must not be null");
1086                Assert.notNull(generics, "Generics array must not be null");
1087                TypeVariable<?>[] variables = clazz.getTypeParameters();
1088                Assert.isTrue(variables.length == generics.length, "Mismatched number of generics specified");
1089
1090                Type[] arguments = new Type[generics.length];
1091                for (int i = 0; i < generics.length; i++) {
1092                        ResolvableType generic = generics[i];
1093                        Type argument = (generic != null ? generic.getType() : null);
1094                        arguments[i] = (argument != null && !(argument instanceof TypeVariable) ? argument : variables[i]);
1095                }
1096
1097                ParameterizedType syntheticType = new SyntheticParameterizedType(clazz, arguments);
1098                return forType(syntheticType, new TypeVariablesVariableResolver(variables, generics));
1099        }
1100
1101        /**
1102         * Return a {@link ResolvableType} for the specified instance. The instance does not
1103         * convey generic information but if it implements {@link ResolvableTypeProvider} a
1104         * more precise {@link ResolvableType} can be used than the simple one based on
1105         * the {@link #forClass(Class) Class instance}.
1106         * @param instance the instance
1107         * @return a {@link ResolvableType} for the specified instance
1108         * @since 4.2
1109         * @see ResolvableTypeProvider
1110         */
1111        public static ResolvableType forInstance(Object instance) {
1112                Assert.notNull(instance, "Instance must not be null");
1113                if (instance instanceof ResolvableTypeProvider) {
1114                        ResolvableType type = ((ResolvableTypeProvider) instance).getResolvableType();
1115                        if (type != null) {
1116                                return type;
1117                        }
1118                }
1119                return ResolvableType.forClass(instance.getClass());
1120        }
1121
1122        /**
1123         * Return a {@link ResolvableType} for the specified {@link Field}.
1124         * @param field the source field
1125         * @return a {@link ResolvableType} for the specified field
1126         * @see #forField(Field, Class)
1127         */
1128        public static ResolvableType forField(Field field) {
1129                Assert.notNull(field, "Field must not be null");
1130                return forType(null, new FieldTypeProvider(field), null);
1131        }
1132
1133        /**
1134         * Return a {@link ResolvableType} for the specified {@link Field} with a given
1135         * implementation.
1136         * <p>Use this variant when the class that declares the field includes generic
1137         * parameter variables that are satisfied by the implementation class.
1138         * @param field the source field
1139         * @param implementationClass the implementation class
1140         * @return a {@link ResolvableType} for the specified field
1141         * @see #forField(Field)
1142         */
1143        public static ResolvableType forField(Field field, Class<?> implementationClass) {
1144                Assert.notNull(field, "Field must not be null");
1145                ResolvableType owner = forType(implementationClass).as(field.getDeclaringClass());
1146                return forType(null, new FieldTypeProvider(field), owner.asVariableResolver());
1147        }
1148
1149        /**
1150         * Return a {@link ResolvableType} for the specified {@link Field} with a given
1151         * implementation.
1152         * <p>Use this variant when the class that declares the field includes generic
1153         * parameter variables that are satisfied by the implementation type.
1154         * @param field the source field
1155         * @param implementationType the implementation type
1156         * @return a {@link ResolvableType} for the specified field
1157         * @see #forField(Field)
1158         */
1159        public static ResolvableType forField(Field field, @Nullable ResolvableType implementationType) {
1160                Assert.notNull(field, "Field must not be null");
1161                ResolvableType owner = (implementationType != null ? implementationType : NONE);
1162                owner = owner.as(field.getDeclaringClass());
1163                return forType(null, new FieldTypeProvider(field), owner.asVariableResolver());
1164        }
1165
1166        /**
1167         * Return a {@link ResolvableType} for the specified {@link Field} with the
1168         * given nesting level.
1169         * @param field the source field
1170         * @param nestingLevel the nesting level (1 for the outer level; 2 for a nested
1171         * generic type; etc)
1172         * @see #forField(Field)
1173         */
1174        public static ResolvableType forField(Field field, int nestingLevel) {
1175                Assert.notNull(field, "Field must not be null");
1176                return forType(null, new FieldTypeProvider(field), null).getNested(nestingLevel);
1177        }
1178
1179        /**
1180         * Return a {@link ResolvableType} for the specified {@link Field} with a given
1181         * implementation and the given nesting level.
1182         * <p>Use this variant when the class that declares the field includes generic
1183         * parameter variables that are satisfied by the implementation class.
1184         * @param field the source field
1185         * @param nestingLevel the nesting level (1 for the outer level; 2 for a nested
1186         * generic type; etc)
1187         * @param implementationClass the implementation class
1188         * @return a {@link ResolvableType} for the specified field
1189         * @see #forField(Field)
1190         */
1191        public static ResolvableType forField(Field field, int nestingLevel, @Nullable Class<?> implementationClass) {
1192                Assert.notNull(field, "Field must not be null");
1193                ResolvableType owner = forType(implementationClass).as(field.getDeclaringClass());
1194                return forType(null, new FieldTypeProvider(field), owner.asVariableResolver()).getNested(nestingLevel);
1195        }
1196
1197        /**
1198         * Return a {@link ResolvableType} for the specified {@link Constructor} parameter.
1199         * @param constructor the source constructor (must not be {@code null})
1200         * @param parameterIndex the parameter index
1201         * @return a {@link ResolvableType} for the specified constructor parameter
1202         * @see #forConstructorParameter(Constructor, int, Class)
1203         */
1204        public static ResolvableType forConstructorParameter(Constructor<?> constructor, int parameterIndex) {
1205                Assert.notNull(constructor, "Constructor must not be null");
1206                return forMethodParameter(new MethodParameter(constructor, parameterIndex));
1207        }
1208
1209        /**
1210         * Return a {@link ResolvableType} for the specified {@link Constructor} parameter
1211         * with a given implementation. Use this variant when the class that declares the
1212         * constructor includes generic parameter variables that are satisfied by the
1213         * implementation class.
1214         * @param constructor the source constructor (must not be {@code null})
1215         * @param parameterIndex the parameter index
1216         * @param implementationClass the implementation class
1217         * @return a {@link ResolvableType} for the specified constructor parameter
1218         * @see #forConstructorParameter(Constructor, int)
1219         */
1220        public static ResolvableType forConstructorParameter(Constructor<?> constructor, int parameterIndex,
1221                        Class<?> implementationClass) {
1222
1223                Assert.notNull(constructor, "Constructor must not be null");
1224                MethodParameter methodParameter = new MethodParameter(constructor, parameterIndex, implementationClass);
1225                return forMethodParameter(methodParameter);
1226        }
1227
1228        /**
1229         * Return a {@link ResolvableType} for the specified {@link Method} return type.
1230         * @param method the source for the method return type
1231         * @return a {@link ResolvableType} for the specified method return
1232         * @see #forMethodReturnType(Method, Class)
1233         */
1234        public static ResolvableType forMethodReturnType(Method method) {
1235                Assert.notNull(method, "Method must not be null");
1236                return forMethodParameter(new MethodParameter(method, -1));
1237        }
1238
1239        /**
1240         * Return a {@link ResolvableType} for the specified {@link Method} return type.
1241         * Use this variant when the class that declares the method includes generic
1242         * parameter variables that are satisfied by the implementation class.
1243         * @param method the source for the method return type
1244         * @param implementationClass the implementation class
1245         * @return a {@link ResolvableType} for the specified method return
1246         * @see #forMethodReturnType(Method)
1247         */
1248        public static ResolvableType forMethodReturnType(Method method, Class<?> implementationClass) {
1249                Assert.notNull(method, "Method must not be null");
1250                MethodParameter methodParameter = new MethodParameter(method, -1, implementationClass);
1251                return forMethodParameter(methodParameter);
1252        }
1253
1254        /**
1255         * Return a {@link ResolvableType} for the specified {@link Method} parameter.
1256         * @param method the source method (must not be {@code null})
1257         * @param parameterIndex the parameter index
1258         * @return a {@link ResolvableType} for the specified method parameter
1259         * @see #forMethodParameter(Method, int, Class)
1260         * @see #forMethodParameter(MethodParameter)
1261         */
1262        public static ResolvableType forMethodParameter(Method method, int parameterIndex) {
1263                Assert.notNull(method, "Method must not be null");
1264                return forMethodParameter(new MethodParameter(method, parameterIndex));
1265        }
1266
1267        /**
1268         * Return a {@link ResolvableType} for the specified {@link Method} parameter with a
1269         * given implementation. Use this variant when the class that declares the method
1270         * includes generic parameter variables that are satisfied by the implementation class.
1271         * @param method the source method (must not be {@code null})
1272         * @param parameterIndex the parameter index
1273         * @param implementationClass the implementation class
1274         * @return a {@link ResolvableType} for the specified method parameter
1275         * @see #forMethodParameter(Method, int, Class)
1276         * @see #forMethodParameter(MethodParameter)
1277         */
1278        public static ResolvableType forMethodParameter(Method method, int parameterIndex, Class<?> implementationClass) {
1279                Assert.notNull(method, "Method must not be null");
1280                MethodParameter methodParameter = new MethodParameter(method, parameterIndex, implementationClass);
1281                return forMethodParameter(methodParameter);
1282        }
1283
1284        /**
1285         * Return a {@link ResolvableType} for the specified {@link MethodParameter}.
1286         * @param methodParameter the source method parameter (must not be {@code null})
1287         * @return a {@link ResolvableType} for the specified method parameter
1288         * @see #forMethodParameter(Method, int)
1289         */
1290        public static ResolvableType forMethodParameter(MethodParameter methodParameter) {
1291                return forMethodParameter(methodParameter, (Type) null);
1292        }
1293
1294        /**
1295         * Return a {@link ResolvableType} for the specified {@link MethodParameter} with a
1296         * given implementation type. Use this variant when the class that declares the method
1297         * includes generic parameter variables that are satisfied by the implementation type.
1298         * @param methodParameter the source method parameter (must not be {@code null})
1299         * @param implementationType the implementation type
1300         * @return a {@link ResolvableType} for the specified method parameter
1301         * @see #forMethodParameter(MethodParameter)
1302         */
1303        public static ResolvableType forMethodParameter(MethodParameter methodParameter,
1304                        @Nullable ResolvableType implementationType) {
1305
1306                Assert.notNull(methodParameter, "MethodParameter must not be null");
1307                implementationType = (implementationType != null ? implementationType :
1308                                forType(methodParameter.getContainingClass()));
1309                ResolvableType owner = implementationType.as(methodParameter.getDeclaringClass());
1310                return forType(null, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).
1311                                getNested(methodParameter.getNestingLevel(), methodParameter.typeIndexesPerLevel);
1312        }
1313
1314        /**
1315         * Return a {@link ResolvableType} for the specified {@link MethodParameter},
1316         * overriding the target type to resolve with a specific given type.
1317         * @param methodParameter the source method parameter (must not be {@code null})
1318         * @param targetType the type to resolve (a part of the method parameter's type)
1319         * @return a {@link ResolvableType} for the specified method parameter
1320         * @see #forMethodParameter(Method, int)
1321         */
1322        public static ResolvableType forMethodParameter(MethodParameter methodParameter, @Nullable Type targetType) {
1323                Assert.notNull(methodParameter, "MethodParameter must not be null");
1324                return forMethodParameter(methodParameter, targetType, methodParameter.getNestingLevel());
1325        }
1326
1327        /**
1328         * Return a {@link ResolvableType} for the specified {@link MethodParameter} at
1329         * a specific nesting level, overriding the target type to resolve with a specific
1330         * given type.
1331         * @param methodParameter the source method parameter (must not be {@code null})
1332         * @param targetType the type to resolve (a part of the method parameter's type)
1333         * @param nestingLevel the nesting level to use
1334         * @return a {@link ResolvableType} for the specified method parameter
1335         * @since 5.2
1336         * @see #forMethodParameter(Method, int)
1337         */
1338        static ResolvableType forMethodParameter(
1339                        MethodParameter methodParameter, @Nullable Type targetType, int nestingLevel) {
1340
1341                ResolvableType owner = forType(methodParameter.getContainingClass()).as(methodParameter.getDeclaringClass());
1342                return forType(targetType, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).
1343                                getNested(nestingLevel, methodParameter.typeIndexesPerLevel);
1344        }
1345
1346        /**
1347         * Return a {@link ResolvableType} as a array of the specified {@code componentType}.
1348         * @param componentType the component type
1349         * @return a {@link ResolvableType} as an array of the specified component type
1350         */
1351        public static ResolvableType forArrayComponent(ResolvableType componentType) {
1352                Assert.notNull(componentType, "Component type must not be null");
1353                Class<?> arrayClass = Array.newInstance(componentType.resolve(), 0).getClass();
1354                return new ResolvableType(arrayClass, null, null, componentType);
1355        }
1356
1357        /**
1358         * Return a {@link ResolvableType} for the specified {@link Type}.
1359         * <p>Note: The resulting {@link ResolvableType} instance may not be {@link Serializable}.
1360         * @param type the source type (potentially {@code null})
1361         * @return a {@link ResolvableType} for the specified {@link Type}
1362         * @see #forType(Type, ResolvableType)
1363         */
1364        public static ResolvableType forType(@Nullable Type type) {
1365                return forType(type, null, null);
1366        }
1367
1368        /**
1369         * Return a {@link ResolvableType} for the specified {@link Type} backed by the given
1370         * owner type.
1371         * <p>Note: The resulting {@link ResolvableType} instance may not be {@link Serializable}.
1372         * @param type the source type or {@code null}
1373         * @param owner the owner type used to resolve variables
1374         * @return a {@link ResolvableType} for the specified {@link Type} and owner
1375         * @see #forType(Type)
1376         */
1377        public static ResolvableType forType(@Nullable Type type, @Nullable ResolvableType owner) {
1378                VariableResolver variableResolver = null;
1379                if (owner != null) {
1380                        variableResolver = owner.asVariableResolver();
1381                }
1382                return forType(type, variableResolver);
1383        }
1384
1385
1386        /**
1387         * Return a {@link ResolvableType} for the specified {@link ParameterizedTypeReference}.
1388         * <p>Note: The resulting {@link ResolvableType} instance may not be {@link Serializable}.
1389         * @param typeReference the reference to obtain the source type from
1390         * @return a {@link ResolvableType} for the specified {@link ParameterizedTypeReference}
1391         * @since 4.3.12
1392         * @see #forType(Type)
1393         */
1394        public static ResolvableType forType(ParameterizedTypeReference<?> typeReference) {
1395                return forType(typeReference.getType(), null, null);
1396        }
1397
1398        /**
1399         * Return a {@link ResolvableType} for the specified {@link Type} backed by a given
1400         * {@link VariableResolver}.
1401         * @param type the source type or {@code null}
1402         * @param variableResolver the variable resolver or {@code null}
1403         * @return a {@link ResolvableType} for the specified {@link Type} and {@link VariableResolver}
1404         */
1405        static ResolvableType forType(@Nullable Type type, @Nullable VariableResolver variableResolver) {
1406                return forType(type, null, variableResolver);
1407        }
1408
1409        /**
1410         * Return a {@link ResolvableType} for the specified {@link Type} backed by a given
1411         * {@link VariableResolver}.
1412         * @param type the source type or {@code null}
1413         * @param typeProvider the type provider or {@code null}
1414         * @param variableResolver the variable resolver or {@code null}
1415         * @return a {@link ResolvableType} for the specified {@link Type} and {@link VariableResolver}
1416         */
1417        static ResolvableType forType(
1418                        @Nullable Type type, @Nullable TypeProvider typeProvider, @Nullable VariableResolver variableResolver) {
1419
1420                if (type == null && typeProvider != null) {
1421                        type = SerializableTypeWrapper.forTypeProvider(typeProvider);
1422                }
1423                if (type == null) {
1424                        return NONE;
1425                }
1426
1427                // For simple Class references, build the wrapper right away -
1428                // no expensive resolution necessary, so not worth caching...
1429                if (type instanceof Class) {
1430                        return new ResolvableType(type, typeProvider, variableResolver, (ResolvableType) null);
1431                }
1432
1433                // Purge empty entries on access since we don't have a clean-up thread or the like.
1434                cache.purgeUnreferencedEntries();
1435
1436                // Check the cache - we may have a ResolvableType which has been resolved before...
1437                ResolvableType resultType = new ResolvableType(type, typeProvider, variableResolver);
1438                ResolvableType cachedType = cache.get(resultType);
1439                if (cachedType == null) {
1440                        cachedType = new ResolvableType(type, typeProvider, variableResolver, resultType.hash);
1441                        cache.put(cachedType, cachedType);
1442                }
1443                resultType.resolved = cachedType.resolved;
1444                return resultType;
1445        }
1446
1447        /**
1448         * Clear the internal {@code ResolvableType}/{@code SerializableTypeWrapper} cache.
1449         * @since 4.2
1450         */
1451        public static void clearCache() {
1452                cache.clear();
1453                SerializableTypeWrapper.cache.clear();
1454        }
1455
1456
1457        /**
1458         * Strategy interface used to resolve {@link TypeVariable TypeVariables}.
1459         */
1460        interface VariableResolver extends Serializable {
1461
1462                /**
1463                 * Return the source of the resolver (used for hashCode and equals).
1464                 */
1465                Object getSource();
1466
1467                /**
1468                 * Resolve the specified variable.
1469                 * @param variable the variable to resolve
1470                 * @return the resolved variable, or {@code null} if not found
1471                 */
1472                @Nullable
1473                ResolvableType resolveVariable(TypeVariable<?> variable);
1474        }
1475
1476
1477        @SuppressWarnings("serial")
1478        private static class DefaultVariableResolver implements VariableResolver {
1479
1480                private final ResolvableType source;
1481
1482                DefaultVariableResolver(ResolvableType resolvableType) {
1483                        this.source = resolvableType;
1484                }
1485
1486                @Override
1487                @Nullable
1488                public ResolvableType resolveVariable(TypeVariable<?> variable) {
1489                        return this.source.resolveVariable(variable);
1490                }
1491
1492                @Override
1493                public Object getSource() {
1494                        return this.source;
1495                }
1496        }
1497
1498
1499        @SuppressWarnings("serial")
1500        private static class TypeVariablesVariableResolver implements VariableResolver {
1501
1502                private final TypeVariable<?>[] variables;
1503
1504                private final ResolvableType[] generics;
1505
1506                public TypeVariablesVariableResolver(TypeVariable<?>[] variables, ResolvableType[] generics) {
1507                        this.variables = variables;
1508                        this.generics = generics;
1509                }
1510
1511                @Override
1512                @Nullable
1513                public ResolvableType resolveVariable(TypeVariable<?> variable) {
1514                        TypeVariable<?> variableToCompare = SerializableTypeWrapper.unwrap(variable);
1515                        for (int i = 0; i < this.variables.length; i++) {
1516                                TypeVariable<?> resolvedVariable = SerializableTypeWrapper.unwrap(this.variables[i]);
1517                                if (ObjectUtils.nullSafeEquals(resolvedVariable, variableToCompare)) {
1518                                        return this.generics[i];
1519                                }
1520                        }
1521                        return null;
1522                }
1523
1524                @Override
1525                public Object getSource() {
1526                        return this.generics;
1527                }
1528        }
1529
1530
1531        private static final class SyntheticParameterizedType implements ParameterizedType, Serializable {
1532
1533                private final Type rawType;
1534
1535                private final Type[] typeArguments;
1536
1537                public SyntheticParameterizedType(Type rawType, Type[] typeArguments) {
1538                        this.rawType = rawType;
1539                        this.typeArguments = typeArguments;
1540                }
1541
1542                @Override
1543                public String getTypeName() {
1544                        String typeName = this.rawType.getTypeName();
1545                        if (this.typeArguments.length > 0) {
1546                                StringJoiner stringJoiner = new StringJoiner(", ", "<", ">");
1547                                for (Type argument : this.typeArguments) {
1548                                        stringJoiner.add(argument.getTypeName());
1549                                }
1550                                return typeName + stringJoiner;
1551                        }
1552                        return typeName;
1553                }
1554
1555                @Override
1556                @Nullable
1557                public Type getOwnerType() {
1558                        return null;
1559                }
1560
1561                @Override
1562                public Type getRawType() {
1563                        return this.rawType;
1564                }
1565
1566                @Override
1567                public Type[] getActualTypeArguments() {
1568                        return this.typeArguments;
1569                }
1570
1571                @Override
1572                public boolean equals(@Nullable Object other) {
1573                        if (this == other) {
1574                                return true;
1575                        }
1576                        if (!(other instanceof ParameterizedType)) {
1577                                return false;
1578                        }
1579                        ParameterizedType otherType = (ParameterizedType) other;
1580                        return (otherType.getOwnerType() == null && this.rawType.equals(otherType.getRawType()) &&
1581                                        Arrays.equals(this.typeArguments, otherType.getActualTypeArguments()));
1582                }
1583
1584                @Override
1585                public int hashCode() {
1586                        return (this.rawType.hashCode() * 31 + Arrays.hashCode(this.typeArguments));
1587                }
1588
1589                @Override
1590                public String toString() {
1591                        return getTypeName();
1592                }
1593        }
1594
1595
1596        /**
1597         * Internal helper to handle bounds from {@link WildcardType WildcardTypes}.
1598         */
1599        private static class WildcardBounds {
1600
1601                private final Kind kind;
1602
1603                private final ResolvableType[] bounds;
1604
1605                /**
1606                 * Internal constructor to create a new {@link WildcardBounds} instance.
1607                 * @param kind the kind of bounds
1608                 * @param bounds the bounds
1609                 * @see #get(ResolvableType)
1610                 */
1611                public WildcardBounds(Kind kind, ResolvableType[] bounds) {
1612                        this.kind = kind;
1613                        this.bounds = bounds;
1614                }
1615
1616                /**
1617                 * Return {@code true} if this bounds is the same kind as the specified bounds.
1618                 */
1619                public boolean isSameKind(WildcardBounds bounds) {
1620                        return this.kind == bounds.kind;
1621                }
1622
1623                /**
1624                 * Return {@code true} if this bounds is assignable to all the specified types.
1625                 * @param types the types to test against
1626                 * @return {@code true} if this bounds is assignable to all types
1627                 */
1628                public boolean isAssignableFrom(ResolvableType... types) {
1629                        for (ResolvableType bound : this.bounds) {
1630                                for (ResolvableType type : types) {
1631                                        if (!isAssignable(bound, type)) {
1632                                                return false;
1633                                        }
1634                                }
1635                        }
1636                        return true;
1637                }
1638
1639                private boolean isAssignable(ResolvableType source, ResolvableType from) {
1640                        return (this.kind == Kind.UPPER ? source.isAssignableFrom(from) : from.isAssignableFrom(source));
1641                }
1642
1643                /**
1644                 * Return the underlying bounds.
1645                 */
1646                public ResolvableType[] getBounds() {
1647                        return this.bounds;
1648                }
1649
1650                /**
1651                 * Get a {@link WildcardBounds} instance for the specified type, returning
1652                 * {@code null} if the specified type cannot be resolved to a {@link WildcardType}.
1653                 * @param type the source type
1654                 * @return a {@link WildcardBounds} instance or {@code null}
1655                 */
1656                @Nullable
1657                public static WildcardBounds get(ResolvableType type) {
1658                        ResolvableType resolveToWildcard = type;
1659                        while (!(resolveToWildcard.getType() instanceof WildcardType)) {
1660                                if (resolveToWildcard == NONE) {
1661                                        return null;
1662                                }
1663                                resolveToWildcard = resolveToWildcard.resolveType();
1664                        }
1665                        WildcardType wildcardType = (WildcardType) resolveToWildcard.type;
1666                        Kind boundsType = (wildcardType.getLowerBounds().length > 0 ? Kind.LOWER : Kind.UPPER);
1667                        Type[] bounds = (boundsType == Kind.UPPER ? wildcardType.getUpperBounds() : wildcardType.getLowerBounds());
1668                        ResolvableType[] resolvableBounds = new ResolvableType[bounds.length];
1669                        for (int i = 0; i < bounds.length; i++) {
1670                                resolvableBounds[i] = ResolvableType.forType(bounds[i], type.variableResolver);
1671                        }
1672                        return new WildcardBounds(boundsType, resolvableBounds);
1673                }
1674
1675                /**
1676                 * The various kinds of bounds.
1677                 */
1678                enum Kind {UPPER, LOWER}
1679        }
1680
1681
1682        /**
1683         * Internal {@link Type} used to represent an empty value.
1684         */
1685        @SuppressWarnings("serial")
1686        static class EmptyType implements Type, Serializable {
1687
1688                static final Type INSTANCE = new EmptyType();
1689
1690                Object readResolve() {
1691                        return INSTANCE;
1692                }
1693        }
1694
1695}