Question

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;
   }
}
Was it helpful?

Solution

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;
    }

}

OTHER TIPS

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());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top