blob: 14dffa16686d09f47579ea4a339ddf077090beba [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.reflect.generics.reflectiveObjects;
27
28
29import java.lang.reflect.Type;
30import java.lang.reflect.WildcardType;
31import sun.reflect.generics.factory.GenericsFactory;
32import sun.reflect.generics.tree.FieldTypeSignature;
33import sun.reflect.generics.visitor.Reifier;
34import java.util.Arrays;
35
36
37/**
38 * Implementation of WildcardType interface for core reflection.
39 */
40public class WildcardTypeImpl extends LazyReflectiveObjectGenerator
41 implements WildcardType {
42 // upper bounds - evaluated lazily
43 private Type[] upperBounds;
44 // lower bounds - evaluated lazily
45 private Type[] lowerBounds;
46 // The ASTs for the bounds. We are required to evaluate the bounds
47 // lazily, so we store these at least until we are first asked
48 // for the bounds. This also neatly solves the
49 // problem with F-bounds - you can't reify them before the formal
50 // is defined.
51 private FieldTypeSignature[] upperBoundASTs;
52 private FieldTypeSignature[] lowerBoundASTs;
53
54 // constructor is private to enforce access through static factory
55 private WildcardTypeImpl(FieldTypeSignature[] ubs,
56 FieldTypeSignature[] lbs,
57 GenericsFactory f) {
58 super(f);
59 upperBoundASTs = ubs;
60 lowerBoundASTs = lbs;
61 }
62
63 /**
64 * Factory method.
65 * @param ubs - an array of ASTs representing the upper bounds for the type
66 * variable to be created
67 * @param lbs - an array of ASTs representing the lower bounds for the type
68 * variable to be created
69 * @param f - a factory that can be used to manufacture reflective
70 * objects that represent the bounds of this wildcard type
71 * @return a wild card type with the requested bounds and factory
72 */
73 public static WildcardTypeImpl make(FieldTypeSignature[] ubs,
74 FieldTypeSignature[] lbs,
75 GenericsFactory f) {
76 return new WildcardTypeImpl(ubs, lbs, f);
77 }
78
79 // Accessors
80
81 // accessor for ASTs for upper bounds. Must not be called after upper
82 // bounds have been evaluated, because we might throw the ASTs
83 // away (but that is not thread-safe, is it?)
84 private FieldTypeSignature[] getUpperBoundASTs() {
85 // check that upper bounds were not evaluated yet
86 assert(upperBounds == null);
87 return upperBoundASTs;
88 }
89 // accessor for ASTs for lower bounds. Must not be called after lower
90 // bounds have been evaluated, because we might throw the ASTs
91 // away (but that is not thread-safe, is it?)
92 private FieldTypeSignature[] getLowerBoundASTs() {
93 // check that lower bounds were not evaluated yet
94 assert(lowerBounds == null);
95 return lowerBoundASTs;
96 }
97
98 /**
99 * Returns an array of <tt>Type</tt> objects representing the upper
100 * bound(s) of this type variable. Note that if no upper bound is
101 * explicitly declared, the upper bound is <tt>Object</tt>.
102 *
103 * <p>For each upper bound B :
104 * <ul>
105 * <li>if B is a parameterized type or a type variable, it is created,
106 * (see {@link #ParameterizedType} for the details of the creation
107 * process for parameterized types).
108 * <li>Otherwise, B is resolved.
109 * </ul>
110 *
111 * @return an array of Types representing the upper bound(s) of this
112 * type variable
113 * @throws <tt>TypeNotPresentException</tt> if any of the
114 * bounds refers to a non-existent type declaration
115 * @throws <tt>MalformedParameterizedTypeException</tt> if any of the
116 * bounds refer to a parameterized type that cannot be instantiated
117 * for any reason
118 */
119 public Type[] getUpperBounds() {
120 // lazily initialize bounds if necessary
121 if (upperBounds == null) {
122 FieldTypeSignature[] fts = getUpperBoundASTs(); // get AST
123
124 // allocate result array; note that
125 // keeping ts and bounds separate helps with threads
126 Type[] ts = new Type[fts.length];
127 // iterate over bound trees, reifying each in turn
128 for ( int j = 0; j < fts.length; j++) {
129 Reifier r = getReifier();
130 fts[j].accept(r);
131 ts[j] = r.getResult();
132 }
133 // cache result
134 upperBounds = ts;
135 // could throw away upper bound ASTs here; thread safety?
136 }
137 return upperBounds.clone(); // return cached bounds
138 }
139
140 /**
141 * Returns an array of <tt>Type</tt> objects representing the
142 * lower bound(s) of this type variable. Note that if no lower bound is
143 * explicitly declared, the lower bound is the type of <tt>null</tt>.
144 * In this case, a zero length array is returned.
145 *
146 * <p>For each lower bound B :
147 * <ul>
148 * <li>if B is a parameterized type or a type variable, it is created,
149 * (see {@link #ParameterizedType} for the details of the creation
150 * process for parameterized types).
151 * <li>Otherwise, B is resolved.
152 * </ul>
153 *
154 * @return an array of Types representing the lower bound(s) of this
155 * type variable
156 * @throws <tt>TypeNotPresentException</tt> if any of the
157 * bounds refers to a non-existent type declaration
158 * @throws <tt>MalformedParameterizedTypeException</tt> if any of the
159 * bounds refer to a parameterized type that cannot be instantiated
160 * for any reason
161 */
162 public Type[] getLowerBounds() {
163 // lazily initialize bounds if necessary
164 if (lowerBounds == null) {
165 FieldTypeSignature[] fts = getLowerBoundASTs(); // get AST
166 // allocate result array; note that
167 // keeping ts and bounds separate helps with threads
168 Type[] ts = new Type[fts.length];
169 // iterate over bound trees, reifying each in turn
170 for ( int j = 0; j < fts.length; j++) {
171 Reifier r = getReifier();
172 fts[j].accept(r);
173 ts[j] = r.getResult();
174 }
175 // cache result
176 lowerBounds = ts;
177 // could throw away lower bound ASTs here; thread safety?
178 }
179 return lowerBounds.clone(); // return cached bounds
180 }
181
182 public String toString() {
183 Type[] lowerBounds = getLowerBounds();
184 Type[] bounds = lowerBounds;
185 StringBuilder sb = new StringBuilder();
186
187 if (lowerBounds.length > 0)
188 sb.append("? super ");
189 else {
190 Type[] upperBounds = getUpperBounds();
191 if (upperBounds.length > 0 && !upperBounds[0].equals(Object.class) ) {
192 bounds = upperBounds;
193 sb.append("? extends ");
194 } else
195 return "?";
196 }
197
198 assert bounds.length > 0;
199
200 boolean first = true;
201 for(Type bound: bounds) {
202 if (!first)
203 sb.append(" & ");
204
205 first = false;
206 if (bound instanceof Class)
207 sb.append(((Class)bound).getName() );
208 else
209 sb.append(bound.toString());
210 }
211 return sb.toString();
212 }
213
214 @Override
215 public boolean equals(Object o) {
216 if (o instanceof WildcardType) {
217 WildcardType that = (WildcardType) o;
218 return
219 Arrays.equals(this.getLowerBounds(),
220 that.getLowerBounds()) &&
221 Arrays.equals(this.getUpperBounds(),
222 that.getUpperBounds());
223 } else
224 return false;
225 }
226
227 @Override
228 public int hashCode() {
229 Type [] lowerBounds = getLowerBounds();
230 Type [] upperBounds = getUpperBounds();
231
232 return Arrays.hashCode(lowerBounds) ^ Arrays.hashCode(upperBounds);
233 }
234}