001: /* ===========================================================
002: * JFreeChart : a free chart library for the Java(tm) platform
003: * ===========================================================
004: *
005: * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
006: *
007: * Project Info: http://www.jfree.org/jfreechart/index.html
008: *
009: * This library is free software; you can redistribute it and/or modify it
010: * under the terms of the GNU Lesser General Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but
015: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017: * License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022: * USA.
023: *
024: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025: * in the United States and other countries.]
026: *
027: * ----------------------------------------
028: * DefaultBoxAndWhiskerCategoryDataset.java
029: * ----------------------------------------
030: * (C) Copyright 2003-2007, by David Browning and Contributors.
031: *
032: * Original Author: David Browning (for Australian Institute of Marine
033: * Science);
034: * Contributor(s): David Gilbert (for Object Refinery Limited);
035: *
036: * $Id: DefaultBoxAndWhiskerCategoryDataset.java,v 1.9.2.5 2007/06/13 15:26:00 mungady Exp $
037: *
038: * Changes
039: * -------
040: * 05-Aug-2003 : Version 1, contributed by David Browning (DG);
041: * 27-Aug-2003 : Moved from org.jfree.data --> org.jfree.data.statistics (DG);
042: * 12-Nov-2003 : Changed 'data' from private to protected and added a new 'add'
043: * method as proposed by Tim Bardzil. Also removed old code (DG);
044: * 01-Mar-2004 : Added equals() method (DG);
045: * 18-Nov-2004 : Updates for changes in RangeInfo interface (DG);
046: * 11-Jan-2005 : Removed deprecated code in preparation for the 1.0.0
047: * release (DG);
048: * ------------- JFREECHART 1.0.x ---------------------------------------------
049: * 02-Feb-2007 : Removed author tags from all over JFreeChart sources (DG);
050: * 17-Apr-2007 : Fixed bug 1701822 (DG);
051: * 13-Jun-2007 : Fixed error in previous patch (DG);
052: *
053: */
054:
055: package org.jfree.data.statistics;
056:
057: import java.util.List;
058:
059: import org.jfree.data.KeyedObjects2D;
060: import org.jfree.data.Range;
061: import org.jfree.data.RangeInfo;
062: import org.jfree.data.general.AbstractDataset;
063: import org.jfree.util.ObjectUtilities;
064:
065: /**
066: * A convenience class that provides a default implementation of the
067: * {@link BoxAndWhiskerCategoryDataset} interface.
068: */
069: public class DefaultBoxAndWhiskerCategoryDataset extends
070: AbstractDataset implements BoxAndWhiskerCategoryDataset,
071: RangeInfo {
072:
073: /** Storage for the data. */
074: protected KeyedObjects2D data;
075:
076: /** The minimum range value. */
077: private Number minimumRangeValue;
078:
079: /** The maximum range value. */
080: private Number maximumRangeValue;
081:
082: /** The range of values. */
083: private Range rangeBounds;
084:
085: /**
086: * Creates a new dataset.
087: */
088: public DefaultBoxAndWhiskerCategoryDataset() {
089: this .data = new KeyedObjects2D();
090: this .minimumRangeValue = null;
091: this .maximumRangeValue = null;
092: this .rangeBounds = new Range(0.0, 0.0);
093: }
094:
095: /**
096: * Adds a list of values relating to one box-and-whisker entity to the
097: * table. The various median values are calculated.
098: *
099: * @param list a collection of values from which the various medians will
100: * be calculated.
101: * @param rowKey the row key.
102: * @param columnKey the column key.
103: */
104: public void add(List list, Comparable rowKey, Comparable columnKey) {
105: BoxAndWhiskerItem item = BoxAndWhiskerCalculator
106: .calculateBoxAndWhiskerStatistics(list);
107: add(item, rowKey, columnKey);
108: }
109:
110: /**
111: * Adds a list of values relating to one Box and Whisker entity to the
112: * table. The various median values are calculated.
113: *
114: * @param item a box and whisker item (<code>null</code> not permitted).
115: * @param rowKey the row key.
116: * @param columnKey the column key.
117: */
118: public void add(BoxAndWhiskerItem item, Comparable rowKey,
119: Comparable columnKey) {
120:
121: this .data.addObject(item, rowKey, columnKey);
122: double minval = Double.NaN;
123: if (item.getMinOutlier() != null) {
124: minval = item.getMinOutlier().doubleValue();
125: }
126: double maxval = Double.NaN;
127: if (item.getMaxOutlier() != null) {
128: maxval = item.getMaxOutlier().doubleValue();
129: }
130:
131: if (this .maximumRangeValue == null) {
132: this .maximumRangeValue = new Double(maxval);
133: } else if (maxval > this .maximumRangeValue.doubleValue()) {
134: this .maximumRangeValue = new Double(maxval);
135: }
136:
137: if (this .minimumRangeValue == null) {
138: this .minimumRangeValue = new Double(minval);
139: } else if (minval < this .minimumRangeValue.doubleValue()) {
140: this .minimumRangeValue = new Double(minval);
141: }
142:
143: this .rangeBounds = new Range(this .minimumRangeValue
144: .doubleValue(), this .maximumRangeValue.doubleValue());
145:
146: fireDatasetChanged();
147:
148: }
149:
150: /**
151: * Return an item from within the dataset.
152: *
153: * @param row the row index.
154: * @param column the column index.
155: *
156: * @return The item.
157: */
158: public BoxAndWhiskerItem getItem(int row, int column) {
159: return (BoxAndWhiskerItem) this .data.getObject(row, column);
160: }
161:
162: /**
163: * Returns the value for an item.
164: *
165: * @param row the row index.
166: * @param column the column index.
167: *
168: * @return The value.
169: */
170: public Number getValue(int row, int column) {
171: return getMedianValue(row, column);
172: }
173:
174: /**
175: * Returns the value for an item.
176: *
177: * @param rowKey the row key.
178: * @param columnKey the columnKey.
179: *
180: * @return The value.
181: */
182: public Number getValue(Comparable rowKey, Comparable columnKey) {
183: return getMedianValue(rowKey, columnKey);
184: }
185:
186: /**
187: * Returns the mean value for an item.
188: *
189: * @param row the row index (zero-based).
190: * @param column the column index (zero-based).
191: *
192: * @return The mean value.
193: */
194: public Number getMeanValue(int row, int column) {
195:
196: Number result = null;
197: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
198: .getObject(row, column);
199: if (item != null) {
200: result = item.getMean();
201: }
202: return result;
203:
204: }
205:
206: /**
207: * Returns the mean value for an item.
208: *
209: * @param rowKey the row key.
210: * @param columnKey the column key.
211: *
212: * @return The mean value.
213: */
214: public Number getMeanValue(Comparable rowKey, Comparable columnKey) {
215: Number result = null;
216: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
217: .getObject(rowKey, columnKey);
218: if (item != null) {
219: result = item.getMean();
220: }
221: return result;
222: }
223:
224: /**
225: * Returns the median value for an item.
226: *
227: * @param row the row index (zero-based).
228: * @param column the column index (zero-based).
229: *
230: * @return The median value.
231: */
232: public Number getMedianValue(int row, int column) {
233: Number result = null;
234: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
235: .getObject(row, column);
236: if (item != null) {
237: result = item.getMedian();
238: }
239: return result;
240: }
241:
242: /**
243: * Returns the median value for an item.
244: *
245: * @param rowKey the row key.
246: * @param columnKey the columnKey.
247: *
248: * @return The median value.
249: */
250: public Number getMedianValue(Comparable rowKey, Comparable columnKey) {
251: Number result = null;
252: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
253: .getObject(rowKey, columnKey);
254: if (item != null) {
255: result = item.getMedian();
256: }
257: return result;
258: }
259:
260: /**
261: * Returns the first quartile value.
262: *
263: * @param row the row index (zero-based).
264: * @param column the column index (zero-based).
265: *
266: * @return The first quartile value.
267: */
268: public Number getQ1Value(int row, int column) {
269: Number result = null;
270: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
271: .getObject(row, column);
272: if (item != null) {
273: result = item.getQ1();
274: }
275: return result;
276: }
277:
278: /**
279: * Returns the first quartile value.
280: *
281: * @param rowKey the row key.
282: * @param columnKey the column key.
283: *
284: * @return The first quartile value.
285: */
286: public Number getQ1Value(Comparable rowKey, Comparable columnKey) {
287: Number result = null;
288: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
289: .getObject(rowKey, columnKey);
290: if (item != null) {
291: result = item.getQ1();
292: }
293: return result;
294: }
295:
296: /**
297: * Returns the third quartile value.
298: *
299: * @param row the row index (zero-based).
300: * @param column the column index (zero-based).
301: *
302: * @return The third quartile value.
303: */
304: public Number getQ3Value(int row, int column) {
305: Number result = null;
306: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
307: .getObject(row, column);
308: if (item != null) {
309: result = item.getQ3();
310: }
311: return result;
312: }
313:
314: /**
315: * Returns the third quartile value.
316: *
317: * @param rowKey the row key.
318: * @param columnKey the column key.
319: *
320: * @return The third quartile value.
321: */
322: public Number getQ3Value(Comparable rowKey, Comparable columnKey) {
323: Number result = null;
324: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
325: .getObject(rowKey, columnKey);
326: if (item != null) {
327: result = item.getQ3();
328: }
329: return result;
330: }
331:
332: /**
333: * Returns the column index for a given key.
334: *
335: * @param key the column key.
336: *
337: * @return The column index.
338: */
339: public int getColumnIndex(Comparable key) {
340: return this .data.getColumnIndex(key);
341: }
342:
343: /**
344: * Returns a column key.
345: *
346: * @param column the column index (zero-based).
347: *
348: * @return The column key.
349: */
350: public Comparable getColumnKey(int column) {
351: return this .data.getColumnKey(column);
352: }
353:
354: /**
355: * Returns the column keys.
356: *
357: * @return The keys.
358: */
359: public List getColumnKeys() {
360: return this .data.getColumnKeys();
361: }
362:
363: /**
364: * Returns the row index for a given key.
365: *
366: * @param key the row key.
367: *
368: * @return The row index.
369: */
370: public int getRowIndex(Comparable key) {
371: return this .data.getRowIndex(key);
372: }
373:
374: /**
375: * Returns a row key.
376: *
377: * @param row the row index (zero-based).
378: *
379: * @return The row key.
380: */
381: public Comparable getRowKey(int row) {
382: return this .data.getRowKey(row);
383: }
384:
385: /**
386: * Returns the row keys.
387: *
388: * @return The keys.
389: */
390: public List getRowKeys() {
391: return this .data.getRowKeys();
392: }
393:
394: /**
395: * Returns the number of rows in the table.
396: *
397: * @return The row count.
398: */
399: public int getRowCount() {
400: return this .data.getRowCount();
401: }
402:
403: /**
404: * Returns the number of columns in the table.
405: *
406: * @return The column count.
407: */
408: public int getColumnCount() {
409: return this .data.getColumnCount();
410: }
411:
412: /**
413: * Returns the minimum y-value in the dataset.
414: *
415: * @param includeInterval a flag that determines whether or not the
416: * y-interval is taken into account.
417: *
418: * @return The minimum value.
419: */
420: public double getRangeLowerBound(boolean includeInterval) {
421: double result = Double.NaN;
422: if (this .minimumRangeValue != null) {
423: result = this .minimumRangeValue.doubleValue();
424: }
425: return result;
426: }
427:
428: /**
429: * Returns the maximum y-value in the dataset.
430: *
431: * @param includeInterval a flag that determines whether or not the
432: * y-interval is taken into account.
433: *
434: * @return The maximum value.
435: */
436: public double getRangeUpperBound(boolean includeInterval) {
437: double result = Double.NaN;
438: if (this .maximumRangeValue != null) {
439: result = this .maximumRangeValue.doubleValue();
440: }
441: return result;
442: }
443:
444: /**
445: * Returns the range of the values in this dataset's range.
446: *
447: * @param includeInterval a flag that determines whether or not the
448: * y-interval is taken into account.
449: *
450: * @return The range.
451: */
452: public Range getRangeBounds(boolean includeInterval) {
453: return this .rangeBounds;
454: }
455:
456: /**
457: * Returns the minimum regular (non outlier) value for an item.
458: *
459: * @param row the row index (zero-based).
460: * @param column the column index (zero-based).
461: *
462: * @return The minimum regular value.
463: */
464: public Number getMinRegularValue(int row, int column) {
465: Number result = null;
466: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
467: .getObject(row, column);
468: if (item != null) {
469: result = item.getMinRegularValue();
470: }
471: return result;
472: }
473:
474: /**
475: * Returns the minimum regular (non outlier) value for an item.
476: *
477: * @param rowKey the row key.
478: * @param columnKey the column key.
479: *
480: * @return The minimum regular value.
481: */
482: public Number getMinRegularValue(Comparable rowKey,
483: Comparable columnKey) {
484: Number result = null;
485: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
486: .getObject(rowKey, columnKey);
487: if (item != null) {
488: result = item.getMinRegularValue();
489: }
490: return result;
491: }
492:
493: /**
494: * Returns the maximum regular (non outlier) value for an item.
495: *
496: * @param row the row index (zero-based).
497: * @param column the column index (zero-based).
498: *
499: * @return The maximum regular value.
500: */
501: public Number getMaxRegularValue(int row, int column) {
502: Number result = null;
503: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
504: .getObject(row, column);
505: if (item != null) {
506: result = item.getMaxRegularValue();
507: }
508: return result;
509: }
510:
511: /**
512: * Returns the maximum regular (non outlier) value for an item.
513: *
514: * @param rowKey the row key.
515: * @param columnKey the column key.
516: *
517: * @return The maximum regular value.
518: */
519: public Number getMaxRegularValue(Comparable rowKey,
520: Comparable columnKey) {
521: Number result = null;
522: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
523: .getObject(rowKey, columnKey);
524: if (item != null) {
525: result = item.getMaxRegularValue();
526: }
527: return result;
528: }
529:
530: /**
531: * Returns the minimum outlier (non farout) value for an item.
532: *
533: * @param row the row index (zero-based).
534: * @param column the column index (zero-based).
535: *
536: * @return The minimum outlier.
537: */
538: public Number getMinOutlier(int row, int column) {
539: Number result = null;
540: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
541: .getObject(row, column);
542: if (item != null) {
543: result = item.getMinOutlier();
544: }
545: return result;
546: }
547:
548: /**
549: * Returns the minimum outlier (non farout) value for an item.
550: *
551: * @param rowKey the row key.
552: * @param columnKey the column key.
553: *
554: * @return The minimum outlier.
555: */
556: public Number getMinOutlier(Comparable rowKey, Comparable columnKey) {
557: Number result = null;
558: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
559: .getObject(rowKey, columnKey);
560: if (item != null) {
561: result = item.getMinOutlier();
562: }
563: return result;
564: }
565:
566: /**
567: * Returns the maximum outlier (non farout) value for an item.
568: *
569: * @param row the row index (zero-based).
570: * @param column the column index (zero-based).
571: *
572: * @return The maximum outlier.
573: */
574: public Number getMaxOutlier(int row, int column) {
575: Number result = null;
576: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
577: .getObject(row, column);
578: if (item != null) {
579: result = item.getMaxOutlier();
580: }
581: return result;
582: }
583:
584: /**
585: * Returns the maximum outlier (non farout) value for an item.
586: *
587: * @param rowKey the row key.
588: * @param columnKey the column key.
589: *
590: * @return The maximum outlier.
591: */
592: public Number getMaxOutlier(Comparable rowKey, Comparable columnKey) {
593: Number result = null;
594: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
595: .getObject(rowKey, columnKey);
596: if (item != null) {
597: result = item.getMaxOutlier();
598: }
599: return result;
600: }
601:
602: /**
603: * Returns a list of outlier values for an item.
604: *
605: * @param row the row index (zero-based).
606: * @param column the column index (zero-based).
607: *
608: * @return A list of outlier values.
609: */
610: public List getOutliers(int row, int column) {
611: List result = null;
612: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
613: .getObject(row, column);
614: if (item != null) {
615: result = item.getOutliers();
616: }
617: return result;
618: }
619:
620: /**
621: * Returns a list of outlier values for an item.
622: *
623: * @param rowKey the row key.
624: * @param columnKey the column key.
625: *
626: * @return A list of outlier values.
627: */
628: public List getOutliers(Comparable rowKey, Comparable columnKey) {
629: List result = null;
630: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this .data
631: .getObject(rowKey, columnKey);
632: if (item != null) {
633: result = item.getOutliers();
634: }
635: return result;
636: }
637:
638: /**
639: * Tests this dataset for equality with an arbitrary object.
640: *
641: * @param obj the object to test against (<code>null</code> permitted).
642: *
643: * @return A boolean.
644: */
645: public boolean equals(Object obj) {
646: if (obj == this ) {
647: return true;
648: }
649: if (obj instanceof DefaultBoxAndWhiskerCategoryDataset) {
650: DefaultBoxAndWhiskerCategoryDataset dataset = (DefaultBoxAndWhiskerCategoryDataset) obj;
651: return ObjectUtilities.equal(this .data, dataset.data);
652: }
653: return false;
654: }
655:
656: }
|