/* * 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.states; import org.pentaho.reporting.engine.classic.core.InvalidReportStateException; import org.pentaho.reporting.engine.classic.core.PerformanceTags; import org.pentaho.reporting.engine.classic.core.ReportProcessingException; import org.pentaho.reporting.engine.classic.core.event.PageEventListener; import org.pentaho.reporting.engine.classic.core.event.ReportEvent; import org.pentaho.reporting.engine.classic.core.function.ExpressionRuntime; import org.pentaho.reporting.engine.classic.core.function.OutputFunction; import org.pentaho.reporting.engine.classic.core.function.StructureFunction; import org.pentaho.reporting.engine.classic.core.states.datarow.ExpressionEventHelper; import org.pentaho.reporting.engine.classic.core.states.datarow.InlineDataRowRuntime; import org.pentaho.reporting.engine.classic.core.states.datarow.LevelStorage; import org.pentaho.reporting.engine.classic.core.states.datarow.OutputFunctionLevelStorage; import org.pentaho.reporting.libraries.base.util.PerformanceLoggingStopWatch; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class InitialLayoutProcess extends ExpressionEventHelper implements LayoutProcess { private class CloseListener implements ChangeListener { public void stateChanged( final ChangeEvent e ) { stopWatch.close(); } } private static final StructureFunction[] EMPTY_FUNCTIONS = new StructureFunction[0]; private InlineDataRowRuntime inlineDataRowRuntime; private OutputFunction outputFunction; private boolean outputFunctionIsPageListener; private PerformanceLoggingStopWatch stopWatch; private PerformanceMonitorContext monitorContext; public InitialLayoutProcess( final OutputFunction outputFunction, final PerformanceMonitorContext monitorContext ) { if ( outputFunction == null ) { throw new NullPointerException(); } this.outputFunction = outputFunction; this.outputFunctionIsPageListener = ( outputFunction instanceof PageEventListener ); this.monitorContext = monitorContext; this.monitorContext.addChangeListener( new CloseListener() ); this.stopWatch = monitorContext.createStopWatch( PerformanceTags.REPORT_LAYOUT_GENERATE ); } public LayoutProcess getParent() { return null; } public boolean isPageListener() { return outputFunctionIsPageListener; } public OutputFunction getOutputFunction() { return outputFunction; } public void restart( final ReportState state ) throws ReportProcessingException { try { stopWatch.start(); if ( inlineDataRowRuntime == null ) { inlineDataRowRuntime = new InlineDataRowRuntime(); } inlineDataRowRuntime.setState( state ); final ExpressionRuntime oldRuntime; final OutputFunction outputFunction = getOutputFunction(); if ( outputFunction != null ) { oldRuntime = outputFunction.getRuntime(); outputFunction.setRuntime( inlineDataRowRuntime ); } else { oldRuntime = null; } try { if ( outputFunction != null ) { outputFunction.restart( state ); } } finally { if ( outputFunction != null ) { outputFunction.setRuntime( oldRuntime ); } } } finally { stopWatch.stop( true ); } } public StructureFunction[] getCollectionFunctions() { return EMPTY_FUNCTIONS; } public LayoutProcess deriveForStorage() { try { final InitialLayoutProcess lp = (InitialLayoutProcess) super.clone(); lp.inlineDataRowRuntime = null; lp.outputFunction = outputFunction.deriveForStorage(); return lp; } catch ( final CloneNotSupportedException e ) { throw new IllegalStateException(); } } public LayoutProcess deriveForPagebreak() { try { final InitialLayoutProcess lp = (InitialLayoutProcess) super.clone(); lp.inlineDataRowRuntime = null; lp.outputFunction = outputFunction.deriveForPagebreak(); return lp; } catch ( final CloneNotSupportedException e ) { throw new IllegalStateException(); } } public Object clone() { try { final InitialLayoutProcess lp = (InitialLayoutProcess) super.clone(); lp.inlineDataRowRuntime = null; lp.outputFunction = (OutputFunction) outputFunction.clone(); return lp; } catch ( CloneNotSupportedException cne ) { throw new IllegalStateException( cne ); } } protected int getRunLevelCount() { return 1; } protected LevelStorage getRunLevel( final int index ) { if ( index != 0 ) { throw new IndexOutOfBoundsException(); } return new OutputFunctionLevelStorage( LayoutProcess.LEVEL_PAGINATE, outputFunction, outputFunctionIsPageListener ); } protected ExpressionRuntime getRuntime() { return inlineDataRowRuntime; } public void fireReportEvent( final ReportEvent event ) { try { stopWatch.start(); if ( inlineDataRowRuntime == null ) { inlineDataRowRuntime = new InlineDataRowRuntime(); } final ReportState state = inlineDataRowRuntime.getState(); inlineDataRowRuntime.setState( event.getState() ); try { final int pageEventMask = ReportEvent.PAGE_STARTED | ReportEvent.PAGE_FINISHED; if ( ( event.getType() & pageEventMask ) == 0 && ( ( event.getType() & ReportEvent.GROUP_BODY_FINISHED ) == ReportEvent.GROUP_BODY_FINISHED ) ) { fireGroupBodyFinishedEvent( event ); } else { super.fireReportEvent( event ); } } catch ( InvalidReportStateException exception ) { throw exception; } catch ( Throwable t ) { throw new InvalidReportStateException( "Failed to fire report event for sub-layout-process", t ); } finally { inlineDataRowRuntime.setState( state ); } } finally { stopWatch.stop( true ); } } private void fireGroupBodyFinishedEvent( final ReportEvent event ) { if ( event.getLevel() != LayoutProcess.LEVEL_PAGINATE ) { return; } final ExpressionRuntime runtime = getRuntime(); final OutputFunction expression = getOutputFunction(); final boolean deepTraversing = event.isDeepTraversing(); if ( deepTraversing && expression.isDeepTraversing() == false ) { return; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { expression.groupBodyFinished( event ); evaluateSingleExpression( expression ); } catch ( InvalidReportStateException rse ) { throw rse; } catch ( Exception ex ) { evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } public void close() { stopWatch.close(); } }