/*! * 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.states.datarow; import java.util.Iterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.reporting.engine.classic.core.InvalidReportStateException; 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.Expression; import org.pentaho.reporting.engine.classic.core.function.ExpressionRuntime; import org.pentaho.reporting.engine.classic.core.function.Function; public abstract class ExpressionEventHelper { private static final Log logger = LogFactory.getLog( ExpressionEventHelper.class ); protected void fireReportEvent( final ReportEvent event ) { if ( ( event.getType() & ReportEvent.PAGE_STARTED ) == ReportEvent.PAGE_STARTED ) { firePageStartedEvent( event ); } else if ( ( event.getType() & ReportEvent.PAGE_FINISHED ) == ReportEvent.PAGE_FINISHED ) { firePageFinishedEvent( event ); } else if ( ( event.getType() & ReportEvent.ITEMS_ADVANCED ) == ReportEvent.ITEMS_ADVANCED ) { fireItemsAdvancedEvent( event ); } else if ( ( event.getType() & ReportEvent.ITEMS_FINISHED ) == ReportEvent.ITEMS_FINISHED ) { fireItemsFinishedEvent( event ); } else if ( ( event.getType() & ReportEvent.ITEMS_STARTED ) == ReportEvent.ITEMS_STARTED ) { fireItemsStartedEvent( event ); } else if ( ( event.getType() & ReportEvent.GROUP_FINISHED ) == ReportEvent.GROUP_FINISHED ) { fireGroupFinishedEvent( event ); } else if ( ( event.getType() & ReportEvent.GROUP_STARTED ) == ReportEvent.GROUP_STARTED ) { fireGroupStartedEvent( event ); } else if ( ( event.getType() & ReportEvent.REPORT_INITIALIZED ) == ReportEvent.REPORT_INITIALIZED ) { fireReportInitializedEvent( event ); } else if ( ( event.getType() & ReportEvent.REPORT_DONE ) == ReportEvent.REPORT_DONE ) { fireReportDoneEvent( event ); } else if ( ( event.getType() & ReportEvent.REPORT_FINISHED ) == ReportEvent.REPORT_FINISHED ) { fireReportFinishedEvent( event ); } else if ( ( event.getType() & ReportEvent.REPORT_STARTED ) == ReportEvent.REPORT_STARTED ) { fireReportStartedEvent( event ); } else if ( ( event.getType() & ReportEvent.SUMMARY_ROW ) == ReportEvent.SUMMARY_ROW ) { fireSummaryRowEvent( event ); } else if ( ( event.getType() & ReportEvent.GROUP_BODY_FINISHED ) == ReportEvent.GROUP_BODY_FINISHED ) { // ignore, nothing we handle here return; } else { throw new IllegalArgumentException(); } } protected abstract int getRunLevelCount(); protected abstract LevelStorage getRunLevel( int index ); protected abstract ExpressionRuntime getRuntime(); protected int getProcessingLevel() { return getRuntime().getProcessingContext().getProcessingLevel(); } private void fireItemsAdvancedEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof Function ) { final Function e = (Function) expression; e.itemsAdvanced( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire prepare event", ex ); } else { logger.error( "Failed to fire prepare event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } private void fireItemsStartedEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof Function ) { final Function e = (Function) expression; e.itemsStarted( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire prepare event", ex ); } else { logger.error( "Failed to fire prepare event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } private void fireItemsFinishedEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof Function ) { final Function e = (Function) expression; e.itemsFinished( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire prepare event", ex ); } else { logger.error( "Failed to fire prepare event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } private void fireGroupStartedEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof Function ) { final Function e = (Function) expression; e.groupStarted( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire group-started event", ex ); } else { logger.error( "Failed to fire group-started event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } private void fireGroupFinishedEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof Function ) { final Function e = (Function) expression; e.groupFinished( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire group-finished event", ex ); } else { logger.error( "Failed to fire group-finished event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } private void fireSummaryRowEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof Function ) { final Function e = (Function) expression; e.summaryRowSelection( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire group-finished event", ex ); } else { logger.error( "Failed to fire group-finished event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } private void fireReportStartedEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof Function ) { final Function e = (Function) expression; e.reportStarted( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire report-started event", ex ); } else { logger.error( "Failed to fire report-started event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } private void fireReportDoneEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof Function ) { final Function e = (Function) expression; e.reportDone( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire report-done event", ex ); } else { logger.error( "Failed to fire report-done event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } private void fireReportFinishedEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof Function ) { final Function e = (Function) expression; e.reportFinished( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire report-finished event", ex ); } else { logger.error( "Failed to fire report-finished event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } private void fireReportInitializedEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof Function ) { final Function e = (Function) expression; e.reportInitialized( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire report-initialized event", ex ); } else { logger.error( "Failed to fire report-initialized event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } private void firePageStartedEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof PageEventListener ) { final PageEventListener e = (PageEventListener) expression; e.pageStarted( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire page-started event", ex ); } else { logger.error( "Failed to fire page-started event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } private void firePageFinishedEvent( final ReportEvent event ) { final boolean deepTraversing = event.isDeepTraversing(); final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); try { if ( expression instanceof PageEventListener ) { final PageEventListener e = (PageEventListener) expression; e.pageFinished( event ); } evaluateSingleExpression( expression ); } catch ( final InvalidReportStateException rse ) { throw rse; } catch ( final Exception ex ) { if ( logger.isDebugEnabled() ) { logger.error( "Failed to fire page-finished event: ", ex ); } else { logger.error( "Failed to fire page-finished event: " + ex ); } evaluateToNull( expression ); } expression.setRuntime( oldRuntime ); } } } protected void reactivateExpressions( final boolean deepTraversing ) { final int activeLevel = getProcessingLevel(); final ExpressionRuntime runtime = getRuntime(); final int runlevelCount = getRunLevelCount(); for ( int levelIdx = 0; levelIdx < runlevelCount; levelIdx++ ) { final LevelStorage levelData = getRunLevel( levelIdx ); final int level = levelData.getLevelNumber(); if ( level < activeLevel ) { break; } final Iterator<Expression> expressions = levelData.getActiveExpressions(); while ( expressions.hasNext() ) { final Expression expression = expressions.next(); if ( deepTraversing && expression.isDeepTraversing() == false ) { continue; } final ExpressionRuntime oldRuntime = expression.getRuntime(); expression.setRuntime( runtime ); evaluateSingleExpression( expression ); expression.setRuntime( oldRuntime ); } } } protected void evaluateSingleExpression( final Expression expression ) { final int activeLevel = getProcessingLevel(); final String name = expression.getName(); Object value; try { if ( activeLevel <= expression.getDependencyLevel() ) { value = expression.getValue(); } else { value = null; } } catch ( final InvalidReportStateException fe ) { throw fe; } catch ( final Exception e ) { logger.info( "Evaluation of expression '" + name + "'failed.", e ); value = null; } if ( name != null ) { // DebugLog.log("Eval Expression: " + name + " " + value); updateMasterDataRow( name, value ); } } protected void evaluateToNull( final Expression expression ) { final String name = expression.getName(); if ( name != null ) { updateMasterDataRow( name, null ); } } protected void updateMasterDataRow( final String name, final Object value ) { } }