package jde.wizards; import java.lang.reflect.Method; import java.util.Hashtable; import java.util.Enumeration; /** * Defines a factory for creating skeleton implementations of * Java interfaces. The factory can be invoked from the command line * or from another program. The factory can generate implementations for * multiple interfaces when invoked from the command line. * * Copyright (C) 1998-2003 Eric D. Friedman . All Rights Reserved. * Copyright (C) 1998-2002 Paul Kinnucan . All Rights Reserved. * * $Date: 2003/09/07 05:29:12 $ * * InterfaceFactory 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. * * InterfaceFactory 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. * * @author Eric D. Friedman * @author Paul Kinnucan * @version $Revision: 1.8 $ */ public class MethodFactory implements ClassRegistry { /** Unique storage of the classes to import */ protected Hashtable imports = new Hashtable(); /** A factory for generating parameter names */ protected NameFactory namefactory = null; /** * Constructs a default method factory. */ public MethodFactory() { this(new DefaultNameFactory()); } /** * Creates a method factory that uses the specified NameFactory * for generating parameter names * * @param factory Factory for generating parameter names */ public MethodFactory(NameFactory factory) { namefactory = factory; } /** * Sets the factory for generating parameter names. * * @param factory Factory for generating parameter names. */ public void setNameFactory(NameFactory factory) { namefactory = factory; } /** * Gets the factory used to generating parameter names for * methods generated by this interface factory. * * @return Name factory */ public NameFactory getNameFactory() { return namefactory; } /** * Gets a table containing the classes that must be imported to * implement an interface generated by this factory. * * @return Classes required to implement the current interface. */ public Hashtable getImports() { return imports; } /** * Return the fully qualified names of classes that * need to be imported to compile this interface * implementation. * * @return Class names as elisp list of strings. */ public String getImportsAsList() { StringBuffer res = new StringBuffer ("(list "); Enumeration i = imports.keys(); while (i.hasMoreElements()) { Class c = (Class) i.nextElement(); String className = c.getName(); // The class to be imported may be an inner // class. The interface implementation qualifies // the inner class name with the outer class name. // Thus the import statement need only reference the // outer class. Therefore remove the inner class // name, which is separated from the outer class name // by a $. int idx = className.indexOf('$'); if (idx > -1) { className = className.substring(0, idx); } res.append ("\"" + className + "\" "); } res.append (")"); return res.toString(); } /** * Registers a class that needs to be imported by the interface * implementation generated by this factory. Store the class in the * import hashtable if it passes the shouldImport test. * Arrays have to be handled differently here. * * @param register Imported class candidate */ public void registerImport(Class register) { if (register.isArray()) { try { Class cl = register; while (cl.isArray()) { cl = cl.getComponentType(); } register = cl; } catch (Throwable t) { throw new RuntimeException("Caught error walking up an Array object: " + t); } } if (shouldImport(register)) { imports.put(register, ""); } } /** * Tests whether a specified class needs to be imported by the interface * implementation generated by this factory. * We don't import primitives. * * @param c the Class object to be tested * @return true if the class should be imported */ private final boolean shouldImport(Class c) { return ! c.isPrimitive(); // import everything else } /** * Array of String names of numeric types. * */ private String[] numericTypesArray = {"char", "byte", "short", "int", "long", "float", "double"}; /** * List of names of numeric types. * */ private java.util.List numericTypesList = java.util.Arrays.asList(numericTypesArray); /** * Return a default body for the implementation of the method described * by sig. * * @param sig a Signature value * @return a String value */ protected String getDefaultBody (Signature sig) { Method m = sig.getMethod(); Class cl = m.getReturnType(); if (numericTypesList.contains(cl.getName())) { return "return 0;"; } else if (cl.getName().equals("boolean")) { return "return false;"; } else if (!cl.getName().equals("void")) { return "return null;"; } return ""; } /** * Get a Lisp form that generates a skeleton * implementation of a specified method. The * List form is of the form * * (jde-wiz-gen-method ... ) * * where jde-wiz-gen-method is a * function defined by the JDEE's jde-wiz package. * * @param sig a Signature value * @return a String value */ public String getMethodSkeletonExpression (Signature sig) { StringBuffer res = new StringBuffer(); res.append ("(jde-wiz-gen-method"); res.append (" \"" + sig.getModifiers() + "\""); res.append (" \"" + sig.getReturnBaseType() + "\""); res.append (" \"" + sig.getMethod().getName() + "\""); res.append (" \"" + sig.getParameters() + "\""); res.append (" \"" + sig.getExceptionList() + "\""); res.append (" \"" + getDefaultBody (sig) + "\")\n"); return res.toString(); } /** * Clears the import hashtables for this factory so it * can be re-used to process a new set of methods. */ public void flush() { imports.clear(); } /** * Print a string and flush the output buffer to * ensure that the string reaches Emacs immediately. * * @param s a String value */ public static void println(String s) { System.out.print(s + "\n"); System.out.flush(); } } // MethodFactory /* * $Log: MethodFactory.java,v $ * Revision 1.8 2003/09/07 05:29:12 paulk * Check for duplicate methods defined by different classes or interfaces. * Thanks to Martin Schwamberg. * * Revision 1.7 2002/12/04 07:16:37 paulk * Cosmetic changes. * * Revision 1.6 2002/12/04 07:06:47 paulk * Updated to handle implementation of interfaces that reference inner classes. * * Revision 1.5 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.4 2001/08/04 03:24:12 paulk * DefaultNameFactory.java * * Revision 1.3 2001/06/13 04:04:43 paulk * Now returns a valid return value for methods that return a value. * Thanks to "Craig McGeachie" . * */ // End of MethodFactory.java