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  	Created on $Date: 2009/04/25 16:36: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   * Produces the commit scatter chart.
58   * @author jentzsch
59   * @author Richard Cyganiak (richard@cyganiak.de)
60   */
61  public class CommitScatterChartMaker {
62      private static final String CHART_NAME = "commitscatterauthors";
63      private final static Color ALL_COMMITS_COLOR = new Color(128, 128, 255);
64      private final ReportConfig config;
65      private final Repository repository;
66      private final int width;
67  
68      /**
69       * Creates a new CommitScatterChartMaker.
70       * @param repository The repository to be analyzed
71       * @param width The width of the chart in pixels
72       */
73      public CommitScatterChartMaker(final ReportConfig config, final int width) {
74          this.config = config;
75          this.repository = config.getRepository();
76          this.width = width;
77      }
78  
79      /**
80       * @return An image file for the chart
81       */
82      public ChartImage toFile() {
83          final DateAxis timeAxis = new DateAxis(Messages.getString("TIME_CSC_DOMAIN"));
84          timeAxis.setVerticalTickLabels(true);
85          final CombinedDomainXYPlot combinedPlot = new CombinedDomainXYPlot(timeAxis);
86          List annotations = SymbolicNameAnnotation.createAnnotations(repository.getSymbolicNames());
87          combinedPlot.add(createPlot(createTimeSeries(this.repository.getRevisions()), "All (" + Messages.getString("TIME_CSC_RANGE") + ")", ALL_COMMITS_COLOR,
88                  annotations));
89          annotations = SymbolicNameAnnotation.createAnnotations(repository.getSymbolicNames(), SymbolicNameAnnotation.STYLE_NO_LABELS);
90          final List authors = new ArrayList(this.repository.getAuthors());
91          Collections.sort(authors);
92          final Iterator it = authors.iterator();
93          while (it.hasNext()) {
94              final Author author = (Author) it.next();
95              final Color color = this.config.isDeveloper(author) ? Color.RED : Color.GRAY;
96              combinedPlot.add(createPlot(createTimeSeries(author.getRevisions()), author.getName(), color, annotations));
97          }
98          combinedPlot.setGap(10);
99          final JFreeChart chart = new JFreeChart(this.config.getProjectName() + ": " + Messages.getString("TIME_CSC_SUBTITLE"), JFreeChart.DEFAULT_TITLE_FONT,
100                 combinedPlot, false);
101 
102         combinedPlot.setBackgroundPaint(ChartConfigUtil.getPlotColor(CHART_NAME));
103         chart.setBackgroundPaint(ChartConfigUtil.getBackgroundColor(CHART_NAME));
104         final XYItemRenderer renderer = combinedPlot.getRenderer();
105         ChartConfigUtil.configureShapes(CHART_NAME, renderer);
106         ChartConfigUtil.configureCopyrightNotice(CHART_NAME, chart);
107         ChartConfigUtil.configureChartBackgroungImage(CHART_NAME, chart);
108         ChartConfigUtil.configurePlotImage(CHART_NAME, chart);
109 
110         final Dimension dim = ChartConfigUtil.getDimension(CHART_NAME, config.getLargeChartSize());
111 
112         return this.config.createChartImage(CHART_NAME + ".png", Messages.getString("TIME_CSC_SUBTITLE"), chart, getSize(dim));
113     }
114 
115     private TimeSeries createTimeSeries(final SortedSet revisions) {
116         final TimeSeries result = new TimeSeries("Dummy", Second.class);
117         final Iterator it = revisions.iterator();
118         Date lastDate = new Date();
119         while (it.hasNext()) {
120             final Revision rev = (Revision) it.next();
121             if (lastDate != null) {
122                 final Calendar cal = Calendar.getInstance();
123                 cal.setTime(lastDate);
124                 final double lastDateSeconds = cal.get(Calendar.SECOND);
125                 cal.setTime(rev.getDate());
126                 final double dateSeconds = cal.get(Calendar.SECOND);
127                 if (lastDateSeconds == dateSeconds) {
128                     continue;
129                 }
130             }
131             lastDate = rev.getDate();
132             final Calendar cal = Calendar.getInstance();
133             cal.setTime(lastDate);
134             final double hour = cal.get(Calendar.HOUR_OF_DAY);
135             final double minutes = cal.get(Calendar.MINUTE);
136             result.add(new Second(lastDate), hour + minutes / 60.0);
137         }
138         return result;
139     }
140 
141     private XYPlot createPlot(final TimeSeries series, final String label, final Color color, final List annotations) {
142         final NumberAxis valueAxis = new NumberAxis(label);
143         valueAxis.setTickUnit(new NumberTickUnit(6.0, new DecimalFormat("0")));
144         valueAxis.setAutoRangeIncludesZero(false);
145         valueAxis.setRange(0.0, 24.0);
146         valueAxis.setLabelFont(new Font("SansSerif", Font.PLAIN, 9));
147         final XYItemRenderer renderer = new StandardXYItemRenderer(StandardXYItemRenderer.SHAPES);
148         renderer.setShape(new Rectangle(new Dimension(2, 2)));
149         final XYPlot result = new XYPlot(new TimeSeriesCollection(series), null, valueAxis, renderer);
150         result.getRenderer().setSeriesPaint(0, color);
151         final Iterator it = annotations.iterator();
152         while (it.hasNext()) {
153             final XYAnnotation annotation = (XYAnnotation) it.next();
154             result.addAnnotation(annotation);
155         }
156         return result;
157     }
158 
159     private Dimension getSize(final Dimension dim) {
160         return new Dimension(dim.width, 70 * (this.repository.getAuthors().size() + 1) + 110);
161     }
162 }