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