/** Adds a private method that will be the replacement for read-access to the field. */
private void addReaderMethod(String fieldName, String cachedFieldName,
String invariantFieldName, boolean cache, String parameterName, String fieldType,
String resourcesFieldName, ClassTransformation transformation)
{
BodyBuilder builder = new BodyBuilder();
builder.begin();
// While the component is still loading, or when the value for the component is cached,
// or if the value is not bound, then return the current value of the field.
builder.addln(
"if (%s || ! %s.isLoaded() || ! %<s.isBound(\"%s\")) return %s;",
cachedFieldName,
resourcesFieldName,
parameterName,
fieldName);
String cast = TransformUtils.getWrapperTypeName(fieldType);
// The ($r) cast will convert the result to the method return type; generally
// this does nothing. but for primitive types, it will unwrap
// the wrapper type back to a primitive.
builder.addln(
"%s result = ($r) ((%s) %s.readParameter(\"%s\", $type));",
fieldType,
cast,
resourcesFieldName,
parameterName);
// If the binding is invariant, then it's ok to cache. Othewise, its only
// ok to cache if a) the @Parameter says to cache and b) the component
// is rendering at the point when field is accessed.
builder.add("if (%s", invariantFieldName);
if (cache)
builder.add(" || %s.isRendering()", resourcesFieldName);
builder.addln(")");
builder.begin();
builder.addln("%s = result;", fieldName);
builder.addln("%s = true;", cachedFieldName);
builder.end();
builder.addln("return result;");
builder.end();
String methodName = transformation.newMemberName("read_parameter", parameterName);
MethodSignature signature = new MethodSignature(Modifier.PRIVATE, fieldType, methodName,
null, null);
transformation.addMethod(signature, builder.toString());
transformation.replaceReadAccess(fieldName, methodName);
}