View Javadoc
1   /**
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Intalio, Inc.  For written permission,
18   *    please contact info@codehaus.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Intalio, Inc. Exolab is a registered
23   *    trademark of Intalio, Inc.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.codehaus.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 1999-2002 (C) Intalio, Inc. All Rights Reserved.
42   *
43   * $Id$
44   */
45  package org.codehaus.modello.plugin.java.javasource;
46  
47  /*
48   * Copyright (c) 2004, Codehaus.org
49   *
50   * Permission is hereby granted, free of charge, to any person obtaining a copy of
51   * this software and associated documentation files (the "Software"), to deal in
52   * the Software without restriction, including without limitation the rights to
53   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
54   * of the Software, and to permit persons to whom the Software is furnished to do
55   * so, subject to the following conditions:
56   *
57   * The above copyright notice and this permission notice shall be included in all
58   * copies or substantial portions of the Software.
59   *
60   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
64   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
65   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
66   * SOFTWARE.
67   */
68  
69  import java.util.ArrayList;
70  import java.util.Collections;
71  import java.util.Enumeration;
72  import java.util.Iterator;
73  import java.util.LinkedHashMap;
74  import java.util.List;
75  import java.util.Map;
76  
77  /**
78   * A class which holds information about the signature
79   * of a JMethod.
80   *
81   * The code in this package was modelled after the Java Reflection API
82   * as much as possible to reduce the learning curve.
83   *
84   * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
85   **/
86  public final class JMethodSignature {
87  
88      /**
89       * The set of modifiers for this JMethod
90       **/
91      private JModifiers modifiers = null;
92  
93      /**
94       * The return type of this Method
95       **/
96      private JType returnType = null;
97  
98      /**
99       * The name of this method
100      **/
101     private String name = null;
102 
103     /**
104      * The list of parameters of this JMethodSignature in declared
105      * order
106      **/
107     private Map<String, JParameter> params = null;
108 
109     /**
110      * The JavaDoc comment for this method signature.
111      **/
112     private JDocComment jdc = null;
113 
114     /**
115      * The exceptions that this method throws
116      **/
117     private List<JClass> exceptions = null;
118 
119     /**
120      * Creates a new method with the given name and return type.
121      * For "void" return types, simply pass in null as the returnType
122      *
123      * @param name, the method name. Must not be null.
124      * @param returnType the return type of the method. May be null.
125      **/
126     public JMethodSignature(String name, JType returnType) {
127 
128         if ((name == null) || (name.isEmpty())) {
129             String err = "The method name must not be null or zero-length";
130             throw new IllegalArgumentException(err);
131         }
132 
133         this.jdc = new JDocComment();
134         this.returnType = returnType;
135         this.name = name;
136         this.modifiers = new JModifiers();
137         this.params = new LinkedHashMap<>(3);
138         this.exceptions = new ArrayList<JClass>(1);
139     } // -- JMethodSignature
140 
141     /**
142      * Adds the given Exception to this JMethodSignature's throws clause.
143      *
144      * @param exp the JClass representing the Exception
145      **/
146     public void addException(JClass exp) {
147 
148         if (exp == null) return;
149 
150         // -- make sure exception is not already added
151         String expClassName = exp.getName();
152         for (JClass jClass : exceptions) {
153             if (expClassName.equals(jClass.getName())) return;
154         }
155         // -- add exception
156         exceptions.add(exp);
157 
158         // -- create comment
159         jdc.addDescriptor(JDocDescriptor.createExceptionDesc(expClassName, expClassName + " if any."));
160     } // -- addException
161 
162     /**
163      * Adds the given parameter to this JMethodSignature's list of
164      * parameters.
165      *
166      * @param parameter the parameter to add to the this Methods
167      * list of parameters.
168      * @throws java.lang.IllegalArgumentException when a parameter already
169      * exists for this Method with the same name as the new
170      * parameter.
171      **/
172     public void addParameter(JParameter parameter) throws IllegalArgumentException {
173 
174         if (parameter == null) return;
175 
176         String pName = parameter.getName();
177         // -- check current params
178         if (params.get(pName) != null) {
179             StringBuilder err = new StringBuilder();
180             err.append("A parameter already exists for this method, ");
181             err.append(name);
182             err.append(", with the name: ");
183             err.append(pName);
184             throw new IllegalArgumentException(err.toString());
185         }
186 
187         params.put(pName, parameter);
188 
189         // -- create comment
190         jdc.addDescriptor(JDocDescriptor.createParamDesc(pName, "a " + pName + " object."));
191     } // -- addParameter
192 
193     /**
194      * Returns the exceptions that this JMethodSignature lists
195      * in it's throws clause.
196      *
197      * @return the exceptions that this JMethodSignature lists
198      * in it's throws clause.
199      **/
200     public JClass[] getExceptions() {
201         return exceptions.toArray(new JClass[0]);
202     } // -- getExceptions
203 
204     /**
205      * Returns the JDocComment describing this JMethodSignature
206      *
207      * @return the JDocComment describing this JMethodSignature
208      **/
209     public JDocComment getJDocComment() {
210         return this.jdc;
211     } // -- getJDocComment
212 
213     /**
214      * Returns the modifiers for this JMethodSignature.
215      *
216      * @return the modifiers for this JMethodSignature.
217      **/
218     public JModifiers getModifiers() {
219         return this.modifiers;
220     } // -- getModifiers
221 
222     /**
223      * Returns the name of the method.
224      *
225      * @return the name of the method.
226      **/
227     public String getName() {
228         return this.name;
229     } // -- getName
230 
231     /**
232      * Returns the JParameter at the given index.
233      *
234      * @param index the index of the JParameter to return.
235      * @return the JParameter at the given index.
236      **/
237     public JParameter getParameter(int index) {
238         Iterator<Map.Entry<String, JParameter>> paramIter = params.entrySet().iterator();
239         Map.Entry<String, JParameter> selected = null;
240         for (int i = 0; i <= index; i++) {
241             selected = paramIter.next();
242         }
243         return selected.getValue();
244     } // -- getParameter
245 
246     /**
247      * Returns the set of JParameters for this JMethodSignature
248      * <BR>
249      * <B>Note:</B> the array is a copy, the params in the array
250      * are the actual references.
251      * @return the set of JParameters for this JMethod
252      **/
253     public synchronized JParameter[] getParameters() {
254         return params.values().toArray(new JParameter[0]);
255     } // -- getParameters
256 
257     /**
258      * Returns the JType that represents the return type for the
259      * method signature.
260      *
261      * @return the JType that represents the return type for the
262      * method signature.
263      **/
264     public JType getReturnType() {
265         return returnType;
266     } // -- getReturnType
267 
268     /**
269      * Sets the comment describing this JMethodSignature.
270      *
271      * @param comment the comment for this member
272      * @see #getJDocComment
273      **/
274     public void setComment(String comment) {
275         jdc.setComment(comment);
276     } // -- setComment
277 
278     /**
279      * Sets the JModifiers for this method signature.
280      *
281      * @param modifiers the JModifiers for this method signature.
282      **/
283     public void setModifiers(JModifiers modifiers) {
284         this.modifiers = modifiers.copy();
285         this.modifiers.setFinal(false);
286     } // -- setModifiers
287 
288     /**
289      * Prints the method signature. A semi-colon (end-of-statement
290      * terminator ';') will Not be printed.
291      *
292      * @param jsw the JSourceWriter to print to.
293      **/
294     public void print(JSourceWriter jsw) {
295         print(jsw, true);
296     } // -- print
297 
298     /**
299      * Prints the method signature. A semi-colon (end-of-statement
300      * terminator ';') will Not be printed.
301      *
302      * @param jsw the JSourceWriter to print to.
303      * @param printJavaDoc a boolean that when true prints the JDocComment
304      * associated with this method signature.
305      **/
306     public void print(JSourceWriter jsw, boolean printJavaDoc) {
307 
308         // ------------/
309         // - Java Doc -/
310         // ------------/
311 
312         if (printJavaDoc) jdc.print(jsw);
313 
314         // -----------------/
315         // - Method Source -/
316         // -----------------/
317 
318         jsw.write(modifiers.toString());
319         if (modifiers.toString().length() > 0) {
320             jsw.write(' ');
321         }
322         if (returnType != null) {
323             jsw.write(returnType);
324         } else jsw.write("void");
325         jsw.write(' ');
326         jsw.write(name);
327         jsw.write('(');
328 
329         // -- print parameters
330         if (params.size() > 0) {
331             jsw.write(' ');
332 
333             Enumeration<JParameter> paramEnum = Collections.enumeration(params.values());
334             jsw.write(paramEnum.nextElement());
335             while (paramEnum.hasMoreElements()) {
336                 jsw.write(", ");
337                 jsw.write(paramEnum.nextElement());
338             }
339 
340             jsw.write(' ');
341         }
342 
343         jsw.write(')');
344 
345         if (exceptions.size() > 0) {
346             jsw.writeln();
347             jsw.write("    throws ");
348             for (int i = 0; i < exceptions.size(); i++) {
349                 if (i > 0) jsw.write(", ");
350                 JClass jClass = exceptions.get(i);
351                 jsw.write(jClass.getName());
352             }
353         }
354     } // -- print
355 
356     /**
357      * Returns the String representation of this JMethod,
358      * which is the method prototype.
359      * @return the String representation of this JMethod, which
360      * is simply the method prototype
361      **/
362     public String toString() {
363 
364         StringBuilder sb = new StringBuilder();
365         if (returnType != null) {
366             sb.append(returnType);
367         } else sb.append("void");
368         sb.append(' ');
369         sb.append(name);
370         sb.append('(');
371 
372         // -- print parameters
373         if (params.size() > 0) {
374             sb.append(' ');
375 
376             Enumeration<JParameter> paramEnum = Collections.enumeration(params.values());
377             sb.append(paramEnum.nextElement().getType().getName());
378             while (paramEnum.hasMoreElements()) {
379                 sb.append(", ");
380                 sb.append(paramEnum.nextElement().getType().getName());
381             }
382 
383             sb.append(' ');
384         }
385 
386         sb.append(')');
387 
388         return sb.toString();
389     } // -- toString
390 
391     protected String[] getParameterClassNames() {
392         List<String> names = new ArrayList<String>(params.size());
393 
394         for (JParameter param : params.values()) {
395             JType jType = param.getType();
396             while (jType.isArray()) jType = jType.getComponentType();
397             if (!jType.isPrimitive()) {
398                 JClass jclass = (JClass) jType;
399                 names.add(jclass.getName());
400             }
401         }
402 
403         return names.toArray(new String[0]);
404     } // -- getParameterClassNames
405 } // -- JMethodSignature