*/
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. We pass the desired type name
// to readParameter(), since its easier to convert it properly to
// a type on that end than in the generated code.
builder.addln("%s result = ($r) ((%s) %s.readParameter(\"%s\", \"%2$s\"));", 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);
TransformMethodSignature signature = new TransformMethodSignature(Modifier.PRIVATE, fieldType, methodName, null,
null);
transformation.addMethod(signature, builder.toString());
transformation.replaceReadAccess(fieldName, methodName);
}