Frames | No Frames |
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: * Changes 37: * ------- 38: * 05-Aug-2003 : Version 1, contributed by David Browning (DG); 39: * 27-Aug-2003 : Moved from org.jfree.data --> org.jfree.data.statistics (DG); 40: * 12-Nov-2003 : Changed 'data' from private to protected and added a new 'add' 41: * method as proposed by Tim Bardzil. Also removed old code (DG); 42: * 01-Mar-2004 : Added equals() method (DG); 43: * 18-Nov-2004 : Updates for changes in RangeInfo interface (DG); 44: * 11-Jan-2005 : Removed deprecated code in preparation for the 1.0.0 45: * release (DG); 46: * ------------- JFREECHART 1.0.x --------------------------------------------- 47: * 02-Feb-2007 : Removed author tags from all over JFreeChart sources (DG); 48: * 17-Apr-2007 : Fixed bug 1701822 (DG); 49: * 13-Jun-2007 : Fixed error in previous patch (DG); 50: * 28-Sep-2007 : Fixed cloning bug (DG); 51: * 02-Oct-2007 : Fixed bug in updating cached bounds (DG); 52: * 03-Oct-2007 : Fixed another bug in updating cached bounds, added removal 53: * methods (DG); 54: * 55: */ 56: 57: package org.jfree.data.statistics; 58: 59: import java.util.List; 60: 61: import org.jfree.data.KeyedObjects2D; 62: import org.jfree.data.Range; 63: import org.jfree.data.RangeInfo; 64: import org.jfree.data.general.AbstractDataset; 65: import org.jfree.data.general.DatasetChangeEvent; 66: import org.jfree.util.ObjectUtilities; 67: import org.jfree.util.PublicCloneable; 68: 69: /** 70: * A convenience class that provides a default implementation of the 71: * {@link BoxAndWhiskerCategoryDataset} interface. 72: */ 73: public class DefaultBoxAndWhiskerCategoryDataset extends AbstractDataset 74: implements BoxAndWhiskerCategoryDataset, RangeInfo, PublicCloneable { 75: 76: /** Storage for the data. */ 77: protected KeyedObjects2D data; 78: 79: /** The minimum range value. */ 80: private double minimumRangeValue; 81: 82: /** The row index for the cell that the minimum range value comes from. */ 83: private int minimumRangeValueRow; 84: 85: /** 86: * The column index for the cell that the minimum range value comes from. 87: */ 88: private int minimumRangeValueColumn; 89: 90: /** The maximum range value. */ 91: private double maximumRangeValue; 92: 93: /** The row index for the cell that the maximum range value comes from. */ 94: private int maximumRangeValueRow; 95: 96: /** 97: * The column index for the cell that the maximum range value comes from. 98: */ 99: private int maximumRangeValueColumn; 100: 101: /** 102: * Creates a new dataset. 103: */ 104: public DefaultBoxAndWhiskerCategoryDataset() { 105: this.data = new KeyedObjects2D(); 106: this.minimumRangeValue = Double.NaN; 107: this.minimumRangeValueRow = -1; 108: this.minimumRangeValueColumn = -1; 109: this.maximumRangeValue = Double.NaN; 110: this.maximumRangeValueRow = -1; 111: this.maximumRangeValueColumn = -1; 112: } 113: 114: /** 115: * Adds a list of values relating to one box-and-whisker entity to the 116: * table. The various median values are calculated. 117: * 118: * @param list a collection of values from which the various medians will 119: * be calculated. 120: * @param rowKey the row key (<code>null</code> not permitted). 121: * @param columnKey the column key (<code>null</code> not permitted). 122: * 123: * @see #add(BoxAndWhiskerItem, Comparable, Comparable) 124: */ 125: public void add(List list, Comparable rowKey, Comparable columnKey) { 126: BoxAndWhiskerItem item = BoxAndWhiskerCalculator 127: .calculateBoxAndWhiskerStatistics(list); 128: add(item, rowKey, columnKey); 129: } 130: 131: /** 132: * Adds a list of values relating to one Box and Whisker entity to the 133: * table. The various median values are calculated. 134: * 135: * @param item a box and whisker item (<code>null</code> not permitted). 136: * @param rowKey the row key (<code>null</code> not permitted). 137: * @param columnKey the column key (<code>null</code> not permitted). 138: * 139: * @see #add(List, Comparable, Comparable) 140: */ 141: public void add(BoxAndWhiskerItem item, Comparable rowKey, 142: Comparable columnKey) { 143: 144: this.data.addObject(item, rowKey, columnKey); 145: 146: // update cached min and max values 147: int r = this.data.getRowIndex(rowKey); 148: int c = this.data.getColumnIndex(columnKey); 149: if ((this.maximumRangeValueRow == r && this.maximumRangeValueColumn 150: == c) || (this.minimumRangeValueRow == r 151: && this.minimumRangeValueColumn == c)) { 152: updateBounds(); 153: } 154: else { 155: 156: double minval = Double.NaN; 157: if (item.getMinOutlier() != null) { 158: minval = item.getMinOutlier().doubleValue(); 159: } 160: double maxval = Double.NaN; 161: if (item.getMaxOutlier() != null) { 162: maxval = item.getMaxOutlier().doubleValue(); 163: } 164: 165: if (Double.isNaN(this.maximumRangeValue)) { 166: this.maximumRangeValue = maxval; 167: this.maximumRangeValueRow = r; 168: this.maximumRangeValueColumn = c; 169: } 170: else if (maxval > this.maximumRangeValue) { 171: this.maximumRangeValue = maxval; 172: this.maximumRangeValueRow = r; 173: this.maximumRangeValueColumn = c; 174: } 175: 176: if (Double.isNaN(this.minimumRangeValue)) { 177: this.minimumRangeValue = minval; 178: this.minimumRangeValueRow = r; 179: this.minimumRangeValueColumn = c; 180: } 181: else if (minval < this.minimumRangeValue) { 182: this.minimumRangeValue = minval; 183: this.minimumRangeValueRow = r; 184: this.minimumRangeValueColumn = c; 185: } 186: } 187: 188: fireDatasetChanged(); 189: 190: } 191: 192: /** 193: * Removes an item from the dataset and sends a {@link DatasetChangeEvent} 194: * to all registered listeners. 195: * 196: * @param rowKey the row key (<code>null</code> not permitted). 197: * @param columnKey the column key (<code>null</code> not permitted). 198: * 199: * @see #add(BoxAndWhiskerItem, Comparable, Comparable) 200: * 201: * @since 1.0.7 202: */ 203: public void remove(Comparable rowKey, Comparable columnKey) { 204: // defer null argument checks 205: int r = getRowIndex(rowKey); 206: int c = getColumnIndex(columnKey); 207: this.data.removeObject(rowKey, columnKey); 208: 209: // if this cell held a maximum and/or minimum value, we'll need to 210: // update the cached bounds... 211: if ((this.maximumRangeValueRow == r && this.maximumRangeValueColumn 212: == c) || (this.minimumRangeValueRow == r 213: && this.minimumRangeValueColumn == c)) { 214: updateBounds(); 215: } 216: 217: fireDatasetChanged(); 218: } 219: 220: /** 221: * Removes a row from the dataset and sends a {@link DatasetChangeEvent} 222: * to all registered listeners. 223: * 224: * @param rowIndex the row index. 225: * 226: * @see #removeColumn(int) 227: * 228: * @since 1.0.7 229: */ 230: public void removeRow(int rowIndex) { 231: this.data.removeRow(rowIndex); 232: updateBounds(); 233: fireDatasetChanged(); 234: } 235: 236: /** 237: * Removes a row from the dataset and sends a {@link DatasetChangeEvent} 238: * to all registered listeners. 239: * 240: * @param rowKey the row key. 241: * 242: * @see #removeColumn(Comparable) 243: * 244: * @since 1.0.7 245: */ 246: public void removeRow(Comparable rowKey) { 247: this.data.removeRow(rowKey); 248: updateBounds(); 249: fireDatasetChanged(); 250: } 251: 252: /** 253: * Removes a column from the dataset and sends a {@link DatasetChangeEvent} 254: * to all registered listeners. 255: * 256: * @param columnIndex the column index. 257: * 258: * @see #removeRow(int) 259: * 260: * @since 1.0.7 261: */ 262: public void removeColumn(int columnIndex) { 263: this.data.removeColumn(columnIndex); 264: updateBounds(); 265: fireDatasetChanged(); 266: } 267: 268: /** 269: * Removes a column from the dataset and sends a {@link DatasetChangeEvent} 270: * to all registered listeners. 271: * 272: * @param columnKey the column key. 273: * 274: * @see #removeRow(Comparable) 275: * 276: * @since 1.0.7 277: */ 278: public void removeColumn(Comparable columnKey) { 279: this.data.removeColumn(columnKey); 280: updateBounds(); 281: fireDatasetChanged(); 282: } 283: 284: /** 285: * Clears all data from the dataset and sends a {@link DatasetChangeEvent} 286: * to all registered listeners. 287: * 288: * @since 1.0.7 289: */ 290: public void clear() { 291: this.data.clear(); 292: updateBounds(); 293: fireDatasetChanged(); 294: } 295: 296: /** 297: * Return an item from within the dataset. 298: * 299: * @param row the row index. 300: * @param column the column index. 301: * 302: * @return The item. 303: */ 304: public BoxAndWhiskerItem getItem(int row, int column) { 305: return (BoxAndWhiskerItem) this.data.getObject(row, column); 306: } 307: 308: /** 309: * Returns the value for an item. 310: * 311: * @param row the row index. 312: * @param column the column index. 313: * 314: * @return The value. 315: * 316: * @see #getMedianValue(int, int) 317: * @see #getValue(Comparable, Comparable) 318: */ 319: public Number getValue(int row, int column) { 320: return getMedianValue(row, column); 321: } 322: 323: /** 324: * Returns the value for an item. 325: * 326: * @param rowKey the row key. 327: * @param columnKey the columnKey. 328: * 329: * @return The value. 330: * 331: * @see #getMedianValue(Comparable, Comparable) 332: * @see #getValue(int, int) 333: */ 334: public Number getValue(Comparable rowKey, Comparable columnKey) { 335: return getMedianValue(rowKey, columnKey); 336: } 337: 338: /** 339: * Returns the mean value for an item. 340: * 341: * @param row the row index (zero-based). 342: * @param column the column index (zero-based). 343: * 344: * @return The mean value. 345: * 346: * @see #getItem(int, int) 347: */ 348: public Number getMeanValue(int row, int column) { 349: 350: Number result = null; 351: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(row, 352: column); 353: if (item != null) { 354: result = item.getMean(); 355: } 356: return result; 357: 358: } 359: 360: /** 361: * Returns the mean value for an item. 362: * 363: * @param rowKey the row key. 364: * @param columnKey the column key. 365: * 366: * @return The mean value. 367: * 368: * @see #getItem(int, int) 369: */ 370: public Number getMeanValue(Comparable rowKey, Comparable columnKey) { 371: Number result = null; 372: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 373: rowKey, columnKey); 374: if (item != null) { 375: result = item.getMean(); 376: } 377: return result; 378: } 379: 380: /** 381: * Returns the median value for an item. 382: * 383: * @param row the row index (zero-based). 384: * @param column the column index (zero-based). 385: * 386: * @return The median value. 387: * 388: * @see #getItem(int, int) 389: */ 390: public Number getMedianValue(int row, int column) { 391: Number result = null; 392: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject(row, 393: column); 394: if (item != null) { 395: result = item.getMedian(); 396: } 397: return result; 398: } 399: 400: /** 401: * Returns the median value for an item. 402: * 403: * @param rowKey the row key. 404: * @param columnKey the columnKey. 405: * 406: * @return The median value. 407: * 408: * @see #getItem(int, int) 409: */ 410: public Number getMedianValue(Comparable rowKey, Comparable columnKey) { 411: Number result = null; 412: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 413: rowKey, columnKey); 414: if (item != null) { 415: result = item.getMedian(); 416: } 417: return result; 418: } 419: 420: /** 421: * Returns the first quartile value. 422: * 423: * @param row the row index (zero-based). 424: * @param column the column index (zero-based). 425: * 426: * @return The first quartile value. 427: * 428: * @see #getItem(int, int) 429: */ 430: public Number getQ1Value(int row, int column) { 431: Number result = null; 432: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 433: row, column); 434: if (item != null) { 435: result = item.getQ1(); 436: } 437: return result; 438: } 439: 440: /** 441: * Returns the first quartile value. 442: * 443: * @param rowKey the row key. 444: * @param columnKey the column key. 445: * 446: * @return The first quartile value. 447: * 448: * @see #getItem(int, int) 449: */ 450: public Number getQ1Value(Comparable rowKey, Comparable columnKey) { 451: Number result = null; 452: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 453: rowKey, columnKey); 454: if (item != null) { 455: result = item.getQ1(); 456: } 457: return result; 458: } 459: 460: /** 461: * Returns the third quartile value. 462: * 463: * @param row the row index (zero-based). 464: * @param column the column index (zero-based). 465: * 466: * @return The third quartile value. 467: * 468: * @see #getItem(int, int) 469: */ 470: public Number getQ3Value(int row, int column) { 471: Number result = null; 472: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 473: row, column); 474: if (item != null) { 475: result = item.getQ3(); 476: } 477: return result; 478: } 479: 480: /** 481: * Returns the third quartile value. 482: * 483: * @param rowKey the row key. 484: * @param columnKey the column key. 485: * 486: * @return The third quartile value. 487: * 488: * @see #getItem(int, int) 489: */ 490: public Number getQ3Value(Comparable rowKey, Comparable columnKey) { 491: Number result = null; 492: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 493: rowKey, columnKey); 494: if (item != null) { 495: result = item.getQ3(); 496: } 497: return result; 498: } 499: 500: /** 501: * Returns the column index for a given key. 502: * 503: * @param key the column key (<code>null</code> not permitted). 504: * 505: * @return The column index. 506: * 507: * @see #getColumnKey(int) 508: */ 509: public int getColumnIndex(Comparable key) { 510: return this.data.getColumnIndex(key); 511: } 512: 513: /** 514: * Returns a column key. 515: * 516: * @param column the column index (zero-based). 517: * 518: * @return The column key. 519: * 520: * @see #getColumnIndex(Comparable) 521: */ 522: public Comparable getColumnKey(int column) { 523: return this.data.getColumnKey(column); 524: } 525: 526: /** 527: * Returns the column keys. 528: * 529: * @return The keys. 530: * 531: * @see #getRowKeys() 532: */ 533: public List getColumnKeys() { 534: return this.data.getColumnKeys(); 535: } 536: 537: /** 538: * Returns the row index for a given key. 539: * 540: * @param key the row key (<code>null</code> not permitted). 541: * 542: * @return The row index. 543: * 544: * @see #getRowKey(int) 545: */ 546: public int getRowIndex(Comparable key) { 547: // defer null argument check 548: return this.data.getRowIndex(key); 549: } 550: 551: /** 552: * Returns a row key. 553: * 554: * @param row the row index (zero-based). 555: * 556: * @return The row key. 557: * 558: * @see #getRowIndex(Comparable) 559: */ 560: public Comparable getRowKey(int row) { 561: return this.data.getRowKey(row); 562: } 563: 564: /** 565: * Returns the row keys. 566: * 567: * @return The keys. 568: * 569: * @see #getColumnKeys() 570: */ 571: public List getRowKeys() { 572: return this.data.getRowKeys(); 573: } 574: 575: /** 576: * Returns the number of rows in the table. 577: * 578: * @return The row count. 579: * 580: * @see #getColumnCount() 581: */ 582: public int getRowCount() { 583: return this.data.getRowCount(); 584: } 585: 586: /** 587: * Returns the number of columns in the table. 588: * 589: * @return The column count. 590: * 591: * @see #getRowCount() 592: */ 593: public int getColumnCount() { 594: return this.data.getColumnCount(); 595: } 596: 597: /** 598: * Returns the minimum y-value in the dataset. 599: * 600: * @param includeInterval a flag that determines whether or not the 601: * y-interval is taken into account. 602: * 603: * @return The minimum value. 604: * 605: * @see #getRangeUpperBound(boolean) 606: */ 607: public double getRangeLowerBound(boolean includeInterval) { 608: return this.minimumRangeValue; 609: } 610: 611: /** 612: * Returns the maximum y-value in the dataset. 613: * 614: * @param includeInterval a flag that determines whether or not the 615: * y-interval is taken into account. 616: * 617: * @return The maximum value. 618: * 619: * @see #getRangeLowerBound(boolean) 620: */ 621: public double getRangeUpperBound(boolean includeInterval) { 622: return this.maximumRangeValue; 623: } 624: 625: /** 626: * Returns the range of the values in this dataset's range. 627: * 628: * @param includeInterval a flag that determines whether or not the 629: * y-interval is taken into account. 630: * 631: * @return The range. 632: */ 633: public Range getRangeBounds(boolean includeInterval) { 634: return new Range(this.minimumRangeValue, this.maximumRangeValue); 635: } 636: 637: /** 638: * Returns the minimum regular (non outlier) value for an item. 639: * 640: * @param row the row index (zero-based). 641: * @param column the column index (zero-based). 642: * 643: * @return The minimum regular value. 644: * 645: * @see #getItem(int, int) 646: */ 647: public Number getMinRegularValue(int row, int column) { 648: Number result = null; 649: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 650: row, column); 651: if (item != null) { 652: result = item.getMinRegularValue(); 653: } 654: return result; 655: } 656: 657: /** 658: * Returns the minimum regular (non outlier) value for an item. 659: * 660: * @param rowKey the row key. 661: * @param columnKey the column key. 662: * 663: * @return The minimum regular value. 664: * 665: * @see #getItem(int, int) 666: */ 667: public Number getMinRegularValue(Comparable rowKey, Comparable columnKey) { 668: Number result = null; 669: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 670: rowKey, columnKey); 671: if (item != null) { 672: result = item.getMinRegularValue(); 673: } 674: return result; 675: } 676: 677: /** 678: * Returns the maximum regular (non outlier) value for an item. 679: * 680: * @param row the row index (zero-based). 681: * @param column the column index (zero-based). 682: * 683: * @return The maximum regular value. 684: * 685: * @see #getItem(int, int) 686: */ 687: public Number getMaxRegularValue(int row, int column) { 688: Number result = null; 689: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 690: row, column); 691: if (item != null) { 692: result = item.getMaxRegularValue(); 693: } 694: return result; 695: } 696: 697: /** 698: * Returns the maximum regular (non outlier) value for an item. 699: * 700: * @param rowKey the row key. 701: * @param columnKey the column key. 702: * 703: * @return The maximum regular value. 704: * 705: * @see #getItem(int, int) 706: */ 707: public Number getMaxRegularValue(Comparable rowKey, Comparable columnKey) { 708: Number result = null; 709: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 710: rowKey, columnKey); 711: if (item != null) { 712: result = item.getMaxRegularValue(); 713: } 714: return result; 715: } 716: 717: /** 718: * Returns the minimum outlier (non farout) value for an item. 719: * 720: * @param row the row index (zero-based). 721: * @param column the column index (zero-based). 722: * 723: * @return The minimum outlier. 724: * 725: * @see #getItem(int, int) 726: */ 727: public Number getMinOutlier(int row, int column) { 728: Number result = null; 729: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 730: row, column); 731: if (item != null) { 732: result = item.getMinOutlier(); 733: } 734: return result; 735: } 736: 737: /** 738: * Returns the minimum outlier (non farout) value for an item. 739: * 740: * @param rowKey the row key. 741: * @param columnKey the column key. 742: * 743: * @return The minimum outlier. 744: * 745: * @see #getItem(int, int) 746: */ 747: public Number getMinOutlier(Comparable rowKey, Comparable columnKey) { 748: Number result = null; 749: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 750: rowKey, columnKey); 751: if (item != null) { 752: result = item.getMinOutlier(); 753: } 754: return result; 755: } 756: 757: /** 758: * Returns the maximum outlier (non farout) value for an item. 759: * 760: * @param row the row index (zero-based). 761: * @param column the column index (zero-based). 762: * 763: * @return The maximum outlier. 764: * 765: * @see #getItem(int, int) 766: */ 767: public Number getMaxOutlier(int row, int column) { 768: Number result = null; 769: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 770: row, column); 771: if (item != null) { 772: result = item.getMaxOutlier(); 773: } 774: return result; 775: } 776: 777: /** 778: * Returns the maximum outlier (non farout) value for an item. 779: * 780: * @param rowKey the row key. 781: * @param columnKey the column key. 782: * 783: * @return The maximum outlier. 784: * 785: * @see #getItem(int, int) 786: */ 787: public Number getMaxOutlier(Comparable rowKey, Comparable columnKey) { 788: Number result = null; 789: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 790: rowKey, columnKey); 791: if (item != null) { 792: result = item.getMaxOutlier(); 793: } 794: return result; 795: } 796: 797: /** 798: * Returns a list of outlier values for an item. 799: * 800: * @param row the row index (zero-based). 801: * @param column the column index (zero-based). 802: * 803: * @return A list of outlier values. 804: * 805: * @see #getItem(int, int) 806: */ 807: public List getOutliers(int row, int column) { 808: List result = null; 809: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 810: row, column); 811: if (item != null) { 812: result = item.getOutliers(); 813: } 814: return result; 815: } 816: 817: /** 818: * Returns a list of outlier values for an item. 819: * 820: * @param rowKey the row key. 821: * @param columnKey the column key. 822: * 823: * @return A list of outlier values. 824: * 825: * @see #getItem(int, int) 826: */ 827: public List getOutliers(Comparable rowKey, Comparable columnKey) { 828: List result = null; 829: BoxAndWhiskerItem item = (BoxAndWhiskerItem) this.data.getObject( 830: rowKey, columnKey); 831: if (item != null) { 832: result = item.getOutliers(); 833: } 834: return result; 835: } 836: 837: /** 838: * Resets the cached bounds, by iterating over the entire dataset to find 839: * the current bounds. 840: */ 841: private void updateBounds() { 842: this.minimumRangeValue = Double.NaN; 843: this.minimumRangeValueRow = -1; 844: this.minimumRangeValueColumn = -1; 845: this.maximumRangeValue = Double.NaN; 846: this.maximumRangeValueRow = -1; 847: this.maximumRangeValueColumn = -1; 848: int rowCount = getRowCount(); 849: int columnCount = getColumnCount(); 850: for (int r = 0; r < rowCount; r++) { 851: for (int c = 0; c < columnCount; c++) { 852: BoxAndWhiskerItem item = getItem(r, c); 853: if (item != null) { 854: Number min = item.getMinOutlier(); 855: if (min != null) { 856: double minv = min.doubleValue(); 857: if (!Double.isNaN(minv)) { 858: if (minv < this.minimumRangeValue || Double.isNaN( 859: this.minimumRangeValue)) { 860: this.minimumRangeValue = minv; 861: this.minimumRangeValueRow = r; 862: this.minimumRangeValueColumn = c; 863: } 864: } 865: } 866: Number max = item.getMaxOutlier(); 867: if (max != null) { 868: double maxv = max.doubleValue(); 869: if (!Double.isNaN(maxv)) { 870: if (maxv > this.maximumRangeValue || Double.isNaN( 871: this.maximumRangeValue)) { 872: this.maximumRangeValue = maxv; 873: this.maximumRangeValueRow = r; 874: this.maximumRangeValueColumn = c; 875: } 876: } 877: } 878: } 879: } 880: } 881: } 882: 883: /** 884: * Tests this dataset for equality with an arbitrary object. 885: * 886: * @param obj the object to test against (<code>null</code> permitted). 887: * 888: * @return A boolean. 889: */ 890: public boolean equals(Object obj) { 891: if (obj == this) { 892: return true; 893: } 894: if (obj instanceof DefaultBoxAndWhiskerCategoryDataset) { 895: DefaultBoxAndWhiskerCategoryDataset dataset 896: = (DefaultBoxAndWhiskerCategoryDataset) obj; 897: return ObjectUtilities.equal(this.data, dataset.data); 898: } 899: return false; 900: } 901: 902: /** 903: * Returns a clone of this dataset. 904: * 905: * @return A clone. 906: * 907: * @throws CloneNotSupportedException if cloning is not possible. 908: */ 909: public Object clone() throws CloneNotSupportedException { 910: DefaultBoxAndWhiskerCategoryDataset clone 911: = (DefaultBoxAndWhiskerCategoryDataset) super.clone(); 912: clone.data = (KeyedObjects2D) this.data.clone(); 913: return clone; 914: } 915: 916: }