package cutils.delegate;
import javax.swing.*;
import java.awt.*;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Vector;
public class DelegateSynthesizer {
private String className = "";
private String methodList = "";
private Vector instanceList = new Vector();
private Vector uniqueMethodList = new Vector();
private Vector dupMethodList = new Vector();
private Vector doMethodList = new Vector();
private boolean choseToplogic = false;
public void chooseToplogic(boolean b) {
choseToplogic = b;
}
public void addMethod(String cn, Method m) {
int i, j;
boolean pos_found = false;
Method other;
i = 0;
j = uniqueMethodList.size();
getException(m);
try {
while (i <= j && !pos_found) {
if (i == j) {
uniqueMethodList.addElement(m);
pos_found = true;
} else {
other = (Method) uniqueMethodList.elementAt(i);
if (equals(other, m)) {
addNonTopologic(other);
getDupMethodList().addElement(m);
pos_found = true;
}
i++;
}
}
} catch (Exception e) {
}
}
private void addNonTopologic(Method other) {
if (!choseToplogic) {
if (getDupMethodList().indexOf(other) == -1)
getDupMethodList().addElement(other);
}
}
public void addDupMethod(Object o) {
getDupMethodList().addElement(o);
}
public void removeDupMethod(Object o) {
getDupMethodList().removeElement(o);
}
public void addDoMethod(Object o) {
getDoMethodList().addElement(o);
}
public void removeDoMethod(Object o) {
getDoMethodList().removeElement(o);
}
public void buildMethodList(Object o) {
ReflectUtil ru = new ReflectUtil(o);
String cn = stripPackageName(ru.getClassName());
String instanceName = cn.toLowerCase();
className = className + stripPackageName(cn);
Method m[] = ru.getAllMethods();
System.out.println("\nClass: " + cn);
for (int i = 0; i < m.length; i++)
addMethod(cn, m[i]);
}
public void process() {
for (int i = 0; i < instanceList.size(); i++)
buildMethodList(instanceList.elementAt(i));
System.out.println("\ntotal unique method: " + uniqueMethodList.size() +
"\nTotal duplicated method: " + getDupMethodList().size());
}
public void add(Object o) {
instanceList.addElement(o);
}
private String getException(Method m) {
Class c[];
String s = new String();
c = m.getExceptionTypes();
if (c.length > 0) {
s = "throws ";
s = s + c[0].getName();
}
for (int i = 1; i < c.length; i++)
s = s + "," + c[i].getName();
return s;
}
public String getInterface() {
StringBuffer sb = new StringBuffer("interface ");
sb.append(getInterfaceName() + "Stub extends \n");
sb.append("\t" + getImplementsList());
sb.append(" {\n");
sb.append("}");
sb.append(getInterfaces());
return sb.toString();
}
public String getInterfaces() {
StringBuffer sb = new StringBuffer("");
for (int i = 0; i < instanceList.size(); i++)
sb.append(getInterface(instanceList.elementAt(i)));
return sb.toString();
}
public String getInterface(Object o) {
String s = "\n interface "
+ getStubName(o)
+ " {\n"
+ getMethodPrototypes(o)
+ " }";
return s;
}
private String getImplementsList() {
StringBuffer sb = new StringBuffer("");
for (int i = 0; i < instanceList.size() - 1; i++)
sb.append(getStubName(
instanceList.elementAt(i)) + ", ");
sb.append(getStubName(
instanceList.elementAt(instanceList.size() - 1)));
return sb.toString();
}
private String getStrippedClassName(Object o) {
ReflectUtil ru = new ReflectUtil(o);
return stripPackageName(ru.getClassName());
}
private String getStubName(Object o) {
ReflectUtil ru = new ReflectUtil(o);
return stripPackageName(ru.getClassName() + "Stub");
}
private String getInterfaceName() {
StringBuffer sb = new StringBuffer("");
for (int i = 0; i < instanceList.size(); i++)
sb.append(getStrippedClassName(
instanceList.elementAt(i)));
return sb.toString();
}
public String getConstructorParameters() {
StringBuffer sb = new StringBuffer("\n\t");
for (int i = 0; i < instanceList.size(); i++)
buildConstructorParameter(i, sb);
return sb.toString();
}
private void buildConstructorParameter(int i, StringBuffer sb) {
ReflectUtil ru = new ReflectUtil(
instanceList.elementAt(i));
String instanceName =
stripPackageName(ru.getClassName()).toLowerCase();
sb.append(ru.getClassName()
+ " _"
+ instanceName
);
if (i < instanceList.size() - 1)
sb.append(",\n\t");
}
private String getConstructorBody() {
StringBuffer sb = new StringBuffer("\n\t");
for (int i = 0; i < instanceList.size(); i++)
buildConstructor(i, sb);
return sb.toString();
}
private void buildConstructor(int i, StringBuffer sb) {
ReflectUtil ru = new ReflectUtil(
instanceList.elementAt(i));
String instanceName =
stripPackageName(ru.getClassName()).toLowerCase();
sb.append(
instanceName
+ " = _"
+ instanceName
+ ";"
);
if (i < instanceList.size() - 1)
sb.append("\n\t");
}
private String getMethodPrototypes(Object o) {
ReflectUtil ru = new ReflectUtil(o);
String cn = stripPackageName(ru.getClassName());
String instanceName = cn.toLowerCase();
Method m[] = ru.getAllMethods();
return getMethodPrototypes(m, instanceName);
}
private void processInstance(Object o) {
ReflectUtil ru = new ReflectUtil(o);
String cn = stripPackageName(ru.getClassName());
String instanceName = cn.toLowerCase();
className = className +
stripPackageName(cn);
Method m[] = ru.getAllMethods();
methodList = methodList
+ " " + ru.getClassName() + " " + instanceName + ";\n"
+ getMethodList(m, instanceName);
}
public String getMethodList(Method m[], String instanceName) {
String s = "";
for (int i = 0; i < m.length; i++)
if (getDupMethodList().indexOf(m[i]) == -1)
s = s + getMethodDeclaration(m[i], instanceName) + "\n";
return s;
}
public String getMethodPrototypes(Method m[], String instanceName) {
String s = "";
for (int i = 0; i < m.length; i++)
s = s + getMethodPrototype(m[i], instanceName) + "\n";
return s;
}
public String getMethodDeclaration(Method m, String instanceName) {
if (isPublic(m))
return "\t"
+ "public" + " "
+ getReturnType(m)
+ " "
+ m.getName()
+ "("
+ getParameters(m)
+ ") "
+ getException(m)
+ " {\n\t"
+ getInvocation(m, instanceName)
+ "\t}";
return "";
}
public String getMethodPrototype(Method m, String instanceName) {
if (isPublic(m))
return "\t"
+ "public" + " "
+ getReturnType(m)
+ " "
+ m.getName()
+ "("
+ getParameters(m)
+ ");";
return "";
}
public static String getReturnType(Method m) {
return getTypeName(m.getReturnType());
}
public static boolean isReturningVoid(Method m) {
return getReturnType(m).startsWith("void");
}
public static String getModifiers(Method m) {
return Modifier.toString(m.getModifiers());
}
private String getOptionalReturn(Method m) {
if (isReturningVoid(m)) return "";
return "return ";
}
private String getInvocation(Method m, String instanceName) {
StringBuffer sb = new StringBuffer(
"\t"
+ getOptionalReturn(m)
+ instanceName
+ "."
+ m.getName()
+ "("
);
Class[] params = m.getParameterTypes();
for (int j = 0; j < params.length; j++) {
sb.append("v" + j);
if (j < (params.length - 1))
sb.append(",");
}
sb.append(");\n");
return sb.toString();
}
public String getParameters(Method m) {
StringBuffer sb = new StringBuffer("");
Class[] params = m.getParameterTypes(); for (int j = 0; j < params.length; j++) {
sb.append(
getTypeName(params[j]) + " v" + j);
if (j < (params.length - 1))
sb.append(",");
}
return sb.toString();
}
public static String getTypeName(Class type) {
if (!type.isArray())
return type.getName();
Class cl = type;
int dimensions = 0;
while (cl.isArray()) {
dimensions++;
cl = cl.getComponentType();
}
StringBuffer sb = new StringBuffer();
sb.append(cl.getName());
for (int i = 0; i < dimensions; i++)
sb.append("[]");
return sb.toString();
}
public static boolean isPublic(Method m) {
return
Modifier.toString(m.getModifiers()).startsWith("public");
}
public static String stripPackageName(String s) {
int index = s.lastIndexOf('.');
if (index == -1) return s;
index++;
return s.substring(index);
}
private String getConstructor() {
return "\n// constructor: \npublic "
+ className
+ "("
+ getConstructorParameters()
+ "){"
+ getConstructorBody()
+ "\n}\n\n";
}
public String getClassString() {
return
"// automatically generated by the DelegateSynthesizer"
+ "\npublic class "
+ className
+ " {\n"
+ getConstructor()
+ methodList
+ "}\n";
}
public void print() {
print(getClassString());
}
private void print(Object o) {
System.out.println(o);
}
public boolean equals(Method obj1, Method obj2) {
if (obj1 != null && obj2 != null) {
if ((obj1.getName().equals(obj2.getName()))) {
Class[] params1 = obj1.getParameterTypes();
Class[] params2 = obj2.getParameterTypes();
if (params1.length == params2.length) {
for (int i = 0; i < params1.length; i++) {
if (params1[i] != params2[i])
return false;
}
return true;
}
}
}
return false;
}
public String getSaveFileName(String prompt) {
FileDialog fd = new FileDialog(new Frame(),
prompt,
FileDialog.SAVE);
fd.setFile(className + ".java");
fd.setVisible(true);
fd.setVisible(false);
String fn = fd.getDirectory() + fd.getFile();
if (fd.getFile() == null) return null;
return fn;
}
public void createFile() {
String fn = getSaveFileName("save file as");
if (fn == null) {
JOptionPane.showMessageDialog(null, "No filename is specified! operation aborted.", "Wait a second",
JOptionPane.INFORMATION_MESSAGE);
return;
}
File f = new File(fn);
BufferedWriter bw = null;
Object[] savedDupMethodList = new Object[getDupMethodList().size()];
Object[] savedDoMethodList = new Object[getDoMethodList().size()];
try {
bw = new BufferedWriter(new FileWriter(f));
} catch (Exception e) {
}
if (choseToplogic == true)
topoSave(savedDupMethodList, savedDoMethodList);
className = "";
methodList = "";
for (int i = 0; i < instanceList.size(); i++)
processInstance(instanceList.elementAt(i));
try {
bw.write("package finalexam;\n" + getClassString() + getInterface());
} catch (Exception e) {
}
try {
bw.close();
} catch (Exception e) {
}
if (choseToplogic == true)
sortTopologic(savedDupMethodList, savedDoMethodList);
}
private void sortTopologic(Object[] savedDupMethodList, Object[] savedDoMethodList) {
getDupMethodList().removeAllElements();
getDoMethodList().removeAllElements();
for (int i = 0; i < savedDupMethodList.length; i++)
getDupMethodList().addElement(savedDupMethodList[i]);
for (int i = 0; i < savedDoMethodList.length; i++)
getDoMethodList().addElement(savedDoMethodList[i]);
}
private void topoSave(Object[] savedDupMethodList, Object[] savedDoMethodList) {
getDupMethodList().copyInto(savedDupMethodList);
getDoMethodList().copyInto(savedDoMethodList);
getDupMethodList().removeAllElements();
getDoMethodList().removeAllElements();
uniqueMethodList.removeAllElements();
for (int i = 0; i < instanceList.size(); i++)
buildMethodList(instanceList.elementAt(i));
}
public void writeSaveFile(BufferedWriter bw, String s) {
try {
bw.write(s);
} catch (Exception e) {
}
}
public static void main(String args[]) {
DelegateSynthesizer ds = new DelegateSynthesizer();
ReflectUtil ru = new ReflectUtil(ds);
ds.add(new String());
ds.process();
System.out.println(
ds.getClassString() +
ds.getInterface());
}
public Vector getDoMethodList() {
return doMethodList;
}
public void setDoMethodList(Vector doMethodList) {
this.doMethodList = doMethodList;
}
public Vector getDupMethodList() {
return dupMethodList;
}
public void setDupMethodList(Vector dupMethodList) {
this.dupMethodList = dupMethodList;
}
}