in plastic/src/main/java/org/apache/tapestry5/plastic/PlasticUtils.java [255:375]
public static void implementPropertyValueProvider(PlasticClass plasticClass, Set<FieldInfo> fieldInfos)
{
final Set<PlasticMethod> methods = plasticClass.introduceInterface(PropertyValueProvider.class);
final InstructionBuilderCallback getterCallback = (builder) -> {
for (FieldInfo field : fieldInfos)
{
builder.loadArgument(0);
builder.loadConstant(field.name);
builder.invokeVirtual(String.class.getName(), "boolean", "equals", Object.class.getName());
builder.when(Condition.NON_ZERO, ifBuilder ->
{
final String prefix = field.type.equals("boolean") ? "is" : "get";
final String methodName = prefix + PlasticInternalUtils.capitalize(field.name);
ifBuilder.loadThis();
builder.invokeVirtual(
plasticClass.getClassName(),
field.type,
methodName);
ifBuilder.boxPrimitive(field.type);
ifBuilder.returnResult();
});
}
// Field/property not found, so let's try the superclass in case
// it also implement
builder.loadThis();
builder.instanceOf(PropertyValueProvider.class);
builder.when(Condition.NON_ZERO, ifBuilder -> {
builder.loadThis();
builder.loadArgument(0);
ifBuilder.invokeSpecial(
plasticClass.getSuperClassName(),
PROPERTY_VALUE_PROVIDER_GETTER_METHOD_DESCRIPTION);
ifBuilder.returnResult();
});
// Giving up
builder.throwException(RuntimeException.class, "Property not found or not supported");
};
final InstructionBuilderCallback setterCallback = (builder) -> {
for (FieldInfo field : fieldInfos)
{
builder.loadArgument(0);
builder.loadConstant(field.name);
builder.invokeVirtual(String.class.getName(), "boolean", "equals", Object.class.getName());
builder.when(Condition.NON_ZERO, ifBuilder ->
{
final String methodName = "set" + PlasticInternalUtils.capitalize(field.name);
ifBuilder.loadThis();
ifBuilder.loadArgument(1);
ifBuilder.castOrUnbox(field.type);
ifBuilder.invokeVirtual(
plasticClass.getClassName(),
void.class.getName(),
methodName,
field.type);
ifBuilder.returnResult();
});
}
// Field/property not found, so let's try the superclass in case
// it also implement
builder.loadThis();
builder.instanceOf(PropertyValueProvider.class);
builder.when(Condition.NON_ZERO, ifBuilder -> {
builder.loadThis();
builder.loadArgument(0);
builder.loadArgument(1);
ifBuilder.invokeSpecial(
plasticClass.getSuperClassName(),
PROPERTY_VALUE_PROVIDER_SETTER_METHOD_DESCRIPTION);
ifBuilder.returnResult();
});
// Giving up
builder.throwException(RuntimeException.class, "Property not found or not supported");
};
final PlasticMethod getterMethod;
final PlasticMethod setterMethod;
// Superclass has already defined this method, so we need to override it so
// it can also find the subclasses' declared fields/properties.
if (methods.isEmpty())
{
getterMethod = plasticClass.introduceMethod(PROPERTY_VALUE_PROVIDER_GETTER_METHOD_DESCRIPTION, getterCallback);
setterMethod = plasticClass.introduceMethod(PROPERTY_VALUE_PROVIDER_SETTER_METHOD_DESCRIPTION, setterCallback);
}
else
{
getterMethod = methods.stream()
.filter(m -> m.getDescription().methodName.equals(GETTER_METHOD_NAME))
.findFirst()
.get();
setterMethod = methods.stream()
.filter(m -> m.getDescription().methodName.equals(SETTER_METHOD_NAME))
.findFirst()
.get();
}
getterMethod.changeImplementation(getterCallback);
setterMethod.changeImplementation(setterCallback);
}