001// Licensed under the Apache License, Version 2.0 (the "License"); 002// you may not use this file except in compliance with the License. 003// You may obtain a copy of the License at 004// 005// http://www.apache.org/licenses/LICENSE-2.0 006// 007// Unless required by applicable law or agreed to in writing, software 008// distributed under the License is distributed on an "AS IS" BASIS, 009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010// See the License for the specific language governing permissions and 011// limitations under the License. 012 013package org.apache.tapestry5.commons.internal.util; 014 015import java.lang.reflect.Field; 016import java.lang.reflect.Method; 017import java.lang.reflect.Type; 018 019import org.apache.tapestry5.commons.services.GenericsResolver; 020 021/** 022 * Static methods related to the use of JDK 1.5 generics. From Tapestry 5.5.0, 023 * this class just delegates to {@link GenericsResolver}. 024 */ 025public class GenericsUtils 026{ 027 final private static GenericsResolver GENERICS_RESOLVER = GenericsResolver.Provider.getInstance(); 028 029 /** 030 * Analyzes the method in the context of containingClass and returns the Class that is represented by 031 * the method's generic return type. Any parameter information in the generic return type is lost. If you want 032 * to preserve the type parameters of the return type consider using 033 * {@link #extractActualType(java.lang.reflect.Type, java.lang.reflect.Method)}. 034 * 035 * @param containingClass class which either contains or inherited the method 036 * @param method method from which to extract the return type 037 * @return the class represented by the methods generic return type, resolved based on the context . 038 * @see #extractActualType(java.lang.reflect.Type, java.lang.reflect.Method) 039 * @see #resolve(java.lang.reflect.Type,java.lang.reflect.Type) 040 * @see #asClass(java.lang.reflect.Type) 041 */ 042 public static Class<?> extractGenericReturnType(Class<?> containingClass, Method method) 043 { 044 return GENERICS_RESOLVER.extractGenericReturnType(containingClass, method); 045 } 046 047 /** 048 * Analyzes the field in the context of containingClass and returns the Class that is represented by 049 * the field's generic type. Any parameter information in the generic type is lost, if you want 050 * to preserve the type parameters of the return type consider using 051 * #getTypeVariableIndex(java.lang.reflect.TypeVariable). 052 * 053 * @param containingClass class which either contains or inherited the field 054 * @param field field from which to extract the type 055 * @return the class represented by the field's generic type, resolved based on the containingClass. 056 * @see #extractActualType(java.lang.reflect.Type, java.lang.reflect.Field) 057 * @see #resolve(java.lang.reflect.Type,java.lang.reflect.Type) 058 * @see #asClass(java.lang.reflect.Type) 059 */ 060 public static Class extractGenericFieldType(Class containingClass, Field field) 061 { 062 return GENERICS_RESOLVER.extractGenericFieldType(containingClass, field); 063 } 064 065 /** 066 * Analyzes the method in the context of containingClass and returns the Class that is represented by 067 * the method's generic return type. Any parameter information in the generic return type is lost. 068 * 069 * @param containingType Type which is/represents the class that either contains or inherited the method 070 * @param method method from which to extract the generic return type 071 * @return the generic type represented by the methods generic return type, resolved based on the containingType. 072 * @see #resolve(java.lang.reflect.Type,java.lang.reflect.Type) 073 */ 074 public static Type extractActualType(Type containingType, Method method) 075 { 076 return GENERICS_RESOLVER.extractActualType(containingType, method); 077 } 078 079 /** 080 * Analyzes the method in the context of containingClass and returns the Class that is represented by 081 * the method's generic return type. Any parameter information in the generic return type is lost. 082 * 083 * @param containingType Type which is/represents the class that either contains or inherited the field 084 * @param field field from which to extract the generic return type 085 * @return the generic type represented by the methods generic return type, resolved based on the containingType. 086 * @see #resolve(java.lang.reflect.Type,java.lang.reflect.Type) 087 */ 088 public static Type extractActualType(Type containingType, Field field) 089 { 090 return GENERICS_RESOLVER.extractActualType(containingType, field); 091 } 092 093 /** 094 * Resolves the type parameter based on the context of the containingType. 095 * 096 * {@link java.lang.reflect.TypeVariable} will be unwrapped to the type argument resolved form the class 097 * hierarchy. This may be something other than a simple Class if the type argument is a ParameterizedType for 098 * instance (e.g. {@code List<E>; List<Map<Long, String>>}, E would be returned as a ParameterizedType with the raw 099 * type Map and type arguments Long and String. 100 * 101 * 102 * @param type 103 * the generic type (ParameterizedType, GenericArrayType, WildcardType, TypeVariable) to be resolved 104 * @param containingType 105 * the type which his 106 * @return 107 * the type resolved to the best of our ability. 108 * @since 5.2.? 109 */ 110 public static Type resolve(final Type type, final Type containingType) 111 { 112 return GENERICS_RESOLVER.resolve(type, containingType); 113 } 114 115 /** 116 * Get the class represented by the reflected type. 117 * This method is lossy; You cannot recover the type information from the class that is returned. 118 * 119 * {@code TypeVariable} the first bound is returned. If your type variable extends multiple interfaces that information 120 * is lost. 121 * 122 * {@code WildcardType} the first lower bound is returned. If the wildcard is defined with upper bounds 123 * then {@code Object} is returned. 124 * 125 * @param actualType 126 * a Class, ParameterizedType, GenericArrayType 127 * @return the un-parameterized class associated with the type. 128 */ 129 public static Class asClass(Type actualType) 130 { 131 return GENERICS_RESOLVER.asClass(actualType); 132 } 133 134}