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: * TotalCalculationFunction.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:
038: /**
039: * A report function that stores the result of a calculation for a group or the complete report. This function
040: * can be used to convert simple running-functions into total-functions by wrapping them up. The wrapped up function
041: * will be evaluated as usual and the result at the end of the report and/or end of the group will be stored in the
042: * TotalCalculationFunction.
043: *
044: * @author Thomas Morgner
045: */
046: public class TotalCalculationFunction extends AbstractFunction {
047: /**
048: * A map of results, keyed by the process-key.
049: */
050: private transient HashMap results;
051:
052: /**
053: * The field that should be evaluated.
054: */
055: private String field;
056: /**
057: * The name of the group on which to reset.
058: */
059: private String group;
060:
061: /**
062: * The current result.
063: */
064: private transient Object result;
065: /**
066: * The global state key is used to store the result for the whole report.
067: */
068: private transient ReportStateKey globalStateKey;
069: /**
070: * The current group key is used to store the result for the current group.
071: */
072: private transient ReportStateKey groupStateKey;
073:
074: /**
075: * Constructs a new function. <P> Initially the function has no name...be sure to assign one before using the
076: * function.
077: */
078: public TotalCalculationFunction() {
079: results = new HashMap();
080: }
081:
082: /**
083: * Receives notification that the report has started.
084: *
085: * @param event the event.
086: */
087: public void reportInitialized(final ReportEvent event) {
088: globalStateKey = event.getState().getProcessKey();
089: if (FunctionUtilities.isDefinedPrepareRunLevel(this , event)) {
090: results.clear();
091: result = getDataRow().get(getField());
092: results.put(globalStateKey, result);
093: } else {
094: result = results.get(globalStateKey);
095: }
096: }
097:
098: /**
099: * Receives notification that a group has started.
100: *
101: * @param event the event.
102: */
103: public void groupStarted(final ReportEvent event) {
104: if (FunctionUtilities.isDefinedGroup(getGroup(), event) == false) {
105: // wrong group ...
106: return;
107: }
108:
109: groupStateKey = event.getState().getProcessKey();
110: if (FunctionUtilities.isDefinedPrepareRunLevel(this , event)) {
111: result = getDataRow().get(getField());
112: results.put(globalStateKey, result);
113: results.put(groupStateKey, result);
114: } else {
115: // Activate the current group, which was filled in the prepare run.
116: result = results.get(groupStateKey);
117: }
118: }
119:
120: /**
121: * Receives notification that a group has finished.
122: *
123: * @param event the event.
124: */
125: public void groupFinished(final ReportEvent event) {
126: if (FunctionUtilities.isDefinedGroup(getGroup(), event) == false) {
127: // wrong group ...
128: return;
129: }
130:
131: if (FunctionUtilities.isDefinedPrepareRunLevel(this , event)) {
132: result = getDataRow().get(getField());
133: results.put(globalStateKey, result);
134: if (groupStateKey != null) {
135: results.put(groupStateKey, result);
136: }
137: }
138: }
139:
140: /**
141: * Receives notification that the report has finished.
142: *
143: * @param event the event.
144: */
145: public void reportFinished(final ReportEvent event) {
146: if (FunctionUtilities.isDefinedPrepareRunLevel(this , event)) {
147: result = getDataRow().get(getField());
148: results.put(globalStateKey, result);
149: if (groupStateKey != null) {
150: results.put(groupStateKey, result);
151: }
152: }
153: }
154:
155: /**
156: * Returns the name of the group to be totalled.
157: *
158: * @return the group name.
159: */
160: public String getGroup() {
161: return group;
162: }
163:
164: /**
165: * Defines the name of the group to be totalled. If the name is null, all groups are totalled.
166: *
167: * @param group the group name.
168: */
169: public void setGroup(final String group) {
170: this .group = group;
171: }
172:
173: /**
174: * Returns the field used by the function. The field name corresponds to a column name in the report's data-row.
175: *
176: * @return The field name.
177: */
178: public String getField() {
179: return field;
180: }
181:
182: /**
183: * Sets the field name for the function. The field name corresponds to a column name in the report's data-row.
184: *
185: * @param field the field name.
186: */
187: public void setField(final String field) {
188: this .field = field;
189: }
190:
191: /**
192: * Return the current expression value. <P> The value depends (obviously) on the expression implementation.
193: *
194: * @return the value of the function.
195: */
196: public Object getValue() {
197: return result;
198: }
199:
200: /**
201: * Helper method for serialization.
202: *
203: * @param in the input stream from where to read the serialized object.
204: * @throws java.io.IOException when reading the stream fails.
205: * @throws ClassNotFoundException if a class definition for a serialized object could not be found.
206: */
207: private void readObject(final ObjectInputStream in)
208: throws IOException, ClassNotFoundException {
209: in.defaultReadObject();
210: results = new HashMap();
211: }
212:
213: public Expression getInstance() {
214: final TotalCalculationFunction fn = (TotalCalculationFunction) super
215: .getInstance();
216: fn.results = new HashMap();
217: return fn;
218: }
219: }
|