KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > data > time > TimeTableXYDataset


1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2005, 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  * TimeTableXYDataset.java
29  * -----------------------
30  * (C) Copyright 2004, 2005, by Andreas Schroeder and Contributors.
31  *
32  * Original Author: Andreas Schroeder;
33  * Contributor(s): David Gilbert (for Object Refinery Limited);
34  *
35  * $Id: TimeTableXYDataset.java,v 1.10.2.1 2005/10/25 21:35:24 mungady Exp $
36  *
37  * Changes
38  * -------
39  * 01-Apr-2004 : Version 1 (AS);
40  * 05-May-2004 : Now implements AbstractIntervalXYDataset (DG);
41  * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
42  * getYValue() (DG);
43  * 15-Sep-2004 : Added getXPosition(), setXPosition(), equals() and
44  * clone() (DG);
45  * 17-Nov-2004 : Updated methods for changes in DomainInfo interface (DG);
46  * 25-Nov-2004 : Added getTimePeriod(int) method (DG);
47  * 11-Jan-2005 : Removed deprecated code in preparation for the 1.0.0
48  * release (DG);
49  * 27-Jan-2005 : Modified to use TimePeriod rather than RegularTimePeriod (DG);
50  *
51  */

52
53 package org.jfree.data.time;
54
55 import java.util.Calendar JavaDoc;
56 import java.util.List JavaDoc;
57 import java.util.Locale JavaDoc;
58 import java.util.TimeZone JavaDoc;
59
60 import org.jfree.data.DefaultKeyedValues2D;
61 import org.jfree.data.DomainInfo;
62 import org.jfree.data.Range;
63 import org.jfree.data.general.DatasetChangeEvent;
64 import org.jfree.data.xy.AbstractIntervalXYDataset;
65 import org.jfree.data.xy.IntervalXYDataset;
66 import org.jfree.data.xy.TableXYDataset;
67 import org.jfree.util.PublicCloneable;
68
69 /**
70  * A dataset for regular time periods that implements the
71  * {@link TableXYDataset} interface.
72  *
73  * @see org.jfree.data.xy.TableXYDataset
74  * @author andreas.schroeder
75  */

76 public class TimeTableXYDataset extends AbstractIntervalXYDataset
77                                 implements Cloneable JavaDoc, PublicCloneable,
78                                            IntervalXYDataset,
79                                            DomainInfo,
80                                            TableXYDataset {
81     
82     /**
83      * The data structure to store the values. Each column represents
84      * a series (elsewhere in JFreeChart rows are typically used for series,
85      * but it doesn't matter that much since this data structure is private
86      * and symmetrical anyway), each row contains values for the same
87      * {@link RegularTimePeriod} (the rows are sorted into ascending order).
88      */

89     private DefaultKeyedValues2D values;
90     
91     /**
92      * A flag that indicates that the domain is 'points in time'. If this flag
93      * is true, only the x-value (and not the x-interval) is used to determine
94      * the range of values in the domain.
95      */

96     private boolean domainIsPointsInTime;
97     
98     /**
99      * The point within each time period that is used for the X value when this
100      * collection is used as an {@link org.jfree.data.xy.XYDataset}. This can
101      * be the start, middle or end of the time period.
102      */

103     private TimePeriodAnchor xPosition;
104
105     /** A working calendar (to recycle) */
106     private Calendar JavaDoc workingCalendar;
107
108     /**
109      * Creates a new dataset.
110      */

111     public TimeTableXYDataset() {
112         // defer argument checking
113
this(TimeZone.getDefault(), Locale.getDefault());
114     }
115     
116     /**
117      * Creates a new dataset with the given time zone.
118      *
119      * @param zone the time zone to use (<code>null</code> not permitted).
120      */

121     public TimeTableXYDataset(TimeZone JavaDoc zone) {
122         // defer argument checking
123
this(zone, Locale.getDefault());
124     }
125
126     /**
127      * Creates a new dataset with the given time zone and locale.
128      *
129      * @param zone the time zone to use (<code>null</code> not permitted).
130      * @param locale the locale to use (<code>null</code> not permitted).
131      */

132     public TimeTableXYDataset(TimeZone JavaDoc zone, Locale JavaDoc locale) {
133         if (zone == null) {
134             throw new IllegalArgumentException JavaDoc("Null 'zone' argument.");
135         }
136         if (locale == null) {
137             throw new IllegalArgumentException JavaDoc("Null 'locale' argument.");
138         }
139         this.values = new DefaultKeyedValues2D(true);
140         this.workingCalendar = Calendar.getInstance(zone, locale);
141         this.xPosition = TimePeriodAnchor.START;
142     }
143     
144     /**
145      * Returns a flag that controls whether the domain is treated as 'points in
146      * time'.
147      * <P>
148      * This flag is used when determining the max and min values for the domain.
149      * If true, then only the x-values are considered for the max and min
150      * values. If false, then the start and end x-values will also be taken
151      * into consideration.
152      *
153      * @return The flag.
154      */

155     public boolean getDomainIsPointsInTime() {
156         return this.domainIsPointsInTime;
157     }
158
159     /**
160      * Sets a flag that controls whether the domain is treated as 'points in
161      * time', or time periods. A {@link DatasetChangeEvent} is sent to all
162      * registered listeners.
163      *
164      * @param flag the new value of the flag.
165      */

166     public void setDomainIsPointsInTime(boolean flag) {
167         this.domainIsPointsInTime = flag;
168         notifyListeners(new DatasetChangeEvent(this, this));
169     }
170     
171     /**
172      * Returns the position within each time period that is used for the X
173      * value.
174      *
175      * @return The anchor position (never <code>null</code>).
176      */

177     public TimePeriodAnchor getXPosition() {
178         return this.xPosition;
179     }
180
181     /**
182      * Sets the position within each time period that is used for the X values,
183      * then sends a {@link DatasetChangeEvent} to all registered listeners.
184      *
185      * @param anchor the anchor position (<code>null</code> not permitted).
186      */

187     public void setXPosition(TimePeriodAnchor anchor) {
188         if (anchor == null) {
189             throw new IllegalArgumentException JavaDoc("Null 'anchor' argument.");
190         }
191         this.xPosition = anchor;
192         notifyListeners(new DatasetChangeEvent(this, this));
193     }
194         
195     /**
196      * Adds a new data item to the dataset and sends a
197      * {@link org.jfree.data.general.DatasetChangeEvent} to all registered
198      * listeners.
199      *
200      * @param period the time period.
201      * @param y the value for this period.
202      * @param seriesName the name of the series to add the value.
203      */

204     public void add(TimePeriod period, double y, String JavaDoc seriesName) {
205         add(period, new Double JavaDoc(y), seriesName, true);
206     }
207     
208     /**
209      * Adds a new data item to the dataset.
210      *
211      * @param period the time period (<code>null</code> not permitted).
212      * @param y the value for this period (<code>null</code> permitted).
213      * @param seriesName the name of the series to add the value
214      * (<code>null</code> not permitted).
215      * @param notify whether dataset listener are notified or not.
216      */

217     public void add(TimePeriod period, Number JavaDoc y, String JavaDoc seriesName,
218                     boolean notify) {
219         this.values.addValue(y, period, seriesName);
220         if (notify) {
221             fireDatasetChanged();
222         }
223     }
224
225     /**
226      * Removes an existing data item from the dataset.
227      *
228      * @param period the (existing!) time period of the value to remove
229      * (<code>null</code> not permitted).
230      * @param seriesName the (existing!) series name to remove the value
231      * (<code>null</code> not permitted).
232      */

233     public void remove(TimePeriod period, String JavaDoc seriesName) {
234         remove(period, seriesName, true);
235     }
236     
237     /**
238      * Removes an existing data item from the dataset.
239      *
240      * @param period the (existing!) time period of the value to remove
241      * (<code>null</code> not permitted).
242      * @param seriesName the (existing!) series name to remove the value
243      * (<code>null</code> not permitted).
244      * @param notify whether dataset listener are notified or not.
245      */

246     public void remove(TimePeriod period, String JavaDoc seriesName, boolean notify) {
247         this.values.removeValue(period, seriesName);
248         if (notify) {
249             fireDatasetChanged();
250         }
251     }
252
253     /**
254      * Returns the time period for the specified item. Bear in mind that all
255      * series share the same set of time periods.
256      *
257      * @param item the item index (0 <= i <= {@link #getItemCount()}).
258      *
259      * @return The time period.
260      */

261     public TimePeriod getTimePeriod(int item) {
262         return (TimePeriod) this.values.getRowKey(item);
263     }
264     
265     /**
266      * Returns the number of items in ALL series.
267      *
268      * @return The item count.
269      */

270     public int getItemCount() {
271         return this.values.getRowCount();
272     }
273
274     /**
275      * Returns the number of items in a series. This is the same value
276      * that is returned by {@link #getItemCount()} since all series
277      * share the same x-values (time periods).
278      *
279      * @param series the series (zero-based index, ignored).
280      *
281      * @return The number of items within the series.
282      */

283     public int getItemCount(int series) {
284         return getItemCount();
285     }
286     
287     /**
288      * Returns the number of series in the dataset.
289      *
290      * @return The series count.
291      */

292     public int getSeriesCount() {
293         return this.values.getColumnCount();
294     }
295
296     /**
297      * Returns the key for a series.
298      *
299      * @param series the series (zero-based index).
300      *
301      * @return The key for the series.
302      */

303     public Comparable JavaDoc getSeriesKey(int series) {
304         return this.values.getColumnKey(series);
305     }
306     
307     /**
308      * Returns the x-value for an item within a series. The x-values may or
309      * may not be returned in ascending order, that is up to the class
310      * implementing the interface.
311      *
312      * @param series the series (zero-based index).
313      * @param item the item (zero-based index).
314      *
315      * @return The x-value.
316      */

317     public Number JavaDoc getX(int series, int item) {
318         return new Double JavaDoc(getXValue(series, item));
319     }
320     
321     /**
322      * Returns the x-value (as a double primitive) for an item within a series.
323      *
324      * @param series the series index (zero-based).
325      * @param item the item index (zero-based).
326      *
327      * @return The value.
328      */

329     public double getXValue(int series, int item) {
330         TimePeriod period = (TimePeriod) this.values.getRowKey(item);
331         return getXValue(period);
332     }
333
334     /**
335      * Returns the starting X value for the specified series and item.
336      *
337      * @param series the series (zero-based index).
338      * @param item the item within a series (zero-based index).
339      *
340      * @return The starting X value for the specified series and item.
341      */

342     public Number JavaDoc getStartX(int series, int item) {
343         return new Double JavaDoc(getStartXValue(series, item));
344     }
345
346     /**
347      * Returns the start x-value (as a double primitive) for an item within
348      * a series.
349      *
350      * @param series the series index (zero-based).
351      * @param item the item index (zero-based).
352      *
353      * @return The value.
354      */

355     public double getStartXValue(int series, int item) {
356         TimePeriod period = (TimePeriod) this.values.getRowKey(item);
357         return period.getStart().getTime();
358     }
359
360     /**
361      * Returns the ending X value for the specified series and item.
362      *
363      * @param series the series (zero-based index).
364      * @param item the item within a series (zero-based index).
365      *
366      * @return The ending X value for the specified series and item.
367      */

368     public Number JavaDoc getEndX(int series, int item) {
369         return new Double JavaDoc(getEndXValue(series, item));
370     }
371
372     /**
373      * Returns the end x-value (as a double primitive) for an item within
374      * a series.
375      *
376      * @param series the series index (zero-based).
377      * @param item the item index (zero-based).
378      *
379      * @return The value.
380      */

381     public double getEndXValue(int series, int item) {
382         TimePeriod period = (TimePeriod) this.values.getRowKey(item);
383         return period.getEnd().getTime();
384     }
385  
386     /**
387      * Returns the y-value for an item within a series.
388      *
389      * @param series the series (zero-based index).
390      * @param item the item (zero-based index).
391      *
392      * @return The y-value (possibly <code>null</code>).
393      */

394     public Number JavaDoc getY(int series, int item) {
395         return this.values.getValue(item, series);
396     }
397     
398     /**
399      * Returns the starting Y value for the specified series and item.
400      *
401      * @param series the series (zero-based index).
402      * @param item the item within a series (zero-based index).
403      *
404      * @return The starting Y value for the specified series and item.
405      */

406     public Number JavaDoc getStartY(int series, int item) {
407         return getY(series, item);
408     }
409     
410     /**
411      * Returns the ending Y value for the specified series and item.
412      *
413      * @param series the series (zero-based index).
414      * @param item the item within a series (zero-based index).
415      *
416      * @return The ending Y value for the specified series and item.
417      */

418     public Number JavaDoc getEndY(int series, int item) {
419         return getY(series, item);
420     }
421     
422     /**
423      * Returns the x-value for a time period.
424      *
425      * @param period the time period.
426      *
427      * @return The x-value.
428      */

429     private long getXValue(TimePeriod period) {
430         long result = 0L;
431         if (this.xPosition == TimePeriodAnchor.START) {
432             result = period.getStart().getTime();
433         }
434         else if (this.xPosition == TimePeriodAnchor.MIDDLE) {
435             long t0 = period.getStart().getTime();
436             long t1 = period.getEnd().getTime();
437             result = t0 + (t1 - t0) / 2L;
438         }
439         else if (this.xPosition == TimePeriodAnchor.END) {
440             result = period.getEnd().getTime();
441         }
442         return result;
443     }
444     
445     /**
446      * Returns the minimum x-value in the dataset.
447      *
448      * @param includeInterval a flag that determines whether or not the
449      * x-interval is taken into account.
450      *
451      * @return The minimum value.
452      */

453     public double getDomainLowerBound(boolean includeInterval) {
454         double result = Double.NaN;
455         Range r = getDomainBounds(includeInterval);
456         if (r != null) {
457             result = r.getLowerBound();
458         }
459         return result;
460     }
461
462     /**
463      * Returns the maximum x-value in the dataset.
464      *
465      * @param includeInterval a flag that determines whether or not the
466      * x-interval is taken into account.
467      *
468      * @return The maximum value.
469      */

470     public double getDomainUpperBound(boolean includeInterval) {
471         double result = Double.NaN;
472         Range r = getDomainBounds(includeInterval);
473         if (r != null) {
474             result = r.getUpperBound();
475         }
476         return result;
477     }
478
479     /**
480      * Returns the range of the values in this dataset's domain.
481      *
482      * @param includeInterval a flag that controls whether or not the
483      * x-intervals are taken into account.
484      *
485      * @return The range.
486      */

487     public Range getDomainBounds(boolean includeInterval) {
488         List JavaDoc keys = this.values.getRowKeys();
489         if (keys.isEmpty()) {
490             return null;
491         }
492         
493         TimePeriod first = (TimePeriod) keys.get(0);
494         TimePeriod last = (TimePeriod) keys.get(keys.size() - 1);
495         
496         if (!includeInterval || this.domainIsPointsInTime) {
497             return new Range(getXValue(first), getXValue(last));
498         }
499         else {
500             return new Range(
501                 first.getStart().getTime(), last.getEnd().getTime()
502             );
503         }
504     }
505     
506     /**
507      * Tests this dataset for equality with an arbitrary object.
508      *
509      * @param obj the object (<code>null</code> permitted).
510      *
511      * @return A boolean.
512      */

513     public boolean equals(Object JavaDoc obj) {
514         if (obj == this) {
515             return true;
516         }
517         if (!(obj instanceof TimeTableXYDataset)) {
518             return false;
519         }
520         TimeTableXYDataset that = (TimeTableXYDataset) obj;
521         if (this.domainIsPointsInTime != that.domainIsPointsInTime) {
522             return false;
523         }
524         if (this.xPosition != that.xPosition) {
525             return false;
526         }
527         if (!this.workingCalendar.getTimeZone().equals(
528             that.workingCalendar.getTimeZone())
529         ) {
530             return false;
531         }
532         if (!this.values.equals(that.values)) {
533             return false;
534         }
535         return true;
536     }
537     
538     /**
539      * Returns a clone of this dataset.
540      *
541      * @return A clone.
542      *
543      * @throws CloneNotSupportedException if the dataset cannot be cloned.
544      */

545     public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
546         TimeTableXYDataset clone = (TimeTableXYDataset) super.clone();
547         clone.values = (DefaultKeyedValues2D) this.values.clone();
548         clone.workingCalendar = (Calendar JavaDoc) this.workingCalendar.clone();
549         return clone;
550     }
551
552 }
553
Popular Tags