1 package net.sf.statcvs.charts;
2
3 import java.awt.Color;
4 import java.awt.Dimension;
5 import java.text.DecimalFormat;
6 import java.util.ArrayList;
7 import java.util.Collection;
8 import java.util.Collections;
9 import java.util.Iterator;
10 import java.util.Set;
11
12 import net.sf.statcvs.Messages;
13 import net.sf.statcvs.model.Author;
14 import net.sf.statcvs.model.Commit;
15 import net.sf.statcvs.model.Repository;
16 import net.sf.statcvs.model.Revision;
17 import net.sf.statcvs.output.ReportConfig;
18
19 import org.jfree.chart.ChartFactory;
20 import org.jfree.chart.JFreeChart;
21 import org.jfree.chart.axis.NumberAxis;
22 import org.jfree.chart.axis.NumberTickUnit;
23 import org.jfree.chart.plot.CategoryPlot;
24 import org.jfree.chart.plot.PlotOrientation;
25 import org.jfree.chart.renderer.category.CategoryItemRenderer;
26 import org.jfree.data.category.DefaultCategoryDataset;
27 import org.jfree.ui.RectangleEdge;
28
29 /**
30 * Class for producing the "Author Activity: Modifying/Adding" chart
31 * @author jentzsch
32 * @author Richard Cyganiak (richard@cyganiak.de)
33 * @version $Id: ModifyAddChartMaker.java,v 1.9 2009/04/25 16:36:20 benoitx Exp $
34 */
35 public class ModifyAddChartMaker {
36 private static final String CHART_NAME = "activity";
37 private static final int MODIFYING = 0;
38 private static final int ADDING = 1;
39
40 private final ReportConfig config;
41 private final Repository repository;
42 private final int width;
43 private double[][] categories;
44 private final ArrayList categoryNames = new ArrayList();
45
46 /**
47 * Creates a new ModifyAddChartMaker
48 * @param content Repository
49 * @param width width of the chart in pixels
50 */
51 public ModifyAddChartMaker(final ReportConfig config, final int width) {
52 this.config = config;
53 this.repository = config.getRepository();
54 this.width = width;
55 }
56
57 public ChartImage toFile() {
58 final Collection authors = this.repository.getAuthors();
59 final Iterator it = authors.iterator();
60 while (it.hasNext()) {
61 final Author author = (Author) it.next();
62 if (!config.isDeveloper(author)) {
63 continue;
64 }
65 categoryNames.add(author.getRealName());
66 }
67 Collections.sort(categoryNames);
68
69 categories = new double[2][categoryNames.size()];
70 for (int j = 0; j < categoryNames.size(); j++) {
71 categories[MODIFYING][j] = 0;
72 categories[ADDING][j] = 0;
73 }
74
75 final Iterator commitIt = this.repository.getCommits().iterator();
76 while (commitIt.hasNext()) {
77 final Commit commit = (Commit) commitIt.next();
78 final Set commitRevList = commit.getRevisions();
79 final Iterator commitRevIt = commitRevList.iterator();
80 final String authorName = commit.getAuthor().getRealName();
81 if (authorName == null) {
82 continue;
83 }
84 final int author = categoryNames.indexOf(authorName);
85 if (author == -1) {
86 continue;
87 }
88 int linesAdded = 0;
89 int linesRemoved = 0;
90 while (commitRevIt.hasNext()) {
91 final Revision revision = (Revision) commitRevIt.next();
92 if (revision.getLinesDelta() > 0) {
93 linesAdded += revision.getLinesDelta() + revision.getReplacedLines();
94 linesRemoved += revision.getReplacedLines();
95 } else {
96 linesAdded += revision.getReplacedLines();
97 linesRemoved += -revision.getLinesDelta() + revision.getReplacedLines();
98 }
99 }
100 if (linesAdded == linesRemoved) {
101 categories[MODIFYING][author] += linesAdded;
102 }
103 if (linesAdded < linesRemoved) {
104 categories[MODIFYING][author] += linesRemoved;
105 }
106 if (linesAdded > linesRemoved) {
107 categories[ADDING][author] += linesAdded - linesRemoved;
108 categories[MODIFYING][author] += linesRemoved;
109 }
110 }
111
112 for (int i = 0; i < categoryNames.size(); i++) {
113 final double maxLines = categories[MODIFYING][i] + categories[ADDING][i];
114 for (int k = 0; k < 2; k++) {
115 categories[k][i] *= (100 / maxLines);
116 }
117 }
118
119 final DefaultCategoryDataset data = new DefaultCategoryDataset();
120 for (int i = 0; i < categories[MODIFYING].length; i++) {
121 data.addValue(categories[MODIFYING][i], "modifying", (Comparable) categoryNames.get(i));
122 }
123 for (int j = 0; j < categories[ADDING].length; j++) {
124 data.addValue(categories[ADDING][j], "adding", (Comparable) categoryNames.get(j));
125 }
126
127
128
129
130 final JFreeChart chart = ChartFactory.createStackedBarChart(this.config.getProjectName() + ": " + Messages.getString("AUTHOR_ACTIVITY_TITLE"), "", "%",
131 data, PlotOrientation.HORIZONTAL, true, false, false);
132
133 final CategoryPlot plot = chart.getCategoryPlot();
134
135 final CategoryItemRenderer renderer = plot.getRenderer();
136 renderer.setSeriesPaint(0, Color.yellow);
137 renderer.setSeriesPaint(1, Color.green);
138
139 final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
140 rangeAxis.setTickUnit(new NumberTickUnit(20.0, new DecimalFormat("0")));
141 rangeAxis.setUpperBound(100.0);
142
143 chart.getLegend().setPosition(RectangleEdge.TOP);
144
145 plot.setBackgroundPaint(ChartConfigUtil.getPlotColor(CHART_NAME));
146 chart.setBackgroundPaint(ChartConfigUtil.getBackgroundColor(CHART_NAME));
147
148
149
150 ChartConfigUtil.configureCopyrightNotice(CHART_NAME, chart);
151 ChartConfigUtil.configureChartBackgroungImage(CHART_NAME, chart);
152 ChartConfigUtil.configurePlotImage(CHART_NAME, chart);
153
154 final Dimension dim = ChartConfigUtil.getDimension(CHART_NAME, new Dimension(config.getSmallChartSize().width, 19));
155 final int totalHeight = dim.height * this.categoryNames.size() + 110;
156 return this.config.createChartImage(CHART_NAME + ".png", Messages.getString("AUTHOR_ACTIVITY_TITLE"), chart, new Dimension(dim.width, totalHeight));
157 }
158 }