View Javadoc

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      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             //oldPoint = newPoint;
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 }