i have a populated arraylist (non-codemodel) in a code generation class using codemodel, and i would like to use it in the generated code. is there any way to do this? it's "crossing worlds" a little, as the generated code does not reference or depend on the code generating it, however i'd still like to use the value of the arraylist without having to go through manually copying it in a traversal of value by value... there has to be a way to do this as there is with strings, numbers, etc...?
my example code is as follows:
private JMethod makeHeadersWrapper( String endPointName, ArrayList<BasicNameValuePair> headersList )
{
JMethod wrapperMethod = definedClass.method( JMod.PUBLIC | JMod.STATIC, codeModel.ref( headersList.getClass() ).narrow( BasicNameValuePair.class ), StringUtils.formatName( "make" + endPointName + "Header", false, StringUtils.FormatType.UP_ENGLISH_WORDS ) );
JVar headersListVar = wrapperMethod.body().decl( wrapperMethod.type(), "headersList", {X} ) );
wrapperMethod.body()._return( headersListVar );
return wrapperMethod;
}
as you see in my declaration of the assignment there is an {X} blank field, which is what i am trying to figure out how to write. that being said, the {X} should reference the 'headersList' parameter in the makeHeadersWrapper signature. is there any way to do this to reference the value of the variable as {X} and having it be a codemodel JExpr(ession)? please help me solve for {X}! :P
thanks sincerely, Piotr
Basically I don't think JExpression
supports Lists. It does have a JArray
but still you'll have to iterate over the headersList
. Up to codemode-2.6 there is no method in JExpr
or JExpression
that iterates over a list. So you cant get away with the iteration part. So with that the standard practice would be iterate over the headersList
and add initialization statements.
Say for example you have a Namevalue pair like
public class BasicNameValuePair {
private String name;
private String value;
public BasicNameValuePair(String name, String value) {
this.name = name;
this.value = value;
}
//getters & setters
}
and initialized like
List<BasicNameValuePair> headerList = new ArrayList<BasicNameValuePair>();
headerList.add(new BasicNameValuePair("1", "1"));
headerList.add(new BasicNameValuePair("2", "2"));
headerList.add(new BasicNameValuePair("3", "3"));
headerList.add(new BasicNameValuePair("4", "4"));
Then you could generate you method body as
private JMethod makeHeadersWrapper( String endPointName, List<BasicNameValuePair> headersList ) {
JClass headerClass = codeModel.ref( headersList.getClass() ).narrow( BasicNameValuePair.class );
JMethod wrapperMethod = definedClass.method( JMod.PUBLIC | JMod.STATIC, headerClass, ( "make" + endPointName + "Header") );
JVar headersListVar = wrapperMethod.body().decl( wrapperMethod.type(), "headersList", JExpr._new(headerClass) );
for(BasicNameValuePair nameValuePair : headersList) {
wrapperMethod.body().add(headersListVar.invoke("add").arg(JExpr._new(nameValuePairClass).arg(nameValuePair.getName()).arg(nameValuePair.getValue())));
}
wrapperMethod.body()._return( headersListVar );
return wrapperMethod;
}
This will generate the code
public static ArrayList<BasicNameValuePair> makeTestHeader() {
ArrayList<BasicNameValuePair> headersList = new ArrayList<BasicNameValuePair>();
headersList.add(new BasicNameValuePair("1", "1"));
headersList.add(new BasicNameValuePair("2", "2"));
headersList.add(new BasicNameValuePair("3", "3"));
headersList.add(new BasicNameValuePair("4", "4"));
return headersList;
}
However ArrayList
have a constructor method using {{ }}
. So you could declare like
List<String> lst = new ArrayList<String>(){{ add("1"); add("2"); add("3"); add("4"); }};
And JExpr
has a direct()
method wherein we could pass a source code directly. Using both of these we could generate the code like below. I wont recommend this approach, but its possible.
private JMethod makeHeadersWrapper( String endPointName, List<BasicNameValuePair> headersList ) {
JMethod wrapperMethod = definedClass.method( JMod.PUBLIC | JMod.STATIC, codeModel.ref( headersList.getClass() ).narrow( BasicNameValuePair.class ), ( "make" + endPointName + "Header") );
JVar headersListVar = wrapperMethod.body().decl( wrapperMethod.type(), "headersList", JExpr.direct(generateListConstructor(headersList)) );
wrapperMethod.body()._return( headersListVar );
return wrapperMethod;
}
private String generateListConstructor(List<BasicNameValuePair> headersList) {
StringBuilder listEpr = new StringBuilder("new ArrayList<scope.BasicNameValuePair>(){{");
for(BasicNameValuePair nameValuePair : headersList) {
listEpr.append("add(new BasicNameValuePair(\"").append(nameValuePair.getName()).append("\", \"").append(nameValuePair.getValue()).append("\")); ");
}
return listEpr.append("}}").toString();
}
This will generate
public static ArrayList<BasicNameValuePair> makeTestHeader() {
ArrayList<BasicNameValuePair> headersList = (new ArrayList<scope.BasicNameValuePair>(){{add(new BasicNameValuePair("1", "1")); add(new BasicNameValuePair("2", "2")); add(new BasicNameValuePair("3", "3")); add(new BasicNameValuePair("4", "4")); }});
return headersList;
}
This is also a valid java code.
This answer may not be the exact one you are looking for but it may give you an idea to progress on. Hope this helps.