Initial Commit
[packages] / xemacs-packages / jde / java / src / jde / wizards / MethodOverrideFactory.java
1 /*
2  * Copyright (c) Paul Kinnucan 1998, 1999, 2000, 2001. All Rights Reserved.
3  *
4  * $Revision: 1.14 $ 
5  * $Date: 2004/03/18 05:28:36 $ 
6  *
7  * MethodOverrideFactory is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2, or (at
10  * your option) any later version.
11  *
12  * MethodOverrideFactory is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * To obtain a copy of the GNU General Public License write to the
18  * Free Software Foundation, Inc.,  59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.  
20  */
21
22 package jde.wizards;
23
24 import java.lang.reflect.Method;
25 import java.lang.reflect.Modifier;
26 import java.io.PrintWriter;
27 import java.util.Hashtable;
28 import java.util.Vector;
29 import java.util.Enumeration;
30
31 import jde.util.DynamicClassLoader;
32
33 /**
34  * Defines a factory for creating an override of a method defined in a 
35  * superclass.
36  *
37  * @author Paul Kinnucan
38  * @version $Revision: 1.14 $
39  */
40
41 public class MethodOverrideFactory extends MethodFactory
42 {
43
44   /** The factory. */
45   static MethodOverrideFactory overrideFactory;
46
47   Vector candidates = new Vector();
48
49   String baseClassName;
50
51   String methodName;
52   
53   public MethodOverrideFactory() {}
54
55   /** 
56    * Creates a MethodOverrideFactory that uses the specified NameFactory
57    * for generating parameter names 
58    *
59    * @param factory Factory for generating parameter names
60    */
61   public MethodOverrideFactory(NameFactory factory)
62   {
63     super(factory);
64   }
65
66   /**
67    * Return a <code>Vector</code> containing all <code>Method</code>
68    * objects for the argument class and methodName which can be
69    * overridden.
70    *
71    * @param cl the <code>Class</code> for which all methods that can
72    * be overridden will be returned.
73    * @param methodName the name of the Method to be returned.
74    * @return a <code>Vector</code> of <code>Method</code> objects.
75    */
76   private Vector getOverrideableMethods(Class cl, String methodName) {
77     
78     Vector m = new Vector();
79     Class baseClass = cl;
80
81     while (baseClass != null) {
82       Method[] methods = baseClass.getDeclaredMethods();
83       for (int i = 0; i < methods.length; i++) {
84         if (methods[i].getName().equals(methodName)) {
85           int methodModifiers = methods[i].getModifiers();
86           if ((Modifier.isPublic(methodModifiers) ||
87                Modifier.isProtected(methodModifiers)) &&
88               !Modifier.isFinal(methodModifiers))
89             m.addElement(methods[i]);
90         }
91       }
92       baseClass = baseClass.getSuperclass();
93     }
94
95     return m;
96   }
97
98
99
100   /**
101    * Get a list of signatures for all methods of a specified name defined
102    * or inherited by a specified class. The signatures returned by this method
103    * including only the types of the method parameters as the generated names
104    * are unnecessary for signature matching. This method prints the signature
105    * list to standard out as a Lisp list form.
106    *
107    * @param baseClassName a <code>String</code> value that specifies the name of
108    * the class that defines or inherits the methods whose signatures are to be
109    * returned.
110    * @param methodName a <code>String</code> value that specifies the name of the
111    * methods whose signatures are to be returned.
112    */
113   public static void getCandidateSignatures(String baseClassName, String methodName) {
114
115     if (overrideFactory == null) 
116       overrideFactory = new MethodOverrideFactory();
117     else
118       overrideFactory.flush();
119
120     overrideFactory.baseClassName = baseClassName;
121     overrideFactory.methodName = methodName;
122
123     try {
124
125       DynamicClassLoader dcl = new DynamicClassLoader();
126       Vector methods = overrideFactory.getOverrideableMethods
127           (dcl.loadClass(baseClassName), methodName);
128
129       for (int i = 0; i < methods.size(); ++i) {
130         Method m = (Method) methods.elementAt(i);
131         Signature s = new Signature(m, overrideFactory);
132         boolean containsSignature = false;
133         for (int j = 0; j < overrideFactory.candidates.size(); ++j) 
134           if (s.equals(overrideFactory.candidates.elementAt(j))) {
135             containsSignature = true;
136             break;
137           }
138         if (! containsSignature) 
139           overrideFactory.candidates.addElement(s);
140       }
141
142       int n = overrideFactory.candidates.size();
143
144       if (n > 0) {
145         String res = "(list ";
146         for (int i = 0; i < n; ++i) {
147           Signature s = (Signature) overrideFactory.candidates.elementAt(i);
148           s.setTruncating(false);
149           String p = s.getParameters(s.getMethod().getParameterTypes(), false);
150           s.setTruncating(true);
151           res = res + "\"" + methodName + "(" + p +  ")\" ";
152         }
153         res = res + ")";
154         println(res);
155       }
156       else
157         println("(error \"Could not find any method named " +
158                 methodName + " in " + baseClassName + 
159                 " or any of its superclasses.\")");
160
161     }
162     catch (ClassNotFoundException ee) {
163       println("(error \"Could not find class " + 
164               baseClassName + "\")");
165     }
166
167   }
168
169   public static void getMethodSkeletonExpression(int variant) {
170     Signature s = (Signature) overrideFactory.candidates.elementAt(variant);
171     String skel = overrideFactory.getMethodSkeletonExpression(s);
172     println(skel);
173
174     // Register imported classes.
175     overrideFactory.imports.clear();
176     Method m = s.getMethod();
177
178     Class[] types = m.getParameterTypes();
179     for (int i = 0; i < types.length; ++i)
180       overrideFactory.registerImport(types[i]);
181
182     types = m.getExceptionTypes();
183     for (int i = 0; i < types.length; ++i)
184       overrideFactory.registerImport(types[i]);
185
186     overrideFactory.registerImport(m.getReturnType());
187
188   }
189
190   public static void getImportedClasses() {
191     println(overrideFactory.getImportsAsList());
192   }
193
194   /** 
195    * Clears the import and candidate hashtables for this factory so they
196    * can be re-used to process a new set of interfaces.
197    */
198   public void flush()
199   {
200     super.flush();
201     candidates.removeAllElements();
202   }
203
204   /**
205    * Gets the candidate signatures for the class and method
206    * passed as arguments on the command line.
207    *
208    * @param args a <code>String[]</code> value
209    */
210   public static void main (String[] args) {
211
212     String className = "javax.swing.AbstractAction";
213     String methodName = "actionPerformed";
214     
215     if (args.length == 2) {
216
217       className = args[0];
218       methodName = args[1];
219
220     }
221
222     System.out.println("Class: " + className);
223     System.out.println("Method: " + methodName);
224
225     getCandidateSignatures(className, methodName);
226
227
228     
229      
230   } // end of main ()
231   
232
233
234 } // MethodOverrideFactory
235
236
237 /*
238  * $Log: MethodOverrideFactory.java,v $
239  * Revision 1.14  2004/03/18 05:28:36  paulk
240  * Now overrides protected as well as public methods and does not override final methods.
241  * Thanks to David Esterkin <desterkin@sciquest.com>.
242  *
243  * Revision 1.13  2004/02/19 06:27:44  paulk
244  * Fixes bug that caused the override wizard to fail to match the method designated by the user to be overriden. Thanks to David Esterkin <desterkin@sciquest.com>.
245  *
246  * Revision 1.12  2003/10/20 05:39:24  paulk
247  * Update the getMethods() method to get all the methods of a class
248  * whether declared by the class or inherited by the class, including
249  * abstract methods.
250  *
251  * Revision 1.11  2003/07/23 04:40:07  paulk
252  * main method now accepts class and method name for testing purpose. Added comment
253  * noting the change in behavior of getDeclaredMethods from JDK 1.3 to JDK 1.4.
254  *
255  * Revision 1.10  2003/05/04 05:50:52  paulk
256  * Document the getCandidateSignatures method.
257  *
258  * Revision 1.9  2003/05/04 05:42:22  paulk
259  * Change getCandidateSignatures to return signatures with parameter
260  * types only (i.e., without parameter nams). This fixes a
261  * signature-matching bug on the Lisp side where the method override
262  * wizard was inadvertently trying to matching a signature without
263  * parameter names to a list of signatures with parameter names.
264  *
265  * Revision 1.8  2002/06/03 18:12:27  mnl
266  * Use DynamicClassLoader instead of simple Class.forName to avoid class
267  * resolving (linking).
268  *
269  * Revision 1.7  2002/05/14 06:38:44  paulk
270  * Enhances code generation wizards for implementing interfaces, abstract
271  * classes, etc., to use customizable templates to generate skeleton methods
272  * instead of hard-wired skeletons. Thanks to "Dr. Michael Lipp" <lipp@danet.de>
273  * for proposing and implementing this improvement.
274  *
275  * Revision 1.6  2001/08/14 05:15:03  paulk
276  * Miscellaneous updates.
277  *
278  * Revision 1.5  2001/08/11 06:52:31  paulk
279  * Adds javadoc parameter to getMethodSkeleton. Thanks to Javier Lopez.
280  *
281  *
282  */
283
284 // End of MethodOverrideFactory.java