001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.codemodel.internal;
027:
028: import java.lang.annotation.Annotation;
029: import java.util.ArrayList;
030: import java.util.List;
031: import java.util.Set;
032: import java.util.TreeSet;
033:
034: import com.sun.codemodel.internal.util.ClassNameComparator;
035:
036: /**
037: * Java method.
038: */
039: public class JMethod extends JGenerifiableImpl implements JDeclaration,
040: JAnnotatable {
041:
042: /**
043: * Modifiers for this method
044: */
045: private JMods mods;
046:
047: /**
048: * Return type for this method
049: */
050: private JType type = null;
051:
052: /**
053: * Name of this method
054: */
055: private String name = null;
056:
057: /**
058: * List of parameters for this method's declaration
059: */
060: private final List<JVar> params = new ArrayList<JVar>();
061:
062: /**
063: * Set of exceptions that this method may throw.
064: * A set instance lazily created.
065: */
066: private Set<JClass> _throws;
067:
068: /**
069: * JBlock of statements that makes up the body this method
070: */
071: private JBlock body = null;
072:
073: private JDefinedClass outer;
074:
075: /**
076: * javadoc comments for this JMethod
077: */
078: private JDocComment jdoc = null;
079:
080: /**
081: * Variable parameter for this method's varargs declaration
082: * introduced in J2SE 1.5
083: */
084: private JVar varParam = null;
085:
086: /**
087: * Annotations on this variable. Lazily created.
088: */
089: private List<JAnnotationUse> annotations = null;
090:
091: private boolean isConstructor() {
092: return type == null;
093: }
094:
095: /** To set the default value for the
096: * annotation member
097: */
098: private JExpression defaultValue = null;
099:
100: /**
101: * JMethod constructor
102: *
103: * @param mods
104: * Modifiers for this method's declaration
105: *
106: * @param type
107: * Return type for the method
108: *
109: * @param name
110: * Name of this method
111: */
112: JMethod(JDefinedClass outer, int mods, JType type, String name) {
113: this .mods = JMods.forMethod(mods);
114: this .type = type;
115: this .name = name;
116: this .outer = outer;
117: }
118:
119: /**
120: * Constructor constructor
121: *
122: * @param mods
123: * Modifiers for this constructor's declaration
124: *
125: * @param _class
126: * JClass containing this constructor
127: */
128: JMethod(int mods, JDefinedClass _class) {
129: this .mods = JMods.forMethod(mods);
130: this .type = null;
131: this .name = _class.name();
132: this .outer = _class;
133: }
134:
135: private Set<JClass> getThrows() {
136: if (_throws == null)
137: _throws = new TreeSet<JClass>(
138: ClassNameComparator.theInstance);
139: return _throws;
140: }
141:
142: /**
143: * Add an exception to the list of exceptions that this
144: * method may throw.
145: *
146: * @param exception
147: * Name of an exception that this method may throw
148: */
149: public JMethod _throws(JClass exception) {
150: getThrows().add(exception);
151: return this ;
152: }
153:
154: public JMethod _throws(Class exception) {
155: return _throws(outer.owner().ref(exception));
156: }
157:
158: /**
159: * Add the specified variable to the list of parameters
160: * for this method signature.
161: *
162: * @param type
163: * JType of the parameter being added
164: *
165: * @param name
166: * Name of the parameter being added
167: *
168: * @return New parameter variable
169: */
170: public JVar param(int mods, JType type, String name) {
171: JVar v = new JVar(JMods.forVar(mods), type, name, null);
172: params.add(v);
173: return v;
174: }
175:
176: public JVar param(JType type, String name) {
177: return param(JMod.NONE, type, name);
178: }
179:
180: public JVar param(int mods, Class type, String name) {
181: return param(mods, outer.owner()._ref(type), name);
182: }
183:
184: public JVar param(Class type, String name) {
185: return param(outer.owner()._ref(type), name);
186: }
187:
188: /**
189: * @see #varParam(JType, String)
190: */
191: public JVar varParam(Class type, String name) {
192: return varParam(outer.owner()._ref(type), name);
193: }
194:
195: /**
196: * Add the specified variable argument to the list of parameters
197: * for this method signature.
198: *
199: * @param type
200: * Type of the parameter being added.
201: *
202: * @param name
203: * Name of the parameter being added
204: *
205: * @return the variable parameter
206: *
207: * @throws IllegalStateException
208: * If this method is called twice.
209: * varargs in J2SE 1.5 can appear only once in the
210: * method signature.
211: */
212: public JVar varParam(JType type, String name) {
213: if (!hasVarArgs()) {
214:
215: varParam = new JVar(JMods.forVar(JMod.NONE), type.array(),
216: name, null);
217: return varParam;
218: } else {
219: throw new IllegalStateException(
220: "Cannot have two varargs in a method,\n"
221: + "Check if varParam method of JMethod is"
222: + " invoked more than once");
223:
224: }
225:
226: }
227:
228: /**
229: * Adds an annotation to this variable.
230: * @param clazz
231: * The annotation class to annotate the field with
232: */
233: public JAnnotationUse annotate(JClass clazz) {
234: if (annotations == null)
235: annotations = new ArrayList<JAnnotationUse>();
236: JAnnotationUse a = new JAnnotationUse(clazz);
237: annotations.add(a);
238: return a;
239: }
240:
241: /**
242: * Adds an annotation to this variable.
243: *
244: * @param clazz
245: * The annotation class to annotate the field with
246: */
247: public JAnnotationUse annotate(Class<? extends Annotation> clazz) {
248: return annotate(owner().ref(clazz));
249: }
250:
251: public <W extends JAnnotationWriter> W annotate2(Class<W> clazz) {
252: return TypedAnnotationWriter.create(clazz, this );
253: }
254:
255: /**
256: * Check if there are any varargs declared
257: * for this method signature.
258: */
259: public boolean hasVarArgs() {
260: return this .varParam != null;
261: }
262:
263: public String name() {
264: return name;
265: }
266:
267: /**
268: * Returns the return type.
269: */
270: public JType type() {
271: return type;
272: }
273:
274: /**
275: * Returns all the parameter types in an array.
276: * @return
277: * If there's no parameter, an empty array will be returned.
278: */
279: public JType[] listParamTypes() {
280: JType[] r = new JType[params.size()];
281: for (int i = 0; i < r.length; i++)
282: r[i] = params.get(i).type();
283: return r;
284: }
285:
286: /**
287: * Returns the varags parameter type.
288: * @return
289: * If there's no vararg parameter type, null will be returned.
290: */
291: public JType listVarParamType() {
292: if (varParam != null)
293: return varParam.type();
294: else
295: return null;
296: }
297:
298: /**
299: * Returns all the parameters in an array.
300: * @return
301: * If there's no parameter, an empty array will be returned.
302: */
303: public JVar[] listParams() {
304: return params.toArray(new JVar[params.size()]);
305: }
306:
307: /**
308: * Returns the variable parameter
309: * @return
310: * If there's no parameter, null will be returned.
311: */
312: public JVar listVarParam() {
313: return varParam;
314: }
315:
316: /**
317: * Returns true if the method has the specified signature.
318: */
319: public boolean hasSignature(JType[] argTypes) {
320: JVar[] p = listParams();
321: if (p.length != argTypes.length)
322: return false;
323:
324: for (int i = 0; i < p.length; i++)
325: if (!p[i].type().equals(argTypes[i]))
326: return false;
327:
328: return true;
329: }
330:
331: /**
332: * Get the block that makes up body of this method
333: *
334: * @return Body of method
335: */
336: public JBlock body() {
337: if (body == null)
338: body = new JBlock();
339: return body;
340: }
341:
342: /**
343: * Specify the default value for this annotation member
344: * @param value
345: * Default value for the annotation member
346: *
347: */
348: public void declareDefaultValue(JExpression value) {
349: this .defaultValue = value;
350: }
351:
352: /**
353: * Creates, if necessary, and returns the class javadoc for this
354: * JDefinedClass
355: *
356: * @return JDocComment containing javadocs for this class
357: */
358: public JDocComment javadoc() {
359: if (jdoc == null)
360: jdoc = new JDocComment(owner());
361: return jdoc;
362: }
363:
364: public void declare(JFormatter f) {
365: if (jdoc != null)
366: f.g(jdoc);
367:
368: if (annotations != null) {
369: for (JAnnotationUse a : annotations)
370: f.g(a).nl();
371: }
372:
373: // declare the generics parameters
374: super .declare(f);
375:
376: f.g(mods);
377: if (!isConstructor())
378: f.g(type);
379: f.id(name).p('(').i();
380: // when parameters are printed in new lines, we want them to be indented.
381: // there's a good chance no newlines happen, too, but just in case it does.
382: boolean first = true;
383: for (JVar var : params) {
384: if (!first)
385: f.p(',');
386: if (var.isAnnotated())
387: f.nl();
388: f.b(var);
389: first = false;
390: }
391: if (hasVarArgs()) {
392: if (!first)
393: f.p(',');
394: f.g(varParam.type().elementType());
395: f.p("... ");
396: f.id(varParam.name());
397: }
398:
399: f.o().p(')');
400: if (_throws != null && !_throws.isEmpty()) {
401: f.nl().i().p("throws").g(_throws).nl().o();
402: }
403:
404: if (defaultValue != null) {
405: f.p("default ");
406: f.g(defaultValue);
407: }
408: if (body != null) {
409: f.s(body);
410: } else if (!outer.isInterface()
411: && !outer.isAnnotationTypeDeclaration()
412: && !mods.isAbstract() && !mods.isNative()) {
413: // Print an empty body for non-native, non-abstract methods
414: f.s(new JBlock());
415: } else {
416: f.p(';').nl();
417: }
418: }
419:
420: /**
421: * @return
422: * the current modifiers of this method.
423: * Always return non-null valid object.
424: */
425: public JMods mods() {
426: return mods;
427: }
428:
429: /**
430: * @deprecated use {@link #mods()}
431: */
432: public JMods getMods() {
433: return mods;
434: }
435:
436: protected JCodeModel owner() {
437: return outer.owner();
438: }
439: }
|