    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2011, 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     * [Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    025     * Other names may be trademarks of their respective owners.]
    026     *
    027     * -----------------
    028     * XYBarDataset.java
    029     * -----------------
    030     * (C) Copyright 2004-2008, by Object Refinery Limited and Contributors.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * Changes
    036     * -------
    037     * 02-Mar-2004 : Version 1 (DG);
    038     * 05-May-2004 : Now extends AbstractIntervalXYDataset (DG);
    039     * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
    040     *               getYValue() (DG);
    041     * ------------- JFREECHART 1.0.x ---------------------------------------------
    042     * 25-Jan-2007 : Added some accessor methods, plus new equals() and clone()
    043     *               overrides (DG);
    044     * 30-Jan-2007 : Added method overrides to prevent unnecessary object
    045     *               creation (DG);
    046     * 22-Apr-2008 : Implemented PublicCloneable (DG);
    047     *
    048     */
    049
    050    package org.jfree.data.xy;
    051
    052    import org.jfree.data.general.DatasetChangeEvent;
    053    import org.jfree.data.general.DatasetChangeListener;
    054    import org.jfree.util.PublicCloneable;
    055
    056    /**
    057     * A dataset wrapper class that converts a standard {@link XYDataset} into an
    058     * {@link IntervalXYDataset} suitable for use in creating XY bar charts.
    059     */
    060    public class XYBarDataset extends AbstractIntervalXYDataset
    061            implements IntervalXYDataset, DatasetChangeListener, PublicCloneable {
    062
    063        /** The underlying dataset. */
    064        private XYDataset underlying;
    065
    066        /** The bar width. */
    067        private double barWidth;
    068
    069        /**
    070         * Creates a new dataset.
    071         *
    072         * @param underlying  the underlying dataset (<code>null</code> not
    073         *     permitted).
    074         * @param barWidth  the width of the bars.
    075         */
    076        public XYBarDataset(XYDataset underlying, double barWidth) {
    077            this.underlying = underlying;
    078            this.underlying.addChangeListener(this);
    079            this.barWidth = barWidth;
    080        }
    081
    082        /**
    083         * Returns the underlying dataset that was specified via the constructor.
    084         *
    085         * @return The underlying dataset (never <code>null</code>).
    086         *
    087         * @since 1.0.4
    088         */
    089        public XYDataset getUnderlyingDataset() {
    090            return this.underlying;
    091        }
    092
    093        /**
    094         * Returns the bar width.
    095         *
    096         * @return The bar width.
    097         *
    098         * @see #setBarWidth(double)
    099         * @since 1.0.4
    100         */
    101        public double getBarWidth() {
    102            return this.barWidth;
    103        }
    104
    105        /**
    106         * Sets the bar width and sends a {@link DatasetChangeEvent} to all
    107         * registered listeners.
    108         *
    109         * @param barWidth  the bar width.
    110         *
    111         * @see #getBarWidth()
    112         * @since 1.0.4
    113         */
    114        public void setBarWidth(double barWidth) {
    115            this.barWidth = barWidth;
    116            notifyListeners(new DatasetChangeEvent(this, this));
    117        }
    118
    119        /**
    120         * Returns the number of series in the dataset.
    121         *
    122         * @return The series count.
    123         */
    124        public int getSeriesCount() {
    125            return this.underlying.getSeriesCount();
    126        }
    127
    128        /**
    129         * Returns the key for a series.
    130         *
    131         * @param series  the series index (in the range <code>0</code> to
    132         *     <code>getSeriesCount() - 1</code>).
    133         *
    134         * @return The series key.
    135         */
    136        public Comparable getSeriesKey(int series) {
    137            return this.underlying.getSeriesKey(series);
    138        }
    139
    140        /**
    141         * Returns the number of items in a series.
    142         *
    143         * @param series  the series index (zero-based).
    144         *
    145         * @return The item count.
    146         */
    147        public int getItemCount(int series) {
    148            return this.underlying.getItemCount(series);
    149        }
    150
    151        /**
    152         * Returns the x-value for an item within a series.
    153         *
    154         * @param series  the series index (zero-based).
    155         * @param item  the item index (zero-based).
    156         *
    157         * @return The x-value.
    158         *
    159         * @see #getXValue(int, int)
    160         */
    161        public Number getX(int series, int item) {
    162            return this.underlying.getX(series, item);
    163        }
    164
    165        /**
    166         * Returns the x-value (as a double primitive) for an item within a series.
    167         *
    168         * @param series  the series index (zero-based).
    169         * @param item  the item index (zero-based).
    170         *
    171         * @return The value.
    172         *
    173         * @see #getX(int, int)
    174         */
    175        public double getXValue(int series, int item) {
    176            return this.underlying.getXValue(series, item);
    177        }
    178
    179        /**
    180         * Returns the y-value for an item within a series.
    181         *
    182         * @param series  the series index (zero-based).
    183         * @param item  the item index (zero-based).
    184         *
    185         * @return The y-value (possibly <code>null</code>).
    186         *
    187         * @see #getYValue(int, int)
    188         */
    189        public Number getY(int series, int item) {
    190            return this.underlying.getY(series, item);
    191        }
    192
    193        /**
    194         * Returns the y-value (as a double primitive) for an item within a series.
    195         *
    196         * @param series  the series index (zero-based).
    197         * @param item  the item index (zero-based).
    198         *
    199         * @return The value.
    200         *
    201         * @see #getY(int, int)
    202         */
    203        public double getYValue(int series, int item) {
    204            return this.underlying.getYValue(series, item);
    205        }
    206
    207        /**
    208         * Returns the starting X value for the specified series and item.
    209         *
    210         * @param series  the series index (zero-based).
    211         * @param item  the item index (zero-based).
    212         *
    213         * @return The value.
    214         */
    215        public Number getStartX(int series, int item) {
    216            Number result = null;
    217            Number xnum = this.underlying.getX(series, item);
    218            if (xnum != null) {
    219                 result = new Double(xnum.doubleValue() - this.barWidth / 2.0);
    220            }
    221            return result;
    222        }
    223
    224        /**
    225         * Returns the starting x-value (as a double primitive) for an item within
    226         * a series.
    227         *
    228         * @param series  the series index (zero-based).
    229         * @param item  the item index (zero-based).
    230         *
    231         * @return The value.
    232         *
    233         * @see #getXValue(int, int)
    234         */
    235        public double getStartXValue(int series, int item) {
    236            return getXValue(series, item) - this.barWidth / 2.0;
    237        }
    238
    239        /**
    240         * Returns the ending X value for the specified series and item.
    241         *
    242         * @param series  the series index (zero-based).
    243         * @param item  the item index (zero-based).
    244         *
    245         * @return The value.
    246         */
    247        public Number getEndX(int series, int item) {
    248            Number result = null;
    249            Number xnum = this.underlying.getX(series, item);
    250            if (xnum != null) {
    251                 result = new Double(xnum.doubleValue() + this.barWidth / 2.0);
    252            }
    253            return result;
    254        }
    255
    256        /**
    257         * Returns the ending x-value (as a double primitive) for an item within
    258         * a series.
    259         *
    260         * @param series  the series index (zero-based).
    261         * @param item  the item index (zero-based).
    262         *
    263         * @return The value.
    264         *
    265         * @see #getXValue(int, int)
    266         */
    267        public double getEndXValue(int series, int item) {
    268            return getXValue(series, item) + this.barWidth / 2.0;
    269        }
    270
    271        /**
    272         * Returns the starting Y value for the specified series and item.
    273         *
    274         * @param series  the series index (zero-based).
    275         * @param item  the item index (zero-based).
    276         *
    277         * @return The value.
    278         */
    279        public Number getStartY(int series, int item) {
    280            return this.underlying.getY(series, item);
    281        }
    282
    283        /**
    284         * Returns the starting y-value (as a double primitive) for an item within
    285         * a series.
    286         *
    287         * @param series  the series index (zero-based).
    288         * @param item  the item index (zero-based).
    289         *
    290         * @return The value.
    291         *
    292         * @see #getYValue(int, int)
    293         */
    294        public double getStartYValue(int series, int item) {
    295            return getYValue(series, item);
    296        }
    297
    298        /**
    299         * Returns the ending Y value for the specified series and item.
    300         *
    301         * @param series  the series index (zero-based).
    302         * @param item  the item index (zero-based).
    303         *
    304         * @return The value.
    305         */
    306        public Number getEndY(int series, int item) {
    307            return this.underlying.getY(series, item);
    308        }
    309
    310        /**
    311         * Returns the ending y-value (as a double primitive) for an item within
    312         * a series.
    313         *
    314         * @param series  the series index (zero-based).
    315         * @param item  the item index (zero-based).
    316         *
    317         * @return The value.
    318         *
    319         * @see #getYValue(int, int)
    320         */
    321        public double getEndYValue(int series, int item) {
    322            return getYValue(series, item);
    323        }
    324
    325        /**
    326         * Receives notification of an dataset change event.
    327         *
    328         * @param event  information about the event.
    329         */
    330        public void datasetChanged(DatasetChangeEvent event) {
    331            notifyListeners(event);
    332        }
    333
    334        /**
    335         * Tests this dataset for equality with an arbitrary object.
    336         *
    337         * @param obj  the object (<code>null</code> permitted).
    338         *
    339         * @return A boolean.
    340         */
    341        public boolean equals(Object obj) {
    342            if (obj == this) {
    343                return true;
    344            }
    345            if (!(obj instanceof XYBarDataset)) {
    346                return false;
    347            }
    348            XYBarDataset that = (XYBarDataset) obj;
    349            if (!this.underlying.equals(that.underlying)) {
    350                return false;
    351            }
    352            if (this.barWidth != that.barWidth) {
    353                return false;
    354            }
    355            return true;
    356        }
    357
    358        /**
    359         * Returns an independent copy of the dataset.  Note that:
    360         * <ul>
    361         * <li>the underlying dataset is only cloned if it implements the
    362         * {@link PublicCloneable} interface;</li>
    363         * <li>the listeners registered with this dataset are not carried over to
    364         * the cloned dataset.</li>
    365         * </ul>
    366         *
    367         * @return An independent copy of the dataset.
    368         *
    369         * @throws CloneNotSupportedException if the dataset cannot be cloned for
    370         *         any reason.
    371         */
    372        public Object clone() throws CloneNotSupportedException {
    373            XYBarDataset clone = (XYBarDataset) super.clone();
    374            if (this.underlying instanceof PublicCloneable) {
    375                PublicCloneable pc = (PublicCloneable) this.underlying;
    376                clone.underlying = (XYDataset) pc.clone();
    377            }
    378            return clone;
    379        }
    380
    381    }