/**
* Generates a setter method for the provided property plus the corresponding code for the
* implementation of {@link HasProperties#set(String, Object)}.
*/
private void generateSetter(ClassStructureBuilder<?> classBuilder, String property, BlockBuilder<?> setMethod) {
MetaMethod getterMethod = bindable.getBeanDescriptor().getReadMethodForProperty(property);
MetaMethod setterMethod = bindable.getBeanDescriptor().getWriteMethodForProperty(property);
if (getterMethod != null && setterMethod != null && !setterMethod.isFinal()) {
setMethod.append(
If.cond(Stmt.loadVariable("property").invoke("equals", property))
.append(
target().invoke(setterMethod.getName(),
Cast.to(setterMethod.getParameters()[0].getType().asBoxed(), Variable.get("value"))))
.append(
Stmt.returnVoid())
.finish()
);
MetaClass paramType = setterMethod.getParameters()[0].getType();
// If the setter method we are proxying returns a value, capture that value into a local variable
Statement returnValueOfSetter = null;
String returnValName = ensureSafeLocalVariableName("returnValueOfSetter", setterMethod);
Statement wrappedListProperty = EmptyStatement.INSTANCE;
if (paramType.isAssignableTo(List.class)) {
wrappedListProperty = Stmt.loadVariable(property).assignValue(
agent().invoke("ensureBoundListIsProxied", property, Stmt.loadVariable(property)));
}
Statement callSetterOnTarget =
target().invoke(setterMethod.getName(), Cast.to(paramType, Stmt.loadVariable(property)));
if (!setterMethod.getReturnType().equals(MetaClassFactory.get(void.class))) {
callSetterOnTarget =
Stmt.declareFinalVariable(returnValName, setterMethod.getReturnType(), callSetterOnTarget);
returnValueOfSetter = Stmt.nestedCall(Refs.get(returnValName)).returnValue();
}
else {
returnValueOfSetter = EmptyStatement.INSTANCE;
}
Statement updateNestedProxy = null;
if (paramType.isAnnotationPresent(Bindable.class)) {
updateNestedProxy =
Stmt.if_(Bool.expr(agent("binders").invoke("containsKey", property)))
.append(Stmt.loadVariable(property).assignValue(Cast.to(paramType,
agent("binders").invoke("get", property).invoke("setModel", Variable.get(property)))))
.finish();
}
else {
updateNestedProxy = EmptyStatement.INSTANCE;
}
String oldValName = ensureSafeLocalVariableName("oldValue", setterMethod);
classBuilder.publicMethod(setterMethod.getReturnType(), setterMethod.getName(),
Parameter.of(paramType, property))
.append(updateNestedProxy)
.append(
Stmt.declareVariable(oldValName, paramType, target().invoke(getterMethod.getName())))
.append(wrappedListProperty)