1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  package net.sf.statcvs.charts;
23  
24  import java.awt.Color;
25  import java.awt.Dimension;
26  import java.awt.Font;
27  import java.awt.Rectangle;
28  import java.text.DecimalFormat;
29  import java.util.ArrayList;
30  import java.util.Calendar;
31  import java.util.Collections;
32  import java.util.Date;
33  import java.util.Iterator;
34  import java.util.List;
35  import java.util.SortedSet;
36  
37  import net.sf.statcvs.Messages;
38  import net.sf.statcvs.model.Author;
39  import net.sf.statcvs.model.Repository;
40  import net.sf.statcvs.model.Revision;
41  import net.sf.statcvs.output.ReportConfig;
42  
43  import org.jfree.chart.JFreeChart;
44  import org.jfree.chart.annotations.XYAnnotation;
45  import org.jfree.chart.axis.DateAxis;
46  import org.jfree.chart.axis.NumberAxis;
47  import org.jfree.chart.axis.NumberTickUnit;
48  import org.jfree.chart.plot.CombinedDomainXYPlot;
49  import org.jfree.chart.plot.XYPlot;
50  import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
51  import org.jfree.chart.renderer.xy.XYItemRenderer;
52  import org.jfree.data.time.Second;
53  import org.jfree.data.time.TimeSeries;
54  import org.jfree.data.time.TimeSeriesCollection;
55  
56  
57  
58  
59  
60  
61  public class CommitScatterChartMaker {
62      private final static Color ALL_COMMITS_COLOR = new Color(128, 128, 255);
63      private final ReportConfig config;
64      private final Repository repository;
65      private final int width;
66  
67      
68  
69  
70  
71  
72      public CommitScatterChartMaker(final ReportConfig config, final int width) {
73          this.config = config;
74          this.repository = config.getRepository();
75          this.width = width;
76      }
77  
78      
79  
80  
81      public ChartImage toFile() {
82          final DateAxis timeAxis = new DateAxis(Messages.getString("TIME_CSC_DOMAIN"));
83          timeAxis.setVerticalTickLabels(true);
84          final CombinedDomainXYPlot combinedPlot = new CombinedDomainXYPlot(timeAxis);
85          List annotations = SymbolicNameAnnotation.createAnnotations(repository.getSymbolicNames());
86          combinedPlot.add(createPlot(createTimeSeries(this.repository.getRevisions()), "All (" + Messages.getString("TIME_CSC_RANGE") + ")", ALL_COMMITS_COLOR,
87                  annotations));
88          annotations = SymbolicNameAnnotation.createAnnotations(repository.getSymbolicNames(), SymbolicNameAnnotation.STYLE_NO_LABELS);
89          final List authors = new ArrayList(this.repository.getAuthors());
90          Collections.sort(authors);
91          final Iterator it = authors.iterator();
92          while (it.hasNext()) {
93              final Author author = (Author) it.next();
94              final Color color = this.config.isDeveloper(author) ? Color.RED : Color.GRAY;
95              combinedPlot.add(createPlot(createTimeSeries(author.getRevisions()), author.getName(), color, annotations));
96          }
97          combinedPlot.setGap(10);
98          final JFreeChart chart = new JFreeChart(this.config.getProjectName() + ": " + Messages.getString("TIME_CSC_SUBTITLE"), JFreeChart.DEFAULT_TITLE_FONT,
99                  combinedPlot, false);
100         return this.config.createChartImage("commitscatterauthors.png", Messages.getString("TIME_CSC_SUBTITLE"), chart, getSize());
101     }
102 
103     private TimeSeries createTimeSeries(final SortedSet revisions) {
104         final TimeSeries result = new TimeSeries("Dummy", Second.class);
105         final Iterator it = revisions.iterator();
106         Date lastDate = new Date();
107         while (it.hasNext()) {
108             final Revision rev = (Revision) it.next();
109             if (lastDate != null) {
110                 final Calendar cal = Calendar.getInstance();
111                 cal.setTime(lastDate);
112                 final double lastDateSeconds = cal.get(Calendar.SECOND);
113                 cal.setTime(rev.getDate());
114                 final double dateSeconds = cal.get(Calendar.SECOND);
115                 if (lastDateSeconds == dateSeconds) {
116                     continue;
117                 }
118             }
119             lastDate = rev.getDate();
120             final Calendar cal = Calendar.getInstance();
121             cal.setTime(lastDate);
122             final double hour = cal.get(Calendar.HOUR_OF_DAY);
123             final double minutes = cal.get(Calendar.MINUTE);
124             result.add(new Second(lastDate), hour + minutes / 60.0);
125         }
126         return result;
127     }
128 
129     private XYPlot createPlot(final TimeSeries series, final String label, final Color color, final List annotations) {
130         final NumberAxis valueAxis = new NumberAxis(label);
131         valueAxis.setTickUnit(new NumberTickUnit(6.0, new DecimalFormat("0")));
132         valueAxis.setAutoRangeIncludesZero(false);
133         valueAxis.setRange(0.0, 24.0);
134         valueAxis.setLabelFont(new Font("SansSerif", Font.PLAIN, 9));
135         final XYItemRenderer renderer = new StandardXYItemRenderer(StandardXYItemRenderer.SHAPES);
136         renderer.setShape(new Rectangle(new Dimension(2, 2)));
137         final XYPlot result = new XYPlot(new TimeSeriesCollection(series), null, valueAxis, renderer);
138         result.getRenderer().setSeriesPaint(0, color);
139         final Iterator it = annotations.iterator();
140         while (it.hasNext()) {
141             final XYAnnotation annotation = (XYAnnotation) it.next();
142             result.addAnnotation(annotation);
143         }
144         return result;
145     }
146 
147     private Dimension getSize() {
148         return new Dimension(this.width, 70 * (this.repository.getAuthors().size() + 1) + 110);
149     }
150 }