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     * MatrixSeriesCollection.java
029     * ---------------------------
030     * (C) Copyright 2003-2007, by Barak Naveh and Contributors.
031     *
032     * Original Author:  Barak Naveh;;
033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
034     *
035     * Changes
036     * -------
037     * 10-Jul-2003 : Version 1 contributed by Barak Naveh (DG);
038     * 05-May-2004 : Now extends AbstractXYZDataset (DG);
039     * 15-Jul-2004 : Switched getZ() and getZValue() methods (DG);
040     * ------------- JFREECHART 1.0.x ---------------------------------------------
041     * 27-Nov-2006 : Added clone() override (DG);
042     * 02-Feb-2007 : Removed author tags all over JFreeChart sources (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.util.ObjectUtilities;
052    
053    /**
054     * Represents a collection of {@link MatrixSeries} that can be used as a 
055     * dataset.
056     *
057     * @see org.jfree.data.xy.MatrixSeries
058     */
059    public class MatrixSeriesCollection extends AbstractXYZDataset
060                                        implements XYZDataset, Serializable {
061        
062        /** For serialization. */
063        private static final long serialVersionUID = -3197705779242543945L;
064        
065        /** The series that are included in the collection. */
066        private List seriesList;
067    
068        /**
069         * Constructs an empty dataset.
070         */
071        public MatrixSeriesCollection() {
072            this(null);
073        }
074    
075    
076        /**
077         * Constructs a dataset and populates it with a single matrix series.
078         *
079         * @param series the time series.
080         */
081        public MatrixSeriesCollection(MatrixSeries series) {
082            this.seriesList = new java.util.ArrayList();
083    
084            if (series != null) {
085                this.seriesList.add(series);
086                series.addChangeListener(this);
087            }
088        }
089    
090        /**
091         * Returns the number of items in the specified series.
092         *
093         * @param seriesIndex zero-based series index.
094         *
095         * @return The number of items in the specified series.
096         */
097        public int getItemCount(int seriesIndex) {
098            return getSeries(seriesIndex).getItemCount();
099        }
100    
101    
102        /**
103         * Returns the series having the specified index.
104         *
105         * @param seriesIndex zero-based series index.
106         *
107         * @return The series.
108         *
109         * @throws IllegalArgumentException
110         */
111        public MatrixSeries getSeries(int seriesIndex) {
112            if ((seriesIndex < 0) || (seriesIndex > getSeriesCount())) {
113                throw new IllegalArgumentException("Index outside valid range.");
114            }
115    
116            MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
117    
118            return series;
119        }
120    
121    
122        /**
123         * Returns the number of series in the collection.
124         *
125         * @return The number of series in the collection.
126         */
127        public int getSeriesCount() {
128            return this.seriesList.size();
129        }
130    
131    
132        /**
133         * Returns the key for a series.
134         *
135         * @param seriesIndex zero-based series index.
136         *
137         * @return The key for a series.
138         */
139        public Comparable getSeriesKey(int seriesIndex) {
140            return getSeries(seriesIndex).getKey();
141        }
142    
143    
144        /**
145         * Returns the j index value of the specified Mij matrix item in the
146         * specified matrix series.
147         *
148         * @param seriesIndex zero-based series index.
149         * @param itemIndex zero-based item index.
150         *
151         * @return The j index value for the specified matrix item.
152         *
153         * @see org.jfree.data.xy.XYDataset#getXValue(int, int)
154         */
155        public Number getX(int seriesIndex, int itemIndex) {
156            MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
157            int x = series.getItemColumn(itemIndex);
158    
159            return new Integer(x); // I know it's bad to create object. better idea?
160        }
161    
162    
163        /**
164         * Returns the i index value of the specified Mij matrix item in the
165         * specified matrix series.
166         *
167         * @param seriesIndex zero-based series index.
168         * @param itemIndex zero-based item index.
169         *
170         * @return The i index value for the specified matrix item.
171         *
172         * @see org.jfree.data.xy.XYDataset#getYValue(int, int)
173         */
174        public Number getY(int seriesIndex, int itemIndex) {
175            MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
176            int y = series.getItemRow(itemIndex);
177    
178            return new Integer(y); // I know it's bad to create object. better idea?
179        }
180    
181    
182        /**
183         * Returns the Mij item value of the specified Mij matrix item in the
184         * specified matrix series.
185         *
186         * @param seriesIndex the series (zero-based index).
187         * @param itemIndex zero-based item index.
188         *
189         * @return The Mij item value for the specified matrix item.
190         *
191         * @see org.jfree.data.xy.XYZDataset#getZValue(int, int)
192         */
193        public Number getZ(int seriesIndex, int itemIndex) {
194            MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
195            Number z = series.getItem(itemIndex);
196            return z;
197        }
198    
199    
200        /**
201         * Adds a series to the collection.
202         * <P>
203         * Notifies all registered listeners that the dataset has changed.
204         * </p>
205         *
206         * @param series the series.
207         *
208         * @throws IllegalArgumentException
209         */
210        public void addSeries(MatrixSeries series) {
211            // check arguments...
212            if (series == null) {
213                throw new IllegalArgumentException("Cannot add null series.");
214            }
215            // FIXME: Check that there isn't already a series with the same key
216            
217            // add the series...
218            this.seriesList.add(series);
219            series.addChangeListener(this);
220            fireDatasetChanged();
221        }
222    
223    
224        /**
225         * Tests this collection for equality with an arbitrary object.
226         *
227         * @param obj the object.
228         *
229         * @return A boolean.
230         */
231        public boolean equals(Object obj) {
232            if (obj == null) {
233                return false;
234            }
235    
236            if (obj == this) {
237                return true;
238            }
239    
240            if (obj instanceof MatrixSeriesCollection) {
241                MatrixSeriesCollection c = (MatrixSeriesCollection) obj;
242    
243                return ObjectUtilities.equal(this.seriesList, c.seriesList);
244            }
245    
246            return false;
247        }
248    
249        /**
250         * Returns a hash code.
251         * 
252         * @return A hash code.
253         */
254        public int hashCode() {
255            return (this.seriesList != null ? this.seriesList.hashCode() : 0);
256        }
257        
258        /**
259         * Returns a clone of this instance.
260         * 
261         * @return A clone.
262         * 
263         * @throws CloneNotSupportedException if there is a problem.
264         */
265        public Object clone() throws CloneNotSupportedException {
266            MatrixSeriesCollection clone = (MatrixSeriesCollection) super.clone();
267            clone.seriesList = (List) ObjectUtilities.deepClone(this.seriesList);
268            return clone;
269        }
270    
271        /**
272         * Removes all the series from the collection.
273         * <P>
274         * Notifies all registered listeners that the dataset has changed.
275         * </p>
276         */
277        public void removeAllSeries() {
278            // Unregister the collection as a change listener to each series in 
279            // the collection.
280            for (int i = 0; i < this.seriesList.size(); i++) {
281                MatrixSeries series = (MatrixSeries) this.seriesList.get(i);
282                series.removeChangeListener(this);
283            }
284    
285            // Remove all the series from the collection and notify listeners.
286            this.seriesList.clear();
287            fireDatasetChanged();
288        }
289    
290    
291        /**
292         * Removes a series from the collection.
293         * <P>
294         * Notifies all registered listeners that the dataset has changed.
295         * </p>
296         *
297         * @param series the series.
298         *
299         * @throws IllegalArgumentException
300         */
301        public void removeSeries(MatrixSeries series) {
302            // check arguments...
303            if (series == null) {
304                throw new IllegalArgumentException("Cannot remove null series.");
305            }
306    
307            // remove the series...
308            if (this.seriesList.contains(series)) {
309                series.removeChangeListener(this);
310                this.seriesList.remove(series);
311                fireDatasetChanged();
312            }
313        }
314    
315    
316        /**
317         * Removes a series from the collection.
318         * <P>
319         * Notifies all registered listeners that the dataset has changed.
320         *
321         * @param seriesIndex the series (zero based index).
322         *
323         * @throws IllegalArgumentException
324         */
325        public void removeSeries(int seriesIndex) {
326            // check arguments...
327            if ((seriesIndex < 0) || (seriesIndex > getSeriesCount())) {
328                throw new IllegalArgumentException("Index outside valid range.");
329            }
330    
331            // fetch the series, remove the change listener, then remove the series.
332            MatrixSeries series = (MatrixSeries) this.seriesList.get(seriesIndex);
333            series.removeChangeListener(this);
334            this.seriesList.remove(seriesIndex);
335            fireDatasetChanged();
336        }
337        
338    }