Source for org.jfree.data.xy.DefaultHighLowDataset

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
   6:  *
   7:  * Project Info:  http://www.jfree.org/jfreechart/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  *
  27:  * --------------------------
  28:  * DefaultHighLowDataset.java
  29:  * --------------------------
  30:  * (C) Copyright 2002-2006, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * $Id: DefaultHighLowDataset.java,v 1.6.2.2 2006/11/28 10:41:51 mungady Exp $
  36:  *
  37:  * Changes
  38:  * -------
  39:  * 21-Mar-2002 : Version 1 (DG);
  40:  * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG);
  41:  * 06-May-2004 : Now extends AbstractXYDataset and added new methods from 
  42:  *               HighLowDataset (DG);
  43:  * 15-Jul-2004 : Switched getX() with getXValue() and getY() with 
  44:  *               getYValue() (DG);
  45:  * ------------- JFREECHART 1.0.x ---------------------------------------------
  46:  * 28-Nov-2006 : Added equals() method override (DG);
  47:  *
  48:  */
  49: 
  50: package org.jfree.data.xy;
  51: 
  52: import java.util.Arrays;
  53: import java.util.Date;
  54: 
  55: /**
  56:  * A simple implementation of the {@link OHLCDataset} interface.  See also
  57:  * the {@link DefaultOHLCDataset} class, which provides another implementation
  58:  * that is very similar.
  59:  */
  60: public class DefaultHighLowDataset extends AbstractXYDataset 
  61:                                    implements OHLCDataset {
  62: 
  63:     /** The series key. */
  64:     private Comparable seriesKey;
  65: 
  66:     /** Storage for the dates. */
  67:     private Date[] date;
  68: 
  69:     /** Storage for the high values. */
  70:     private Number[] high;
  71: 
  72:     /** Storage for the low values. */
  73:     private Number[] low;
  74: 
  75:     /** Storage for the open values. */
  76:     private Number[] open;
  77: 
  78:     /** Storage for the close values. */
  79:     private Number[] close;
  80: 
  81:     /** Storage for the volume values. */
  82:     private Number[] volume;
  83: 
  84:     /**
  85:      * Constructs a new high/low/open/close dataset.
  86:      * <p>
  87:      * The current implementation allows only one series in the dataset.
  88:      * This may be extended in a future version.
  89:      *
  90:      * @param seriesKey  the key for the series (<code>null</code> not 
  91:      *     permitted).
  92:      * @param date  the dates (<code>null</code> not permitted).
  93:      * @param high  the high values (<code>null</code> not permitted).
  94:      * @param low  the low values (<code>null</code> not permitted).
  95:      * @param open  the open values (<code>null</code> not permitted).
  96:      * @param close  the close values (<code>null</code> not permitted).
  97:      * @param volume  the volume values (<code>null</code> not permitted).
  98:      */
  99:     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: }