Thu, 12 Oct 2017 19:44:07 +0800
merge
1 /*
2 * Copyright (c) 1997, 2010, 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 */
26 package com.sun.codemodel.internal;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collections;
31 import java.util.Iterator;
32 import java.util.List;
34 /**
35 * Represents a Java reference type, such as a class, an interface,
36 * an enum, an array type, a parameterized type.
37 *
38 * <p>
39 * To be exact, this object represents an "use" of a reference type,
40 * not necessarily a declaration of it, which is modeled as {@link JDefinedClass}.
41 */
42 public abstract class JClass extends JType
43 {
44 protected JClass( JCodeModel _owner ) {
45 this._owner = _owner;
46 }
48 /**
49 * Gets the name of this class.
50 *
51 * @return
52 * name of this class, without any qualification.
53 * For example, this method returns "String" for
54 * <code>java.lang.String</code>.
55 */
56 abstract public String name();
58 /**
59 * Gets the package to which this class belongs.
60 * TODO: shall we move move this down?
61 */
62 abstract public JPackage _package();
64 /**
65 * Returns the class in which this class is nested, or <tt>null</tt> if
66 * this is a top-level class.
67 */
68 public JClass outer() {
69 return null;
70 }
72 private final JCodeModel _owner;
73 /** Gets the JCodeModel object to which this object belongs. */
74 public final JCodeModel owner() { return _owner; }
76 /**
77 * Gets the super class of this class.
78 *
79 * @return
80 * Returns the JClass representing the superclass of the
81 * entity (class or interface) represented by this {@link JClass}.
82 * Even if no super class is given explicitly or this {@link JClass}
83 * is not a class, this method still returns
84 * {@link JClass} for {@link Object}.
85 * If this JClass represents {@link Object}, return null.
86 */
87 abstract public JClass _extends();
89 /**
90 * Iterates all super interfaces directly implemented by
91 * this class/interface.
92 *
93 * @return
94 * A non-null valid iterator that iterates all
95 * {@link JClass} objects that represents those interfaces
96 * implemented by this object.
97 */
98 abstract public Iterator<JClass> _implements();
100 /**
101 * Iterates all the type parameters of this class/interface.
102 *
103 * <p>
104 * For example, if this {@link JClass} represents
105 * <code>Set<T></code>, this method returns an array
106 * that contains single {@link JTypeVar} for 'T'.
107 */
108 public JTypeVar[] typeParams() {
109 return EMPTY_ARRAY;
110 }
112 /**
113 * Sometimes useful reusable empty array.
114 */
115 protected static final JTypeVar[] EMPTY_ARRAY = new JTypeVar[0];
117 /**
118 * Checks if this object represents an interface.
119 */
120 abstract public boolean isInterface();
122 /**
123 * Checks if this class is an abstract class.
124 */
125 abstract public boolean isAbstract();
127 /**
128 * If this class represents one of the wrapper classes
129 * defined in the java.lang package, return the corresponding
130 * primitive type. Otherwise null.
131 */
132 public JPrimitiveType getPrimitiveType() { return null; }
134 /**
135 * @deprecated calling this method from {@link JClass}
136 * would be meaningless, since it's always guaranteed to
137 * return <tt>this</tt>.
138 */
139 public JClass boxify() { return this; }
141 public JType unboxify() {
142 JPrimitiveType pt = getPrimitiveType();
143 return pt==null ? (JType)this : pt;
144 }
146 public JClass erasure() {
147 return this;
148 }
150 /**
151 * Checks the relationship between two classes.
152 * <p>
153 * This method works in the same way as {@link Class#isAssignableFrom(Class)}
154 * works. For example, baseClass.isAssignableFrom(derivedClass)==true.
155 */
156 public final boolean isAssignableFrom( JClass derived ) {
157 // to avoid the confusion, always use "this" explicitly in this method.
159 // null can be assigned to any type.
160 if( derived instanceof JNullType ) return true;
162 if( this==derived ) return true;
164 // the only class that is assignable from an interface is
165 // java.lang.Object
166 if( this==_package().owner().ref(Object.class) ) return true;
168 JClass b = derived._extends();
169 if( b!=null && this.isAssignableFrom(b) )
170 return true;
172 if( this.isInterface() ) {
173 Iterator<JClass> itfs = derived._implements();
174 while( itfs.hasNext() )
175 if( this.isAssignableFrom(itfs.next()) )
176 return true;
177 }
179 return false;
180 }
182 /**
183 * Gets the parameterization of the given base type.
184 *
185 * <p>
186 * For example, given the following
187 * <pre><xmp>
188 * interface Foo<T> extends List<List<T>> {}
189 * interface Bar extends Foo<String> {}
190 * </xmp></pre>
191 * This method works like this:
192 * <pre><xmp>
193 * getBaseClass( Bar, List ) = List<List<String>
194 * getBaseClass( Bar, Foo ) = Foo<String>
195 * getBaseClass( Foo<? extends Number>, Collection ) = Collection<List<? extends Number>>
196 * getBaseClass( ArrayList<? extends BigInteger>, List ) = List<? extends BigInteger>
197 * </xmp></pre>
198 *
199 * @param baseType
200 * The class whose parameterization we are interested in.
201 * @return
202 * The use of {@code baseType} in {@code this} type.
203 * or null if the type is not assignable to the base type.
204 */
205 public final JClass getBaseClass( JClass baseType ) {
207 if( this.erasure().equals(baseType) )
208 return this;
210 JClass b = _extends();
211 if( b!=null ) {
212 JClass bc = b.getBaseClass(baseType);
213 if(bc!=null)
214 return bc;
215 }
217 Iterator<JClass> itfs = _implements();
218 while( itfs.hasNext() ) {
219 JClass bc = itfs.next().getBaseClass(baseType);
220 if(bc!=null)
221 return bc;
222 }
224 return null;
225 }
227 public final JClass getBaseClass( Class<?> baseType ) {
228 return getBaseClass(owner().ref(baseType));
229 }
232 private JClass arrayClass;
233 public JClass array() {
234 if(arrayClass==null)
235 arrayClass = new JArrayClass(owner(),this);
236 return arrayClass;
237 }
239 /**
240 * "Narrows" a generic class to a concrete class by specifying
241 * a type argument.
242 *
243 * <p>
244 * <code>.narrow(X)</code> builds <code>Set<X></code> from <code>Set</code>.
245 */
246 public JClass narrow( Class<?> clazz ) {
247 return narrow(owner().ref(clazz));
248 }
250 public JClass narrow( Class<?>... clazz ) {
251 JClass[] r = new JClass[clazz.length];
252 for( int i=0; i<clazz.length; i++ )
253 r[i] = owner().ref(clazz[i]);
254 return narrow(r);
255 }
257 /**
258 * "Narrows" a generic class to a concrete class by specifying
259 * a type argument.
260 *
261 * <p>
262 * <code>.narrow(X)</code> builds <code>Set<X></code> from <code>Set</code>.
263 */
264 public JClass narrow( JClass clazz ) {
265 return new JNarrowedClass(this,clazz);
266 }
268 public JClass narrow( JType type ) {
269 return narrow(type.boxify());
270 }
272 public JClass narrow( JClass... clazz ) {
273 return new JNarrowedClass(this,Arrays.asList(clazz.clone()));
274 }
276 public JClass narrow( List<? extends JClass> clazz ) {
277 return new JNarrowedClass(this,new ArrayList<JClass>(clazz));
278 }
280 /**
281 * If this class is parameterized, return the type parameter of the given index.
282 */
283 public List<JClass> getTypeParameters() {
284 return Collections.emptyList();
285 }
287 /**
288 * Returns true if this class is a parameterized class.
289 */
290 public final boolean isParameterized() {
291 return erasure()!=this;
292 }
294 /**
295 * Create "? extends T" from T.
296 *
297 * @return never null
298 */
299 public final JClass wildcard() {
300 return new JTypeWildcard(this);
301 }
303 /**
304 * Substitutes the type variables with their actual arguments.
305 *
306 * <p>
307 * For example, when this class is Map<String,Map<V>>,
308 * (where V then doing
309 * substituteParams( V, Integer ) returns a {@link JClass}
310 * for <code>Map<String,Map<Integer>></code>.
311 *
312 * <p>
313 * This method needs to work recursively.
314 */
315 protected abstract JClass substituteParams( JTypeVar[] variables, List<JClass> bindings );
317 public String toString() {
318 return this.getClass().getName() + '(' + name() + ')';
319 }
322 public final JExpression dotclass() {
323 return JExpr.dotclass(this);
324 }
326 /** Generates a static method invocation. */
327 public final JInvocation staticInvoke(JMethod method) {
328 return new JInvocation(this,method);
329 }
331 /** Generates a static method invocation. */
332 public final JInvocation staticInvoke(String method) {
333 return new JInvocation(this,method);
334 }
336 /** Static field reference. */
337 public final JFieldRef staticRef(String field) {
338 return new JFieldRef(this, field);
339 }
341 /** Static field reference. */
342 public final JFieldRef staticRef(JVar field) {
343 return new JFieldRef(this, field);
344 }
346 public void generate(JFormatter f) {
347 f.t(this);
348 }
350 /**
351 * Prints the class name in javadoc @link format.
352 */
353 void printLink(JFormatter f) {
354 f.p("{@link ").g(this).p('}');
355 }
356 }