Package org.pentaho.reporting.engine.classic.core.layout.output

Source Code of org.pentaho.reporting.engine.classic.core.layout.output.ElementChangeChecker$PerformanceCollector

/*!
* 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.output;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.engine.classic.core.AttributeNames;
import org.pentaho.reporting.engine.classic.core.DataRow;
import org.pentaho.reporting.engine.classic.core.Element;
import org.pentaho.reporting.engine.classic.core.ReportElement;
import org.pentaho.reporting.engine.classic.core.Section;
import org.pentaho.reporting.engine.classic.core.metadata.AttributeMetaData;
import org.pentaho.reporting.engine.classic.core.metadata.ElementMetaData;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;

public class ElementChangeChecker
{
  private static class NeedEvalResult implements Serializable
  {
    private boolean needToRun;
    private long changeTracker;
    private long styleChangeTracker;
    private long styleModificationCounter;
    private HashMap<String, Object> fieldsAndValues;

    private NeedEvalResult(final boolean needToRun, final ReportElement e,
                           final HashMap<String,Object> fieldsAndValues)
    {
      this.needToRun = needToRun;
      this.changeTracker = e.getChangeTracker();
      this.fieldsAndValues = fieldsAndValues;
      this.styleChangeTracker = e.getStyle().getChangeTracker();
      this.styleModificationCounter = e.getStyle().getModificationCount();
    }

    public boolean isNeedToRun()
    {
      return needToRun;
    }

    public long getChangeTracker()
    {
      return changeTracker;
    }

    public boolean isValid (final ReportElement e, final DataRow dataRow)
    {
      if (changeTracker != e.getChangeTracker() ||
          styleChangeTracker != e.getStyle().getChangeTracker() ||
          styleModificationCounter != e.getStyle().getModificationCount())
      {
        return false;
      }

      for (final Map.Entry<String, Object> entry : fieldsAndValues.entrySet())
      {
        final String field = entry.getKey();
        final Object oldValue = entry.getValue();
        final Object currentValue = dataRow.get(field);
        if (ObjectUtilities.equal(oldValue, currentValue) == false)
        {
          return false;
        }
      }

      return true;
    }
  }

  private static class ElementMetaDataEvaluationResult implements Serializable
  {
    private long changeTracker;
    private long styleChangeTracker;
    private long styleModificationCounter;
    private HashMap<String, Object> seenFields;

    private ElementMetaDataEvaluationResult(final ReportElement e,
                                            final HashMap<String, Object> seenFields)
    {
      this.seenFields = seenFields;
      changeTracker = e.getChangeTracker();
      styleChangeTracker = e.getStyle().getChangeTracker();
      styleModificationCounter = e.getStyle().getModificationCount();
    }

    public boolean isValid(final ReportElement e, final DataRow dataRow)
    {
      if (changeTracker != e.getChangeTracker() ||
          styleChangeTracker != e.getStyle().getChangeTracker() ||
          styleModificationCounter != e.getStyle().getModificationCount())
      {
        return false;
      }

      for (final Map.Entry<String, Object> entry : seenFields.entrySet())
      {
        final String field = entry.getKey();
        final Object oldValue = entry.getValue();
        final Object currentValue = dataRow.get(field);
        if (ObjectUtilities.equal(oldValue, currentValue) == false)
        {
          return false;
        }
      }

      return true;
    }

  }

  private static class PerformanceCollector
  {
    public int totalEvaluations;
    public int evaluations;
    public int skippedEvaluations;
  }

  private final Log performanceLogger = LogFactory.getLog(getClass());
  private PerformanceCollector performanceCollector;
  private String attrName;
  private String elementAttribute;

  private DataRow currentDataRow;
  private HashMap<String,Object> currentFieldsAndValues;

  public ElementChangeChecker()
  {
    performanceCollector = new PerformanceCollector();
    attrName = "ElementChangeTracker-NeedResult@" + System.identityHashCode(this);
    elementAttribute = "ElementChangeTracker-DetailResult@" + System.identityHashCode(this);
    currentFieldsAndValues = new HashMap<String, Object>();
  }

  public boolean isBandChanged(final Section b, final DataRow dataRow)
  {
    this.currentFieldsAndValues.clear();
    this.currentDataRow = dataRow;
    try
    {
      return processRootBand(b);
    }
    finally
    {
      this.currentFieldsAndValues.clear();
      this.currentDataRow = null;
    }
  }

  /**
   * Evaluates all style expressions from all elements and updates the style-sheet if needed.
   *
   * @param b the band.
   * @return true if the element needs reprinting.
   */
  protected final boolean processRootBand(final Section b)
  {
    if (b == null)
    {
      return false;
    }

    final NeedEvalResult needToRun = (NeedEvalResult) b.getAttribute(AttributeNames.Internal.NAMESPACE, attrName);
    if (needToRun != null)
    {
      if (needToRun.isNeedToRun() == false)
      {
        if (needToRun.isValid(b, currentDataRow))
        {
          recordCacheHit(b);
          return false;
        }
      }
    }

    recordCacheMiss(b);

    final boolean needToRunVal = processBand(b);
    b.setAttribute(AttributeNames.Internal.NAMESPACE, attrName,
        new NeedEvalResult(needToRunVal, b, (HashMap<String, Object>) currentFieldsAndValues.clone()), false);
    return true;
  }

  protected boolean evaluateElement(final ReportElement e)
  {
    final ElementMetaDataEvaluationResult evalResult =
        (ElementMetaDataEvaluationResult) e.getAttribute(AttributeNames.Internal.NAMESPACE, elementAttribute);
    if (evalResult != null && evalResult.isValid(e, currentDataRow))
    {
      currentFieldsAndValues.putAll(evalResult.seenFields);
      return false;
    }

    final HashMap<String, Object> values = new HashMap<String, Object>();
    final ElementMetaData metaData = e.getElementType().getMetaData();
    final AttributeMetaData[] attributeDescriptions = metaData.getAttributeDescriptions();
    for (int i = 0; i < attributeDescriptions.length; i++)
    {
      final AttributeMetaData attributeDescription = attributeDescriptions[i];
      final Object attribute = e.getAttribute(attributeDescription.getNameSpace(), attributeDescription.getName());
      if (attribute == null)
      {
        continue;
      }

      final String[] referencedFields = attributeDescription.getReferencedFields(e, attribute);
      for (int j = 0; j < referencedFields.length; j++)
      {
        final String field = referencedFields[j];
        final Object value = currentDataRow.get(field);
        values.put(field, value);
        currentFieldsAndValues.put(field, value);
      }
    }

    final ElementMetaDataEvaluationResult current = new ElementMetaDataEvaluationResult(e, values);
    e.setAttribute(AttributeNames.Internal.NAMESPACE, elementAttribute, current, false);
    return true;
  }

  protected final boolean processBand(final Section b)
  {
    boolean hasAttrExpressions = evaluateElement(b);

    final int length = b.getElementCount();
    for (int i = 0; i < length; i++)
    {
      final Element element = b.getElement(i);

      final ElementMetaData.TypeClassification reportElementType = element.getMetaData().getReportElementType();
      if (reportElementType == ElementMetaData.TypeClassification.DATA ||
          reportElementType == ElementMetaData.TypeClassification.CONTROL ||
          reportElementType == ElementMetaData.TypeClassification.SUBREPORT ||
          element instanceof Section == false)
      {
        if (evaluateElement(element))
        {
          hasAttrExpressions = true;
        }
      }
      else
      {
        final Section section = (Section) element;
        if (processBand(section))
        {
          hasAttrExpressions = true;
        }
      }
    }

    return hasAttrExpressions;
  }

  protected void recordCacheHit(final ReportElement e)
  {
    performanceCollector.totalEvaluations += 1;
    performanceCollector.skippedEvaluations += 1;
  }

  protected void recordCacheMiss(final ReportElement e)
  {
    performanceCollector.totalEvaluations += 1;
    performanceCollector.evaluations += 1;
  }

  protected void reportCachePerformance()
  {
    if (performanceLogger.isInfoEnabled())
    {
      performanceLogger.info(String.format("Performance: %s => total=%d, evaluated=%d (%f%%), avoided=%d (%f%%)", getClass(),
          performanceCollector.totalEvaluations,
          performanceCollector.evaluations,
          100f * performanceCollector.evaluations / Math.max(1.0f, performanceCollector.totalEvaluations),
          performanceCollector.skippedEvaluations,
          100f * performanceCollector.skippedEvaluations / Math.max(1.0f, performanceCollector.totalEvaluations)));
    }
  }

}
TOP

Related Classes of org.pentaho.reporting.engine.classic.core.layout.output.ElementChangeChecker$PerformanceCollector

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.