KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jdiff > HTMLStatistics


1 package jdiff;
2
3 import java.util.*;
4 import java.io.*;
5
6 /**
7  * Emit an HTML file containing statistics about the differences.
8  * Statistical information only appears if the -stats argument is used.
9  *
10  * See the file LICENSE.txt for copyright details.
11  * @author Matthew Doar, doar@pobox.com
12  */

13 public class HTMLStatistics {
14
15     /** Constructor. */
16     public HTMLStatistics(HTMLReportGenerator h) {
17         h_ = h;
18     }
19
20     /** The HTMLReportGenerator instance used to write HTML. */
21     private HTMLReportGenerator h_ = null;
22
23     /**
24      * Emit the statistics HTML file.
25      */

26     public void emitStatistics(String JavaDoc filename, APIDiff apiDiff) {
27         try {
28             FileOutputStream fos = new FileOutputStream(filename);
29             h_.reportFile = new PrintWriter(fos);
30             // Write out the HTML header
31
h_.writeStartHTMLHeader();
32             // Write out the title
33
h_.writeHTMLTitle("JDiff Statistics");
34             h_.writeStyleSheetRef();
35             h_.writeText("</HEAD>");
36             h_.writeText("<BODY>");
37
38             // Write a customized navigation bar for the statistics page
39
h_.writeText("<!-- Start of nav bar -->");
40             h_.writeText("<TABLE summary=\"Navigation bar\" BORDER=\"0\" WIDTH=\"100%\" CELLPADDING=\"1\" CELLSPACING=\"0\">");
41             h_.writeText("<TR>");
42             h_.writeText("<TD COLSPAN=2 BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\">");
43             h_.writeText(" <TABLE summary=\"Navigation bar\" BORDER=\"0\" CELLPADDING=\"0\" CELLSPACING=\"3\">");
44             h_.writeText(" <TR ALIGN=\"center\" VALIGN=\"top\">");
45             // Always have a link to the Javadoc files
46
h_.writeText(" <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"" + h_.newDocPrefix + "index.html\" target=\"_top\"><FONT CLASS=\"NavBarFont1\"><B><tt>" + apiDiff.newAPIName_ + "</tt></B></FONT></A>&nbsp;</TD>");
47             h_.writeText(" <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"" + h_.reportFileName + "-summary" + h_.reportFileExt + "\"><FONT CLASS=\"NavBarFont1\"><B>Overview</B></FONT></A>&nbsp;</TD>");
48             h_.writeText(" <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> &nbsp;<FONT CLASS=\"NavBarFont1\">Package</FONT>&nbsp;</TD>");
49             h_.writeText(" <TD BGCOLOR=\"#FFFFFF\" CLASS=\"NavBarCell1\"> &nbsp;<FONT CLASS=\"NavBarFont1\">Class</FONT>&nbsp;</TD>");
50             if (!Diff.noDocDiffs) {
51                 h_.writeText(" <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"" + Diff.diffFileName + "index" + h_.reportFileExt + "\"><FONT CLASS=\"NavBarFont1\"><B>Text Changes</B></FONT></A>&nbsp;</TD>");
52             }
53             h_.writeText(" <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1Rev\"> &nbsp;<FONT CLASS=\"NavBarFont1Rev\"><B>Statistics</B></FONT>&nbsp;</TD>");
54             h_.writeText(" <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"jdiff_help" + h_.reportFileExt + "\"><FONT CLASS=\"NavBarFont1\"><B>Help</B></FONT></A>&nbsp;</TD>");
55             h_.writeText(" </TR>");
56             h_.writeText(" </TABLE>");
57             h_.writeText("</TD>");
58
59             // The right hand side title
60
h_.writeText("<TD ALIGN=\"right\" VALIGN=\"top\" ROWSPAN=3><EM><b>Generated by<br><a HREF=\"" + JDiff.jDiffLocation + "\" class=\"staysblack\" target=\"_top\">JDiff</a></b></EM></TD>");
61             h_.writeText("</TR>");
62             
63             // Links for frames and no frames
64
h_.writeText("<TR>");
65             h_.writeText(" <TD BGCOLOR=\"" + h_.bgcolor + "\" CLASS=\"NavBarCell2\"><FONT SIZE=\"-2\"></FONT>");
66             h_.writeText("</TD>");
67             h_.writeText(" <TD BGCOLOR=\"" + h_.bgcolor + "\" CLASS=\"NavBarCell2\"><FONT SIZE=\"-2\">");
68             h_.writeText(" <A HREF=\"" + "../" + h_.reportFileName + h_.reportFileExt + "\" TARGET=\"_top\"><B>FRAMES</B></A> &nbsp;");
69             h_.writeText(" &nbsp;<A HREF=\"jdiff_statistics" + h_.reportFileExt + "\" TARGET=\"_top\"><B>NO FRAMES</B></A></FONT></TD>");
70             h_.writeText("</TR>");
71             
72             h_.writeText("</TABLE>");
73             h_.writeText("<HR>");
74             h_.writeText ("<!-- End of nav bar -->");
75
76             h_.writeText("<center>");
77             h_.writeText("<H1>JDiff Statistics</H1>");
78             h_.writeText("</center>");
79
80             h_.writeText("<BLOCKQUOTE>");
81             h_.writeText("The percent change statistic reported for all elements in each API is defined recursively as follows:<br>");
82             h_.writeText("<pre>");
83             h_.writeText("Percentage difference = 100 * (added + removed + 2*changed)");
84             h_.writeText(" -----------------------------------");
85             h_.writeText(" sum of public elements in BOTH APIs");
86             h_.writeText("</pre>");
87             h_.writeText("Where <code>added</code> is the number of packages added, <code>removed</code> is the number of packages removed, and <code>changed</code> is the number of packages changed.");
88             h_.writeText("This definition is applied recursively for the classes and their program elements, so the value for a changed package will be less than 1, unless every class in that package has changed.");
89             h_.writeText("The definition ensures that if all packages are removed and all new packages are");
90             h_.writeText("added, the change will be 100%. Values are rounded here, so a value of 0% indicates a percentage difference of less than 0.5%.");
91
92             h_.writeText("<p>The overall difference between the two APIs is approximately " + (int)(apiDiff.pdiff) + "%.");
93             h_.writeText("</BLOCKQUOTE>");
94
95             h_.writeText("<h3>Sections</h3>");
96             h_.writeText("<a HREF=\"#packages\">Packages</a> sorted by percentage difference<br>");
97             h_.writeText("<a HREF=\"#classes\">Classes and <i>Interfaces</i></a> sorted by percentage difference<br>");
98             h_.writeText("<a HREF=\"#numbers\">Differences</a> by number and type<br>");
99
100             h_.writeText("<hr>");
101             h_.writeText("<a name=\"packages\"></a>");
102             h_.writeText("<h2>Packages Sorted By Percentage Difference</h2>");
103             emitPackagesByDiff(apiDiff);
104
105             h_.writeText("<hr>");
106             h_.writeText("<a name=\"classes\"></a>");
107             h_.writeText("<h2>Classes and <i>Interfaces</i> Sorted By Percentage Difference</h2>");
108             emitClassesByDiff(apiDiff);
109
110             h_.writeText("<hr>");
111             h_.writeText("<a name=\"numbers\"></a>");
112             h_.writeText("<h2>Differences By Number and Type</h2>");
113             h_.writeText("<BLOCKQUOTE>");
114             h_.writeText("The numbers of program elements (packages, classes. constructors, methods and fields) which are recorded as removed, added or changed includes only the highest-level program elements. That is, if a class with two methods was added, the number of methods added does not include those two methods, but the number of classes added does include that class.");
115             h_.writeText("</BLOCKQUOTE>");
116
117             emitNumbersByElement(apiDiff);
118
119             h_.writeText("</HTML>");
120             h_.reportFile.close();
121         } catch(IOException e) {
122             System.out.println("IO Error while attempting to create " + filename);
123             System.out.println("Error: " + e.getMessage());
124             System.exit(1);
125         }
126     }
127
128     /**
129      * Emit all packages sorted by percentage difference, and a histogram
130      * of the values.
131      */

132     public void emitPackagesByDiff(APIDiff apiDiff) {
133         
134         Collections.sort(apiDiff.packagesChanged, new ComparePkgPdiffs());
135
136         // Write out the table start
137
h_.writeText("<TABLE summary=\"Packages sorted by percentage difference\" BORDER=\"1\" WIDTH=\"100%\" cellspacing=\"0\" cellpadding=\"0\">");
138         h_.writeText("<TR WIDTH=\"20%\">");
139         h_.writeText(" <TD ALIGN=\"center\" bgcolor=\"#EEEEFF\"><FONT size=\"+1\"><b>Percentage<br>Difference</b></FONT></TD>");
140         h_.writeText(" <TD ALIGN=\"center\" bgcolor=\"#EEEEFF\"><FONT size=\"+1\"><b>Package</b></FONT></TD>");
141         h_.writeText("</TR>");
142
143         int[] hist = new int[101];
144         for (int i = 0; i < 101; i++) {
145             hist[i] = 0;
146         }
147
148         Iterator iter = apiDiff.packagesChanged.iterator();
149         while (iter.hasNext()) {
150             PackageDiff pkg = (PackageDiff)(iter.next());
151             int bucket = (int)(pkg.pdiff);
152             hist[bucket]++;
153             h_.writeText("<TR>");
154             if (bucket != 0)
155                 h_.writeText(" <TD ALIGN=\"center\">" + bucket + "</TD>");
156             else
157                 h_.writeText(" <TD ALIGN=\"center\">&lt;1</TD>");
158             h_.writeText(" <TD><A HREF=\"pkg_" + pkg.name_ + h_.reportFileExt + "\">" + pkg.name_ + "</A></TD>");
159             h_.writeText("</TR>");
160         }
161
162         h_.writeText("</TABLE>");
163         
164         // Emit the histogram of the results
165
h_.writeText("<hr>");
166         h_.writeText("<p><a name=\"packages_hist\"></a>");
167         h_.writeText("<TABLE summary=\"Histogram of the package percentage differences\" BORDER=\"1\" cellspacing=\"0\" cellpadding=\"0\">");
168         h_.writeText("<TR>");
169         h_.writeText(" <TD ALIGN=\"center\" bgcolor=\"#EEEEFF\"><FONT size=\"+1\"><b>Percentage<br>Difference</b></FONT></TD>");
170         h_.writeText(" <TD ALIGN=\"center\" bgcolor=\"#EEEEFF\"><FONT size=\"+1\"><b>Frequency</b></FONT></TD>");
171         h_.writeText(" <TD width=\"300\" ALIGN=\"center\" bgcolor=\"#EEEEFF\"><FONT size=\"+1\"><b>Percentage Frequency</b></FONT></TD>");
172         h_.writeText("</TR>");
173
174         double total = 0;
175         for (int i = 0; i < 101; i++) {
176             total += hist[i];
177         }
178         for (int i = 0; i < 101; i++) {
179             if (hist[i] != 0) {
180                 h_.writeText("<TR>");
181                 h_.writeText(" <TD ALIGN=\"center\">" + i + "</TD>");
182                 h_.writeText(" <TD>" + (hist[i]/total) + "</TD>");
183                 h_.writeText(" <TD><img alt=\"|\" SRC=\"../black.gif\" height=20 width=" + (hist[i]*300/total) + "></TD>");
184                 h_.writeText("</TR>");
185             }
186         }
187         // Repeat the data in a format which is easier for spreadsheets
188
h_.writeText("<!-- START_PACKAGE_HISTOGRAM");
189         for (int i = 0; i < 101; i++) {
190             if (hist[i] != 0) {
191                 h_.writeText(i + "," + (hist[i]/total));
192             }
193         }
194         h_.writeText("END_PACKAGE_HISTOGRAM -->");
195         
196         h_.writeText("</TABLE>");
197     }
198
199     /**
200      * Emit all classes sorted by percentage difference, and a histogram
201      * of the values..
202      */

203     public void emitClassesByDiff(APIDiff apiDiff) {
204         // Add all the changed classes to a list
205
List allChangedClasses = new ArrayList();
206         Iterator iter = apiDiff.packagesChanged.iterator();
207         while (iter.hasNext()) {
208             PackageDiff pkg = (PackageDiff)(iter.next());
209             if (pkg.classesChanged != null) {
210                 // Add the package name to the class name
211
List cc = new ArrayList(pkg.classesChanged);
212                 Iterator iter2 = cc.iterator();
213                 while (iter2.hasNext()) {
214                     ClassDiff classDiff = (ClassDiff)(iter2.next());
215                     classDiff.name_ = pkg.name_ + "." + classDiff.name_;
216                 }
217                 allChangedClasses.addAll(cc);
218             }
219         }
220         Collections.sort(allChangedClasses, new CompareClassPdiffs());
221
222         // Write out the table start
223
h_.writeText("<TABLE summary=\"Classes sorted by percentage difference\" BORDER=\"1\" WIDTH=\"100%\" cellspacing=\"0\" cellpadding=\"0\">");
224         h_.writeText("<TR WIDTH=\"20%\">");
225         h_.writeText(" <TD ALIGN=\"center\" bgcolor=\"#EEEEFF\"><FONT size=\"+1\"><b>Percentage<br>Difference</b></FONT></TD>");
226         h_.writeText(" <TD ALIGN=\"center\" bgcolor=\"#EEEEFF\"><FONT size=\"+1\"><b>Class or <i>Interface</i></b></FONT></TD>");
227         h_.writeText("</TR>");
228
229         int[] hist = new int[101];
230         for (int i = 0; i < 101; i++) {
231             hist[i] = 0;
232         }
233
234         iter = allChangedClasses.iterator();
235         while (iter.hasNext()) {
236             ClassDiff classDiff = (ClassDiff)(iter.next());
237             int bucket = (int)(classDiff.pdiff);
238             hist[bucket]++;
239             h_.writeText("<TR>");
240             if (bucket != 0)
241                 h_.writeText(" <TD ALIGN=\"center\">" + bucket + "</TD>");
242             else
243                 h_.writeText(" <TD ALIGN=\"center\">&lt;1</TD>");
244             h_.writeText(" <TD><A HREF=\"" + classDiff.name_ + h_.reportFileExt + "\">");
245             if (classDiff.isInterface_)
246                 h_.writeText("<i>" + classDiff.name_ + "</i></A></TD>");
247             else
248                 h_.writeText(classDiff.name_ + "</A></TD>");
249             h_.writeText("</TR>");
250         }
251
252         h_.writeText("</TABLE>");
253
254         // Emit the histogram of the results
255
h_.writeText("<hr>");
256         h_.writeText("<p><a name=\"classes_hist\"></a>");
257         h_.writeText("<TABLE summary=\"Histogram of the class percentage differences\" BORDER=\"1\" cellspacing=\"0\" cellpadding=\"0\">");
258         h_.writeText("<TR>");
259         h_.writeText(" <TD ALIGN=\"center\" bgcolor=\"#EEEEFF\"><FONT size=\"+1\"><b>Percentage<br>Difference</b></FONT></TD>");
260         h_.writeText(" <TD ALIGN=\"center\" bgcolor=\"#EEEEFF\"><FONT size=\"+1\"><b>Frequency</b></FONT></TD>");
261         h_.writeText(" <TD width=\"300\" ALIGN=\"center\" bgcolor=\"#EEEEFF\"><FONT size=\"+1\"><b>Percentage Frequency</b></FONT></TD>");
262         h_.writeText("</TR>");
263
264         double total = 0;
265         for (int i = 0; i < 101; i++) {
266             total += hist[i];
267         }
268         for (int i = 0; i < 101; i++) {
269             if (hist[i] != 0) {
270                 h_.writeText("<TR>");
271                 h_.writeText(" <TD ALIGN=\"center\">" + i + "</TD>");
272                 h_.writeText(" <TD>" + (hist[i]/total) + "</TD>");
273                 h_.writeText(" <TD><img alt=\"|\" SRC=\"../black.gif\" height=20 width=" + (hist[i]*300/total) + "></TD>");
274                 h_.writeText("</TR>");
275             }
276         }
277         // Repeat the data in a format which is easier for spreadsheets
278
h_.writeText("<!-- START_CLASS_HISTOGRAM");
279         for (int i = 0; i < 101; i++) {
280             if (hist[i] != 0) {
281                 h_.writeText(i + "," + (hist[i]/total));
282             }
283         }
284         h_.writeText("END_CLASS_HISTOGRAM -->");
285         
286         h_.writeText("</TABLE>");
287     }
288
289     /**
290      * Emit a table of numbers of removals, additions and changes by
291      * package, class, constructor, method and field.
292      */

293     public void emitNumbersByElement(APIDiff apiDiff) {
294
295         // Local variables to hold the values
296
int numPackagesRemoved = apiDiff.packagesRemoved.size();
297         int numPackagesAdded = apiDiff.packagesAdded.size();
298         int numPackagesChanged = apiDiff.packagesChanged.size();
299
300         int numClassesRemoved = 0;
301         int numClassesAdded = 0;
302         int numClassesChanged = 0;
303
304         int numCtorsRemoved = 0;
305         int numCtorsAdded = 0;
306         int numCtorsChanged = 0;
307
308         int numMethodsRemoved = 0;
309         int numMethodsAdded = 0;
310         int numMethodsChanged = 0;
311
312         int numFieldsRemoved = 0;
313         int numFieldsAdded = 0;
314         int numFieldsChanged = 0;
315
316         int numRemoved = 0;
317         int numAdded = 0;
318         int numChanged = 0;
319
320         // Calculate the values
321
Iterator iter = apiDiff.packagesChanged.iterator();
322         while (iter.hasNext()) {
323             PackageDiff pkg = (PackageDiff)(iter.next());
324             numClassesRemoved += pkg.classesRemoved.size();
325             numClassesAdded += pkg.classesAdded.size();
326             numClassesChanged += pkg.classesChanged.size();
327
328             Iterator iter2 = pkg.classesChanged.iterator();
329             while (iter2.hasNext()) {
330                  ClassDiff classDiff = (ClassDiff)(iter2.next());
331                  numCtorsRemoved += classDiff.ctorsRemoved.size();
332                  numCtorsAdded += classDiff.ctorsAdded.size();
333                  numCtorsChanged += classDiff.ctorsChanged.size();
334                  
335                  numMethodsRemoved += classDiff.methodsRemoved.size();
336                  numMethodsAdded += classDiff.methodsAdded.size();
337                  numMethodsChanged += classDiff.methodsChanged.size();
338                  
339                  numFieldsRemoved += classDiff.fieldsRemoved.size();
340                  numFieldsAdded += classDiff.fieldsAdded.size();
341                  numFieldsChanged += classDiff.fieldsChanged.size();
342             }
343         }
344         
345         // Write out the table
346
h_.writeText("<TABLE summary=\"Number of differences\" BORDER=\"1\" WIDTH=\"100%\" cellspacing=\"0\" cellpadding=\"0\">");
347         h_.writeText("<TR>");
348         h_.writeText(" <TD COLSPAN=5 ALIGN=\"center\" NOWRAP bgcolor=\"#EEEEFF\"><FONT size=\"+1\">");
349         h_.writeText(" <B>Number of Differences</B></FONT></TD>");
350         h_.writeText("</TR>");
351         h_.writeText("<TR>");
352         h_.writeText(" <TD>&nbsp;</TD>");
353         h_.writeText(" <TD ALIGN=\"center\"><b>Removals</b></TD>");
354         h_.writeText(" <TD ALIGN=\"center\"><b>Additions</b></TD>");
355         h_.writeText(" <TD ALIGN=\"center\"><b>Changes</b></TD>");
356         h_.writeText(" <TD ALIGN=\"center\"><b>Total</b></TD>");
357         h_.writeText("</TR>");
358
359         h_.writeText("<TR>");
360         h_.writeText(" <TD>Packages</TD>");
361         h_.writeText(" <TD ALIGN=\"right\">" + numPackagesRemoved + "</TD>");
362         h_.writeText(" <TD ALIGN=\"right\">" + numPackagesAdded + "</TD>");
363         h_.writeText(" <TD ALIGN=\"right\">" + numPackagesChanged + "</TD>");
364         int numPackages = numPackagesRemoved + numPackagesAdded + numPackagesChanged;
365         h_.writeText(" <TD ALIGN=\"right\">" + numPackages + "</TD>");
366         h_.writeText("</TR>");
367
368         numRemoved += numPackagesRemoved;
369         numAdded += numPackagesAdded;
370         numChanged += numPackagesChanged;
371
372         h_.writeText("<TR>");
373         h_.writeText(" <TD>Classes and <i>Interfaces</i></TD>");
374         h_.writeText(" <TD ALIGN=\"right\">" + numClassesRemoved + "</TD>");
375         h_.writeText(" <TD ALIGN=\"right\">" + numClassesAdded + "</TD>");
376         h_.writeText(" <TD ALIGN=\"right\">" + numClassesChanged + "</TD>");
377         int numClasses = numClassesRemoved + numClassesAdded + numClassesChanged;
378         h_.writeText(" <TD ALIGN=\"right\">" + numClasses + "</TD>");
379         h_.writeText("</TR>");
380
381         numRemoved += numClassesRemoved;
382         numAdded += numClassesAdded;
383         numChanged += numClassesChanged;
384
385         h_.writeText("<TR>");
386         h_.writeText(" <TD>Constructors</TD>");
387         h_.writeText(" <TD ALIGN=\"right\">" + numCtorsRemoved + "</TD>");
388         h_.writeText(" <TD ALIGN=\"right\">" + numCtorsAdded + "</TD>");
389         h_.writeText(" <TD ALIGN=\"right\">" + numCtorsChanged + "</TD>");
390         int numCtors = numCtorsRemoved + numCtorsAdded + numCtorsChanged;
391         h_.writeText(" <TD ALIGN=\"right\">" + numCtors + "</TD>");
392         h_.writeText("</TR>");
393
394         numRemoved += numCtorsRemoved;
395         numAdded += numCtorsAdded;
396         numChanged += numCtorsChanged;
397
398         h_.writeText("<TR>");
399         h_.writeText(" <TD>Methods</TD>");
400         h_.writeText(" <TD ALIGN=\"right\">" + numMethodsRemoved + "</TD>");
401         h_.writeText(" <TD ALIGN=\"right\">" + numMethodsAdded + "</TD>");
402         h_.writeText(" <TD ALIGN=\"right\">" + numMethodsChanged + "</TD>");
403         int numMethods = numMethodsRemoved + numMethodsAdded + numMethodsChanged;
404         h_.writeText(" <TD ALIGN=\"right\">" + numMethods + "</TD>");
405         h_.writeText("</TR>");
406
407         numRemoved += numMethodsRemoved;
408         numAdded += numMethodsAdded;
409         numChanged += numMethodsChanged;
410
411         h_.writeText("<TR>");
412         h_.writeText(" <TD>Fields</TD>");
413         h_.writeText(" <TD ALIGN=\"right\">" + numFieldsRemoved + "</TD>");
414         h_.writeText(" <TD ALIGN=\"right\">" + numFieldsAdded + "</TD>");
415         h_.writeText(" <TD ALIGN=\"right\">" + numFieldsChanged + "</TD>");
416         int numFields = numFieldsRemoved + numFieldsAdded + numFieldsChanged;
417         h_.writeText(" <TD ALIGN=\"right\">" + numFields + "</TD>");
418         h_.writeText("</TR>");
419
420         numRemoved += numFieldsRemoved;
421         numAdded += numFieldsAdded;
422         numChanged += numFieldsChanged;
423
424         h_.writeText("<TR>");
425         h_.writeText(" <TD><b>Total</b></TD>");
426         h_.writeText(" <TD ALIGN=\"right\">" + numRemoved + "</TD>");
427         h_.writeText(" <TD ALIGN=\"right\">" + numAdded + "</TD>");
428         h_.writeText(" <TD ALIGN=\"right\">" + numChanged + "</TD>");
429         int total = numRemoved + numAdded + numChanged;
430         h_.writeText(" <TD ALIGN=\"right\">" + total + "</TD>");
431         h_.writeText("</TR>");
432
433         h_.writeText("</TABLE>");
434     }
435
436 }
437
Popular Tags