View Javadoc

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          //        SymbolicAxis yAxis = new SymbolicAxis(grouper.getName(), (String[])groupNames.toArray(new String[0])); 
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          //plot.setRenderAsPoints(true);
79          // don't use plot units for ratios when x axis is date
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                 // save old map
114                 max = Math.max(commitsPerModule.max(), max);
115                 mapByDate.put(new Date(currentDate), commitsPerModule);
116 
117                 // create new map
118                 commitsPerModule = new IntegerMap();
119 
120                 // hack: fill in intermediate values
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         final Iterator itMod = repository.getModules().values().iterator();
136 
137         while (itMod.hasNext()) {
138             final Module module = (Module) itMod.next();
139             final Iterator it = module.getRevisions().iterator();
140             System.out.println("Consider Module " + module.getName());
141             long currentDate = -1;
142             while (it.hasNext()) {
143                 final Revision rev = (Revision) it.next();
144                 final Date date = rev.getDate();
145                 System.out.println(module.getName() + " | Consider Rev " + rev.getDate() + " currentDate:" + currentDate);
146                 if (currentDate == -1) {
147                     currentDate = date.getTime();
148                 } else if (date.getTime() > currentDate + windowSize) {
149                     // save old map
150                     max = Math.max(commitsPerModule.max(), max);
151                     mapByDate.put(new Date(currentDate), commitsPerModule);
152 
153                     // create new map
154                     commitsPerModule = new IntegerMap();
155 
156                     // hack: fill in intermediate values
157                     final int fill = (int) ((date.getTime() - currentDate) / windowSize);
158                     if (fill > 1) {
159                         mapByDate.put(new Date(currentDate + windowSize), null);
160                     }
161                     currentDate += fill * windowSize;
162                 }
163                 commitsPerModule.inc(module.getName());
164             }
165             if (currentDate != -1) {
166                 mapByDate.put(new Date(currentDate), commitsPerModule);
167                 max = Math.max(commitsPerModule.max(), max);
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                     //oDoubleZ[index] = null;
226                 }
227             }
228         }
229         return new DefaultContourDataset(null, oDateX, oDoubleY, oDoubleZ);
230     }
231 }