Reputation: 33
I am trying to figure out how to use a loop to build a JExpression
that I can use in an .assign()
call. I know that you can do something like JExpr.invoke("methodA").invoke("methodB")
with JCodeModel, but I want to be able to add each .invoke()
method based on a list of method names. Does anyone know how to do this?
Example of my Generator code [this is assuming that I have modified the ArrayList.add() method to return the ArrayList]:
JDefinedClass newClass = jCodeModel._class("com.me.GeneratedClass");
JClass refObject = jCodeModel.ref(Object.class);
JClass refArrayList = jCodeModel.ref(ArrayList.class);
JFieldVar objectList = newClass.field(refArrayList, "objects");
JBlock methodBody = newClass.method(JMod.PUBLIC, refArrayList, "getNewObjectList");
String[] methodsToInvoke = {"add", "add", "add"};
JExpression rhsAssignmentExpression = JExpr._new(refArrayList).narrow(refObject);
for(String methodName : methodsToInvoke) {
rhsAssignmentExpression.invoke(methodName).arg(JExpr._new(refObject));
}
methodBody.assign(objectList, rhsAssignmentExpression);
methodBody._return(objectList);
Example of what I am trying to generate:
class GeneratedClass {
ArrayList<Object> objects;
public ArrayList<Object> getNewObjectList()
{
objects = new ArrayList<Object>().add(new Object()).add(new Object()).add(new Object());
return objects;
}
}
My problem is that this method doesn't chain the invoke methods, but replaces them so the generated code looks like this:
class GeneratedClass {
ArrayList<Object> objects;
public ArrayList<Object> getNewObjectList()
{
objects = new ArrayList<Object>().add(new Object());
return objects;
}
}
Upvotes: 3
Views: 2057
Reputation: 11113
What you will need to do is store an intermediate value for each invoke() JExpression call:
JExpression rhsAssignmentExpression = JExpr._new(refArrayList);
for(String methodName : methodsToInvoke) {
rhsAssignmentExpression = rhsAssignmentExpression.invoke(methodName).arg(JExpr._new(refObject));
}
This avoids redefining the invocation each time, and effectively chains the calls. The result is the following:
public class GeneratedClass {
public ArrayList objects;
public ArrayList getNewObjectList() {
objects = new ArrayList().add(new Object()).add(new Object()).add(new Object());
return objects;
}
}
Upvotes: 1
Reputation: 139
This could also be done by having JCodeModel print raw strings instead of declaring the JCode objects. For this particular problem, there are no java-imports that need to be generated – so that this can be done with directStatement().
StringBuilder expression = new StringBuilder();
expression.append (“objects = new ArrayList<Object>()”);
if ((methodsToInvoke != null) && (methodsToInvoke.length > 0))
{
for(String methodName : methodsToInvoke)
{
expression.append(“.add(new Object())”);
}
}
expression.append(“;”);
methodBoby.directStatement(expression.toString());
Upvotes: 1