CollectionChangeTracker.class);
changeTracker.setTransient(true);
BCMethod m = bc.declareMethod("getChangeTracker", ChangeTracker.class,
null);
m.makePublic();
Code code = m.getCode(true);
code.aload().setThis();
code.getfield().setField(changeTracker);
code.areturn();
code.calculateMaxStack();
code.calculateMaxLocals();
// collection copy
Constructor cons = findCopyConstructor(type);
if (cons == null && SortedSet.class.isAssignableFrom(type))
cons = findComparatorConstructor(type);
Class[] params = (cons == null) ? new Class[0]
: cons.getParameterTypes();
m = bc.declareMethod("copy", Object.class, new Class[] {Object.class});
m.makePublic();
code = m.getCode(true);
code.anew().setType(type);
code.dup();
if (params.length == 1) {
code.aload().setParam(0);
if (params[0] == Comparator.class) {
code.checkcast().setType(SortedSet.class);
code.invokeinterface().setMethod(SortedSet.class, "comparator",
Comparator.class, null);
} else
code.checkcast().setType(params[0]);
}
code.invokespecial().setMethod(type, "<init>", void.class, params);
if (params.length == 0 || params[0] == Comparator.class) {
code.dup();
code.aload().setParam(0);
code.checkcast().setType(Collection.class);
code.invokevirtual().setMethod(type, "addAll", boolean.class,
new Class[] { Collection.class });
code.pop();
}
code.areturn();
code.calculateMaxStack();
code.calculateMaxLocals();
// element type
BCField elementType = bc.declareField("elementType", Class.class);
elementType.setTransient(true);
m = bc.declareMethod("getElementType", Class.class, null);
m.makePublic();
code = m.getCode(true);
code.aload().setThis();
code.getfield().setField(elementType);
code.areturn();
code.calculateMaxStack();
code.calculateMaxLocals();
// new instance factory
m = bc.declareMethod("newInstance", ProxyCollection.class,
new Class[] { Class.class, Comparator.class, boolean.class, boolean.class });
m.makePublic();
code = m.getCode(true);
code.anew().setType(bc);
code.dup();
cons = findComparatorConstructor(type);
params = (cons == null) ? new Class[0] : cons.getParameterTypes();
if (params.length == 1)
code.aload().setParam(1);
code.invokespecial().setMethod("<init>", void.class, params);
int ret = code.getNextLocalsIndex();
code.astore().setLocal(ret);
// set element type
code.aload().setLocal(ret);
code.aload().setParam(0);
code.putfield().setField(elementType);
// create change tracker and set it
code.iload().setParam(2);
JumpInstruction ifins = code.ifeq();
code.aload().setLocal(ret);
code.anew().setType(CollectionChangeTrackerImpl.class);
code.dup();
code.aload().setLocal(ret);
code.constant().setValue(allowsDuplicates(type));
code.constant().setValue(isOrdered(type));
code.aload().setParam(3);
code.invokespecial().setMethod(CollectionChangeTrackerImpl.class,
"<init>", void.class, new Class[] { Collection.class,
boolean.class, boolean.class, boolean.class });
code.putfield().setField(changeTracker);
ifins.setTarget(code.aload().setLocal(ret));
code.areturn();
code.calculateMaxStack();
code.calculateMaxLocals();
}