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 * OHLCSeriesCollection.java
029 * -------------------------
030 * (C) Copyright 2006, 2007, by Object Refinery Limited.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): -;
034 *
035 * Changes
036 * -------
037 * 04-Dec-2006 : Version 1 (DG);
038 *
039 */
040
041 package org.jfree.data.time.ohlc;
042
043 import java.io.Serializable;
044 import java.util.List;
045
046 import org.jfree.data.general.DatasetChangeEvent;
047 import org.jfree.data.time.RegularTimePeriod;
048 import org.jfree.data.time.TimePeriodAnchor;
049 import org.jfree.data.xy.AbstractXYDataset;
050 import org.jfree.data.xy.OHLCDataset;
051 import org.jfree.util.ObjectUtilities;
052
053 /**
054 * A collection of {@link OHLCSeries} objects.
055 *
056 * @since 1.0.4
057 *
058 * @see OHLCSeries
059 */
060 public class OHLCSeriesCollection extends AbstractXYDataset
061 implements OHLCDataset, Serializable {
062
063 /** Storage for the data series. */
064 private List data;
065
066 private TimePeriodAnchor xPosition = TimePeriodAnchor.MIDDLE;
067
068 /**
069 * Creates a new instance of <code>OHLCSeriesCollection</code>.
070 */
071 public OHLCSeriesCollection() {
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(OHLCSeries 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 OHLCSeries getSeries(int series) {
110 if ((series < 0) || (series >= getSeriesCount())) {
111 throw new IllegalArgumentException("Series index out of bounds");
112 }
113 return (OHLCSeries) 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 a time period.
149 *
150 * @param period the time period (<code>null</code> not permitted).
151 *
152 * @return The x-value.
153 */
154 protected synchronized long getX(RegularTimePeriod period) {
155 long result = 0L;
156 if (this.xPosition == TimePeriodAnchor.START) {
157 result = period.getFirstMillisecond();
158 }
159 else if (this.xPosition == TimePeriodAnchor.MIDDLE) {
160 result = period.getMiddleMillisecond();
161 }
162 else if (this.xPosition == TimePeriodAnchor.END) {
163 result = period.getLastMillisecond();
164 }
165 return result;
166 }
167
168 /**
169 * Returns the x-value for an item within a series.
170 *
171 * @param series the series index.
172 * @param item the item index.
173 *
174 * @return The x-value.
175 */
176 public double getXValue(int series, int item) {
177 OHLCSeries s = (OHLCSeries) this.data.get(series);
178 OHLCItem di = (OHLCItem) s.getDataItem(item);
179 RegularTimePeriod period = di.getPeriod();
180 return getX(period);
181 }
182
183 /**
184 * Returns the x-value for an item within a series.
185 *
186 * @param series the series index.
187 * @param item the item index.
188 *
189 * @return The x-value.
190 */
191 public Number getX(int series, int item) {
192 return new Double(getXValue(series, item));
193 }
194
195 /**
196 * Returns the y-value for an item within a series.
197 *
198 * @param series the series index.
199 * @param item the item index.
200 *
201 * @return The y-value.
202 */
203 public Number getY(int series, int item) {
204 OHLCSeries s = (OHLCSeries) this.data.get(series);
205 OHLCItem di = (OHLCItem) s.getDataItem(item);
206 return new Double(di.getYValue());
207 }
208
209 /**
210 * Returns the open-value for an item within a series.
211 *
212 * @param series the series index.
213 * @param item the item index.
214 *
215 * @return The open-value.
216 */
217 public double getOpenValue(int series, int item) {
218 OHLCSeries s = (OHLCSeries) this.data.get(series);
219 OHLCItem di = (OHLCItem) s.getDataItem(item);
220 return di.getOpenValue();
221 }
222
223 /**
224 * Returns the open-value for an item within a series.
225 *
226 * @param series the series index.
227 * @param item the item index.
228 *
229 * @return The open-value.
230 */
231 public Number getOpen(int series, int item) {
232 return new Double(getOpenValue(series, item));
233 }
234
235 /**
236 * Returns the close-value for an item within a series.
237 *
238 * @param series the series index.
239 * @param item the item index.
240 *
241 * @return The close-value.
242 */
243 public double getCloseValue(int series, int item) {
244 OHLCSeries s = (OHLCSeries) this.data.get(series);
245 OHLCItem di = (OHLCItem) s.getDataItem(item);
246 return di.getCloseValue();
247 }
248
249 /**
250 * Returns the close-value for an item within a series.
251 *
252 * @param series the series index.
253 * @param item the item index.
254 *
255 * @return The close-value.
256 */
257 public Number getClose(int series, int item) {
258 return new Double(getCloseValue(series, item));
259 }
260
261 /**
262 * Returns the high-value for an item within a series.
263 *
264 * @param series the series index.
265 * @param item the item index.
266 *
267 * @return The high-value.
268 */
269 public double getHighValue(int series, int item) {
270 OHLCSeries s = (OHLCSeries) this.data.get(series);
271 OHLCItem di = (OHLCItem) s.getDataItem(item);
272 return di.getHighValue();
273 }
274
275 /**
276 * Returns the high-value for an item within a series.
277 *
278 * @param series the series index.
279 * @param item the item index.
280 *
281 * @return The high-value.
282 */
283 public Number getHigh(int series, int item) {
284 return new Double(getHighValue(series, item));
285 }
286
287 /**
288 * Returns the low-value for an item within a series.
289 *
290 * @param series the series index.
291 * @param item the item index.
292 *
293 * @return The low-value.
294 */
295 public double getLowValue(int series, int item) {
296 OHLCSeries s = (OHLCSeries) this.data.get(series);
297 OHLCItem di = (OHLCItem) s.getDataItem(item);
298 return di.getLowValue();
299 }
300
301 /**
302 * Returns the low-value for an item within a series.
303 *
304 * @param series the series index.
305 * @param item the item index.
306 *
307 * @return The low-value.
308 */
309 public Number getLow(int series, int item) {
310 return new Double(getLowValue(series, item));
311 }
312
313 public Number getVolume(int series, int item) {
314 return null;
315 }
316
317 public double getVolumeValue(int series, int item) {
318 return Double.NaN;
319 }
320
321 /**
322 * Tests this instance for equality with an arbitrary object.
323 *
324 * @param obj the object (<code>null</code> permitted).
325 *
326 * @return A boolean.
327 */
328 public boolean equals(Object obj) {
329 if (obj == this) {
330 return true;
331 }
332 if (!(obj instanceof OHLCSeriesCollection)) {
333 return false;
334 }
335 OHLCSeriesCollection that = (OHLCSeriesCollection) obj;
336 return ObjectUtilities.equal(this.data, that.data);
337 }
338
339 /**
340 * Returns a clone of this instance.
341 *
342 * @return A clone.
343 *
344 * @throws CloneNotSupportedException if there is a problem.
345 */
346 public Object clone() throws CloneNotSupportedException {
347 OHLCSeriesCollection clone
348 = (OHLCSeriesCollection) super.clone();
349 clone.data = (List) ObjectUtilities.deepClone(this.data);
350 return clone;
351 }
352
353 }