001: /*
002: * Copyright 2006 Pentaho Corporation. All rights reserved.
003: * This software was developed by Pentaho Corporation and is provided under the terms
004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
005: * this file except in compliance with the license. If you need a copy of the license,
006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
007: * BI Platform. The Initial Developer is Pentaho Corporation.
008: *
009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
011: * the license for the specific language governing your rights and limitations.
012: *
013: * Created March 1, 2006
014: * @author mbatchel
015: */
016: package org.pentaho.plugin.jfreereport.reportcharts;
017:
018: import java.util.ArrayList;
019: import java.util.List;
020:
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023: import org.jfree.data.general.AbstractDataset;
024: import org.jfree.data.general.DefaultPieDataset;
025: import org.jfree.report.event.ReportEvent;
026: import org.jfree.report.function.AbstractFunction;
027: import org.jfree.report.function.Expression;
028: import org.jfree.report.function.FunctionUtilities;
029: import org.pentaho.messages.Messages;
030:
031: public class PieSetCollectorFunction extends AbstractFunction implements
032: ICollectorFunction {
033:
034: // This COULD descend from BaseCollectorFunction, EXCEPT that this class
035: // has a String seriesColumn field, and BaseCollectorFunction has
036: // a boolean seriesColumn field. It's not worth it to require users
037: // to change old reports because of the field name change, so we
038: // have left this class ugly for the time being.
039:
040: private static final long serialVersionUID = -5778788510651234706L;
041:
042: // Things that change during the processing of the report
043: private int currentIndex;
044: DefaultPieDataset pieDataset;
045: private List results;
046:
047: // Things that come from the report definition
048: private String seriesColumn;
049: private String valueColumn;
050: private String group;
051: private String resetGroup;
052: private boolean summaryOnly;
053:
054: private static final Log logger = LogFactory
055: .getLog(PieSetCollectorFunction.class);
056:
057: public String getSeriesColumn() {
058: return seriesColumn;
059: }
060:
061: public String getValueColumn() {
062: return valueColumn;
063: }
064:
065: public String getGroup() {
066: return group;
067: }
068:
069: public String getResetGroup() {
070: return resetGroup;
071: }
072:
073: public void setSeriesColumn(String value) {
074: seriesColumn = value;
075: }
076:
077: public void setValueColumn(String value) {
078: valueColumn = value;
079: }
080:
081: public void setGroup(String value) {
082: group = value;
083: }
084:
085: public void setResetGroup(String value) {
086: resetGroup = value;
087: }
088:
089: public boolean isSummaryOnly() {
090: return summaryOnly;
091: }
092:
093: public void setSummaryOnly(boolean value) {
094: summaryOnly = value;
095: }
096:
097: public PieSetCollectorFunction() {
098: results = new ArrayList();
099: }
100:
101: public Object getValue() {
102: return this ;
103: }
104:
105: /**
106: * Return the dataset if we have one
107: */
108: public Object getDataSourceValue() {
109: return pieDataset;
110: }
111:
112: public void reportInitialized(ReportEvent event) {
113: currentIndex = -1;
114: logger.debug(Messages
115: .getString("PIESETCOLL.USER_DEBUG_REPORT_INITIALIZED")); //$NON-NLS-1$
116: if (FunctionUtilities.isDefinedPrepareRunLevel(this , event)) {
117: pieDataset = null;
118: results.clear();
119: if (getResetGroup() == null) {
120: pieDataset = new DefaultPieDataset();
121: results.add(pieDataset);
122: }
123: } else {
124: // Activate the current group, which was filled in the prepare run.
125: if (getResetGroup() == null) {
126: pieDataset = (DefaultPieDataset) results.get(0);
127: }
128: }
129: }
130:
131: public void groupStarted(ReportEvent event) {
132: logger.debug(Messages
133: .getString("PIESETCOLL.USER_DEBUG_GROUP_STARTED")); //$NON-NLS-1$
134:
135: final String localGroup = getGroup();
136: if (localGroup != null) {
137: if (FunctionUtilities
138: .isDefinedGroup(getResetGroup(), event)) {
139: // reset ...
140: if (FunctionUtilities.isDefinedPrepareRunLevel(this ,
141: event)) {
142: pieDataset = new DefaultPieDataset();
143: results.add(pieDataset);
144: } else {
145: if (FunctionUtilities.isLayoutLevel(event)) {
146: // Activate the current group, which was filled in the
147: // prepare run.
148: currentIndex += 1;
149: pieDataset = (DefaultPieDataset) results
150: .get(currentIndex);
151: }
152: }
153: }
154: }
155: }
156:
157: public void itemsAdvanced(ReportEvent reportEvent) {
158: logger.debug(Messages
159: .getString("PIESETCOLL.USER_DEBUG_ITEMS_ADVANCED")); //$NON-NLS-1$
160: if (FunctionUtilities.isDefinedPrepareRunLevel(this ,
161: reportEvent) == false) {
162: // we do not modify the created dataset if this is not the function
163: // computation run. (FunctionLevel '0')
164: return;
165: }
166:
167: DefaultPieDataset localPieDataset = null;
168: if (getDataSourceValue() instanceof DefaultPieDataset) {
169: localPieDataset = (DefaultPieDataset) getDataSourceValue();
170: }
171:
172: if (!isSummaryOnly()) {
173: final Object seriesObject = getDataRow().get(
174: getSeriesColumn());
175: final Comparable seriesComparable;
176: if (seriesObject instanceof Comparable) {
177: seriesComparable = (Comparable) seriesObject;
178: } else {
179: // ok, we need some better error management here. Its a
180: // prototype :)
181: seriesComparable = Messages
182: .getString("PIESETCOLL.USER_ERROR_CATEGORY_NOT_COMPARABLE"); //$NON-NLS-1$
183: }
184: final Object valueObject = getDataRow().get(
185: getValueColumn());
186:
187: Number value = (valueObject instanceof Number) ? (Number) valueObject
188: : null;
189:
190: Object isThere = null;
191: try {
192: isThere = localPieDataset.getValue(seriesComparable);
193: } catch (Exception ignored) {
194: }
195: if (isThere != null) {
196: double val = (value != null) ? value.doubleValue() : 0;
197: value = new Double(val
198: + ((Number) isThere).doubleValue());
199: }
200:
201: localPieDataset.setValue(seriesComparable, value);
202:
203: }
204: }
205:
206: public void groupFinished(ReportEvent reportEvent) {
207: logger.debug(Messages
208: .getString("PIESETCOLL.USER_DEBUG_GROUPS_FINISHED")); //$NON-NLS-1$
209: if (FunctionUtilities.isDefinedPrepareRunLevel(this ,
210: reportEvent) == false) {
211: // we do not modify the created dataset if this is not the function
212: // computation run. (FunctionLevel '0')
213: return;
214: }
215:
216: DefaultPieDataset localPieDataset = null;
217: if (getDataSourceValue() instanceof DefaultPieDataset) {
218: localPieDataset = (DefaultPieDataset) getDataSourceValue();
219: }
220:
221: if (isSummaryOnly()) {
222: if (FunctionUtilities.isDefinedGroup(getGroup(),
223: reportEvent)) {
224: // we can be sure that everything has been computed here. So
225: // grab the
226: // values and add them to the dataset.
227: final Object seriesObject = getDataRow().get(
228: getSeriesColumn());
229: final Comparable seriesComparable;
230: if (seriesObject instanceof Comparable) {
231: seriesComparable = (Comparable) seriesObject;
232: } else {
233: // ok, we need some better error management here. Its a
234: // prototype :)
235: seriesComparable = Messages
236: .getString("PIESETCOLL.USER_ERROR_SERIES_NOT_COMPARABLE"); //$NON-NLS-1$
237: }
238: final Object valueObject = getDataRow().get(
239: getValueColumn());
240:
241: Number value = (valueObject instanceof Number) ? (Number) valueObject
242: : null;
243: localPieDataset.setValue(seriesComparable, value);
244: }
245: }
246: }
247:
248: public AbstractDataset getNewDataset() {
249: return new DefaultPieDataset();
250: }
251:
252: /**
253: * Return a completly separated copy of this function. The copy no longer
254: * shares any changeable objects with the original function.
255: * Also from Thomas:
256: * Should retain data from the report definition, but clear calculated data.
257: *
258: * @return a copy of this function.
259: */
260: public Expression getInstance() {
261: final PieSetCollectorFunction fn = (PieSetCollectorFunction) super
262: .getInstance();
263: fn.pieDataset = null;
264: fn.results = new ArrayList();
265: fn.currentIndex = 0;
266: return fn;
267: }
268:
269: public Object getCacheKey() {
270: return this .pieDataset;
271: }
272:
273: public Object getDatasourceValue() {
274: return this.pieDataset;
275: }
276:
277: }
|