eventTrigger = Math.min(maxRows, Math.max(maxRows / MAX_EVENTS_PER_RUN, MIN_ROWS_PER_EVENT));
}
final boolean pagebreaksSupported = isPagebreaksSupported();
ReportStateKey rollbackPageState = null;
ProcessState state = startState.deriveForStorage();
ProcessState fallBackState = pagebreaksSupported ? state.deriveForPagebreak() : null;
final ProcessState globalState = pagebreaksSupported ? state.deriveForStorage() : null;
state.setErrorHandler(errorHandler);
boolean isInRollBackMode = false;
int lastRow = -1;
int eventCount = 0;
int pageEventCount = 0;
while (!state.isFinish())
{
checkInterrupted();
if (lastRow != state.getCurrentRow())
{
lastRow = state.getCurrentRow();
if (eventCount == 0)
{
repaginationState.reuse(ReportProgressEvent.GENERATING_CONTENT, state, calculatePageCount(state));
fireStateUpdate(repaginationState);
eventCount += 1;
}
else
{
if (eventCount == eventTrigger)
{
eventCount = 0;
}
else
{
eventCount += 1;
}
}
}
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())
{
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
logger.debug("Print: Try to generate new fallback state after commit count reached: " + state.getProcessKey());
}
realFallbackState = state.deriveForPagebreak();
}
else
{
realFallbackState = null;
}
}
}
}
else
{
restoreState = null;
}
final ProcessState nextState = state.advance();
state.setErrorHandler(IgnoreEverythingReportErrorHandler.INSTANCE);
state = nextState;
final ReportStateKey nextStateKey = state.getProcessKey();
if (errorHandler.isErrorOccured() == true)
{
final List childExceptions = Arrays.asList(errorHandler.getErrors());
errorHandler.clearErrors();
if (failOnError)
{
throw new ReportEventException("Failed to dispatch an event.", childExceptions);
}
else
{
final ReportEventException exception =
new ReportEventException("Failed to dispatch an event.", childExceptions);
AbstractReportProcessor.logger.error("Failed to dispatch an event.", exception);
}
}
if (state.isArtifcialState())
{
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
logger.debug("Print: Silent commit as we are in an artificial state: " + state.getProcessKey());
}
state = state.commit();
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
logger.debug("Print: Post Silent commit as we are in an artificial state: " + state.getProcessKey());
}
continue;
}
final OutputFunction outputFunction = state.getLayoutProcess().getOutputFunction();
if (outputFunction instanceof DefaultOutputFunction == false)
{
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
logger.debug("Print: Silent commit as we are have no access to the renderer: " + state.getProcessKey());
}
state = state.commit();
continue;
}
final DefaultOutputFunction lm = (DefaultOutputFunction) outputFunction;
final Renderer renderer = lm.getRenderer();
renderer.setStateKey(state.getProcessKey());
pagebreakHandler.setReportState(state);
boolean assertExpectPagebreak = false;
if (isInRollBackMode)
{
if (nextStateKey.equals(rollbackPageState))
{
// reached the border case. We have to insert a manual pagebreak here or at least
// we have to force the renderer to end the page right now.
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
AbstractReportProcessor.logger.debug(
"Print: Found real pagebreak position. This might be the last state we process: " + rollbackPageState);
AbstractReportProcessor.logger.debug(
"Print: (Current state process key) : " + state.getProcessKey());
AbstractReportProcessor.logger.debug(
"Print: (Handler) : " + state.getAdvanceHandler().getClass().getName());
}
assertExpectPagebreak = true;
renderer.addPagebreak();
}
}
final Renderer.LayoutResult pagebreakEncountered = renderer.validatePages();
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
AbstractReportProcessor.logger.debug("Print: Validate Page returned " + pagebreakEncountered);
if (assertExpectPagebreak == true && pagebreakEncountered != Renderer.LayoutResult.LAYOUT_PAGEBREAK)
{
AbstractReportProcessor.logger.debug("Print: Missed the pagebreak. This smells fishy!");
}
}
if (pagebreakEncountered != Renderer.LayoutResult.LAYOUT_UNVALIDATABLE)
{
if (pagebreaksSupported && state.isArtifcialState() == false)
{
if (isInRollBackMode == false)
{
if (pageEventCount >= AbstractReportProcessor.COMMIT_RATE)
{
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
logger.debug("Print: Try to apply new fallback state after commit count reached: " + state.getProcessKey());
logger.debug("Print: : " + renderer.getLastStateKey());
}
fallBackState = realFallbackState;
pageEventCount = 0;
}
else
{
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
logger.debug("Print: Increase counter: " + state.getProcessKey());
}
pageEventCount += 1;
}
}
}
}
else if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
if (pagebreaksSupported && state.isArtifcialState() == false)
{
if (isInRollBackMode == false)
{
logger.debug("Print: SKIP : " + state.getProcessKey());
}
}
}
if (pagebreakEncountered == Renderer.LayoutResult.LAYOUT_PAGEBREAK)
{
final boolean onGoingPageBreak;
final ReportStateKey lastVisibleStateKey = renderer.getLastStateKey();
if (pagebreaksSupported &&
isInRollBackMode == false &&
renderer.isOpen() &&
lastVisibleStateKey != null)
{
if (lastVisibleStateKey.equals(nextStateKey) == false &&
lastVisibleStateKey.getSequenceCounter() > globalState.getProcessKey().getSequenceCounter())
{
// Roll back to the last known to be good position and process the states up to, but not
// including the current state. This way, we can fire the page-events *before* this band
// gets printed.
rollbackPageState = lastVisibleStateKey;
final ReportStateKey restoreStateProcessKey = restoreState.getProcessKey();
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
AbstractReportProcessor.logger.debug(
"Print: Encountered bad break, need to roll-back: " + rollbackPageState);
AbstractReportProcessor.logger.debug(
"Print: Next StateKey : " + state.getProcessKey());
AbstractReportProcessor.logger.debug(
"Print: Restored Key : " + restoreStateProcessKey);
AbstractReportProcessor.logger.debug(
"Print: Position in event chain : " + restoreState.getSequenceCounter());
}
if (lastVisibleStateKey.getSequenceCounter() < restoreStateProcessKey.getSequenceCounter())
{
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
AbstractReportProcessor.logger.debug(
"Print: Fall back to start of page : " + globalState.getProcessKey());