001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2005, 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-2005, 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.1 2005/10/25 21:34:46 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 * 049 */ 050 051 package org.jfree.data.statistics; 052 053 import java.util.List; 054 055 import org.jfree.data.KeyedObjects2D; 056 import org.jfree.data.Range; 057 import org.jfree.data.RangeInfo; 058 import org.jfree.data.general.AbstractDataset; 059 import org.jfree.util.ObjectUtilities; 060 061 /** 062 * A convenience class that provides a default implementation of the 063 * {@link BoxAndWhiskerCategoryDataset} interface. 064 * 065 * @author David Browning (for Australian Institute of Marine Science) 066 */ 067 public class DefaultBoxAndWhiskerCategoryDataset extends AbstractDataset 068 implements BoxAndWhiskerCategoryDataset, RangeInfo { 069 070 /** Storage for the data. */ 071 protected KeyedObjects2D data; 072 073 /** The minimum range value. */ 074 private Number minimumRangeValue; 075 076 /** The maximum range value. */ 077 private Number maximumRangeValue; 078 079 /** The range of values. */ 080 private Range rangeBounds; 081 082 /** 083 * Creates a new dataset. 084 */ 085 public DefaultBoxAndWhiskerCategoryDataset() { 086 this.data = new KeyedObjects2D(); 087 this.minimumRangeValue = null; 088 this.maximumRangeValue = null; 089 this.rangeBounds = new Range(0.0, 0.0); 090 } 091 092 /** 093 * Adds a list of values relating to one box-and-whisker entity to the 094 * table. The various median values are calculated. 095 * 096 * @param list a collection of values from which the various medians will 097 * be calculated. 098 * @param rowKey the row key. 099 * @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 }