use of org.apache.tapestry5.plastic.InstructionBuilderCallback 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();
}
use of org.apache.tapestry5.plastic.InstructionBuilderCallback 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();
}
});
}
});
}
use of org.apache.tapestry5.plastic.InstructionBuilderCallback 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());
}
use of org.apache.tapestry5.plastic.InstructionBuilderCallback 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();
}
});
}
use of org.apache.tapestry5.plastic.InstructionBuilderCallback 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();
}
});
}
Aggregations