1 package net.sf.statcvs.charts;
2
3 import java.awt.Dimension;
4 import java.util.ArrayList;
5 import java.util.Date;
6 import java.util.Iterator;
7 import java.util.LinkedHashMap;
8 import java.util.List;
9 import java.util.Map;
10
11 import net.sf.statcvs.model.Module;
12 import net.sf.statcvs.model.Repository;
13 import net.sf.statcvs.model.Revision;
14 import net.sf.statcvs.output.ReportConfig;
15 import net.sf.statcvs.util.IntegerMap;
16
17 import org.jfree.chart.JFreeChart;
18 import org.jfree.chart.axis.ColorBar;
19 import org.jfree.chart.axis.DateAxis;
20 import org.jfree.chart.axis.SymbolAxis;
21 import org.jfree.chart.axis.ValueAxis;
22 import org.jfree.chart.plot.ContourPlot;
23 import org.jfree.data.contour.ContourDataset;
24 import org.jfree.data.contour.DefaultContourDataset;
25 import org.jfree.ui.RectangleEdge;
26
27 /**
28 * Class for producing directory pie charts
29 * @author jentzsch
30 * @author Richard Cyganiak (richard@cyganiak.de)
31 * @version $Id: ModuleEvolutionChartMaker.java,v 1.2 2010/01/01 10:03:43 benoitx Exp $
32 */
33 public class ModuleEvolutionChartMaker {
34 private static final int SLICE_MIN_PERCENT = 5;
35
36 private final ReportConfig config;
37 private final String title;
38 private final String fileName;
39 private final List files = new ArrayList();
40 private final String chartName;
41 private final Repository repository;
42
43 /**
44 * Creates a new PieChartMaker
45 * @param config The report configuration to use
46 * @param directories The set of directories to consider
47 * @param title The chart title
48 * @param fileName The file name for chart
49 */
50 public ModuleEvolutionChartMaker(final String chartName, final ReportConfig config, final String title, final String fileName) {
51 this.chartName = chartName;
52 this.config = config;
53 this.title = title;
54 this.fileName = fileName;
55 this.repository = config.getRepository();
56 }
57
58 public ChartImage toFile() {
59
60 final ContourDataset data = buildDs();
61
62 if (data == null) {
63 return null;
64 }
65
66 final ValueAxis xAxis = new DateAxis("Date");
67 final SymbolAxis yAxis = new SymbolAxis("Module", (String[]) repository.getModules().keySet().toArray(new String[0]));
68
69
70 yAxis.setInverted(true);
71 yAxis.setLowerMargin(0.0);
72 yAxis.setUpperMargin(0.0);
73
74 final ColorBar zAxis = new ColorBar("Commit Activity (%)");
75 zAxis.getAxis();
76
77 final ContourPlot plot = new ContourPlot(data, xAxis, yAxis, zAxis);
78
79
80 plot.setDataAreaRatio(0.0);
81 plot.setColorBarLocation(RectangleEdge.BOTTOM);
82
83 final JFreeChart chart = new JFreeChart(config.getProjectName(), null, plot, false);
84
85 plot.setBackgroundPaint(ChartConfigUtil.getPlotColor(chartName));
86 chart.setBackgroundPaint(ChartConfigUtil.getBackgroundColor(chartName));
87 ChartConfigUtil.configureCopyrightNotice(chartName, chart);
88 ChartConfigUtil.configureChartBackgroungImage(chartName, chart);
89 ChartConfigUtil.configurePlotImage(chartName, chart);
90 final Dimension dim = ChartConfigUtil.getDimension(chartName, config.getLargeChartSize());
91 return this.config.createChartImage(this.fileName, this.title, chart, dim);
92 }
93
94 private ContourDataset buildDs() {
95 final Map mapByDate = new LinkedHashMap();
96 int max = 0;
97 final long elapsed = repository.getLastDate().getTime() - repository.getFirstDate().getTime();
98 final long windowSize = Math.max(elapsed / 60, 1);
99
100 IntegerMap commitsPerModule = new IntegerMap();
101
102 final Iterator itRev = repository.getRevisions().iterator();
103
104 long currentDate = -1;
105 while (itRev.hasNext()) {
106 final Revision rev = (Revision) itRev.next();
107
108 final Date date = rev.getDate();
109 System.out.println("| Consider Rev " + rev.getDate() + " Mod:" + rev.getFile().getModule().getName() + " currentDate:" + currentDate);
110 if (currentDate == -1) {
111 currentDate = date.getTime();
112 } else if (date.getTime() > currentDate + windowSize) {
113
114 max = Math.max(commitsPerModule.max(), max);
115 mapByDate.put(new Date(currentDate), commitsPerModule);
116
117
118 commitsPerModule = new IntegerMap();
119
120
121 final int fill = (int) ((date.getTime() - currentDate) / windowSize);
122 if (fill > 1) {
123 mapByDate.put(new Date(currentDate + windowSize), null);
124 }
125 currentDate += fill * windowSize;
126 }
127 commitsPerModule.inc(rev.getFile().getModule().getName());
128 }
129 if (currentDate != -1) {
130 mapByDate.put(new Date(currentDate), commitsPerModule);
131 max = Math.max(commitsPerModule.max(), max);
132 }
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 System.out.println("Module Commit");
172 Iterator it = mapByDate.keySet().iterator();
173 while (it.hasNext()) {
174 final Object key = it.next();
175 final IntegerMap map = (IntegerMap) mapByDate.get(key);
176 System.out.println("Key:" + key);
177 if (map != null) {
178 final Iterator it2 = map.iteratorSortedByKey();
179 while (it2.hasNext()) {
180 final Object o = it2.next();
181 System.out.println("Val:" + o + "\t -> " + map.get(o));
182 }
183 }
184 }
185
186 final int groupCount = repository.getModules().size();
187
188 final int dateCount = mapByDate.size();
189 final int numValues = dateCount * groupCount;
190 if (numValues == 0 || max == 0 || dateCount == 1) {
191 return null;
192 }
193
194 final Date[] oDateX = new Date[numValues];
195 final Double[] oDoubleY = new Double[numValues];
196 final Double[] oDoubleZ = new Double[numValues];
197
198 it = mapByDate.keySet().iterator();
199 for (int x = 0; x < dateCount; x++) {
200 if (!it.hasNext()) {
201 throw new RuntimeException("Invalid date count");
202 }
203 final Date date = (Date) it.next();
204
205 final IntegerMap map = (IntegerMap) mapByDate.get(date);
206 if (map != null) {
207 final Iterator it2 = repository.getModules().values().iterator();
208 for (int y = 0; y < groupCount; y++) {
209 if (!it2.hasNext()) {
210 throw new RuntimeException("Invalid group count");
211 }
212 final Module group = (Module) it2.next();
213
214 final int index = (x * groupCount) + y;
215 oDateX[index] = date;
216 oDoubleY[index] = new Double(y);
217 final double value = map.get(group.getName()) * 100.0 / max;
218 oDoubleZ[index] = (value != 0) ? new Double(value) : null;
219 }
220 } else {
221 for (int y = 0; y < groupCount; y++) {
222 final int index = (x * groupCount) + y;
223 oDateX[index] = date;
224 oDoubleY[index] = new Double(y);
225
226 }
227 }
228 }
229 return new DefaultContourDataset(null, oDateX, oDoubleY, oDoubleZ);
230 }
231 }