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 */ 25 26 package com.sun.codemodel.internal; 27 28 import java.lang.annotation.Annotation; 29 import java.util.ArrayList; 30 import java.util.List; 31 import java.util.Set; 32 import java.util.TreeSet; 33 import java.util.Collections; 34 import java.util.Collection; 35 36 import com.sun.codemodel.internal.util.ClassNameComparator; 37 38 /** 39 * Java method. 40 */ 41 public class JMethod extends JGenerifiableImpl implements JDeclaration, JAnnotatable, JDocCommentable { 42 43 /** 44 * Modifiers for this method 45 */ 46 private JMods mods; 47 48 /** 49 * Return type for this method 50 */ 51 private JType type = null; 52 53 /** 54 * Name of this method 55 */ 56 private String name = null; 57 58 /** 59 * List of parameters for this method's declaration 60 */ 61 private final List<JVar> params = new ArrayList<JVar>(); 62 63 /** 64 * Set of exceptions that this method may throw. 65 * A set instance lazily created. 66 */ 67 private Set<JClass> _throws; 68 69 /** 70 * JBlock of statements that makes up the body this method 71 */ 72 private JBlock body = null; 73 74 private JDefinedClass outer; 75 76 /** 77 * javadoc comments for this JMethod 78 */ 79 private JDocComment jdoc = null; 80 81 /** 82 * Variable parameter for this method's varargs declaration 83 * introduced in J2SE 1.5 84 */ 85 private JVar varParam = null; 86 87 /** 88 * Annotations on this variable. Lazily created. 89 */ 90 private List<JAnnotationUse> annotations = null; 91 92 93 private boolean isConstructor() { 94 return type == null; 95 } 96 97 /** To set the default value for the 98 * annotation member 99 */ 100 private JExpression defaultValue = null; 101 102 103 /** 104 * JMethod constructor 105 * 106 * @param mods 107 * Modifiers for this method's declaration 108 * 109 * @param type 110 * Return type for the method 111 * 112 * @param name 113 * Name of this method 114 */ 115 JMethod(JDefinedClass outer, int mods, JType type, String name) { 116 this.mods = JMods.forMethod(mods); 117 this.type = type; 118 this.name = name; 119 this.outer = outer; 120 } 121 122 /** 123 * Constructor constructor 124 * 125 * @param mods 126 * Modifiers for this constructor's declaration 127 * 128 * @param _class 129 * JClass containing this constructor 130 */ 131 JMethod(int mods, JDefinedClass _class) { 132 this.mods = JMods.forMethod(mods); 133 this.type = null; 134 this.name = _class.name(); 135 this.outer = _class; 136 } 137 138 private Set<JClass> getThrows() { 139 if(_throws==null) 140 _throws = new TreeSet<JClass>(ClassNameComparator.theInstance); 141 return _throws; 142 } 143 144 /** 145 * Add an exception to the list of exceptions that this 146 * method may throw. 147 * 148 * @param exception 149 * Name of an exception that this method may throw 150 */ 151 public JMethod _throws(JClass exception) { 152 getThrows().add(exception); 153 return this; 154 } 155 156 public JMethod _throws(Class<? extends Throwable> exception) { 157 return _throws(outer.owner().ref(exception)); 158 } 159 160 /** 161 * Returns the list of variable of this method. 162 * 163 * @return List of parameters of this method. This list is not modifiable. 164 */ 165 public List<JVar> params() { 166 return Collections.<JVar>unmodifiableList(params); 167 } 168 169 /** 170 * Add the specified variable to the list of parameters 171 * for this method signature. 172 * 173 * @param type 174 * JType of the parameter being added 175 * 176 * @param name 177 * Name of the parameter being added 178 * 179 * @return New parameter variable 180 */ 181 public JVar param(int mods, JType type, String name) { 182 JVar v = new JVar(JMods.forVar(mods), type, name, null); 183 params.add(v); 184 return v; 185 } 186 187 public JVar param(JType type, String name) { 188 return param(JMod.NONE, type, name); 189 } 190 191 public JVar param(int mods, Class<?> type, String name) { 192 return param(mods, outer.owner()._ref(type), name); 193 } 194 195 public JVar param(Class<?> type, String name) { 196 return param(outer.owner()._ref(type), name); 197 } 198 199 /** 200 * @see #varParam(JType, String) 201 */ 202 public JVar varParam(Class<?> type, String name) { 203 return varParam(outer.owner()._ref(type),name); 204 } 205 206 /** 207 * Add the specified variable argument to the list of parameters 208 * for this method signature. 209 * 210 * @param type 211 * Type of the parameter being added. 212 * 213 * @param name 214 * Name of the parameter being added 215 * 216 * @return the variable parameter 217 * 218 * @throws IllegalStateException 219 * If this method is called twice. 220 * varargs in J2SE 1.5 can appear only once in the 221 * method signature. 222 */ 223 public JVar varParam(JType type, String name) { 224 if (!hasVarArgs()) { 225 226 varParam = 227 new JVar( 228 JMods.forVar(JMod.NONE), 229 type.array(), 230 name, 231 null); 232 return varParam; 233 } else { 234 throw new IllegalStateException( 235 "Cannot have two varargs in a method,\n" 236 + "Check if varParam method of JMethod is" 237 + " invoked more than once"); 238 239 } 240 241 } 242 243 /** 244 * Adds an annotation to this variable. 245 * @param clazz 246 * The annotation class to annotate the field with 247 */ 248 public JAnnotationUse annotate(JClass clazz){ 249 if(annotations==null) 250 annotations = new ArrayList<JAnnotationUse>(); 251 JAnnotationUse a = new JAnnotationUse(clazz); 252 annotations.add(a); 253 return a; 254 } 255 256 /** 257 * Adds an annotation to this variable. 258 * 259 * @param clazz 260 * The annotation class to annotate the field with 261 */ 262 public JAnnotationUse annotate(Class <? extends Annotation> clazz){ 263 return annotate(owner().ref(clazz)); 264 } 265 266 public <W extends JAnnotationWriter> W annotate2(Class<W> clazz) { 267 return TypedAnnotationWriter.create(clazz,this); 268 } 269 270 public Collection<JAnnotationUse> annotations() { 271 if (annotations == null) 272 annotations = new ArrayList<JAnnotationUse>(); 273 return Collections.unmodifiableList(annotations); 274 } 275 276 /** 277 * Check if there are any varargs declared 278 * for this method signature. 279 */ 280 public boolean hasVarArgs() { 281 return this.varParam!=null; 282 } 283 284 public String name() { 285 return name; 286 } 287 288 /** 289 * Changes the name of the method. 290 */ 291 public void name(String n) { 292 this.name = n; 293 } 294 295 /** 296 * Returns the return type. 297 */ 298 public JType type() { 299 return type; 300 } 301 302 /** 303 * Overrides the return type. 304 */ 305 public void type(JType t) { 306 this.type = t; 307 } 308 309 /** 310 * Returns all the parameter types in an array. 311 * @return 312 * If there's no parameter, an empty array will be returned. 313 */ 314 public JType[] listParamTypes() { 315 JType[] r = new JType[params.size()]; 316 for (int i = 0; i < r.length; i++) 317 r[i] = params.get(i).type(); 318 return r; 319 } 320 321 /** 322 * Returns the varags parameter type. 323 * @return 324 * If there's no vararg parameter type, null will be returned. 325 */ 326 public JType listVarParamType() { 327 if (varParam != null) 328 return varParam.type(); 329 else 330 return null; 331 } 332 333 /** 334 * Returns all the parameters in an array. 335 * @return 336 * If there's no parameter, an empty array will be returned. 337 */ 338 public JVar[] listParams() { 339 return params.toArray(new JVar[params.size()]); 340 } 341 342 /** 343 * Returns the variable parameter 344 * @return 345 * If there's no parameter, null will be returned. 346 */ 347 public JVar listVarParam() { 348 return varParam; 349 } 350 351 /** 352 * Returns true if the method has the specified signature. 353 */ 354 public boolean hasSignature(JType[] argTypes) { 355 JVar[] p = listParams(); 356 if (p.length != argTypes.length) 357 return false; 358 359 for (int i = 0; i < p.length; i++) 360 if (!p[i].type().equals(argTypes[i])) 361 return false; 362 363 return true; 364 } 365 366 /** 367 * Get the block that makes up body of this method 368 * 369 * @return Body of method 370 */ 371 public JBlock body() { 372 if (body == null) 373 body = new JBlock(); 374 return body; 375 } 376 377 /** 378 * Specify the default value for this annotation member 379 * @param value 380 * Default value for the annotation member 381 * 382 */ 383 public void declareDefaultValue(JExpression value){ 384 this.defaultValue = value; 385 } 386 387 /** 388 * Creates, if necessary, and returns the class javadoc for this 389 * JDefinedClass 390 * 391 * @return JDocComment containing javadocs for this class 392 */ 393 public JDocComment javadoc() { 394 if (jdoc == null) 395 jdoc = new JDocComment(owner()); 396 return jdoc; 397 } 398 399 public void declare(JFormatter f) { 400 if (jdoc != null) 401 f.g(jdoc); 402 403 if (annotations != null){ 404 for (JAnnotationUse a : annotations) 405 f.g(a).nl(); 406 } 407 408 f.g(mods); 409 410 // declare the generics parameters 411 super.declare(f); 412 413 if (!isConstructor()) 414 f.g(type); 415 f.id(name).p('(').i(); 416 // when parameters are printed in new lines, we want them to be indented. 417 // there's a good chance no newlines happen, too, but just in case it does. 418 boolean first = true; 419 for (JVar var : params) { 420 if (!first) 421 f.p(','); 422 if(var.isAnnotated()) 423 f.nl(); 424 f.b(var); 425 first = false; 426 } 427 if (hasVarArgs()) { 428 if (!first) 429 f.p(','); 430 f.g(varParam.type().elementType()); 431 f.p("... "); 432 f.id(varParam.name()); 433 } 434 435 f.o().p(')'); 436 if (_throws!=null && !_throws.isEmpty()) { 437 f.nl().i().p("throws").g(_throws).nl().o(); 438 } 439 440 if (defaultValue != null) { 441 f.p("default "); 442 f.g(defaultValue); 443 } 444 if (body != null) { 445 f.s(body); 446 } else if ( 447 !outer.isInterface() && !outer.isAnnotationTypeDeclaration() && !mods.isAbstract() && !mods.isNative()) { 448 // Print an empty body for non-native, non-abstract methods 449 f.s(new JBlock()); 450 } else { 451 f.p(';').nl(); 452 } 453 } 454 455 /** 456 * @return 457 * the current modifiers of this method. 458 * Always return non-null valid object. 459 */ 460 public JMods mods() { 461 return mods; 462 } 463 464 /** 465 * @deprecated use {@link #mods()} 466 */ 467 public JMods getMods() { 468 return mods; 469 } 470 471 protected JCodeModel owner() { 472 return outer.owner(); 473 } 474 }