/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2001 - 2013 Object Refinery Ltd, Pentaho Corporation and Contributors.. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.core.layout;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.engine.classic.core.ReportDefinition;
import org.pentaho.reporting.engine.classic.core.function.ProcessingContext;
import org.pentaho.reporting.engine.classic.core.layout.model.LogicalPageBox;
import org.pentaho.reporting.engine.classic.core.layout.output.ContentProcessingException;
import org.pentaho.reporting.engine.classic.core.layout.output.IterativeOutputProcessor;
import org.pentaho.reporting.engine.classic.core.layout.output.LayoutPagebreakHandler;
import org.pentaho.reporting.engine.classic.core.layout.output.OutputProcessor;
import org.pentaho.reporting.engine.classic.core.layout.output.OutputProcessorFeature;
import org.pentaho.reporting.engine.classic.core.layout.process.ApplyAutoCommitPageHeaderStep;
import org.pentaho.reporting.engine.classic.core.layout.process.CleanFlowBoxesStep;
import org.pentaho.reporting.engine.classic.core.layout.process.CountBoxesStep;
import org.pentaho.reporting.engine.classic.core.layout.process.FillFlowPagesStep;
import org.pentaho.reporting.engine.classic.core.states.PerformanceMonitorContext;
/**
* The streaming renderer streams all generated (and layouted) elements to the output processor. The output processor
* should mark the processed elements by setting the 'dirty' flag to false. Pagebreaks will be ignored, all content ends
* up in a single stream of data.
*
* @author Thomas Morgner
*/
public class StreamingRenderer extends AbstractRenderer {
private static final Log logger = LogFactory.getLog( StreamingRenderer.class );
private CountBoxesStep countBoxesStep;
private CleanFlowBoxesStep cleanBoxesStep;
private ApplyAutoCommitPageHeaderStep applyAutoCommitPageHeaderStep;
private FillFlowPagesStep fillPhysicalPagesStep;
private int floodPrevention;
private int pageCount;
public StreamingRenderer( final OutputProcessor outputProcessor ) {
super( outputProcessor );
this.countBoxesStep = new CountBoxesStep();
this.cleanBoxesStep = new CleanFlowBoxesStep();
this.applyAutoCommitPageHeaderStep = new ApplyAutoCommitPageHeaderStep();
this.fillPhysicalPagesStep = new FillFlowPagesStep();
initialize();
}
protected boolean isPageFinished() {
if ( getPageBox().isOpen() ) {
return false;
}
return true;
}
public void startReport( final ReportDefinition report, final ProcessingContext processingContext,
final PerformanceMonitorContext performanceMonitorContext ) {
pageCount = 0;
super.startReport( report, processingContext, performanceMonitorContext );
}
public void processIncrementalUpdate( final boolean performOutput ) throws ContentProcessingException {
if ( isDirty() == false ) {
// Log.debug ("Not dirty, no update needed.");
return;
}
clearDirty();
floodPrevention += 1;
if ( floodPrevention < 50 ) { // this is a magic number ..
return;
}
floodPrevention = 0;
final OutputProcessor outputProcessor = getOutputProcessor();
if ( outputProcessor instanceof IterativeOutputProcessor == false
|| outputProcessor.getMetaData().isFeatureSupported( OutputProcessorFeature.ITERATIVE_RENDERING ) == false ) {
// logger.debug ("No incremental system.");
return;
}
// logger.debug("Computing Incremental update.");
final LogicalPageBox pageBox = getPageBox();
pageBox.setPageOffset( 0 );
pageBox.setPageEnd( pageBox.getHeight() );
// shiftBox(pageBox, true);
if ( pageBox.isOpen() ) {
final IterativeOutputProcessor io = (IterativeOutputProcessor) outputProcessor;
if ( applyAutoCommitPageHeaderStep.compute( pageBox ) ) {
// logger.debug("Applying Incremental update.");
io.processIterativeContent( pageBox, performOutput );
countBoxesStep.process( pageBox );
cleanBoxesStep.compute( pageBox );
}
}
}
protected boolean performPagination( final LayoutPagebreakHandler handler, final boolean performOutput )
throws ContentProcessingException {
if ( performOutput == false ) {
return false;
}
final OutputProcessor outputProcessor = getOutputProcessor();
final LogicalPageBox pageBox = getPageBox();
// This is fixed: The streaming renderers always use the whole page area ..
pageBox.setPageOffset( 0 );
pageBox.setPageEnd( pageBox.getHeight() );
if ( pageBox.isOpen() ) {
// Not finished and the output target is non-iterative, so we have to wait until everything is done..
return false;
}
// the reporting finally came to an end. Lets process the content.
// Recover the page-grid, then restart everything from scratch.
// (We have to recompute, as the pages may be different now, due to changed margins or page definitions)
final long nextOffset = pageBox.computePageEnd();
pageBox.setPageEnd( nextOffset );
final long pageOffset = pageBox.getPageOffset();
applyAutoCommitPageHeaderStep.commitAll( pageBox );
if ( outputProcessor.isNeedAlignedPage() ) {
final LogicalPageBox box = fillPhysicalPagesStep.compute( pageBox, pageOffset, nextOffset );
logger.debug( "Processing contents for stream. Page-Offset: " + pageOffset + " -> " + nextOffset );
outputProcessor.processContent( box );
} else {
logger.debug( "Processing fast contents for stream. Page-Offset: " + pageOffset + " -> " + nextOffset );
outputProcessor.processContent( pageBox );
}
countBoxesStep.process( pageBox );
cleanBoxesStep.compute( pageBox );
debugPrint( pageBox );
outputProcessor.processingFinished();
pageCount = 1;
setPagebreaks( 1 );
return false;
}
public int getPageCount() {
return pageCount;
}
protected void debugPrint( final LogicalPageBox pageBox ) {
// Log.debug("**** Start Printing Page: " + 1);
// ModelPrinter.print(pageBox);
// Log.debug("**** Done Printing Page: " + 1);
}
public void createRollbackInformation() {
throw new UnsupportedOperationException(
"Streaming-Renderer do not implement the createRollbackInformation-method." );
}
public void applyRollbackInformation() {
throw new UnsupportedOperationException( "Streaming-Renderer do not implement the applyRollbackInformation method." );
}
public void rollback() {
throw new UnsupportedOperationException( "Streaming-Renderer do not implement the rollback method." );
}
}