001: /*
002: * The contents of this file are subject to the terms
003: * of the Common Development and Distribution License
004: * (the "License"). You may not use this file except
005: * in compliance with the License.
006: *
007: * You can obtain a copy of the license at
008: * https://jwsdp.dev.java.net/CDDLv1.0.html
009: * See the License for the specific language governing
010: * permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL
013: * HEADER in each file and include the License file at
014: * https://jwsdp.dev.java.net/CDDLv1.0.html If applicable,
015: * add the following below this CDDL HEADER, with the
016: * fields enclosed by brackets "[]" replaced with your
017: * own identifying information: Portions Copyright [yyyy]
018: * [name of copyright owner]
019: */
020: package com.sun.codemodel;
021:
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Collections;
025: import java.util.ArrayList;
026:
027: /**
028: * Represents X<Y>.
029: *
030: * TODO: consider separating the decl and the use.
031: *
032: * @author
033: * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
034: */
035: class JNarrowedClass extends JClass {
036: /**
037: * A generic class with type parameters.
038: */
039: final JClass basis;
040: /**
041: * Arguments to those parameters.
042: */
043: private final List<JClass> args;
044:
045: JNarrowedClass(JClass basis, JClass arg) {
046: this (basis, Collections.singletonList(arg));
047: }
048:
049: JNarrowedClass(JClass basis, List<JClass> args) {
050: super (basis.owner());
051: this .basis = basis;
052: assert !(basis instanceof JNarrowedClass);
053: this .args = args;
054: }
055:
056: public JClass narrow(JClass clazz) {
057: List<JClass> newArgs = new ArrayList<JClass>(args);
058: newArgs.add(clazz);
059: return new JNarrowedClass(basis, newArgs);
060: }
061:
062: public JClass narrow(JClass... clazz) {
063: List<JClass> newArgs = new ArrayList<JClass>(args);
064: for (JClass c : clazz)
065: newArgs.add(c);
066: return new JNarrowedClass(basis, newArgs);
067: }
068:
069: public String name() {
070: StringBuffer buf = new StringBuffer();
071: buf.append(basis.name());
072: buf.append('<');
073: boolean first = true;
074: for (JClass c : args) {
075: if (first)
076: first = false;
077: else
078: buf.append(',');
079: buf.append(c.name());
080: }
081: buf.append('>');
082: return buf.toString();
083: }
084:
085: public String fullName() {
086: StringBuilder buf = new StringBuilder();
087: buf.append(basis.fullName());
088: buf.append('<');
089: boolean first = true;
090: for (JClass c : args) {
091: if (first)
092: first = false;
093: else
094: buf.append(',');
095: buf.append(c.fullName());
096: }
097: buf.append('>');
098: return buf.toString();
099: }
100:
101: public String binaryName() {
102: StringBuilder buf = new StringBuilder();
103: buf.append(basis.binaryName());
104: buf.append('<');
105: boolean first = true;
106: for (JClass c : args) {
107: if (first)
108: first = false;
109: else
110: buf.append(',');
111: buf.append(c.binaryName());
112: }
113: buf.append('>');
114: return buf.toString();
115: }
116:
117: public void generate(JFormatter f) {
118: f.t(basis).p('<').g(args).p(JFormatter.CLOSE_TYPE_ARGS);
119: }
120:
121: @Override
122: void printLink(JFormatter f) {
123: basis.printLink(f);
124: f.p("{@code <}");
125: boolean first = true;
126: for (JClass c : args) {
127: if (first)
128: first = false;
129: else
130: f.p(',');
131: c.printLink(f);
132: }
133: f.p("{@code >}");
134: }
135:
136: public JPackage _package() {
137: return basis._package();
138: }
139:
140: public JClass _extends() {
141: JClass base = basis._extends();
142: if (base == null)
143: return base;
144: return base.substituteParams(basis.typeParams(), args);
145: }
146:
147: public Iterator<JClass> _implements () {
148: return new Iterator<JClass>() {
149: private final Iterator<JClass> core = basis._implements ();
150:
151: public void remove() {
152: core.remove();
153: }
154:
155: public JClass next() {
156: return core.next().substituteParams(basis.typeParams(),
157: args);
158: }
159:
160: public boolean hasNext() {
161: return core.hasNext();
162: }
163: };
164: }
165:
166: public JClass erasure() {
167: return basis;
168: }
169:
170: public boolean isInterface() {
171: return basis.isInterface();
172: }
173:
174: public boolean isAbstract() {
175: return basis.isAbstract();
176: }
177:
178: public boolean isArray() {
179: return false;
180: }
181:
182: //
183: // Equality is based on value
184: //
185:
186: public boolean equals(Object obj) {
187: if (!(obj instanceof JNarrowedClass))
188: return false;
189: return fullName().equals(((JClass) obj).fullName());
190: }
191:
192: public int hashCode() {
193: return fullName().hashCode();
194: }
195:
196: protected JClass substituteParams(JTypeVar[] variables,
197: List<JClass> bindings) {
198: JClass b = basis.substituteParams(variables, bindings);
199: boolean different = b != basis;
200:
201: List<JClass> clazz = new ArrayList<JClass>(args.size());
202: for (int i = 0; i < clazz.size(); i++) {
203: JClass c = args.get(i)
204: .substituteParams(variables, bindings);
205: clazz.set(i, c);
206: different |= c != args.get(i);
207: }
208:
209: if (different)
210: return new JNarrowedClass(b, clazz);
211: else
212: return this ;
213: }
214:
215: public List<JClass> getTypeParameters() {
216: return args;
217: }
218: }
|