Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2002-2008 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.

Only usable on Java 5. Use an appropriate JdkVersion check before calling this class, if a fallback for JDK 1.4 is desirable.

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 typeVariableCache = Collections.synchronizedMap(new WeakHashMap());


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 typeVariableMap = 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 typeVariableMap = getTypeVariableMap(clazz);
		Type rawType = getRawType(genericTypetypeVariableMap);
		return (rawType instanceof Class ? (ClassrawType : method.getReturnType());
	}


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 typeVariableMap) {
		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 typeVariableMap) {
		Type resolvedType = genericType;
		if (genericType instanceof TypeVariable) {
			TypeVariable tv = (TypeVariablegenericType;
			resolvedType = (TypetypeVariableMap.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.
	static Map getTypeVariableMap(Class clazz) {
		Map typeVariableMap = (Map) (ref != null ? ref.get() : null);
		if (typeVariableMap == null) {
			typeVariableMap = new HashMap();
			// 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(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 typeVariableMap) {
		for (int i = 0; i < genericInterfaces.lengthi++) {
			Type genericInterface = genericInterfaces[i];
			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 typeVariableMap) {
		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 = (TypetypeVariableMap.get(typeVariableArgument);
					if (resolvedType == null) {
						resolvedType = extractBoundForTypeVariable(typeVariableArgument);
					}
					typeVariableMap.put(variableresolvedType);
				}
			}
		}
	}
New to GrepCode? Check out our FAQ X