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