Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
TimeLine |
|
| 2.0;2 |
1 | /* | |
2 | StatCvs - CVS statistics generation | |
3 | Copyright (C) 2002 Lukasz Pekacki <lukasz@pekacki.de> | |
4 | http://statcvs.sf.net/ | |
5 | | |
6 | This library is free software; you can redistribute it and/or | |
7 | modify it under the terms of the GNU Lesser General Public | |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
10 | ||
11 | This library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Lesser General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Lesser General Public | |
17 | License along with this library; if not, write to the Free Software | |
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | | |
20 | $RCSfile: TimeLine.java,v $ | |
21 | $Date: 2008/04/02 11:52:02 $ | |
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 | 48 | private final TreeMap dataPoints = new TreeMap(); |
45 | 48 | private Date minimumDate = null; |
46 | private int initialValue; | |
47 | 48 | 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 | 48 | public TimeLine(final String title, final String rangeLabel) { |
57 | 48 | this.title = title; |
58 | 48 | this.rangeLabel = rangeLabel; |
59 | 48 | } |
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 | 16 | this.initialValue = initialValue; |
68 | 16 | this.hasInitialValue = true; |
69 | 16 | } |
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 | 40 | addTimePoint(HelperTimePoint.createAbsoluteValueTimePoint(date, value)); |
79 | 40 | } |
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 | 56 | addTimePoint(HelperTimePoint.createDeltaTimePoint(date, delta)); |
89 | 56 | } |
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 | 24 | 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 | 56 | if (hasInitialValue && dataPoints.size() > 0) { |
109 | 16 | result = new ArrayList(dataPoints.size() + 1); |
110 | 16 | final Date beforeMinimum = new Date(minimumDate.getTime() - 1); |
111 | 16 | result.add(new TimePoint(beforeMinimum, initialValue, 0)); |
112 | 16 | currentValue = initialValue; |
113 | 14 | } else { |
114 | 40 | result = new ArrayList(dataPoints.size()); |
115 | 40 | if (dataPoints.size() == 0) { |
116 | 8 | return result; |
117 | } | |
118 | 32 | final HelperTimePoint firstPoint = (HelperTimePoint) dataPoints.get(dataPoints.firstKey()); |
119 | 32 | if (!firstPoint.isAbsolute()) { |
120 | 8 | throw new IllegalStateException("The first data point must be absolute, or setInitialValue must be used"); |
121 | } | |
122 | 24 | currentValue = firstPoint.getValue(); |
123 | } | |
124 | 40 | final Iterator it = dataPoints.values().iterator(); |
125 | 120 | while (it.hasNext()) { |
126 | 80 | final HelperTimePoint point = (HelperTimePoint) it.next(); |
127 | 80 | if (point.isAbsolute()) { |
128 | 48 | final int delta = point.getValue() - currentValue; |
129 | 48 | result.add(new TimePoint(point.getDate(), point.getValue(), delta)); |
130 | 48 | currentValue = point.getValue(); |
131 | 42 | } else { |
132 | 32 | currentValue += point.getValue(); |
133 | 32 | result.add(new TimePoint(point.getDate(), currentValue, point.getValue())); |
134 | } | |
135 | 70 | } |
136 | 40 | return result; |
137 | } | |
138 | ||
139 | private void addTimePoint(HelperTimePoint newPoint) { | |
140 | 96 | final HelperTimePoint oldPoint = (HelperTimePoint) dataPoints.get(newPoint.getDate()); |
141 | 96 | if (oldPoint == null) { |
142 | 88 | if (minimumDate == null || newPoint.getDate().before(minimumDate)) { |
143 | 48 | minimumDate = newPoint.getDate(); |
144 | } | |
145 | 0 | //oldPoint = newPoint; |
146 | } else { | |
147 | 8 | newPoint = oldPoint.join(newPoint); |
148 | } | |
149 | 96 | dataPoints.put(newPoint.getDate(), newPoint); |
150 | 96 | } |
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 | 8 | return rangeLabel; |
158 | } | |
159 | ||
160 | /** | |
161 | * Returns the title of the time line | |
162 | * @return the title | |
163 | */ | |
164 | public String getTitle() { | |
165 | 8 | return title; |
166 | } | |
167 | } |