Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.sf.jasperreports.components.table.fill.FillTable Maven / Gradle / Ivy
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2019 TIBCO Software Inc. 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 .
*/
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 java.util.concurrent.atomic.AtomicInteger;
import net.sf.jasperreports.components.headertoolbar.HeaderToolbarElement;
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.JRLineBox;
import net.sf.jasperreports.engine.JROrigin;
import net.sf.jasperreports.engine.JRPrintElement;
import net.sf.jasperreports.engine.JRPropertiesMap;
import net.sf.jasperreports.engine.JRPropertyExpression;
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.export.JRPdfExporterTagHelper;
import net.sf.jasperreports.engine.fill.JRFillCloneFactory;
import net.sf.jasperreports.engine.fill.JRFillComponentElement;
import net.sf.jasperreports.engine.fill.JRFillContext;
import net.sf.jasperreports.engine.fill.JRFillDatasetRun;
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.fill.VirtualizableFrame;
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 ([email protected] )
*/
public class FillTable extends BaseFillComponent
{
private static final Log log = LogFactory.getLog(FillTable.class);
protected static final String FILL_CACHE_KEY_TABLE_INSTANCE_COUNTER = FillTable.class.getName() + "#instanceCounter";
protected static final String EXCEPTION_MESSAGE_KEY_UNSUPPORTED_REPORT_DATA_TYPE = "components.table.unsupported.report.data.type";
private final TableComponent table;
private final JRFillObjectFactory factory;
private Map, FillTableSubreportFactory> fillSubreportFactories;
private FillTableSubreport fillSubreport;
private boolean filling;
private List fillColumns;
private int fillWidth;
private Map printFrameTemplates = new HashMap();
public FillTable(TableComponent table, JRFillObjectFactory factory)
{
this.table = table;
this.factory = factory;
// we need to do this for return values with derived variables
JRFillDatasetRun fillDatasetRun = factory.getDatasetRun(table.getDatasetRun());
// this is needed for returned variables with evaluationTime=Auto
factory.registerDatasetRun(fillDatasetRun);
this.fillSubreportFactories = new HashMap, FillTableSubreportFactory>();
}
public FillTable(FillTable table, JRFillCloneFactory factory)
{
super(table, factory);
this.table = table.table;
this.factory = table.factory;
this.fillSubreportFactories = table.fillSubreportFactories;
this.printFrameTemplates = table.printFrameTemplates;
}
@Override
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();
setTableInstanceCounter();
fillSubreport.evaluateSubreport(evaluation);
}
}
protected void setTableInstanceCounter()
{
JRFillContext fillerContext = fillContext.getFiller().getFillContext();
AtomicInteger counter = (AtomicInteger) fillerContext.getFillCache(FILL_CACHE_KEY_TABLE_INSTANCE_COUNTER);
if (counter == null)
{
// we just need a mutable integer, there's no actual concurrency here
counter = new AtomicInteger();
fillerContext.setFillCache(FILL_CACHE_KEY_TABLE_INSTANCE_COUNTER, counter);
}
int instanceIndex = counter.getAndIncrement();
if (log.isDebugEnabled())
{
log.debug("table instance index is " + instanceIndex);
}
fillSubreport.getTableReport().getBaseReport().setTableInstanceIndex(instanceIndex);
}
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;
}
}
return toPrint;
}
protected JRPropertiesMap evaluateProperties(BaseColumn column, byte evaluation) throws JRException
{
JRPropertiesMap staticProperties = column.hasProperties() ? column.getPropertiesMap().cloneProperties() : null;
JRPropertiesMap mergedProperties = null;
JRPropertyExpression[] propExprs = column.getPropertyExpressions();
if (propExprs == null || propExprs.length == 0)
{
mergedProperties = staticProperties;
}
else
{
JRPropertiesMap dynamicProperties = new JRPropertiesMap();
for (int i = 0; i < propExprs.length; i++)
{
JRPropertyExpression prop = propExprs[i];
String value = (String) evaluateExpression(prop.getValueExpression(), evaluation);
//if (value != null) //for some properties such as data properties in metadata exporters, the null value is significant
{
dynamicProperties.setProperty(prop.getName(), value);
}
}
mergedProperties = dynamicProperties.cloneProperties();
mergedProperties.setBaseProperties(staticProperties);
}
return mergedProperties;
}
protected class FillColumnEvaluator implements ColumnVisitor
{
final byte evaluation;
public FillColumnEvaluator(byte evaluation)
{
this.evaluation = evaluation;
}
@Override
public FillColumn visitColumn(Column column)
{
try
{
boolean toPrint = toPrintColumn(column, evaluation);
if (toPrint)
{
JRPropertiesMap properties = evaluateProperties(column, evaluation);
return new FillColumn(column, properties);
}
return null;
}
catch (JRException e)
{
throw new JRRuntimeException(e);
}
}
@Override
public FillColumn visitColumnGroup(ColumnGroup columnGroup)
{
try
{
boolean toPrint = toPrintColumn(columnGroup, evaluation);
FillColumn fillColumn;
if (toPrint)
{
List columns = columnGroup.getColumns();
List subColumns = new ArrayList(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
{
JRPropertiesMap properties = evaluateProperties(columnGroup, evaluation);
fillColumn = new FillColumn(columnGroup, printWidth, subColumns, properties);
}
}
else
{
fillColumn = null;
}
return fillColumn;
}
catch (JRException e)
{
throw new JRRuntimeException(e);
}
}
}
protected void evaluateColumns(byte evaluation)
{
FillColumnEvaluator columnEvaluator = new FillColumnEvaluator(evaluation);
List columns = table.getColumns();
fillColumns = new ArrayList(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
{
FillTableSubreportFactory subreportFactory = fillSubreportFactories.get(fillColumns);
if (subreportFactory == null)
{
subreportFactory = createFillTableSubreportFactory();
fillSubreportFactories.put(fillColumns, subreportFactory);
}
fillSubreport = subreportFactory.createFillSubreport();
}
protected FillTableSubreportFactory createFillTableSubreportFactory() throws JRException
{
JasperReport parentReport = fillContext.getFiller().getJasperReport();
JasperReport containingReport = containingReport(parentReport);
JRDataset reportSubdataset = JRReportUtils.findSubdataset(table.getDatasetRun(),
containingReport);
BuiltinExpressionEvaluatorFactory builtinEvaluatorFactory = new BuiltinExpressionEvaluatorFactory();
String tableReportName = JRAbstractCompiler.getUnitName(containingReport, reportSubdataset);
// clone the table subdataset in order to have a different instance for other
// elements that might be using it.
// we're cloning the subdataset via an object factory in order to preserve
// the relationship between objects (e.g. variables and groups) in the cloned
// dataset
JRDataset tableSubdataset = DatasetCloneObjectFactory.cloneDataset(reportSubdataset);
TableReportDataset reportDataset = new TableReportDataset(tableSubdataset, tableReportName);
TableReport tableReport = new TableReport(fillContext, table, reportDataset, fillColumns, builtinEvaluatorFactory);
if (log.isDebugEnabled())
{
String tableReportXml = new JRXmlWriter(fillContext.getFiller().getJasperReportsContext()).write(tableReport, "UTF-8");
log.debug("Generated table report:\n" + tableReportXml);
}
JRReportCompileData tableReportCompileData = createTableReportCompileData(
containingReport, reportSubdataset);
TableJasperReport compiledTableReport = new TableJasperReport(parentReport, tableReport,
tableReportCompileData,
new TableReportBaseObjectFactory(reportDataset),
"");// no suffix as already included in the report name
TableSubreport subreport =
new TableSubreport(
table.getDatasetRun(),
((JRFillComponentElement)fillContext.getComponentElement()).getParent()
);
return
new FillTableSubreportFactory(
subreport, compiledTableReport,
builtinEvaluatorFactory
);
}
protected JasperReport containingReport(JasperReport parentReport)
{
JasperReport containingReport = parentReport;
while (containingReport instanceof TableJasperReport)
{
containingReport = ((TableJasperReport) containingReport).getParentReport();
}
return containingReport;
}
protected JRReportCompileData createTableReportCompileData(
JasperReport parentReport, JRDataset reportSubdataset)
throws JRException
{
Serializable reportCompileDataObj = parentReport.getCompileData();
if (!(reportCompileDataObj instanceof JRReportCompileData))
{
throw
new JRRuntimeException(
EXCEPTION_MESSAGE_KEY_UNSUPPORTED_REPORT_DATA_TYPE,
new Object[]{reportCompileDataObj.getClass().getName()}
);
}
JRReportCompileData reportCompileData = (JRReportCompileData) reportCompileDataObj;
Serializable datasetCompileData = reportCompileData.getDatasetCompileData(
reportSubdataset);
TableReportCompileData 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);
}
}
tableReportCompileData.copyCrosstabCompileData(reportCompileData);
return tableReportCompileData;
}
@Override
public FillPrepareResult prepare(int availableHeight)
{
try
{
if (fillColumns.isEmpty())
{
//no columns to print
return FillPrepareResult.NO_PRINT_NO_OVERFLOW;
}
JRTemplatePrintFrame printFrame = new JRTemplatePrintFrame(getFrameTemplate(), printElementOriginator);
JRLineBox lineBox = printFrame.getLineBox();
int verticalPadding = lineBox.getTopPadding() + lineBox.getBottomPadding();
FillPrepareResult result =
fillSubreport.prepareSubreport(
availableHeight - verticalPadding,
filling
);
if (verticalPadding != 0)
{
result = result.addStretch(verticalPadding);
}
filling = result.willOverflow();
return result;
}
catch (JRException e)
{
throw new JRRuntimeException(e);
}
}
@Override
public JRPrintElement fill()
{
JRTemplatePrintFrame printFrame = new JRTemplatePrintFrame(getFrameTemplate(), printElementOriginator);
if (fillSubreport.getTableReport().getBaseReport().isInteractiveTable()) {
printFrame.getPropertiesMap().setProperty(HeaderToolbarElement.PROPERTY_TABLE_UUID, fillContext.getComponentElement().getUUID().toString());
}
JRLineBox lineBox = printFrame.getLineBox();
printFrame.setUUID(fillContext.getComponentElement().getUUID());
printFrame.setX(fillContext.getComponentElement().getX());
printFrame.setY(fillContext.getElementPrintY());
printFrame.setHeight(fillSubreport.getContentsStretchHeight() + lineBox.getTopPadding() + lineBox.getBottomPadding());
if (fillSubreport.getTableReport().getBaseReport().isGeneratePdfTags())
{
printFrame.getPropertiesMap().setProperty(JRPdfExporterTagHelper.PROPERTY_TAG_TABLE, JRPdfExporterTagHelper.TAG_FULL);
}
List styles = fillSubreport.getSubreportStyles();
for (Iterator it = styles.iterator(); it.hasNext();)
{
JRStyle style = 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 = it.next();
fillContext.getFiller().getJasperPrint().addOrigin(origin);
}
int contentsWidth = fillWidth;
Collection elements = fillSubreport.getPrintElements();
if (elements != null)
{
VirtualizableFrame virtualizableFrame = new VirtualizableFrame(printFrame,
fillContext.getFiller().getVirtualizationContext(),
fillContext.getFiller().getCurrentPage());
virtualizableFrame.addOffsetElements(elements, 0, 0);
virtualizableFrame.fill();
if (fillSubreport.getPrintContentsWidth() > contentsWidth)
{
contentsWidth = fillSubreport.getPrintContentsWidth();
}
}
printFrame.setWidth(contentsWidth + lineBox.getLeftPadding() + lineBox.getRightPadding());
fillSubreport.subreportPageFilled();
return printFrame;
}
protected JRTemplateFrame getFrameTemplate()
{
JRStyle style = fillContext.getElementStyle();
JRTemplateFrame frameTemplate = printFrameTemplates.get(style);
if (frameTemplate == null)
{
frameTemplate = new JRTemplateFrame(
fillContext.getElementOrigin(),
fillContext.getDefaultStyleProvider());
frameTemplate.setElement(fillContext.getComponentElement());
frameTemplate = deduplicate(frameTemplate);
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;
}
}
protected class FillTableSubreportFactory
{
private final TableSubreport subreport;
private final TableJasperReport compiledTableReport;
private final BuiltinExpressionEvaluatorFactory builtinEvaluatorFactory;
public FillTableSubreportFactory(TableSubreport subreport, TableJasperReport compiledTableReport,
BuiltinExpressionEvaluatorFactory builtinEvaluatorFactory)
{
this.subreport = subreport;
this.compiledTableReport = compiledTableReport;
this.builtinEvaluatorFactory = builtinEvaluatorFactory;
}
public FillTableSubreport createFillSubreport()
{
return new FillTableSubreport(
fillContext, subreport, factory, compiledTableReport,
builtinEvaluatorFactory
);
}
}
}