private void buildMutator(EnhancementOperation op, String parameterName,
String propertyName, Class propertyType, String fieldName,
String defaultFieldName, String cachedFieldName,
String bindingFieldName, Location location)
{
BodyBuilder builder = new BodyBuilder();
builder.begin();
// The mutator method may be invoked from finishLoad(), in which
// case it changes the default value for the parameter property, if the
// parameter
// is not bound.
builder.addln("if (! isInActiveState())");
builder.begin();
builder.addln("{0} = $1;", defaultFieldName);
builder.addln("return;");
builder.end();
// In the normal state, we update the binding first - and it's an error
// if the parameter is not bound.
builder.addln("if ({0} == null)", bindingFieldName);
builder.addln(" throw new {0}(\"Parameter ''{1}'' is not bound and can not be updated.\");",
ApplicationRuntimeException.class.getName(), parameterName);
// Always updated the binding first (which may fail with an exception).
builder.addln("{0}.setObject(($w) $1);", bindingFieldName);
// While rendering, we store the updated value for fast
// access again (while the component is still rendering).
// The property value will be reset to default by cleanupAfterRender().
builder.addln("if (isRendering())");
builder.begin();
builder.addln("{0} = $1;", fieldName);
builder.addln("{0} = true;", cachedFieldName);
builder.end();
builder.end();
String mutatorMethodName = EnhanceUtils.createMutatorMethodName(propertyName);
op.addMethod(Modifier.PUBLIC,
new MethodSignature(void.class, mutatorMethodName, new Class[] { propertyType }, null),
builder.toString(), location);
}