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