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-2007, 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-2007, 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.3 2007/02/02 15:50:24 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:  * ------------- JFREECHART 1.0.x ---------------------------------------------
  49:  * 02-Feb-2007 : Removed author tags from all over JFreeChart sources (DG);
  50:  *
  51:  */
  52: 
  53: package org.jfree.data.statistics;
  54: 
  55: import java.util.List;
  56: 
  57: import org.jfree.data.KeyedObjects2D;
  58: import org.jfree.data.Range;
  59: import org.jfree.data.RangeInfo;
  60: import org.jfree.data.general.AbstractDataset;
  61: import org.jfree.util.ObjectUtilities;
  62: 
  63: /**
  64:  * A convenience class that provides a default implementation of the
  65:  * {@link BoxAndWhiskerCategoryDataset} interface.
  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 (<code>null</code> not permitted).
 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(this.minimumRangeValue.doubleValue(),
 138:               this.maximumRangeValue.doubleValue());
 139: 
 140:         fireDatasetChanged();
 141: 
 142:     }
 143: 
 144:     /**
 145:      * Return an item from within the dataset.
 146:      * 
 147:      * @param row  the row index.
 148:      * @param column  the column index.
 149:      * 
 150:      * @return The item.
 151:      */
 152:     public BoxAndWhiskerItem getItem(int row, int column) {
 153:         return (BoxAndWhiskerItem) this.data.getObject(row, column);  
 154:     }
 155: 
 156:     /**
 157:      * Returns the value for an item.
 158:      *
 159:      * @param row  the row index.
 160:      * @param column  the column index.
 161:      *
 162:      * @return The value.
 163:      */
 164:     public Number getValue(int row, int column) {
 165:         return getMedianValue(row, column);
 166:     }
 167: 
 168:     /**
 169:      * Returns the value for an item.
 170:      *
 171:      * @param rowKey  the row key.
 172:      * @param columnKey  the columnKey.
 173:      *
 174:      * @return The value.
 175:      */
 176:     public Number getValue(Comparable rowKey, Comparable columnKey) {
 177:         return getMedianValue(rowKey, columnKey);
 178:     }
 179: 
 180:     /**
 181:      * Returns the mean value for an item.
 182:      * 
 183:      * @param row  the row index (zero-based).
 184:      * @param column  the column index (zero-based).
 185:      * 
 186:      * @return The mean value.
 187:      */
 188:     public Number getMeanValue(int row, int column) {
 189: 
 190:         Number result = null;
 191:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(row, 
 192:                 column);
 193:         if (item != null) {
 194:             result = item.getMean();
 195:         }
 196:         return result;
 197: 
 198:     }
 199: 
 200:     /**
 201:      * Returns the mean value for an item.
 202:      * 
 203:      * @param rowKey  the row key.
 204:      * @param columnKey  the column key.
 205:      * 
 206:      * @return The mean value.
 207:      */
 208:     public Number getMeanValue(Comparable rowKey, Comparable columnKey) {
 209:         Number result = null;
 210:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 211:                 rowKey, columnKey);
 212:         if (item != null) {
 213:             result = item.getMean();
 214:         }
 215:         return result;
 216:     }
 217: 
 218:     /**
 219:      * Returns the median value for an item.
 220:      *
 221:      * @param row  the row index (zero-based).
 222:      * @param column  the column index (zero-based).
 223:      *
 224:      * @return The median value.
 225:      */
 226:     public Number getMedianValue(int row, int column) {
 227:         Number result = null;
 228:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(row, 
 229:                 column);
 230:         if (item != null) {
 231:             result = item.getMedian();
 232:         }
 233:         return result;
 234:     }
 235: 
 236:     /**
 237:      * Returns the median value for an item.
 238:      *
 239:      * @param rowKey  the row key.
 240:      * @param columnKey  the columnKey.
 241:      *
 242:      * @return The median value.
 243:      */
 244:     public Number getMedianValue(Comparable rowKey, Comparable columnKey) {
 245:         Number result = null;
 246:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 247:                 rowKey, columnKey);
 248:         if (item != null) {
 249:             result = item.getMedian();
 250:         }
 251:         return result;
 252:     }
 253: 
 254:     /**
 255:      * Returns the first quartile value.
 256:      * 
 257:      * @param row  the row index (zero-based).
 258:      * @param column  the column index (zero-based).
 259:      * 
 260:      * @return The first quartile value.
 261:      */
 262:     public Number getQ1Value(int row, int column) {
 263:         Number result = null;
 264:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 265:                 row, column);
 266:         if (item != null) {
 267:             result = item.getQ1();
 268:         }
 269:         return result;
 270:     }
 271: 
 272:     /**
 273:      * Returns the first quartile value.
 274:      * 
 275:      * @param rowKey  the row key.
 276:      * @param columnKey  the column key.
 277:      * 
 278:      * @return The first quartile value.
 279:      */
 280:     public Number getQ1Value(Comparable rowKey, Comparable columnKey) {
 281:         Number result = null;
 282:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 283:                 rowKey, columnKey);
 284:         if (item != null) {
 285:             result = item.getQ1();
 286:         }
 287:         return result;
 288:     }
 289: 
 290:     /**
 291:      * Returns the third quartile value.
 292:      * 
 293:      * @param row  the row index (zero-based).
 294:      * @param column  the column index (zero-based).
 295:      * 
 296:      * @return The third quartile value.
 297:      */
 298:     public Number getQ3Value(int row, int column) {
 299:         Number result = null;
 300:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 301:                 row, column);
 302:         if (item != null) {
 303:             result = item.getQ3();
 304:         }
 305:         return result;
 306:     }
 307: 
 308:     /**
 309:      * Returns the third quartile value.
 310:      * 
 311:      * @param rowKey  the row key.
 312:      * @param columnKey  the column key.
 313:      * 
 314:      * @return The third quartile value.
 315:      */
 316:     public Number getQ3Value(Comparable rowKey, Comparable columnKey) {
 317:         Number result = null;
 318:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 319:                 rowKey, columnKey);
 320:         if (item != null) {
 321:             result = item.getQ3();
 322:         }
 323:         return result;
 324:     }
 325: 
 326:     /**
 327:      * Returns the column index for a given key.
 328:      *
 329:      * @param key  the column key.
 330:      *
 331:      * @return The column index.
 332:      */
 333:     public int getColumnIndex(Comparable key) {
 334:         return this.data.getColumnIndex(key);
 335:     }
 336: 
 337:     /**
 338:      * Returns a column key.
 339:      *
 340:      * @param column  the column index (zero-based).
 341:      *
 342:      * @return The column key.
 343:      */
 344:     public Comparable getColumnKey(int column) {
 345:         return this.data.getColumnKey(column);
 346:     }
 347: 
 348:     /**
 349:      * Returns the column keys.
 350:      *
 351:      * @return The keys.
 352:      */
 353:     public List getColumnKeys() {
 354:         return this.data.getColumnKeys();
 355:     }
 356: 
 357:     /**
 358:      * Returns the row index for a given key.
 359:      *
 360:      * @param key  the row key.
 361:      *
 362:      * @return The row index.
 363:      */
 364:     public int getRowIndex(Comparable key) {
 365:         return this.data.getRowIndex(key);
 366:     }
 367: 
 368:     /**
 369:      * Returns a row key.
 370:      *
 371:      * @param row  the row index (zero-based).
 372:      *
 373:      * @return The row key.
 374:      */
 375:     public Comparable getRowKey(int row) {
 376:         return this.data.getRowKey(row);
 377:     }
 378: 
 379:     /**
 380:      * Returns the row keys.
 381:      *
 382:      * @return The keys.
 383:      */
 384:     public List getRowKeys() {
 385:         return this.data.getRowKeys();
 386:     }
 387: 
 388:     /**
 389:      * Returns the number of rows in the table.
 390:      *
 391:      * @return The row count.
 392:      */
 393:     public int getRowCount() {
 394:         return this.data.getRowCount();
 395:     }
 396: 
 397:     /**
 398:      * Returns the number of columns in the table.
 399:      *
 400:      * @return The column count.
 401:      */
 402:     public int getColumnCount() {
 403:         return this.data.getColumnCount();
 404:     }
 405: 
 406:     /**
 407:      * Returns the minimum y-value in the dataset.
 408:      *
 409:      * @param includeInterval  a flag that determines whether or not the
 410:      *                         y-interval is taken into account.
 411:      * 
 412:      * @return The minimum value.
 413:      */
 414:     public double getRangeLowerBound(boolean includeInterval) {
 415:         double result = Double.NaN;
 416:         if (this.minimumRangeValue != null) {
 417:             result = this.minimumRangeValue.doubleValue();
 418:         }
 419:         return result;
 420:     }
 421: 
 422:     /**
 423:      * Returns the maximum y-value in the dataset.
 424:      *
 425:      * @param includeInterval  a flag that determines whether or not the
 426:      *                         y-interval is taken into account.
 427:      * 
 428:      * @return The maximum value.
 429:      */
 430:     public double getRangeUpperBound(boolean includeInterval) {
 431:         double result = Double.NaN;
 432:         if (this.maximumRangeValue != null) {
 433:             result = this.maximumRangeValue.doubleValue();
 434:         }
 435:         return result;
 436:     }
 437: 
 438:     /**
 439:      * Returns the range of the values in this dataset's range.
 440:      *
 441:      * @param includeInterval  a flag that determines whether or not the
 442:      *                         y-interval is taken into account.
 443:      * 
 444:      * @return The range.
 445:      */
 446:     public Range getRangeBounds(boolean includeInterval) {
 447:         return this.rangeBounds;
 448:     }
 449:     
 450:     /**
 451:      * Returns the minimum regular (non outlier) value for an item.
 452:      * 
 453:      * @param row  the row index (zero-based).
 454:      * @param column  the column index (zero-based).
 455:      * 
 456:      * @return The minimum regular value.
 457:      */
 458:     public Number getMinRegularValue(int row, int column) {
 459:         Number result = null;
 460:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 461:                 row, column);
 462:         if (item != null) {
 463:             result = item.getMinRegularValue();
 464:         }
 465:         return result;
 466:     }
 467: 
 468:     /**
 469:      * Returns the minimum regular (non outlier) value for an item.
 470:      * 
 471:      * @param rowKey  the row key.
 472:      * @param columnKey  the column key.
 473:      * 
 474:      * @return The minimum regular value.
 475:      */
 476:     public Number getMinRegularValue(Comparable rowKey, Comparable columnKey) {
 477:         Number result = null;
 478:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 479:                 rowKey, columnKey);
 480:         if (item != null) {
 481:             result = item.getMinRegularValue();
 482:         }
 483:         return result;
 484:     }
 485: 
 486:     /**
 487:      * Returns the maximum regular (non outlier) value for an item.
 488:      * 
 489:      * @param row  the row index (zero-based).
 490:      * @param column  the column index (zero-based).
 491:      * 
 492:      * @return The maximum regular value.
 493:      */
 494:     public Number getMaxRegularValue(int row, int column) {
 495:         Number result = null;
 496:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 497:                 row, column);
 498:         if (item != null) {
 499:             result = item.getMaxRegularValue();
 500:         }
 501:         return result;
 502:     }
 503: 
 504:     /**
 505:      * Returns the maximum regular (non outlier) value for an item.
 506:      * 
 507:      * @param rowKey  the row key.
 508:      * @param columnKey  the column key.
 509:      * 
 510:      * @return The maximum regular value.
 511:      */
 512:     public Number getMaxRegularValue(Comparable rowKey, Comparable columnKey) {
 513:         Number result = null;
 514:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 515:                 rowKey, columnKey);
 516:         if (item != null) {
 517:             result = item.getMaxRegularValue();
 518:         }
 519:         return result;
 520:     }
 521: 
 522:     /**
 523:      * Returns the minimum outlier (non farout) value for an item.
 524:      * 
 525:      * @param row  the row index (zero-based).
 526:      * @param column  the column index (zero-based).
 527:      * 
 528:      * @return The minimum outlier.
 529:      */
 530:     public Number getMinOutlier(int row, int column) {
 531:         Number result = null;
 532:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 533:                 row, column);
 534:         if (item != null) {
 535:             result = item.getMinOutlier();
 536:         }
 537:         return result;
 538:     }
 539: 
 540:     /**
 541:      * Returns the minimum outlier (non farout) value for an item.
 542:      * 
 543:      * @param rowKey  the row key.
 544:      * @param columnKey  the column key.
 545:      * 
 546:      * @return The minimum outlier.
 547:      */
 548:     public Number getMinOutlier(Comparable rowKey, Comparable columnKey) {
 549:         Number result = null;
 550:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 551:                 rowKey, columnKey);
 552:         if (item != null) {
 553:             result = item.getMinOutlier();
 554:         }
 555:         return result;
 556:     }
 557: 
 558:     /**
 559:      * Returns the maximum outlier (non farout) value for an item.
 560:      * 
 561:      * @param row  the row index (zero-based).
 562:      * @param column  the column index (zero-based).
 563:      * 
 564:      * @return The maximum outlier.
 565:      */
 566:     public Number getMaxOutlier(int row, int column) {
 567:         Number result = null;
 568:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 569:                 row, column);
 570:         if (item != null) {
 571:             result = item.getMaxOutlier();
 572:         }
 573:         return result;
 574:     }
 575: 
 576:     /**
 577:      * Returns the maximum outlier (non farout) value for an item.
 578:      * 
 579:      * @param rowKey  the row key.
 580:      * @param columnKey  the column key.
 581:      * 
 582:      * @return The maximum outlier.
 583:      */
 584:     public Number getMaxOutlier(Comparable rowKey, Comparable columnKey) {
 585:         Number result = null;
 586:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 587:                 rowKey, columnKey);
 588:         if (item != null) {
 589:             result = item.getMaxOutlier();
 590:         }
 591:         return result;
 592:     }
 593: 
 594:     /**
 595:      * Returns a list of outlier values for an item.
 596:      * 
 597:      * @param row  the row index (zero-based).
 598:      * @param column  the column index (zero-based).
 599:      * 
 600:      * @return A list of outlier values.
 601:      */
 602:     public List getOutliers(int row, int column) {
 603:         List result = null;
 604:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 605:                 row, column);
 606:         if (item != null) {
 607:             result = item.getOutliers();
 608:         }
 609:         return result;
 610:     }
 611: 
 612:     /**
 613:      * Returns a list of outlier values for an item.
 614:      * 
 615:      * @param rowKey  the row key.
 616:      * @param columnKey  the column key.
 617:      * 
 618:      * @return A list of outlier values.
 619:      */
 620:     public List getOutliers(Comparable rowKey, Comparable columnKey) {
 621:         List result = null;
 622:         BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(
 623:                 rowKey, columnKey);
 624:         if (item != null) {
 625:             result = item.getOutliers();
 626:         }
 627:         return result;
 628:     }
 629:     
 630:     /**
 631:      * Tests this dataset for equality with an arbitrary object.
 632:      * 
 633:      * @param obj  the object to test against (<code>null</code> permitted).
 634:      * 
 635:      * @return A boolean.
 636:      */
 637:     public boolean equals(Object obj) {
 638:         if (obj == this) {
 639:             return true;   
 640:         }
 641:         if (obj instanceof DefaultBoxAndWhiskerCategoryDataset) {
 642:             DefaultBoxAndWhiskerCategoryDataset dataset 
 643:                     = (DefaultBoxAndWhiskerCategoryDataset) obj;
 644:             return ObjectUtilities.equal(this.data, dataset.data);
 645:         }
 646:         return false;
 647:     }
 648: 
 649: }