Initial Commit
[packages] / xemacs-packages / jde / java / src / jde / wizards / MethodFactory.java
1 package jde.wizards;
2
3 import java.lang.reflect.Method;
4 import java.util.Hashtable;
5 import java.util.Enumeration;
6
7 /**
8  * Defines a factory for creating  skeleton implementations of 
9  * Java interfaces. The factory can be invoked from the command line
10  * or from another program. The factory can generate implementations for
11  * multiple interfaces when invoked from the command line.
12  *
13  * Copyright (C) 1998-2004 Eric D. Friedman . All Rights Reserved.
14  * Copyright (C) 1998-2002 Paul Kinnucan . All Rights Reserved.
15  *
16  * $Date: 2004/10/18 05:11:17 $ 
17  *
18  * InterfaceFactory is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License as
20  * published by the Free Software Foundation; either version 2, or (at
21  * your option) any later version.
22  *
23  * InterfaceFactory is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26  * General Public License for more details.
27  *
28  * To obtain a copy of the GNU General Public License write to the
29  * Free Software Foundation, Inc.,  59 Temple Place - Suite 330,
30  * Boston, MA 02111-1307, USA.  
31  *
32  * @author Eric D. Friedman
33  * @author Paul Kinnucan
34  * @version $Revision: 1.9 $
35  */
36 public class MethodFactory implements ClassRegistry {
37
38   /** Unique storage of the classes to import */
39   protected Hashtable imports = new Hashtable();
40
41   /** A factory for generating parameter names */
42   protected NameFactory namefactory = null;
43   
44   /**
45    * Constructs a default method factory.
46    */
47   public MethodFactory() {
48     this(new DefaultNameFactory());
49   }
50
51   /** 
52    * Creates a method factory that uses the specified NameFactory
53    * for generating parameter names 
54    *
55    * @param factory Factory for generating parameter names
56    */
57   public MethodFactory(NameFactory factory) {
58     namefactory = factory;
59   }
60
61   /** 
62    * Sets the factory for generating parameter names.
63    *
64    * @param factory Factory for generating parameter names.
65    */
66   public void setNameFactory(NameFactory factory) {
67     namefactory = factory;
68   }
69
70   /** 
71    * Gets the factory used to generating parameter names for 
72    * methods generated by this interface factory.
73    *
74    * @return Name factory
75    */
76   public NameFactory getNameFactory() {
77     return namefactory;
78   }
79
80   /** 
81    * Gets a table containing the classes that must be imported to
82    * implement an interface generated by this factory.
83    *
84    * @return Classes required to implement the current interface.
85    */
86   public Hashtable getImports() {
87     return imports;
88   }
89
90   /**
91    * Return the fully qualified names of classes that
92    * need to be imported to compile this interface
93    * implementation.
94    *
95    * @return Class names as elisp list of strings.
96    */
97   public String getImportsAsList() {
98     StringBuffer res = new StringBuffer ("(list ");
99     Enumeration i = imports.keys();
100     while (i.hasMoreElements()) {
101       Class c = (Class) i.nextElement();
102       String className = c.getName();
103       
104       // The class to be imported may be an inner
105       // class. The interface implementation qualifies
106       // the inner class name with the outer class name.
107       // Thus the import statement need only reference the
108       // outer class. Therefore remove the inner class
109       // name, which is separated from the outer class name
110       // by a $.
111       int idx = className.indexOf('$');
112       if (idx > -1) {
113         className = className.substring(0, idx);
114       }
115       
116       res.append ("\"" + className + "\" ");
117     }
118     res.append (")");
119     return res.toString();
120   }
121
122   /** 
123    * Registers a class that needs to be imported by the interface 
124    * implementation generated by this factory. Store the class in the 
125    * import hashtable if it passes the shouldImport test.  
126    * Arrays have to be handled differently here. 
127    *
128    * @param register Imported class candidate
129    */
130   public void registerImport(Class register) {
131     if (register.isArray()) {
132       try {
133         Class cl = register;
134         
135         while (cl.isArray()) {
136           cl = cl.getComponentType();
137         }
138         
139         register = cl;
140       } catch (Throwable t) {
141         throw new RuntimeException("Caught error walking up an Array object: "
142                                    + t);
143       }
144     }
145     
146     if (shouldImport(register)) {
147       imports.put(register, "");
148     }
149   }
150
151   /**
152    * Tests whether a specified class needs to be imported by the interface
153    * implementation generated by this factory.
154    * We don't import primitives.
155    * 
156    * @param c the <code>Class</code> object to be tested
157    * @return <code>true</code> if the class should be imported
158    */
159   private final boolean shouldImport(Class c) {        
160     return ! c.isPrimitive();                // import everything else
161   }
162
163
164   /**
165    * Array of <code>String</> names of numeric types.
166    *
167    */
168   private String[] numericTypesArray = {"char", "byte",
169                                         "short", "int", "long",
170                                         "float", "double"};
171   
172   /**
173    * List of names of numeric types.
174    *
175    */
176   private java.util.List numericTypesList =
177     java.util.Arrays.asList(numericTypesArray);
178
179   /**
180    * Return a default body for the implementation of the method described
181    * by <code>sig</code>.
182    *
183    * @param sig a <code>Signature</code> value
184    * @return a <code>String</code> value
185    */
186   protected String getDefaultBody (Signature sig) {
187     Method m = sig.getMethod();
188     Class cl = m.getReturnType();
189     if (numericTypesList.contains(cl.getName())) {
190       return "return 0;";
191     } else if (cl.getName().equals("boolean")) {
192       return "return false;";
193     } else if (!cl.getName().equals("void")) {
194       return "return null;";
195     }
196     return "";
197   }
198
199   /**
200    * Get a Lisp form that generates a skeleton
201    * implementation of a specified method. The
202    * List form is of the form
203    *
204    *   <code>(jde-wiz-gen-method ... )</code>
205    *
206    * where <code>jde-wiz-gen-method</code> is a
207    * function defined by the JDEE's jde-wiz package.
208    *
209    * @param sig a <code>Signature</code> value
210    * @return a <code>String</code> value
211    */
212   public String getMethodSkeletonExpression (Signature sig)  {
213     StringBuffer res = new StringBuffer();
214
215     res.append ("(jde-wiz-gen-method");
216     res.append (" \"" + sig.getModifiers() + "\"");
217     res.append (" \"" + sig.getReturnBaseType() + "\"");
218     res.append (" \"" + sig.getMethod().getName() + "\"");
219     res.append (" \"" + sig.getParameters() + "\"");
220     res.append (" \"" + sig.getExceptionList() + "\"");
221     res.append (" \"" + getDefaultBody (sig) + "\")\n");
222     return res.toString();
223   }
224
225   /** 
226    * Clears the import hashtables for this factory so it
227    * can be re-used to process a new set of methods.
228    */
229   public void flush() {
230     imports.clear();
231   }
232
233   /**
234    * Print a string and flush the output buffer to
235    * ensure that the string reaches Emacs immediately.
236    *
237    * @param s a <code>String</code> value
238    */
239   public static void println(String s) {
240     System.out.print(s + "\n");
241     System.out.flush();
242   }
243
244
245 } // MethodFactory
246
247 /*
248  * $Log: MethodFactory.java,v $
249  * Revision 1.9  2004/10/18 05:11:17  paulk
250  * Update copyright.
251  *
252  * Revision 1.8  2003/09/07 05:29:12  paulk
253  * Check for duplicate methods defined by different classes or interfaces.
254  * Thanks to Martin Schwamberg.
255  *
256  * Revision 1.7  2002/12/04 07:16:37  paulk
257  * Cosmetic changes.
258  *
259  * Revision 1.6  2002/12/04 07:06:47  paulk
260  * Updated to handle implementation of interfaces that reference inner classes.
261  *
262  * Revision 1.5  2002/05/14 06:38:44  paulk
263  * Enhances code generation wizards for implementing interfaces, abstract
264  * classes, etc., to use customizable templates to generate skeleton methods
265  * instead of hard-wired skeletons. Thanks to "Dr. Michael Lipp" <lipp@danet.de>
266  * for proposing and implementing this improvement.
267  *
268  * Revision 1.4  2001/08/04 03:24:12  paulk
269  * DefaultNameFactory.java
270  *
271  * Revision 1.3  2001/06/13 04:04:43  paulk
272  * Now returns a valid return value for methods that return a value. 
273  * Thanks to "Craig McGeachie" <craig@rhe.com.au>.
274  *
275  */
276
277 // End of MethodFactory.java