1 package jdiff; 2 3 import java.util.*; 4 import java.io.*; 5 6 13 public class HTMLStatistics { 14 15 16 public HTMLStatistics(HTMLReportGenerator h) { 17 h_ = h; 18 } 19 20 21 private HTMLReportGenerator h_ = null; 22 23 26 public void emitStatistics(String filename, APIDiff apiDiff) { 27 try { 28 FileOutputStream fos = new FileOutputStream(filename); 29 h_.reportFile = new PrintWriter(fos); 30 h_.writeStartHTMLHeader(); 32 h_.writeHTMLTitle("JDiff Statistics"); 34 h_.writeStyleSheetRef(); 35 h_.writeText("</HEAD>"); 36 h_.writeText("<BODY>"); 37 38 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 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> </TD>"); 47 h_.writeText(" <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"" + h_.reportFileName + "-summary" + h_.reportFileExt + "\"><FONT CLASS=\"NavBarFont1\"><B>Overview</B></FONT></A> </TD>"); 48 h_.writeText(" <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <FONT CLASS=\"NavBarFont1\">Package</FONT> </TD>"); 49 h_.writeText(" <TD BGCOLOR=\"#FFFFFF\" CLASS=\"NavBarCell1\"> <FONT CLASS=\"NavBarFont1\">Class</FONT> </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> </TD>"); 52 } 53 h_.writeText(" <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1Rev\"> <FONT CLASS=\"NavBarFont1Rev\"><B>Statistics</B></FONT> </TD>"); 54 h_.writeText(" <TD BGCOLOR=\"#EEEEFF\" CLASS=\"NavBarCell1\"> <A HREF=\"jdiff_help" + h_.reportFileExt + "\"><FONT CLASS=\"NavBarFont1\"><B>Help</B></FONT></A> </TD>"); 55 h_.writeText(" </TR>"); 56 h_.writeText(" </TABLE>"); 57 h_.writeText("</TD>"); 58 59 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 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> "); 69 h_.writeText(" <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 132 public void emitPackagesByDiff(APIDiff apiDiff) { 133 134 Collections.sort(apiDiff.packagesChanged, new ComparePkgPdiffs()); 135 136 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\"><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 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 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 203 public void emitClassesByDiff(APIDiff apiDiff) { 204 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 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 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\"><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 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 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 293 public void emitNumbersByElement(APIDiff apiDiff) { 294 295 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 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 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> </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 |