MapChangeTracker.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();
// map copy
Constructor cons = findCopyConstructor(type);
if (cons == null && SortedMap.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(SortedMap.class);
code.invokeinterface().setMethod(SortedMap.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(Map.class);
code.invokevirtual().setMethod(type, "putAll", void.class,
new Class[] { Map.class });
}
code.areturn();
code.calculateMaxStack();
code.calculateMaxLocals();
// key type
BCField keyType = bc.declareField("keyType", Class.class);
keyType.setTransient(true);
m = bc.declareMethod("getKeyType", Class.class, null);
m.makePublic();
code = m.getCode(true);
code.aload().setThis();
code.getfield().setField(keyType);
code.areturn();
code.calculateMaxStack();
code.calculateMaxLocals();
// value type
BCField valueType = bc.declareField("valueType", Class.class);
valueType.setTransient(true);
m = bc.declareMethod("getValueType", Class.class, null);
m.makePublic();
code = m.getCode(true);
code.aload().setThis();
code.getfield().setField(valueType);
code.areturn();
code.calculateMaxStack();
code.calculateMaxLocals();
// new instance factory
m = bc.declareMethod("newInstance", ProxyMap.class,
new Class[] { Class.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(2);
code.invokespecial().setMethod("<init>", void.class, params);
int ret = code.getNextLocalsIndex();
code.astore().setLocal(ret);
// set key and value types
code.aload().setLocal(ret);
code.aload().setParam(0);
code.putfield().setField(keyType);
code.aload().setLocal(ret);
code.aload().setParam(1);
code.putfield().setField(valueType);
// create change tracker and set it
code.iload().setParam(3);
JumpInstruction ifins = code.ifeq();
code.aload().setLocal(ret);
code.anew().setType(MapChangeTrackerImpl.class);
code.dup();
code.aload().setLocal(ret);
code.aload().setParam(4);
code.invokespecial().setMethod(MapChangeTrackerImpl.class,
"<init>", void.class, new Class[] { Map.class, boolean.class });
code.putfield().setField(changeTracker);
ifins.setTarget(code.aload().setLocal(ret));
code.areturn();
code.calculateMaxStack();
code.calculateMaxLocals();
}