/* * JasperReports - Free Java Reporting Library. * Copyright (C) 2001 - 2009 Jaspersoft Corporation. All rights reserved. * http://www.jaspersoft.com * * Unless you have purchased a commercial license agreement from Jaspersoft, * the following license terms apply: * * This program is part of JasperReports. * * JasperReports is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JasperReports is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with JasperReports. If not, see <http://www.gnu.org/licenses/>. */ package net.sf.jasperreports.components.table.fill; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import net.sf.jasperreports.components.table.BaseColumn; import net.sf.jasperreports.components.table.Column; import net.sf.jasperreports.components.table.ColumnGroup; import net.sf.jasperreports.components.table.ColumnVisitor; import net.sf.jasperreports.components.table.TableComponent; import net.sf.jasperreports.engine.JRDataset; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRExpression; import net.sf.jasperreports.engine.JROrigin; import net.sf.jasperreports.engine.JRPrintElement; import net.sf.jasperreports.engine.JRRuntimeException; import net.sf.jasperreports.engine.JRStyle; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.component.BaseFillComponent; import net.sf.jasperreports.engine.component.FillPrepareResult; import net.sf.jasperreports.engine.design.JRAbstractCompiler; import net.sf.jasperreports.engine.design.JRReportCompileData; import net.sf.jasperreports.engine.fill.JRFillObjectFactory; import net.sf.jasperreports.engine.fill.JRTemplateFrame; import net.sf.jasperreports.engine.fill.JRTemplatePrintFrame; import net.sf.jasperreports.engine.util.JRReportUtils; import net.sf.jasperreports.engine.xml.JRXmlWriter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * * * @author Lucian Chirita (lucianc@users.sourceforge.net) * @version $Id: FillTable.java 3735 2010-04-12 15:45:13Z lucianc $ */ public class FillTable extends BaseFillComponent { private static final Log log = LogFactory.getLog(FillTable.class); private final TableComponent table; private final JRFillObjectFactory factory; private final Map<List<FillColumn>, FillTableSubreport> fillSubreports = new HashMap<List<FillColumn>, FillTableSubreport>(); private FillTableSubreport fillSubreport; private boolean filling; private List<FillColumn> fillColumns; private int fillWidth; private Map printFrameTemplates = new HashMap(); public FillTable(TableComponent table, JRFillObjectFactory factory) { this.table = table; this.factory = factory; } public void evaluate(byte evaluation) throws JRException { if (filling) { log.warn("Table fill did not complete, canceling previous table subreport"); fillSubreport.cancelSubreportFill(); } filling = false; evaluateColumns(evaluation); if (!fillColumns.isEmpty()) { createFillSubreport(); fillSubreport.evaluateSubreport(evaluation); } } protected boolean toPrintColumn(BaseColumn column, byte evaluation) throws JRException { boolean toPrint; JRExpression printWhenExpression = column.getPrintWhenExpression(); if (printWhenExpression == null) { toPrint = true; } else { Boolean printWhenVal = (Boolean) evaluateExpression( printWhenExpression, evaluation); if (printWhenVal == null) { toPrint = false; } else { toPrint = printWhenVal.booleanValue(); } } return toPrint; } protected class FillColumnEvaluator implements ColumnVisitor<FillColumn> { final byte evaluation; public FillColumnEvaluator(byte evaluation) { this.evaluation = evaluation; } public FillColumn visitColumn(Column column) { try { boolean toPrint = toPrintColumn(column, evaluation); return toPrint ? new FillColumn(column) : null; } catch (JRException e) { throw new JRRuntimeException(e); } } public FillColumn visitColumnGroup(ColumnGroup columnGroup) { try { boolean toPrint = toPrintColumn(columnGroup, evaluation); FillColumn fillColumn; if (toPrint) { List<BaseColumn> columns = columnGroup.getColumns(); List<FillColumn> subColumns = new ArrayList<FillColumn>(columns.size()); int printWidth = 0; for (BaseColumn column : columns) { FillColumn fillSubColumn = column.visitColumn(this); if (fillSubColumn != null) { printWidth += fillSubColumn.getWidth(); subColumns.add(fillSubColumn); } } if (subColumns.isEmpty()) { // no sub columns prints // the column group won't print either fillColumn = null; } else { fillColumn = new FillColumn(columnGroup, printWidth, subColumns); } } else { fillColumn = null; } return fillColumn; } catch (JRException e) { throw new JRRuntimeException(e); } } } protected void evaluateColumns(byte evaluation) { FillColumnEvaluator columnEvaluator = new FillColumnEvaluator(evaluation); List<BaseColumn> columns = table.getColumns(); fillColumns = new ArrayList<FillColumn>(columns.size()); fillWidth = 0; for (BaseColumn column : columns) { FillColumn fillColumn = column.visitColumn(columnEvaluator); if (fillColumn != null) { fillColumns.add(fillColumn); fillWidth += fillColumn.getWidth(); } } } protected void createFillSubreport() throws JRException { fillSubreport = fillSubreports.get(fillColumns); if (fillSubreport == null) { fillSubreport = createFillTableSubreport(); fillSubreports.put(fillColumns, fillSubreport); } } protected FillTableSubreport createFillTableSubreport() throws JRException { JasperReport parentReport = fillContext.getFiller().getJasperReport(); JRDataset reportSubdataset = JRReportUtils.findSubdataset(table.getDatasetRun(), parentReport); Map<JRExpression, BuiltinExpressionEvaluator> builtinEvaluators = new HashMap<JRExpression, BuiltinExpressionEvaluator>(); String tableReportName = JRAbstractCompiler.getUnitName(parentReport, reportSubdataset); // clone the table subdataset in order to have a different instance for other // elements that might be using it JRDataset tableSubdataset = (JRDataset) reportSubdataset.clone(); TableReportDataset reportDataset = new TableReportDataset(tableSubdataset, tableReportName); TableReport tableReport = new TableReport(fillContext, reportDataset, fillColumns, builtinEvaluators); if (log.isDebugEnabled()) { String tableReportXml = JRXmlWriter.writeReport(tableReport, "UTF-8"); log.debug("Generated table report:\n" + tableReportXml); } JRReportCompileData tableReportCompileData = createTableReportCompileData( parentReport, reportSubdataset); JasperReport compiledTableReport = new JasperReport(tableReport, parentReport.getCompilerClass(), tableReportCompileData, new TableReportBaseObjectFactory(reportDataset), "");// no suffix as already included in the report name TableSubreport subreport = new TableSubreport(table.getDatasetRun(), fillContext); return new FillTableSubreport( fillContext.getFiller(), subreport, factory, compiledTableReport, builtinEvaluators); } protected JRReportCompileData createTableReportCompileData( JasperReport parentReport, JRDataset reportSubdataset) throws JRException { Serializable reportCompileDataObj = parentReport.getCompileData(); if (!(reportCompileDataObj instanceof JRReportCompileData)) { throw new JRRuntimeException("Unsupported compiled report data of type " + reportCompileDataObj.getClass().getName()); } JRReportCompileData reportCompileData = (JRReportCompileData) reportCompileDataObj; Serializable datasetCompileData = reportCompileData.getDatasetCompileData( reportSubdataset); JRReportCompileData tableReportCompileData = new TableReportCompileData( parentReport); tableReportCompileData.setMainDatasetCompileData(datasetCompileData); JRDataset[] datasets = parentReport.getDatasets(); if (datasets != null) { for (JRDataset dataset : datasets) { Serializable compileData = reportCompileData.getDatasetCompileData(dataset); tableReportCompileData.setDatasetCompileData(dataset, compileData); } } return tableReportCompileData; } public FillPrepareResult prepare(int availableHeight) { try { if (fillColumns.isEmpty()) { //no columns to print return FillPrepareResult.NO_PRINT_NO_OVERFLOW; } FillPrepareResult result = fillSubreport.prepareSubreport( availableHeight, filling); filling = result.willOverflow(); return result; } catch (JRException e) { throw new JRRuntimeException(e); } } public JRPrintElement fill() { JRTemplatePrintFrame printFrame = new JRTemplatePrintFrame(getFrameTemplate()); printFrame.setX(fillContext.getComponentElement().getX()); printFrame.setY(fillContext.getElementPrintY()); printFrame.setWidth(fillWidth); printFrame.setHeight(fillSubreport.getContentsStretchHeight()); List styles = fillSubreport.getSubreportStyles(); for (Iterator it = styles.iterator(); it.hasNext();) { JRStyle style = (JRStyle) it.next(); try { fillContext.getFiller().addPrintStyle(style); } catch (JRException e) { throw new JRRuntimeException(e); } } List origins = fillSubreport.getSubreportOrigins(); for (Iterator it = origins.iterator(); it.hasNext();) { JROrigin origin = (JROrigin) it.next(); fillContext.getFiller().getJasperPrint().addOrigin(origin); } Collection elements = fillSubreport.getPrintElements(); if (elements != null) { for (Iterator it = elements.iterator(); it.hasNext();) { JRPrintElement element = (JRPrintElement) it.next(); printFrame.addElement(element); } } return printFrame; } protected JRTemplateFrame getFrameTemplate() { JRStyle style = fillContext.getElementStyle(); JRTemplateFrame frameTemplate = (JRTemplateFrame) printFrameTemplates.get(style); if (frameTemplate == null) { frameTemplate = new JRTemplateFrame( fillContext.getElementOrigin(), fillContext.getDefaultStyleProvider()); frameTemplate.setElement(fillContext.getComponentElement()); printFrameTemplates.put(style, frameTemplate); } return frameTemplate; } @Override public void rewind() { if (filling) { if (log.isDebugEnabled()) { log.debug("Rewinding table subreport"); } try { fillSubreport.rewind(); } catch (JRException e) { throw new JRRuntimeException(e); } filling = false; } } }