1 package net.sf.statcvs.charts;
2
3 import java.awt.Color;
4 import java.awt.Dimension;
5 import java.awt.Paint;
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.SortedSet;
13 import java.util.Map.Entry;
14
15 import net.sf.statcvs.Messages;
16 import net.sf.statcvs.model.Author;
17 import net.sf.statcvs.model.Directory;
18 import net.sf.statcvs.model.Revision;
19 import net.sf.statcvs.model.VersionedFile;
20 import net.sf.statcvs.output.ReportConfig;
21 import net.sf.statcvs.pages.HTML;
22 import net.sf.statcvs.util.IntegerMap;
23
24 import org.jfree.chart.ChartFactory;
25 import org.jfree.chart.JFreeChart;
26 import org.jfree.chart.plot.PiePlot;
27 import org.jfree.data.general.DefaultPieDataset;
28
29 /**
30 * Class for producing directory pie charts
31 * @author jentzsch
32 * @author Richard Cyganiak (richard@cyganiak.de)
33 * @version $Id: DirectoryPieChartMaker.java,v 1.13 2009/04/25 16:36:20 benoitx Exp $
34 */
35 public abstract class DirectoryPieChartMaker {
36 private static final int SLICE_MIN_PERCENT = 5;
37
38 private final ReportConfig config;
39 private final String title;
40 private final String fileName;
41 private List directories = new ArrayList();
42 private final String chartName;
43
44 /**
45 * Creates a new PieChartMaker
46 * @param config The report configuration to use
47 * @param directories The set of directories to consider
48 * @param title The chart title
49 * @param fileName The file name for chart
50 */
51 public DirectoryPieChartMaker(final String chartName, final ReportConfig config, final SortedSet directories, final String title, final String fileName) {
52 this.chartName = chartName;
53 this.config = config;
54 this.title = title;
55 this.fileName = fileName;
56 this.directories = new ArrayList(directories);
57 }
58
59 public ChartImage toFile() {
60 final DefaultPieDataset data = new DefaultPieDataset();
61
62 final IntegerMap dirSizes = new IntegerMap();
63 Collections.sort(directories);
64 Iterator it = directories.iterator();
65 while (it.hasNext()) {
66 final Directory dir = (Directory) it.next();
67 dirSizes.addInt(dir, calculateValue(dir));
68 }
69
70 int otherSum = 0;
71 final Map colors = new HashMap();
72 it = dirSizes.iteratorSortedByValue();
73 while (it.hasNext()) {
74 final Directory dir = (Directory) it.next();
75 if (dirSizes.getPercent(dir) >= SLICE_MIN_PERCENT) {
76 final String dirName = dir.isRoot() ? "/" : dir.getPath();
77 data.setValue(dirName, dirSizes.getInteger(dir));
78 colors.put(dirName, ChartUtils.getStringColor(dirName));
79 } else {
80 otherSum += dirSizes.get(dir);
81 }
82 }
83 data.setValue(Messages.getString("PIE_MODSIZE_OTHER"), new Integer(otherSum));
84 colors.put(Messages.getString("PIE_MODSIZE_OTHER"), Color.GRAY);
85
86 final JFreeChart chart = ChartFactory.createPieChart(this.config.getProjectName() + ": " + title, data, false, false, false);
87
88 final PiePlot plot = (PiePlot) chart.getPlot();
89 plot.setShadowPaint(null);
90 plot.setLabelShadowPaint(null);
91 plot.setLabelOutlinePaint(Color.LIGHT_GRAY);
92 plot.setForegroundAlpha(0.8f);
93 plot.setSectionOutlinePaint(Color.BLACK);
94 it = colors.entrySet().iterator();
95 while (it.hasNext()) {
96 final Entry entry = (Entry) it.next();
97 plot.setSectionPaint((String) entry.getKey(), (Paint) entry.getValue());
98 }
99
100 plot.setBackgroundPaint(ChartConfigUtil.getPlotColor(chartName));
101 chart.setBackgroundPaint(ChartConfigUtil.getBackgroundColor(chartName));
102
103
104 ChartConfigUtil.configureCopyrightNotice(chartName, chart);
105 ChartConfigUtil.configureChartBackgroungImage(chartName, chart);
106 ChartConfigUtil.configurePlotImage(chartName, chart);
107
108 final Dimension dim = ChartConfigUtil.getDimension(chartName, config.getLargeChartSize());
109
110 return this.config.createChartImage(this.fileName, this.title, chart, dim);
111 }
112
113 protected abstract int calculateValue(Directory directory);
114
115 public static class DirectorySizesChartMaker extends DirectoryPieChartMaker {
116 public DirectorySizesChartMaker(final ReportConfig config) {
117 super("directory_sizes", config, config.getRepository().getDirectories(), Messages.getString("PIE_MODSIZE_SUBTITLE"), "directory_sizes.png");
118 }
119
120 protected int calculateValue(final Directory directory) {
121 int result = 0;
122 final Iterator fileIt = directory.getFiles().iterator();
123 while (fileIt.hasNext()) {
124 final VersionedFile element = (VersionedFile) fileIt.next();
125 result += element.getCurrentLinesOfCode();
126 }
127 return result;
128 }
129 }
130
131 public static class CodeDistributionChartMaker extends DirectoryPieChartMaker {
132 private static String getFileName(final Author author) {
133 return "directory_sizes_" + HTML.escapeAuthorName(author.getName()) + ".png";
134 }
135
136 private final Author author;
137
138 public CodeDistributionChartMaker(final ReportConfig config, final Author author) {
139 super("directory_sizes", config, author.getDirectories(), Messages.getString("PIE_CODEDISTRIBUTION_SUBTITLE") + " " + author.getRealName(),
140 getFileName(author));
141 this.author = author;
142 }
143
144 public ChartImage toFile() {
145 final Iterator it = this.author.getRevisions().iterator();
146 int totalLinesOfCode = 0;
147 while (it.hasNext()) {
148 final Revision rev = (Revision) it.next();
149 totalLinesOfCode += rev.getNewLines();
150 }
151 if (totalLinesOfCode == 0) {
152 return null;
153 }
154 return super.toFile();
155 }
156
157 protected int calculateValue(final Directory directory) {
158 int result = 0;
159 final Iterator it = directory.getRevisions().iterator();
160 while (it.hasNext()) {
161 final Revision rev = (Revision) it.next();
162 if (!this.author.equals(rev.getAuthor())) {
163 continue;
164 }
165 result += rev.getNewLines();
166 }
167 return result;
168 }
169 }
170 }