Search in sources :

Example 1 with StrategyRegistry

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());
}
Also used : PlasticClass(org.apache.tapestry5.plastic.PlasticClass) InstructionBuilder(org.apache.tapestry5.plastic.InstructionBuilder) ClassInstantiator(org.apache.tapestry5.plastic.ClassInstantiator) StrategyRegistry(org.apache.tapestry5.commons.util.StrategyRegistry) MethodDescription(org.apache.tapestry5.plastic.MethodDescription) Method(java.lang.reflect.Method) PlasticClassTransformer(org.apache.tapestry5.plastic.PlasticClassTransformer) PlasticField(org.apache.tapestry5.plastic.PlasticField) PlasticClass(org.apache.tapestry5.plastic.PlasticClass) InstructionBuilderCallback(org.apache.tapestry5.plastic.InstructionBuilderCallback)

Aggregations

Method (java.lang.reflect.Method)1 StrategyRegistry (org.apache.tapestry5.commons.util.StrategyRegistry)1 ClassInstantiator (org.apache.tapestry5.plastic.ClassInstantiator)1 InstructionBuilder (org.apache.tapestry5.plastic.InstructionBuilder)1 InstructionBuilderCallback (org.apache.tapestry5.plastic.InstructionBuilderCallback)1 MethodDescription (org.apache.tapestry5.plastic.MethodDescription)1 PlasticClass (org.apache.tapestry5.plastic.PlasticClass)1 PlasticClassTransformer (org.apache.tapestry5.plastic.PlasticClassTransformer)1 PlasticField (org.apache.tapestry5.plastic.PlasticField)1