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: * ColumnAverageExpression.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 horizontal average over all columns specified in the field-list. The average will be computed over all
035: * fields of the current data-row, it will not be computed for all rows in the group. For that use the {@link
036: * org.jfree.report.function.ItemAvgFunction} instead.
037: * <p/>
038: * Non numeric and null-columns will be treated as zero for the task of summing up all members. Whether these fields are
039: * used counted as valid fields can be controlled with the 'onlyValidFields' flag.
040: *
041: * @author Thomas Morgner
042: */
043: public class ColumnAverageExpression extends
044: ColumnAggregationExpression {
045: /**
046: * A flag defining whether non-numeric and null-values should be ignored.
047: */
048: private boolean onlyValidFields;
049:
050: /**
051: * A flag defining whether the expression should return infinity if there are no valid fields. If set to false, this
052: * expression returns null instead.
053: */
054: private boolean returnInfinity;
055: /**
056: * The scale-property defines the precission of the divide-operation.
057: */
058: private int scale;
059: /**
060: * The rounding-property defines the precission of the divide-operation.
061: */
062: private int roundingMode;
063:
064: /**
065: * Default Constructor.
066: */
067: public ColumnAverageExpression() {
068: this .returnInfinity = true; // for backward compatiblity.
069: scale = 14;
070: roundingMode = BigDecimal.ROUND_HALF_UP;
071: }
072:
073: /**
074: * Returns the defined rounding mode. This influences the precision of the divide-operation.
075: *
076: * @return the rounding mode.
077: * @see java.math.BigDecimal#divide(java.math.BigDecimal,int)
078: */
079: public int getRoundingMode() {
080: return roundingMode;
081: }
082:
083: /**
084: * Defines the rounding mode. This influences the precision of the divide-operation.
085: *
086: * @param roundingMode the rounding mode.
087: * @see java.math.BigDecimal#divide(java.math.BigDecimal,int)
088: */
089: public void setRoundingMode(final int roundingMode) {
090: this .roundingMode = roundingMode;
091: }
092:
093: /**
094: * Returns the scale for the divide-operation. The scale influences the precision of the division.
095: *
096: * @return the scale.
097: */
098: public int getScale() {
099: return scale;
100: }
101:
102: /**
103: * Defines the scale for the divide-operation. The scale influences the precision of the division.
104: *
105: * @param scale the scale.
106: */
107: public void setScale(final int scale) {
108: this .scale = scale;
109: }
110:
111: /**
112: * Returns, whether the expression returns infinity if there are no valid fields. If set to false, this expression
113: * returns null instead.
114: *
115: * @return true, if infinity is returned, false otherwise.
116: */
117: public boolean isReturnInfinity() {
118: return returnInfinity;
119: }
120:
121: /**
122: * Defines, whether the expression returns infinity if there are no valid fields. If set to false, this expression
123: * returns null instead.
124: *
125: * @param returnInfinity true, if infinity is returned, false otherwise.
126: */
127: public void setReturnInfinity(final boolean returnInfinity) {
128: this .returnInfinity = returnInfinity;
129: }
130:
131: /**
132: * Returns, whether non-numeric and null-values are ignored for the average-computation.
133: *
134: * @return true, if the invalid fields will be ignored, false if they count as valid zero-value fields.
135: */
136: public boolean isOnlyValidFields() {
137: return onlyValidFields;
138: }
139:
140: /**
141: * Defines, whether non-numeric and null-values are ignored for the average-computation.
142: *
143: * @param onlyValidFields true, if the invalid fields will be ignored, false if they count as valid zero-value
144: * fields.
145: */
146: public void setOnlyValidFields(final boolean onlyValidFields) {
147: this .onlyValidFields = onlyValidFields;
148: }
149:
150: /**
151: * Computes the horizontal average of all field in the field-list. The average will be computed over all fields of the
152: * current data-row, it will not be computed for all rows in the group. For that use the {@link
153: * org.jfree.report.function.ItemAvgFunction} instead.
154: *
155: * @return the value of the function.
156: */
157: public Object getValue() {
158: final Object[] values = getFieldValues();
159: BigDecimal computedResult = new BigDecimal(0);
160: int count = 0;
161: for (int i = 0; i < values.length; i++) {
162: final Object value = values[i];
163: if (value instanceof Number == false) {
164: continue;
165: }
166:
167: final Number n = (Number) value;
168: final BigDecimal nval = new BigDecimal(n.toString());
169: computedResult = computedResult.add(nval);
170: count += 1;
171: }
172:
173: if (onlyValidFields) {
174: if (count == 0) {
175: if (returnInfinity == false) {
176: return null;
177: }
178: if (computedResult.signum() == -1) {
179: return new Double(Double.NEGATIVE_INFINITY);
180: } else {
181: return new Double(Double.POSITIVE_INFINITY);
182: }
183: }
184: return computedResult.divide(new BigDecimal(count), scale,
185: roundingMode);
186: }
187:
188: if (values.length == 0) {
189: if (returnInfinity == false) {
190: return null;
191: }
192: if (computedResult.signum() == -1) {
193: return new Double(Double.NEGATIVE_INFINITY);
194: } else {
195: return new Double(Double.POSITIVE_INFINITY);
196: }
197: }
198: return computedResult.divide(new BigDecimal(values.length),
199: scale, roundingMode);
200: }
201: }
|