KickJava   Java API By Example, From Geeks To Geeks.

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


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  * DatasetUtilities.java
24  * ---------------------
25  * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
26  *
27  * Original Author: David Gilbert (for Object Refinery Limited);
28  * Contributor(s): Andrzej Porebski (bug fix);
29  * Jonathan Nash (bug fix);
30  * Richard Atkinson;
31  *
32  * $Id: DatasetUtilities.java,v 1.16 2003/10/21 10:51:40 mungady Exp $
33  *
34  * Changes (from 18-Sep-2001)
35  * --------------------------
36  * 18-Sep-2001 : Added standard header and fixed DOS encoding problem (DG);
37  * 22-Oct-2001 : Renamed DataSource.java --> Dataset.java etc. (DG);
38  * 15-Nov-2001 : Moved to package com.jrefinery.data.* in the JCommon class library (DG);
39  * Changed to handle null values from datasets (DG);
40  * Bug fix (thanks to Andrzej Porebski) - initial value now set to positive or
41  * negative infinity when iterating (DG);
42  * 22-Nov-2001 : Datasets with containing no data now return null for min and max calculations (DG);
43  * 13-Dec-2001 : Extended to handle HighLowDataset and IntervalXYDataset (DG);
44  * 15-Feb-2002 : Added getMinimumStackedRangeValue() and getMaximumStackedRangeValue() (DG);
45  * 28-Feb-2002 : Renamed Datasets.java --> DatasetUtilities.java (DG);
46  * 18-Mar-2002 : Fixed bug in min/max domain calculation for datasets that implement the
47  * CategoryDataset interface AND the XYDataset interface at the same time. Thanks
48  * to Jonathan Nash for the fix (DG);
49  * 23-Apr-2002 : Added getDomainExtent() and getRangeExtent() methods (DG);
50  * 13-Jun-2002 : Modified range measurements to handle IntervalCategoryDataset (DG);
51  * 12-Jul-2002 : Method name change in DomainInfo interface (DG);
52  * 30-Jul-2002 : Added pie dataset summation method (DG);
53  * 01-Oct-2002 : Added a method for constructing an XYDataset from a Function2D instance (DG);
54  * 24-Oct-2002 : Amendments required following changes to the CategoryDataset interface (DG);
55  * 18-Nov-2002 : Changed CategoryDataset to TableDataset (DG);
56  * 04-Mar-2003 : Added isEmpty(XYDataset) method (DG);
57  * 05-Mar-2003 : Added a method for creating a CategoryDataset from a KeyedValues instance (DG);
58  * 15-May-2003 : Renamed isEmpty --> isEmptyOrNull (DG);
59  * 25-Jun-2003 : Added limitPieDataset methods (RA);
60  * 26-Jun-2003 : Modified getDomainExtent(...) method to accept null datasets (DG);
61  * 27-Jul-2003 : Added getStackedRangeExtent(TableXYDataset data) (RA);
62  * 18-Aug-2003 : getStackedRangeExtent(TableXYDataset data) now handles null values (RA);
63  * 02-Sep-2003 : Added method to check for null or empty PieDataset (DG);
64  * 18-Sep-2003 : Fix for bug 803660 (getMaximumRangeValue for CategoryDataset) (DG);
65  * 20-Oct-2003 : Added getCumulativeRangeExtent(...) method (DG);
66  *
67  */

68
69 package org.jfree.data;
70
71 import java.util.ArrayList JavaDoc;
72 import java.util.Iterator JavaDoc;
73 import java.util.List JavaDoc;
74
75 /**
76  * A collection of useful static methods relating to datasets.
77  *
78  * @author David Gilbert
79  */

80 public class DatasetUtilities {
81
82     /**
83      * To prevent instantiation.
84      */

85     protected DatasetUtilities() {
86     }
87
88     /**
89      * Constructs an array of <code>Number</code> objects from an array of <code>double</code>
90      * primitives.
91      *
92      * @param data the data.
93      *
94      * @return an array of <code>Double</code>.
95      */

96     public static Number JavaDoc[] createNumberArray(double[] data) {
97
98         Number JavaDoc[] result = new Number JavaDoc[data.length];
99
100         for (int i = 0; i < data.length; i++) {
101             result[i] = new Double JavaDoc(data[i]);
102         }
103
104         return result;
105
106     }
107
108     /**
109      * Constructs an array of arrays of <code>Number</code> objects from a corresponding
110      * structure containing <code>double</code> primitives.
111      *
112      * @param data the data.
113      *
114      * @return an array of <code>Double</code>.
115      */

116     public static Number JavaDoc[][] createNumberArray2D(double[][] data) {
117
118         int l1 = data.length;
119         int l2 = data[0].length;
120
121         Number JavaDoc[][] result = new Number JavaDoc[l1][l2];
122
123         for (int i = 0; i < l1; i++) {
124             result[i] = createNumberArray(data[i]);
125         }
126
127         return result;
128
129     }
130
131     /**
132      * Returns the range of values in the domain for the dataset.
133      * <P>
134      * If the supplied dataset is <code>null</code>, the range returned is <code>null</code>.
135      *
136      * @param data the dataset (<code>null</code> permitted).
137      *
138      * @return The range of values (possibly <code>null</code>).
139      */

140     public static Range getDomainExtent(Dataset data) {
141
142         // check parameters...
143
if (data == null) {
144             return null;
145         }
146
147         if ((data instanceof CategoryDataset) && !(data instanceof XYDataset)) {
148             throw new IllegalArgumentException JavaDoc("Datasets.getDomainExtent(...): "
149                 + "CategoryDataset does not have a numerical domain.");
150         }
151
152         // work out the minimum value...
153
if (data instanceof DomainInfo) {
154             DomainInfo info = (DomainInfo) data;
155             return info.getDomainRange();
156         }
157
158         // hasn't implemented DomainInfo, so iterate...
159
else if (data instanceof XYDataset) {
160             double minimum = Double.POSITIVE_INFINITY;
161             double maximum = Double.NEGATIVE_INFINITY;
162             XYDataset xyData = (XYDataset) data;
163             int seriesCount = xyData.getSeriesCount();
164             for (int series = 0; series < seriesCount; series++) {
165                 int itemCount = xyData.getItemCount(series);
166                 for (int item = 0; item < itemCount; item++) {
167
168                     Number JavaDoc lvalue = null;
169                     Number JavaDoc uvalue = null;
170                     if (data instanceof IntervalXYDataset) {
171                         IntervalXYDataset intervalXYData = (IntervalXYDataset) data;
172                         lvalue = intervalXYData.getStartXValue(series, item);
173                         uvalue = intervalXYData.getEndXValue(series, item);
174                     }
175                     else {
176                         lvalue = xyData.getXValue(series, item);
177                         uvalue = lvalue;
178                     }
179                     if (lvalue != null) {
180                         minimum = Math.min(minimum, lvalue.doubleValue());
181                     }
182                     if (uvalue != null) {
183                         maximum = Math.max(maximum, uvalue.doubleValue());
184                     }
185
186                 }
187             }
188             if (minimum == Double.POSITIVE_INFINITY) {
189                 return null;
190             }
191             else {
192                 return new Range(minimum, maximum);
193             }
194         }
195         else {
196             return null; // unrecognised dataset...how should this be handled?
197
}
198
199     }
200
201     /**
202      * Returns the range of values in the range for the dataset. This method
203      * is the partner for the getDomainExtent method.
204      *
205      * @param data the dataset.
206      *
207      * @return the range of values in the range for the dataset.
208      */

209     public static Range getRangeExtent(Dataset data) {
210
211         // check parameters...
212
if (data == null) {
213             return null;
214         }
215
216         // work out the minimum value...
217
if (data instanceof RangeInfo) {
218             RangeInfo info = (RangeInfo) data;
219             return info.getValueRange();
220         }
221
222         // hasn't implemented RangeInfo, so we'll have to iterate...
223
else if (data instanceof CategoryDataset) {
224
225             CategoryDataset tableData = (CategoryDataset) data;
226             double minimum = Double.POSITIVE_INFINITY;
227             double maximum = Double.NEGATIVE_INFINITY;
228             int rowCount = tableData.getRowCount();
229             int columnCount = tableData.getColumnCount();
230             for (int row = 0; row < rowCount; row++) {
231                 for (int column = 0; column < columnCount; column++) {
232                     Number JavaDoc lvalue = null;
233                     Number JavaDoc uvalue = null;
234                     if (data instanceof IntervalCategoryDataset) {
235                         IntervalCategoryDataset icd = (IntervalCategoryDataset) data;
236                         lvalue = icd.getStartValue(row, column);
237                         uvalue = icd.getEndValue(row, column);
238                     }
239                     else {
240                         lvalue = tableData.getValue(row, column);
241                         uvalue = lvalue;
242                     }
243                     if (lvalue != null) {
244                         minimum = Math.min(minimum, lvalue.doubleValue());
245                     }
246                     if (uvalue != null) {
247                         maximum = Math.max(maximum, uvalue.doubleValue());
248                     }
249                 }
250             }
251             if (minimum == Double.POSITIVE_INFINITY) {
252                 return null;
253             }
254             else {
255                 return new Range(minimum, maximum);
256             }
257
258         }
259         else if (data instanceof XYDataset) {
260
261             // hasn't implemented RangeInfo, so we'll have to iterate...
262
XYDataset xyData = (XYDataset) data;
263             double minimum = Double.POSITIVE_INFINITY;
264             double maximum = Double.NEGATIVE_INFINITY;
265             int seriesCount = xyData.getSeriesCount();
266             for (int series = 0; series < seriesCount; series++) {
267                 int itemCount = xyData.getItemCount(series);
268                 for (int item = 0; item < itemCount; item++) {
269
270                     Number JavaDoc lvalue = null;
271                     Number JavaDoc uvalue = null;
272                     if (data instanceof IntervalXYDataset) {
273                         IntervalXYDataset intervalXYData = (IntervalXYDataset) data;
274                         lvalue = intervalXYData.getStartYValue(series, item);
275                         uvalue = intervalXYData.getEndYValue(series, item);
276                     }
277                     else if (data instanceof HighLowDataset) {
278                         HighLowDataset highLowData = (HighLowDataset) data;
279                         lvalue = highLowData.getLowValue(series, item);
280                         uvalue = highLowData.getHighValue(series, item);
281                     }
282                     else {
283                         lvalue = xyData.getYValue(series, item);
284                         uvalue = lvalue;
285                     }
286                     if (lvalue != null) {
287                         minimum = Math.min(minimum, lvalue.doubleValue());
288                     }
289                     if (uvalue != null) {
290                         maximum = Math.max(maximum, uvalue.doubleValue());
291                     }
292
293                 }
294             }
295             if (minimum == Double.POSITIVE_INFINITY) {
296                 return null;
297             }
298             else {
299                 return new Range(minimum, maximum);
300             }
301
302         }
303         else {
304             return null;
305         }
306
307     }
308
309     /**
310      * Returns the minimum domain value for the specified dataset.
311      * <P>
312      * This is easy if the dataset implements the DomainInfo interface (a good
313      * idea if there is an efficient way to determine the minimum value).
314      * Otherwise, it involves iterating over the entire data-set.
315      * <p>
316      * Returns null if all the data values in the dataset are null.
317      *
318      * @param data the dataset.
319      *
320      * @return the minimum domain value in the dataset (or null).
321      */

322     public static Number JavaDoc getMinimumDomainValue(Dataset data) {
323
324         // check parameters...
325
if (data == null) {
326             throw new IllegalArgumentException JavaDoc(
327                 "DatasetUtilities.getMinimumDomainValue: null dataset not allowed.");
328         }
329
330         if ((data instanceof CategoryDataset) && !(data instanceof XYDataset)) {
331             throw new IllegalArgumentException JavaDoc("DatasetUtilities.getMinimumDomainValue(...): "
332                 + "TableDataset does not have numerical domain.");
333         }
334
335         // work out the minimum value...
336
if (data instanceof DomainInfo) {
337             DomainInfo info = (DomainInfo) data;
338             return info.getMinimumDomainValue();
339         }
340
341         // hasn't implemented DomainInfo, so iterate...
342
else if (data instanceof XYDataset) {
343             double minimum = Double.POSITIVE_INFINITY;
344             XYDataset xyData = (XYDataset) data;
345             int seriesCount = xyData.getSeriesCount();
346             for (int series = 0; series < seriesCount; series++) {
347                 int itemCount = xyData.getItemCount(series);
348                 for (int item = 0; item < itemCount; item++) {
349
350                     Number JavaDoc value = null;
351                     if (data instanceof IntervalXYDataset) {
352                         IntervalXYDataset intervalXYData = (IntervalXYDataset) data;
353                         value = intervalXYData.getStartXValue(series, item);
354                     }
355                     else {
356                         value = xyData.getXValue(series, item);
357                     }
358                     if (value != null) {
359                         minimum = Math.min(minimum, value.doubleValue());
360                     }
361
362                 }
363             }
364             if (minimum == Double.POSITIVE_INFINITY) {
365                 return null;
366             }
367             else {
368                 return new Double JavaDoc(minimum);
369             }
370         }
371
372         else {
373             return null; // unrecognised dataset...how should this be handled?
374
}
375
376     }
377
378     /**
379      * Returns the maximum domain value for the specified dataset.
380      * <P>
381      * This is easy if the dataset implements the DomainInfo interface (a good
382      * idea if there is an efficient way to determine the maximum value).
383      * Otherwise, it involves iterating over the entire data-set.
384      * <p>
385      * Returns null if all the data values in the dataset are null.
386      *
387      * @param data the dataset.
388      *
389      * @return the maximum domain value in the dataset (or null).
390      */

391     public static Number JavaDoc getMaximumDomainValue(Dataset data) {
392
393         // check parameters...
394
if (data == null) {
395             throw new IllegalArgumentException JavaDoc(
396                 "Datasets.getMaximumDomainValue: null dataset not allowed.");
397         }
398
399         if ((data instanceof CategoryDataset) && !(data instanceof XYDataset)) {
400             throw new IllegalArgumentException JavaDoc("Datasets.getMaximumDomainValue(...): "
401                 + "CategoryDataset does not have numerical domain.");
402         }
403
404         // work out the maximum value...
405
if (data instanceof DomainInfo) {
406             DomainInfo info = (DomainInfo) data;
407             return info.getMaximumDomainValue();
408         }
409
410         // hasn't implemented DomainInfo, so iterate...
411
else if (data instanceof XYDataset) {
412             XYDataset xyData = (XYDataset) data;
413             double maximum = Double.NEGATIVE_INFINITY;
414             int seriesCount = xyData.getSeriesCount();
415             for (int series = 0; series < seriesCount; series++) {
416                 int itemCount = xyData.getItemCount(series);
417                 for (int item = 0; item < itemCount; item++) {
418
419                     Number JavaDoc value = null;
420                     if (data instanceof IntervalXYDataset) {
421                         IntervalXYDataset intervalXYData = (IntervalXYDataset) data;
422                         value = intervalXYData.getEndXValue(series, item);
423                     }
424                     else {
425                         value = xyData.getXValue(series, item);
426                     }
427                     if (value != null) {
428                         maximum = Math.max(maximum, value.doubleValue());
429                     }
430                 }
431             }
432             if (maximum == Double.NEGATIVE_INFINITY) {
433                 return null;
434             }
435             else {
436                 return new Double JavaDoc(maximum);
437             }
438
439         }
440         else {
441             return null; // unrecognised dataset...how should this be handled?
442
}
443
444     }
445
446     /**
447      * Returns the minimum range value for the specified dataset.
448      * <P>
449      * This is easy if the dataset implements the RangeInfo interface (a good
450      * idea if there is an efficient way to determine the minimum value).
451      * Otherwise, it involves iterating over the entire data-set.
452      * <p>
453      * Returns null if all the data values in the dataset are null.
454      *
455      * @param data the dataset.
456      *
457      * @return the minimum range value in the dataset (or null).
458      */

459     public static Number JavaDoc getMinimumRangeValue(Dataset data) {
460
461         // check parameters...
462
if (data == null) {
463             throw new IllegalArgumentException JavaDoc(
464                 "Datasets.getMinimumRangeValue: null dataset not allowed.");
465         }
466
467         // work out the minimum value...
468
if (data instanceof RangeInfo) {
469             RangeInfo info = (RangeInfo) data;
470             return info.getMinimumRangeValue();
471         }
472
473         // hasn't implemented RangeInfo, so we'll have to iterate...
474
else if (data instanceof CategoryDataset) {
475
476             CategoryDataset categoryData = (CategoryDataset) data;
477             double minimum = Double.POSITIVE_INFINITY;
478             int seriesCount = categoryData.getRowCount();
479             int itemCount = categoryData.getColumnCount();
480             for (int series = 0; series < seriesCount; series++) {
481                 for (int item = 0; item < itemCount; item++) {
482                     Number JavaDoc value = null;
483                     if (data instanceof IntervalCategoryDataset) {
484                         IntervalCategoryDataset icd = (IntervalCategoryDataset) data;
485                         value = icd.getStartValue(series, item);
486                     }
487                     else {
488                         value = categoryData.getValue(series, item);
489                     }
490                     if (value != null) {
491                         minimum = Math.min(minimum, value.doubleValue());
492                     }
493                 }
494             }
495             if (minimum == Double.POSITIVE_INFINITY) {
496                 return null;
497             }
498             else {
499                 return new Double JavaDoc(minimum);
500             }
501
502         }
503         else if (data instanceof XYDataset) {
504
505             // hasn't implemented RangeInfo, so we'll have to iterate...
506
XYDataset xyData = (XYDataset) data;
507             double minimum = Double.POSITIVE_INFINITY;
508             int seriesCount = xyData.getSeriesCount();
509             for (int series = 0; series < seriesCount; series++) {
510                 int itemCount = xyData.getItemCount(series);
511                 for (int item = 0; item < itemCount; item++) {
512
513                     Number JavaDoc value = null;
514                     if (data instanceof IntervalXYDataset) {
515                         IntervalXYDataset intervalXYData = (IntervalXYDataset) data;
516                         value = intervalXYData.getStartYValue(series, item);
517                     }
518                     else if (data instanceof HighLowDataset) {
519                         HighLowDataset highLowData = (HighLowDataset) data;
520                         value = highLowData.getLowValue(series, item);
521                     }
522                     else {
523                         value = xyData.getYValue(series, item);
524                     }
525                     if (value != null) {
526                         minimum = Math.min(minimum, value.doubleValue());
527                     }
528
529                 }
530             }
531             if (minimum == Double.POSITIVE_INFINITY) {
532                 return null;
533             }
534             else {
535                 return new Double JavaDoc(minimum);
536             }
537
538         }
539         else {
540             return null;
541         }
542
543     }
544
545     /**
546      * Returns the maximum range value for the specified dataset.
547      * <P>
548      * This is easy if the dataset implements the RangeInfo interface (a good
549      * idea if there is an efficient way to determine the maximum value).
550      * Otherwise, it involves iterating over the entire data-set.
551      * <p>
552      * Returns null if all the data values are null.
553      *
554      * @param data the dataset.
555      *
556      * @return the maximum range value in the dataset (or null).
557      */

558     public static Number JavaDoc getMaximumRangeValue(Dataset data) {
559
560         // check parameters...
561
if (data == null) {
562             throw new IllegalArgumentException JavaDoc(
563                 "Datasets.getMinimumRangeValue: null dataset not allowed.");
564         }
565
566         // work out the minimum value...
567
if (data instanceof RangeInfo) {
568             RangeInfo info = (RangeInfo) data;
569             return info.getMaximumRangeValue();
570         }
571
572         // hasn't implemented RangeInfo, so we'll have to iterate...
573
else if (data instanceof CategoryDataset) {
574
575             CategoryDataset categoryData = (CategoryDataset) data;
576             double maximum = Double.NEGATIVE_INFINITY;
577             int seriesCount = categoryData.getRowCount();
578             int itemCount = categoryData.getColumnCount();
579             for (int series = 0; series < seriesCount; series++) {
580                 for (int item = 0; item < itemCount; item++) {
581                     Number JavaDoc value = null;
582                     if (data instanceof IntervalCategoryDataset) {
583                         IntervalCategoryDataset icd = (IntervalCategoryDataset) data;
584                         value = icd.getEndValue(series, item);
585                     }
586                     else {
587                         value = categoryData.getValue(series, item);
588                     }
589                     if (value != null) {
590                         maximum = Math.max(maximum, value.doubleValue());
591                     }
592                 }
593             }
594             if (maximum == Double.NEGATIVE_INFINITY) {
595                 return null;
596             }
597             else {
598                 return new Double JavaDoc(maximum);
599             }
600
601         }
602         else if (data instanceof XYDataset) {
603
604             XYDataset xyData = (XYDataset) data;
605             double maximum = Double.NEGATIVE_INFINITY;
606             int seriesCount = xyData.getSeriesCount();
607             for (int series = 0; series < seriesCount; series++) {
608                 int itemCount = xyData.getItemCount(series);
609                 for (int item = 0; item < itemCount; item++) {
610                     Number JavaDoc value = null;
611                     if (data instanceof IntervalXYDataset) {
612                         IntervalXYDataset intervalXYData = (IntervalXYDataset) data;
613                         value = intervalXYData.getEndYValue(series, item);
614                     }
615                     else if (data instanceof HighLowDataset) {
616                         HighLowDataset highLowData = (HighLowDataset) data;
617                         value = highLowData.getHighValue(series, item);
618                     }
619                     else {
620                         value = xyData.getYValue(series, item);
621                     }
622                     if (value != null) {
623                         maximum = Math.max(maximum, value.doubleValue());
624                     }
625                 }
626             }
627             if (maximum == Double.NEGATIVE_INFINITY) {
628                 return null;
629             }
630             else {
631                 return new Double JavaDoc(maximum);
632             }
633
634         }
635         else {
636             return null;
637         }
638
639     }
640
641     /**
642      * Creates a pie dataset from a table dataset by taking all the values
643      * for a single row.
644      *
645      * @param data the data.
646      * @param rowKey the row key.
647      *
648      * @return a pie dataset.
649      */

650     public static PieDataset createPieDatasetForRow(CategoryDataset data, Comparable JavaDoc rowKey) {
651
652         int row = data.getRowIndex(rowKey);
653         return createPieDatasetForRow(data, row);
654
655     }
656
657     /**
658      * Creates a pie dataset from a table dataset by taking all the values
659      * for a single row.
660      *
661      * @param data the data.
662      * @param row the row (zero-based index).
663      *
664      * @return a pie dataset.
665      */

666     public static PieDataset createPieDatasetForRow(CategoryDataset data, int row) {
667
668         DefaultPieDataset result = new DefaultPieDataset();
669         int columnCount = data.getColumnCount();
670         for (int current = 0; current < columnCount; current++) {
671             Comparable JavaDoc columnKey = data.getColumnKey(current);
672             result.setValue(columnKey, data.getValue(row, current));
673         }
674         return result;
675
676     }
677
678     /**
679      * Creates a pie dataset from a table dataset by taking all the values
680      * for a single column.
681      *
682      * @param data the data.
683      * @param columnKey the column key.
684      *
685      * @return a pie dataset.
686      */

687     public static PieDataset createPieDatasetForColumn(CategoryDataset data,
688                                                        Comparable JavaDoc columnKey) {
689
690         int column = data.getColumnIndex(columnKey);
691         return createPieDatasetForColumn(data, column);
692
693     }
694
695     /**
696      * Creates a pie dataset from a table dataset by taking all the values
697      * for a single column.
698      *
699      * @param data the data.
700      * @param column the column (zero-based index).
701      *
702      * @return a pie dataset.
703      */

704     public static PieDataset createPieDatasetForColumn(CategoryDataset data, int column) {
705
706         DefaultPieDataset result = new DefaultPieDataset();
707         int rowCount = data.getRowCount();
708         for (int i = 0; i < rowCount; i++) {
709             Comparable JavaDoc rowKey = data.getRowKey(i);
710             result.setValue(rowKey, data.getValue(i, column));
711         }
712         return result;
713
714     }
715
716     /**
717      * Calculates the total of all the values in a {@link PieDataset}.
718      *
719      * @param data the dataset.
720      *
721      * @return the total.
722      */

723     public static double getPieDatasetTotal(PieDataset data) {
724
725         // get a list of categories...
726
List JavaDoc categories = data.getKeys();
727
728         // compute the total value of the data series skipping over the negative values
729
double totalValue = 0;
730         Iterator JavaDoc iterator = categories.iterator();
731         while (iterator.hasNext()) {
732             Comparable JavaDoc current = (Comparable JavaDoc) iterator.next();
733             if (current != null) {
734                 Number JavaDoc value = data.getValue(current);
735                 double v = 0.0;
736                 if (value != null) {
737                     v = value.doubleValue();
738                 }
739                 if (v > 0) {
740                     totalValue = totalValue + v;
741                 }
742             }
743         }
744         return totalValue;
745     }
746
747     /**
748      * Returns the minimum and maximum values for the dataset's range (as in domain/range),
749      * assuming that the series in one category are stacked.
750      *
751      * @param data the dataset.
752      *
753      * @return the value range.
754      */

755     public static Range getStackedRangeExtent(CategoryDataset data) {
756
757         Range result = null;
758
759         if (data != null) {
760
761             double minimum = 0.0;
762             double maximum = 0.0;
763
764             int categoryCount = data.getColumnCount();
765             for (int item = 0; item < categoryCount; item++) {
766                 double positive = 0.0;
767                 double negative = 0.0;
768                 int seriesCount = data.getRowCount();
769                 for (int series = 0; series < seriesCount; series++) {
770                     Number JavaDoc number = data.getValue(series, item);
771                     if (number != null) {
772                         double value = number.doubleValue();
773                         if (value > 0.0) {
774                             positive = positive + value;
775                         }
776                         if (value < 0.0) {
777                             negative = negative + value; // '+', remember value is negative
778
}
779                     }
780                 }
781                 minimum = Math.min(minimum, negative);
782                 maximum = Math.max(maximum, positive);
783
784             }
785
786             result = new Range(minimum, maximum);
787
788         }
789
790         return result;
791
792     }
793
794     /**
795      * Returns the minimum value in the dataset range, assuming that values in
796      * each category are "stacked".
797      *
798      * @param data the dataset.
799      *
800      * @return the minimum value.
801      */

802     public static Number JavaDoc getMinimumStackedRangeValue(CategoryDataset data) {
803
804         Number JavaDoc result = null;
805
806         if (data != null) {
807
808             double minimum = 0.0;
809
810             int categoryCount = data.getRowCount();
811             for (int item = 0; item < categoryCount; item++) {
812                 double total = 0.0;
813
814                 int seriesCount = data.getColumnCount();
815                 for (int series = 0; series < seriesCount; series++) {
816                     Number JavaDoc number = data.getValue(series, item);
817                     if (number != null) {
818                         double value = number.doubleValue();
819                         if (value < 0.0) {
820                             total = total + value; // '+', remember value is negative
821
}
822                     }
823                 }
824                 minimum = Math.min(minimum, total);
825
826             }
827
828             result = new Double JavaDoc(minimum);
829
830         }
831
832         return result;
833
834     }
835
836     /**
837      * Returns the maximum value in the dataset range, assuming that values in
838      * each category are "stacked".
839      *
840      * @param data the dataset.
841      *
842      * @return the maximum value.
843      */

844     public static Number JavaDoc getMaximumStackedRangeValue(CategoryDataset data) {
845
846         Number JavaDoc result = null;
847
848         if (data != null) {
849
850             double maximum = 0.0;
851
852             int categoryCount = data.getRowCount();
853             for (int item = 0; item < categoryCount; item++) {
854                 double total = 0.0;
855
856                 int seriesCount = data.getColumnCount();
857                 for (int series = 0; series < seriesCount; series++) {
858                     Number JavaDoc number = data.getValue(series, item);
859                     if (number != null) {
860                         double value = number.doubleValue();
861                         if (value > 0.0) {
862                             total = total + value;
863                         }
864                     }
865                 }
866                 maximum = Math.max(maximum, total);
867
868             }
869
870             result = new Double JavaDoc(maximum);
871
872         }
873
874         return result;
875
876     }
877
878     /**
879      * Creates an {@link XYDataset} by sampling the specified function over a fixed range.
880      *
881      * @param f the function.
882      * @param start the start value for the range.
883      * @param end the end value for the range.
884      * @param samples the number of samples (must be > 1).
885      * @param seriesName the name to give the resulting series.
886      *
887      * @return the dataset.
888      */

889     public static XYDataset sampleFunction2D(Function2D f,
890                                              double start, double end, int samples,
891                                              String JavaDoc seriesName) {
892
893         if (start >= end) {
894             throw new IllegalArgumentException JavaDoc("DatasetUtilities.createXYDataset(...): "
895                 + "start must be before end.");
896         }
897
898         if (samples < 2) {
899             throw new IllegalArgumentException JavaDoc("DatasetUtilities.createXYDataset(...): "
900                 + "samples must be at least 2.");
901         }
902
903         XYSeries series = new XYSeries(seriesName);
904
905         double step = (end - start) / samples;
906         for (int i = 0; i <= samples; i++) {
907             double x = start + (step * i);
908             series.add(x, f.getValue(x));
909         }
910
911         XYSeriesCollection collection = new XYSeriesCollection(series);
912         return collection;
913
914     }
915
916     /**
917      * Creates a {@link CategoryDataset} that contains a copy of the data in an array
918      * (instances of <code>Double</code> are created to represent the data items).
919      * <p>
920      * Row and column keys are created by appending 0, 1, 2, ... to the supplied prefixes.
921      *
922      * @param rowKeyPrefix the row key prefix.
923      * @param columnKeyPrefix the column key prefix.
924      * @param data the data.
925      *
926      * @return the dataset.
927      */

928     public static CategoryDataset createCategoryDataset(String JavaDoc rowKeyPrefix,
929                                                         String JavaDoc columnKeyPrefix,
930                                                         double[][] data) {
931
932         DefaultCategoryDataset result = new DefaultCategoryDataset();
933         for (int r = 0; r < data.length; r++) {
934             String JavaDoc rowKey = rowKeyPrefix + (r + 1);
935             for (int c = 0; c < data[r].length; c++) {
936                 String JavaDoc columnKey = columnKeyPrefix + (c + 1);
937                 result.addValue(new Double JavaDoc(data[r][c]), rowKey, columnKey);
938             }
939         }
940         return result;
941
942     }
943
944     /**
945      * Creates a {@link CategoryDataset} that contains a copy of the data in an array.
946      * <p>
947      * Row and column keys are created by appending 0, 1, 2, ... to the supplied prefixes.
948      *
949      * @param rowKeyPrefix the row key prefix.
950      * @param columnKeyPrefix the column key prefix.
951      * @param data the data.
952      *
953      * @return the dataset.
954      */

955     public static CategoryDataset createCategoryDataset(String JavaDoc rowKeyPrefix,
956                                                         String JavaDoc columnKeyPrefix,
957                                                         Number JavaDoc[][] data) {
958
959         DefaultCategoryDataset result = new DefaultCategoryDataset();
960         for (int r = 0; r < data.length; r++) {
961             String JavaDoc rowKey = rowKeyPrefix + (r + 1);
962             for (int c = 0; c < data[r].length; c++) {
963                 String JavaDoc columnKey = columnKeyPrefix + (c + 1);
964                 result.addValue(data[r][c], rowKey, columnKey);
965             }
966         }
967         return result;
968
969     }
970
971     /**
972      * Creates a {@link CategoryDataset} that contains a copy of the data in an array
973      * (instances of <code>Double</code> are created to represent the data items).
974      * <p>
975      * Row and column keys are taken from the supplied arrays.
976      *
977      * @param rowKeys the row keys.
978      * @param columnKeys the column keys.
979      * @param data the data.
980      *
981      * @return The dataset.
982      */

983     public static CategoryDataset createCategoryDataset(String JavaDoc[] rowKeys,
984                                                         String JavaDoc[] columnKeys,
985                                                         double[][] data) {
986
987         DefaultCategoryDataset result = new DefaultCategoryDataset();
988         for (int r = 0; r < data.length; r++) {
989             String JavaDoc rowKey = rowKeys[r];
990             for (int c = 0; c < data[r].length; c++) {
991                 String JavaDoc columnKey = columnKeys[c];
992                 result.addValue(new Double JavaDoc(data[r][c]), rowKey, columnKey);
993             }
994         }
995         return result;
996
997     }
998
999     /**
1000     * Creates a {@link CategoryDataset} by copying the data from the supplied {@link KeyedValues}
1001     * instance.
1002     *
1003     * @param rowKey the row key.
1004     * @param rowData the row data.
1005     *
1006     * @return A dataset.
1007     */

1008    public static CategoryDataset createCategoryDataset(String JavaDoc rowKey, KeyedValues rowData) {
1009
1010        DefaultCategoryDataset result = new DefaultCategoryDataset();
1011        for (int i = 0; i < rowData.getItemCount(); i++) {
1012            result.addValue(rowData.getValue(i), rowKey, rowData.getKey(i));
1013        }
1014        return result;
1015
1016    }
1017
1018    /**
1019     * Returns <code>true</code> if the dataset is empty (or <code>null</code>), and
1020     * <code>false</code> otherwise.
1021     *
1022     * @param data the dataset (<code>null</code> permitted).
1023     *
1024     * @return A boolean.
1025     */

1026    public static boolean isEmptyOrNull(XYDataset data) {
1027
1028        boolean result = true;
1029
1030        if (data != null) {
1031            for (int s = 0; s < data.getSeriesCount(); s++) {
1032                if (data.getItemCount(s) > 0) {
1033                    result = false;
1034                    continue;
1035                }
1036            }
1037        }
1038
1039        return result;
1040
1041    }
1042
1043    /**
1044     * Returns <code>true</code> if the dataset is empty (or <code>null</code>), and
1045     * <code>false</code> otherwise.
1046     *
1047     * @param dataset the dataset (<code>null</code> permitted).
1048     *
1049     * @return A boolean.
1050     */

1051    public static boolean isEmptyOrNull(PieDataset dataset) {
1052
1053        if (dataset == null) {
1054            return true;
1055        }
1056
1057        int itemCount = dataset.getItemCount();
1058        if (itemCount == 0) {
1059            return true;
1060        }
1061
1062        for (int item = 0; item < itemCount; item++) {
1063            Number JavaDoc y = dataset.getValue(item);
1064            if (y != null) {
1065                double yy = y.doubleValue();
1066                if (yy > 0.0) {
1067                    return false;
1068                }
1069            }
1070        }
1071
1072        return true;
1073
1074    }
1075
1076    /**
1077     * Returns <code>true</code> if the dataset is empty (or <code>null</code>), and
1078     * <code>false</code> otherwise.
1079     *
1080     * @param data the dataset (<code>null</code> permitted).
1081     *
1082     * @return A boolean.
1083     */

1084    public static boolean isEmptyOrNull(CategoryDataset data) {
1085
1086        if (data == null) {
1087            return true;
1088        }
1089
1090        int rowCount = data.getRowCount();
1091        int columnCount = data.getColumnCount();
1092        if (rowCount == 0 || columnCount == 0) {
1093            return true;
1094        }
1095
1096        for (int r = 0; r < rowCount; r++) {
1097            for (int c = 0; c < columnCount; c++) {
1098                if (data.getValue(r, c) != null) {
1099                    return false;
1100                }
1101
1102            }
1103        }
1104
1105        return true;
1106
1107    }
1108
1109    /**
1110     * Creates an "Other" slice for percentages below the percent threshold.
1111     *
1112     * @param data the PieDataset.
1113     * @param percentThreshold the percent threshold.
1114     * @return A PieDataset.
1115     */

1116    public static PieDataset limitPieDataset(PieDataset data, double percentThreshold) {
1117        return DatasetUtilities.limitPieDataset(data, percentThreshold, 1, "Other");
1118    }
1119
1120    /**
1121     * Create an "Other" slice for percentages below the percent threshold providing there
1122     * are more slices below the percent threshold than specified in the slice threshold.
1123     *
1124     * @param data the PieDataset.
1125     * @param percentThreshold the percent threshold.
1126     * @param sliceThreshold the slice threshold.
1127     * @return A PieDataset.
1128     */

1129    public static PieDataset limitPieDataset(PieDataset data,
1130                                             double percentThreshold, int sliceThreshold) {
1131        return DatasetUtilities.limitPieDataset(data, percentThreshold, sliceThreshold, "Other");
1132    }
1133
1134    /**
1135     * Create an Other slice with a given label for percentages below the percent threshold
1136     * providing there are more slices below the percent threshold than specified in the slice
1137     * threshold.
1138     *
1139     * @param data the PieDataset.
1140     * @param percentThreshold the percent threshold.
1141     * @param sliceThreshold the slice threshold.
1142     * @param label the label to give the "Other" slice.
1143     * @return A PieDataset.
1144     */

1145    public static PieDataset limitPieDataset(PieDataset data,
1146                                             double percentThreshold, int sliceThreshold,
1147                                             String JavaDoc label) {
1148        DefaultPieDataset newDataset = new DefaultPieDataset();
1149        double total = DatasetUtilities.getPieDatasetTotal(data);
1150
1151        // Iterate and find all keys below threshold percentThreshold
1152
List JavaDoc keys = data.getKeys();
1153        ArrayList JavaDoc otherKeys = new ArrayList JavaDoc();
1154        Iterator JavaDoc kIter = keys.iterator();
1155        while (kIter.hasNext()) {
1156            Comparable JavaDoc key = (Comparable JavaDoc) kIter.next();
1157            Number JavaDoc dataValue = data.getValue(key);
1158            if (dataValue != null) {
1159                double value = dataValue.doubleValue();
1160                if (value / total < percentThreshold / 100) {
1161                    otherKeys.add(key);
1162                }
1163            }
1164        }
1165
1166        // Create new dataset with keys above threshold percentThreshold
1167
kIter = keys.iterator();
1168        double otherValue = 0;
1169        while (kIter.hasNext()) {
1170            Comparable JavaDoc key = (Comparable JavaDoc) kIter.next();
1171            Number JavaDoc dataValue = data.getValue(key);
1172            if (dataValue != null) {
1173                if (otherKeys.contains(key) && otherKeys.size() > sliceThreshold) {
1174                    // Do not add key to dataset
1175
otherValue += dataValue.doubleValue();
1176                }
1177                else {
1178                    // Add key to dataset
1179
newDataset.setValue(key, dataValue);
1180                }
1181            }
1182            // Add other category if applicable
1183
if (otherKeys.size() > sliceThreshold) {
1184                newDataset.setValue(label, otherValue);
1185            }
1186        }
1187        return newDataset;
1188    }
1189
1190    /**
1191     * Returns the minimum and maximum values for the dataset's range,
1192     * assuming that the series are stacked.
1193     *
1194     * @param data the dataset.
1195     * @return the value range.
1196     */

1197    public static Range getStackedRangeExtent(TableXYDataset data) {
1198        // check parameters...
1199
if (data == null) {
1200            return null;
1201        }
1202        double minimum = Double.POSITIVE_INFINITY;
1203        double maximum = Double.NEGATIVE_INFINITY;
1204        for (int itemNo = 0; itemNo < data.getItemCount(); itemNo++) {
1205            double value = 0;
1206            for (int seriesNo = 0; seriesNo < data.getSeriesCount(); seriesNo++) {
1207                if (data.getYValue(seriesNo, itemNo) != null) {
1208                    value += (data.getYValue(seriesNo, itemNo).doubleValue());
1209                }
1210            }
1211            if (value > maximum) {
1212                maximum = value;
1213            }
1214            if (value < minimum) {
1215                minimum = value;
1216            }
1217        }
1218        if (minimum == Double.POSITIVE_INFINITY) {
1219            return null;
1220        }
1221        else {
1222            return new Range(minimum, maximum);
1223        }
1224    }
1225
1226    /**
1227     * Calculates the range of values for a dataset where each item is the running total of
1228     * the items for the current series.
1229     *
1230     * @param dataset the dataset.
1231     *
1232     * @return The range.
1233     */

1234    public static Range getCumulativeRangeExtent(CategoryDataset dataset) {
1235        
1236        if (dataset == null) {
1237            return null;
1238        }
1239        
1240        boolean allItemsNull = true; // we'll set this to false if there is at least one
1241
// non-null data item...
1242
double minimum = 0.0;
1243        double maximum = 0.0;
1244        for (int row = 0; row < dataset.getRowCount(); row++) {
1245            double runningTotal = 0.0;
1246            for (int column = 0; column < dataset.getColumnCount() - 1; column++) {
1247                Number JavaDoc n = dataset.getValue(row, column);
1248                if (n != null) {
1249                    allItemsNull = false;
1250                    double value = n.doubleValue();
1251                    runningTotal = runningTotal + value;
1252                    minimum = Math.min(minimum, runningTotal);
1253                    maximum = Math.max(maximum, runningTotal);
1254                }
1255            }
1256        }
1257        if (!allItemsNull) {
1258            return new Range(minimum, maximum);
1259        }
1260        else {
1261            return null;
1262        }
1263        
1264    }
1265    
1266}
1267
Popular Tags