Initial Commit
[packages] / xemacs-packages / jde / java / src / jde / wizards / DefaultNameFactory.java
1 package jde.wizards;
2
3 import java.beans.Introspector;
4 import java.lang.reflect.Method;
5
6 /**
7  * Defines a default parameter name factory for the InterfaceFactory.
8  * Tries hard to find a meaningfull name.
9  *
10  * Copyright (c) Eric D. Friedman 1998. All Rights Reserved.
11  * Copyright (c) Paul Kinnucan 1998. All Rights Reserved.
12  *
13  * $Date: 2002/12/12 05:15:48 $ 
14  *
15  * InterfaceFactory is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License as
17  * published by the Free Software Foundation; either version 2, or (at
18  * your option) any later version.
19  *
20  * InterfaceFactory is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * General Public License for more details.
24  *
25  * To obtain a copy of the GNU General Public License write to the
26  * Free Software Foundation, Inc.,  59 Temple Place - Suite 330,
27  * Boston, MA 02111-1307, USA.  
28  *
29  * @author Eric D. Friedman
30  * @author Paul Kinnucan
31  * @author Ole Arndt
32  * @version $Revision: 1.6 $
33  */
34
35 public class DefaultNameFactory implements NameFactory {
36
37   /**
38    * Make up a name for the nth parameter of a method.
39    * First this method tries to recognize bean methods, if the method is named
40    * "setName" and has one parameter, the parameter returned is the
41    * lowercased method name with "set" stripped: "name".
42    *
43    * Index Bean Properties are methods starting with "set" and having two
44    * parameters, the first one of which is an int, or methods starting with
45    * "get" and having only one int parameter. In both cases the first
46    * parameter is given the name "index". 
47    *     
48    * Examples:
49    *
50    *   void setName(String name);
51    *   void setNames(String[] names);
52    *   void setName(int index, String name);
53    *   String getName(int index);
54    *
55    * For other method names the parameters are named according to their
56    * type. 
57    *
58    * Primitive types are named after the following mapping (now
59    * hardcoded, can perhaps be made configurable):
60    *
61    *   boolean: flag
62    *   byte: b
63    *   char: c
64    *   short: s
65    *   int: n
66    *   long: l
67    *   float: f
68    *   double: d
69    * 
70    * Array types are named like their base type with the String "Array"
71    * appended, so a "byte[]" parameter will be named "byteArray":
72    *
73    *    void fill(char[] charArray);
74    *
75    * All other parameters will be named according to their type's unqualified
76    * lowercased classname:
77    *
78    *    void actionPerformed(ActionEvent actionEvent);
79    *
80    * To avoid any name clashes, the parameters will have a number appended
81    * if there is another parameter of the same type in the methods
82    * parameterlist:
83    *
84    *   void write(byte[] byteArray, int n, int n1);
85    *   void put(String string, String string1);
86    *
87    * @param sig  - signature of the declaring method
88    * @param num     - the parameter number whose name we want.
89    * @return a name for the n'th parameter of the method.
90    */
91   public String getParameterName(Signature sig, int num) {
92     Method method = sig.getMethod();
93     String  methodName = method.getName();
94     Class[] parameters = method.getParameterTypes();
95     Class   type = parameters[num];
96
97     // To handle inner-class .class files
98     String  className = type.getName().replace('$', '.'); 
99
100     // special handling for bean methods
101     if (methodName.length() > 3) {
102       if (methodName.startsWith("set")) {
103         if (parameters.length == 2) {
104           // an indexed propery setter
105           if (num == 1 && className.equals("int")) {
106             return "index";
107           }
108
109           if (num == 2) {
110             return methodToParamName(methodName, 3);
111           }
112         }
113       
114         // a normal propery setter
115         if (parameters.length == 1 && num == 1) {
116           return methodToParamName(methodName, 3);
117         }
118       }
119
120       if (methodName.startsWith("get")) {
121         // indexed getter
122         if (parameters.length == 1 && num == 1 && className.equals("int"))
123           return "index";
124       }
125     }
126
127     return unique(parameters, type, num, getNameFromClass(className));
128   }
129
130
131   /**
132    * Generate a name for a parameter from the type of the parameter.
133    *
134    * @param className  the parameters type
135    * @return a more or less fitting name.
136    */
137   private final String getNameFromClass(String className) {
138
139         
140     
141     // if this is an classname starting with an upper case letter
142     // downcase it and use class name as parameter name
143     int i = className.lastIndexOf('.')+1;      
144     if (Character.isUpperCase(className.charAt(i))) {
145       className = Introspector.decapitalize(className.substring(i));
146
147       // Handle user-defined type array names of the form
148       //   [Lname;
149       if (className.endsWith(";")) {
150         className = className.substring(0, className.length()-1) + "Array";
151       }
152       
153       return className;
154     }
155
156     // handle primitive arrays
157     if (className.equals("[Z")) {
158       return "boolArray";
159     }
160         
161     if (className.equals("[B")) {
162       return "byteArray";
163     }
164         
165     if (className.equals("[C"))
166       return "charArray";
167     if (className.equals("[S"))
168       return "shortArray";
169     if (className.equals("[I"))
170       return "intArray";
171     if (className.equals("[J"))
172       return "longArray";
173     if (className.equals("[F"))
174       return "floatArray";
175     if (className.equals("[D"))
176       return "doubleArray";
177
178     // handle primitives
179     if (className.equals("boolean"))
180       return "flag";
181     if (className.equals("byte"))
182       return "b";
183     if (className.equals("char"))
184       return "c";
185     if (className.equals("short"))
186       return "s";
187     if (className.equals("int"))
188       return "n";
189     if (className.equals("long"))
190       return "l";
191     if (className.equals("float"))
192       return "f";
193     if (className.equals("double"))
194       return "d";
195
196     // give up
197     return "arg";
198   }
199     
200   /**
201    * Make name unique, look if there a more parameters of this type
202    * before us. In this case append a number.
203    *
204    * @param parameters all parameter types of the method
205    * @param type the type of the current parameter
206    * @param num the position of the current parameter
207    * @param name parameter basename
208    * @return a unique parameter name
209    */
210   private final String unique(Class[] parameters, Class type, int num, String name) {
211     if (parameters.length > 1) {
212       int i = 0;
213       for (int j = 0; j < num; ++j)
214         if (parameters[j] == type)
215           ++i;
216
217       if (i != 0)
218         name += i;
219     }
220
221     return name;    
222   }
223     
224   /**
225    * Strip the first characters from the string and decapitalize
226    * the rest.
227    *
228    * @param name the original name.
229    * @param strip number of characters to strip from the front of the name.
230    * @return the decapitalized and shortened name.
231    */
232   private final String methodToParamName(String name, int strip) {
233     return Introspector.decapitalize(name.substring(strip));
234   }
235 }
236
237 /*
238  * $Log: DefaultNameFactory.java,v $
239  * Revision 1.6  2002/12/12 05:15:48  paulk
240  * Now correctly generates names for method parameters that are arrays of user-defined types.
241  *
242  * Revision 1.5  2002/12/04 07:06:47  paulk
243  * Updated to handle implementation of interfaces that reference inner classes.
244  *
245  * Revision 1.4  2002/06/06 05:12:44  paulk
246  * DefaultNameFactory now generates meaningful method parameter names based
247  * on the parameter type or the method name. Thanks to Ole Arndt.
248  *
249  */
250
251 // End of DefaultNameFactory.java