KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > data > CombinedDataset


1 /* ======================================
2  * JFreeChart : a free Java chart library
3  * ======================================
4  *
5  * Project Info: http://www.jfree.org/jfreechart/index.html
6  * Project Lead: David Gilbert (david.gilbert@object-refinery.com);
7  *
8  * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
9  *
10  * This library is free software; you can redistribute it and/or modify it under the terms
11  * of the GNU Lesser General Public License as published by the Free Software Foundation;
12  * either version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License along with this
19  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  * --------------------
23  * CombinedDataset.java
24  * --------------------
25  * (C) Copyright 2001-2003, by Bill Kelemen.
26  *
27  * Original Author: Bill Kelemen;
28  * Contributor(s): -;
29  *
30  * $Id: CombinedDataset.java,v 1.5 2003/07/25 12:31:09 mungady Exp $
31  *
32  * Changes
33  * -------
34  * 06-Dec-2001 : Version 1 (BK);
35  * 27-Dec-2001 : Fixed bug in getChildPosition method (BK);
36  * 29-Dec-2001 : Fixed bug in getChildPosition method with complex CombinePlot (BK);
37  * 05-Feb-2002 : Small addition to the interface HighLowDataset, as requested by Sylvain
38  * Vieujot (DG);
39  * 14-Feb-2002 : Added bug fix for IntervalXYDataset methods, submitted by Gyula Kun-Szabo (DG);
40  * 11-Jun-2002 : Updated for change in event constructor (DG);
41  * 04-Oct-2002 : Fixed errors reported by Checkstyle (DG);
42  *
43  */

44
45 package org.jfree.data;
46
47 import java.util.List JavaDoc;
48
49 /**
50  * This class can combine instances of {@link XYDataset}, {@link HighLowDataset} and
51  * {@link IntervalXYDataset} together exposing the union of all the series under one dataset.
52  *
53  * @author Bill Kelemen (bill@kelemen-usa.com)
54  */

55 public class CombinedDataset extends AbstractSeriesDataset
56                              implements XYDataset, HighLowDataset, IntervalXYDataset,
57                                         CombinationDataset {
58
59     /** Storage for the datasets we combine. */
60     private List JavaDoc datasetInfo = new java.util.ArrayList JavaDoc();
61
62     /**
63      * Default constructor for an empty combination.
64      */

65     public CombinedDataset() {
66     }
67
68     /**
69      * Creates a CombinedDataset initialized with an array of SeriesDatasets.
70      *
71      * @param data array of SeriesDataset that contains the SeriesDatasets to combine.
72      */

73     public CombinedDataset(SeriesDataset[] data) {
74         add(data);
75     }
76
77     /**
78      * Adds one SeriesDataset to the combination. Listeners are notified of the change.
79      *
80      * @param data the SeriesDataset to add.
81      */

82     public void add(SeriesDataset data) {
83
84         fastAdd(data);
85         DatasetChangeEvent event = new DatasetChangeEvent(this, this);
86         notifyListeners(event);
87
88     }
89
90     /**
91      * Adds an array of SeriesDataset's to the combination. Listeners are
92      * notified of the change.
93      *
94      * @param data array of SeriesDataset to add
95      */

96     public void add(SeriesDataset[] data) {
97
98         for (int i = 0; i < data.length; i++) {
99             fastAdd(data[i]);
100         }
101         DatasetChangeEvent event = new DatasetChangeEvent(this, this);
102         notifyListeners(event);
103
104     }
105
106     /**
107      * Adds one series from a SeriesDataset to the combination. Listeners are
108      * notified of the change.
109      *
110      * @param data the SeriesDataset where series is contained
111      * @param series series to add
112      */

113     public void add(SeriesDataset data, int series) {
114         add(new SubSeriesDataset(data, series));
115     }
116
117     /**
118      * Fast add of a SeriesDataset. Does not notify listeners of the change.
119      *
120      * @param data SeriesDataset to add
121      */

122     private void fastAdd(SeriesDataset data) {
123         for (int i = 0; i < data.getSeriesCount(); i++) {
124             datasetInfo.add(new DatasetInfo(data, i));
125         }
126     }
127
128     ///////////////////////////////////////////////////////////////////////////
129
// From SeriesDataset
130
///////////////////////////////////////////////////////////////////////////
131

132     /**
133      * Returns the number of series in the dataset.
134      *
135      * @return The number of series in the dataset.
136      */

137     public int getSeriesCount() {
138         return datasetInfo.size();
139     }
140
141     /**
142      * Returns the name of a series.
143      *
144      * @param series the series (zero-based index).
145      *
146      * @return the name of a series.
147      */

148     public String JavaDoc getSeriesName(int series) {
149         DatasetInfo di = getDatasetInfo(series);
150         return di.data.getSeriesName(di.series);
151     }
152
153     ///////////////////////////////////////////////////////////////////////////
154
// From XYDataset
155
///////////////////////////////////////////////////////////////////////////
156

157     /**
158      * Returns the X-value for the specified series and item.
159      * <P>
160      * Note: throws <code>ClassCastException</code> if the series is not from a {@link XYDataset}.
161      *
162      * @param series the index of the series of interest (zero-based).
163      * @param item the index of the item of interest (zero-based).
164      *
165      * @return the X-value for the specified series and item.
166      */

167     public Number JavaDoc getXValue(int series, int item) {
168         DatasetInfo di = getDatasetInfo(series);
169         return ((XYDataset) di.data).getXValue(di.series, item);
170     }
171
172     /**
173      * Returns the Y-value for the specified series and item.
174      * <P>
175      * Note: throws <code>ClassCastException</code> if the series is not from a {@link XYDataset}.
176      *
177      * @param series the index of the series of interest (zero-based).
178      * @param item the index of the item of interest (zero-based).
179      *
180      * @return the Y-value for the specified series and item.
181      */

182     public Number JavaDoc getYValue(int series, int item) {
183         DatasetInfo di = getDatasetInfo(series);
184         return ((XYDataset) di.data).getYValue(di.series, item);
185     }
186
187     /**
188      * Returns the number of items in a series.
189      * <P>
190      * Note: throws <code>ClassCastException</code> if the series is not from a {@link XYDataset}.
191      *
192      * @param series the index of the series of interest (zero-based).
193      *
194      * @return the number of items in a series.
195      */

196     public int getItemCount(int series) {
197         DatasetInfo di = getDatasetInfo(series);
198         return ((XYDataset) di.data).getItemCount(di.series);
199     }
200
201     ///////////////////////////////////////////////////////////////////////////
202
// From HighLowDataset
203
///////////////////////////////////////////////////////////////////////////
204

205     /**
206      * Returns the high-value for the specified series and item.
207      * <P>
208      * Note: throws <code>ClassCastException</code> if the series is not from a
209      * {@link HighLowDataset}.
210      *
211      * @param series the index of the series of interest (zero-based).
212      * @param item the index of the item of interest (zero-based).
213      *
214      * @return the high-value for the specified series and item.
215      */

216     public Number JavaDoc getHighValue(int series, int item) {
217         DatasetInfo di = getDatasetInfo(series);
218         return ((HighLowDataset) di.data).getHighValue(di.series, item);
219     }
220
221     /**
222      * Returns the low-value for the specified series and item.
223      * <P>
224      * Note: throws <code>ClassCastException</code> if the series is not from a
225      * {@link HighLowDataset}.
226      *
227      * @param series the index of the series of interest (zero-based).
228      * @param item the index of the item of interest (zero-based).
229      *
230      * @return the low-value for the specified series and item.
231      */

232     public Number JavaDoc getLowValue(int series, int item) {
233         DatasetInfo di = getDatasetInfo(series);
234         return ((HighLowDataset) di.data).getLowValue(di.series, item);
235     }
236
237     /**
238      * Returns the open-value for the specified series and item.
239      * <P>
240      * Note: throws <code>ClassCastException</code> if the series is not from a
241      * {@link HighLowDataset}.
242      *
243      * @param series the index of the series of interest (zero-based).
244      * @param item the index of the item of interest (zero-based).
245      *
246      * @return the open-value for the specified series and item.
247      */

248     public Number JavaDoc getOpenValue(int series, int item) {
249         DatasetInfo di = getDatasetInfo(series);
250         return ((HighLowDataset) di.data).getOpenValue(di.series, item);
251     }
252
253     /**
254      * Returns the close-value for the specified series and item.
255      * <P>
256      * Note: throws <code>ClassCastException</code> if the series is not from a
257      * {@link HighLowDataset}.
258      *
259      * @param series the index of the series of interest (zero-based).
260      * @param item the index of the item of interest (zero-based).
261      *
262      * @return the close-value for the specified series and item.
263      */

264     public Number JavaDoc getCloseValue(int series, int item) {
265         DatasetInfo di = getDatasetInfo(series);
266         return ((HighLowDataset) di.data).getCloseValue(di.series, item);
267     }
268
269     /**
270      * Returns the volume value for the specified series and item.
271      * <P>
272      * Note: throws <code>ClassCastException</code> if the series is not from a
273      * {@link HighLowDataset}.
274      *
275      * @param series the index of the series of interest (zero-based).
276      * @param item the index of the item of interest (zero-based).
277      *
278      * @return the volume value for the specified series and item.
279      */

280     public Number JavaDoc getVolumeValue(int series, int item) {
281         DatasetInfo di = getDatasetInfo(series);
282         return ((HighLowDataset) di.data).getVolumeValue(di.series, item);
283     }
284
285     ///////////////////////////////////////////////////////////////////////////
286
// From IntervalXYDataset
287
///////////////////////////////////////////////////////////////////////////
288

289     /**
290      * Returns the starting X value for the specified series and item.
291      *
292      * @param series the index of the series of interest (zero-based).
293      * @param item the index of the item of interest (zero-based).
294      *
295      * @return the starting X value for the specified series and item.
296      */

297     public Number JavaDoc getStartXValue(int series, int item) {
298         DatasetInfo di = getDatasetInfo(series);
299         if (di.data instanceof IntervalXYDataset) {
300             return ((IntervalXYDataset) di.data).getStartXValue(di.series, item);
301         }
302         else {
303             return getXValue(series, item);
304         }
305     }
306
307     /**
308      * Returns the ending X value for the specified series and item.
309      *
310      * @param series the index of the series of interest (zero-based).
311      * @param item the index of the item of interest (zero-based).
312      *
313      * @return the ending X value for the specified series and item.
314      */

315     public Number JavaDoc getEndXValue(int series, int item) {
316         DatasetInfo di = getDatasetInfo(series);
317         if (di.data instanceof IntervalXYDataset) {
318             return ((IntervalXYDataset) di.data).getEndXValue(di.series, item);
319         }
320         else {
321             return getXValue(series, item);
322         }
323     }
324
325     /**
326      * Returns the starting Y value for the specified series and item.
327      *
328      * @param series the index of the series of interest (zero-based).
329      * @param item the index of the item of interest (zero-based).
330      *
331      * @return the starting Y value for the specified series and item.
332      */

333     public Number JavaDoc getStartYValue(int series, int item) {
334         DatasetInfo di = getDatasetInfo(series);
335         if (di.data instanceof IntervalXYDataset) {
336             return ((IntervalXYDataset) di.data).getStartYValue(di.series, item);
337         }
338         else {
339             return getYValue(series, item);
340         }
341     }
342
343     /**
344      * Returns the ending Y value for the specified series and item.
345      *
346      * @param series the index of the series of interest (zero-based).
347      * @param item the index of the item of interest (zero-based).
348      *
349      * @return the ending Y value for the specified series and item.
350      */

351     public Number JavaDoc getEndYValue(int series, int item) {
352         DatasetInfo di = getDatasetInfo(series);
353         if (di.data instanceof IntervalXYDataset) {
354             return ((IntervalXYDataset) di.data).getEndYValue(di.series, item);
355         }
356         else {
357             return getYValue(series, item);
358         }
359     }
360
361     ///////////////////////////////////////////////////////////////////////////
362
// New methods from CombinationDataset
363
///////////////////////////////////////////////////////////////////////////
364

365     /**
366      * Returns the parent Dataset of this combination. If there is more than
367      * one parent, or a child is found that is not a CombinationDataset, then
368      * returns <code>null</code>.
369      *
370      * @return the parent Dataset of this combination or <code>null</code>.
371      */

372     public SeriesDataset getParent() {
373
374         SeriesDataset parent = null;
375         for (int i = 0; i < datasetInfo.size(); i++) {
376             SeriesDataset child = getDatasetInfo(i).data;
377             if (child instanceof CombinationDataset) {
378                 SeriesDataset childParent = ((CombinationDataset) child).getParent();
379                 if (parent == null) {
380                     parent = childParent;
381                 }
382                 else if (parent != childParent) {
383                     return null;
384                 }
385             }
386             else {
387                 return null;
388             }
389         }
390         return parent;
391
392     }
393
394     /**
395      * Returns a map or indirect indexing form our series into parent's series.
396      * Prior to calling this method, the client should check getParent() to make
397      * sure the CombinationDataset uses the same parent. If not, the map
398      * returned by this method will be invalid or null.
399      *
400      * @return a map or indirect indexing form our series into parent's series.
401      *
402      * @see #getParent()
403      */

404     public int[] getMap() {
405
406         int[] map = null;
407         for (int i = 0; i < datasetInfo.size(); i++) {
408             SeriesDataset child = getDatasetInfo(i).data;
409             if (child instanceof CombinationDataset) {
410                 int[] childMap = ((CombinationDataset) child).getMap();
411                 if (childMap == null) {
412                     return null;
413                 }
414                 map = joinMap(map, childMap);
415             }
416             else {
417                 return null;
418             }
419         }
420         return map;
421     }
422
423     ///////////////////////////////////////////////////////////////////////////
424
// New Methods
425
///////////////////////////////////////////////////////////////////////////
426

427     /**
428      * Returns the child position.
429      *
430      * @param child the child dataset.
431      *
432      * @return the position.
433      */

434     public int getChildPosition(Dataset child) {
435
436         int n = 0;
437         for (int i = 0; i < datasetInfo.size(); i++) {
438             SeriesDataset childDataset = getDatasetInfo(i).data;
439             if (childDataset instanceof CombinedDataset) {
440                 int m = ((CombinedDataset) childDataset).getChildPosition(child);
441                 if (m >= 0) {
442                     return n + m;
443                 }
444                 n++;
445             }
446             else {
447                 if (child == childDataset) {
448                     return n;
449                 }
450                 n++;
451             }
452         }
453         return -1;
454     }
455
456     ///////////////////////////////////////////////////////////////////////////
457
// Private
458
///////////////////////////////////////////////////////////////////////////
459

460     /**
461      * Returns the DatasetInfo object associated with the series.
462      *
463      * @param series the index of the series.
464      *
465      * @return the DatasetInfo object associated with the series.
466      */

467     private DatasetInfo getDatasetInfo(int series) {
468         return (DatasetInfo) datasetInfo.get(series);
469     }
470
471     /**
472      * Joins two map arrays (int[]) together.
473      *
474      * @param a the first array.
475      * @param b the second array.
476      *
477      * @return a copy of { a[], b[] }.
478      */

479     private int[] joinMap(int[] a, int[] b) {
480         if (a == null) {
481             return b;
482         }
483         if (b == null) {
484             return a;
485         }
486         int[] result = new int[a.length + b.length];
487         System.arraycopy(a, 0, result, 0, a.length);
488         System.arraycopy(b, 0, result, a.length, b.length);
489         return result;
490     }
491
492     /**
493      * Private class to store as pairs (SeriesDataset, series) for all combined series.
494      *
495      * @see add()
496      */

497     private class DatasetInfo {
498
499         /** The dataset. */
500         private SeriesDataset data;
501
502         /** The series. */
503         private int series;
504
505         /**
506          * Creates a new dataset info record.
507          *
508          * @param data the dataset.
509          * @param series the series.
510          */

511         DatasetInfo(SeriesDataset data, int series) {
512             this.data = data;
513             this.series = series;
514         }
515     }
516
517 }
518
Popular Tags