use of org.apache.tapestry5.commons.util.StrategyRegistry in project tapestry-5 by apache.
the class StrategyBuilderImpl method createProxy.
private <S> S createProxy(final Class<S> interfaceType, final StrategyRegistry<S> registry) {
ClassInstantiator instantiator = proxyFactory.createProxy(interfaceType, new PlasticClassTransformer() {
@Override
public void transform(PlasticClass plasticClass) {
final PlasticField registryField = plasticClass.introduceField(StrategyRegistry.class, "registry").inject(registry);
Class<?> interfaceSelectorType = null;
for (final Method method : interfaceType.getMethods()) {
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 0) {
throw new IllegalArgumentException("Invalid method " + method + ", when using the strategy pattern, every method must take at least the selector as its parameter");
}
Class<?> methodSelectorType = parameterTypes[0];
if (interfaceSelectorType == null) {
interfaceSelectorType = methodSelectorType;
} else if (!interfaceSelectorType.equals(methodSelectorType)) {
throw new IllegalArgumentException("Conflicting method definitions," + " expecting the first argument of every method to have the same type");
}
plasticClass.introduceMethod(new MethodDescription(method), new InstructionBuilderCallback() {
@Override
public void doBuild(InstructionBuilder builder) {
Class returnType = method.getReturnType();
builder.loadThis().getField(registryField);
// Argument 0 is the selector used to find the adapter and should be an object reference,
// not a primitive.
builder.loadArgument(0);
// Use the StrategyRegistry to get the adapter to re-invoke the method on
builder.invoke(StrategyRegistry.class, Object.class, "getByInstance", Object.class).checkcast(interfaceType);
// That leaves the correct adapter on top of the stack. Get the
// selector and the rest of the arguments in place and invoke the method.
builder.loadArguments().invoke(interfaceType, returnType, method.getName(), method.getParameterTypes());
builder.returnResult();
}
});
}
plasticClass.addToString(String.format("<Strategy for %s>", interfaceType.getName()));
}
});
return interfaceType.cast(instantiator.newInstance());
}
Aggregations