1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package net.sf.statcvs.reportmodel;
24
25 import java.util.ArrayList;
26 import java.util.Date;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.TreeMap;
30
31 /**
32 * Contains time line data for an integer value. The semantics is that at
33 * every data point, the time line's value changed from the previous point's
34 * value to the current point's value. Time points may be specified either
35 * by an absolute value using <tt>addTimePoint</tt>, or by a value relative
36 * to the previous time point using {@link #addChange}. If all points are
37 * specified using <tt>addChange</tt>, an initial value must be given
38 * using {@link #setInitialValue}.
39 *
40 * @author Richard Cyganiak <rcyg@gmx.de>
41 * @version $Id: TimeLine.java,v 1.5 2008/04/02 11:52:02 benoitx Exp $
42 */
43 public class TimeLine {
44 private final TreeMap dataPoints = new TreeMap();
45 private Date minimumDate = null;
46 private int initialValue;
47 private boolean hasInitialValue = false;
48 private final String title;
49 private final String rangeLabel;
50
51 /**
52 * Creates a new time line.
53 * @param title the time line's title
54 * @param rangeLabel a range label (axis label) for the values
55 */
56 public TimeLine(final String title, final String rangeLabel) {
57 this.title = title;
58 this.rangeLabel = rangeLabel;
59 }
60
61 /**
62 * Sets the initial value of the time line, that is the value just before
63 * the first data point.
64 * @param initialValue the time line's initial value
65 */
66 public void setInitialValue(final int initialValue) {
67 this.initialValue = initialValue;
68 this.hasInitialValue = true;
69 }
70
71 /**
72 * Adds a data point to the time line. Data points may be added in any
73 * order.
74 * @param date the data point's date
75 * @param value the data point's value
76 */
77 public void addTimePoint(final Date date, final int value) {
78 addTimePoint(HelperTimePoint.createAbsoluteValueTimePoint(date, value));
79 }
80
81 /**
82 * Specifies that the time line's value changed at a given date. Data
83 * points may be added in any order.
84 * @param date the data point's date
85 * @param delta the value change at this time
86 */
87 public void addChange(final Date date, final int delta) {
88 addTimePoint(HelperTimePoint.createDeltaTimePoint(date, delta));
89 }
90
91 /**
92 * Checks if the time series is empty. A series is considered empty if
93 * it has zero or one time points. It takes two distinct time points
94 * to actually make it a series.
95 * @return <tt>true</tt> if the time series is empty
96 */
97 public boolean isEmpty() {
98 return dataPoints.size() <= 1;
99 }
100
101 /**
102 * Returns a <tt>List</tt> of data points, ordered by date.
103 * @return a <tt>List</tt> of {@link TimePoint}s
104 */
105 public List getDataPoints() {
106 List result;
107 int currentValue;
108 if (hasInitialValue && dataPoints.size() > 0) {
109 result = new ArrayList(dataPoints.size() + 1);
110 final Date beforeMinimum = new Date(minimumDate.getTime() - 1);
111 result.add(new TimePoint(beforeMinimum, initialValue, 0));
112 currentValue = initialValue;
113 } else {
114 result = new ArrayList(dataPoints.size());
115 if (dataPoints.size() == 0) {
116 return result;
117 }
118 final HelperTimePoint firstPoint = (HelperTimePoint) dataPoints.get(dataPoints.firstKey());
119 if (!firstPoint.isAbsolute()) {
120 throw new IllegalStateException("The first data point must be absolute, or setInitialValue must be used");
121 }
122 currentValue = firstPoint.getValue();
123 }
124 final Iterator it = dataPoints.values().iterator();
125 while (it.hasNext()) {
126 final HelperTimePoint point = (HelperTimePoint) it.next();
127 if (point.isAbsolute()) {
128 final int delta = point.getValue() - currentValue;
129 result.add(new TimePoint(point.getDate(), point.getValue(), delta));
130 currentValue = point.getValue();
131 } else {
132 currentValue += point.getValue();
133 result.add(new TimePoint(point.getDate(), currentValue, point.getValue()));
134 }
135 }
136 return result;
137 }
138
139 private void addTimePoint(HelperTimePoint newPoint) {
140 final HelperTimePoint oldPoint = (HelperTimePoint) dataPoints.get(newPoint.getDate());
141 if (oldPoint == null) {
142 if (minimumDate == null || newPoint.getDate().before(minimumDate)) {
143 minimumDate = newPoint.getDate();
144 }
145
146 } else {
147 newPoint = oldPoint.join(newPoint);
148 }
149 dataPoints.put(newPoint.getDate(), newPoint);
150 }
151
152 /**
153 * Returns the range label (axis label) of the values
154 * @return an axis label for the values
155 */
156 public String getRangeLabel() {
157 return rangeLabel;
158 }
159
160 /**
161 * Returns the title of the time line
162 * @return the title
163 */
164 public String getTitle() {
165 return title;
166 }
167 }