    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    }