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