/* * Copyright (c) Paul Kinnucan 1998, 1999, 2000, 2001. All Rights Reserved. * * $Revision: 1.11 $ * $Date: 2003/07/23 04:40:07 $ * * MethodOverrideFactory is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2, or (at * your option) any later version. * * MethodOverrideFactory is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * To obtain a copy of the GNU General Public License write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package jde.wizards; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.io.PrintWriter; import java.util.Hashtable; import java.util.Vector; import java.util.Enumeration; import jde.util.DynamicClassLoader; /** * Defines a factory for creating an override of a method defined in a * superclass. * * @author Paul Kinnucan * @version $Revision: 1.11 $ */ public class MethodOverrideFactory extends MethodFactory { /** The factory. */ static MethodOverrideFactory overrideFactory; Vector candidates = new Vector(); String baseClassName; String methodName; public MethodOverrideFactory() {} /** * Creates a MethodOverrideFactory that uses the specified NameFactory * for generating parameter names * * @param factory Factory for generating parameter names */ public MethodOverrideFactory(NameFactory factory) { super(factory); } public Vector getMethods(Class cl, String methodName) { /* * Note that before JDK 1.4, getDeclaredMethods() returned * methods declared by an interface implemented by a class * including methods defined by the interface but * not implemented by the class. Starting with JDK 1.4, * getDeclaredMethods() returns only the methods actually * declared by a class. An example that illustrates the difference * in behavior is AbstractAction. JDK 1.3 returns actionPerformed * as one of the methods declared by AbstractAction even though * AbstractAction does not actually implement this method. */ Method [] methods = cl.getDeclaredMethods(); Vector m = new Vector(); for (int i = 0; i < methods.length; ++i) { if (methods[i].getName().equals(methodName)) m.addElement(methods[i]); } return m; } /** * Get a list of signatures for all methods of a specified name defined * or inherited by a specified class. The signatures returned by this method * including only the types of the method parameters as the generated names * are unnecessary for signature matching. This method prints the signature * list to standard out as a Lisp list form. * * @param baseClassName a String value that specifies the name of * the class that defines or inherits the methods whose signatures are to be * returned. * @param methodName a String value that specifies the name of the * methods whose signatures are to be returned. */ public static void getCandidateSignatures(String baseClassName, String methodName) { if (overrideFactory == null) overrideFactory = new MethodOverrideFactory(); else overrideFactory.flush(); overrideFactory.baseClassName = baseClassName; overrideFactory.methodName = methodName; try { DynamicClassLoader dcl = new DynamicClassLoader(); Class baseClass = dcl.loadClass(baseClassName); while (baseClass != null) { Vector methods = overrideFactory.getMethods(baseClass, methodName); int n = methods.size(); if (n > 0) { for (int i = 0; i < n; ++i) { Method m = (Method) methods.elementAt(i); Signature s = new Signature(m, overrideFactory); boolean containsSignature = false; for (int j = 0; j < overrideFactory.candidates.size(); ++j) if (s.equals(overrideFactory.candidates.elementAt(j))) { containsSignature = true; break; } if (! containsSignature) overrideFactory.candidates.addElement(s); } } baseClass = baseClass.getSuperclass(); } int n = overrideFactory.candidates.size(); if (n > 0) { String res = "(list "; for (int i = 0; i < n; ++i) { Signature s = (Signature) overrideFactory.candidates.elementAt(i); String p = s.getParameters(s.getMethod().getParameterTypes(), false); res = res + "\"" + methodName + "(" + p + ")\" "; } res = res + ")"; println(res); } else println("(error \"Could not find any method named " + methodName + " in " + baseClassName + " or any of its superclasses.\")"); } catch (ClassNotFoundException ee) { println("(error \"Could not find class " + baseClassName + "\")"); } } public static void getMethodSkeletonExpression(int variant) { Signature s = (Signature) overrideFactory.candidates.elementAt(variant); String skel = overrideFactory.getMethodSkeletonExpression(s); println(skel); // Register imported classes. overrideFactory.imports.clear(); Method m = s.getMethod(); Class[] types = m.getParameterTypes(); for (int i = 0; i < types.length; ++i) overrideFactory.registerImport(types[i]); types = m.getExceptionTypes(); for (int i = 0; i < types.length; ++i) overrideFactory.registerImport(types[i]); overrideFactory.registerImport(m.getReturnType()); } public static void getImportedClasses() { println(overrideFactory.getImportsAsList()); } /** * Clears the import and candidate hashtables for this factory so they * can be re-used to process a new set of interfaces. */ public void flush() { super.flush(); candidates.removeAllElements(); } /** * Gets the candidate signatures for the class and method * passed as arguments on the command line. * * @param args a String[] value */ public static void main (String[] args) { String className = "javax.swing.AbstractAction"; String methodName = "actionPerformed"; if (args.length == 2) { className = args[0]; methodName = args[1]; } System.out.println("Class: " + className); System.out.println("Method: " + methodName); getCandidateSignatures(className, methodName); } // end of main () } // MethodOverrideFactory /* * $Log: MethodOverrideFactory.java,v $ * Revision 1.11 2003/07/23 04:40:07 paulk * main method now accepts class and method name for testing purpose. Added comment * noting the change in behavior of getDeclaredMethods from JDK 1.3 to JDK 1.4. * * Revision 1.10 2003/05/04 05:50:52 paulk * Document the getCandidateSignatures method. * * Revision 1.9 2003/05/04 05:42:22 paulk * Change getCandidateSignatures to return signatures with parameter * types only (i.e., without parameter nams). This fixes a * signature-matching bug on the Lisp side where the method override * wizard was inadvertently trying to matching a signature without * parameter names to a list of signatures with parameter names. * * Revision 1.8 2002/06/03 18:12:27 mnl * Use DynamicClassLoader instead of simple Class.forName to avoid class * resolving (linking). * * Revision 1.7 2002/05/14 06:38:44 paulk * Enhances code generation wizards for implementing interfaces, abstract * classes, etc., to use customizable templates to generate skeleton methods * instead of hard-wired skeletons. Thanks to "Dr. Michael Lipp" * for proposing and implementing this improvement. * * Revision 1.6 2001/08/14 05:15:03 paulk * Miscellaneous updates. * * Revision 1.5 2001/08/11 06:52:31 paulk * Adds javadoc parameter to getMethodSkeleton. Thanks to Javier Lopez. * * */ // End of MethodOverrideFactory.java