private String generateSubReport(
final Input input,
final Map<String, Class<?>> columns) throws JRException, ClassNotFoundException, IOException {
byte[] bytes = input.template.getConfiguration().loadFile(this.jasperTemplate);
final JasperDesign templateDesign = JRXmlLoader.load(new ByteArrayInputStream(bytes));
int headerHeight = templateDesign.getColumnHeader().getHeight();
final JRDesignSection detailSection = (JRDesignSection) templateDesign.getDetailSection();
int detailHeight = detailSection.getBands()[0].getHeight();
final JRElement sampleHeaderEl = templateDesign.getColumnHeader().getElements()[0];
int headerPosX = sampleHeaderEl.getX();
int headerPosY = sampleHeaderEl.getY();
final JRElement sampleDetailEl = detailSection.getBands()[0].getElements()[0];
int detailPosX = sampleDetailEl.getX();
int detailPosY = sampleDetailEl.getY();
clearFields(templateDesign);
removeDetailBand(templateDesign);
JRDesignBand headerBand = new JRDesignBand();
headerBand.setHeight(headerHeight);
templateDesign.setColumnHeader(headerBand);
JRDesignBand detailBand = new JRDesignBand();
detailBand.setHeight(detailHeight);
detailSection.addBand(detailBand);
final int columnWidth;
final int numColumns = columns.size();
if (columns.isEmpty()) {
columnWidth = templateDesign.getPageWidth();
} else {
columnWidth = (templateDesign.getPageWidth() - (SPACE_BETWEEN_COLS * (numColumns - 1))) / numColumns;
}
int i = 0;
for (Map.Entry<String, Class<?>> entry : columns.entrySet()) {
i++;
JRStyle columnDetailStyle;
JRStyle columnHeaderStyle;
if (i == 1) {
columnDetailStyle = getStyle(templateDesign, this.firstDetailStyle, this.detailStyle);
columnHeaderStyle = getStyle(templateDesign, this.firstHeaderStyle, this.headerStyle);
} else if (i == numColumns) {
columnDetailStyle = getStyle(templateDesign, this.lastDetailStyle, this.detailStyle);
columnHeaderStyle = getStyle(templateDesign, this.lastHeaderStyle, this.headerStyle);
} else {
columnDetailStyle = templateDesign.getStylesMap().get(this.detailStyle);
columnHeaderStyle = templateDesign.getStylesMap().get(this.headerStyle);
}
String columnName = entry.getKey();
Class<?> valueClass = String.class;
if (entry.getValue() != null) {
valueClass = entry.getValue();
}
// Create a Column Field
JRDesignField field = new JRDesignField();
field.setName(columnName);
if (this.converters.isEmpty()) {
// if there are no cell converters, the type for all cells in a column should be the same.
// so we can set a specific type. otherwise we have to set a generic type (Object.class).
field.setValueClass(valueClass);
} else {
field.setValueClass(Object.class);
}
templateDesign.addField(field);
// Add a Header Field to the headerBand
JRDesignTextField colHeaderField = new JRDesignTextField();
colHeaderField.setX(headerPosX);
colHeaderField.setY(headerPosY);