Package org.pentaho.reporting.engine.classic.core.states.datarow

Source Code of org.pentaho.reporting.engine.classic.core.states.datarow.ExpressionDataRow

/*
* 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 - 2009 Object Refinery Ltd, Pentaho Corporation and Contributors..  All rights reserved.
*/

package org.pentaho.reporting.engine.classic.core.states.datarow;

import java.util.ArrayList;
import javax.swing.table.TableModel;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.engine.classic.core.DataFactory;
import org.pentaho.reporting.engine.classic.core.DataRow;
import org.pentaho.reporting.engine.classic.core.ReportProcessingException;
import org.pentaho.reporting.engine.classic.core.ResourceBundleFactory;
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;
import org.pentaho.reporting.engine.classic.core.function.ProcessingContext;
import org.pentaho.reporting.engine.classic.core.states.DefaultGroupingState;
import org.pentaho.reporting.engine.classic.core.states.GroupingState;
import org.pentaho.reporting.engine.classic.core.util.IntList;
import org.pentaho.reporting.engine.classic.core.util.IntegerCache;
import org.pentaho.reporting.engine.classic.core.util.LevelList;
import org.pentaho.reporting.engine.classic.core.wizard.DataSchema;
import org.pentaho.reporting.libraries.base.config.Configuration;

/**
* Creation-Date: Dec 13, 2006, 3:17:20 PM
*
* @author Thomas Morgner
* @noinspection AssignmentToCollectionOrArrayFieldFromParameter,ReturnOfCollectionOrArrayField
*/
public final class ExpressionDataRow
{
  private static final Log logger = LogFactory.getLog(ExpressionDataRow.class);

  private static final Integer[] EMPTY_INTEGERARRAY = new Integer[0];
  private static final Expression[] EMPTY_EXPRESSIONS = new Expression[0];

  private static class DataRowRuntime implements ExpressionRuntime
  {
    private ExpressionDataRow expressionDataRow;
    private GroupingState state;

    protected DataRowRuntime(final ExpressionDataRow dataRow)
    {
      this.expressionDataRow = dataRow;
      this.state = DefaultGroupingState.EMPTY;
    }

    public DataSchema getDataSchema()
    {
      return expressionDataRow.getMasterRow().getDataSchema();
    }

    public DataRow getDataRow()
    {
      return expressionDataRow.getMasterRow().getGlobalView();
    }

    public Configuration getConfiguration()
    {
      return getProcessingContext().getConfiguration();
    }

    public ResourceBundleFactory getResourceBundleFactory()
    {
      return expressionDataRow.getMasterRow().getResourceBundleFactory();
    }

    public DataFactory getDataFactory()
    {
      return expressionDataRow.getMasterRow().getDataFactory();
    }

    /**
     * Access to the tablemodel was granted using report properties, now direct.
     */
    public TableModel getData()
    {
      return expressionDataRow.getMasterRow().getReportDataRow().getReportData();
    }

    /**
     * Where are we in the current processing.
     */
    public int getCurrentRow()
    {
      return expressionDataRow.getMasterRow().getReportDataRow().getCursor();
    }

    /**
     * The output descriptor is a simple string collections consisting of the following components:
     * exportclass/type/subtype
     * <p/>
     * For example, the PDF export would be: pageable/pdf The StreamHTML export would return table/html/stream
     *
     * @return the export descriptor.
     */
    public String getExportDescriptor()
    {
      return getProcessingContext().getExportDescriptor();
    }

    public ProcessingContext getProcessingContext()
    {
      return expressionDataRow.getProcessingContext();
    }

    public int getCurrentGroup()
    {
      return state.getCurrentGroup();
    }

    public int getGroupStartRow(final String groupName)
    {
      return state.getGroupStartRow(groupName);
    }

    public int getGroupStartRow(final int groupIndex)
    {
      return state.getGroupStartRow(groupIndex);
    }

    public GroupingState getState()
    {
      return state;
    }

    public void setState(final GroupingState state)
    {
      if (state == null)
      {
        throw new NullPointerException();
      }
      this.state = state;
    }
  }


  private static class LevelStorage
  {
    private int levelNumber;
    private int[] activeExpressions;
    private int[] functions;
    private int[] pageEventListeners;
    private int[] prepareEventListeners;
    private int[] expressions;

    protected LevelStorage(final int levelNumber,
                           final int[] expressions,
                           final int[] activeExpressions,
                           final int[] functions,
                           final int[] pageEventListeners,
                           final int[] prepareEventListeners)
    {
      this.levelNumber = levelNumber;
      this.activeExpressions = activeExpressions;
      this.functions = functions;
      this.pageEventListeners = pageEventListeners;
      this.prepareEventListeners = prepareEventListeners;
      this.expressions = expressions;
    }

    public int getLevelNumber()
    {
      return levelNumber;
    }

    public int[] getFunctions()
    {
      return functions;
    }


    /**
     * @return Returns the activeExpressions.
     */
    public int[] getActiveExpressions()
    {
      return activeExpressions;
    }

    /**
     * @return Returns the expressions.
     * @noinspection ReturnOfCollectionOrArrayField
     */
    public int[] getExpressions()
    {
      return expressions;
    }

    /**
     * @return Returns the pageEventListeners.
     */
    public int[] getPageEventListeners()
    {
      return pageEventListeners;
    }

    /**
     * @return Returns the prepareEventListeners.
     */
    public int[] getPrepareEventListeners()
    {
      return prepareEventListeners;
    }
  }

  //private HashMap nameCache;
  private MasterDataRow masterRow;
  private ProcessingContext processingContext;
  private int length;
  private Expression[] expressions;
  private LevelStorage[] levelData;
  private MasterDataRowChangeEvent chEvent;
  private DataRowRuntime runtime;
  private ArrayList errorList;
  private static final Exception[] EMPTY_EXCEPTIONS = new Exception[0];
  private boolean prepareEventListener;
  private boolean includeStructuralProcessing;

  public ExpressionDataRow(final MasterDataRow masterRow,
                           final ProcessingContext processingContext,
                           final boolean includeStructuralProcessing)
  {
    if (masterRow == null)
    {
      throw new NullPointerException();
    }
    if (processingContext == null)
    {
      throw new NullPointerException();
    }

    this.includeStructuralProcessing = includeStructuralProcessing;
    this.processingContext = processingContext;
    this.masterRow = masterRow;
    this.expressions = ExpressionDataRow.EMPTY_EXPRESSIONS;
    this.chEvent = new MasterDataRowChangeEvent
        (MasterDataRowChangeEvent.COLUMN_UPDATED, "", "");
    this.runtime = new DataRowRuntime(this);
    this.revalidate();
  }

  public boolean isIncludeStructuralProcessing()
  {
    return includeStructuralProcessing;
  }

  private ExpressionDataRow(final MasterDataRow masterRow,
                            final ExpressionDataRow previousRow,
                            final boolean updateGlobalView)
      throws CloneNotSupportedException
  {
    this.chEvent = new MasterDataRowChangeEvent
        (MasterDataRowChangeEvent.COLUMN_UPDATED, "", "");
    this.processingContext = previousRow.processingContext;
    this.masterRow = masterRow;
    this.expressions = new Expression[previousRow.expressions.length];
    this.length = previousRow.length;
    this.levelData = previousRow.levelData;
    this.runtime = new DataRowRuntime(this);
    this.runtime.setState(previousRow.runtime.getState());
    this.includeStructuralProcessing = previousRow.includeStructuralProcessing;

    for (int i = 0; i < length; i++)
    {
      final Expression expression = previousRow.expressions[i];
      if (expression == null)
      {
        ExpressionDataRow.logger.debug("Error: Expression is null...");
        throw new IllegalStateException();
      }

      if (expression instanceof Function)
      {
        expressions[i] = (Expression) expression.clone();
      }
      else
      {
        expressions[i] = expression;
      }

      if (updateGlobalView == false)
      {
        continue;
      }

      final String name = expression.getName();
      if (name != null)
      {
        chEvent.setColumnName(name);
      }
      Object value;

      final ExpressionRuntime oldRuntime = expression.getRuntime();
      try
      {
        expression.setRuntime(runtime);
        if (runtime.getProcessingContext().getProcessingLevel() <= expression.getDependencyLevel())
        {
          value = expression.getValue();
        }
        else
        {
          value = null;
        }
      }
      catch (Exception e)
      {
        if (ExpressionDataRow.logger.isDebugEnabled())
        {
          ExpressionDataRow.logger.warn("Failed to evaluate expression '" + name + '\'', e);
        }
        else
        {
          ExpressionDataRow.logger.warn("Failed to evaluate expression '" + name + '\'');
        }
        value = null;
      }
      finally
      {
        expression.setRuntime(oldRuntime);
      }
      if (name != null)
      {
        chEvent.setColumnValue(value);
        masterRow.dataRowChanged(chEvent);
      }
    }
  }

  /**
   * This adds the expression to the data-row and queries the expression for the first time.
   *
   * @param expressionSlot the expression that should be added.
   * @param preserveState  a flag indicating whether the expression is statefull and should preserve its internal
   *                       state.
   * @throws ReportProcessingException if the processing failed due to invalid function implementations.
   */
  private void pushExpression(final Expression expressionSlot,
                              final boolean preserveState)
      throws ReportProcessingException
  {
    if (expressionSlot == null)
    {
      throw new NullPointerException();
    }

    ensureCapacity(length + 1);

    if (preserveState == false)
    {
      this.expressions[length] = expressionSlot.getInstance();
    }
    else
    {
      try
      {
        this.expressions[length] = (Expression) expressionSlot.clone();
      }
      catch (final CloneNotSupportedException e)
      {
        throw new ReportProcessingException("Failed to clone the expression.", e);
      }
    }

    final String name = expressionSlot.getName();
    length += 1;

    // A manual advance to initialize the function.
    if (name != null)
    {
      final MasterDataRowChangeEvent chEvent = new MasterDataRowChangeEvent
          (MasterDataRowChangeEvent.COLUMN_ADDED, name, null);
      masterRow.dataRowChanged(chEvent);
    }
  }

  public void pushExpressions(final Expression[] expressionSlots,
                              final boolean preserveState)
      throws ReportProcessingException
  {
    if (expressionSlots == null)
    {
      throw new NullPointerException();
    }

    ensureCapacity(length + expressionSlots.length);
    for (int i = 0; i < expressionSlots.length; i++)
    {
      final Expression expression = expressionSlots[i];
      if (expression == null)
      {
        continue;
      }
      pushExpression(expression, preserveState);
    }

    revalidate();
  }

  public void popExpressions(final int counter)
  {
    for (int i = 0; i < counter; i++)
    {
      popExpression();
    }

    revalidate();
  }

  private void popExpression()
  {
    if (length == 0)
    {
      return;
    }
    final Expression removedExpression = this.expressions[length - 1];
    final String originalName = removedExpression.getName();
    removedExpression.setRuntime(null);

    this.expressions[length - 1] = null;
    this.length -= 1;
    if (originalName != null)
    {
      if (removedExpression.isPreserve() == false)
      {
        final MasterDataRowChangeEvent chEvent = new MasterDataRowChangeEvent
            (MasterDataRowChangeEvent.COLUMN_REMOVED, originalName, null);
        masterRow.dataRowChanged(chEvent);
      }
    }
  }

  private void ensureCapacity(final int requestedSize)
  {
    final int capacity = this.expressions.length;
    if (capacity > requestedSize)
    {
      return;
    }
    final int newSize = Math.max(capacity * 2, requestedSize + 10);

    final Expression[] newExpressions = new Expression[newSize];
    System.arraycopy(expressions, 0, newExpressions, 0, length);

    this.expressions = newExpressions;
  }

  private void revalidate()
  {
    // recompute the level storage ..
    int minLevel = Integer.MIN_VALUE;
    final LevelList levelList = new LevelList();
    for (int i = 0; i < length; i++)
    {
      final Expression expression = expressions[i];

      // The list maps the current position to the level ..
      final int dependencyLevel = expression.getDependencyLevel();
      levelList.add(IntegerCache.getInteger(i), dependencyLevel);
      if (minLevel < dependencyLevel)
      {
        minLevel = dependencyLevel;
      }
    }

    if (minLevel > Integer.MIN_VALUE)
    {
      if (isIncludeStructuralProcessing())
      {
        for (int i = 0; i < length; i++)
        {
          final Expression expression = expressions[i];

          // The list maps the current position to the level ..
          final int dependencyLevel = expression.getDependencyLevel();
          if (dependencyLevel == minLevel && (expression instanceof Function == false))
          {
            levelList.add(IntegerCache.getInteger(i), minLevel);
          }
        }
      }
    }

    final Integer[] levels = levelList.getLevelsDescendingArray();
    this.levelData = new LevelStorage[levels.length];
    final int expressionsCount = levelList.size();

    final int capacity = Math.min(20, expressionsCount);
    final IntList expressionPositions = new IntList(capacity);
    final IntList activeExpressions = new IntList(capacity);
    final IntList functions = new IntList(capacity);
    final IntList pageEventListeners = new IntList(capacity);
    final IntList prepareEventListeners = new IntList(capacity);
    final boolean prepareEventListener = false;

    for (int i = 0; i < levels.length; i++)
    {
      final int currentLevel = levels[i].intValue();
      final Integer[] data = (Integer[])
          levelList.getElementArrayForLevel(currentLevel, ExpressionDataRow.EMPTY_INTEGERARRAY);
      for (int x = 0; x < data.length; x++)
      {
        final Integer position = data[x];
        final Expression ex = this.expressions[position.intValue()];
        final int globalPosition = position.intValue();

        expressionPositions.add(globalPosition);
        activeExpressions.add(globalPosition);
        if (ex instanceof Function == false)
        {
          continue;
        }

        functions.add(globalPosition);
        if (ex instanceof PageEventListener)
        {
          pageEventListeners.add(globalPosition);
        }
      }

      levelData[i] = new LevelStorage(currentLevel,
          expressionPositions.toArray(), activeExpressions.toArray(),
          functions.toArray(), pageEventListeners.toArray(),
          prepareEventListeners.toArray());

      expressionPositions.clear();
      activeExpressions.clear();
      functions.clear();
      pageEventListeners.clear();
      prepareEventListeners.clear();

      this.prepareEventListener = prepareEventListener;
    }
  }

  public int[] getLevels()
  {
    final int[] retval = new int[levelData.length];
    for (int i = 0; i < levelData.length; i++)
    {
      final LevelStorage storage = levelData[i];
      retval[i] = storage.getLevelNumber();
    }
    return retval;
  }

  /**
   * Returns the number of columns, expressions and functions and marked ReportProperties in the report.
   *
   * @return the item count.
   */
  public int getColumnCount()
  {
    return length;
  }

  public void fireReportEvent(final ReportEvent event)
  {
    runtime.setState(event.getState().createGroupingState());

    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
    {
      throw new IllegalArgumentException();
    }

    reactivateExpressions(event.isDeepTraversing());
  }

  private void reactivateExpressions(final boolean deepTraversing)
  {
    final int activeLevel;

    final int rawLevel = processingContext.getProcessingLevel();
    if (rawLevel == Integer.MAX_VALUE)
    {
      // we are in the data-pre-processing stage. Include all common expressions, in case they
      // compute a group-break.
      if (levelData.length > 1)
      {
        activeLevel = levelData[1].getLevelNumber();
      }
      else
      {
        activeLevel = rawLevel;
      }
    }
    else
    {
      activeLevel = rawLevel;
    }

    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getActiveExpressions();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        expression.setRuntime(runtime);
        final String name = expression.getName();
        if (name != null)
        {
          chEvent.setColumnName(name);
          try
          {
            final Object value;
            if (runtime.getProcessingContext().getProcessingLevel() <= expression.getDependencyLevel())
            {
              value = expression.getValue();
            }
            else
            {
              value = null;
            }
            chEvent.setColumnValue(value);
          }
          catch (Exception e)
          {
            chEvent.setColumnValue(null);
            ExpressionDataRow.logger.info("Evaluation of expression '" + name + "'failed.", e);
          }
          masterRow.dataRowChanged(chEvent);
        }
        expression.setRuntime(null);
      }
    }
  }

  private void fireItemsAdvancedEvent(final ReportEvent event)
  {
    final boolean deepTraversing = event.isDeepTraversing();
    final int activeLevel = processingContext.getProcessingLevel();
    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getFunctions();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        final ExpressionRuntime oldRuntime = expression.getRuntime();
        expression.setRuntime(runtime);
        final Function e = (Function) expression;
        try
        {
          e.itemsAdvanced(event);
          final String name = expression.getName();
          if (name != null)
          {
            chEvent.setColumnName(name);
            chEvent.setColumnValue(expression.getValue());
            masterRow.dataRowChanged(chEvent);
          }
        }
        catch (Exception ex)
        {
          if (ExpressionDataRow.logger.isDebugEnabled())
          {
            ExpressionDataRow.logger.error("Failed to fire prepare event", ex);
          }
          else
          {
            ExpressionDataRow.logger.error("Failed to fire prepare event: " + ex);
          }
          addError(ex);
        }

        expression.setRuntime(oldRuntime);
      }
    }
  }

  private void fireItemsStartedEvent(final ReportEvent event)
  {
    final boolean deepTraversing = event.isDeepTraversing();
    final int activeLevel = processingContext.getProcessingLevel();
    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getFunctions();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        final ExpressionRuntime oldRuntime = expression.getRuntime();
        expression.setRuntime(runtime);
        final Function e = (Function) expression;
        try
        {
          e.itemsStarted(event);
          final String name = expression.getName();
          if (name != null)
          {
            chEvent.setColumnName(name);
            chEvent.setColumnValue(expression.getValue());
            masterRow.dataRowChanged(chEvent);
          }
        }
        catch (Exception ex)
        {
          if (ExpressionDataRow.logger.isDebugEnabled())
          {
            ExpressionDataRow.logger.error("Failed to fire prepare event", ex);
          }
          else
          {
            ExpressionDataRow.logger.error("Failed to fire prepare event: " + ex);
          }
          addError(ex);
        }

        expression.setRuntime(oldRuntime);
      }
    }
  }

  private void fireItemsFinishedEvent(final ReportEvent event)
  {
    final boolean deepTraversing = event.isDeepTraversing();
    final int activeLevel = processingContext.getProcessingLevel();
    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getFunctions();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        final ExpressionRuntime oldRuntime = expression.getRuntime();
        expression.setRuntime(runtime);
        final Function e = (Function) expression;
        try
        {
          e.itemsFinished(event);
          final String name = expression.getName();
          if (name != null)
          {
            chEvent.setColumnName(name);
            chEvent.setColumnValue(expression.getValue());
            masterRow.dataRowChanged(chEvent);
          }
        }
        catch (Exception ex)
        {
          if (ExpressionDataRow.logger.isDebugEnabled())
          {
            ExpressionDataRow.logger.error("Failed to fire prepare event", ex);
          }
          else
          {
            ExpressionDataRow.logger.error("Failed to fire prepare event: " + ex);
          }
          addError(ex);
        }

        expression.setRuntime(oldRuntime);
      }
    }
  }

  private void fireGroupStartedEvent(final ReportEvent event)
  {
    final boolean deepTraversing = event.isDeepTraversing();
    final int activeLevel = processingContext.getProcessingLevel();
    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getFunctions();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        final ExpressionRuntime oldRuntime = expression.getRuntime();
        expression.setRuntime(runtime);
        final Function e = (Function) expression;
        try
        {
          e.groupStarted(event);
          final String name = expression.getName();
          if (name != null)
          {
            chEvent.setColumnName(name);
            chEvent.setColumnValue(expression.getValue());
            masterRow.dataRowChanged(chEvent);
          }
        }
        catch (Exception ex)
        {
          if (ExpressionDataRow.logger.isDebugEnabled())
          {
            ExpressionDataRow.logger.error("Failed to fire group-started event", ex);
          }
          else
          {
            ExpressionDataRow.logger.error("Failed to fire group-started event: " + ex);
          }
          addError(ex);
        }

        expression.setRuntime(oldRuntime);
      }
    }
  }

  private void fireGroupFinishedEvent(final ReportEvent event)
  {
    final boolean deepTraversing = event.isDeepTraversing();
    final int activeLevel = processingContext.getProcessingLevel();
    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getFunctions();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        final ExpressionRuntime oldRuntime = expression.getRuntime();
        expression.setRuntime(runtime);
        final Function e = (Function) expression;
        try
        {
          e.groupFinished(event);
          final String name = expression.getName();
          if (name != null)
          {
            chEvent.setColumnName(name);
            chEvent.setColumnValue(expression.getValue());
            masterRow.dataRowChanged(chEvent);
          }
        }
        catch (Exception ex)
        {
          if (ExpressionDataRow.logger.isDebugEnabled())
          {
            ExpressionDataRow.logger.error("Failed to fire group-finished event", ex);
          }
          else
          {
            ExpressionDataRow.logger.error("Failed to fire group-finished event: " + ex);
          }
          addError(ex);
        }

        expression.setRuntime(oldRuntime);
      }
    }
  }

  private void fireReportStartedEvent(final ReportEvent event)
  {
    final boolean deepTraversing = event.isDeepTraversing();
    final int activeLevel = processingContext.getProcessingLevel();
    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getFunctions();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        final ExpressionRuntime oldRuntime = expression.getRuntime();
        expression.setRuntime(runtime);
        final Function e = (Function) expression;
        try
        {
          e.reportStarted(event);
          final String name = expression.getName();
          if (name != null)
          {
            chEvent.setColumnName(name);
            chEvent.setColumnValue(expression.getValue());
            masterRow.dataRowChanged(chEvent);
          }
        }
        catch (Exception ex)
        {
          if (ExpressionDataRow.logger.isDebugEnabled())
          {
            ExpressionDataRow.logger.error("Failed to fire report-started event", ex);
          }
          else
          {
            ExpressionDataRow.logger.error("Failed to fire report-started event: " + ex);
          }
          addError(ex);
        }

        expression.setRuntime(oldRuntime);
      }
    }
  }

  private void fireReportDoneEvent(final ReportEvent event)
  {
    final boolean deepTraversing = event.isDeepTraversing();
    final int activeLevel = processingContext.getProcessingLevel();
    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getFunctions();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        final ExpressionRuntime oldRuntime = expression.getRuntime();
        expression.setRuntime(runtime);
        final Function e = (Function) expression;
        try
        {
          e.reportDone(event);
          final String name = expression.getName();
          if (name != null)
          {
            chEvent.setColumnName(name);
            chEvent.setColumnValue(expression.getValue());
            masterRow.dataRowChanged(chEvent);
          }
        }
        catch (Exception ex)
        {
          if (ExpressionDataRow.logger.isDebugEnabled())
          {
            ExpressionDataRow.logger.error("Failed to fire report-done event", ex);
          }
          else
          {
            ExpressionDataRow.logger.error("Failed to fire report-done event: " + ex);
          }
          addError(ex);
        }

        expression.setRuntime(oldRuntime);
      }
    }
  }

  private void fireReportFinishedEvent(final ReportEvent event)
  {
    final boolean deepTraversing = event.isDeepTraversing();
    final int activeLevel = processingContext.getProcessingLevel();
    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getFunctions();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        final ExpressionRuntime oldRuntime = expression.getRuntime();
        expression.setRuntime(runtime);
        final Function e = (Function) expression;
        try
        {
          e.reportFinished(event);
          final String name = expression.getName();
          if (name != null)
          {
            chEvent.setColumnName(name);
            chEvent.setColumnValue(expression.getValue());
            masterRow.dataRowChanged(chEvent);
          }
        }
        catch (Exception ex)
        {
          if (ExpressionDataRow.logger.isDebugEnabled())
          {
            ExpressionDataRow.logger.error("Failed to fire report-finished event", ex);
          }
          else
          {
            ExpressionDataRow.logger.error("Failed to fire report-finished event: " + ex);
          }
          addError(ex);
        }

        expression.setRuntime(oldRuntime);
      }
    }
  }

  private void fireReportInitializedEvent(final ReportEvent event)
  {
    final boolean deepTraversing = event.isDeepTraversing();
    final int activeLevel = processingContext.getProcessingLevel();
    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getFunctions();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        final ExpressionRuntime oldRuntime = expression.getRuntime();
        expression.setRuntime(runtime);
        final Function e = (Function) expression;
        try
        {
          e.reportInitialized(event);
          final String name = expression.getName();
          if (name != null)
          {
            chEvent.setColumnName(name);
            chEvent.setColumnValue(expression.getValue());
            masterRow.dataRowChanged(chEvent);
          }

        }
        catch (Exception ex)
        {
          if (ExpressionDataRow.logger.isDebugEnabled())
          {
            ExpressionDataRow.logger.error("Failed to fire report-initialized event", ex);
          }
          else
          {
            ExpressionDataRow.logger.error("Failed to fire report-initialized event: " + ex);
          }
          addError(ex);
        }

        expression.setRuntime(oldRuntime);
      }
    }
  }

  private void firePageStartedEvent(final ReportEvent event)
  {
    final boolean deepTraversing = event.isDeepTraversing();
    final int activeLevel = processingContext.getProcessingLevel();
    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getPageEventListeners();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        final ExpressionRuntime oldRuntime = expression.getRuntime();
        expression.setRuntime(runtime);
        final PageEventListener e = (PageEventListener) expression;
        try
        {
          e.pageStarted(event);
          final String name = expression.getName();
          if (name != null)
          {
            chEvent.setColumnName(name);
            chEvent.setColumnValue(expression.getValue());
            masterRow.dataRowChanged(chEvent);
          }

        }
        catch (Exception ex)
        {
          if (ExpressionDataRow.logger.isDebugEnabled())
          {
            ExpressionDataRow.logger.error("Failed to fire page-started event", ex);
          }
          else
          {
            ExpressionDataRow.logger.error("Failed to fire page-started event: " + ex);
          }
          addError(ex);
        }

        expression.setRuntime(oldRuntime);
      }
    }
  }

  private void firePageFinishedEvent(final ReportEvent event)
  {
    final boolean deepTraversing = event.isDeepTraversing();
    final int activeLevel = processingContext.getProcessingLevel();
    for (int levelIdx = 0; levelIdx < levelData.length; levelIdx++)
    {
      final int level = levelData[levelIdx].getLevelNumber();
      if (level < activeLevel)
      {
        break;
      }

      final int[] listeners = levelData[levelIdx].getPageEventListeners();
      for (int l = 0; l < listeners.length; l++)
      {
        final Expression expression = expressions[listeners[l]];
        if (deepTraversing && expression.isDeepTraversing() == false)
        {
          continue;
        }

        final ExpressionRuntime oldRuntime = expression.getRuntime();
        expression.setRuntime(runtime);
        final PageEventListener e = (PageEventListener) expression;
        try
        {
          e.pageFinished(event);
          final String name = expression.getName();
          if (name != null)
          {
            chEvent.setColumnName(name);
            chEvent.setColumnValue(expression.getValue());
            masterRow.dataRowChanged(chEvent);
          }

        }
        catch (Exception ex)
        {
          if (ExpressionDataRow.logger.isDebugEnabled())
          {
            ExpressionDataRow.logger.error("Failed to fire page-finished event", ex);
          }
          else
          {
            ExpressionDataRow.logger.error("Failed to fire page-finished event: " + ex);
          }
          addError(ex);
        }

        expression.setRuntime(oldRuntime);
      }
    }
  }

  public ExpressionDataRow derive(final MasterDataRow masterRow,
                                  final boolean update)
  {
    try
    {
      return new ExpressionDataRow(masterRow, this, update);
    }
    catch (final CloneNotSupportedException e)
    {
      logger.error("Error on derive(..): ", e);
      throw new IllegalStateException("Cannot clone? Cannot survive!");
    }
  }

  public boolean isErrorOccured()
  {
    if (errorList == null)
    {
      return false;
    }
    return errorList.isEmpty() == false;
  }

  public void clearErrors()
  {
    if (errorList == null)
    {
      return;
    }
    this.errorList.clear();
  }

  public Exception[] getErrors()
  {
    if (errorList == null)
    {
      return ExpressionDataRow.EMPTY_EXCEPTIONS;
    }
    return (Exception[]) errorList.toArray(new Exception[errorList.size()]);
  }

  private void addError(final Exception e)
  {
    if (errorList == null)
    {
      errorList = new ArrayList();
    }
    errorList.add(e);
  }

  public boolean isValid()
  {
    return levelData != null;
  }

  public Expression[] getExpressions()
  {
    final Expression[] retval = new Expression[length];
    System.arraycopy(expressions, 0, retval, 0, length);
    return retval;
  }

  public boolean isPrepareEventListener()
  {
    return prepareEventListener;
  }


  /**
   * Returns the current master-row instance to inner-classes.
   *
   * @return a reference to the master-row (to be used in inner classes).
   * @noinspection ProtectedMemberInFinalClass
   */
  protected MasterDataRow getMasterRow()
  {
    return masterRow;
  }

  /**
   * Returns the current processing context to inner-classes.
   *
   * @return a reference to the processing context (to be used in inner classes).
   * @noinspection ProtectedMemberInFinalClass
   */
  protected ProcessingContext getProcessingContext()
  {
    return processingContext;
  }


  public void refresh()
  {
    reactivateExpressions(false);
  }
}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.states.datarow.ExpressionDataRow

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.