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
26package sun.reflect.generics.reflectiveObjects;
27
28import java.lang.annotation.*;
29import java.lang.reflect.AnnotatedType;
30import java.lang.reflect.Array;
31import java.lang.reflect.Constructor;
32import java.lang.reflect.GenericDeclaration;
33import java.lang.reflect.Member;
34import java.lang.reflect.Method;
35import java.lang.reflect.Type;
36import java.lang.reflect.TypeVariable;
37import java.util.LinkedHashMap;
38import java.util.Map;
39import java.util.Objects;
40import sun.reflect.annotation.AnnotationSupport;
41import sun.reflect.annotation.TypeAnnotationParser;
42import sun.reflect.annotation.AnnotationType;
43import sun.reflect.generics.factory.GenericsFactory;
44import sun.reflect.generics.tree.FieldTypeSignature;
45import sun.reflect.generics.visitor.Reifier;
46import sun.reflect.misc.ReflectUtil;
47
48/**
49 * Implementation of {@code java.lang.reflect.TypeVariable} interface
50 * for core reflection.
51 */
52public class TypeVariableImpl<D extends GenericDeclaration>
53    extends LazyReflectiveObjectGenerator implements TypeVariable<D> {
54    private final D genericDeclaration;
55    private final String name;
56
57    /**
58     * The upper bounds.  Lazily converted from FieldTypeSignature[] to Type[].
59     * We are required to evaluate the bounds lazily, so we store them as ASTs
60     * until we are first asked for them.  This also neatly solves the problem
61     * with F-bounds - you can't reify them before the formal is defined.
62     */
63    private volatile Object[] bounds;
64
65    // constructor is private to enforce access through static factory
66    private TypeVariableImpl(D decl, String n, FieldTypeSignature[] bs,
67                             GenericsFactory f) {
68        super(f);
69        genericDeclaration = decl;
70        name = n;
71        bounds = bs;
72    }
73
74    /**
75     * Factory method.
76     * @param decl - the reflective object that declared the type variable
77     * that this method should create
78     * @param name - the name of the type variable to be returned
79     * @param bs - an array of ASTs representing the bounds for the type
80     * variable to be created
81     * @param f - a factory that can be used to manufacture reflective
82     * objects that represent the bounds of this type variable
83     * @return A type variable with name, bounds, declaration and factory
84     * specified
85     */
86    public static <T extends GenericDeclaration>
87                             TypeVariableImpl<T> make(T decl, String name,
88                                                      FieldTypeSignature[] bs,
89                                                      GenericsFactory f) {
90
91        if (!((decl instanceof Class) ||
92                (decl instanceof Method) ||
93                (decl instanceof Constructor))) {
94            throw new AssertionError("Unexpected kind of GenericDeclaration" +
95                    decl.getClass().toString());
96        }
97        return new TypeVariableImpl<T>(decl, name, bs, f);
98    }
99
100
101    /**
102     * Returns an array of {@code Type} objects representing the
103     * upper bound(s) of this type variable.  Note that if no upper bound is
104     * explicitly declared, the upper bound is {@code Object}.
105     *
106     * <p>For each upper bound B:
107     * <ul>
108     *  <li>if B is a parameterized type or a type variable, it is created,
109     *  (see {@link #ParameterizedType} for the details of the creation
110     *  process for parameterized types).
111     *  <li>Otherwise, B is resolved.
112     * </ul>
113     *
114     * @throws {@code TypeNotPresentException} if any of the
115     *     bounds refers to a non-existent type declaration
116     * @throws {@code MalformedParameterizedTypeException} if any of the
117     *     bounds refer to a parameterized type that cannot be instantiated
118     *     for any reason
119     * @return an array of Types representing the upper bound(s) of this
120     *     type variable
121    */
122    public Type[] getBounds() {
123        Object[] value = bounds;
124        if (value instanceof FieldTypeSignature[]) {
125            value = reifyBounds((FieldTypeSignature[])value);
126            bounds = value;
127        }
128        return (Type[])value.clone();
129    }
130
131    /**
132     * Returns the {@code GenericDeclaration} object representing the
133     * generic declaration that declared this type variable.
134     *
135     * @return the generic declaration that declared this type variable.
136     *
137     * @since 1.5
138     */
139    public D getGenericDeclaration() {
140        if (genericDeclaration instanceof Class)
141            ReflectUtil.checkPackageAccess((Class)genericDeclaration);
142        else if ((genericDeclaration instanceof Method) ||
143                (genericDeclaration instanceof Constructor))
144            ReflectUtil.conservativeCheckMemberAccess((Member)genericDeclaration);
145        else
146            throw new AssertionError("Unexpected kind of GenericDeclaration");
147        return genericDeclaration;
148    }
149
150
151    /**
152     * Returns the name of this type variable, as it occurs in the source code.
153     *
154     * @return the name of this type variable, as it appears in the source code
155     */
156    public String getName()   { return name; }
157
158    public String toString() {return getName();}
159
160    @Override
161    public boolean equals(Object o) {
162        if (o instanceof TypeVariable &&
163                o.getClass() == TypeVariableImpl.class) {
164            TypeVariable<?> that = (TypeVariable<?>) o;
165
166            GenericDeclaration thatDecl = that.getGenericDeclaration();
167            String thatName = that.getName();
168
169            return Objects.equals(genericDeclaration, thatDecl) &&
170                Objects.equals(name, thatName);
171
172        } else
173            return false;
174    }
175
176    @Override
177    public int hashCode() {
178        return genericDeclaration.hashCode() ^ name.hashCode();
179    }
180
181    // Implementations of AnnotatedElement methods.
182    @SuppressWarnings("unchecked")
183    public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
184        Objects.requireNonNull(annotationClass);
185        // T is an Annotation type, the return value of get will be an annotation
186        return (T)mapAnnotations(getAnnotations()).get(annotationClass);
187    }
188
189    public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
190        Objects.requireNonNull(annotationClass);
191        return getAnnotation(annotationClass);
192    }
193
194    @Override
195    public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
196        Objects.requireNonNull(annotationClass);
197        return AnnotationSupport.getDirectlyAndIndirectlyPresent(mapAnnotations(getAnnotations()), annotationClass);
198    }
199
200    @Override
201    public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
202        Objects.requireNonNull(annotationClass);
203        return getAnnotationsByType(annotationClass);
204    }
205
206    public Annotation[] getAnnotations() {
207        int myIndex = typeVarIndex();
208        if (myIndex < 0)
209            throw new AssertionError("Index must be non-negative.");
210        return TypeAnnotationParser.parseTypeVariableAnnotations(getGenericDeclaration(), myIndex);
211    }
212
213    public Annotation[] getDeclaredAnnotations() {
214        return getAnnotations();
215    }
216
217    public AnnotatedType[] getAnnotatedBounds() {
218        return TypeAnnotationParser.parseAnnotatedBounds(getBounds(),
219                                                         getGenericDeclaration(),
220                                                         typeVarIndex());
221    }
222
223    private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
224
225    // Helpers for annotation methods
226    private int typeVarIndex() {
227        TypeVariable<?>[] tVars = getGenericDeclaration().getTypeParameters();
228        int i = -1;
229        for (TypeVariable<?> v : tVars) {
230            i++;
231            if (equals(v))
232                return i;
233        }
234        return -1;
235    }
236
237    private static Map<Class<? extends Annotation>, Annotation> mapAnnotations(Annotation[] annos) {
238        Map<Class<? extends Annotation>, Annotation> result =
239            new LinkedHashMap<>();
240        for (Annotation a : annos) {
241            Class<? extends Annotation> klass = a.annotationType();
242            AnnotationType type = AnnotationType.getInstance(klass);
243            if (type.retention() == RetentionPolicy.RUNTIME)
244                if (result.put(klass, a) != null)
245                    throw new AnnotationFormatError("Duplicate annotation for class: "+klass+": " + a);
246        }
247        return result;
248    }
249}
250