Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2002-2009 the original author or authors.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package org.springframework.core;
 
 import java.util.Map;
 
Helper class for resolving generic types against type variables.

Mainly intended for usage within the framework, resolving method parameter types even when they are declared generically.

Author(s):
Juergen Hoeller
Rob Harrop
Since:
2.5.2
See also:
GenericCollectionTypeResolver
JdkVersion
 
 public abstract class GenericTypeResolver {

Cache from Class to TypeVariable Map
 
 	private static final Map<ClassReference<Map<TypeVariableType>>> typeVariableCache =
Determine the target type for the given parameter specification.

Parameters:
methodParam the method parameter specification
Returns:
the corresponding generic parameter type
 
 	public static Type getTargetType(MethodParameter methodParam) {
 		Assert.notNull(methodParam"MethodParameter must not be null");
 		if (methodParam.getConstructor() != null) {
 			return methodParam.getConstructor().getGenericParameterTypes()[methodParam.getParameterIndex()];
 		}
 		else {
 			if (methodParam.getParameterIndex() >= 0) {
 				return methodParam.getMethod().getGenericParameterTypes()[methodParam.getParameterIndex()];
 			}
 			else {
 				return methodParam.getMethod().getGenericReturnType();
 			}
 		}
 	}

Determine the target type for the given generic parameter type.

Parameters:
methodParam the method parameter specification
clazz the class to resolve type variables against
Returns:
the corresponding generic parameter or return type
 
 	public static Class<?> resolveParameterType(MethodParameter methodParamClass clazz) {
 		Type genericType = getTargetType(methodParam);
 		Assert.notNull(clazz"Class must not be null");
 		Map<TypeVariableTypetypeVariableMap = getTypeVariableMap(clazz);
 		Type rawType = getRawType(genericTypetypeVariableMap);
 		Class result = (rawType instanceof Class ? (ClassrawType : methodParam.getParameterType());
 		methodParam.setParameterType(result);
 		methodParam.typeVariableMap = typeVariableMap;
 		return result;
 	}

Determine the target type for the generic return type of the given method.

Parameters:
method the method to introspect
clazz the class to resolve type variables against
Returns:
the corresponding generic parameter or return type
 
 	public static Class<?> resolveReturnType(Method methodClass clazz) {
 		Assert.notNull(method"Method must not be null");
 		Type genericType = method.getGenericReturnType();
 		Assert.notNull(clazz"Class must not be null");
 		Map<TypeVariableTypetypeVariableMap = getTypeVariableMap(clazz);
		Type rawType = getRawType(genericTypetypeVariableMap);
		return (rawType instanceof Class ? (ClassrawType : method.getReturnType());
	}

Resolve the single type argument of the given generic interface against the given target class which is assumed to implement the generic interface and possibly declare a concrete type for its type variable.

Parameters:
clazz the target class to check against
genericIfc the generic interface to resolve the type argument from
Returns:
the resolved type of the argument, or null if not resolvable
	public static Class<?> resolveTypeArgument(Class clazzClass genericIfc) {
		Class[] typeArgs = resolveTypeArguments(clazzgenericIfc);
		if (typeArgs == null) {
			return null;
		}
		if (typeArgs.length != 1) {
			throw new IllegalArgumentException("Expected 1 type argument on generic interface [" +
					genericIfc.getName() + "] but found " + typeArgs.length);
		}
		return typeArgs[0];
	}

Resolve the type arguments of the given generic interface against the given target class which is assumed to implement the generic interface and possibly declare concrete types for its type variables.

Parameters:
clazz the target class to check against
genericIfc the generic interface to resolve the type argument from
Returns:
the resolved type of each argument, with the array size matching the number of actual type arguments, or null if not resolvable
	public static Class[] resolveTypeArguments(Class clazzClass genericIfc) {
		return doResolveTypeArguments(clazzclazzgenericIfc);
	}
	private static Class[] doResolveTypeArguments(Class ownerClassClass classToIntrospectClass genericIfc) {
		while (classToIntrospect != null) {
			Type[] ifcs = classToIntrospect.getGenericInterfaces();
			for (Type ifc : ifcs) {
				if (ifc instanceof ParameterizedType) {
					Type rawType = paramIfc.getRawType();
					if (genericIfc.equals(rawType)) {
						Type[] typeArgs = paramIfc.getActualTypeArguments();
						Class[] result = new Class[typeArgs.length];
						for (int i = 0; i < typeArgs.lengthi++) {
							Type arg = typeArgs[i];
							if (arg instanceof TypeVariable) {
								arg = getTypeVariableMap(ownerClass).get((TypeVariablearg);
							}
							result[i] = (arg instanceof Class ? (Classarg : Object.class);
						}
						return result;
					}
					else if (genericIfc.isAssignableFrom((ClassrawType)) {
						return doResolveTypeArguments(ownerClass, (ClassrawTypegenericIfc);
					}
				}
				else if (genericIfc.isAssignableFrom((Classifc)) {
					return doResolveTypeArguments(ownerClass, (ClassifcgenericIfc);
				}
			}
			classToIntrospect = classToIntrospect.getSuperclass();
		}
		return null;
	}


Resolve the specified generic type against the given TypeVariable map.

Parameters:
genericType the generic type to resolve
typeVariableMap the TypeVariable Map to resolved against
Returns:
the type if it resolves to a Class, or Object.class otherwise
	static Class resolveType(Type genericTypeMap<TypeVariableTypetypeVariableMap) {
		Type rawType = getRawType(genericTypetypeVariableMap);
		return (rawType instanceof Class ? (ClassrawType : Object.class);
	}

Determine the raw type for the given generic parameter type.

Parameters:
genericType the generic type to resolve
typeVariableMap the TypeVariable Map to resolved against
Returns:
the resolved raw type
	static Type getRawType(Type genericTypeMap<TypeVariableTypetypeVariableMap) {
		Type resolvedType = genericType;
		if (genericType instanceof TypeVariable) {
			TypeVariable tv = (TypeVariablegenericType;
			resolvedType = typeVariableMap.get(tv);
			if (resolvedType == null) {
				resolvedType = extractBoundForTypeVariable(tv);
			}
		}
		if (resolvedType instanceof ParameterizedType) {
			return ((ParameterizedTyperesolvedType).getRawType();
		}
		else {
			return resolvedType;
		}
	}

Build a mapping of TypeVariable names to concrete java.lang.Class for the specified java.lang.Class. Searches all super types, enclosing types and interfaces.
		Map<TypeVariableTypetypeVariableMap = (ref != null ? ref.get() : null);
		if (typeVariableMap == null) {
			typeVariableMap = new HashMap<TypeVariableType>();
			// interfaces
			// super class
			Type genericType = clazz.getGenericSuperclass();
			Class type = clazz.getSuperclass();
			while (type != null && !Object.class.equals(type)) {
				if (genericType instanceof ParameterizedType) {
					ParameterizedType pt = (ParameterizedTypegenericType;
				}
				genericType = type.getGenericSuperclass();
				type = type.getSuperclass();
			}
			// enclosing class
			type = clazz;
			while (type.isMemberClass()) {
				genericType = type.getGenericSuperclass();
				if (genericType instanceof ParameterizedType) {
					ParameterizedType pt = (ParameterizedTypegenericType;
				}
				type = type.getEnclosingClass();
			}
			.put(clazznew WeakReference<Map<TypeVariableType>>(typeVariableMap));
		}
		return typeVariableMap;
	}

Extracts the bound Type for a given java.lang.reflect.TypeVariable.
		Type[] bounds = typeVariable.getBounds();
		if (bounds.length == 0) {
			return Object.class;
		}
		Type bound = bounds[0];
		if (bound instanceof TypeVariable) {
		}
		return bound;
	}
	private static void extractTypeVariablesFromGenericInterfaces(Type[] genericInterfacesMap<TypeVariableTypetypeVariableMap) {
		for (Type genericInterface : genericInterfaces) {
			if (genericInterface instanceof ParameterizedType) {
				ParameterizedType pt = (ParameterizedTypegenericInterface;
				if (pt.getRawType() instanceof Class) {
							((Classpt.getRawType()).getGenericInterfaces(), typeVariableMap);
				}
			}
			else if (genericInterface instanceof Class) {
						((ClassgenericInterface).getGenericInterfaces(), typeVariableMap);
			}
		}
	}

Read the TypeVariables from the supplied java.lang.reflect.ParameterizedType and add mappings corresponding to the TypeVariable name -> concrete type to the supplied java.util.Map.

Consider this case:

 public interface Foo {
  ..
 }

 public class FooImpl implements Foo<String, Integer> {
  ..
 }
For 'FooImpl' the following mappings would be added to the java.util.Map: {S=java.lang.String, T=java.lang.Integer}.
	private static void populateTypeMapFromParameterizedType(ParameterizedType typeMap<TypeVariableTypetypeVariableMap) {
		if (type.getRawType() instanceof Class) {
			Type[] actualTypeArguments = type.getActualTypeArguments();
			TypeVariable[] typeVariables = ((Classtype.getRawType()).getTypeParameters();
			for (int i = 0; i < actualTypeArguments.lengthi++) {
				Type actualTypeArgument = actualTypeArguments[i];
				TypeVariable variable = typeVariables[i];
				if (actualTypeArgument instanceof Class) {
					typeVariableMap.put(variableactualTypeArgument);
				}
				else if (actualTypeArgument instanceof GenericArrayType) {
					typeVariableMap.put(variableactualTypeArgument);
				}
				else if (actualTypeArgument instanceof ParameterizedType) {
					typeVariableMap.put(variableactualTypeArgument);
				}
				else if (actualTypeArgument instanceof TypeVariable) {
					// We have a type that is parameterized at instantiation time
					// the nearest match on the bridge method will be the bounded type.
					TypeVariable typeVariableArgument = (TypeVariableactualTypeArgument;
					Type resolvedType = typeVariableMap.get(typeVariableArgument);
					if (resolvedType == null) {
						resolvedType = extractBoundForTypeVariable(typeVariableArgument);
					}
					typeVariableMap.put(variableresolvedType);
				}
			}
		}
	}
New to GrepCode? Check out our FAQ X