net.sf.jasperreports.engine.JRSubreport Maven / Gradle / Ivy
Show all versions of jasperreports Show documentation
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2022 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;
import net.sf.jasperreports.engine.type.OverflowType;
/**
* An abstract representation of a subreport.
* Subreport Overview
* Subreports are an important feature of a report-generating tool. They enable you to create
* more complex reports and simplify the design work. Subreports are very useful when
* creating master-detail reports or when the structure of a single report is not sufficient to
* describe the complexity of the desired output document. Subreport elements are introduced by the
* <subreport>
tag in the JRXML file.
*
* A subreport is in fact a normal report that has been incorporated into another report. You
* can overlap subreports or make a subreport that contains other subreports, up to any level
* of nesting. Subreports are compiled and filled just like normal reports. Any report
* template can be used as a subreport when incorporated into another report template,
* without anything inside it having to change.
*
* Just like normal report templates, subreport templates are in fact
* {@link net.sf.jasperreports.engine.JasperReport} objects, which are obtained after
* compiling a {@link net.sf.jasperreports.engine.design.JasperDesign} object.
*
* Subreport elements have an expression that is evaluated at runtime to obtain the source of the
* {@link net.sf.jasperreports.engine.JasperReport} object to load.
* The so-called subreport expression is introduced by the <subreportExpression>
* tag (see {@link #getExpression()}) and can return values from the following classes:
*
* java.lang.String
(default)
* java.io.File
* java.io.InputStream
* java.net.URL
* {@link net.sf.jasperreports.engine.JasperReport}
*
*
* Note: When the subreport expression returns a java.lang.String
value, the engine tries to see
* whether the value represents a URL from which to load the subreport template object. If the value is not a valid
* URL representation, then the engine will try to locate a file on disk and load the subreport template from it,
* assuming that the value represents a file name. If no file is found, it will finally assume that the string value
* represents the location of a classpath resource and will try to load the subreport template from there. Only if all
* those fail will an exception be thrown.
* Caching Subreports
* A subreport element can load different subreport templates with every evaluation, giving
* users great flexibility in shaping their documents.
*
* However, most of the time, the subreport elements on a report are in fact static and their
* sources do not necessarily change with each new evaluation of the subreport expression.
* Usually, the subreport templates are loaded from fixed locations: files on disk or static
* URLs. If the same subreport template is filled multiple times on a report, there is no
* point in loading the subreport template object from the source file every time it is filled
* with data. To avoid this, one can instruct the reporting engine to cache the subreport
* template object. This way, one make sure that the subreport template is loaded from disk
* or from its particular location only once, after which it will be reused only when it must
* be filled.
*
* If the isUsingCache
attribute (see {@link #getUsingCache()} is set to true,
* the reporting engine will try to recognize previously loaded subreport template objects,
* using their specified source. For example, it will recognize a subreport object if its
* source is a file name that it has already loaded, or if it is the same URL.
*
* This caching functionality is available only for subreport elements that have expressions
* returning java.lang.String
objects as the subreport template source, representing file
* names, URLs, or classpath resources. That's because the engine uses the subreport
* source string as the key to recognize that it is the same subreport template that it has
* cached.
* Subreport Parameters
* Since subreports are normal reports themselves, they are compiled and filled just like
* other reports. This means that they also require a data source from which to get the data
* when they are filled. They can also rely on parameters for additional information to use
* when being filled.
*
* There are two ways to supply parameter values to a subreport.
* You can supply a map containing the parameter values, as when filling a normal report
* with data, using one of the fillReportXXX()
methods exposed by the
* {@link net.sf.jasperreports.engine.JasperFillManager} class.
* To do this, use the <parametersMapExpression>
element
* (see {@link #getParametersMapExpression()}), which introduces the
* expression that will be evaluated to obtain the specified parameters map. This expression
* should always return a java.util.Map
object in which the keys are the parameter
* names.
*
* In addition to (or instead of) supplying the parameter values in a map, you can supply the
* parameter values individually, one by one, using a <subreportParameter>
* element (see {@link #getParameters()}) for
* each relevant parameter. To do this, specify the name of the corresponding parameter
* using the mandatory name
attribute and provide an expression that will be evaluated at
* runtime to obtain the value for that particular parameter, the value that will be supplied
* to the subreport-filling routines.
*
* Note that you can use both ways to provide subreport parameter values simultaneously.
* When this happens, the parameter values specified individually, using the
* <subreportParameter>
element, override the parameter values present in the
* parameters map that correspond to the same subreport parameter. If the map does not
* contain corresponding parameter values already, the individually specified parameter
* values are added to the map.
*
* Caution: When you supply the subreport parameter values, be aware that the reporting engine will affect the
* java.util.Map
object it receives, adding the built-in report parameter values that correspond to the
* subreport. This map is also affected by the individually specified subreport parameter values, as already
* explained.
*
* To avoid altering the original java.util.Map object that you send, wrap it in a different map before
* supplying it to the subreport-filling process, as follows:
*
* new HashMap(myOriginalMap)
*
* This way, the original map object remains unaffected and modifications are made to the wrapping map object.
* This is especially useful when you want to supply to the subreport the same set of parameters that the master
* report has received and you are using the built-in
* {@link net.sf.jasperreports.engine.JRParameter#REPORT_PARAMETERS_MAP REPORT_PARAMETERS_MAP} report parameter of the
* master report. However, you don't want to affect the value of this built-in parameter, so a clone of the original
* map needs to be used. Starting with JasperReports 3.0.1,
* {@link net.sf.jasperreports.engine.JRParameter#REPORT_PARAMETERS_MAP REPORT_PARAMETERS_MAP} is automatically
* cloned when it is used as subreport parameters map.
* Subreport Data Source
* Subreports require a data source in order to generate their content, just like normal
* reports.
*
* When filling a report,
* one must supply either a data source object or a connection object, depending on the
* report type.
*
* Subreports behave in the same way and expect to receive the same kind of input when
* they are being filled. One can supply to the subreport either a data source using the
* <dataSourceExpression>
element (see {@link #getDataSourceExpression()})
* or a JDBC connection (see {@link #getConnectionExpression()}) for the engine to execute the
* subreport's internal SQL query using the <connectionExpression>
element. These
* two XML elements cannot both be present at the same time in a <subreport>
element
* declaration. This is because you cannot supply both a data source and a connection for
* your subreport.
*
* The report engine expects that the data source expression will return a
* {@link net.sf.jasperreports.engine.JRDataSource} object or that the connection
* expression will return a java.sql.Connnection
object - whichever is present.
* Returning Values from a Subreport
* Values calculated by a subreport can be returned to the parent report. More specifically,
* after a subreport is filled, values of the subreport variables can be either copied or
* accumulated (using an incrementer) to variables of the caller report.
*
* One or many <returnValue>
elements (see {@link #getReturnValues()}) can be used inside
* a <subreport>
to specify values to be returned from the subreport.
*
* A subreport return value is represented by the {@link net.sf.jasperreports.engine.JRSubreportReturnValue}
* class that provides information about the subreport variable, master variable, calculation type
* and incrementer factory.
*
* Note that the value from the subreport is not returned on a column or page break, but
* only when the subreport filling is done. Also note that the calculation is a two-level
* process - that is, if the subreport computes a total average and the master accumulates
* values from the subreports using calculated averages, then the master result will be the
* average of the subreport averages, not the average of the combined subreport records.
* Subreport Runners
* By default, JasperReports uses multiple threads to render subreports. There is a separate
* thread for the master report and one thread for each subreport element found in the report
* template hierarchy. Each of these threads deals with the filling of its associated report
* template, which is either a master report or an embedded subreport. Even though
* multiple threads are involved when subreports are present, those threads do not actually
* run simultaneously; rather, they pass the control from one another at specific moments,
* usually when page breaks occur. At any one moment, there is only one report or
* subreport-filling thread in execution, the others being in wait state.
*
* Using multiple threads was the easiest way to add subreporting functionality in
* JasperReports. It allowed the reuse of the existing report-filling logic. However, while
* initially easy to implement, the solution proved to have some drawbacks due to the heavy
* use of threads. One of the most important limitations was that J2EE containers
* discourage any use of threads. Also, some operating systems manage threads poorly,
* which resulted in decreased performance and heavy memory usage.
*
* The alternate solution to this was found in a concept called Java continuations.
* From among several third-partly libraries implementing this concept that were available
* at the time, JasperReports proved to work well with Jakarta Commons Javaflow.
*
* In order to avoid breaking any existing functionality and also allow users to turn off
* multi-threading when working with subreports in JasperReports, the solution was to
* isolate subreport-filling logic into a separate abstract class called
* {@link net.sf.jasperreports.engine.fill.JRSubreportRunnable}, which would have
* two interchangeable implementations:
*
* - {@link net.sf.jasperreports.engine.fill.JRThreadSubreportRunner} - The
* initial thread-based implementation
* - {@link net.sf.jasperreports.engine.fill.JRContinuationSubreportRunner} - A
* Javaflow-based implementation
*
*
* Switching between the preceding subreport runner implementation is not done through
* direct instantiation, but rather through a configuration property called
* {@link net.sf.jasperreports.engine.fill.JRSubreportRunnerFactory#SUBREPORT_RUNNER_FACTORY net.sf.jasperreports.subreport.runner.factory}. This configuration property
* should point to a
* {@link net.sf.jasperreports.engine.fill.JRSubreportRunnerFactory}
* implementation able to produce the needed {@link net.sf.jasperreports.engine.fill.JRSubreportRunnable}
* objects at runtime. That could be one of the following two:
*
* - {@link net.sf.jasperreports.engine.fill.JRContinuationSubreportRunnerFactory}
* - {@link net.sf.jasperreports.engine.fill.JRThreadSubreportRunnerFactory}
*
*
* The default value for the factory configuration property is
* {@link net.sf.jasperreports.engine.fill.JRThreadSubreportRunnerFactory},
* for backward-compatibility reasons.
*
* Note: A special JasperReports JAR file built using Javaflow byte code instrumentation is available for
* download with each JasperReports release and should be used when Java Continuations support during
* subreport filling is needed. In such cases, the Jakarta Commons Javaflow library is required; it can be found in
* the /lib directory of the JasperReports project distribution package.
*
* @see net.sf.jasperreports.engine.JasperReport
* @see net.sf.jasperreports.engine.JRSubreportReturnValue
* @see net.sf.jasperreports.engine.design.JasperDesign
* @see net.sf.jasperreports.engine.fill.JRContinuationSubreportRunner
* @see net.sf.jasperreports.engine.fill.JRContinuationSubreportRunnerFactory
* @see net.sf.jasperreports.engine.fill.JRSubreportRunnable
* @see net.sf.jasperreports.engine.fill.JRSubreportRunnerFactory
* @see net.sf.jasperreports.engine.fill.JRThreadSubreportRunner
* @see net.sf.jasperreports.engine.fill.JRThreadSubreportRunnerFactory
* @author Teodor Danciu ([email protected])
*/
public interface JRSubreport extends JRElement
{
/**
*
*/
public JRExpression getParametersMapExpression();
/**
*
*/
public JRSubreportParameter[] getParameters();
/**
*
*/
public JRExpression getConnectionExpression();
/**
*
*/
public JRExpression getDataSourceExpression();
/**
*
*/
public JRExpression getExpression();
/**
* Returns the list of subreport copied values.
*
* @return the list of subreport copied values.
*/
public JRSubreportReturnValue[] getReturnValues();
/**
* Indicates if the engine is loading the current subreport from cache.
* Implementations of this method return the actual value for the internal flag that was explicitly
* set on this subreport.
* @return Boolean.TRUE if the subreport should be loaded from cache, Boolean.FALSE otherwise
* or null in case the flag was never explicitly set on this subreport element
*/
public Boolean getUsingCache();
/**
* Specifies if the engine should be loading the current subreport from cache. If set to Boolean.TRUE, the reporting engine
* will try to recognize previously loaded subreports using their specified source. For example, it will recognize
* an subreport if the subreport source is a file name that it has already loaded, or if it is the same URL.
*
* If set to null, the engine will rely on some default value which depends on the type of the subreport expression.
* The cache is turned on by default only for subreports that have java.lang.String objects in their expressions.
*/
public void setUsingCache(Boolean isUsingCache);
/**
* Specifies whether the subreport element will consume the entire vertical
* space available on the report page.
*
* @return whether the subreport element will consume the entire space down to
* the bottom of the page
* @see #setRunToBottom(Boolean)
*/
public Boolean isRunToBottom();
/**
* Sets the flag that Specifies whether the subreport element will consume the
* entire vertical space available on the report page.
*
*
* This flag should be set to true
if the subreport needs to always
* print its column and page footers at the bottom of the report page, even when
* the subreport data does not stretch to the bottom.
*
*
* Note that when {@link JRReport#isFloatColumnFooter() isFloatColumnFooter}
* is set for the subreport, the column footers will not be printed at the bottom
* of the page even if this flag is set.
*
* @param runToBottom whether the subreport element will consume the entire
* space down to the bottom of the page
*/
public void setRunToBottom(Boolean runToBottom);
public OverflowType getOverflowType();
public void setOverflowType(OverflowType overflowType);
}