001: package sample.vector;
002:
003: import java.io.IOException;
004: import javassist.*;
005: import sample.preproc.Assistant;
006:
007: /**
008: * This is a Javassist program which produce a new class representing
009: * vectors of a given type. For example,
010: *
011: * <ul>import java.util.Vector by sample.vector.VectorAssistant(int)</ul>
012: *
013: * <p>requests the Javassist preprocessor to substitute the following
014: * lines for the original import declaration:
015: *
016: * <ul><pre>
017: * import java.util.Vector;
018: * import sample.vector.intVector;
019: * </pre></ul>
020: *
021: * <p>The Javassist preprocessor calls <code>VectorAssistant.assist()</code>
022: * and produces class <code>intVector</code> equivalent to:
023: *
024: * <ul><pre>
025: * package sample.vector;
026: *
027: * public class intVector extends Vector {
028: * pubilc void add(int value) {
029: * addElement(new Integer(value));
030: * }
031: *
032: * public int at(int index) {
033: * return elementAt(index).intValue();
034: * }
035: * }
036: * </pre></ul>
037: *
038: * <p><code>VectorAssistant.assist()</code> uses
039: * <code>sample.vector.Sample</code> and <code>sample.vector.Sample2</code>
040: * as a template to produce the methods <code>add()</code> and
041: * <code>at()</code>.
042: */
043: public class VectorAssistant implements Assistant {
044: public final String packageName = "sample.vector.";
045:
046: /**
047: * Calls <code>makeSubclass()</code> and produces a new vector class.
048: * This method is called by a <code>sample.preproc.Compiler</code>.
049: *
050: * @see sample.preproc.Compiler
051: */
052: public CtClass[] assist(ClassPool pool, String vec, String[] args)
053: throws CannotCompileException {
054: if (args.length != 1)
055: throw new CannotCompileException(
056: "VectorAssistant receives a single argument.");
057:
058: try {
059: CtClass subclass;
060: CtClass elementType = pool.get(args[0]);
061: if (elementType.isPrimitive())
062: subclass = makeSubclass2(pool, elementType);
063: else
064: subclass = makeSubclass(pool, elementType);
065:
066: CtClass[] results = { subclass, pool.get(vec) };
067: return results;
068: } catch (NotFoundException e) {
069: throw new CannotCompileException(e);
070: } catch (IOException e) {
071: throw new CannotCompileException(e);
072: }
073: }
074:
075: /**
076: * Produces a new vector class. This method does not work if
077: * the element type is a primitive type.
078: *
079: * @param type the type of elements
080: */
081: public CtClass makeSubclass(ClassPool pool, CtClass type)
082: throws CannotCompileException, NotFoundException,
083: IOException {
084: CtClass vec = pool.makeClass(makeClassName(type));
085: vec.setSuperclass(pool.get("java.util.Vector"));
086:
087: CtClass c = pool.get("sample.vector.Sample");
088: CtMethod addmethod = c.getDeclaredMethod("add");
089: CtMethod atmethod = c.getDeclaredMethod("at");
090:
091: ClassMap map = new ClassMap();
092: map.put("sample.vector.X", type.getName());
093:
094: vec.addMethod(CtNewMethod.copy(addmethod, "add", vec, map));
095: vec.addMethod(CtNewMethod.copy(atmethod, "at", vec, map));
096: vec.writeFile();
097: return vec;
098: }
099:
100: /**
101: * Produces a new vector class. This uses wrapped methods so that
102: * the element type can be a primitive type.
103: *
104: * @param type the type of elements
105: */
106: public CtClass makeSubclass2(ClassPool pool, CtClass type)
107: throws CannotCompileException, NotFoundException,
108: IOException {
109: CtClass vec = pool.makeClass(makeClassName(type));
110: vec.setSuperclass(pool.get("java.util.Vector"));
111:
112: CtClass c = pool.get("sample.vector.Sample2");
113: CtMethod addmethod = c.getDeclaredMethod("add");
114: CtMethod atmethod = c.getDeclaredMethod("at");
115:
116: CtClass[] args1 = { type };
117: CtClass[] args2 = { CtClass.intType };
118: CtMethod m = CtNewMethod.wrapped(CtClass.voidType, "add",
119: args1, null, addmethod, null, vec);
120: vec.addMethod(m);
121: m = CtNewMethod.wrapped(type, "at", args2, null, atmethod,
122: null, vec);
123: vec.addMethod(m);
124: vec.writeFile();
125: return vec;
126: }
127:
128: private String makeClassName(CtClass type) {
129: return packageName + type.getSimpleName() + "Vector";
130: }
131: }
|