169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage sample.vector;
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport java.io.IOException;
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.*;
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport sample.preproc.Assistant;
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This is a Javassist program which produce a new class representing
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * vectors of a given type.  For example,
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul>import java.util.Vector by sample.vector.VectorAssistant(int)</ul>
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>requests the Javassist preprocessor to substitute the following
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * lines for the original import declaration:
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre>
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * import java.util.Vector;
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * import sample.vector.intVector;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul>
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>The Javassist preprocessor calls <code>VectorAssistant.assist()</code>
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * and produces class <code>intVector</code> equivalent to:
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <ul><pre>
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * package sample.vector;
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * public class intVector extends Vector {
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *   pubilc void add(int value) {
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *     addElement(new Integer(value));
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *   }
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *   public int at(int index) {
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *     return elementAt(index).intValue();
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *   }
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * }
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * </pre></ul>
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p><code>VectorAssistant.assist()</code> uses
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>sample.vector.Sample</code> and <code>sample.vector.Sample2</code>
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * as a template to produce the methods <code>add()</code> and
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <code>at()</code>.
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class VectorAssistant implements Assistant {
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public final String packageName = "sample.vector.";
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Calls <code>makeSubclass()</code> and produces a new vector class.
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method is called by a <code>sample.preproc.Compiler</code>.
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see sample.preproc.Compiler
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtClass[] assist(ClassPool pool, String vec, String[] args)
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	throws CannotCompileException
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	if (args.length != 1)
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	    throw new CannotCompileException(
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal			"VectorAssistant receives a single argument.");
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	try {
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	    CtClass subclass;
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	    CtClass elementType = pool.get(args[0]);
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	    if (elementType.isPrimitive())
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal		subclass = makeSubclass2(pool, elementType);
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	    else
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal		subclass = makeSubclass(pool, elementType);
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	    CtClass[] results = { subclass, pool.get(vec) };
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	    return results;
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	}
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	catch (NotFoundException e) {
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	    throw new CannotCompileException(e);
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	}
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	catch (IOException e) {
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	    throw new CannotCompileException(e);
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	}
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Produces a new vector class.  This method does not work if
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the element type is a primitive type.
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param type	the type of elements
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtClass makeSubclass(ClassPool pool, CtClass type)
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	throws CannotCompileException, NotFoundException, IOException
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	CtClass vec = pool.makeClass(makeClassName(type));
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	vec.setSuperclass(pool.get("java.util.Vector"));
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	CtClass c = pool.get("sample.vector.Sample");
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	CtMethod addmethod = c.getDeclaredMethod("add");
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	CtMethod atmethod = c.getDeclaredMethod("at");
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	ClassMap map = new ClassMap();
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	map.put("sample.vector.X", type.getName());
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	vec.addMethod(CtNewMethod.copy(addmethod, "add", vec, map));
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	vec.addMethod(CtNewMethod.copy(atmethod, "at", vec, map));
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	vec.writeFile();
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	return vec;
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Produces a new vector class.  This uses wrapped methods so that
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the element type can be a primitive type.
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param type	the type of elements
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtClass makeSubclass2(ClassPool pool, CtClass type)
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	throws CannotCompileException, NotFoundException, IOException
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	CtClass vec = pool.makeClass(makeClassName(type));
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	vec.setSuperclass(pool.get("java.util.Vector"));
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	CtClass c = pool.get("sample.vector.Sample2");
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	CtMethod addmethod = c.getDeclaredMethod("add");
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	CtMethod atmethod = c.getDeclaredMethod("at");
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	CtClass[] args1 = { type };
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	CtClass[] args2 = { CtClass.intType };
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	CtMethod m
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	    = CtNewMethod.wrapped(CtClass.voidType, "add", args1,
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal				  null, addmethod, null, vec);
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	vec.addMethod(m);
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	m = CtNewMethod.wrapped(type, "at", args2,
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal				null, atmethod, null, vec);
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	vec.addMethod(m);
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	vec.writeFile();
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	return vec;
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private String makeClassName(CtClass type) {
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal	return packageName + type.getSimpleName() + "Vector";
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
136