/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