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 }