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: * TotalItemMaxFunction.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.io.IOException;
032: import java.io.ObjectInputStream;
033: import java.util.HashMap;
034:
035: import org.jfree.report.event.ReportEvent;
036: import org.jfree.report.states.ReportStateKey;
037: import org.jfree.util.Log;
038:
039: /**
040: * A report function that pre-computes the largest item in a group. The Items must be mutually comparable
041: * among each other or the function will fail. Comparing dates with strings will not work.
042: * <p/>
043: * Like all Total-Functions, this function produces a precomputed grand total. The function's result
044: * is precomputed once and will not change later. Printing the result of this function in a group header
045: * returns the same value as printed in the group-footer.
046: * <p/>
047: * A group can be defined using the property "group". If the group property is not set, the function will process the
048: * whole report.
049: *
050: * @author Thomas Morgner
051: */
052: public class TotalItemMaxFunction extends AbstractFunction {
053: /**
054: * A map of results, keyed by the process-key.
055: */
056: private transient HashMap results;
057:
058: /**
059: * The name of the group on which to reset.
060: */
061: private String group;
062: /**
063: * The field that should be evaluated.
064: */
065: private String field;
066: /**
067: * The currently computed maximum value.
068: */
069: private transient Comparable max;
070: /**
071: * The global state key is used to store the result for the whole report.
072: */
073: private transient ReportStateKey globalStateKey;
074: /**
075: * The current group key is used to store the result for the current group.
076: */
077: private transient ReportStateKey groupStateKey;
078:
079: /**
080: * Default constructor.
081: */
082: public TotalItemMaxFunction() {
083: results = new HashMap();
084: }
085:
086: /**
087: * Returns the field used by the function. The field name corresponds to a column name in the report's data-row.
088: *
089: * @return The field name.
090: */
091: public String getField() {
092: return field;
093: }
094:
095: /**
096: * Sets the field name for the function. The field name corresponds to a column name in the report's data-row.
097: *
098: * @param field the field name.
099: */
100: public void setField(final String field) {
101: this .field = field;
102: }
103:
104: /**
105: * Receives notification that the report has started.
106: *
107: * @param event the event.
108: */
109: public void reportInitialized(final ReportEvent event) {
110: globalStateKey = event.getState().getProcessKey();
111: if (FunctionUtilities.isDefinedPrepareRunLevel(this , event)) {
112: results.clear();
113: this .max = null;
114: results.put(globalStateKey, null);
115: } else {
116: this .max = (Comparable) results.get(globalStateKey);
117: }
118: }
119:
120: /**
121: * Receives notification that a group has started.
122: *
123: * @param event the event.
124: */
125: public void groupStarted(final ReportEvent event) {
126: if (FunctionUtilities.isDefinedGroup(getGroup(), event) == false) {
127: // wrong group ...
128: return;
129: }
130:
131: groupStateKey = event.getState().getProcessKey();
132: if (FunctionUtilities.isDefinedPrepareRunLevel(this , event)) {
133: this .max = null;
134: results.put(globalStateKey, max);
135: results.put(groupStateKey, max);
136: } else {
137: // Activate the current group, which was filled in the prepare run.
138: max = (Integer) results.get(groupStateKey);
139: }
140: }
141:
142: /**
143: * Receives notification that a row of data is being processed.
144: *
145: * @param event the event.
146: */
147: public void itemsAdvanced(final ReportEvent event) {
148: if (FunctionUtilities.isDefinedPrepareRunLevel(this , event) == false) {
149: return;
150: }
151:
152: final Object fieldValue = event.getDataRow().get(getField());
153: if (fieldValue instanceof Comparable == false) {
154: return;
155: }
156: try {
157: final Comparable compare = (Comparable) fieldValue;
158: if (max == null) {
159: max = compare;
160: } else if (max.compareTo(compare) < 0) {
161: max = compare;
162: }
163: } catch (Exception e) {
164: Log
165: .error("TotalItemMaxFunction.advanceItems(): problem comparing values.");
166: }
167:
168: results.put(globalStateKey, max);
169: if (groupStateKey != null) {
170: results.put(groupStateKey, max);
171: }
172: }
173:
174: /**
175: * Returns the name of the group for which the minimum should be computed.
176: *
177: * @return the group name.
178: */
179: public String getGroup() {
180: return group;
181: }
182:
183: /**
184: * Defines the name of the group to be totalled. If the name is null, the minimum for the whole report is computed.
185: *
186: * @param group the group name.
187: */
188: public void setGroup(final String group) {
189: this .group = group;
190: }
191:
192: /**
193: * Returns the computed maximum value.
194: *
195: * @return The computed maximum value.
196: */
197: public Object getValue() {
198: return max;
199: }
200:
201: /**
202: * Return a completly separated copy of this function. The copy does no longer share any
203: * changeable objects with the original function.
204: *
205: * @return a copy of this function.
206: */
207: public Expression getInstance() {
208: final TotalItemMaxFunction function = (TotalItemMaxFunction) super
209: .getInstance();
210: function.results = new HashMap();
211: return function;
212: }
213:
214: /**
215: * Helper function for the serialization.
216: *
217: * @param in the input stream.
218: * @throws IOException if an IO error occured.
219: * @throws ClassNotFoundException if a required class could not be found.
220: */
221: private void readObject(final ObjectInputStream in)
222: throws IOException, ClassNotFoundException {
223: in.defaultReadObject();
224: results = new HashMap();
225: }
226:
227: }
|