    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2008, 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     * XYIntervalSeriesCollection.java
    029     * -------------------------------
    030     * (C) Copyright 2006-2008, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   -;
    034     *
    035     * Changes
    036     * -------
    037     * 20-Oct-2006 : Version 1 (DG);
    038     * 13-Feb-2007 : Provided a number of method overrides that enhance
    039     *               performance, and added a proper clone()
    040     *               implementation (DG);
    041     * 18-Jan-2008 : Added removeSeries() and removeAllSeries() methods (DG);
    042     * 22-Apr-2008 : Implemented PublicCloneable (DG);
    043     *
    044     */
    045
    046    package org.jfree.data.xy;
    047
    048    import java.io.Serializable;
    049    import java.util.List;
    050
    051    import org.jfree.data.general.DatasetChangeEvent;
    052    import org.jfree.util.ObjectUtilities;
    053    import org.jfree.util.PublicCloneable;
    054
    055    /**
    056     * A collection of {@link XYIntervalSeries} objects.
    057     *
    058     * @since 1.0.3
    059     *
    060     * @see XYIntervalSeries
    061     */
    062    public class XYIntervalSeriesCollection extends AbstractIntervalXYDataset
    063            implements IntervalXYDataset, PublicCloneable, Serializable {
    064
    065        /** Storage for the data series. */
    066        private List data;
    067
    068        /**
    069         * Creates a new instance of <code>XIntervalSeriesCollection</code>.
    070         */
    071        public XYIntervalSeriesCollection() {
    072            this.data = new java.util.ArrayList();
    073        }
    074
    075        /**
    076         * Adds a series to the collection and sends a {@link DatasetChangeEvent}
    077         * to all registered listeners.
    078         *
    079         * @param series  the series (<code>null</code> not permitted).
    080         */
    081        public void addSeries(XYIntervalSeries series) {
    082            if (series == null) {
    083                throw new IllegalArgumentException("Null 'series' argument.");
    084            }
    085            this.data.add(series);
    086            series.addChangeListener(this);
    087            fireDatasetChanged();
    088        }
    089
    090        /**
    091         * Returns the number of series in the collection.
    092         *
    093         * @return The series count.
    094         */
    095        public int getSeriesCount() {
    096            return this.data.size();
    097        }
    098
    099        /**
    100         * Returns a series from the collection.
    101         *
    102         * @param series  the series index (zero-based).
    103         *
    104         * @return The series.
    105         *
    106         * @throws IllegalArgumentException if <code>series</code> is not in the
    107         *     range <code>0</code> to <code>getSeriesCount() - 1</code>.
    108         */
    109        public XYIntervalSeries getSeries(int series) {
    110            if ((series < 0) || (series >= getSeriesCount())) {
    111                throw new IllegalArgumentException("Series index out of bounds");
    112            }
    113            return (XYIntervalSeries) this.data.get(series);
    114        }
    115
    116        /**
    117         * Returns the key for a series.
    118         *
    119         * @param series  the series index (in the range <code>0</code> to
    120         *     <code>getSeriesCount() - 1</code>).
    121         *
    122         * @return The key for a series.
    123         *
    124         * @throws IllegalArgumentException if <code>series</code> is not in the
    125         *     specified range.
    126         */
    127        public Comparable getSeriesKey(int series) {
    128            // defer argument checking
    129            return getSeries(series).getKey();
    130        }
    131
    132        /**
    133         * Returns the number of items in the specified series.
    134         *
    135         * @param series  the series (zero-based index).
    136         *
    137         * @return The item count.
    138         *
    139         * @throws IllegalArgumentException if <code>series</code> is not in the
    140         *     range <code>0</code> to <code>getSeriesCount() - 1</code>.
    141         */
    142        public int getItemCount(int series) {
    143            // defer argument checking
    144            return getSeries(series).getItemCount();
    145        }
    146
    147        /**
    148         * Returns the x-value for an item within a series.
    149         *
    150         * @param series  the series index.
    151         * @param item  the item index.
    152         *
    153         * @return The x-value.
    154         */
    155        public Number getX(int series, int item) {
    156            XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
    157            return s.getX(item);
    158        }
    159
    160        /**
    161         * Returns the start x-value (as a double primitive) for an item within a
    162         * series.
    163         *
    164         * @param series  the series index (zero-based).
    165         * @param item  the item index (zero-based).
    166         *
    167         * @return The value.
    168         */
    169        public double getStartXValue(int series, int item) {
    170            XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
    171            return s.getXLowValue(item);
    172        }
    173
    174        /**
    175         * Returns the end x-value (as a double primitive) for an item within a
    176         * series.
    177         *
    178         * @param series  the series index (zero-based).
    179         * @param item  the item index (zero-based).
    180         *
    181         * @return The value.
    182         */
    183        public double getEndXValue(int series, int item) {
    184            XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
    185            return s.getXHighValue(item);
    186        }
    187
    188        /**
    189         * Returns the y-value (as a double primitive) for an item within a
    190         * series.
    191         *
    192         * @param series  the series index (zero-based).
    193         * @param item  the item index (zero-based).
    194         *
    195         * @return The value.
    196         */
    197        public double getYValue(int series, int item) {
    198            XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
    199            return s.getYValue(item);
    200        }
    201
    202        /**
    203         * Returns the start y-value (as a double primitive) for an item within a
    204         * series.
    205         *
    206         * @param series  the series index (zero-based).
    207         * @param item  the item index (zero-based).
    208         *
    209         * @return The value.
    210         */
    211        public double getStartYValue(int series, int item) {
    212            XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
    213            return s.getYLowValue(item);
    214        }
    215
    216        /**
    217         * Returns the end y-value (as a double primitive) for an item within a
    218         * series.
    219         *
    220         * @param series  the series (zero-based index).
    221         * @param item  the item (zero-based index).
    222         *
    223         * @return The value.
    224         */
    225        public double getEndYValue(int series, int item) {
    226            XYIntervalSeries s = (XYIntervalSeries) this.data.get(series);
    227            return s.getYHighValue(item);
    228        }
    229
    230        /**
    231         * Returns the y-value for an item within a series.
    232         *
    233         * @param series  the series index.
    234         * @param item  the item index.
    235         *
    236         * @return The y-value.
    237         */
    238        public Number getY(int series, int item) {
    239            return new Double(getYValue(series, item));
    240        }
    241
    242        /**
    243         * Returns the start x-value for an item within a series.
    244         *
    245         * @param series  the series index.
    246         * @param item  the item index.
    247         *
    248         * @return The x-value.
    249         */
    250        public Number getStartX(int series, int item) {
    251            return new Double(getStartXValue(series, item));
    252        }
    253
    254        /**
    255         * Returns the end x-value for an item within a series.
    256         *
    257         * @param series  the series index.
    258         * @param item  the item index.
    259         *
    260         * @return The x-value.
    261         */
    262        public Number getEndX(int series, int item) {
    263            return new Double(getEndXValue(series, item));
    264        }
    265
    266        /**
    267         * Returns the start y-value for an item within a series.  This method
    268         * maps directly to {@link #getY(int, int)}.
    269         *
    270         * @param series  the series index.
    271         * @param item  the item index.
    272         *
    273         * @return The start y-value.
    274         */
    275        public Number getStartY(int series, int item) {
    276            return new Double(getStartYValue(series, item));
    277        }
    278
    279        /**
    280         * Returns the end y-value for an item within a series.  This method
    281         * maps directly to {@link #getY(int, int)}.
    282         *
    283         * @param series  the series index.
    284         * @param item  the item index.
    285         *
    286         * @return The end y-value.
    287         */
    288        public Number getEndY(int series, int item) {
    289            return new Double(getEndYValue(series, item));
    290        }
    291
    292        /**
    293         * Removes a series from the collection and sends a
    294         * {@link DatasetChangeEvent} to all registered listeners.
    295         *
    296         * @param series  the series index (zero-based).
    297         *
    298         * @since 1.0.10
    299         */
    300        public void removeSeries(int series) {
    301            if ((series < 0) || (series >= getSeriesCount())) {
    302                throw new IllegalArgumentException("Series index out of bounds.");
    303            }
    304            XYIntervalSeries ts = (XYIntervalSeries) this.data.get(series);
    305            ts.removeChangeListener(this);
    306            this.data.remove(series);
    307            fireDatasetChanged();
    308        }
    309
    310        /**
    311         * Removes a series from the collection and sends a
    312         * {@link DatasetChangeEvent} to all registered listeners.
    313         *
    314         * @param series  the series (<code>null</code> not permitted).
    315         *
    316         * @since 1.0.10
    317         */
    318        public void removeSeries(XYIntervalSeries series) {
    319            if (series == null) {
    320                throw new IllegalArgumentException("Null 'series' argument.");
    321            }
    322            if (this.data.contains(series)) {
    323                series.removeChangeListener(this);
    324                this.data.remove(series);
    325                fireDatasetChanged();
    326            }
    327        }
    328
    329        /**
    330         * Removes all the series from the collection and sends a
    331         * {@link DatasetChangeEvent} to all registered listeners.
    332         *
    333         * @since 1.0.10
    334         */
    335        public void removeAllSeries() {
    336            // Unregister the collection as a change listener to each series in
    337            // the collection.
    338            for (int i = 0; i < this.data.size(); i++) {
    339              XYIntervalSeries series = (XYIntervalSeries) this.data.get(i);
    340              series.removeChangeListener(this);
    341            }
    342            this.data.clear();
    343            fireDatasetChanged();
    344        }
    345
    346        /**
    347         * Tests this instance for equality with an arbitrary object.
    348         *
    349         * @param obj  the object (<code>null</code> permitted).
    350         *
    351         * @return A boolean.
    352         */
    353        public boolean equals(Object obj) {
    354            if (obj == this) {
    355                return true;
    356            }
    357            if (!(obj instanceof XYIntervalSeriesCollection)) {
    358                return false;
    359            }
    360            XYIntervalSeriesCollection that = (XYIntervalSeriesCollection) obj;
    361            return ObjectUtilities.equal(this.data, that.data);
    362        }
    363
    364        /**
    365         * Returns a clone of this dataset.
    366         *
    367         * @return A clone of this dataset.
    368         *
    369         * @throws CloneNotSupportedException if there is a problem cloning.
    370         */
    371        public Object clone() throws CloneNotSupportedException {
    372            XYIntervalSeriesCollection clone
    373                    = (XYIntervalSeriesCollection) super.clone();
    374            int seriesCount = getSeriesCount();
    375            clone.data = new java.util.ArrayList(seriesCount);
    376            for (int i = 0; i < this.data.size(); i++) {
    377                clone.data.set(i, getSeries(i).clone());
    378            }
    379            return clone;
    380        }
    381
    382    }