001 /* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2006, 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 * DefaultHighLowDataset.java 029 * -------------------------- 030 * (C) Copyright 2002-2006, by Object Refinery Limited. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): -; 034 * 035 * $Id: DefaultHighLowDataset.java,v 1.6.2.2 2006/11/28 10:41:51 mungady Exp $ 036 * 037 * Changes 038 * ------- 039 * 21-Mar-2002 : Version 1 (DG); 040 * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG); 041 * 06-May-2004 : Now extends AbstractXYDataset and added new methods from 042 * HighLowDataset (DG); 043 * 15-Jul-2004 : Switched getX() with getXValue() and getY() with 044 * getYValue() (DG); 045 * ------------- JFREECHART 1.0.x --------------------------------------------- 046 * 28-Nov-2006 : Added equals() method override (DG); 047 * 048 */ 049 050 package org.jfree.data.xy; 051 052 import java.util.Arrays; 053 import java.util.Date; 054 055 /** 056 * A simple implementation of the {@link OHLCDataset} interface. See also 057 * the {@link DefaultOHLCDataset} class, which provides another implementation 058 * that is very similar. 059 */ 060 public class DefaultHighLowDataset extends AbstractXYDataset 061 implements OHLCDataset { 062 063 /** The series key. */ 064 private Comparable seriesKey; 065 066 /** Storage for the dates. */ 067 private Date[] date; 068 069 /** Storage for the high values. */ 070 private Number[] high; 071 072 /** Storage for the low values. */ 073 private Number[] low; 074 075 /** Storage for the open values. */ 076 private Number[] open; 077 078 /** Storage for the close values. */ 079 private Number[] close; 080 081 /** Storage for the volume values. */ 082 private Number[] volume; 083 084 /** 085 * Constructs a new high/low/open/close dataset. 086 * <p> 087 * The current implementation allows only one series in the dataset. 088 * This may be extended in a future version. 089 * 090 * @param seriesKey the key for the series (<code>null</code> not 091 * permitted). 092 * @param date the dates (<code>null</code> not permitted). 093 * @param high the high values (<code>null</code> not permitted). 094 * @param low the low values (<code>null</code> not permitted). 095 * @param open the open values (<code>null</code> not permitted). 096 * @param close the close values (<code>null</code> not permitted). 097 * @param volume the volume values (<code>null</code> not permitted). 098 */ 099 public DefaultHighLowDataset(Comparable seriesKey, Date[] date, 100 double[] high, double[] low, double[] open, double[] close, 101 double[] volume) { 102 103 if (seriesKey == null) { 104 throw new IllegalArgumentException("Null 'series' argument."); 105 } 106 if (date == null) { 107 throw new IllegalArgumentException("Null 'date' argument."); 108 } 109 this.seriesKey = seriesKey; 110 this.date = date; 111 this.high = createNumberArray(high); 112 this.low = createNumberArray(low); 113 this.open = createNumberArray(open); 114 this.close = createNumberArray(close); 115 this.volume = createNumberArray(volume); 116 117 } 118 119 /** 120 * Returns the key for the series stored in this dataset. 121 * 122 * @param series the index of the series (ignored, this dataset supports 123 * only one series and this method always returns the key for series 0). 124 * 125 * @return The series key (never <code>null</code>). 126 */ 127 public Comparable getSeriesKey(int series) { 128 return this.seriesKey; 129 } 130 131 /** 132 * Returns the x-value for one item in a series. The value returned is a 133 * <code>Long</code> instance generated from the underlying 134 * <code>Date</code> object. To avoid generating a new object instance, 135 * you might prefer to call {@link #getXValue(int, int)}. 136 * 137 * @param series the series (zero-based index). 138 * @param item the item (zero-based index). 139 * 140 * @return The x-value. 141 * 142 * @see #getXValue(int, int) 143 * @see #getXDate(int, int) 144 */ 145 public Number getX(int series, int item) { 146 return new Long(this.date[item].getTime()); 147 } 148 149 /** 150 * Returns the x-value for one item in a series, as a Date. 151 * <p> 152 * This method is provided for convenience only. 153 * 154 * @param series the series (zero-based index). 155 * @param item the item (zero-based index). 156 * 157 * @return The x-value as a Date. 158 * 159 * @see #getX(int, int) 160 */ 161 public Date getXDate(int series, int item) { 162 return this.date[item]; 163 } 164 165 /** 166 * Returns the y-value for one item in a series. 167 * <p> 168 * This method (from the {@link XYDataset} interface) is mapped to the 169 * {@link #getCloseValue(int, int)} method. 170 * 171 * @param series the series (zero-based index). 172 * @param item the item (zero-based index). 173 * 174 * @return The y-value. 175 * 176 * @see #getYValue(int, int) 177 */ 178 public Number getY(int series, int item) { 179 return getClose(series, item); 180 } 181 182 /** 183 * Returns the high-value for one item in a series. 184 * 185 * @param series the series (zero-based index). 186 * @param item the item (zero-based index). 187 * 188 * @return The high-value. 189 * 190 * @see #getHighValue(int, int) 191 */ 192 public Number getHigh(int series, int item) { 193 return this.high[item]; 194 } 195 196 /** 197 * Returns the high-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 high-value. 204 * 205 * @see #getHigh(int, int) 206 */ 207 public double getHighValue(int series, int item) { 208 double result = Double.NaN; 209 Number high = getHigh(series, item); 210 if (high != null) { 211 result = high.doubleValue(); 212 } 213 return result; 214 } 215 216 /** 217 * Returns the low-value for one item in a series. 218 * 219 * @param series the series (zero-based index). 220 * @param item the item (zero-based index). 221 * 222 * @return The low-value. 223 * 224 * @see #getLowValue(int, int) 225 */ 226 public Number getLow(int series, int item) { 227 return this.low[item]; 228 } 229 230 /** 231 * Returns the low-value (as a double primitive) for an item within a 232 * series. 233 * 234 * @param series the series (zero-based index). 235 * @param item the item (zero-based index). 236 * 237 * @return The low-value. 238 * 239 * @see #getLow(int, int) 240 */ 241 public double getLowValue(int series, int item) { 242 double result = Double.NaN; 243 Number low = getLow(series, item); 244 if (low != null) { 245 result = low.doubleValue(); 246 } 247 return result; 248 } 249 250 /** 251 * Returns the open-value for one item in a series. 252 * 253 * @param series the series (zero-based index). 254 * @param item the item (zero-based index). 255 * 256 * @return The open-value. 257 * 258 * @see #getOpenValue(int, int) 259 */ 260 public Number getOpen(int series, int item) { 261 return this.open[item]; 262 } 263 264 /** 265 * Returns the open-value (as a double primitive) for an item within a 266 * series. 267 * 268 * @param series the series (zero-based index). 269 * @param item the item (zero-based index). 270 * 271 * @return The open-value. 272 * 273 * @see #getOpen(int, int) 274 */ 275 public double getOpenValue(int series, int item) { 276 double result = Double.NaN; 277 Number open = getOpen(series, item); 278 if (open != null) { 279 result = open.doubleValue(); 280 } 281 return result; 282 } 283 284 /** 285 * Returns the close-value for one item in a series. 286 * 287 * @param series the series (zero-based index). 288 * @param item the item (zero-based index). 289 * 290 * @return The close-value. 291 * 292 * @see #getCloseValue(int, int) 293 */ 294 public Number getClose(int series, int item) { 295 return this.close[item]; 296 } 297 298 /** 299 * Returns the close-value (as a double primitive) for an item within a 300 * series. 301 * 302 * @param series the series (zero-based index). 303 * @param item the item (zero-based index). 304 * 305 * @return The close-value. 306 * 307 * @see #getClose(int, int) 308 */ 309 public double getCloseValue(int series, int item) { 310 double result = Double.NaN; 311 Number close = getClose(series, item); 312 if (close != null) { 313 result = close.doubleValue(); 314 } 315 return result; 316 } 317 318 /** 319 * Returns the volume-value for one item in a series. 320 * 321 * @param series the series (zero-based index). 322 * @param item the item (zero-based index). 323 * 324 * @return The volume-value. 325 * 326 * @see #getVolumeValue(int, int) 327 */ 328 public Number getVolume(int series, int item) { 329 return this.volume[item]; 330 } 331 332 /** 333 * Returns the volume-value (as a double primitive) for an item within a 334 * series. 335 * 336 * @param series the series (zero-based index). 337 * @param item the item (zero-based index). 338 * 339 * @return The volume-value. 340 * 341 * @see #getVolume(int, int) 342 */ 343 public double getVolumeValue(int series, int item) { 344 double result = Double.NaN; 345 Number volume = getVolume(series, item); 346 if (volume != null) { 347 result = volume.doubleValue(); 348 } 349 return result; 350 } 351 352 /** 353 * Returns the number of series in the dataset. 354 * <p> 355 * This implementation only allows one series. 356 * 357 * @return The number of series. 358 */ 359 public int getSeriesCount() { 360 return 1; 361 } 362 363 /** 364 * Returns the number of items in the specified series. 365 * 366 * @param series the index (zero-based) of the series. 367 * 368 * @return The number of items in the specified series. 369 */ 370 public int getItemCount(int series) { 371 return this.date.length; 372 } 373 374 /** 375 * Tests this dataset for equality with an arbitrary instance. 376 * 377 * @param obj the object (<code>null</code> permitted). 378 * 379 * @return A boolean. 380 */ 381 public boolean equals(Object obj) { 382 if (obj == this) { 383 return true; 384 } 385 if (!(obj instanceof DefaultHighLowDataset)) { 386 return false; 387 } 388 DefaultHighLowDataset that = (DefaultHighLowDataset) obj; 389 if (!this.seriesKey.equals(that.seriesKey)) { 390 return false; 391 } 392 if (!Arrays.equals(this.date, that.date)) { 393 return false; 394 } 395 if (!Arrays.equals(this.open, that.open)) { 396 return false; 397 } 398 if (!Arrays.equals(this.high, that.high)) { 399 return false; 400 } 401 if (!Arrays.equals(this.low, that.low)) { 402 return false; 403 } 404 if (!Arrays.equals(this.close, that.close)) { 405 return false; 406 } 407 if (!Arrays.equals(this.volume, that.volume)) { 408 return false; 409 } 410 return true; 411 } 412 413 /** 414 * Constructs an array of Number objects from an array of doubles. 415 * 416 * @param data the double values to convert (<code>null</code> not 417 * permitted). 418 * 419 * @return The data as an array of Number objects. 420 */ 421 public static Number[] createNumberArray(double[] data) { 422 Number[] result = new Number[data.length]; 423 for (int i = 0; i < data.length; i++) { 424 result[i] = new Double(data[i]); 425 } 426 return result; 427 } 428 429 }