throws ReportProcessingException
{
try
{
final boolean failOnError = isStrictErrorHandling(getReport().getReportConfiguration());
final ReportProcessingErrorHandler errorHandler = new CollectingReportErrorHandler();
final DefaultLayoutPagebreakHandler pagebreakHandler = new DefaultLayoutPagebreakHandler();
final ProcessState initialReportState = startState.deriveForStorage();
final PageState initialPageState = new PageState(initialReportState, outputProcessor.getPageCursor());
pageStates.add(initialPageState);
final ReportProgressEvent repaginationState = new ReportProgressEvent(this);
// inner loop: process the complete report, calculate the function values
// for the current level. Higher level functions are not available in the
// dataRow.
final int eventTrigger;
if (maxRows <= 0)
{
eventTrigger = Math.max(maxRows / MAX_EVENTS_PER_RUN, MIN_ROWS_PER_EVENT);
}
else
{
eventTrigger = Math.min(maxRows, Math.max(maxRows / MAX_EVENTS_PER_RUN, MIN_ROWS_PER_EVENT));
}
ProcessState state = startState.deriveForStorage();
state.setErrorHandler(errorHandler);
validate(state);
int pageEventCount = 0;
// First and last derive of a page must be a storage derivate - this clones everything and does
// not rely on the more complicated transactional layouting ..
ProcessState fallBackState = state.deriveForPagebreak();
ProcessState globalState = state.deriveForStorage();
ReportStateKey rollbackPageState = null;
boolean isInRollBackMode = false;
final boolean pagebreaksSupported = isPagebreaksSupported();
int eventCount = 0;
int lastRow = -1;
while (!state.isFinish())
{
int logPageCount = outputProcessor.getLogicalPageCount();
int physPageCount = outputProcessor.getPhysicalPageCount();
checkInterrupted();
if (lastRow != state.getCurrentDataItem())
{
lastRow = state.getCurrentDataItem();
if (eventCount == 0)
{
if (isPagebreaksSupported() && fallBackState != null)
{
repaginationState.reuse(ReportProgressEvent.PAGINATING,
fallBackState.getCurrentDataItem(), fallBackState.getNumberOfRows(), fallBackState.getCurrentPage(),
fallBackState.getProgressLevel(), fallBackState.getProgressLevelCount());
}
else
{
repaginationState.reuse(ReportProgressEvent.PAGINATING,
state.getCurrentDataItem(), state.getNumberOfRows(), state.getCurrentPage(),
state.getProgressLevel(), state.getProgressLevelCount());
}
fireStateUpdate(repaginationState);
eventCount += 1;
}
else
{
if (eventCount == eventTrigger)
{
eventCount = 0;
}
else
{
eventCount += 1;
}
}
}
// Do not try to layout on a artificial state. Those states are not valid on
// generating page events and cannot be trusted.
ProcessState realFallbackState = fallBackState;
final ProcessState restoreState;
if (pagebreaksSupported && state.isArtifcialState() == false)
{
restoreState = fallBackState;
if (isInRollBackMode == false)
{
if (pageEventCount >= AbstractReportProcessor.COMMIT_RATE)
{
final OutputFunction outputFunction = state.getLayoutProcess().getOutputFunction();
if (outputFunction.createRollbackInformation())
{
realFallbackState = state.deriveForPagebreak();
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
logger.debug("Paginate: Try to generate new fallback state after commit count reached: " + state.getProcessKey());
}
validate(state);
}
else
{
realFallbackState = null;
}
}
}
}
else
{
restoreState = null;
}
final ProcessState nextState = state.advance();
state.setErrorHandler(IgnoreEverythingReportErrorHandler.INSTANCE);
state = nextState;
validate(state);
final ReportStateKey nextStateKey = state.getProcessKey();
if (errorHandler.isErrorOccured() == true)
{
final List childExceptions = Arrays.asList(errorHandler.getErrors());
errorHandler.clearErrors();
final ReportEventException exception =
new ReportEventException("Failed to dispatch an event.", childExceptions);
if (failOnError)
{
throw exception;