Accessing collections of string as object properties doesn't work when used in a loop.
I have modified the loop test case as an example.
Developer object add tools collection.
....
private Collection tools;
...
public Developer(String name, String email) {
this.name = name;
this.email = email;
roles = new ArrayList();
tools = new ArrayList();
}
...
public Collection getTools() {
return tools;
}
public void addTool(String tool) {
tools.add(tool);
....
Modify configuration in net.sourceforge.rtf.usecases.loop.RTFJakartaVelocityProjectWithVelocity
...
List developers = new ArrayList();
Developer developer = new Developer("Will Glass-Husain", "wglass@apache.org");
developer.addRole("Java Developer");
developer.addRole("Release Manager");
developer.addTool("Eclipse");
developer.addTool("VI");
developers.add(developer);
context.put("developer", developer);
context.put("tools", developer.getTools());
...
Modify loop.rtf
...
Test 11: Loop over the tools in a simple table – works
«$tools»
Test 12: Loop over developer tools in a simple table – doesn’t work
«$developer.Tools»
...
Let me know if you need additional information.
Logged In: YES
user_id=1978587
Originator: YES
File Added: loop.rtf
Modified loop.rtf
Modified RTFJakartaVelocityProjectWithVelocity.java
Logged In: YES
user_id=1978587
Originator: YES
File Added: RTFJakartaVelocityProjectWithVelocity.java
Logged In: YES
user_id=1978587
Originator: YES
File Added: Developer.java
Modified Developer.java
Logged In: YES
user_id=1978587
Originator: YES
It fails in 2 ways. First the data is never put into the generated document. Second the entire table is repeated twice, with blank data, instead of 2 rows.
Logged In: YES
user_id=1006268
Originator: NO
Hi,
Yes I understand your problem.
I will try to correct that when I will have time.
Regards Angelo
Logged In: YES
user_id=1850799
Originator: NO
Hi,
I've had a similar issue.
To fix it I've added 7 lines of code to the 'getObjectValueList' method of 'net.sourceforge.rtf.template.velocity.RTFVelocityTransformerImpl' class.
In fact, I'm newbie in OpenSource projects and I don't know how to include my code to further releases of RTFTemplate.
I will be very pleased to receive any instructions or advice about it, otherwise I will explore it myself and add fixed code in a week or two.
Logged In: YES
user_id=1006268
Originator: NO
Hi vetaleg,
Thank you for your answer. If you want you can send me your code and explain me what you have changed.
Thank you very much.
Regards Angelo
Logged In: YES
user_id=1850799
Originator: NO
Hi again, Angelo.
Talking about the example above we should mention a mergefield element in the fields.xml corresponding to «$developer.Tools»:
<mergefield>
<list>true</list>
<listinfo>developer.[Tools]</listinfo>
<name>developer.[Tools]</name>
<mergefield>
If I understand the code of RTFVelocityTransformerImpl correctly it assumes that the last element in listInfo chain should be 'getter' field. That's why it transforms «$developer.Tools» field with start_loop and end_loop bookmarks into:
#foreach ($item_developer in $developer.tools) $item_developer.tools #end
(sorry if syntax isn't right, I haven't exact examples offhand)
Actually we need other transformation:
#foreach ($item_developer_tool in $developer.tools) $item_developer_tools #end
So, here is my fix:
I check if the field has collection element at the last position of chain described in <listInfo>. If it is true we should generate cycle variable by adding 'item_' and replacing '.' with '_'.
Code (I post the whole method of net.sourceforge.rtf.template.velocity.RTFVelocityTransformerImpl):
protected String getObjectValueList(String fieldName,
String fieldNameWithListInfo, boolean withGetter) {
String objectName = "";
if (fieldNameWithListInfo != null && fieldNameWithListInfo.length() > 0) {
// eg : $workspace.[Developers].manager.Name must be transformed
// into $item_workspace_Developers.manager.Name
int indexLastEndedArray = fieldNameWithListInfo.lastIndexOf("]");
if (indexLastEndedArray > 0) {
// Test if there is several object after list (eg:manager.Name)
if (fieldNameWithListInfo.indexOf(".", indexLastEndedArray + 2) > 0) {
String s = fieldNameWithListInfo.substring(0,
indexLastEndedArray);
s = s.replaceAll("\\[", "");
objectName = getObjectValueList(s, true);
objectName = objectName.replace('.', '_');
if (!withGetter)
return objectName;
else {
return objectName
+ fieldNameWithListInfo.substring(
indexLastEndedArray + 1,
fieldNameWithListInfo.length());
}
}
// Here is my fix starts
if (fieldNameWithListInfo.length() == indexLastEndedArray + 1) {
fieldNameWithListInfo = fieldNameWithListInfo.replaceAll("\\[", "");
fieldNameWithListInfo = fieldNameWithListInfo.replaceAll("\\]", "");
objectName = getObjectValueList(fieldNameWithListInfo, true);
objectName = objectName.replace('.', '_');
return objectName;
}
// Here is my fix ends
}
}
// HERE : After list there is one getter
// OLD transformation :
return getObjectValueList(fieldName, withGetter);
}
Sorry, if I was not quite clear. I'll answer any of your questions.
Logged In: YES
user_id=1850799
Originator: NO
Frankly speaking, I'm not 100% sure this fix won't break any other usecases but it works perfectly for my project.
Another question is when can I legally use your tool with proper fixes in my project and how could I help you with this issue?
Thank you.
Best regards, Vitaliy.