// 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;
}
else
{
AbstractReportProcessor.logger.error("Failed to dispatch an event.", exception);
}
}
if (state.isArtifcialState())
{
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
logger.debug("Paginate: Silent commit as we are in an artificial state: " + state.getProcessKey());
}
state = state.commit();
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
logger.debug("Paginate: Post Silent commit as we are in an artificial state: " + state.getProcessKey());
}
continue;
}
final OutputFunction outputFunction = state.getLayoutProcess().getOutputFunction();
if (outputFunction instanceof DefaultOutputFunction == false)
{
state = state.commit();
if (state.isFinish() && pageStates.size() == 1)
{
physicalMapping.add(0);
logicalMapping.add(0);
}
continue;
}
final DefaultOutputFunction lm = (DefaultOutputFunction) outputFunction;
final Renderer renderer = lm.getRenderer();
pagebreakHandler.setReportState(state);
boolean assertExpectPagebreak = false;
if (isInRollBackMode)
{
// todo: Could be that we have to use the other key here..
// was: state.getProcessKey()
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(
"Paginate: Found real pagebreak position. This might be the last state we process: " + rollbackPageState);
AbstractReportProcessor.logger.debug(
"Paginate: : " + state.getProcessKey());
if (restoreState != null)
{
AbstractReportProcessor.logger.debug(
"Paginate: : " + restoreState.getProcessKey());
}
AbstractReportProcessor.logger.debug(
"Paginate: (Handler) : " + state.getAdvanceHandler());
}
assertExpectPagebreak = true;
renderer.addPagebreak(state.getProcessKey());
}
}
final Renderer.LayoutResult pagebreakEncountered = renderer.validatePages();
if (AbstractReportProcessor.SHOW_ROLLBACKS)
{
AbstractReportProcessor.logger.debug("Validate Page returned " + pagebreakEncountered);
}
if (assertExpectPagebreak == true && pagebreakEncountered != Renderer.LayoutResult.LAYOUT_PAGEBREAK)
{
if (SHOW_ROLLBACKS)
{
AbstractReportProcessor.logger.debug("Paginate: 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("Paginate: Try to apply new fallback state after commit count reached: " + state.getProcessKey());
logger.debug("Paginate: : " + renderer.getLastStateKey());
}
fallBackState = realFallbackState;
pageEventCount = 0;
}
else
{
pageEventCount += 1;
}
}
}
}
if (pagebreakEncountered == Renderer.LayoutResult.LAYOUT_PAGEBREAK)
{
final ReportStateKey lastVisibleStateKey = renderer.getLastStateKey();
if (isPagebreaksSupported() &&
isInRollBackMode == false &&
lastVisibleStateKey != null &&
renderer.isOpen())
{
if (lastVisibleStateKey.equals(nextStateKey) == false)
{
// 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(
"Paginate: Encountered bad break, need to roll-back: " + rollbackPageState);
AbstractReportProcessor.logger.debug(
"Paginate: Next StateKey : " + state.getProcessKey());
AbstractReportProcessor.logger.debug(
"Paginate: Restored Key : " + restoreStateProcessKey);
AbstractReportProcessor.logger.debug(
"Paginate: 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 : " + restoreStateProcessKey);