001: /**
002: * ===========================================
003: * JFreeReport : a free Java reporting library
004: * ===========================================
005: *
006: * Project Info: http://reporting.pentaho.org/
007: *
008: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
009: *
010: * This library is free software; you can redistribute it and/or modify it under the terms
011: * of the GNU Lesser General Public License as published by the Free Software Foundation;
012: * either version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015: * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: * See the GNU Lesser General Public License for more details.
017: *
018: * You should have received a copy of the GNU Lesser General Public License along with this
019: * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020: * Boston, MA 02111-1307, USA.
021: *
022: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023: * in the United States and other countries.]
024: *
025: * ------------
026: * PercentageExpression.java
027: * ------------
028: * (C) Copyright 2001-2007, by Object Refinery Ltd, Pentaho Corporation and Contributors.
029: */package org.jfree.report.function;
030:
031: import java.math.BigDecimal;
032:
033: /**
034: * Computes the percentage for a column in relation to a base column.
035: * <p/>
036: * The function undestands two parameters. The <code>dividend</code> parameter is required and denotes the name of an
037: * ItemBand-field which is used as dividend. The <code>divisor</code> parameter is required and denotes the name of an
038: * ItemBand-field which is uses as divisor.
039: * <p/>
040: * If either the divident or the divisor are not numeric, the expression will return <code>null</code>.
041: * <p/>
042: * The formula used is as follows:
043: * <pre>
044: * Percent := divident / divisor
045: * </pre>
046: * <p/>
047: * If the flag <code>useDifference</code> is set, the difference between base and subject is used instead.
048: * <pre>
049: * Percent := (divisor - divident) / divisor
050: * </pre>
051: *
052: * @author Heiko Evermann
053: * @author Thomas Morgner
054: * @deprecated The same can be achieved using a simple ValueExpression.
055: */
056: public class PercentageExpression extends AbstractExpression {
057: /**
058: * A constant for the value ZERO.
059: */
060: private static final BigDecimal ZERO = new BigDecimal(0);
061: /**
062: * the field used as dividend by the function.
063: */
064: private String dividend;
065: /**
066: * the field used as divisor by the function.
067: */
068: private String divisor;
069: /**
070: * A flag indicating whether the difference between divident and divisor should be used as real divisor.
071: */
072: private boolean useDifference;
073: /**
074: * The scale-property defines the precission of the divide-operation.
075: */
076: private int scale;
077: /**
078: * The rounding-property defines the precission of the divide-operation.
079: */
080: private int roundingMode;
081:
082: /**
083: * Constructs a new function. <P> Initially the function has no name...be sure to assign one before using the
084: * function.
085: */
086: public PercentageExpression() {
087: scale = 14;
088: roundingMode = BigDecimal.ROUND_HALF_UP;
089: }
090:
091: /**
092: * Returns whether the difference between divident and divisor should be used as real divisor.
093: *
094: * @return true, if the difference is used, false if the divident is used directly.
095: */
096: public boolean isUseDifference() {
097: return useDifference;
098: }
099:
100: /**
101: * Defines whether the difference between divident and divisor should be used as real divisor.
102: *
103: * @param useDifference true, if the difference is used, false if the divident is used directly.
104: */
105: public void setUseDifference(final boolean useDifference) {
106: this .useDifference = useDifference;
107: }
108:
109: /**
110: * Returns the defined rounding mode. This influences the precision of the divide-operation.
111: *
112: * @return the rounding mode.
113: * @see java.math.BigDecimal#divide(java.math.BigDecimal,int)
114: */
115: public int getRoundingMode() {
116: return roundingMode;
117: }
118:
119: /**
120: * Defines the rounding mode. This influences the precision of the divide-operation.
121: *
122: * @param roundingMode the rounding mode.
123: * @see java.math.BigDecimal#divide(java.math.BigDecimal,int)
124: */
125: public void setRoundingMode(final int roundingMode) {
126: this .roundingMode = roundingMode;
127: }
128:
129: /**
130: * Returns the scale for the divide-operation. The scale influences the precision of the division.
131: *
132: * @return the scale.
133: */
134: public int getScale() {
135: return scale;
136: }
137:
138: /**
139: * Defines the scale for the divide-operation. The scale influences the precision of the division.
140: *
141: * @param scale the scale.
142: */
143: public void setScale(final int scale) {
144: this .scale = scale;
145: }
146:
147: /**
148: * Returns the field used as dividend by the function. <P> The field name corresponds to a column name in the report's
149: * data-row.
150: *
151: * @return The field name.
152: */
153: public String getDividend() {
154: return dividend;
155: }
156:
157: /**
158: * Returns the field used as divisor by the function. <P> The field name corresponds to a column name in the report's
159: * data-row.
160: *
161: * @return The field name.
162: */
163: public String getDivisor() {
164: return divisor;
165: }
166:
167: /**
168: * Sets the field name to be used as dividend for the function. <P> The field name corresponds to a column name in the
169: * report's data-row.
170: *
171: * @param dividend the field name.
172: */
173: public void setDividend(final String dividend) {
174: this .dividend = dividend;
175: }
176:
177: /**
178: * Sets the field name to be used as divisor for the function. <P> The field name corresponds to a column name in the
179: * report's data-row.
180: *
181: * @param divisor the field name.
182: */
183: public void setDivisor(final String divisor) {
184: this .divisor = divisor;
185: }
186:
187: /**
188: * Return the current function value. <P> The value is calculated as the quotient of two columns: the dividend column
189: * and the divisor column. If the divisor is zero, the return value is "n/a";
190: *
191: * @return The quotient
192: */
193: public Object getValue() {
194: if (dividend == null || divisor == null) {
195: return null;
196: }
197:
198: final Object dividentFieldValue = getDataRow().get(
199: getDividend());
200: // do not add when field is null or no number
201: final BigDecimal dividend;
202: if (dividentFieldValue instanceof BigDecimal) {
203: dividend = (BigDecimal) dividentFieldValue;
204: } else if (dividentFieldValue instanceof Number == false) {
205: return null;
206: } else {
207: dividend = new BigDecimal(dividentFieldValue.toString());
208: }
209:
210: final Object divisorFieldValue = getDataRow().get(getDivisor());
211: // do not add when field is null or no number
212: final BigDecimal divisor;
213: if (divisorFieldValue instanceof BigDecimal) {
214: divisor = (BigDecimal) divisorFieldValue;
215: } else if (divisorFieldValue instanceof Number == false) {
216: return null;
217: } else {
218: divisor = new BigDecimal(divisorFieldValue.toString());
219: }
220:
221: if (ZERO.compareTo(divisor) == 0) {
222: return null;
223: }
224:
225: if (useDifference) {
226: final BigDecimal delta = dividend.subtract(divisor);
227: return delta.divide(divisor, scale, roundingMode);
228: } else {
229: return dividend.divide(divisor, scale, roundingMode);
230: }
231: }
232: }
|