/*!
* 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) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.core.layout.build;
import org.pentaho.reporting.engine.classic.core.Band;
import org.pentaho.reporting.engine.classic.core.Group;
import org.pentaho.reporting.engine.classic.core.GroupBody;
import org.pentaho.reporting.engine.classic.core.ReportDefinition;
import org.pentaho.reporting.engine.classic.core.ReportProcessingException;
import org.pentaho.reporting.engine.classic.core.function.ExpressionRuntime;
import org.pentaho.reporting.engine.classic.core.function.ProcessingContext;
import org.pentaho.reporting.engine.classic.core.layout.InlineSubreportMarker;
import org.pentaho.reporting.engine.classic.core.layout.RenderComponentFactory;
import org.pentaho.reporting.engine.classic.core.layout.Renderer;
import org.pentaho.reporting.engine.classic.core.layout.model.LogicalPageBox;
import org.pentaho.reporting.engine.classic.core.layout.output.OutputProcessorMetaData;
import org.pentaho.reporting.engine.classic.core.states.ReportStateKey;
import org.pentaho.reporting.engine.classic.core.style.StyleSheet;
import org.pentaho.reporting.engine.classic.core.util.InstanceID;
import java.util.ArrayList;
public class ReportRenderModelBuilder implements RenderModelBuilder, Cloneable {
private static final InlineSubreportMarker[] EMPTY_SUBREPORT_MARKERS = new InlineSubreportMarker[0];
private LayoutModelBuilder normalFlow;
private LayoutModelBuilder header;
private LayoutModelBuilder footer;
private LayoutModelBuilder repeatedFooter;
private LayoutModelBuilder watermark;
private Renderer.SectionType activeSection;
private LogicalPageBox pageBox;
private ArrayList<InlineSubreportMarker> collectedSubReportMarker;
private ProcessingContext processingContext;
private RenderNodeFactory renderNodeFactory;
private ReportStateKey stateKey;
private LayoutBuilderStrategy layoutBuilderStrategy;
private RenderComponentFactory componentFactory;
public ReportRenderModelBuilder( final RenderComponentFactory componentFactory ) {
this.componentFactory = componentFactory;
this.layoutBuilderStrategy = componentFactory.createLayoutBuilderStrategy();
this.collectedSubReportMarker = new ArrayList<InlineSubreportMarker>();
}
public void startReport( final ReportDefinition report, final ProcessingContext processingContext ) {
final OutputProcessorMetaData outputProcessorMetaData = processingContext.getOutputProcessorMetaData();
renderNodeFactory = componentFactory.createRenderNodeFactory();
renderNodeFactory.initialize( outputProcessorMetaData );
this.processingContext = processingContext;
final StyleSheet resolverStyle = report.getComputedStyle();
this.pageBox = renderNodeFactory.createPage( report, resolverStyle );
normalFlow = createNormalBuilder( processingContext );
header = createHeaderBuilder( processingContext );
footer = createFooterBuilder( processingContext );
repeatedFooter = createRepeatedFooterBuilder( processingContext );
watermark = createWatermarkBuilder( processingContext );
}
protected LayoutModelBuilder createNormalBuilder( final ProcessingContext processingContext ) {
LayoutModelBuilder normalFlow = componentFactory.createLayoutModelBuilder( "Section-0" );
normalFlow.initialize( processingContext, this.pageBox.getContentArea(), renderNodeFactory );
normalFlow.updateState( stateKey );
return normalFlow;
}
protected LayoutModelBuilder createHeaderBuilder( final ProcessingContext processingContext ) {
HeaderLayoutModelBuilder header =
new HeaderLayoutModelBuilder( componentFactory.createLayoutModelBuilder( "Header-1" ) );
header.initialize( processingContext, this.pageBox.getHeaderArea(), renderNodeFactory );
header.updateState( stateKey );
return header;
}
protected LayoutModelBuilder createFooterBuilder( final ProcessingContext processingContext ) {
FooterLayoutModelBuilder footer =
new FooterLayoutModelBuilder( componentFactory.createLayoutModelBuilder( "Footer-2" ) );
footer.initialize( processingContext, this.pageBox.getFooterArea(), renderNodeFactory );
footer.updateState( stateKey );
return footer;
}
protected LayoutModelBuilder createRepeatedFooterBuilder( final ProcessingContext processingContext ) {
RepeatedFooterLayoutModelBuilder repeatedFooter =
new RepeatedFooterLayoutModelBuilder( componentFactory.createLayoutModelBuilder( "Repeat-Footer-3" ) );
repeatedFooter.initialize( processingContext, this.pageBox.getRepeatFooterArea(), renderNodeFactory );
repeatedFooter.updateState( stateKey );
return repeatedFooter;
}
protected LayoutModelBuilder createWatermarkBuilder( final ProcessingContext processingContext ) {
WatermarkLayoutModelBuilder watermark =
new WatermarkLayoutModelBuilder( componentFactory.createLayoutModelBuilder( "Watermark-Section" ) );
watermark.initialize( processingContext, this.pageBox.getWatermarkArea(), renderNodeFactory );
watermark.updateState( stateKey );
return watermark;
}
protected RenderNodeFactory getRenderNodeFactory() {
return renderNodeFactory;
}
public ReportStateKey getStateKey() {
return stateKey;
}
protected RenderComponentFactory getComponentFactory() {
return componentFactory;
}
public void updateStateKey( final ReportStateKey stateKey ) {
this.stateKey = stateKey;
if ( normalFlow != null ) {
normalFlow.updateState( stateKey );
}
if ( header != null ) {
header.updateState( stateKey );
}
if ( footer != null ) {
footer.updateState( stateKey );
}
if ( repeatedFooter != null ) {
repeatedFooter.updateState( stateKey );
}
if ( watermark != null ) {
watermark.updateState( stateKey );
}
}
public void startSubReport( final ReportDefinition report, final InstanceID insertationPoint ) {
if ( insertationPoint == null ) {
normalFlow.startSubFlow( report );
} else {
normalFlow.startSubFlow( insertationPoint );
}
}
public void startGroup( final Group group, final Integer predictedStateCount ) {
final int count;
if ( predictedStateCount == null ) {
count = 0;
} else {
count = predictedStateCount;
}
normalFlow.startSection( group, count );
}
public void startGroupBody( final GroupBody groupBody, final Integer predictedStateCount ) {
final int count;
if ( predictedStateCount == null ) {
count = 0;
} else {
count = predictedStateCount;
}
normalFlow.startSection( groupBody, count );
}
public void startSection( final Renderer.SectionType type ) {
this.activeSection = type;
this.collectedSubReportMarker.clear();
getLayoutModelBuilder().startSection();
}
public void addProgressBox() throws ReportProcessingException {
normalFlow.addProgressMarkerBox();
}
public void addEmptyRootLevelBand() throws ReportProcessingException {
getLayoutModelBuilder().addProgressMarkerBox();
}
public void addPageBreak() {
if ( getPageBox() == null ) {
throw new IllegalStateException();
}
normalFlow.addManualPageBreakBox( getPageBox().getPageOffset() );
}
public void add( final ExpressionRuntime runtime, final Band band ) throws ReportProcessingException {
final LayoutBuilderStrategy builderStrategy = getLayoutBuilderStrategy();
LayoutModelBuilder layoutModelBuilder = getLayoutModelBuilder();
builderStrategy.add( runtime, layoutModelBuilder, band, collectedSubReportMarker );
}
public void addToNormalFlow( final ExpressionRuntime runtime, final Band band ) throws ReportProcessingException {
final LayoutBuilderStrategy builderStrategy = getLayoutBuilderStrategy();
builderStrategy.add( runtime, normalFlow, band, collectedSubReportMarker );
}
protected LayoutBuilderStrategy getLayoutBuilderStrategy() {
return layoutBuilderStrategy;
}
public SectionResult endSection() {
final boolean empty = getLayoutModelBuilder().isEmpty();
getLayoutModelBuilder().endSection();
final InlineSubreportMarker[] markers;
if ( collectedSubReportMarker.isEmpty() ) {
markers = EMPTY_SUBREPORT_MARKERS;
} else {
markers = collectedSubReportMarker.toArray( new InlineSubreportMarker[collectedSubReportMarker.size()] );
}
activeSection = Renderer.SectionType.NORMALFLOW;
return new SectionResult( markers, empty );
}
public void endGroupBody() {
normalFlow.endSection();
}
public void endGroup() {
normalFlow.endSection();
}
public void endSubReport() {
normalFlow.endSubFlow();
}
public void endReport() {
getPageBox().getContentArea().close();
getPageBox().close();
normalFlow.close();
header.close();
footer.close();
repeatedFooter.close();
watermark.close();
renderNodeFactory.close();
}
public LayoutModelBuilder getNormalFlowLayoutModelBuilder() {
return normalFlow;
}
private LayoutModelBuilder getLayoutModelBuilder() {
switch ( activeSection ) {
case NORMALFLOW:
return normalFlow;
case HEADER:
return header;
case FOOTER:
return footer;
case REPEAT_FOOTER:
return repeatedFooter;
case WATERMARK:
return watermark;
default:
throw new IllegalStateException();
}
}
public ReportRenderModelBuilder clone() {
try {
final ReportRenderModelBuilder builder = (ReportRenderModelBuilder) super.clone();
builder.collectedSubReportMarker = (ArrayList<InlineSubreportMarker>) collectedSubReportMarker.clone();
return builder;
} catch ( CloneNotSupportedException e ) {
throw new IllegalStateException( e );
}
}
public LogicalPageBox getPageBox() {
return pageBox;
}
public RenderModelBuilder deriveForStorage() {
final ReportRenderModelBuilder clone = clone();
if ( pageBox != null ) {
clone.pageBox = (LogicalPageBox) clone.pageBox.derive( true );
clone.normalFlow = clone.normalFlow.deriveForStorage( clone.pageBox.getContentArea() );
clone.header = clone.header.deriveForStorage( clone.pageBox.getHeaderArea() );
clone.footer = clone.footer.deriveForStorage( clone.pageBox.getFooterArea() );
clone.repeatedFooter = clone.repeatedFooter.deriveForStorage( clone.pageBox.getRepeatFooterArea() );
clone.watermark = clone.watermark.deriveForStorage( clone.pageBox.getWatermarkArea() );
}
return clone;
}
public RenderModelBuilder deriveForPageBreak() {
final ReportRenderModelBuilder clone = clone();
if ( pageBox != null ) {
clone.normalFlow = clone.normalFlow.deriveForPageBreak();
clone.header = clone.header.deriveForPageBreak();
clone.footer = clone.footer.deriveForPageBreak();
clone.repeatedFooter = clone.repeatedFooter.deriveForPageBreak();
clone.watermark = clone.watermark.deriveForPageBreak();
}
return clone;
}
public void performParanoidModelCheck() {
if ( pageBox == null ) {
return;
}
normalFlow.performParanoidModelCheck( pageBox.getContentArea() );
header.performParanoidModelCheck( pageBox.getHeaderArea() );
footer.performParanoidModelCheck( pageBox.getFooterArea() );
repeatedFooter.performParanoidModelCheck( pageBox.getRepeatFooterArea() );
watermark.performParanoidModelCheck( pageBox.getWatermarkArea() );
}
public void validateAfterCommit() {
if ( pageBox == null ) {
return;
}
normalFlow.validateAfterCommit();
header.validateAfterCommit();
footer.validateAfterCommit();
repeatedFooter.validateAfterCommit();
watermark.validateAfterCommit();
}
public void restoreStateAfterRollback() {
header.initialize( processingContext, pageBox.getHeaderArea(), renderNodeFactory );
header.restoreStateAfterRollback();
footer.initialize( processingContext, pageBox.getFooterArea(), renderNodeFactory );
footer.restoreStateAfterRollback();
repeatedFooter.initialize( processingContext, pageBox.getRepeatFooterArea(), renderNodeFactory );
repeatedFooter.restoreStateAfterRollback();
watermark.initialize( processingContext, pageBox.getWatermarkArea(), renderNodeFactory );
watermark.restoreStateAfterRollback();
normalFlow.restoreStateAfterRollback();
}
}