/Users/lyon/j4p/src/classUtils/delegate/DelegateSynthesizer.java
|
1 package classUtils.delegate;
2
3 import javax.swing.JOptionPane;
4 import java.awt.FileDialog;
5 import java.awt.Frame;
6 import java.io.BufferedWriter;
7 import java.io.ByteArrayOutputStream;
8 import java.io.File;
9 import java.io.FileWriter;
10 import java.io.OutputStreamWriter;
11 import java.lang.reflect.Method;
12 import java.lang.reflect.Modifier;
13 import java.util.Date;
14 import java.util.Vector;
15
16 /**
17 * DelegateSynthesizer class
18 * These classes are use reflectutil to automatically
19 * generate a new class file
20 */
21 public class DelegateSynthesizer {
22 private String className = "";
23 private String methodList = "";
24 private Vector instanceVector = new Vector();
25 private Vector uniqueMethodVector = new Vector();
26 private Vector duplicateMethodVector = new Vector();
27 private Vector compositeMethodVector = new Vector();
28 private boolean isTopologicallySorted = false;
29 private boolean isDebugging = false;
30
31 public void printUniqueMethodList() {
32 for (int i = 0; i < uniqueMethodVector.size(); i++) {
33 System.out.println(uniqueMethodVector.elementAt(i));
34 }
35 }
36
37 public void setToplogicalSorting(boolean b) {
38 isTopologicallySorted = b;
39 }
40
41 // compare method with all methods in uniqueMethodList, if equal,
42 // then add it to dupmethodlist, or else append at the end.
43 public void addMethod(String cn, Method m) {
44 int i, j;
45 boolean pos_found = false;
46 Method other;
47 i = 0;
48 println("uniqueMethodList size=" + uniqueMethodVector.size());
49 j = uniqueMethodVector.size();
50 getException(m);
51 try {
52 while (i <= j && !pos_found) {
53 if (i == j) {
54 // uniqueClassnameList.addElement(cn);
55 uniqueMethodVector.addElement(m);
56 pos_found = true;
57 } else {
58 other = (Method) uniqueMethodVector.elementAt(i);
59 if (equals(other, m)) {
60 // if it's toplogic, do nothing
61 addNonTopologic(other);
62
63 // add current to dup vectors
64 getDuplicateMethodVector().addElement(m);
65 pos_found = true;
66 }
67 i++;
68 }
69 }
70 } catch (Exception e) {
71 }
72 }
73
74 private void println(String s) {
75 if (isDebugging)
76 System.out.println(s);
77 }
78
79 private void addNonTopologic(Method other) {
80 if (!isTopologicallySorted) {
81 // duplicate record, copy from unique to dup vector
82 // but if the same one has been copied alread, do not copy again
83 if (getDuplicateMethodVector().indexOf(other) == -1)
84 getDuplicateMethodVector().addElement(other);
85 }
86 }
87
88 public void addDupMethod(Object o) {
89 getDuplicateMethodVector().addElement(o);
90 }
91
92 public void removeDupMethod(Object o) {
93 getDuplicateMethodVector().removeElement(o);
94 }
95
96 public void addDoMethod(Object o) {
97 getCompositeMethodVector().addElement(o);
98 }
99
100 public void removeDoMethod(Object o) {
101 getCompositeMethodVector().removeElement(o);
102 }
103
104 // build both unique method list and duplicate method list
105 public void buildMethodList(Object o) {
106 ReflectUtil ru = new ReflectUtil(o);
107 String cn = stripPackageName(ru.getClassName());
108 className = className + stripPackageName(cn);
109 Method m[] = ru.getAllMethods();
110 println("getAllmethods returned:" + m.length);
111 println("\nClass: " + cn);
112 for (int i = 0; i < m.length; i++)
113 addMethod(cn, m[i]);
114 }
115
116 public void process() {
117 for (int i = 0; i < instanceVector.size(); i++)
118 buildMethodList(instanceVector.elementAt(i));
119 System.out.println("\ntotal unique method: " + uniqueMethodVector.size() +
120 "\nTotal duplicated method: " + getDuplicateMethodVector().size());
121 }
122
123 public void add(Object o) {
124 instanceVector.addElement(o);
125 }
126
127 private String getException(Method m) {
128 Class c[];
129 String s = new String();
130 c = m.getExceptionTypes();
131 if (c.length > 0) {
132 s = "throws ";
133 s = s + c[0].getName();
134 }
135 // in case have more than one exception, this will work
136 for (int i = 1; i < c.length; i++)
137 s = s + "," + c[i].getName();
138 return s;
139 }
140
141 public String getInterface() {
142 StringBuffer sb = new StringBuffer("interface ");
143 sb.append(getInterfaceName() + "Stub extends \n");
144 sb.append("\t" + getImplementsList());
145 sb.append(" {\n");
146 sb.append("}");
147 sb.append(getInterfaces());
148 return sb.toString();
149 }
150
151 public String getInterfaces() {
152 StringBuffer sb = new StringBuffer("");
153 for (int i = 0; i < instanceVector.size(); i++)
154 sb.append(getInterface(instanceVector.elementAt(i)));
155 return sb.toString();
156 }
157
158 public String getInterface(Object o) {
159 String s = "\n interface "
160 + getStubName(o)
161 + " {\n"
162 + getMethodPrototypes(o)
163 + " }";
164 return s;
165 }
166
167 private String getImplementsList() {
168 StringBuffer sb = new StringBuffer("");
169 for (int i = 0; i < instanceVector.size() - 1; i++)
170 sb.append(getStubName(instanceVector.elementAt(i)) + ", ");
171 sb.append(getStubName(instanceVector.elementAt(instanceVector.size() - 1)));
172 return sb.toString();
173 }
174
175 private String getStrippedClassName(Object o) {
176 ReflectUtil ru = new ReflectUtil(o);
177 return stripPackageName(ru.getClassName());
178 }
179
180 private String getStubName(Object o) {
181 ReflectUtil ru = new ReflectUtil(o);
182 return stripPackageName(ru.getClassName() + "Stub");
183 }
184
185 private String getInterfaceName() {
186 StringBuffer sb = new StringBuffer("");
187 for (int i = 0; i < instanceVector.size(); i++)
188 sb.append(getStrippedClassName(instanceVector.elementAt(i)));
189 return sb.toString();
190 }
191
192 public String getConstructorParameters() {
193 StringBuffer sb = new StringBuffer("\n\t");
194 for (int i = 0; i < instanceVector.size(); i++)
195 buildConstructorParameter(i, sb);
196 return sb.toString();
197 }
198
199 private void buildConstructorParameter(int i, StringBuffer sb) {
200 ReflectUtil ru = new ReflectUtil(instanceVector.elementAt(i));
201 String instanceName =
202 stripPackageName(ru.getClassName()).toLowerCase();
203 sb.append(ru.getClassName()
204 + " _"
205 + instanceName);
206 if (i < instanceVector.size() - 1)
207 sb.append(",\n\t");
208 }
209
210 private String getConstructorBody() {
211 StringBuffer sb = new StringBuffer("\n\t");
212 for (int i = 0; i < instanceVector.size(); i++)
213 buildConstructor(i, sb);
214 return sb.toString();
215 }
216
217 private void buildConstructor(int i, StringBuffer sb) {
218 ReflectUtil ru = new ReflectUtil(instanceVector.elementAt(i));
219 String instanceName =
220 stripPackageName(ru.getClassName()).toLowerCase();
221 sb.append(instanceName
222 + " = _"
223 + instanceName
224 + ";");
225 if (i < instanceVector.size() - 1)
226 sb.append("\n\t");
227 }
228
229 private String getMethodPrototypes(Object o) {
230 ReflectUtil ru = new ReflectUtil(o);
231 String cn = stripPackageName(ru.getClassName());
232 String instanceName = cn.toLowerCase();
233 Method m[] = ru.getAllMethods();
234 return getMethodPrototypes(m, instanceName);
235 }
236
237 private void processInstance(Object o) {
238 ReflectUtil ru = new ReflectUtil(o);
239 String cn = stripPackageName(ru.getClassName());
240 String instanceName = cn.toLowerCase();
241 className = className +
242 stripPackageName(cn);
243 Method m[] = ru.getAllMethods();
244 methodList = methodList
245 + " " + ru.getClassName() + " " + instanceName + ";\n"
246 + getMethodList(m, instanceName);
247 }
248
249 public String getMethodList(Method m[], String instanceName) {
250 String s = "";
251 for (int i = 0; i < m.length; i++)
252 if (getDuplicateMethodVector().indexOf(m[i]) == -1)
253 s = s + getMethodDeclaration(m[i], instanceName) + "\n";
254 return s;
255 }
256
257 public String getMethodPrototypes(Method m[], String instanceName) {
258 String s = "";
259 for (int i = 0; i < m.length; i++)
260 s = s + getMethodPrototype(m[i], instanceName) + "\n";
261 return s;
262 }
263
264 public String getMethodDeclaration(Method m, String instanceName) {
265 if (isPublic(m))
266 return "\t"
267 + "public" // strip out other modifiers.
268 + " "
269 + getReturnType(m)
270 + " "
271 + m.getName()
272 + "("
273 + getParameters(m)
274 + ") "
275 + getException(m)
276 + " {\n\t"
277 + getInvocation(m, instanceName)
278 + "\t}";
279 return "";
280 }
281
282 public String getMethodPrototype(Method m, String instanceName) {
283 if (isPublic(m))
284 return "\t"
285 + "public" // strip out other modifiers.
286 + " "
287 + getReturnType(m)
288 + " "
289 + m.getName()
290 + "("
291 + getParameters(m)
292 + ");";
293 return "";
294 }
295
296 public static String getReturnType(Method m) {
297 return getTypeName(m.getReturnType());
298 }
299
300 public static boolean isReturningVoid(Method m) {
301 return getReturnType(m).startsWith("void");
302 }
303
304 public static String getModifiers(Method m) {
305 return Modifier.toString(m.getModifiers());
306 }
307
308 private String getOptionalReturn(Method m) {
309 if (isReturningVoid(m)) return "";
310 return "return ";
311 }
312
313 private String getInvocation(Method m, String instanceName) {
314 StringBuffer sb = new StringBuffer("\t"
315 + getOptionalReturn(m)
316 + instanceName
317 + "."
318 + m.getName()
319 + "(");
320 Class[] params = m.getParameterTypes();
321 for (int j = 0; j < params.length; j++) {
322 sb.append("v" + j);
323 if (j < (params.length - 1))
324 sb.append(",");
325 }
326 sb.append(");\n");
327 return sb.toString();
328 }
329
330 public String getParameters(Method m) {
331 StringBuffer sb = new StringBuffer("");
332 Class[] params = m.getParameterTypes(); // avoid clone
333 for (int j = 0; j < params.length; j++) {
334 sb.append(getTypeName(params[j]) + " v" + j);
335 if (j < (params.length - 1))
336 sb.append(",");
337 }
338 return sb.toString();
339 }
340
341 public static String getTypeName(Class type) {
342 if (!type.isArray())
343 return type.getName();
344 Class cl = type;
345 int dimensions = 0;
346 while (cl.isArray()) {
347 dimensions++;
348 cl = cl.getComponentType();
349 }
350 StringBuffer sb = new StringBuffer();
351 sb.append(cl.getName());
352 for (int i = 0; i < dimensions; i++)
353 sb.append("[]");
354 return sb.toString();
355 }
356
357 public static boolean isPublic(Method m) {
358 return
359 Modifier.toString(m.getModifiers()).startsWith("public");
360 }
361
362 public static String stripPackageName(String s) {
363 int index = s.lastIndexOf('.');
364 if (index == -1) return s;
365 index++;
366 return s.substring(index);
367 }
368
369 private String getConstructor() {
370 // public className(class1 _class1Instance, class2 _class2Instance...) {
371 // class1Instance = _class1Instance;
372 // class2Instance = _class2Instance;
373 //}
374 return "\n// constructor: \npublic "
375 + className
376 + "("
377 + getConstructorParameters()
378 + "){"
379 + getConstructorBody()
380 + "\n}\n\n";
381 }
382
383 public String getClassString() {
384 return
385 "// automatically generated by the DelegateSynthesizer"
386 + "\npublic class "
387 + className
388 + " {\n"
389 + getConstructor()
390 + methodList
391 + "}\n";
392 }
393
394 public void print() {
395 print(getClassString());
396 }
397
398 private void print(Object o) {
399 System.out.println(o);
400 }
401
402 /**
403 * Compares this <code>Method</code> against the specified object. Returns
404 * true if the objects are the same. Two <code>Methods</code> are the same if
405 * they were declared by the same class and have the same name
406 * and formal parameter types.
407 */
408 public boolean equals(Method obj1, Method obj2) {
409 if (obj1 != null && obj2 != null) {
410 if ((obj1.getName().equals(obj2.getName()))) {
411 /* Avoid unnecessary cloning */
412 Class[] params1 = obj1.getParameterTypes();
413 Class[] params2 = obj2.getParameterTypes();
414 if (params1.length == params2.length) {
415 for (int i = 0; i < params1.length; i++) {
416 if (params1[i] != params2[i])
417 return false;
418 }
419 return true;
420 }
421 }
422 }
423 return false;
424 }
425
426 public String getSaveFileName(String prompt) {
427 FileDialog fd = new FileDialog(new Frame(),
428 prompt,
429 FileDialog.SAVE);
430 fd.setFile(className + ".java");
431 fd.setVisible(true);
432 fd.setVisible(false);
433 String fn = fd.getDirectory() + fd.getFile();
434 if (fd.getFile() == null) return null;
435 return fn;
436 }
437
438 public void createFile() {
439 String fn = getSaveFileName("save file as");
440 if (fn == null) {
441 JOptionPane.showMessageDialog(null,
442 "No filename is specified! " +
443 "operation aborted.",
444 "Wait a second",
445 JOptionPane.INFORMATION_MESSAGE);
446 return;
447 }
448 File f = new File(fn);
449 createFile(f);
450 }
451
452 private void createFile(File f) {
453 BufferedWriter bw = null;
454 // open file
455 try {
456 bw = new BufferedWriter(new FileWriter(f));
457 } catch (Exception e) {
458 }
459 createFile(bw);
460 }
461
462 /**
463 * Use the ds to generate output into
464 * a string.
465 *
466 * @return a list of classes with interfaces for proxy delegation
467 */
468 public String toString() {
469 ByteArrayOutputStream baos = new ByteArrayOutputStream();
470 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(baos));
471 createFile(bw);
472 return baos.toString();
473 }
474
475 public void createFile(BufferedWriter bw) {
476 Object[] savedDupMethodList = new Object[getDuplicateMethodVector().size()];
477 Object[] savedDoMethodList = new Object[getCompositeMethodVector().size()];
478
479 // default is user chosen solving ambg, now we need to rebuild
480 // the dupMethodList according to toplogic rule
481 if (isTopologicallySorted == true)
482 topoSave(savedDupMethodList, savedDoMethodList);
483 className = "";
484 methodList = "";
485 for (int i = 0; i < instanceVector.size(); i++)
486 processInstance(instanceVector.elementAt(i));
487 try {
488 bw.write("package finalexam;\n" + getClassString() + getInterface());
489 } catch (Exception e) {
490 }
491 try {
492 bw.close();
493 } catch (Exception e) {
494 }
495 if (isTopologicallySorted == true)
496 sortTopologic(savedDupMethodList, savedDoMethodList);
497 }
498
499 private void sortTopologic(Object[] savedDupMethodList, Object[] savedDoMethodList) {
500 //put data back to dup list
501 getDuplicateMethodVector().removeAllElements();
502 getCompositeMethodVector().removeAllElements();
503 for (int i = 0; i < savedDupMethodList.length; i++)
504 getDuplicateMethodVector().addElement(savedDupMethodList[i]);
505 for (int i = 0; i < savedDoMethodList.length; i++)
506 getCompositeMethodVector().addElement(savedDoMethodList[i]);
507 }
508
509 private void topoSave(Object[] savedDupMethodList, Object[] savedDoMethodList) {
510 // reset the dup method list and unique method list
511 getDuplicateMethodVector().copyInto(savedDupMethodList);
512 getCompositeMethodVector().copyInto(savedDoMethodList);
513 getDuplicateMethodVector().removeAllElements();
514 getCompositeMethodVector().removeAllElements();
515 uniqueMethodVector.removeAllElements();
516 for (int i = 0; i < instanceVector.size(); i++)
517 buildMethodList(instanceVector.elementAt(i));
518 }
519
520 // write the specified string to file
521 public void writeSaveFile(BufferedWriter bw, String s) {
522 try {
523 bw.write(s);
524 } catch (Exception e) {
525 }
526 }
527
528 public static void main(String args[]) {
529 DelegateSynthesizer ds = new DelegateSynthesizer();
530 // ds.add(new ChineseExample());
531 // ds.add(new AmericanExample());
532 ds.add(new Date());
533 ds.add(new String());
534 ds.process();
535 System.out.println(ds.getClassString() +
536 ds.getInterface());
537 }
538
539 public Vector getCompositeMethodVector() {
540 return compositeMethodVector;
541 }
542
543 public void setCompositeMethodVector(Vector compositeMethodVector) {
544 this.compositeMethodVector = compositeMethodVector;
545 }
546
547 public Vector getDuplicateMethodVector() {
548 return duplicateMethodVector;
549 }
550
551 public void setDuplicateMethodVector(Vector duplicateMethodVector) {
552 this.duplicateMethodVector = duplicateMethodVector;
553 }
554 }
555
556