| 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 | } |