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.3 2007/02/02 15:50:24 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 * 051 */ 052 053 package org.jfree.data.statistics; 054 055 import java.util.List; 056 057 import org.jfree.data.KeyedObjects2D; 058 import org.jfree.data.Range; 059 import org.jfree.data.RangeInfo; 060 import org.jfree.data.general.AbstractDataset; 061 import org.jfree.util.ObjectUtilities; 062 063 /** 064 * A convenience class that provides a default implementation of the 065 * {@link BoxAndWhiskerCategoryDataset} interface. 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 (<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 }