Change in conflict tracker!
[jpf-core.git] / examples / TypeVariableImpl.java
1 /*
2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25
26 package sun.reflect.generics.reflectiveObjects;
27
28 import java.lang.annotation.*;
29 import java.lang.reflect.AnnotatedType;
30 import java.lang.reflect.Array;
31 import java.lang.reflect.Constructor;
32 import java.lang.reflect.GenericDeclaration;
33 import java.lang.reflect.Member;
34 import java.lang.reflect.Method;
35 import java.lang.reflect.Type;
36 import java.lang.reflect.TypeVariable;
37 import java.util.LinkedHashMap;
38 import java.util.Map;
39 import java.util.Objects;
40 import sun.reflect.annotation.AnnotationSupport;
41 import sun.reflect.annotation.TypeAnnotationParser;
42 import sun.reflect.annotation.AnnotationType;
43 import sun.reflect.generics.factory.GenericsFactory;
44 import sun.reflect.generics.tree.FieldTypeSignature;
45 import sun.reflect.generics.visitor.Reifier;
46 import sun.reflect.misc.ReflectUtil;
47
48 /**
49  * Implementation of <tt>java.lang.reflect.TypeVariable interface
50  * for core reflection.
51  */
52 public class TypeVariableImpl<D extends GenericDeclaration>
53     extends LazyReflectiveObjectGenerator implements TypeVariable<D> {
54     D genericDeclaration;
55     private String name;
56     // upper bounds - evaluated lazily
57     private Type[] bounds;
58
59     // The ASTs for the bounds. We are required to evaluate the bounds
60     // lazily, so we store these at least until we are first asked
61     // for the bounds. This also neatly solves the
62     // problem with F-bounds - you can't reify them before the formal
63     // is defined.
64     private FieldTypeSignature[] boundASTs;
65
66     // constructor is private to enforce access through static factory
67     private TypeVariableImpl(D decl, String n, FieldTypeSignature[] bs,
68                              GenericsFactory f) {
69         super(f);
70         genericDeclaration = decl;
71         name = n;
72         boundASTs = bs;
73     }
74
75     // Accessors
76
77     // accessor for ASTs for bounds. Must not be called after
78     // bounds have been evaluated, because we might throw the ASTs
79     // away (but that is not thread-safe, is it?)
80     private FieldTypeSignature[] getBoundASTs() {
81         // check that bounds were not evaluated yet
82         assert(bounds == null);
83         return boundASTs;
84     }
85
86     /**
87      * Factory method.
88      * @param decl - the reflective object that declared the type variable
89      * that this method should create
90      * @param name - the name of the type variable to be returned
91      * @param bs - an array of ASTs representing the bounds for the type
92      * variable to be created
93      * @param f - a factory that can be used to manufacture reflective
94      * objects that represent the bounds of this type variable
95      * @return A type variable with name, bounds, declaration and factory
96      * specified
97      */
98     public static <T extends GenericDeclaration>
99                              TypeVariableImpl<T> make(T decl, String name,
100                                                       FieldTypeSignature[] bs,
101                                                       GenericsFactory f) {
102
103         if (!((decl instanceof Class) ||
104                 (decl instanceof Method) ||
105                 (decl instanceof Constructor))) {
106             throw new AssertionError("Unexpected kind of GenericDeclaration" +
107                     decl.getClass().toString());
108         }
109         return new TypeVariableImpl<T>(decl, name, bs, f);
110     }
111
112
113     /**
114      * Returns an array of <tt>Type objects representing the
115      * upper bound(s) of this type variable.  Note that if no upper bound is
116      * explicitly declared, the upper bound is <tt>Object.
117      *
118      * <p>For each upper bound B:
119      * <ul>
120      *  <li>if B is a parameterized type or a type variable, it is created,
121      *  (see {@link #ParameterizedType} for the details of the creation
122      *  process for parameterized types).
123      *  <li>Otherwise, B is resolved.
124      * </ul>
125      *
126      * @throws <tt>TypeNotPresentException  if any of the
127      *     bounds refers to a non-existent type declaration
128      * @throws <tt>MalformedParameterizedTypeException if any of the
129      *     bounds refer to a parameterized type that cannot be instantiated
130      *     for any reason
131      * @return an array of Types representing the upper bound(s) of this
132      *     type variable
133     */
134     public Type[] getBounds() {
135         // lazily initialize bounds if necessary
136         if (bounds == null) {
137             FieldTypeSignature[] fts = getBoundASTs(); // get AST
138             // allocate result array; note that
139             // keeping ts and bounds separate helps with threads
140             Type[] ts = new Type[fts.length];
141             // iterate over bound trees, reifying each in turn
142             for ( int j = 0; j  < fts.length; j++) {
143                 Reifier r = getReifier();
144                 fts[j].accept(r);
145                 ts[j] = r.getResult();
146             }
147             // cache result
148             bounds = ts;
149             // could throw away bound ASTs here; thread safety?
150         }
151         return bounds.clone(); // return cached bounds
152     }
153
154     /**
155      * Returns the <tt>GenericDeclaration  object representing the
156      * generic declaration that declared this type variable.
157      *
158      * @return the generic declaration that declared this type variable.
159      *
160      * @since 1.5
161      */
162     public D getGenericDeclaration(){
163         if (genericDeclaration instanceof Class)
164             ReflectUtil.checkPackageAccess((Class)genericDeclaration);
165         else if ((genericDeclaration instanceof Method) ||
166                 (genericDeclaration instanceof Constructor))
167             ReflectUtil.conservativeCheckMemberAccess((Member)genericDeclaration);
168         else
169             throw new AssertionError("Unexpected kind of GenericDeclaration");
170         return genericDeclaration;
171     }
172
173
174     /**
175      * Returns the name of this type variable, as it occurs in the source code.
176      *
177      * @return the name of this type variable, as it appears in the source code
178      */
179     public String getName()   { return name; }
180
181     public String toString() {return getName();}
182
183     @Override
184     public boolean equals(Object o) {
185         if (o instanceof TypeVariable &&
186                 o.getClass() == TypeVariableImpl.class) {
187             TypeVariable<?> that = (TypeVariable) o;
188
189             GenericDeclaration thatDecl = that.getGenericDeclaration();
190             String thatName = that.getName();
191
192             return Objects.equals(genericDeclaration, thatDecl) &&
193                 Objects.equals(name, thatName);
194
195         } else
196             return false;
197     }
198
199     @Override
200     public int hashCode() {
201         return genericDeclaration.hashCode() ^ name.hashCode();
202     }
203
204     // Implementations of AnnotatedElement methods.
205     @SuppressWarnings("unchecked")
206     public <T extends Annotation> T getAnnotation(Class annotationClass) {
207         Objects.requireNonNull(annotationClass);
208         // T is an Annotation type, the return value of get will be an annotation
209         return (T)mapAnnotations(getAnnotations()).get(annotationClass);
210     }
211
212     public <T extends Annotation> T getDeclaredAnnotation(Class annotationClass) {
213         Objects.requireNonNull(annotationClass);
214         return getAnnotation(annotationClass);
215     }
216
217     @Override
218     public <T extends Annotation> T[] getAnnotationsByType(Class annotationClass) {
219         Objects.requireNonNull(annotationClass);
220         return AnnotationSupport.getDirectlyAndIndirectlyPresent(mapAnnotations(getAnnotations()), annotationClass);
221     }
222
223     @Override
224     public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class annotationClass) {
225         Objects.requireNonNull(annotationClass);
226         return getAnnotationsByType(annotationClass);
227     }
228
229     public Annotation[] getAnnotations() {
230         int myIndex = typeVarIndex();
231         if (myIndex < 0)
232             throw new AssertionError("Index must be non-negative.");
233         return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex);
234     }
235
236     public Annotation[] getDeclaredAnnotations() {
237         return getAnnotations();
238     }
239
240     public AnnotatedType[] getAnnotatedBounds() {
241         return TypeAnnotationParser.parseAnnotatedBounds(getBounds(),
242                                                          getGenericDeclaration(),
243                                                          typeVarIndex());
244     }
245
246     private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
247
248     // Helpers for annotation methods
249     private int typeVarIndex() {
250         TypeVariable<?>[] tVars = getGenericDeclaration().getTypeParameters();
251         int i = -1;
252         for (TypeVariable<?> v : tVars) {
253             i++;
254             if (equals(v))
255                 return i;
256         }
257         return -1;
258     }
259
260     private static Map<Class mapAnnotations(Annotation[] annos) {
261         Map<Class result =
262             new LinkedHashMap<>();
263         for (Annotation a : annos) {
264             Class<? extends Annotation> klass = a.annotationType();
265             AnnotationType type = AnnotationType.getInstance(klass);
266             if (type.retention() == RetentionPolicy.RUNTIME)
267                 if (result.put(klass, a) != null)
268                     throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
269         }
270         return result;
271     }
272     
273     public static void main(String[] args) {
274     
275         TypeVariable typeVar = new TypeVariableImpl(null, null, null, null);
276
277         }
278 }