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 }