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 }