Java tutorial
/* * 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 <http://www.gnu.org/licenses/>. */ 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 (teodord@users.sourceforge.net) */ 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<String> 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<String, JRFillDataset> 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<String> readPrintTransferPropertyPrefixes() { List<JRPropertiesUtil.PropertySuffix> transferProperties = propertiesUtil .getProperties(JasperPrint.PROPERTIES_PRINT_TRANSFER_PREFIX); List<String> prefixes = new ArrayList<String>(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<String, JRFillDataset>(); 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<JRFillDataset> 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<String, Object> parameterValues) { @SuppressWarnings("deprecation") JasperReportsContext localContext = net.sf.jasperreports.engine.util.LocalJasperReportsContext .getLocalContext(jasperReportsContext, parameterValues); if (localContext != jasperReportsContext) { setJasperReportsContext(localContext); } } protected void initVirtualizationContext(Map<String, Object> 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<String, Object> 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<String, Object> parameterValues, Connection conn) throws JRException { if (parameterValues == null) { parameterValues = new HashMap<String, Object>(); } setConnectionParameterValue(parameterValues, conn); return fill(parameterValues); } protected void setConnectionParameterValue(Map<String, Object> parameterValues, Connection conn) { mainDataset.setConnectionParameterValue(parameterValues, conn); } @Override @continuable public JasperPrint fill(Map<String, Object> parameterValues, JRDataSource ds) throws JRException { if (parameterValues == null) { parameterValues = new HashMap<String, Object>(); } setDatasourceParameterValue(parameterValues, ds); return fill(parameterValues); } protected void setDatasourceParameterValue(Map<String, Object> parameterValues, JRDataSource ds) { mainDataset.setDatasourceParameterValue(parameterValues, ds); } protected void setParameters(Map<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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 JRFillDataset getMainDataset() { return mainDataset; } /** * Returns the map of parameter values. * * @return the map of parameter values */ public Map<String, Object> getParameterValuesMap() { return mainDataset.getParameterValuesMap(); } /** * Returns the report parameters indexed by name. * * @return the report parameters map */ protected Map<String, JRFillParameter> 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<String, Object> 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; } }