001 // Copyright 2006 Waterken Inc. under the terms of the MIT X license 002 // found at http://www.opensource.org/licenses/mit-license.html 003 package org.ref_send.type; 004 005 import java.lang.reflect.ParameterizedType; 006 import java.lang.reflect.Type; 007 import java.lang.reflect.TypeVariable; 008 import java.lang.reflect.WildcardType; 009 010 /** 011 * Type definition manipulation. 012 */ 013 public final class 014 Typedef { 015 private Typedef() {} 016 017 /** 018 * Gets the named type variable. 019 * @param declaration generic declaration 020 * @param name variable name 021 * @return corresponding type variable 022 * @throws NullPointerException no matching variable found 023 */ 024 static public <T> TypeVariable<Class<T>> 025 var(final Class<T> declaration, final String name) { 026 for (final TypeVariable<Class<T>> i : declaration.getTypeParameters()) { 027 if (i.getName().equals(name)) { return i; } 028 } 029 throw new NullPointerException(); 030 } 031 032 /** 033 * Gets the value of a type variable. 034 * @param p type variable 035 * @param a instantiated type 036 * @return type argument, or <code>null</code> if <code>p</code> is not from 037 * <code>a</code> or one of its super types 038 */ 039 static public Type 040 value(final TypeVariable<?> p, final Type a) { 041 Type r; 042 final Class<?> template = raw(a); 043 final Class<?> declaration = (Class<?>)p.getGenericDeclaration(); 044 if (declaration == template) { 045 r = p; 046 } else if (declaration.isAssignableFrom(template)) { 047 r = null; 048 for (final Type i : template.getGenericInterfaces()) { 049 r = value(p, i); 050 if (null != r) { break; } 051 } 052 if (null == r) { 053 r = value(p, template.getGenericSuperclass()); 054 } 055 } else { 056 return null; 057 } 058 if (r instanceof TypeVariable<?>) { 059 if (a instanceof ParameterizedType) { 060 int i = 0; 061 for (final TypeVariable<?> v : declaration.getTypeParameters()){ 062 if (p.equals(v)) { break; } 063 ++i; 064 } 065 r = ((ParameterizedType)a).getActualTypeArguments()[i]; 066 } else { 067 r = Object.class; // Class implements the raw type. 068 } 069 } 070 return r; 071 } 072 073 /** 074 * Determine the corresponding raw type. 075 * @param type generic type 076 * @return corresponding raw type 077 */ 078 static public Class<?> 079 raw(final Type type) { 080 return type instanceof Class<?> 081 ? (Class<?>)type 082 : (type instanceof ParameterizedType 083 ? raw(((ParameterizedType)type).getRawType()) 084 : (type instanceof WildcardType 085 ? raw(((WildcardType)type).getUpperBounds()[0]) 086 : Object.class)); 087 } 088 089 /** 090 * Determine the upper bound on a type parameter. 091 * @param parameter generic parameter type 092 * @param declared generic class type 093 * @return upper bound on the actual type 094 */ 095 static public Type 096 bound(final Type parameter, final Type declared) { 097 final Type argument = parameter instanceof TypeVariable<?> 098 ? value((TypeVariable<?>)parameter, declared) 099 : parameter; 100 return argument instanceof WildcardType 101 ? ((WildcardType)argument).getUpperBounds()[0] 102 : argument; 103 } 104 }