1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package libcore.reflect; 18 19 import java.lang.reflect.AccessibleObject; 20 import java.lang.reflect.Constructor; 21 import java.lang.reflect.GenericDeclaration; 22 import java.lang.reflect.Method; 23 import java.lang.reflect.Type; 24 import java.lang.reflect.TypeVariable; 25 26 27 public final class TypeVariableImpl<D extends GenericDeclaration> implements TypeVariable<D> { 28 private TypeVariableImpl<D> formalVar; 29 private final GenericDeclaration declOfVarUser; 30 private final String name; 31 private D genericDeclaration; 32 private ListOfTypes bounds; 33 34 @Override equals(Object o)35 public boolean equals(Object o) { 36 if(!(o instanceof TypeVariable)) { 37 return false; 38 } 39 TypeVariable<?> that = (TypeVariable<?>) o; 40 return getName().equals(that.getName()) && 41 getGenericDeclaration().equals(that.getGenericDeclaration()); 42 } 43 44 45 @Override hashCode()46 public int hashCode() { 47 return 31 * getName().hashCode() + getGenericDeclaration().hashCode(); 48 } 49 50 /** 51 * @param genericDecl declaration where a type variable is declared 52 * @param name type variable name 53 * @param bounds class and interface bounds 54 */ TypeVariableImpl(D genericDecl, String name, ListOfTypes bounds)55 TypeVariableImpl(D genericDecl, String name, ListOfTypes bounds) { 56 this.genericDeclaration = genericDecl; 57 this.name = name; 58 this.bounds = bounds; 59 this.formalVar = this; 60 this.declOfVarUser = null; 61 } 62 63 /** 64 * @param genericDecl declaration where a type variable is used 65 * @param name type variable name 66 */ TypeVariableImpl(D genericDecl, String name)67 TypeVariableImpl(D genericDecl, String name) { 68 this.name = name; 69 this.declOfVarUser = genericDecl; 70 } 71 findFormalVar(GenericDeclaration layer, String name)72 static TypeVariable findFormalVar(GenericDeclaration layer, String name) { 73 TypeVariable[] formalVars = layer.getTypeParameters(); 74 for (TypeVariable var : formalVars) { 75 if (name.equals(var.getName())) { 76 return var; 77 } 78 } 79 // resolve() looks up the next level only, if null is returned 80 return null; 81 } 82 nextLayer(GenericDeclaration decl)83 private static GenericDeclaration nextLayer(GenericDeclaration decl) { 84 if (decl instanceof Class) { 85 // FIXME: Is the following hierarchy correct?: 86 Class cl = (Class)decl; 87 Method m = cl.getEnclosingMethod(); 88 decl = (GenericDeclaration) m != null ? m : cl.getEnclosingConstructor(); 89 if (decl != null) { 90 return decl; 91 } 92 return cl.getEnclosingClass(); 93 } else if (decl instanceof Method) { 94 return ((Method)decl).getDeclaringClass(); 95 } else if (decl instanceof Constructor) { 96 return ((Constructor)decl).getDeclaringClass(); 97 } else { 98 throw new AssertionError(); 99 } 100 } 101 resolve()102 void resolve() { 103 if (formalVar != null) { 104 return; 105 } 106 GenericDeclaration curLayer = declOfVarUser; 107 TypeVariable var; 108 while ((var = findFormalVar(curLayer, name)) == null) { 109 curLayer = nextLayer(curLayer); 110 if (curLayer == null) { 111 throw new AssertionError("illegal type variable reference"); 112 } 113 } 114 formalVar = (TypeVariableImpl<D>) var; 115 this.genericDeclaration = formalVar.genericDeclaration; 116 this.bounds = formalVar.bounds; 117 } 118 getBounds()119 public Type[] getBounds() { 120 resolve(); 121 return bounds.getResolvedTypes().clone(); 122 } 123 getGenericDeclaration()124 public D getGenericDeclaration() { 125 resolve(); 126 return genericDeclaration; 127 } 128 getName()129 public String getName() { 130 return name; 131 } 132 133 @Override toString()134 public String toString() { 135 return name; 136 } 137 } 138