I have a parameter whose expression class is a List. Inside that List is another list so the data looks something like this.
Class Bean{
String property1
St
There are multiple solutions to achieve what you need.
Create flat structure of your datasource, as example a List
of Map<String,Object>
, looping your Bean
, BeanDetails
example
List<Map<String,Object>> mapList = new ArrayList<Map<String,Object>>();
for(Bean bean : yourBeans){
Map<String,Object> map = new HashMap<String,Object>();
map.put("col1", bean.getProperty1());
map.put("col2", bean.getProperty2());
map.put("col3", bean.getProperty3());
boolean first = true;
if (bean.getBeanDetails()==null|| bean.getBeanDetails().size()==0){
mapList.add(map);
}else{
for (BeanDetails bd:bean.getBeanDetails()){
if (!first){
map = new HashMap<String,Object>();
map."col1", "");//or use printWhenExpression != null in jrxml
....
}else{
first = false;
}
map.put("col4",bd.getDet1());
....
mapList.add(map);
}
}
}
//This now becomes your datasource
JRMapArrayDataSource datasource = new JRMapArrayDataSource(mapList);
Use subreport include a subreport spanning col4 to col6, setup field Bean
in main report
<field name="_THIS" class="com.your.package.Bean"/>
and pass as datasource to the subreport
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{_THIS}.getBeanDetails())]]></dataSourceExpression>
Create you own JRDataSource (I will not submit the whole class, but only some hints on how this can be done, creating a new class implementing JRDataSource
)
JRDataSource myDatasource = new JRDataSource() {
//TODO: keep controll of you list of Beans, current Bean and current BeanDetails, using pointers.
@Override
public boolean next() throws JRException {
//TODO: Implement if there are still records, move to next Bean or BeanDetails
boolean existsRecords = false;
return existsRecords;
}
@Override
public Object getFieldValue(JRField field) throws JRException {
String name = field.getName();
//TODO: On the basis of your pointer, current Bean and current BeanDetails, return the value requested.
return null;
}
};
Make your choice and have fun!