return result;
}
private Method buildSetter(Class rootClass, ClassFab classFab, String expression, String[] terms)
{
BodyBuilder builder = new BodyBuilder();
builder.begin();
builder.addln("%s root = (%<s) $1;", ClassFabUtils.toJavaClassName(rootClass));
String previousStep = "root";
Class activeType = rootClass;
for (int i = 0; i < terms.length - 1; i++)
{
String thisStep = "step" + (i + 1);
String term = terms[i];
boolean nullable = term.endsWith("?");
if (nullable)
term = term.substring(0, term.length() - 1);
Method readMethod = readMethodForTerm(activeType, expression, term, true);
// If a primitive type, convert to wrapper type
Class termType = ClassFabUtils.getWrapperType(readMethod.getReturnType());
// $w is harmless for non-wrapper types.
builder.addln(
"%s %s = ($w) %s.%s();",
ClassFabUtils.toJavaClassName(termType),
thisStep,
previousStep,
readMethod.getName());
if (nullable)
builder.addln("if (%s == null) return;", thisStep);
activeType = termType;
previousStep = thisStep;
}
// When writing, the last step is different.
Method writeMethod = writeMethodForTerm(activeType, expression, terms[terms.length - 1]);
if (writeMethod == null)
{
builder.clear();
builder
.addln(
"throw new java.lang.RuntimeException(\"Expression %s for class %s is read-only.\");",
expression,
rootClass.getName());
classFab.addMethod(Modifier.PUBLIC, SET_SIGNATURE, builder.toString());
return null;
}
Class parameterType = writeMethod.getParameterTypes()[0];
Class wrapperType = ClassFabUtils.getWrapperType(parameterType);
builder.addln("%s value = (%<s) $2;", ClassFabUtils.toJavaClassName(wrapperType));
builder.add("%s.%s(value", previousStep, writeMethod.getName());
if (parameterType != wrapperType)
builder.add(".%s()", ClassFabUtils.getUnwrapMethodName(parameterType.getName()));
builder.addln(");");
builder.end();
classFab.addMethod(Modifier.PUBLIC, SET_SIGNATURE, builder.toString());
return writeMethod;
}