net.sf.jasperreports.engine.fill.BaseReportFiller Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jasperreports Show documentation
Show all versions of jasperreports Show documentation
Free Java Reporting Library
/*
* 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.engine.fill;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import org.apache.commons.javaflow.api.continuable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.jasperreports.engine.BookmarkHelper;
import net.sf.jasperreports.engine.JRAbstractScriptlet;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRDataset;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JRPrintElement;
import net.sf.jasperreports.engine.JRPrintPage;
import net.sf.jasperreports.engine.JRPropertiesUtil;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JRVirtualizer;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.JasperReportsContext;
import net.sf.jasperreports.engine.ReportContext;
import net.sf.jasperreports.engine.base.JRVirtualPrintPage;
import net.sf.jasperreports.engine.type.CalculationEnum;
import net.sf.jasperreports.engine.util.DefaultFormatFactory;
import net.sf.jasperreports.engine.util.FormatFactory;
import net.sf.jasperreports.engine.util.JRGraphEnvInitializer;
import net.sf.jasperreports.repo.RepositoryContext;
import net.sf.jasperreports.repo.SimpleRepositoryContext;
/**
* @author Teodor Danciu ([email protected])
*/
public abstract class BaseReportFiller implements ReportFiller
{
private static final Log log = LogFactory.getLog(BaseReportFiller.class);
protected JasperReportsContext jasperReportsContext;
protected JRPropertiesUtil propertiesUtil;
protected JRFillContext fillContext;
protected FillerParent parent;
protected final int fillerId;
protected List printTransferPropertyPrefixes;
protected JasperReportSource reportSource;
/**
* The report.
*/
protected JasperReport jasperReport;
protected RepositoryContext repositoryContext;
protected JRCalculator calculator;
protected final JRFillObjectFactory factory;
/**
* Main report dataset.
*/
protected JRFillDataset mainDataset;
/**
* Map of datasets ({@link JRFillDataset JRFillDataset} objects} indexed by name.
*/
protected Map datasetMap;
protected DelayedFillActions delayedActions;
protected JRAbstractScriptlet scriptlet;
protected FormatFactory formatFactory;
protected boolean ignorePagination;
protected BookmarkHelper bookmarkHelper;
protected JRVirtualizationContext virtualizationContext;
protected JasperPrint jasperPrint;
protected Thread fillingThread;
private boolean isInterrupted;
private boolean threadInterrupted;
protected FillListener fillListener;
protected int usedPageWidth = 0;
public BaseReportFiller(JasperReportsContext jasperReportsContext, JasperReport jasperReport,
FillerParent parent) throws JRException
{
this(jasperReportsContext, SimpleJasperReportSource.from(jasperReport), parent);
}
public BaseReportFiller(JasperReportsContext jasperReportsContext, JasperReportSource reportSource,
FillerParent parent) throws JRException
{
JRGraphEnvInitializer.initializeGraphEnv();
setJasperReportsContext(jasperReportsContext);
this.reportSource = reportSource;
this.jasperReport = reportSource.getReport();
this.repositoryContext = SimpleRepositoryContext.of(jasperReportsContext, reportSource.getRepositoryReportContext());
jasperReportSet();
this.parent = parent;
DatasetExpressionEvaluator initEvaluator = null;
if (parent == null)
{
fillContext = new JRFillContext(this);
printTransferPropertyPrefixes = readPrintTransferPropertyPrefixes();
}
else
{
fillContext = parent.getFiller().fillContext;
printTransferPropertyPrefixes = parent.getFiller().printTransferPropertyPrefixes;
initEvaluator = parent.getCachedEvaluator();
}
this.fillerId = fillContext.generatedFillerId();
if (log.isDebugEnabled())
{
log.debug("Fill " + fillerId + ": created for " + jasperReport.getName());
}
if (initEvaluator == null)
{
calculator = JRFillDataset.createCalculator(jasperReportsContext, jasperReport, jasperReport.getMainDataset());
}
else
{
calculator = new JRCalculator(initEvaluator);
}
jasperPrint = new JasperPrint();
factory = initFillFactory();
createDatasets();
mainDataset = factory.getDataset(jasperReport.getMainDataset());
if (parent == null)
{
FillDatasetPosition masterFillPosition = new FillDatasetPosition(null);
mainDataset.setFillPosition(masterFillPosition);
}
delayedActions = new DelayedFillActions(this);
if (log.isDebugEnabled())
{
log.debug("created delayed actions " + delayedActions.getId() + " for filler " + fillerId);
}
}
protected abstract void jasperReportSet();
private List readPrintTransferPropertyPrefixes()
{
List transferProperties = propertiesUtil.getProperties(
JasperPrint.PROPERTIES_PRINT_TRANSFER_PREFIX);
List prefixes = new ArrayList(transferProperties.size());
for (JRPropertiesUtil.PropertySuffix property : transferProperties)
{
String transferPrefix = property.getValue();
if (transferPrefix != null && transferPrefix.length() > 0)
{
prefixes.add(transferPrefix);
}
}
return prefixes;
}
protected abstract JRFillObjectFactory initFillFactory();
private void createDatasets() throws JRException
{
datasetMap = new HashMap();
JRDataset[] datasets = jasperReport.getDatasets();
if (datasets != null && datasets.length > 0)
{
for (int i = 0; i < datasets.length; i++)
{
JRFillDataset fillDataset = factory.getDataset(datasets[i]);
fillDataset.createCalculator(jasperReport);
datasetMap.put(datasets[i].getName(), fillDataset);
}
}
}
protected final void initDatasets() throws JRException
{
mainDataset.initElementDatasets(factory);
initDatasets(factory);
mainDataset.checkVariableCalculationReqs(factory);
mainDataset.setCalculator(calculator);
mainDataset.initCalculator();
}
private void initDatasets(JRFillObjectFactory factory)
{
for (Iterator it = datasetMap.values().iterator(); it.hasNext();)
{
JRFillDataset dataset = it.next();
dataset.inheritFromMain();
dataset.initElementDatasets(factory);
}
}
protected final void createBoundElementMaps(JREvaluationTime evaluationTime)
{
delayedActions.createDelayedEvaluationTime(evaluationTime);
}
/**
* Adds a fill lister to be notified by events that occur during the fill.
*
* @param fillListener the listener to add
*/
@Override
public void addFillListener(FillListener fillListener)
{
this.fillListener = CompositeFillListener.addListener(this.fillListener, fillListener);
}
public JasperReportsContext getJasperReportsContext()
{
return jasperReportsContext;
}
public RepositoryContext getRepositoryContext()
{
return repositoryContext;
}
public JRPropertiesUtil getPropertiesUtil()
{
return propertiesUtil;
}
public JasperReportSource getReportSource()
{
return reportSource;
}
/**
* Returns the report.
*
* @return the report
*/
public JasperReport getJasperReport()
{
return jasperReport;
}
public JasperPrint getJasperPrint()
{
return jasperPrint;
}
protected void setJasperReportsContext(JasperReportsContext jasperReportsContext)
{
this.jasperReportsContext = jasperReportsContext;
this.propertiesUtil = JRPropertiesUtil.getInstance(jasperReportsContext);
}
protected final void setParametersToContext(Map parameterValues)
{
@SuppressWarnings("deprecation")
JasperReportsContext localContext =
net.sf.jasperreports.engine.util.LocalJasperReportsContext.getLocalContext(jasperReportsContext, parameterValues);
if (localContext != jasperReportsContext)
{
setJasperReportsContext(localContext);
}
}
protected void initVirtualizationContext(Map parameterValues)
{
if (isSubreport())
{
if (fillContext.isUsingVirtualizer())
{
if (parent.isParentPagination())// using this method to tell between part and band parents
{
// this is a filler of a subreport in a band parent, creating a subcontext for the subreport.
// this allows setting a separate listener, and guarantees that
// the current subreport page is not externalized.
virtualizationContext = new JRVirtualizationContext(fillContext.getVirtualizationContext());//FIXME lucianc clear this context from the virtualizer
// setting per subreport page size
setVirtualPageSize(parameterValues);
}
else
{
// the parent is a part filler, using the master virtualization context
//FIXMEBOOK JRVirtualPrintPage.PROPERTY_VIRTUAL_PAGE_ELEMENT_SIZE at part level is not used
virtualizationContext = fillContext.getVirtualizationContext();
}
}
}
else
{
/* Virtualizer */
JRVirtualizer virtualizer = (JRVirtualizer) parameterValues.get(JRParameter.REPORT_VIRTUALIZER);
if (virtualizer == null)
{
return;
}
if (log.isDebugEnabled())
{
log.debug("Fill " + fillerId + ": using virtualizer " + virtualizer);
}
fillContext.setUsingVirtualizer(true);
virtualizationContext = fillContext.getVirtualizationContext();
virtualizationContext.setVirtualizer(virtualizer);
setVirtualPageSize(parameterValues);
JRVirtualizationContext.register(virtualizationContext, jasperPrint);
}
if (virtualizationContext != null && log.isDebugEnabled())
{
log.debug("filler " + fillerId + " created virtualization context " + virtualizationContext);
}
}
protected void setVirtualPageSize(Map parameterValues)
{
// see if we have a parameter for the page size
Integer virtualPageSize = (Integer) parameterValues.get(
JRVirtualPrintPage.PROPERTY_VIRTUAL_PAGE_ELEMENT_SIZE);
if (virtualPageSize == null)
{
// check if we have a property
String pageSizeProp = jasperReport.getPropertiesMap().getProperty(
JRVirtualPrintPage.PROPERTY_VIRTUAL_PAGE_ELEMENT_SIZE);
if (pageSizeProp != null)
{
virtualPageSize = JRPropertiesUtil.asInteger(pageSizeProp);
}
}
if (virtualPageSize != null)
{
if (log.isDebugEnabled())
{
log.debug("virtual page size " + virtualPageSize);
}
// override the default
virtualizationContext.setPageElementSize(virtualPageSize);
}
}
@Override
@continuable
public JasperPrint fill(Map parameterValues, Connection conn) throws JRException
{
if (parameterValues == null)
{
parameterValues = new HashMap();
}
setConnectionParameterValue(parameterValues, conn);
return fill(parameterValues);
}
protected void setConnectionParameterValue(Map parameterValues, Connection conn)
{
mainDataset.setConnectionParameterValue(parameterValues, conn);
}
@Override
@continuable
public JasperPrint fill(Map parameterValues, JRDataSource ds) throws JRException
{
if (parameterValues == null)
{
parameterValues = new HashMap();
}
setDatasourceParameterValue(parameterValues, ds);
return fill(parameterValues);
}
protected void setDatasourceParameterValue(Map parameterValues, JRDataSource ds)
{
mainDataset.setDatasourceParameterValue(parameterValues, ds);
}
protected void setParameters(Map parameterValues) throws JRException
{
initVirtualizationContext(parameterValues);
setFormatFactory(parameterValues);
setIgnorePagination(parameterValues);
if (parent == null)
{
ReportContext reportContext = (ReportContext) parameterValues.get(JRParameter.REPORT_CONTEXT);
fillContext.setReportContext(reportContext);
}
mainDataset.setParameterValues(parameterValues);
mainDataset.evaluateFieldProperties();
mainDataset.initDatasource();
this.scriptlet = mainDataset.delegateScriptlet;
if (!isSubreport())
{
fillContext.setMasterFormatFactory(getFormatFactory());
fillContext.setMasterLocale(getLocale());
fillContext.setMasterTimeZone(getTimeZone());
}
}
protected void setBookmarkHelper()
{
boolean isCreateBookmarks = propertiesUtil.getBooleanProperty(mainDataset,
JasperPrint.PROPERTY_CREATE_BOOKMARKS, false);
if (isCreateBookmarks)
{
boolean collapseMissingLevels = propertiesUtil.getBooleanProperty(mainDataset,
JasperPrint.PROPERTY_COLLAPSE_MISSING_BOOKMARK_LEVELS, false);
bookmarkHelper = new BookmarkHelper(collapseMissingLevels);
}
}
protected void setIgnorePagination(Map parameterValues)
{
boolean ignore;
if (parent == null)
{
ignore = getOwnIgnorePagination(parameterValues, false);
}
else
{
if (parent.isParentPagination())
{
// the parent drives pagination, not looking at parameter and flag
ignore = parent.getFiller().ignorePagination;
}
else
{
// subreport parts are allowed to ignore pagination even if the parent does not have the flag
// the report attribute overrides the parent only when set to true
Boolean ownIgnorePagination = getOwnIgnorePagination(parameterValues, true);
if (ownIgnorePagination != null)
{
ignore = ownIgnorePagination;
}
else
{
// default to the parent
ignore = parent.getFiller().ignorePagination;
}
}
}
ignorePagination = ignore;
parameterValues.put(JRParameter.IS_IGNORE_PAGINATION, ignorePagination);
ignorePaginationSet(parameterValues);
}
protected Boolean getOwnIgnorePagination(Map parameterValues, boolean onlySetAttribute)
{
Boolean isIgnorePaginationParam = (Boolean) parameterValues.get(JRParameter.IS_IGNORE_PAGINATION);
if (isIgnorePaginationParam != null)
{
return isIgnorePaginationParam;
}
boolean ignorePaginationAttribute = jasperReport.isIgnorePagination();
if (ignorePaginationAttribute)
{
return ignorePaginationAttribute;
}
return onlySetAttribute ? null : false;
}
protected abstract void ignorePaginationSet(Map parameterValues);
public boolean isIgnorePagination()
{
return ignorePagination;
}
protected boolean isInterrupted()
{
return (isInterrupted || threadInterrupted || (parent != null && parent.getFiller().isInterrupted()));
}
protected boolean isDeliberatelyInterrupted()
{
return (isInterrupted || (parent != null && parent.getFiller().isDeliberatelyInterrupted()));
}
protected void setInterrupted(boolean isInterrupted)
{
this.isInterrupted = isInterrupted;
}
protected void checkInterrupted()
{
if (Thread.interrupted())
{
threadInterrupted = true;
}
if (isInterrupted())
{
if (log.isDebugEnabled())
{
log.debug("Fill " + fillerId + ": interrupting");
}
throw new JRFillInterruptedException();
}
}
@Override
public JRFillContext getFillContext()
{
return fillContext;
}
public JRVirtualizationContext getVirtualizationContext()
{
return virtualizationContext;
}
public JRFillDataset getMainDataset()
{
return mainDataset;
}
/**
* Returns the map of parameter values.
*
* @return the map of parameter values
*/
public Map getParameterValuesMap()
{
return mainDataset.getParameterValuesMap();
}
/**
* Returns the report parameters indexed by name.
*
* @return the report parameters map
*/
protected Map getParametersMap()
{
return mainDataset.parametersMap;
}
/**
* Returns the value of a parameter.
*
* @param parameterName the parameter name
* @return the parameter value
*/
public Object getParameterValue(String parameterName)
{
return mainDataset.getParameterValue(parameterName);
}
/**
* Returns the report locale.
*
* @return the report locale
*/
protected Locale getLocale()
{
return mainDataset.getLocale();
}
/**
* Returns the report time zone.
*
* @return the report time zone
*/
protected TimeZone getTimeZone()
{
return mainDataset.timeZone;
}
/**
* Adds a variable calculation request.
*
* @param variableName
* the variable name
* @param calculation
* the calculation type
*/
protected void addVariableCalculationReq(String variableName, CalculationEnum calculation)
{
mainDataset.addVariableCalculationReq(variableName, calculation);
}
/**
* Returns a report variable.
*
* @param variableName the variable name
* @return the variable
*/
public JRFillVariable getVariable(String variableName)
{
return mainDataset.getVariable(variableName);
}
/**
* Returns the value of a variable.
*
* @param variableName
* the variable name
*
* @return the variable value
*
* @throws JRRuntimeException when the variable does not exist
*/
public Object getVariableValue(String variableName)
{
return mainDataset.getVariableValue(variableName);
}
protected JRFillExpressionEvaluator getExpressionEvaluator()
{
return calculator;
}
protected boolean isSubreport()
{
return parent != null;
}
protected boolean isMasterReport()
{
return parent == null;
}
/**
* Evaluates an expression
* @param expression the expression
* @param evaluation the evaluation type
* @return the evaluation result
* @throws JRException
*/
public Object evaluateExpression(JRExpression expression, byte evaluation) throws JRException
{
return mainDataset.evaluateExpression(expression, evaluation);
}
protected final void setFormatFactory(Map parameterValues)
{
formatFactory = (FormatFactory)parameterValues.get(JRParameter.REPORT_FORMAT_FACTORY);
if (formatFactory == null)
{
formatFactory = DefaultFormatFactory.createFormatFactory(jasperReport.getFormatFactoryClass());
parameterValues.put(JRParameter.REPORT_FORMAT_FACTORY, formatFactory);
}
}
/**
* Returns the report format factory.
*
* @return the report format factory
*/
protected FormatFactory getFormatFactory()
{
return formatFactory;
}
protected void addLastPageBookmarks()
{
if (bookmarkHelper != null)
{
int pageIndex = jasperPrint.getPages() == null ? -1 : (jasperPrint.getPages().size() - 1);
if (pageIndex >= 0)
{
JRPrintPage page = jasperPrint.getPages().get(pageIndex);
bookmarkHelper.addBookmarks(page, pageIndex);
}
}
}
public void updateBookmark(JRPrintElement element)
{
if (isMasterReport())
{
if (bookmarkHelper != null)
{
bookmarkHelper.updateBookmark(element);
}
}
else
{
parent.updateBookmark(element);
}
}
/**
* Cancels the fill process.
*
* @throws JRException
*/
@Override
public void cancelFill() throws JRException
{
if (log.isDebugEnabled())
{
log.debug("Fill " + fillerId + ": cancelling");
}
fillContext.markCanceled();
if (fillContext.cancelRunningQuery())
{
if (log.isDebugEnabled())
{
log.debug("Fill " + fillerId + ": query cancelled");
}
}
else
{
Thread t = fillingThread;
if (t != null)
{
if (log.isDebugEnabled())
{
log.debug("Fill " + fillerId + ": Interrupting thread " + t);
}
t.interrupt();
}
}
}
protected void addBoundElement(JRFillElement element, JRPrintElement printElement, JREvaluationTime evaluationTime,
FillPageKey pageKey)
{
if (log.isDebugEnabled())
{
log.debug("Adding evaluation of " + printElement + " by " + element
+ " for evaluation " + evaluationTime);
}
delayedActions.addDelayedAction(element, printElement, evaluationTime, pageKey);
}
protected void resolveBoundElements(JREvaluationTime evaluationTime, byte evaluation) throws JRException
{
delayedActions.runActions(evaluationTime, evaluation);
}
protected void resolveMasterBoundElements() throws JRException
{
resolveBoundElements(JREvaluationTime.EVALUATION_TIME_MASTER, JRExpression.EVALUATION_DEFAULT);
}
public void recordUsedPageWidth(int width)
{
if (width > usedPageWidth)
{
usedPageWidth = width;
}
}
public int getUsedPageWidth()
{
return usedPageWidth;
}
}