Initial Commit
[packages] / xemacs-packages / jde / java / src / jde / wizards / Signature.java
1 /*
2  * Copyright (c) Eric D. Friedman 1998. All Rights Reserved.
3  * Copyright (c) Paul Kinnucan 1998. All Rights Reserved.
4  *
5  * $Revision: 1.11 $ 
6  * $Date: 2002/12/04 07:06:46 $ 
7  *
8  * InterfaceFactory is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2, or (at
11  * your option) any later version.
12  *
13  * InterfaceFactory is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * To obtain a copy of the GNU General Public License write to the
19  * Free Software Foundation, Inc.,  59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.  
21  */
22
23 package jde.wizards;
24
25 import java.lang.reflect.Method;
26 import java.lang.reflect.Modifier;
27
28 /**
29  * Defines a method signature.
30  *
31  * @author Eric D. Friedman
32  * @version $Revision: 1.11 $
33  */
34
35 public class Signature {
36   
37   /** 
38    * The method represented by this signature 
39   */
40   private Method method;
41
42   /** 
43    * the parameters in this signature 
44    */
45   private Class[] parameters;
46
47   /** 
48    * the exceptions thrown by this signature 
49    */
50   private Class[] exceptions;
51
52   /** 
53    * the return value 
54    */
55   private Class returnValue;
56
57   /** 
58    * The Class that declared this signature
59    */
60   private Class declaring;
61
62   /**
63    * the InterfaceFactory processing this signature 
64    */
65   private ClassRegistry registry;
66
67   /**
68    * Toggles truncation of package information in signatures 
69    */
70   private boolean truncate;
71
72   /**
73    * Toggles generation of see
74    */
75   private boolean see;
76
77   /** 
78    * Creates a signature for the specified method and register
79    * its types with the specified registry (which may be null).
80    * Removes package info from generated signatures.
81    *
82    * @param meth Method represented by this signature
83    * @param aregistry Registry containing this signature
84    */
85   public Signature (Method meth, ClassRegistry aregistry) {
86     this(meth, aregistry, true);
87   }
88
89   /** 
90    * Creates a signature for the specified method and register its
91    * types with the specified registry (which may be null).
92    *
93    * @param meth Method represented by thi signature
94    * @param aregistry Registry containing this signature
95    * @param truncate toggles removal of package info from generated signatures 
96    */
97   public Signature (Method meth, ClassRegistry aregistry, boolean truncate) {
98     this(meth, aregistry, truncate, false);
99   }
100
101   /** 
102    * Creates a signature for the specified method and register its
103    * types with the specified registry (which may be null).
104    *
105    * @param meth Method represented by thi signature
106    * @param aregistry Registry containing this signature
107    * @param truncate toggles removal of package info from generated signatures 
108    * @param see Class to link the see section to or null, if no see
109    * section should be created
110    */
111   public Signature (Method meth, ClassRegistry aregistry, boolean truncate,
112                     boolean see) {
113     this.method   = meth;
114     this.registry = aregistry;
115     this.truncate = truncate;
116     this.see = see;
117     
118     parameters   = method.getParameterTypes();
119     exceptions   = method.getExceptionTypes();
120     returnValue = method.getReturnType();
121     declaring    = method.getDeclaringClass();
122
123     register();
124   }
125
126   /** 
127    * Toggles truncation of package info .
128    * 
129    * @param b Truncation toggle
130    */
131   public void setTruncating(boolean b) {
132     truncate = b;
133   }
134
135   /** 
136    * Sets the registry used to register this signature's types.
137    * 
138    * @param registry Registry used to register this signature's type.
139    */
140   public void setRegistry(ClassRegistry registry) {
141     this.registry = registry;
142   }
143
144   /** 
145    * Gets the class that declared the method represented by this signature.
146    *
147    * @return The class this method was declared in 
148    */
149   public Class getDeclaringClass () {
150     return declaring;
151   }
152
153   /** 
154    * Generates a javadoc string for this signature.
155    * 
156    * @return A javadoc for this method
157    */
158   public String toJavaDoc() {
159     NameFactory factory = registry.getNameFactory();
160     StringBuffer buf = new StringBuffer("/**\n *\n *");
161     
162     for (int i = 0; i < parameters.length; i++) {
163       buf.append(" @param "
164                  + factory.getParameterName(this, i)
165                  + " <description>\n *");
166     }
167
168     if (!"void".equals(returnValue.getName())) {
169       buf.append(" @return <description>" + "\n *");
170     }
171     
172     for (int i = 0; i < exceptions.length; i++) {
173       buf.append(" @exception " + exceptions[i].getName()
174                  + " <description>\n *");
175     }
176     
177     if (see) {
178       buf.append(" @see ");
179       buf.append(method.getDeclaringClass().getName());
180       buf.append('#');
181       buf.append(method.getName());
182       buf.append('(');
183       buf.append(getParameters(method.getParameterTypes(), false));
184       buf.append(')');
185       buf.append("\n *");
186     }
187     
188     buf.append("/");
189     
190     return buf.toString();
191   }
192
193   /** 
194    * Gets the signature as a string.
195    *
196    * @return Signature of this method.
197    */
198   public String toString() {
199     String m    = getModifiers();
200     String r    = baseName(returnValue);
201     String meth = method.getName();
202
203     String p    = getParameters(parameters);
204     String e    = getExceptions(exceptions);
205
206     return m + " " + r + " " + meth + "(" + p + ")" + e;
207   }
208
209   /**
210    * Describe <code>paramsEqual</code> method here.
211    *
212    * @param p a <code>Class[]</code> value
213    * @return a <code>boolean</code> value
214    */
215   public boolean paramsEqual(Class[] p) {
216     int n = parameters.length;
217     boolean res = (p.length == n);
218     if (res) {
219       for (int i = 0; i < n; ++i) {
220         if (!p[i].equals(parameters[i])) {
221           res = false;
222           break;
223        }
224       }
225     }
226     return res;
227   }
228
229   /**
230    * Tests whether a given object equals this signature.
231    * The object is considered equal if it is a signature
232    * and it has the same method name and parameter list.
233    *
234    * @param compare Test object
235    * @return <code>true</code> if the test object equals this signature.
236    */
237   public boolean equals(Object compare) {
238     if (compare instanceof Signature) {
239       Signature sig = (Signature) compare;
240       return method.getName().equals(sig.getMethod().getName())
241         && paramsEqual(sig.getMethod().getParameterTypes());
242     }
243     return false;
244   }
245
246   /**
247    * Gets the method of which this is a signature.
248    *
249    * @return Method of which this is a signature.
250    */
251   public Method getMethod() {
252     return method;
253   }
254     
255   /** 
256    *  Computes the basename of the specified class.  This returns
257    *  "Object" from "java.lang.Object."  It returns the "single"
258    *  form of an Array object.
259    *
260    *  In the case of inner classes, the base name includes
261    *  the outer class name, e.g.,
262    *
263    *    mypackage.OuterClass$InnerClass
264    *
265    *  is returned as
266    *
267    *    OuterClass.InnerClass
268    *
269    * @param type Class whose basename is required
270    * 
271    * @return basename
272    */
273   public final String baseName(Class type) {
274     String name = null;
275     if (type.isArray()) {
276       try {
277         
278         Class cl       = type;
279         int dimensions = 0;
280         
281         while (cl.isArray()) {
282           cl = cl.getComponentType();
283           dimensions++;
284         }
285         
286         StringBuffer sb = new StringBuffer();
287         sb.append(cl.getName());
288         
289         for (int i = 0; i < dimensions; i++) {
290           sb.append("[]");
291         }
292         
293         name = sb.toString();
294       } catch (Throwable e) {
295         name = type.getName();
296       }
297     } else {
298          name = type.getName();    
299     }
300     
301
302     // If truncate flag is true, remove
303     // the package name from the class
304     // name, e.g.,
305     //
306     //  java.lang.Object
307     //
308     // becomes simply Object.
309     if (truncate) {
310       int idx = name.lastIndexOf('.');
311       
312       if (idx > -1) {
313         name = name.substring(idx + 1);
314       }
315     }  
316
317     // If type is an inner class, its base
318     // name includes the outer class name,
319     // with a $ separating the inner from
320     // the outer name, e.g.,
321     //
322     //   OuterClass$InnerClass
323     //   
324     // Replace the $ with  a . (period).
325     name =  name.replace('$', '.');
326
327     return name;
328   }
329
330   /** 
331    * Make a list of this method's exceptions separated by commata.
332    * 
333    * @return Exceptions thrown by this method.
334    */
335   public final String getExceptionList() {
336     return getExceptionList(exceptions);
337   }
338
339
340   
341   /**
342    * Make a list of all given exceptions separated by commas.
343    *
344    * @param except Array of exception types
345    * @return Comma-separated list of exceptions
346    */
347   public final String getExceptionList(Class[] except) {
348     
349     if ((null == except) || (except.length == 0)) {
350       return "";
351     }
352
353     StringBuffer buf = new StringBuffer();
354     
355     for (int i = 0; i < except.length; i++) {
356       String type = baseName(except[i]);
357
358       buf.append(type);
359       if (i < except.length - 1) {
360         buf.append(", ");
361       }
362       
363     }
364     
365     return buf.toString();
366   }
367
368   /** 
369    * Gets a throw clause listing the exceptions thrown by this method.
370    * 
371    * @param except Vector of exceptions
372    *
373    * @return Exceptions thrown by this method.
374    */
375   private final String getExceptions(Class[] except) {
376     String res = getExceptionList (except);
377     
378     if (res.length() == 0) {
379       return res;
380     }
381     
382     return " throws " + res;
383   }
384
385   /** 
386    * Gets a parameter list for this method; parameters are named
387    * by the NameFactory whose default implementation uses param1
388    * .. paramn 
389    *
390    * @return Parameter list in string form
391    */
392   public final String getParameters () {
393     return getParameters(parameters, true);
394   }
395
396   /** 
397    * Gets a parameter list for this method; parameters are named
398    * by the NameFactory whose default implementation uses param1
399    * .. paramn 
400    *
401    * @param params Parameters of this method
402    *
403    * @return Parameter list in string form
404    */
405   public final String getParameters (Class[] params) {
406     return getParameters(params, true);
407   }
408
409   /** 
410    * Gets a parameter list for this method; parameters are named
411    * by the NameFactory whose default implementation uses param1
412    * .. paramn 
413    *
414    * @param params Parameters of this method
415    * @param withName toggles parameter names
416    *
417    * @return Parameter list in string form
418    */
419   public final String getParameters (Class[] params, boolean withName) {
420     
421     if ((null == params) || (params.length == 0)) {
422       return "";
423     }
424     
425     StringBuffer buf = new StringBuffer();
426     NameFactory factory = registry.getNameFactory();
427
428     for (int i = 0; i < params.length; i++) {
429       String type = baseName(params[i]);
430       String name = factory.getParameterName(this, i);
431
432       buf.append(type);
433       if (withName) {
434         buf.append(' ');
435         buf.append(name);
436       }
437
438       if (i < params.length - 1) {
439         buf.append(", ");
440       }
441       
442     }
443
444     return buf.toString();
445   }
446
447   /**
448    * Get the names of all parameters of this signature,
449    * without typenames.
450    *
451    * @return te parameter names seperated by comma.
452    */
453   public final String getParameterNames () {
454     return getParameterNames(method.getParameterTypes());
455   }    
456
457   /** 
458    * Gets a list of parameter names for this method; parameters are
459    * named by the NameFactory whose default implementation uses param1
460    * .. paramn.  Class type names are not included in the result
461    * Contributed by Charles Hart <cfhart@Z-TEL.com>
462    *
463    * @param params Parameters of this method
464    *
465    * @return Parameter list in string form */
466   public final String getParameterNames (Class[] params) {
467     
468     if ((null == params) || (params.length == 0)) {
469       return "";
470     }
471     
472     StringBuffer buf = new StringBuffer();
473     NameFactory factory = registry.getNameFactory();
474
475     for (int i = 0; i < params.length; i++) {
476       String type = baseName(params[i]);
477       String name = factory.getParameterName(this, i);
478
479       buf.append(name);
480
481       if (i < params.length - 1) {
482         buf.append(", ");
483       }
484       
485     }
486
487     return buf.toString();
488   }
489
490   /**
491    * Gets list of modifiers for this method.
492    * Interface methods are always public and may be synchronized 
493    *
494    * @return a <code>String</code> containing a list of modifiers
495    */
496   public final String getModifiers () {
497     StringBuffer buf = new StringBuffer("public");
498     int mod = method.getModifiers();
499
500     if (Modifier.isSynchronized(mod)) {
501       buf.append(" synchronized");
502     }
503     
504     return buf.toString();
505   }
506
507   /** 
508    * Gets the base type of the return value.
509    *
510    * @return Base type of return value.
511    */
512   public String getReturnBaseType () {
513     return baseName(returnValue);
514   }
515
516   /** 
517    * Register this Signature's types with the SignatureRegistry
518    */
519   private final void register() {
520     if (null != registry) {
521       registry.registerImport(declaring);
522       registry.registerImport(returnValue);
523     
524       for (int i = 0; i < parameters.length; i++) {
525         registry.registerImport(parameters[i]);
526       }
527
528       for (int i = 0; i < exceptions.length; i++) {
529         registry.registerImport(exceptions[i]);
530       }
531     }
532   }
533
534 } // end of Signature class
535
536 /*
537  * $Log: Signature.java,v $
538  * Revision 1.11  2002/12/04 07:06:46  paulk
539  * Updated to handle implementation of interfaces that reference inner classes.
540  *
541  * Revision 1.10  2002/06/06 05:12:44  paulk
542  * DefaultNameFactory now generates meaningful method parameter names based
543  * on the parameter type or the method name. Thanks to Ole Arndt.
544  *
545  * Revision 1.9  2002/05/14 06:38:43  paulk
546  * Enhances code generation wizards for implementing interfaces, abstract
547  * classes, etc., to use customizable templates to generate skeleton methods
548  * instead of hard-wired skeletons. Thanks to "Dr. Michael Lipp" <lipp@danet.de>
549  * for proposing and implementing this improvement.
550  *
551  * Revision 1.8  2001/09/16 16:24:13  paulk
552  * Corrected bug in the constructor Signature (Method meth, ClassRegistry aregistry,
553  * boolean truncate).
554  * Thanks to petter.mahlen@chello.se.
555  *
556  * Revision 1.7  2000/08/03 04:28:41  paulk
557  * Add support for generating a see secton in the Javadoc comment for a method.
558  * Thanks to raffael.herzog@comartis.com
559  *
560  * Revision 1.6  2000/07/14 05:26:56  paulk
561  * Adds support for delegation wizard.
562  *
563  */
564
565 // End of Signature.java