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: * TotalItemCountFunction.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.report.util.IntegerCache;
038:
039: /**
040: * A report function that counts the total number of items contained in groups in a
041: * report. If no groupname is given, all items of the report are counted.
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: * The ItemCount can be used to produce a running row-count for a group or report.
048: * <p/>
049: * To count the number of groups in a report, use the TotalGroupCountFunction.
050: *
051: * @author Thomas Morgner
052: */
053: public class TotalItemCountFunction extends AbstractFunction {
054: /**
055: * A map of results, keyed by the process-key.
056: */
057: private transient HashMap results;
058:
059: /**
060: * The name of the group on which to reset.
061: */
062: private String group;
063:
064: /**
065: * The current row-count.
066: */
067: private transient Integer result;
068: /**
069: * The global state key is used to store the result for the whole report.
070: */
071: private transient ReportStateKey globalStateKey;
072: /**
073: * The current group key is used to store the result for the current group.
074: */
075: private transient ReportStateKey groupStateKey;
076:
077: /**
078: * Default constructor.
079: */
080: public TotalItemCountFunction() {
081: results = new HashMap();
082: }
083:
084: /**
085: * Receives notification that the report has started.
086: *
087: * @param event the event.
088: */
089: public void reportInitialized(final ReportEvent event) {
090: globalStateKey = event.getState().getProcessKey();
091: if (isPrepareRunLevel(event)) {
092: results.clear();
093: result = IntegerCache.getInteger(0);
094: results.put(globalStateKey, result);
095: } else {
096: result = (Integer) results.get(globalStateKey);
097: }
098: }
099:
100: protected boolean isPrepareRunLevel(final ReportEvent event) {
101: return FunctionUtilities.isDefinedPrepareRunLevel(this , event);
102: }
103:
104: /**
105: * Receives notification that a group has started.
106: *
107: * @param event the event.
108: */
109: public void groupStarted(final ReportEvent event) {
110: if (FunctionUtilities.isDefinedGroup(getGroup(), event) == false) {
111: // wrong group ...
112: return;
113: }
114:
115: groupStateKey = event.getState().getProcessKey();
116: if (isPrepareRunLevel(event)) {
117: result = IntegerCache.getInteger(0);
118: results.put(globalStateKey, result);
119: results.put(groupStateKey, result);
120: } else {
121: // Activate the current group, which was filled in the prepare run.
122: result = (Integer) results.get(groupStateKey);
123: }
124: }
125:
126: /**
127: * Receives notification that a row of data is being processed.
128: *
129: * @param event the event.
130: */
131: public void itemsAdvanced(final ReportEvent event) {
132: if (isPrepareRunLevel(event) == false) {
133: return;
134: }
135:
136: result = IntegerCache.getInteger(result.intValue() + 1);
137: results.put(globalStateKey, result);
138: if (groupStateKey != null) {
139: results.put(groupStateKey, result);
140: }
141: }
142:
143: protected Integer getCount() {
144: return result;
145: }
146:
147: protected void setCount(final Integer result) {
148: if (result == null) {
149: throw new NullPointerException();
150: }
151: this .result = result;
152: }
153:
154: /**
155: * Returns the name of the group to be totalled.
156: *
157: * @return the group name.
158: */
159: public String getGroup() {
160: return group;
161: }
162:
163: /**
164: * Defines the name of the group to be totalled. If the name is null, all groups are
165: * 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 number of items counted (so far) by the function. This is either the
175: * number of items in the report, or the group (if a group has been defined for the
176: * function).
177: *
178: * @return The item count.
179: */
180: public Object getValue() {
181: return result;
182: }
183:
184: /**
185: * Return a completly separated copy of this function. The copy does no longer share any
186: * changeable objects with the original function.
187: *
188: * @return a copy of this function.
189: */
190: public Expression getInstance() {
191: final TotalItemCountFunction function = (TotalItemCountFunction) super
192: .getInstance();
193: function.results = new HashMap();
194: return function;
195: }
196:
197: /**
198: * Helper function for the serialization.
199: *
200: * @param in the input stream.
201: * @throws IOException if an IO error occured.
202: * @throws ClassNotFoundException if a required class could not be found.
203: */
204: private void readObject(final ObjectInputStream in)
205: throws IOException, ClassNotFoundException {
206: in.defaultReadObject();
207: results = new HashMap();
208: }
209:
210: }
|