/* * 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.function; import java.math.BigDecimal; /** * Computes the percentage for a column in relation to a base column. * <p/> * The function undestands two parameters. The <code>dividend</code> parameter is required and denotes the name of an * ItemBand-field which is used as dividend. The <code>divisor</code> parameter is required and denotes the name of an * ItemBand-field which is uses as divisor. * <p/> * If either the divident or the divisor are not numeric, the expression will return <code>null</code>. * <p/> * The formula used is as follows: * * <pre> * Percent := divident / divisor * </pre> * <p/> * If the flag <code>useDifference</code> is set, the difference between base and subject is used instead. * * <pre> * Percent := (divisor - divident) / divisor * </pre> * * @author Heiko Evermann * @author Thomas Morgner * @deprecated The same can be achieved using a simple ValueExpression. */ @SuppressWarnings( "deprecation" ) public class PercentageExpression extends AbstractExpression { /** * A constant for the value ZERO. */ private static final BigDecimal ZERO = new BigDecimal( 0 ); /** * the field used as dividend by the function. */ private String dividend; /** * the field used as divisor by the function. */ private String divisor; /** * A flag indicating whether the difference between divident and divisor should be used as real divisor. */ private boolean useDifference; /** * The scale-property defines the precission of the divide-operation. */ private int scale; /** * The rounding-property defines the precission of the divide-operation. */ private int roundingMode; /** * Constructs a new function. * <P> * Initially the function has no name...be sure to assign one before using the function. */ public PercentageExpression() { scale = 14; roundingMode = BigDecimal.ROUND_HALF_UP; } /** * Returns whether the difference between divident and divisor should be used as real divisor. * * @return true, if the difference is used, false if the divident is used directly. */ public boolean isUseDifference() { return useDifference; } /** * Defines whether the difference between divident and divisor should be used as real divisor. * * @param useDifference * true, if the difference is used, false if the divident is used directly. */ public void setUseDifference( final boolean useDifference ) { this.useDifference = useDifference; } /** * Returns the defined rounding mode. This influences the precision of the divide-operation. * * @return the rounding mode. * @see java.math.BigDecimal#divide(java.math.BigDecimal, int) */ public int getRoundingMode() { return roundingMode; } /** * Defines the rounding mode. This influences the precision of the divide-operation. * * @param roundingMode * the rounding mode. * @see java.math.BigDecimal#divide(java.math.BigDecimal, int) */ public void setRoundingMode( final int roundingMode ) { this.roundingMode = roundingMode; } /** * Returns the scale for the divide-operation. The scale influences the precision of the division. * * @return the scale. */ public int getScale() { return scale; } /** * Defines the scale for the divide-operation. The scale influences the precision of the division. * * @param scale * the scale. */ public void setScale( final int scale ) { this.scale = scale; } /** * Returns the field used as dividend by the function. * <P> * The field name corresponds to a column name in the report's data-row. * * @return The field name. */ public String getDividend() { return dividend; } /** * Returns the field used as divisor by the function. * <P> * The field name corresponds to a column name in the report's data-row. * * @return The field name. */ public String getDivisor() { return divisor; } /** * Sets the field name to be used as dividend for the function. * <P> * The field name corresponds to a column name in the report's data-row. * * @param dividend * the field name. */ public void setDividend( final String dividend ) { this.dividend = dividend; } /** * Sets the field name to be used as divisor for the function. * <P> * The field name corresponds to a column name in the report's data-row. * * @param divisor * the field name. */ public void setDivisor( final String divisor ) { this.divisor = divisor; } /** * Return the current function value. * <P> * The value is calculated as the quotient of two columns: the dividend column and the divisor column. If the divisor * is zero, the return value is "n/a"; * * @return The quotient */ public Object getValue() { if ( dividend == null || divisor == null ) { return null; } final Object dividentFieldValue = getDataRow().get( getDividend() ); // do not add when field is null or no number final BigDecimal dividend; if ( dividentFieldValue instanceof BigDecimal ) { dividend = (BigDecimal) dividentFieldValue; } else if ( dividentFieldValue instanceof Number == false ) { return null; } else { dividend = new BigDecimal( dividentFieldValue.toString() ); } final Object divisorFieldValue = getDataRow().get( getDivisor() ); // do not add when field is null or no number final BigDecimal divisor; if ( divisorFieldValue instanceof BigDecimal ) { divisor = (BigDecimal) divisorFieldValue; } else if ( divisorFieldValue instanceof Number == false ) { return null; } else { divisor = new BigDecimal( divisorFieldValue.toString() ); } if ( PercentageExpression.ZERO.compareTo( divisor ) == 0 ) { return null; } if ( useDifference ) { final BigDecimal delta = dividend.subtract( divisor ); return delta.divide( divisor, scale, roundingMode ); } else { return dividend.divide( divisor, scale, roundingMode ); } } }