this.currentSubReportMarker = subReports[subReportIndex];
this.inlineProcess =
parentState.isInlineProcess() || currentSubReportMarker.getProcessType() == SubReportProcessType.INLINE;
final SubReport subreportFromMarker = currentSubReportMarker.getSubreport();
final FunctionStorageKey functionStorageKey = FunctionStorageKey.createKey
(parentSubReportState.getProcessKey(), subreportFromMarker);
final boolean needPreProcessing;
final SubReport report;
if (subReportStorage.contains(functionStorageKey))
{
report = subReportStorage.restore(functionStorageKey);
final ElementStyleSheet subreportStyle = subreportFromMarker.getStyle();
final Map styleExpressions = subreportFromMarker.getStyleExpressions();
final StyleKey[] definedStyle =
(StyleKey[]) styleExpressions.keySet().toArray(new StyleKey[styleExpressions.size()]);
for (int i = 0; i < definedStyle.length; i++)
{
final StyleKey styleKey = definedStyle[i];
report.getStyle().setStyleProperty(styleKey, subreportStyle.getStyleProperty(styleKey));
}
needPreProcessing = false;
}
else
{
report = subreportFromMarker;
needPreProcessing = true;
}
final ResourceBundleFactory resourceBundleFactory;
if (report.getResourceBundleFactory() != null)
{
resourceBundleFactory = MasterReport.computeAndInitResourceBundleFactory
(report.getResourceBundleFactory(), parentState.getFlowController().getReportContext().getEnvironment());
}
else
{
resourceBundleFactory = parentState.getResourceBundleFactory();
}
final int processingLevel = flowController.getReportContext().getProcessingLevel();
if (processingLevel == LayoutProcess.LEVEL_PAGINATE &&
report.isVisible() == false)
{
// make it a minimum effort report, but still enter the loop.
final ReportDefinition parentReport = parentState.getReport();
final SubReport dummyReport = new SubReport(functionStorageKey.getReportId());
this.report = new ReportDefinitionImpl(dummyReport, parentReport.getPageDefinition());
this.flowController = parentState.flowController.derive();
this.advanceHandler = EndSubReportHandler.HANDLER;
this.layoutProcess = new SubLayoutProcess
(parentState.layoutProcess, computeStructureFunctions(report.getStructureFunctions(),
flowController.getReportContext().getOutputProcessorMetaData()));
}
else
{
CachingDataFactory dataFactory = dataFactoryManager.restore(functionStorageKey);
if (dataFactory == null)
{
final DataFactory subreportDf = report.getDataFactory();
final Object dataCacheEnabledRaw =
report.getAttribute(AttributeNames.Core.NAMESPACE, AttributeNames.Core.DATA_CACHE);
final boolean dataCacheEnabled = Boolean.FALSE.equals(dataCacheEnabledRaw) == false;
if (subreportDf == null)
{
// subreport does not define a own factory, so reuse the parent's data-factory.
dataFactory = new CachingDataFactory(parentState.getFlowController().getDataFactory(), true, dataCacheEnabled);
}
else
{
// subreport comes with an own factory, so open the gates ..
dataFactory = new CachingDataFactory(subreportDf, dataCacheEnabled);
final ProcessingContext context = parentState.getFlowController().getReportContext();
dataFactory.initialize(context.getConfiguration(), context.getResourceManager(),
context.getContentBase(), resourceBundleFactory);
dataFactory.open();
dataFactoryManager.store(functionStorageKey, dataFactory);
}
}
// And now initialize the sub-report.
final ParameterMapping[] inputMappings = report.getInputMappings();
final ParameterMapping[] exportMappings = report.getExportMappings();
// eval query, query-limit and query-timeout
this.flowController = parentState.flowController.performInitSubreport
(dataFactory, inputMappings, resourceBundleFactory);
final Integer queryLimitDefault = IntegerCache.getInteger(report.getQueryLimit());
final Integer queryTimeoutDefault = IntegerCache.getInteger(report.getQueryTimeout());
final Object queryRaw = evaluateExpression(report.getAttributeExpression(AttributeNames.Internal.NAMESPACE,
AttributeNames.Internal.QUERY), report.getQuery());
final Object queryLimitRaw = evaluateExpression(report.getAttributeExpression(AttributeNames.Internal.NAMESPACE,
AttributeNames.Internal.QUERY_LIMIT), queryLimitDefault);
final Object queryTimeoutRaw = evaluateExpression(report.getAttributeExpression(AttributeNames.Internal.NAMESPACE,
AttributeNames.Internal.QUERY_TIMEOUT), queryTimeoutDefault);
this.query = (String) ConverterRegistry.convert(queryRaw, String.class, report.getQuery());
this.queryLimit = (Integer) ConverterRegistry.convert(queryLimitRaw, Integer.class, queryLimitDefault);
this.queryTimeout = (Integer) ConverterRegistry.convert(queryTimeoutRaw, Integer.class, queryTimeoutDefault);
DefaultFlowController postQueryFlowController = flowController.performSubReportQuery
(query, queryLimit.intValue(), queryTimeout.intValue(), exportMappings);
final ProxyDataSchemaDefinition schemaDefinition =
new ProxyDataSchemaDefinition(report.getDataSchemaDefinition(),
postQueryFlowController.getMasterRow().getDataSchemaDefinition());
postQueryFlowController = postQueryFlowController.updateDataSchema(schemaDefinition);
SubReport fullReport = report;
DataSchemaDefinition fullDefinition = schemaDefinition;
if (needPreProcessing)
{
final ReportPreProcessor[] processors = getAllPreProcessors(report);
for (int i = 0; i < processors.length; i++)
{
final ReportPreProcessor processor = processors[i];
fullReport = processor.performPreProcessing(fullReport, postQueryFlowController);
if (fullReport.getDataSchemaDefinition() != fullDefinition)
{
fullDefinition = fullReport.getDataSchemaDefinition();
postQueryFlowController = postQueryFlowController.updateDataSchema(fullDefinition);
}
}
subReportStorage.store(functionStorageKey, fullReport);
}
this.report = new ReportDefinitionImpl(fullReport, fullReport.getPageDefinition());
final Expression[] structureFunctions = getStructureFunctionStorage().restore(functionStorageKey);
if (structureFunctions != null)
{
final StructureFunction[] functions = new StructureFunction[structureFunctions.length];
//noinspection SuspiciousSystemArraycopy
System.arraycopy(structureFunctions, 0, functions, 0, structureFunctions.length);
this.layoutProcess = new SubLayoutProcess(parentState.layoutProcess, functions);
}
else
{
final StructureFunction[] functions = computeStructureFunctions(fullReport.getStructureFunctions(),
postQueryFlowController.getReportContext().getOutputProcessorMetaData());
this.layoutProcess = new SubLayoutProcess(parentState.layoutProcess, functions);
}
boolean preserve = true;
Expression[] expressions = getFunctionStorage().restore(functionStorageKey);
if (expressions == null)
{
// ok, it seems we have entered a new subreport ..
// we use the expressions from the report itself ..
expressions = fullReport.getExpressions().getExpressions();
preserve = false;
}
this.flowController = postQueryFlowController.activateExpressions(expressions, preserve);
}