diff options
Diffstat (limited to 'sample/vector/VectorAssistant.java')
-rw-r--r-- | sample/vector/VectorAssistant.java | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/sample/vector/VectorAssistant.java b/sample/vector/VectorAssistant.java new file mode 100644 index 0000000..8b721db --- /dev/null +++ b/sample/vector/VectorAssistant.java @@ -0,0 +1,135 @@ +package sample.vector; + +import java.io.IOException; +import javassist.*; +import sample.preproc.Assistant; + +/** + * This is a Javassist program which produce a new class representing + * vectors of a given type. For example, + * + * <ul>import java.util.Vector by sample.vector.VectorAssistant(int)</ul> + * + * <p>requests the Javassist preprocessor to substitute the following + * lines for the original import declaration: + * + * <ul><pre> + * import java.util.Vector; + * import sample.vector.intVector; + * </pre></ul> + * + * <p>The Javassist preprocessor calls <code>VectorAssistant.assist()</code> + * and produces class <code>intVector</code> equivalent to: + * + * <ul><pre> + * package sample.vector; + * + * public class intVector extends Vector { + * pubilc void add(int value) { + * addElement(new Integer(value)); + * } + * + * public int at(int index) { + * return elementAt(index).intValue(); + * } + * } + * </pre></ul> + * + * <p><code>VectorAssistant.assist()</code> uses + * <code>sample.vector.Sample</code> and <code>sample.vector.Sample2</code> + * as a template to produce the methods <code>add()</code> and + * <code>at()</code>. + */ +public class VectorAssistant implements Assistant { + public final String packageName = "sample.vector."; + + /** + * Calls <code>makeSubclass()</code> and produces a new vector class. + * This method is called by a <code>sample.preproc.Compiler</code>. + * + * @see sample.preproc.Compiler + */ + public CtClass[] assist(ClassPool pool, String vec, String[] args) + throws CannotCompileException + { + if (args.length != 1) + throw new CannotCompileException( + "VectorAssistant receives a single argument."); + + try { + CtClass subclass; + CtClass elementType = pool.get(args[0]); + if (elementType.isPrimitive()) + subclass = makeSubclass2(pool, elementType); + else + subclass = makeSubclass(pool, elementType); + + CtClass[] results = { subclass, pool.get(vec) }; + return results; + } + catch (NotFoundException e) { + throw new CannotCompileException(e); + } + catch (IOException e) { + throw new CannotCompileException(e); + } + } + + /** + * Produces a new vector class. This method does not work if + * the element type is a primitive type. + * + * @param type the type of elements + */ + public CtClass makeSubclass(ClassPool pool, CtClass type) + throws CannotCompileException, NotFoundException, IOException + { + CtClass vec = pool.makeClass(makeClassName(type)); + vec.setSuperclass(pool.get("java.util.Vector")); + + CtClass c = pool.get("sample.vector.Sample"); + CtMethod addmethod = c.getDeclaredMethod("add"); + CtMethod atmethod = c.getDeclaredMethod("at"); + + ClassMap map = new ClassMap(); + map.put("sample.vector.X", type.getName()); + + vec.addMethod(CtNewMethod.copy(addmethod, "add", vec, map)); + vec.addMethod(CtNewMethod.copy(atmethod, "at", vec, map)); + vec.writeFile(); + return vec; + } + + /** + * Produces a new vector class. This uses wrapped methods so that + * the element type can be a primitive type. + * + * @param type the type of elements + */ + public CtClass makeSubclass2(ClassPool pool, CtClass type) + throws CannotCompileException, NotFoundException, IOException + { + CtClass vec = pool.makeClass(makeClassName(type)); + vec.setSuperclass(pool.get("java.util.Vector")); + + CtClass c = pool.get("sample.vector.Sample2"); + CtMethod addmethod = c.getDeclaredMethod("add"); + CtMethod atmethod = c.getDeclaredMethod("at"); + + CtClass[] args1 = { type }; + CtClass[] args2 = { CtClass.intType }; + CtMethod m + = CtNewMethod.wrapped(CtClass.voidType, "add", args1, + null, addmethod, null, vec); + vec.addMethod(m); + m = CtNewMethod.wrapped(type, "at", args2, + null, atmethod, null, vec); + vec.addMethod(m); + vec.writeFile(); + return vec; + } + + private String makeClassName(CtClass type) { + return packageName + type.getSimpleName() + "Vector"; + } +} |