Source for org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
   6:  *
   7:  * Project Info:  http://www.jfree.org/jfreechart/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  *
  27:  * ----------------------------------------
  28:  * DefaultBoxAndWhiskerCategoryDataset.java
  29:  * ----------------------------------------
  30:  * (C) Copyright 2003-2005, by David Browning and Contributors.
  31:  *
  32:  * Original Author:  David Browning (for Australian Institute of Marine 
  33:  *                   Science);
  34:  * Contributor(s):   David Gilbert (for Object Refinery Limited);
  35:  *
  36:  * $Id: DefaultBoxAndWhiskerCategoryDataset.java,v 1.9.2.1 2005/10/25 21:34:46 mungady Exp $
  37:  *
  38:  * Changes
  39:  * -------
  40:  * 05-Aug-2003 : Version 1, contributed by David Browning (DG);
  41:  * 27-Aug-2003 : Moved from org.jfree.data --> org.jfree.data.statistics (DG);
  42:  * 12-Nov-2003 : Changed 'data' from private to protected and added a new 'add' 
  43:  *               method as proposed by Tim Bardzil.  Also removed old code (DG);
  44:  * 01-Mar-2004 : Added equals() method (DG);
  45:  * 18-Nov-2004 : Updates for changes in RangeInfo interface (DG);
  46:  * 11-Jan-2005 : Removed deprecated code in preparation for the 1.0.0 
  47:  *               release (DG);
  48:  *
  49:  */
  50: 
  51: package org.jfree.data.statistics;
  52: 
  53: import java.util.List;
  54: 
  55: import org.jfree.data.KeyedObjects2D;
  56: import org.jfree.data.Range;
  57: import org.jfree.data.RangeInfo;
  58: import org.jfree.data.general.AbstractDataset;
  59: import org.jfree.util.ObjectUtilities;
  60: 
  61: /**
  62:  * A convenience class that provides a default implementation of the
  63:  * {@link BoxAndWhiskerCategoryDataset} interface.
  64:  *
  65:  * @author David Browning (for Australian Institute of Marine Science)
  66:  */
  67: public class DefaultBoxAndWhiskerCategoryDataset extends AbstractDataset
  68:     implements BoxAndWhiskerCategoryDataset, RangeInfo {
  69: 
  70:     /** Storage for the data. */
  71:     protected KeyedObjects2D data;
  72: 
  73:     /** The minimum range value. */
  74:     private Number minimumRangeValue;
  75: 
  76:     /** The maximum range value. */
  77:     private Number maximumRangeValue;
  78: 
  79:     /** The range of values. */
  80:     private Range rangeBounds;
  81: 
  82:     /**
  83:      * Creates a new dataset.
  84:      */
  85:     public DefaultBoxAndWhiskerCategoryDataset() {
  86:         this.data = new KeyedObjects2D();
  87:         this.minimumRangeValue = null;
  88:         this.maximumRangeValue = null;
  89:         this.rangeBounds = new Range(0.0, 0.0);
  90:     }
  91: 
  92:     /**
  93:      * Adds a list of values relating to one box-and-whisker entity to the 
  94:      * table.  The various median values are calculated.
  95:      *
  96:      * @param list  a collection of values from which the various medians will 
  97:      *              be calculated.
  98:      * @param rowKey  the row key.
  99:      * @param columnKey  the column key.
 100:      */
 101:     public void add(List list, Comparable rowKey, Comparable columnKey) {
 102:         BoxAndWhiskerItem item 
 103:             = BoxAndWhiskerCalculator.calculateBoxAndWhiskerStatistics(list);
 104:         add(item, rowKey, columnKey);
 105:     }
 106:     
 107:     /**
 108:      * Adds a list of values relating to one Box and Whisker entity to the 
 109:      * table.  The various median values are calculated.
 110:      *
 111:      * @param item  a box and whisker item.
 112:      * @param rowKey  the row key.
 113:      * @param columnKey  the column key.
 114:      */
 115:     public void add(BoxAndWhiskerItem item, 
 116:                     Comparable rowKey, 
 117:                     Comparable columnKey) {
 118: 
 119:         this.data.addObject(item, rowKey, columnKey);
 120:         double minval = item.getMinOutlier().doubleValue();
 121:         double maxval = item.getMaxOutlier().doubleValue();
 122:         
 123:         if (this.maximumRangeValue == null) {
 124:             this.maximumRangeValue = new Double(maxval);
 125:         }
 126:         else if (maxval > this.maximumRangeValue.doubleValue()) {
 127:             this.maximumRangeValue = new Double(maxval);
 128:         }
 129:         
 130:         if (this.minimumRangeValue == null) {
 131:             this.minimumRangeValue = new Double(minval);
 132:         }
 133:         else if (minval < this.minimumRangeValue.doubleValue()) {
 134:             this.minimumRangeValue = new Double(minval);
 135:         }
 136:         
 137:         this.rangeBounds = new Range(
 138:             this.minimumRangeValue.doubleValue(),
 139:             this.maximumRangeValue.doubleValue()
 140:         );
 141: 
 142:         fireDatasetChanged();
 143: 
 144:     }
 145: 
 146:     /**
 147:      * Return an item from within the dataset.
 148:      * 
 149:      * @param row  the row index.
 150:      * @param column  the column index.
 151:      * 
 152:      * @return The item.
 153:      */
 154:     public BoxAndWhiskerItem getItem(int row, int column) {
 155:         return (BoxAndWhiskerItem) this.data.getObject(row, column);  
 156:     }
 157: 
 158:     /**
 159:      * Returns the value for an item.
 160:      *
 161:      * @param row  the row index.
 162:      * @param column  the column index.
 163:      *
 164:      * @return The value.
 165:      */
 166:     public Number getValue(int row, int column) {
 167:         return getMedianValue(row, column);
 168:     }
 169: 
 170:     /**
 171:      * Returns the value for an item.
 172:      *
 173:      * @param rowKey  the row key.
 174:      * @param columnKey  the columnKey.
 175:      *
 176:      * @return The value.
 177:      */
 178:     public Number getValue(Comparable rowKey, Comparable columnKey) {
 179:         return getMedianValue(rowKey, columnKey);
 180:     }
 181: 
 182:     /**
 183:      * Returns the mean value for an item.
 184:      * 
 185:      * @param row  the row index (zero-based).
 186:      * @param column  the column index (zero-based).
 187:      * 
 188:      * @return The mean value.
 189:      */
 190:     public Number getMeanValue(int row, int column) {
 191: 
 192:         Number result = null;
 193:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 194:             row, column
 195:         );
 196:         if (item != null) {
 197:             result = item.getMean();
 198:         }
 199:         return result;
 200: 
 201:     }
 202: 
 203:     /**
 204:      * Returns the mean value for an item.
 205:      * 
 206:      * @param rowKey  the row key.
 207:      * @param columnKey  the column key.
 208:      * 
 209:      * @return The mean value.
 210:      */
 211:     public Number getMeanValue(Comparable rowKey, Comparable columnKey) {
 212: 
 213:         Number result = null;
 214:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 215:             rowKey, columnKey
 216:         );
 217:         if (item != null) {
 218:             result = item.getMean();
 219:         }
 220:         return result;
 221: 
 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.getObject(
 235:             row, column
 236:         );
 237:         if (item != null) {
 238:             result = item.getMedian();
 239:         }
 240:         return result;
 241:     }
 242: 
 243:     /**
 244:      * Returns the median value for an item.
 245:      *
 246:      * @param rowKey  the row key.
 247:      * @param columnKey  the columnKey.
 248:      *
 249:      * @return The median value.
 250:      */
 251:     public Number getMedianValue(Comparable rowKey, Comparable columnKey) {
 252:         Number result = null;
 253:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 254:             rowKey, columnKey
 255:         );
 256:         if (item != null) {
 257:             result = item.getMedian();
 258:         }
 259:         return result;
 260:     }
 261: 
 262:     /**
 263:      * Returns the first quartile value.
 264:      * 
 265:      * @param row  the row index (zero-based).
 266:      * @param column  the column index (zero-based).
 267:      * 
 268:      * @return The first quartile value.
 269:      */
 270:     public Number getQ1Value(int row, int column) {
 271:         Number result = null;
 272:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 273:             row, column
 274:         );
 275:         if (item != null) {
 276:             result = item.getQ1();
 277:         }
 278:         return result;
 279:     }
 280: 
 281:     /**
 282:      * Returns the first quartile value.
 283:      * 
 284:      * @param rowKey  the row key.
 285:      * @param columnKey  the column key.
 286:      * 
 287:      * @return The first quartile value.
 288:      */
 289:     public Number getQ1Value(Comparable rowKey, Comparable columnKey) {
 290:         Number result = null;
 291:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 292:             rowKey, columnKey
 293:         );
 294:         if (item != null) {
 295:             result = item.getQ1();
 296:         }
 297:         return result;
 298:     }
 299: 
 300:     /**
 301:      * Returns the third quartile value.
 302:      * 
 303:      * @param row  the row index (zero-based).
 304:      * @param column  the column index (zero-based).
 305:      * 
 306:      * @return The third quartile value.
 307:      */
 308:     public Number getQ3Value(int row, int column) {
 309:         Number result = null;
 310:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 311:             row, column
 312:         );
 313:         if (item != null) {
 314:             result = item.getQ3();
 315:         }
 316:         return result;
 317:     }
 318: 
 319:     /**
 320:      * Returns the third quartile value.
 321:      * 
 322:      * @param rowKey  the row key.
 323:      * @param columnKey  the column key.
 324:      * 
 325:      * @return The third quartile value.
 326:      */
 327:     public Number getQ3Value(Comparable rowKey, Comparable columnKey) {
 328:         Number result = null;
 329:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 330:             rowKey, columnKey
 331:         );
 332:         if (item != null) {
 333:             result = item.getQ3();
 334:         }
 335:         return result;
 336:     }
 337: 
 338:     /**
 339:      * Returns the column index for a given key.
 340:      *
 341:      * @param key  the column key.
 342:      *
 343:      * @return The column index.
 344:      */
 345:     public int getColumnIndex(Comparable key) {
 346:         return this.data.getColumnIndex(key);
 347:     }
 348: 
 349:     /**
 350:      * Returns a column key.
 351:      *
 352:      * @param column  the column index (zero-based).
 353:      *
 354:      * @return The column key.
 355:      */
 356:     public Comparable getColumnKey(int column) {
 357:         return this.data.getColumnKey(column);
 358:     }
 359: 
 360:     /**
 361:      * Returns the column keys.
 362:      *
 363:      * @return The keys.
 364:      */
 365:     public List getColumnKeys() {
 366:         return this.data.getColumnKeys();
 367:     }
 368: 
 369:     /**
 370:      * Returns the row index for a given key.
 371:      *
 372:      * @param key  the row key.
 373:      *
 374:      * @return The row index.
 375:      */
 376:     public int getRowIndex(Comparable key) {
 377:         return this.data.getRowIndex(key);
 378:     }
 379: 
 380:     /**
 381:      * Returns a row key.
 382:      *
 383:      * @param row  the row index (zero-based).
 384:      *
 385:      * @return The row key.
 386:      */
 387:     public Comparable getRowKey(int row) {
 388:         return this.data.getRowKey(row);
 389:     }
 390: 
 391:     /**
 392:      * Returns the row keys.
 393:      *
 394:      * @return The keys.
 395:      */
 396:     public List getRowKeys() {
 397:         return this.data.getRowKeys();
 398:     }
 399: 
 400:     /**
 401:      * Returns the number of rows in the table.
 402:      *
 403:      * @return The row count.
 404:      */
 405:     public int getRowCount() {
 406:         return this.data.getRowCount();
 407:     }
 408: 
 409:     /**
 410:      * Returns the number of columns in the table.
 411:      *
 412:      * @return The column count.
 413:      */
 414:     public int getColumnCount() {
 415:         return this.data.getColumnCount();
 416:     }
 417: 
 418:     /**
 419:      * Returns the minimum y-value in the dataset.
 420:      *
 421:      * @param includeInterval  a flag that determines whether or not the
 422:      *                         y-interval is taken into account.
 423:      * 
 424:      * @return The minimum value.
 425:      */
 426:     public double getRangeLowerBound(boolean includeInterval) {
 427:         double result = Double.NaN;
 428:         if (this.minimumRangeValue != null) {
 429:             result = this.minimumRangeValue.doubleValue();
 430:         }
 431:         return result;
 432:     }
 433: 
 434:     /**
 435:      * Returns the maximum y-value in the dataset.
 436:      *
 437:      * @param includeInterval  a flag that determines whether or not the
 438:      *                         y-interval is taken into account.
 439:      * 
 440:      * @return The maximum value.
 441:      */
 442:     public double getRangeUpperBound(boolean includeInterval) {
 443:         double result = Double.NaN;
 444:         if (this.maximumRangeValue != null) {
 445:             result = this.maximumRangeValue.doubleValue();
 446:         }
 447:         return result;
 448:     }
 449: 
 450:     /**
 451:      * Returns the range of the values in this dataset's range.
 452:      *
 453:      * @param includeInterval  a flag that determines whether or not the
 454:      *                         y-interval is taken into account.
 455:      * 
 456:      * @return The range.
 457:      */
 458:     public Range getRangeBounds(boolean includeInterval) {
 459:         return this.rangeBounds;
 460:     }
 461:     
 462:     /**
 463:      * Returns the minimum regular (non outlier) value for an item.
 464:      * 
 465:      * @param row  the row index (zero-based).
 466:      * @param column  the column index (zero-based).
 467:      * 
 468:      * @return The minimum regular value.
 469:      */
 470:     public Number getMinRegularValue(int row, int column) {
 471: 
 472:         Number result = null;
 473:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 474:             row, column
 475:         );
 476:         if (item != null) {
 477:             result = item.getMinRegularValue();
 478:         }
 479:         return result;
 480: 
 481:     }
 482: 
 483:     /**
 484:      * Returns the minimum regular (non outlier) value for an item.
 485:      * 
 486:      * @param rowKey  the row key.
 487:      * @param columnKey  the column key.
 488:      * 
 489:      * @return The minimum regular value.
 490:      */
 491:     public Number getMinRegularValue(Comparable rowKey, Comparable columnKey) {
 492: 
 493:         Number result = null;
 494:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 495:             rowKey, columnKey
 496:         );
 497:         if (item != null) {
 498:             result = item.getMinRegularValue();
 499:         }
 500:         return result;
 501: 
 502:     }
 503: 
 504:     /**
 505:      * Returns the maximum regular (non outlier) value for an item.
 506:      * 
 507:      * @param row  the row index (zero-based).
 508:      * @param column  the column index (zero-based).
 509:      * 
 510:      * @return The maximum regular value.
 511:      */
 512:     public Number getMaxRegularValue(int row, int column) {
 513: 
 514:         Number result = null;
 515:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 516:             row, column
 517:         );
 518:         if (item != null) {
 519:             result = item.getMaxRegularValue();
 520:         }
 521:         return result;
 522: 
 523:     }
 524: 
 525:     /**
 526:      * Returns the maximum regular (non outlier) value for an item.
 527:      * 
 528:      * @param rowKey  the row key.
 529:      * @param columnKey  the column key.
 530:      * 
 531:      * @return The maximum regular value.
 532:      */
 533:     public Number getMaxRegularValue(Comparable rowKey, Comparable columnKey) {
 534: 
 535:         Number result = null;
 536:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 537:             rowKey, columnKey
 538:         );
 539:         if (item != null) {
 540:             result = item.getMaxRegularValue();
 541:         }
 542:         return result;
 543: 
 544:     }
 545: 
 546:     /**
 547:      * Returns the minimum outlier (non farout) value for an item.
 548:      * 
 549:      * @param row  the row index (zero-based).
 550:      * @param column  the column index (zero-based).
 551:      * 
 552:      * @return The minimum outlier.
 553:      */
 554:     public Number getMinOutlier(int row, int column) {
 555: 
 556:         Number result = null;
 557:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 558:             row, column
 559:         );
 560:         if (item != null) {
 561:             result = item.getMinOutlier();
 562:         }
 563:         return result;
 564: 
 565:     }
 566: 
 567:     /**
 568:      * Returns the minimum outlier (non farout) value for an item.
 569:      * 
 570:      * @param rowKey  the row key.
 571:      * @param columnKey  the column key.
 572:      * 
 573:      * @return The minimum outlier.
 574:      */
 575:     public Number getMinOutlier(Comparable rowKey, Comparable columnKey) {
 576: 
 577:         Number result = null;
 578:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 579:             rowKey, columnKey
 580:         );
 581:         if (item != null) {
 582:             result = item.getMinOutlier();
 583:         }
 584:         return result;
 585: 
 586:     }
 587: 
 588:     /**
 589:      * Returns the maximum outlier (non farout) value for an item.
 590:      * 
 591:      * @param row  the row index (zero-based).
 592:      * @param column  the column index (zero-based).
 593:      * 
 594:      * @return The maximum outlier.
 595:      */
 596:     public Number getMaxOutlier(int row, int column) {
 597: 
 598:         Number result = null;
 599:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 600:             row, column
 601:         );
 602:         if (item != null) {
 603:             result = item.getMaxOutlier();
 604:         }
 605:         return result;
 606: 
 607:     }
 608: 
 609:     /**
 610:      * Returns the maximum outlier (non farout) value for an item.
 611:      * 
 612:      * @param rowKey  the row key.
 613:      * @param columnKey  the column key.
 614:      * 
 615:      * @return The maximum outlier.
 616:      */
 617:     public Number getMaxOutlier(Comparable rowKey, Comparable columnKey) {
 618: 
 619:         Number result = null;
 620:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 621:             rowKey, columnKey
 622:         );
 623:         if (item != null) {
 624:             result = item.getMaxOutlier();
 625:         }
 626:         return result;
 627: 
 628:     }
 629: 
 630:     /**
 631:      * Returns a list of outlier values for an item.
 632:      * 
 633:      * @param row  the row index (zero-based).
 634:      * @param column  the column index (zero-based).
 635:      * 
 636:      * @return A list of outlier values.
 637:      */
 638:     public List getOutliers(int row, int column) {
 639: 
 640:         List result = null;
 641:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 642:             row, column
 643:         );
 644:         if (item != null) {
 645:             result = item.getOutliers();
 646:         }
 647:         return result;
 648: 
 649:     }
 650: 
 651:     /**
 652:      * Returns a list of outlier values for an item.
 653:      * 
 654:      * @param rowKey  the row key.
 655:      * @param columnKey  the column key.
 656:      * 
 657:      * @return A list of outlier values.
 658:      */
 659:     public List getOutliers(Comparable rowKey, Comparable columnKey) {
 660: 
 661:         List result = null;
 662:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 663:             rowKey, columnKey
 664:         );
 665:         if (item != null) {
 666:             result = item.getOutliers();
 667:         }
 668:         return result;
 669: 
 670:     }
 671:     
 672:     /**
 673:      * Tests this dataset for equality with an arbitrary object.
 674:      * 
 675:      * @param obj  the object to test against (<code>null</code> permitted).
 676:      * 
 677:      * @return A boolean.
 678:      */
 679:     public boolean equals(Object obj) {
 680:         
 681:         if (obj == null) {
 682:             return false;   
 683:         }
 684:         
 685:         if (obj == this) {
 686:             return true;   
 687:         }
 688:         
 689:         if (obj instanceof DefaultBoxAndWhiskerCategoryDataset) {
 690:             DefaultBoxAndWhiskerCategoryDataset dataset 
 691:                 = (DefaultBoxAndWhiskerCategoryDataset) obj;
 692:             return ObjectUtilities.equal(this.data, dataset.data);
 693:         }
 694:         
 695:         return false;
 696:     }
 697: 
 698: }