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-2007, 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-2007, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   -;
  34:  *
  35:  * Changes
  36:  * -------
  37:  * 21-Mar-2002 : Version 1 (DG);
  38:  * 07-Oct-2002 : Fixed errors reported by Checkstyle (DG);
  39:  * 06-May-2004 : Now extends AbstractXYDataset and added new methods from 
  40:  *               HighLowDataset (DG);
  41:  * 15-Jul-2004 : Switched getX() with getXValue() and getY() with 
  42:  *               getYValue() (DG);
  43:  * ------------- JFREECHART 1.0.x ---------------------------------------------
  44:  * 28-Nov-2006 : Added equals() method override (DG);
  45:  *
  46:  */
  47: 
  48: package org.jfree.data.xy;
  49: 
  50: import java.util.Arrays;
  51: import java.util.Date;
  52: 
  53: /**
  54:  * A simple implementation of the {@link OHLCDataset} interface.  See also
  55:  * the {@link DefaultOHLCDataset} class, which provides another implementation
  56:  * that is very similar.
  57:  */
  58: public class DefaultHighLowDataset extends AbstractXYDataset 
  59:                                    implements OHLCDataset {
  60: 
  61:     /** The series key. */
  62:     private Comparable seriesKey;
  63: 
  64:     /** Storage for the dates. */
  65:     private Date[] date;
  66: 
  67:     /** Storage for the high values. */
  68:     private Number[] high;
  69: 
  70:     /** Storage for the low values. */
  71:     private Number[] low;
  72: 
  73:     /** Storage for the open values. */
  74:     private Number[] open;
  75: 
  76:     /** Storage for the close values. */
  77:     private Number[] close;
  78: 
  79:     /** Storage for the volume values. */
  80:     private Number[] volume;
  81: 
  82:     /**
  83:      * Constructs a new high/low/open/close dataset.
  84:      * <p>
  85:      * The current implementation allows only one series in the dataset.
  86:      * This may be extended in a future version.
  87:      *
  88:      * @param seriesKey  the key for the series (<code>null</code> not 
  89:      *     permitted).
  90:      * @param date  the dates (<code>null</code> not permitted).
  91:      * @param high  the high values (<code>null</code> not permitted).
  92:      * @param low  the low values (<code>null</code> not permitted).
  93:      * @param open  the open values (<code>null</code> not permitted).
  94:      * @param close  the close values (<code>null</code> not permitted).
  95:      * @param volume  the volume values (<code>null</code> not permitted).
  96:      */
  97:     public DefaultHighLowDataset(Comparable seriesKey, Date[] date, 
  98:             double[] high, double[] low, double[] open, double[] close,
  99:             double[] volume) {
 100: 
 101:         if (seriesKey == null) {
 102:             throw new IllegalArgumentException("Null 'series' argument.");
 103:         }
 104:         if (date == null) {
 105:             throw new IllegalArgumentException("Null 'date' argument.");
 106:         }
 107:         this.seriesKey = seriesKey;
 108:         this.date = date;
 109:         this.high = createNumberArray(high);
 110:         this.low = createNumberArray(low);
 111:         this.open = createNumberArray(open);
 112:         this.close = createNumberArray(close);
 113:         this.volume = createNumberArray(volume);
 114: 
 115:     }
 116: 
 117:     /**
 118:      * Returns the key for the series stored in this dataset.
 119:      *
 120:      * @param series  the index of the series (ignored, this dataset supports 
 121:      *     only one series and this method always returns the key for series 0).
 122:      * 
 123:      * @return The series key (never <code>null</code>).
 124:      */
 125:     public Comparable getSeriesKey(int series) {
 126:         return this.seriesKey;
 127:     }
 128:     
 129:     /**
 130:      * Returns the x-value for one item in a series.  The value returned is a 
 131:      * <code>Long</code> instance generated from the underlying 
 132:      * <code>Date</code> object.  To avoid generating a new object instance,
 133:      * you might prefer to call {@link #getXValue(int, int)}.
 134:      *
 135:      * @param series  the series (zero-based index).
 136:      * @param item  the item (zero-based index).
 137:      *
 138:      * @return The x-value.
 139:      * 
 140:      * @see #getXValue(int, int)
 141:      * @see #getXDate(int, int)
 142:      */
 143:     public Number getX(int series, int item) {
 144:         return new Long(this.date[item].getTime());
 145:     }
 146: 
 147:     /**
 148:      * Returns the x-value for one item in a series, as a Date.
 149:      * <p>
 150:      * This method is provided for convenience only.
 151:      *
 152:      * @param series  the series (zero-based index).
 153:      * @param item  the item (zero-based index).
 154:      *
 155:      * @return The x-value as a Date.
 156:      * 
 157:      * @see #getX(int, int)
 158:      */
 159:     public Date getXDate(int series, int item) {
 160:         return this.date[item];
 161:     }
 162: 
 163:     /**
 164:      * Returns the y-value for one item in a series.
 165:      * <p>
 166:      * This method (from the {@link XYDataset} interface) is mapped to the 
 167:      * {@link #getCloseValue(int, int)} method.
 168:      *
 169:      * @param series  the series (zero-based index).
 170:      * @param item  the item (zero-based index).
 171:      *
 172:      * @return The y-value.
 173:      * 
 174:      * @see #getYValue(int, int)
 175:      */
 176:     public Number getY(int series, int item) {
 177:         return getClose(series, item);
 178:     }
 179: 
 180:     /**
 181:      * Returns the high-value for one item in a series.
 182:      *
 183:      * @param series  the series (zero-based index).
 184:      * @param item  the item (zero-based index).
 185:      *
 186:      * @return The high-value.
 187:      * 
 188:      * @see #getHighValue(int, int)
 189:      */
 190:     public Number getHigh(int series, int item) {
 191:         return this.high[item];
 192:     }
 193: 
 194:     /**
 195:      * Returns the high-value (as a double primitive) for an item within a 
 196:      * series.
 197:      * 
 198:      * @param series  the series (zero-based index).
 199:      * @param item  the item (zero-based index).
 200:      * 
 201:      * @return The high-value.
 202:      * 
 203:      * @see #getHigh(int, int)
 204:      */
 205:     public double getHighValue(int series, int item) {
 206:         double result = Double.NaN;
 207:         Number high = getHigh(series, item);
 208:         if (high != null) {
 209:             result = high.doubleValue();   
 210:         }
 211:         return result;   
 212:     }
 213: 
 214:     /**
 215:      * Returns the low-value for one item in a series.
 216:      *
 217:      * @param series  the series (zero-based index).
 218:      * @param item  the item (zero-based index).
 219:      *
 220:      * @return The low-value.
 221:      * 
 222:      * @see #getLowValue(int, int)
 223:      */
 224:     public Number getLow(int series, int item) {
 225:         return this.low[item];
 226:     }
 227: 
 228:     /**
 229:      * Returns the low-value (as a double primitive) for an item within a 
 230:      * series.
 231:      * 
 232:      * @param series  the series (zero-based index).
 233:      * @param item  the item (zero-based index).
 234:      * 
 235:      * @return The low-value.
 236:      * 
 237:      * @see #getLow(int, int)
 238:      */
 239:     public double getLowValue(int series, int item) {
 240:         double result = Double.NaN;
 241:         Number low = getLow(series, item);
 242:         if (low != null) {
 243:             result = low.doubleValue();   
 244:         }
 245:         return result;   
 246:     }
 247: 
 248:     /**
 249:      * Returns the open-value for one item in a series.
 250:      *
 251:      * @param series  the series (zero-based index).
 252:      * @param item  the item (zero-based index).
 253:      *
 254:      * @return The open-value.
 255:      * 
 256:      * @see #getOpenValue(int, int)
 257:      */
 258:     public Number getOpen(int series, int item) {
 259:         return this.open[item];
 260:     }
 261: 
 262:     /**
 263:      * Returns the open-value (as a double primitive) for an item within a 
 264:      * series.
 265:      * 
 266:      * @param series  the series (zero-based index).
 267:      * @param item  the item (zero-based index).
 268:      * 
 269:      * @return The open-value.
 270:      * 
 271:      * @see #getOpen(int, int)
 272:      */
 273:     public double getOpenValue(int series, int item) {
 274:         double result = Double.NaN;
 275:         Number open = getOpen(series, item);
 276:         if (open != null) {
 277:             result = open.doubleValue();   
 278:         }
 279:         return result;   
 280:     }
 281: 
 282:     /**
 283:      * Returns the close-value for one item in a series.
 284:      *
 285:      * @param series  the series (zero-based index).
 286:      * @param item  the item (zero-based index).
 287:      *
 288:      * @return The close-value.
 289:      * 
 290:      * @see #getCloseValue(int, int)
 291:      */
 292:     public Number getClose(int series, int item) {
 293:         return this.close[item];
 294:     }
 295: 
 296:     /**
 297:      * Returns the close-value (as a double primitive) for an item within a 
 298:      * series.
 299:      * 
 300:      * @param series  the series (zero-based index).
 301:      * @param item  the item (zero-based index).
 302:      * 
 303:      * @return The close-value.
 304:      * 
 305:      * @see #getClose(int, int)
 306:      */
 307:     public double getCloseValue(int series, int item) {
 308:         double result = Double.NaN;
 309:         Number close = getClose(series, item);
 310:         if (close != null) {
 311:             result = close.doubleValue();   
 312:         }
 313:         return result;   
 314:     }
 315: 
 316:     /**
 317:      * Returns the volume-value for one item in a series.
 318:      *
 319:      * @param series  the series (zero-based index).
 320:      * @param item  the item (zero-based index).
 321:      *
 322:      * @return The volume-value.
 323:      * 
 324:      * @see #getVolumeValue(int, int)
 325:      */
 326:     public Number getVolume(int series, int item) {
 327:         return this.volume[item];
 328:     }
 329: 
 330:     /**
 331:      * Returns the volume-value (as a double primitive) for an item within a 
 332:      * series.
 333:      * 
 334:      * @param series  the series (zero-based index).
 335:      * @param item  the item (zero-based index).
 336:      * 
 337:      * @return The volume-value.
 338:      * 
 339:      * @see #getVolume(int, int)
 340:      */
 341:     public double getVolumeValue(int series, int item) {
 342:         double result = Double.NaN;
 343:         Number volume = getVolume(series, item);
 344:         if (volume != null) {
 345:             result = volume.doubleValue();   
 346:         }
 347:         return result;   
 348:     }
 349: 
 350:     /**
 351:      * Returns the number of series in the dataset.
 352:      * <p>
 353:      * This implementation only allows one series.
 354:      *
 355:      * @return The number of series.
 356:      */
 357:     public int getSeriesCount() {
 358:         return 1;
 359:     }
 360: 
 361:     /**
 362:      * Returns the number of items in the specified series.
 363:      *
 364:      * @param series  the index (zero-based) of the series.
 365:      *
 366:      * @return The number of items in the specified series.
 367:      */
 368:     public int getItemCount(int series) {
 369:         return this.date.length;
 370:     }
 371: 
 372:     /**
 373:      * Tests this dataset for equality with an arbitrary instance.
 374:      * 
 375:      * @param obj  the object (<code>null</code> permitted).
 376:      * 
 377:      * @return A boolean.
 378:      */
 379:     public boolean equals(Object obj) {
 380:         if (obj == this) {
 381:             return true;
 382:         }
 383:         if (!(obj instanceof DefaultHighLowDataset)) {
 384:             return false;
 385:         }
 386:         DefaultHighLowDataset that = (DefaultHighLowDataset) obj;
 387:         if (!this.seriesKey.equals(that.seriesKey)) {
 388:             return false;
 389:         }
 390:         if (!Arrays.equals(this.date, that.date)) {
 391:             return false;
 392:         }
 393:         if (!Arrays.equals(this.open, that.open)) {
 394:             return false;
 395:         }
 396:         if (!Arrays.equals(this.high, that.high)) {
 397:             return false;
 398:         }
 399:         if (!Arrays.equals(this.low, that.low)) {
 400:             return false;
 401:         }
 402:         if (!Arrays.equals(this.close, that.close)) {
 403:             return false;
 404:         }
 405:         if (!Arrays.equals(this.volume, that.volume)) {
 406:             return false;
 407:         }
 408:         return true;    
 409:     }
 410:     
 411:     /**
 412:      * Constructs an array of Number objects from an array of doubles.
 413:      *
 414:      * @param data  the double values to convert (<code>null</code> not 
 415:      *     permitted).
 416:      *
 417:      * @return The data as an array of Number objects.
 418:      */
 419:     public static Number[] createNumberArray(double[] data) {
 420:         Number[] result = new Number[data.length];
 421:         for (int i = 0; i < data.length; i++) {
 422:             result[i] = new Double(data[i]);
 423:         }
 424:         return result;
 425:     }
 426: 
 427: }