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 * DefaultOHLCDataset.java
029 * -----------------------
030 * (C) Copyright 2003-2008, by Object Refinery Limited.
031 *
032 * Original Author:  David Gilbert (for Object Refinery Limited);
033 * Contributor(s):   -;
034 *
035 * Changes
036 * -------
037 * 03-Dec-2003 : Version 1 (DG);
038 * 05-May-2004 : Now extends AbstractXYDataset (DG);
039 * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
040 *               getYValue() (DG);
041 * 29-Apr-2005 : Added equals() method (DG);
042 * 22-Apr-2008 : Implemented PublicCloneable, and fixed cloning bug (DG);
043 *
044 */
045
046package org.jfree.data.xy;
047
048import java.util.Arrays;
049import java.util.Date;
050
051import org.jfree.util.PublicCloneable;
052
053/**
054 * A simple implementation of the {@link OHLCDataset} interface.  This
055 * implementation supports only one series.
056 */
057public class DefaultOHLCDataset extends AbstractXYDataset
058        implements OHLCDataset, PublicCloneable {
059
060    /** The series key. */
061    private Comparable key;
062
063    /** Storage for the data items. */
064    private OHLCDataItem[] data;
065
066    /**
067     * Creates a new dataset.
068     *
069     * @param key  the series key.
070     * @param data  the data items.
071     */
072    public DefaultOHLCDataset(Comparable key, OHLCDataItem[] data) {
073        this.key = key;
074        this.data = data;
075    }
076
077    /**
078     * Returns the series key.
079     *
080     * @param series  the series index (ignored).
081     *
082     * @return The series key.
083     */
084    public Comparable getSeriesKey(int series) {
085        return this.key;
086    }
087
088    /**
089     * Returns the x-value for a data item.
090     *
091     * @param series  the series index (ignored).
092     * @param item  the item index (zero-based).
093     *
094     * @return The x-value.
095     */
096    public Number getX(int series, int item) {
097        return new Long(this.data[item].getDate().getTime());
098    }
099
100    /**
101     * Returns the x-value for a data item as a date.
102     *
103     * @param series  the series index (ignored).
104     * @param item  the item index (zero-based).
105     *
106     * @return The x-value as a date.
107     */
108    public Date getXDate(int series, int item) {
109        return this.data[item].getDate();
110    }
111
112    /**
113     * Returns the y-value.
114     *
115     * @param series  the series index (ignored).
116     * @param item  the item index (zero-based).
117     *
118     * @return The y value.
119     */
120    public Number getY(int series, int item) {
121        return getClose(series, item);
122    }
123
124    /**
125     * Returns the high value.
126     *
127     * @param series  the series index (ignored).
128     * @param item  the item index (zero-based).
129     *
130     * @return The high value.
131     */
132    public Number getHigh(int series, int item) {
133        return this.data[item].getHigh();
134    }
135
136    /**
137     * Returns the high-value (as a double primitive) for an item within a
138     * series.
139     *
140     * @param series  the series (zero-based index).
141     * @param item  the item (zero-based index).
142     *
143     * @return The high-value.
144     */
145    public double getHighValue(int series, int item) {
146        double result = Double.NaN;
147        Number high = getHigh(series, item);
148        if (high != null) {
149            result = high.doubleValue();
150        }
151        return result;
152    }
153
154    /**
155     * Returns the low value.
156     *
157     * @param series  the series index (ignored).
158     * @param item  the item index (zero-based).
159     *
160     * @return The low value.
161     */
162    public Number getLow(int series, int item) {
163        return this.data[item].getLow();
164    }
165
166    /**
167     * Returns the low-value (as a double primitive) for an item within a
168     * series.
169     *
170     * @param series  the series (zero-based index).
171     * @param item  the item (zero-based index).
172     *
173     * @return The low-value.
174     */
175    public double getLowValue(int series, int item) {
176        double result = Double.NaN;
177        Number low = getLow(series, item);
178        if (low != null) {
179            result = low.doubleValue();
180        }
181        return result;
182    }
183
184    /**
185     * Returns the open value.
186     *
187     * @param series  the series index (ignored).
188     * @param item  the item index (zero-based).
189     *
190     * @return The open value.
191     */
192    public Number getOpen(int series, int item) {
193        return this.data[item].getOpen();
194    }
195
196    /**
197     * Returns the open-value (as a double primitive) for an item within a
198     * series.
199     *
200     * @param series  the series (zero-based index).
201     * @param item  the item (zero-based index).
202     *
203     * @return The open-value.
204     */
205    public double getOpenValue(int series, int item) {
206        double result = Double.NaN;
207        Number open = getOpen(series, item);
208        if (open != null) {
209            result = open.doubleValue();
210        }
211        return result;
212    }
213
214    /**
215     * Returns the close value.
216     *
217     * @param series  the series index (ignored).
218     * @param item  the item index (zero-based).
219     *
220     * @return The close value.
221     */
222    public Number getClose(int series, int item) {
223        return this.data[item].getClose();
224    }
225
226    /**
227     * Returns the close-value (as a double primitive) for an item within a
228     * series.
229     *
230     * @param series  the series (zero-based index).
231     * @param item  the item (zero-based index).
232     *
233     * @return The close-value.
234     */
235    public double getCloseValue(int series, int item) {
236        double result = Double.NaN;
237        Number close = getClose(series, item);
238        if (close != null) {
239            result = close.doubleValue();
240        }
241        return result;
242    }
243
244    /**
245     * Returns the trading volume.
246     *
247     * @param series  the series index (ignored).
248     * @param item  the item index (zero-based).
249     *
250     * @return The trading volume.
251     */
252    public Number getVolume(int series, int item) {
253        return this.data[item].getVolume();
254    }
255
256    /**
257     * Returns the volume-value (as a double primitive) for an item within a
258     * series.
259     *
260     * @param series  the series (zero-based index).
261     * @param item  the item (zero-based index).
262     *
263     * @return The volume-value.
264     */
265    public double getVolumeValue(int series, int item) {
266        double result = Double.NaN;
267        Number volume = getVolume(series, item);
268        if (volume != null) {
269            result = volume.doubleValue();
270        }
271        return result;
272    }
273
274    /**
275     * Returns the series count.
276     *
277     * @return 1.
278     */
279    public int getSeriesCount() {
280        return 1;
281    }
282
283    /**
284     * Returns the item count for the specified series.
285     *
286     * @param series  the series index (ignored).
287     *
288     * @return The item count.
289     */
290    public int getItemCount(int series) {
291        return this.data.length;
292    }
293
294    /**
295     * Sorts the data into ascending order by date.
296     */
297    public void sortDataByDate() {
298        Arrays.sort(this.data);
299    }
300
301    /**
302     * Tests this instance for equality with an arbitrary object.
303     *
304     * @param obj  the object (<code>null</code> permitted).
305     *
306     * @return A boolean.
307     */
308    public boolean equals(Object obj) {
309        if (this == obj) {
310            return true;
311        }
312        if (!(obj instanceof DefaultOHLCDataset)) {
313            return false;
314        }
315        DefaultOHLCDataset that = (DefaultOHLCDataset) obj;
316        if (!this.key.equals(that.key)) {
317            return false;
318        }
319        if (!Arrays.equals(this.data, that.data)) {
320            return false;
321        }
322        return true;
323    }
324
325    /**
326     * Returns an independent copy of this dataset.
327     *
328     * @return A clone.
329     *
330     * @throws CloneNotSupportedException
331     */
332    public Object clone() throws CloneNotSupportedException {
333        DefaultOHLCDataset clone = (DefaultOHLCDataset) super.clone();
334        clone.data = new OHLCDataItem[this.data.length];
335        System.arraycopy(this.data, 0, clone.data, 0, this.data.length);
336        return clone;
337    }
338
339}