Search in sources :

Example 6 with InstructionBuilder

use of org.apache.tapestry5.plastic.InstructionBuilder in project tapestry-5 by apache.

the class SwitchBlockImpl method doCallback.

void doCallback(SwitchCallback callback) {
    check();
    callback.doSwitch(this);
    if (!defaultAdded) {
        addDefault(new InstructionBuilderCallback() {

            @Override
            public void doBuild(InstructionBuilder builder) {
                builder.throwException(IllegalArgumentException.class, "Switch value not matched in case statement.");
            }
        });
    }
    state.visitor.visitLabel(endSwitchLabel);
    lock();
}
Also used : InstructionBuilder(org.apache.tapestry5.plastic.InstructionBuilder) InstructionBuilderCallback(org.apache.tapestry5.plastic.InstructionBuilderCallback)

Example 7 with InstructionBuilder

use of org.apache.tapestry5.plastic.InstructionBuilder in project tapestry-5 by apache.

the class OnEventWorker method implementDispatchMethod.

private void implementDispatchMethod(final PlasticClass plasticClass, final boolean isRoot, final MutableComponentModel model, final Flow<EventHandlerMethod> eventHandlerMethods) {
    plasticClass.introduceMethod(TransformConstants.DISPATCH_COMPONENT_EVENT_DESCRIPTION).changeImplementation(new InstructionBuilderCallback() {

        public void doBuild(InstructionBuilder builder) {
            builder.startVariable("boolean", new LocalVariableCallback() {

                public void doBuild(LocalVariable resultVariable, InstructionBuilder builder) {
                    if (!isRoot) {
                        // As a subclass, there will be a base class implementation (possibly empty).
                        builder.loadThis().loadArguments().invokeSpecial(plasticClass.getSuperClassName(), TransformConstants.DISPATCH_COMPONENT_EVENT_DESCRIPTION);
                        // First store the result of the super() call into the variable.
                        builder.storeVariable(resultVariable);
                        builder.loadArgument(0).invoke(Event.class, boolean.class, "isAborted");
                        builder.when(Condition.NON_ZERO, RETURN_TRUE);
                    } else {
                        // No event handler method has yet been invoked.
                        builder.loadConstant(false).storeVariable(resultVariable);
                    }
                    boolean hasRestEndpointEventHandlerMethod = false;
                    JSONArray restEndpointEventHandlerMethods = null;
                    for (EventHandlerMethod method : eventHandlerMethods) {
                        method.buildMatchAndInvocation(builder, resultVariable);
                        model.addEventHandler(method.eventType);
                        if (method.handleActivationEventContext) {
                            model.doHandleActivationEventContext();
                        }
                        // We're collecting this info for all components, even considering REST
                        // events are only triggered in pages, because we can have REST event
                        // handler methods in base classes too, and we need this info
                        // for generating complete, correct OpenAPI documentation.
                        final OnEvent onEvent = method.method.getAnnotation(OnEvent.class);
                        final String methodName = method.method.getDescription().methodName;
                        if (isRestEndpointEventHandlerMethod(onEvent, methodName)) {
                            hasRestEndpointEventHandlerMethod = true;
                            if (restEndpointEventHandlerMethods == null) {
                                restEndpointEventHandlerMethods = new JSONArray();
                            }
                            JSONObject methodMeta = new JSONObject();
                            methodMeta.put("name", methodName);
                            JSONArray parameters = new JSONArray();
                            for (MethodParameter parameter : method.method.getParameters()) {
                                parameters.add(parameter.getType());
                            }
                            methodMeta.put("parameters", parameters);
                            restEndpointEventHandlerMethods.add(methodMeta);
                        }
                    }
                    // memory by not setting it to all component models.
                    if (model.isPage()) {
                        model.setMeta(InternalConstants.REST_ENDPOINT_EVENT_HANDLER_METHOD_PRESENT, hasRestEndpointEventHandlerMethod ? InternalConstants.TRUE : InternalConstants.FALSE);
                    }
                    // methods in components, something that would be ignored anyway.
                    if (restEndpointEventHandlerMethods != null) {
                        model.setMeta(InternalConstants.REST_ENDPOINT_EVENT_HANDLER_METHODS, restEndpointEventHandlerMethods.toCompactString());
                    }
                    builder.loadVariable(resultVariable).returnResult();
                }
            });
        }
    });
}
Also used : LocalVariableCallback(org.apache.tapestry5.plastic.LocalVariableCallback) InstructionBuilder(org.apache.tapestry5.plastic.InstructionBuilder) JSONObject(org.apache.tapestry5.json.JSONObject) LocalVariable(org.apache.tapestry5.plastic.LocalVariable) JSONArray(org.apache.tapestry5.json.JSONArray) MethodParameter(org.apache.tapestry5.plastic.MethodParameter) InstructionBuilderCallback(org.apache.tapestry5.plastic.InstructionBuilderCallback) OnEvent(org.apache.tapestry5.annotations.OnEvent)

Example 8 with InstructionBuilder

use of org.apache.tapestry5.plastic.InstructionBuilder 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)

Example 9 with InstructionBuilder

use of org.apache.tapestry5.plastic.InstructionBuilder in project tapestry-5 by apache.

the class ChainBuilderImpl method implementMethod.

private void implementMethod(PlasticClass plasticClass, final Method method, final PlasticField commandsField) {
    plasticClass.introduceMethod(method).changeImplementation(new InstructionBuilderCallback() {

        @Override
        public void doBuild(InstructionBuilder builder) {
            builder.loadThis().getField(commandsField).iterateArray(new InstructionBuilderCallback() {

                @Override
                public void doBuild(InstructionBuilder builder) {
                    // The command is on the stack; add the elements and invoke the method.
                    builder.loadArguments().invoke(method);
                    Class returnType = method.getReturnType();
                    if (returnType == void.class)
                        return;
                    final boolean wide = returnType == long.class || returnType == double.class;
                    if (wide)
                        builder.dupeWide();
                    else
                        builder.dupe();
                    if (returnType == float.class) {
                        builder.loadConstant(0f).compareSpecial("float");
                    }
                    if (returnType == long.class) {
                        builder.loadConstant(0l).compareSpecial("long");
                    }
                    if (returnType == double.class) {
                        builder.loadConstant(0d).compareSpecial("double");
                    }
                    Condition condition = returnType.isPrimitive() ? Condition.NON_ZERO : Condition.NON_NULL;
                    builder.when(condition, new WhenCallback() {

                        @Override
                        public void ifTrue(InstructionBuilder builder) {
                            builder.returnResult();
                        }

                        @Override
                        public void ifFalse(InstructionBuilder builder) {
                            if (wide)
                                builder.popWide();
                            else
                                builder.pop();
                        }
                    });
                }
            });
            builder.returnDefaultValue();
        }
    });
}
Also used : Condition(org.apache.tapestry5.plastic.Condition) WhenCallback(org.apache.tapestry5.plastic.WhenCallback) InstructionBuilder(org.apache.tapestry5.plastic.InstructionBuilder) PlasticClass(org.apache.tapestry5.plastic.PlasticClass) InstructionBuilderCallback(org.apache.tapestry5.plastic.InstructionBuilderCallback)

Example 10 with InstructionBuilder

use of org.apache.tapestry5.plastic.InstructionBuilder in project tapestry-5 by apache.

the class ComponentInstantiatorSourceImpl method implementComponentInterface.

private void implementComponentInterface(PlasticClass plasticClass) {
    plasticClass.introduceInterface(Component.class);
    final PlasticField resourcesField = plasticClass.introduceField(InternalComponentResources.class, "internalComponentResources").injectFromInstanceContext();
    plasticClass.introduceMethod(GET_COMPONENT_RESOURCES, new InstructionBuilderCallback() {

        public void doBuild(InstructionBuilder builder) {
            builder.loadThis().getField(resourcesField).returnResult();
        }
    });
}
Also used : InstructionBuilder(org.apache.tapestry5.plastic.InstructionBuilder) InternalComponentResources(org.apache.tapestry5.internal.InternalComponentResources) PlasticField(org.apache.tapestry5.plastic.PlasticField) InstructionBuilderCallback(org.apache.tapestry5.plastic.InstructionBuilderCallback)

Aggregations

MethodNode (org.apache.tapestry5.internal.plastic.asm.tree.MethodNode)7 InstructionBuilder (org.apache.tapestry5.plastic.InstructionBuilder)6 InstructionBuilderCallback (org.apache.tapestry5.plastic.InstructionBuilderCallback)6 Method (java.lang.reflect.Method)3 PlasticClass (org.apache.tapestry5.plastic.PlasticClass)3 PlasticField (org.apache.tapestry5.plastic.PlasticField)3 Label (org.apache.tapestry5.internal.plastic.asm.Label)2 Type (org.apache.tapestry5.internal.plastic.asm.Type)2 PlasticClassTransformer (org.apache.tapestry5.plastic.PlasticClassTransformer)2 IFn (clojure.lang.IFn)1 Symbol (clojure.lang.Symbol)1 OnEvent (org.apache.tapestry5.annotations.OnEvent)1 Namespace (org.apache.tapestry5.clojure.Namespace)1 StrategyRegistry (org.apache.tapestry5.commons.util.StrategyRegistry)1 InternalComponentResources (org.apache.tapestry5.internal.InternalComponentResources)1 LVInfo (org.apache.tapestry5.internal.plastic.InstructionBuilderState.LVInfo)1 JSONArray (org.apache.tapestry5.json.JSONArray)1 JSONObject (org.apache.tapestry5.json.JSONObject)1 ClassInstantiator (org.apache.tapestry5.plastic.ClassInstantiator)1 Condition (org.apache.tapestry5.plastic.Condition)1