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     * SubseriesDataset.java
029     * ---------------------
030     * (C) Copyright 2001-2007, by Bill Kelemen and Contributors.
031     *
032     * Original Author:  Bill Kelemen;
033     * Contributor(s):   Sylvain Vieujot;
034     *                   David Gilbert (for Object Refinery Limited);
035     *
036     * Changes
037     * -------
038     * 06-Dec-2001 : Version 1 (BK);
039     * 05-Feb-2002 : Added SignalsDataset (and small change to HighLowDataset
040     *               interface) as requested by Sylvain Vieujot (DG);
041     * 28-Feb-2002 : Fixed bug: missing map[series] in IntervalXYDataset and
042     *               SignalsDataset methods (BK);
043     * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG);
044     * 06-May-2004 : Now extends AbstractIntervalXYDataset (DG);
045     * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
046     *               getYValue() (DG);
047     * 29-Nov-2005 : Removed SignalsDataset (DG);
048     * ------------- JFREECHART 1.0.x ---------------------------------------------
049     * 02-Feb-2007 : Removed author tags from all over JFreeChart sources (DG);
050     *
051     */
052    
053    package org.jfree.data.general;
054    
055    import org.jfree.data.xy.AbstractIntervalXYDataset;
056    import org.jfree.data.xy.IntervalXYDataset;
057    import org.jfree.data.xy.OHLCDataset;
058    import org.jfree.data.xy.XYDataset;
059    
060    /**
061     * This class will create a dataset with one or more series from another
062     * {@link SeriesDataset}.
063     */
064    public class SubSeriesDataset extends AbstractIntervalXYDataset
065            implements OHLCDataset, IntervalXYDataset, CombinationDataset {
066    
067        /** The parent dataset. */
068        private SeriesDataset parent = null;
069    
070        /** Storage for map. */
071        private int[] map;  // maps our series into our parent's
072    
073        /**
074         * Creates a SubSeriesDataset using one or more series from
075         * <code>parent</code>.  The series to use are passed as an array of int.
076         *
077         * @param parent  underlying dataset
078         * @param map  int[] of series from parent to include in this Dataset
079         */
080        public SubSeriesDataset(SeriesDataset parent, int[] map) {
081            this.parent = parent;
082            this.map = map;
083        }
084    
085        /**
086         * Creates a SubSeriesDataset using one series from <code>parent</code>.
087         * The series to is passed as an int.
088         *
089         * @param parent  underlying dataset
090         * @param series  series from parent to include in this Dataset
091         */
092        public SubSeriesDataset(SeriesDataset parent, int series) {
093            this(parent, new int[] {series});
094        }
095    
096        ///////////////////////////////////////////////////////////////////////////
097        // From HighLowDataset
098        ///////////////////////////////////////////////////////////////////////////
099    
100        /**
101         * Returns the high-value for the specified series and item.
102         * <p>
103         * Note: throws <code>ClassCastException</code> if the series if not from a
104         * {@link OHLCDataset}.
105         *
106         * @param series  the index of the series of interest (zero-based).
107         * @param item  the index of the item of interest (zero-based).
108         *
109         * @return The high-value for the specified series and item.
110         */
111        public Number getHigh(int series, int item) {
112            return ((OHLCDataset) this.parent).getHigh(this.map[series], item);
113        }
114    
115        /**
116         * Returns the high-value (as a double primitive) for an item within a
117         * series.
118         *
119         * @param series  the series (zero-based index).
120         * @param item  the item (zero-based index).
121         *
122         * @return The high-value.
123         */
124        public double getHighValue(int series, int item) {
125            double result = Double.NaN;
126            Number high = getHigh(series, item);
127            if (high != null) {
128                result = high.doubleValue();
129            }
130            return result;
131        }
132    
133        /**
134         * Returns the low-value for the specified series and item.
135         * <p>
136         * Note: throws <code>ClassCastException</code> if the series if not from a
137         * {@link OHLCDataset}.
138         *
139         * @param series  the index of the series of interest (zero-based).
140         * @param item  the index of the item of interest (zero-based).
141         *
142         * @return The low-value for the specified series and item.
143         */
144        public Number getLow(int series, int item) {
145            return ((OHLCDataset) this.parent).getLow(this.map[series], item);
146        }
147    
148        /**
149         * Returns the low-value (as a double primitive) for an item within a
150         * series.
151         *
152         * @param series  the series (zero-based index).
153         * @param item  the item (zero-based index).
154         *
155         * @return The low-value.
156         */
157        public double getLowValue(int series, int item) {
158            double result = Double.NaN;
159            Number low = getLow(series, item);
160            if (low != null) {
161                result = low.doubleValue();
162            }
163            return result;
164        }
165    
166        /**
167         * Returns the open-value for the specified series and item.
168         * <p>
169         * Note: throws <code>ClassCastException</code> if the series if not from a
170         * {@link OHLCDataset}.
171         *
172         * @param series  the index of the series of interest (zero-based).
173         * @param item  the index of the item of interest (zero-based).
174         *
175         * @return The open-value for the specified series and item.
176         */
177        public Number getOpen(int series, int item) {
178            return ((OHLCDataset) this.parent).getOpen(this.map[series], item);
179        }
180    
181        /**
182         * Returns the open-value (as a double primitive) for an item within a
183         * series.
184         *
185         * @param series  the series (zero-based index).
186         * @param item  the item (zero-based index).
187         *
188         * @return The open-value.
189         */
190        public double getOpenValue(int series, int item) {
191            double result = Double.NaN;
192            Number open = getOpen(series, item);
193            if (open != null) {
194                result = open.doubleValue();
195            }
196            return result;
197        }
198    
199        /**
200         * Returns the close-value for the specified series and item.
201         * <p>
202         * Note: throws <code>ClassCastException</code> if the series if not from a
203         * {@link OHLCDataset}.
204         *
205         * @param series  the index of the series of interest (zero-based).
206         * @param item  the index of the item of interest (zero-based).
207         *
208         * @return The close-value for the specified series and item.
209         */
210        public Number getClose(int series, int item) {
211            return ((OHLCDataset) this.parent).getClose(this.map[series], item);
212        }
213    
214        /**
215         * Returns the close-value (as a double primitive) for an item within a
216         * series.
217         *
218         * @param series  the series (zero-based index).
219         * @param item  the item (zero-based index).
220         *
221         * @return The close-value.
222         */
223        public double getCloseValue(int series, int item) {
224            double result = Double.NaN;
225            Number close = getClose(series, item);
226            if (close != null) {
227                result = close.doubleValue();
228            }
229            return result;
230        }
231    
232        /**
233         * Returns the volume.
234         * <p>
235         * Note: throws <code>ClassCastException</code> if the series if not from a
236         * {@link OHLCDataset}.
237         *
238         * @param series  the series (zero based index).
239         * @param item  the item (zero based index).
240         *
241         * @return The volume.
242         */
243        public Number getVolume(int series, int item) {
244            return ((OHLCDataset) this.parent).getVolume(this.map[series], item);
245        }
246    
247        /**
248         * Returns the volume-value (as a double primitive) for an item within a
249         * series.
250         *
251         * @param series  the series (zero-based index).
252         * @param item  the item (zero-based index).
253         *
254         * @return The volume-value.
255         */
256        public double getVolumeValue(int series, int item) {
257            double result = Double.NaN;
258            Number volume = getVolume(series, item);
259            if (volume != null) {
260                result = volume.doubleValue();
261            }
262            return result;
263        }
264    
265        ///////////////////////////////////////////////////////////////////////////
266        // From XYDataset
267        ///////////////////////////////////////////////////////////////////////////
268    
269        /**
270         * Returns the X-value for the specified series and item.
271         * <p>
272         * Note: throws <code>ClassCastException</code> if the series if not from a
273         * {@link XYDataset}.
274         *
275         * @param series  the index of the series of interest (zero-based);
276         * @param item  the index of the item of interest (zero-based).
277         *
278         * @return The X-value for the specified series and item.
279         */
280        public Number getX(int series, int item) {
281            return ((XYDataset) this.parent).getX(this.map[series], item);
282        }
283    
284        /**
285         * Returns the Y-value for the specified series and item.
286         * <p>
287         * Note: throws <code>ClassCastException</code> if the series if not from a
288         * {@link XYDataset}.
289         *
290         * @param series  the index of the series of interest (zero-based).
291         * @param item  the index of the item of interest (zero-based).
292         *
293         * @return The Y-value for the specified series and item.
294         */
295        public Number getY(int series, int item) {
296            return ((XYDataset) this.parent).getY(this.map[series], item);
297        }
298    
299        /**
300         * Returns the number of items in a series.
301         * <p>
302         * Note: throws <code>ClassCastException</code> if the series if not from a
303         * {@link XYDataset}.
304         *
305         * @param series  the index of the series of interest (zero-based).
306         *
307         * @return The number of items in a series.
308         */
309        public int getItemCount(int series) {
310            return ((XYDataset) this.parent).getItemCount(this.map[series]);
311        }
312    
313        ///////////////////////////////////////////////////////////////////////////
314        // From SeriesDataset
315        ///////////////////////////////////////////////////////////////////////////
316    
317        /**
318         * Returns the number of series in the dataset.
319         *
320         * @return The number of series in the dataset.
321         */
322        public int getSeriesCount() {
323            return this.map.length;
324        }
325    
326        /**
327         * Returns the key for a series.
328         *
329         * @param series  the series (zero-based index).
330         *
331         * @return The name of a series.
332         */
333        public Comparable getSeriesKey(int series) {
334            return this.parent.getSeriesKey(this.map[series]);
335        }
336    
337        ///////////////////////////////////////////////////////////////////////////
338        // From IntervalXYDataset
339        ///////////////////////////////////////////////////////////////////////////
340    
341        /**
342         * Returns the starting X value for the specified series and item.
343         *
344         * @param series  the index of the series of interest (zero-based).
345         * @param item  the index of the item of interest (zero-based).
346         *
347         * @return The starting X value for the specified series and item.
348         */
349        public Number getStartX(int series, int item) {
350            if (this.parent instanceof IntervalXYDataset) {
351                return ((IntervalXYDataset) this.parent).getStartX(
352                    this.map[series], item
353                );
354            }
355            else {
356                return getX(series, item);
357            }
358        }
359    
360        /**
361         * Returns the ending X value for the specified series and item.
362         *
363         * @param series  the index of the series of interest (zero-based).
364         * @param item  the index of the item of interest (zero-based).
365         *
366         * @return The ending X value for the specified series and item.
367         */
368        public Number getEndX(int series, int item) {
369            if (this.parent instanceof IntervalXYDataset) {
370                return ((IntervalXYDataset) this.parent).getEndX(
371                    this.map[series], item
372                );
373            }
374            else {
375                return getX(series, item);
376            }
377        }
378    
379        /**
380         * Returns the starting Y value for the specified series and item.
381         *
382         * @param series  the index of the series of interest (zero-based).
383         * @param item  the index of the item of interest (zero-based).
384         *
385         * @return The starting Y value for the specified series and item.
386         */
387        public Number getStartY(int series, int item) {
388            if (this.parent instanceof IntervalXYDataset) {
389                return ((IntervalXYDataset) this.parent).getStartY(
390                    this.map[series], item
391                );
392            }
393            else {
394                return getY(series, item);
395            }
396        }
397    
398        /**
399         * Returns the ending Y value for the specified series and item.
400         *
401         * @param series  the index of the series of interest (zero-based).
402         * @param item  the index of the item of interest (zero-based).
403         *
404         * @return The ending Y value for the specified series and item.
405         */
406        public Number getEndY(int series,  int item) {
407            if (this.parent instanceof IntervalXYDataset) {
408                return ((IntervalXYDataset) this.parent).getEndY(
409                    this.map[series], item
410                );
411            }
412            else {
413                return getY(series, item);
414            }
415        }
416    
417        ///////////////////////////////////////////////////////////////////////////
418        // New methods from CombinationDataset
419        ///////////////////////////////////////////////////////////////////////////
420    
421        /**
422         * Returns the parent Dataset of this combination.
423         *
424         * @return The parent Dataset of this combination.
425         */
426        public SeriesDataset getParent() {
427            return this.parent;
428        }
429    
430        /**
431         * Returns a map or indirect indexing form our series into parent's series.
432         *
433         * @return A map or indirect indexing form our series into parent's series.
434         */
435        public int[] getMap() {
436            return (int[]) this.map.clone();
437        }
438    
439    }