View Javadoc
1   /*
2    * Copyright (c) 1997, 2011, 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 com.sun.codemodel.internal;
27  
28  import java.util.Arrays;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Collections;
32  import java.util.ArrayList;
33  
34  /**
35   * Represents X<Y>.
36   *
37   * TODO: consider separating the decl and the use.
38   *
39   * @author
40   *     Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
41   */
42  class JNarrowedClass extends JClass {
43      /**
44       * A generic class with type parameters.
45       */
46      final JClass basis;
47      /**
48       * Arguments to those parameters.
49       */
50      private final List<JClass> args;
51  
52      JNarrowedClass(JClass basis, JClass arg) {
53          this(basis,Collections.singletonList(arg));
54      }
55  
56      JNarrowedClass(JClass basis, List<JClass> args) {
57          super(basis.owner());
58          this.basis = basis;
59          assert !(basis instanceof JNarrowedClass);
60          this.args = args;
61      }
62  
63      @Override
64      public JClass narrow( JClass clazz ) {
65          List<JClass> newArgs = new ArrayList<JClass>(args);
66          newArgs.add(clazz);
67          return new JNarrowedClass(basis,newArgs);
68      }
69  
70      @Override
71      public JClass narrow( JClass... clazz ) {
72          List<JClass> newArgs = new ArrayList<JClass>(args);
73          newArgs.addAll(Arrays.asList(clazz));
74          return new JNarrowedClass(basis,newArgs);
75      }
76  
77      public String name() {
78          StringBuilder buf = new StringBuilder();
79          buf.append(basis.name());
80          buf.append('<');
81          boolean first = true;
82          for (JClass c : args) {
83              if(first)
84                  first = false;
85              else
86                  buf.append(',');
87              buf.append(c.name());
88          }
89          buf.append('>');
90          return buf.toString();
91      }
92  
93      public String fullName() {
94          StringBuilder buf = new StringBuilder();
95          buf.append(basis.fullName());
96          buf.append('<');
97          boolean first = true;
98          for (JClass c : args) {
99              if(first)
100                 first = false;
101             else
102                 buf.append(',');
103             buf.append(c.fullName());
104         }
105         buf.append('>');
106         return buf.toString();
107     }
108 
109     @Override
110     public String binaryName() {
111         StringBuilder buf = new StringBuilder();
112         buf.append(basis.binaryName());
113         buf.append('<');
114         boolean first = true;
115         for (JClass c : args) {
116             if(first)
117                 first = false;
118             else
119                 buf.append(',');
120             buf.append(c.binaryName());
121         }
122         buf.append('>');
123         return buf.toString();
124     }
125 
126     @Override
127     public void generate(JFormatter f) {
128         f.t(basis).p('<').g(args).p(JFormatter.CLOSE_TYPE_ARGS);
129     }
130 
131     @Override
132     void printLink(JFormatter f) {
133         basis.printLink(f);
134         f.p("{@code <}");
135         boolean first = true;
136         for( JClass c : args ) {
137             if(first)
138                 first = false;
139             else
140                 f.p(',');
141             c.printLink(f);
142         }
143         f.p("{@code >}");
144     }
145 
146     public JPackage _package() {
147         return basis._package();
148     }
149 
150     public JClass _extends() {
151         JClass base = basis._extends();
152         if(base==null)  return base;
153         return base.substituteParams(basis.typeParams(),args);
154     }
155 
156     public Iterator<JClass> _implements() {
157         return new Iterator<JClass>() {
158             private final Iterator<JClass> core = basis._implements();
159             public void remove() {
160                 core.remove();
161             }
162             public JClass next() {
163                 return core.next().substituteParams(basis.typeParams(),args);
164             }
165             public boolean hasNext() {
166                 return core.hasNext();
167             }
168         };
169     }
170 
171     @Override
172     public JClass erasure() {
173         return basis;
174     }
175 
176     public boolean isInterface() {
177         return basis.isInterface();
178     }
179 
180     public boolean isAbstract() {
181         return basis.isAbstract();
182     }
183 
184     @Override
185     public boolean isArray() {
186         return false;
187     }
188 
189 
190     //
191     // Equality is based on value
192     //
193 
194     @Override
195     public boolean equals(Object obj) {
196         if(!(obj instanceof JNarrowedClass))   return false;
197         return fullName().equals(((JClass)obj).fullName());
198     }
199 
200     @Override
201     public int hashCode() {
202         return fullName().hashCode();
203     }
204 
205     protected JClass substituteParams(JTypeVar[] variables, List<JClass> bindings) {
206         JClass b = basis.substituteParams(variables,bindings);
207         boolean different = b!=basis;
208 
209         List<JClass> clazz = new ArrayList<JClass>(args.size());
210         for( int i=0; i<clazz.size(); i++ ) {
211             JClass c = args.get(i).substituteParams(variables,bindings);
212             clazz.set(i,c);
213             different |= c != args.get(i);
214         }
215 
216         if(different)
217             return new JNarrowedClass(b,clazz);
218         else
219             return this;
220     }
221 
222     @Override
223     public List<JClass> getTypeParameters() {
224         return args;
225     }
226 }