492 lines
21 KiB
Java
492 lines
21 KiB
Java
package net.sf.jasperreports.engine.fill;
|
|
|
|
import java.io.File;
|
|
import java.io.InputStream;
|
|
import java.net.URL;
|
|
import java.sql.Connection;
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import net.sf.jasperreports.engine.JRCommonElement;
|
|
import net.sf.jasperreports.engine.JRDataSource;
|
|
import net.sf.jasperreports.engine.JRDatasetParameter;
|
|
import net.sf.jasperreports.engine.JRElement;
|
|
import net.sf.jasperreports.engine.JRException;
|
|
import net.sf.jasperreports.engine.JRExpression;
|
|
import net.sf.jasperreports.engine.JRExpressionCollector;
|
|
import net.sf.jasperreports.engine.JRPrintElement;
|
|
import net.sf.jasperreports.engine.JRPrintPage;
|
|
import net.sf.jasperreports.engine.JRPrintRectangle;
|
|
import net.sf.jasperreports.engine.JRRewindableDataSource;
|
|
import net.sf.jasperreports.engine.JRRuntimeException;
|
|
import net.sf.jasperreports.engine.JRStyle;
|
|
import net.sf.jasperreports.engine.JRSubreport;
|
|
import net.sf.jasperreports.engine.JRSubreportParameter;
|
|
import net.sf.jasperreports.engine.JRSubreportReturnValue;
|
|
import net.sf.jasperreports.engine.JRVariable;
|
|
import net.sf.jasperreports.engine.JRVisitor;
|
|
import net.sf.jasperreports.engine.JasperCompileManager;
|
|
import net.sf.jasperreports.engine.JasperReport;
|
|
import net.sf.jasperreports.engine.design.JRDesignSubreportReturnValue;
|
|
import net.sf.jasperreports.engine.util.JRLoader;
|
|
import net.sf.jasperreports.engine.util.JRProperties;
|
|
import net.sf.jasperreports.engine.util.JRSingletonCache;
|
|
import net.sf.jasperreports.engine.util.JRStyleResolver;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
public class JRFillSubreport extends JRFillElement implements JRSubreport {
|
|
private static final Log log = LogFactory.getLog(JRFillSubreport.class);
|
|
|
|
private static final JRSingletonCache runnerFactoryCache = new JRSingletonCache(JRSubreportRunnerFactory.class);
|
|
|
|
private Map parameterValues = null;
|
|
|
|
private JRSubreportParameter[] parameters = null;
|
|
|
|
private Connection connection = null;
|
|
|
|
private JRDataSource dataSource = null;
|
|
|
|
private JasperReport jasperReport = null;
|
|
|
|
private Map loadedEvaluators = null;
|
|
|
|
private JRFillSubreportReturnValue[] returnValues = null;
|
|
|
|
protected JRBaseFiller subreportFiller = null;
|
|
|
|
private JRPrintPage printPage = null;
|
|
|
|
private JRSubreportRunner runner;
|
|
|
|
private Set checkedReports;
|
|
|
|
protected JRFillSubreport(JRBaseFiller filler, JRSubreport subreport, JRFillObjectFactory factory) {
|
|
super(filler, (JRElement)subreport, factory);
|
|
this.parameters = subreport.getParameters();
|
|
JRSubreportReturnValue[] subrepReturnValues = subreport.getReturnValues();
|
|
if (subrepReturnValues != null) {
|
|
List returnValuesList = new ArrayList(subrepReturnValues.length * 2);
|
|
this.returnValues = new JRFillSubreportReturnValue[subrepReturnValues.length];
|
|
for (int i = 0; i < subrepReturnValues.length; i++)
|
|
addReturnValue(subrepReturnValues[i], returnValuesList, factory);
|
|
this.returnValues = new JRFillSubreportReturnValue[returnValuesList.size()];
|
|
returnValuesList.toArray((Object[])this.returnValues);
|
|
}
|
|
this.loadedEvaluators = new HashMap();
|
|
this.checkedReports = new HashSet();
|
|
}
|
|
|
|
public byte getMode() {
|
|
return JRStyleResolver.getMode((JRCommonElement)this, (byte)2);
|
|
}
|
|
|
|
public boolean isUsingCache() {
|
|
return ((JRSubreport)this.parent).isUsingCache();
|
|
}
|
|
|
|
public void setUsingCache(boolean isUsingCache) {}
|
|
|
|
public JRExpression getParametersMapExpression() {
|
|
return ((JRSubreport)this.parent).getParametersMapExpression();
|
|
}
|
|
|
|
public JRSubreportParameter[] getParameters() {
|
|
return this.parameters;
|
|
}
|
|
|
|
public JRExpression getConnectionExpression() {
|
|
return ((JRSubreport)this.parent).getConnectionExpression();
|
|
}
|
|
|
|
public JRExpression getDataSourceExpression() {
|
|
return ((JRSubreport)this.parent).getDataSourceExpression();
|
|
}
|
|
|
|
public JRExpression getExpression() {
|
|
return ((JRSubreport)this.parent).getExpression();
|
|
}
|
|
|
|
protected JRTemplateRectangle getJRTemplateRectangle() {
|
|
JRStyle style = getStyle();
|
|
JRTemplateRectangle template = (JRTemplateRectangle)getTemplate(style);
|
|
if (template == null) {
|
|
template = new JRTemplateRectangle(this.band.getOrigin(), this.filler.getJasperPrint().getDefaultStyleProvider(), this);
|
|
transferProperties(template);
|
|
registerTemplate(style, template);
|
|
}
|
|
return template;
|
|
}
|
|
|
|
protected Collection getPrintElements() {
|
|
Collection printElements = null;
|
|
if (this.printPage != null)
|
|
printElements = this.printPage.getElements();
|
|
return printElements;
|
|
}
|
|
|
|
protected void evaluate(byte evaluation) throws JRException {
|
|
reset();
|
|
evaluatePrintWhenExpression(evaluation);
|
|
evaluateProperties(evaluation);
|
|
if (isPrintWhenExpressionNull() || (!isPrintWhenExpressionNull() && isPrintWhenTrue()))
|
|
evaluateSubreport(evaluation);
|
|
}
|
|
|
|
protected void evaluateSubreport(byte evaluation) throws JRException {
|
|
JRExpression expression = getExpression();
|
|
Object source = evaluateExpression(expression, evaluation);
|
|
if (source != null) {
|
|
JREvaluator evaluator = null;
|
|
if (isUsingCache() && this.filler.fillContext.hasLoadedSubreport(source)) {
|
|
this.jasperReport = this.filler.fillContext.getLoadedSubreport(source);
|
|
evaluator = (JREvaluator)this.loadedEvaluators.get(this.jasperReport);
|
|
if (evaluator == null) {
|
|
evaluator = JasperCompileManager.loadEvaluator(this.jasperReport);
|
|
this.loadedEvaluators.put(this.jasperReport, evaluator);
|
|
}
|
|
} else {
|
|
Class expressionClass = expression.getValueClass();
|
|
if (expressionClass.equals(JasperReport.class)) {
|
|
this.jasperReport = (JasperReport)source;
|
|
} else if (expressionClass.equals(InputStream.class)) {
|
|
this.jasperReport = (JasperReport)JRLoader.loadObject((InputStream)source);
|
|
} else if (expressionClass.equals(URL.class)) {
|
|
this.jasperReport = (JasperReport)JRLoader.loadObject((URL)source);
|
|
} else if (expressionClass.equals(File.class)) {
|
|
this.jasperReport = (JasperReport)JRLoader.loadObject((File)source);
|
|
} else if (expressionClass.equals(String.class)) {
|
|
this.jasperReport = (JasperReport)JRLoader.loadObjectFromLocation((String)source, this.filler.reportClassLoader, this.filler.urlHandlerFactory, this.filler.fileResolver);
|
|
}
|
|
if (this.jasperReport != null)
|
|
evaluator = JasperCompileManager.loadEvaluator(this.jasperReport);
|
|
if (isUsingCache()) {
|
|
this.filler.fillContext.registerLoadedSubreport(source, this.jasperReport);
|
|
this.loadedEvaluators.put(this.jasperReport, evaluator);
|
|
}
|
|
}
|
|
if (this.jasperReport != null) {
|
|
expression = getConnectionExpression();
|
|
this.connection = (Connection)evaluateExpression(expression, evaluation);
|
|
expression = getDataSourceExpression();
|
|
this.dataSource = (JRDataSource)evaluateExpression(expression, evaluation);
|
|
this.parameterValues = getParameterValues(this.filler, getParametersMapExpression(), (JRDatasetParameter[])getParameters(), evaluation, false, (this.jasperReport.getResourceBundle() != null), (this.jasperReport.getFormatFactoryClass() != null));
|
|
if (this.subreportFiller != null)
|
|
this.filler.unregisterSubfiller(this.subreportFiller);
|
|
initSubreportFiller(evaluator);
|
|
checkReturnValues();
|
|
saveReturnVariables();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void initSubreportFiller(JREvaluator evaluator) throws JRException {
|
|
if (log.isDebugEnabled())
|
|
log.debug("Fill " + this.filler.fillerId + ": creating subreport filler");
|
|
switch (this.jasperReport.getPrintOrder()) {
|
|
case 2:
|
|
this.subreportFiller = new JRHorizontalFiller(this.jasperReport, evaluator, this.filler);
|
|
break;
|
|
case 1:
|
|
this.subreportFiller = new JRVerticalFiller(this.jasperReport, evaluator, this.filler);
|
|
break;
|
|
default:
|
|
throw new JRRuntimeException("Unkown print order " + this.jasperReport.getPrintOrder() + ".");
|
|
}
|
|
this.runner = getRunnerFactory().createSubreportRunner(this, this.subreportFiller);
|
|
this.subreportFiller.setSubreportRunner(this.runner);
|
|
}
|
|
|
|
protected void saveReturnVariables() {
|
|
if (this.returnValues != null)
|
|
for (int i = 0; i < this.returnValues.length; i++) {
|
|
String varName = this.returnValues[i].getToVariable();
|
|
this.band.saveVariable(varName);
|
|
}
|
|
}
|
|
|
|
public static Map getParameterValues(JRBaseFiller filler, JRExpression parametersMapExpression, JRDatasetParameter[] subreportParameters, byte evaluation, boolean ignoreNullExpressions, boolean removeResourceBundle, boolean removeFormatFactory) throws JRException {
|
|
Map parameterValues = null;
|
|
if (parametersMapExpression != null)
|
|
parameterValues = (Map)filler.evaluateExpression(parametersMapExpression, evaluation);
|
|
if (parameterValues != null) {
|
|
if (removeResourceBundle)
|
|
parameterValues.remove("REPORT_RESOURCE_BUNDLE");
|
|
if (removeFormatFactory)
|
|
parameterValues.remove("REPORT_FORMAT_FACTORY");
|
|
parameterValues.remove("REPORT_CONNECTION");
|
|
parameterValues.remove("REPORT_MAX_COUNT");
|
|
parameterValues.remove("REPORT_DATA_SOURCE");
|
|
parameterValues.remove("REPORT_SCRIPTLET");
|
|
parameterValues.remove("REPORT_VIRTUALIZER");
|
|
parameterValues.remove("IS_IGNORE_PAGINATION");
|
|
parameterValues.remove("REPORT_PARAMETERS_MAP");
|
|
}
|
|
if (parameterValues == null)
|
|
parameterValues = new HashMap();
|
|
if (subreportParameters != null && subreportParameters.length > 0) {
|
|
Object parameterValue = null;
|
|
for (int i = 0; i < subreportParameters.length; i++) {
|
|
JRExpression expression = subreportParameters[i].getExpression();
|
|
if (expression != null || !ignoreNullExpressions) {
|
|
parameterValue = filler.evaluateExpression(expression, evaluation);
|
|
if (parameterValue == null) {
|
|
parameterValues.remove(subreportParameters[i].getName());
|
|
} else {
|
|
parameterValues.put(subreportParameters[i].getName(), parameterValue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!parameterValues.containsKey("REPORT_LOCALE"))
|
|
parameterValues.put("REPORT_LOCALE", filler.getLocale());
|
|
if (!parameterValues.containsKey("REPORT_TIME_ZONE"))
|
|
parameterValues.put("REPORT_TIME_ZONE", filler.getTimeZone());
|
|
if (!parameterValues.containsKey("REPORT_FORMAT_FACTORY") && !removeFormatFactory)
|
|
parameterValues.put("REPORT_FORMAT_FACTORY", filler.getFormatFactory());
|
|
if (!parameterValues.containsKey("REPORT_CLASS_LOADER") && filler.reportClassLoader != null)
|
|
parameterValues.put("REPORT_CLASS_LOADER", filler.reportClassLoader);
|
|
if (!parameterValues.containsKey("REPORT_URL_HANDLER_FACTORY") && filler.urlHandlerFactory != null)
|
|
parameterValues.put("REPORT_URL_HANDLER_FACTORY", filler.urlHandlerFactory);
|
|
if (!parameterValues.containsKey("REPORT_FILE_RESOLVER") && filler.fileResolver != null)
|
|
parameterValues.put("REPORT_FILE_RESOLVER", filler.fileResolver);
|
|
return parameterValues;
|
|
}
|
|
|
|
protected void fillSubreport() throws JRException {
|
|
if (getConnectionExpression() != null) {
|
|
this.subreportFiller.fill(this.parameterValues, this.connection);
|
|
} else if (getDataSourceExpression() != null) {
|
|
this.subreportFiller.fill(this.parameterValues, this.dataSource);
|
|
} else {
|
|
this.subreportFiller.fill(this.parameterValues);
|
|
}
|
|
}
|
|
|
|
protected boolean prepare(int availableStretchHeight, boolean isOverflow) throws JRException {
|
|
boolean willOverflow = false;
|
|
super.prepare(availableStretchHeight, isOverflow);
|
|
if (this.subreportFiller == null)
|
|
setToPrint(false);
|
|
if (!isToPrint())
|
|
return willOverflow;
|
|
if (availableStretchHeight < getRelativeY() - getY() - getBandBottomY()) {
|
|
setToPrint(false);
|
|
return true;
|
|
}
|
|
boolean filling = this.runner.isFilling();
|
|
boolean toPrint = (!isOverflow || isPrintWhenDetailOverflows() || !isAlreadyPrinted());
|
|
boolean reprinted = (isOverflow && isPrintWhenDetailOverflows());
|
|
if (!filling && toPrint && reprinted)
|
|
rewind();
|
|
int availableHeight = getHeight() + availableStretchHeight - getRelativeY() + getY() + getBandBottomY();
|
|
this.subreportFiller.setPageHeight(availableHeight);
|
|
synchronized (this.subreportFiller) {
|
|
JRSubreportRunResult result;
|
|
if (filling) {
|
|
if (log.isDebugEnabled())
|
|
log.debug("Fill " + this.filler.fillerId + ": resuming " + this.subreportFiller.fillerId);
|
|
result = this.runner.resume();
|
|
} else if (toPrint) {
|
|
setReprinted(reprinted);
|
|
if (log.isDebugEnabled())
|
|
log.debug("Fill " + this.filler.fillerId + ": starting " + this.subreportFiller.fillerId);
|
|
result = this.runner.start();
|
|
} else {
|
|
this.printPage = null;
|
|
setStretchHeight(getHeight());
|
|
setToPrint(false);
|
|
return willOverflow;
|
|
}
|
|
if (result.getException() != null) {
|
|
Throwable error = result.getException();
|
|
if (log.isErrorEnabled())
|
|
log.error("Fill " + this.filler.fillerId + ": exception", error);
|
|
if (error instanceof RuntimeException)
|
|
throw (RuntimeException)error;
|
|
throw new JRRuntimeException(error);
|
|
}
|
|
if (result.hasFinished()) {
|
|
if (log.isDebugEnabled())
|
|
log.debug("Fill " + this.filler.fillerId + ": subreport " + this.subreportFiller.fillerId + " finished");
|
|
copyValues();
|
|
} else if (log.isDebugEnabled()) {
|
|
log.debug("Fill " + this.filler.fillerId + ": subreport " + this.subreportFiller.fillerId + " to continue");
|
|
}
|
|
this.printPage = this.subreportFiller.getCurrentPage();
|
|
setStretchHeight(result.hasFinished() ? this.subreportFiller.getCurrentPageStretchHeight() : availableHeight);
|
|
willOverflow = !result.hasFinished();
|
|
if (!willOverflow)
|
|
this.runner.reset();
|
|
}
|
|
Collection printElements = getPrintElements();
|
|
if ((printElements == null || printElements.size() == 0) && isRemoveLineWhenBlank())
|
|
setToPrint(false);
|
|
return willOverflow;
|
|
}
|
|
|
|
public void rewind() throws JRException {
|
|
if (this.subreportFiller == null)
|
|
return;
|
|
if (log.isDebugEnabled())
|
|
log.debug("Fill " + this.filler.fillerId + ": cancelling " + this.subreportFiller.fillerId);
|
|
this.subreportFiller.setInterrupted(true);
|
|
synchronized (this.subreportFiller) {
|
|
this.runner.cancel();
|
|
this.runner.reset();
|
|
}
|
|
this.filler.unregisterSubfiller(this.subreportFiller);
|
|
initSubreportFiller((JREvaluator)null);
|
|
if (getConnectionExpression() == null && this.dataSource != null)
|
|
if (this.dataSource instanceof JRRewindableDataSource) {
|
|
((JRRewindableDataSource)this.dataSource).moveFirst();
|
|
} else {
|
|
throw new JRException("The subreport is placed on a non-splitting band, but it does not have a rewindable data source.");
|
|
}
|
|
}
|
|
|
|
protected JRPrintElement fill() {
|
|
JRPrintRectangle printRectangle = new JRTemplatePrintRectangle(getJRTemplateRectangle());
|
|
printRectangle.setX(getX());
|
|
printRectangle.setY(getRelativeY());
|
|
printRectangle.setWidth(getWidth());
|
|
printRectangle.setHeight(getStretchHeight());
|
|
return (JRPrintElement)printRectangle;
|
|
}
|
|
|
|
public void collectExpressions(JRExpressionCollector collector) {
|
|
collector.collect(this);
|
|
}
|
|
|
|
public void visit(JRVisitor visitor) {
|
|
visitor.visitSubreport(this);
|
|
}
|
|
|
|
private JRFillSubreportReturnValue addReturnValue(JRSubreportReturnValue parentReturnValue, List returnValueList, JRFillObjectFactory factory) {
|
|
JRSubreportReturnValue jRSubreportReturnValue1, varianceVal, countVal, sumVal;
|
|
JRFillSubreportReturnValue returnValue = factory.getSubreportReturnValue(parentReturnValue);
|
|
byte calculation = returnValue.getCalculation();
|
|
switch (calculation) {
|
|
case 3:
|
|
case 7:
|
|
jRSubreportReturnValue1 = createHelperReturnValue(parentReturnValue, "_COUNT", (byte)1);
|
|
addReturnValue(jRSubreportReturnValue1, returnValueList, factory);
|
|
sumVal = createHelperReturnValue(parentReturnValue, "_SUM", (byte)2);
|
|
addReturnValue(sumVal, returnValueList, factory);
|
|
this.filler.addVariableCalculationReq(returnValue.getToVariable(), calculation);
|
|
break;
|
|
case 6:
|
|
varianceVal = createHelperReturnValue(parentReturnValue, "_VARIANCE", (byte)7);
|
|
addReturnValue(varianceVal, returnValueList, factory);
|
|
this.filler.addVariableCalculationReq(returnValue.getToVariable(), calculation);
|
|
break;
|
|
case 10:
|
|
countVal = createDistinctCountHelperReturnValue(parentReturnValue);
|
|
addReturnValue(countVal, returnValueList, factory);
|
|
this.filler.addVariableCalculationReq(returnValue.getToVariable(), calculation);
|
|
break;
|
|
}
|
|
returnValueList.add(returnValue);
|
|
return returnValue;
|
|
}
|
|
|
|
protected JRSubreportReturnValue createHelperReturnValue(JRSubreportReturnValue returnValue, String nameSuffix, byte calculation) {
|
|
JRDesignSubreportReturnValue helper = new JRDesignSubreportReturnValue();
|
|
helper.setToVariable(returnValue.getToVariable() + nameSuffix);
|
|
helper.setSubreportVariable(returnValue.getSubreportVariable());
|
|
helper.setCalculation(calculation);
|
|
helper.setIncrementerFactoryClassName(helper.getIncrementerFactoryClassName());
|
|
return (JRSubreportReturnValue)helper;
|
|
}
|
|
|
|
protected JRSubreportReturnValue createDistinctCountHelperReturnValue(JRSubreportReturnValue returnValue) {
|
|
JRDesignSubreportReturnValue helper = new JRDesignSubreportReturnValue();
|
|
helper.setToVariable(returnValue.getToVariable() + "_DISTINCT_COUNT");
|
|
helper.setSubreportVariable(returnValue.getSubreportVariable());
|
|
helper.setCalculation((byte)0);
|
|
helper.setIncrementerFactoryClassName(helper.getIncrementerFactoryClassName());
|
|
return (JRSubreportReturnValue)helper;
|
|
}
|
|
|
|
public JRSubreportReturnValue[] getReturnValues() {
|
|
return (JRSubreportReturnValue[])this.returnValues;
|
|
}
|
|
|
|
public boolean usesForReturnValue(String variableName) {
|
|
boolean used = false;
|
|
if (this.returnValues != null)
|
|
for (int j = 0; j < this.returnValues.length; j++) {
|
|
JRSubreportReturnValue returnValue = this.returnValues[j];
|
|
if (returnValue.getToVariable().equals(variableName)) {
|
|
used = true;
|
|
break;
|
|
}
|
|
}
|
|
return used;
|
|
}
|
|
|
|
protected void copyValues() {
|
|
if (this.returnValues != null && this.returnValues.length > 0)
|
|
for (int i = 0; i < this.returnValues.length; i++)
|
|
copyValue(this.returnValues[i]);
|
|
}
|
|
|
|
protected void copyValue(JRFillSubreportReturnValue returnValue) {
|
|
try {
|
|
JRFillVariable variable = this.filler.getVariable(returnValue.getToVariable());
|
|
Object value = this.subreportFiller.getVariableValue(returnValue.getSubreportVariable());
|
|
Object newValue = returnValue.getIncrementer().increment(variable, value, AbstractValueProvider.getCurrentValueProvider());
|
|
variable.setOldValue(newValue);
|
|
variable.setValue(newValue);
|
|
variable.setIncrementedValue(newValue);
|
|
} catch (JRException e) {
|
|
throw new JRRuntimeException(e);
|
|
}
|
|
}
|
|
|
|
private void checkReturnValues() throws JRException {
|
|
if (this.returnValues != null && this.returnValues.length > 0 && !this.checkedReports.contains(this.jasperReport)) {
|
|
for (int i = 0; i < this.returnValues.length; i++) {
|
|
JRSubreportReturnValue returnValue = this.returnValues[i];
|
|
String subreportVariableName = returnValue.getSubreportVariable();
|
|
JRVariable subrepVariable = this.subreportFiller.getVariable(subreportVariableName);
|
|
if (subrepVariable == null)
|
|
throw new JRException("Subreport variable " + subreportVariableName + " not found.");
|
|
JRVariable variable = this.filler.getVariable(returnValue.getToVariable());
|
|
if (returnValue.getCalculation() == 1 || returnValue.getCalculation() == 10) {
|
|
if (!Number.class.isAssignableFrom(variable.getValueClass()))
|
|
throw new JRException("Variable " + returnValue.getToVariable() + " must have a numeric type.");
|
|
} else if (!variable.getValueClass().isAssignableFrom(subrepVariable.getValueClass()) && (!Number.class.isAssignableFrom(variable.getValueClass()) || !Number.class.isAssignableFrom(subrepVariable.getValueClass()))) {
|
|
throw new JRException("Variable " + returnValue.getToVariable() + " is not assignable from subreport variable " + subreportVariableName);
|
|
}
|
|
}
|
|
if (isUsingCache())
|
|
this.checkedReports.add(this.jasperReport);
|
|
}
|
|
}
|
|
|
|
protected void resolveElement(JRPrintElement element, byte evaluation) {}
|
|
|
|
public Boolean isOwnUsingCache() {
|
|
return ((JRSubreport)this.parent).isOwnUsingCache();
|
|
}
|
|
|
|
public void setUsingCache(Boolean isUsingCache) {}
|
|
|
|
public JRFillCloneable createClone(JRFillCloneFactory factory) {
|
|
return null;
|
|
}
|
|
|
|
protected static JRSubreportRunnerFactory getRunnerFactory() throws JRException {
|
|
String factoryClassName = JRProperties.getProperty("net.sf.jasperreports.subreport.runner.factory");
|
|
if (factoryClassName == null)
|
|
throw new JRException("Property \"net.sf.jasperreports.subreport.runner.factory\" must be set");
|
|
return (JRSubreportRunnerFactory)runnerFactoryCache.getCachedInstance(factoryClassName);
|
|
}
|
|
}
|