001package Torello.JavaDoc; 002 003import java.io.Serializable; 004 005import java.util.*; 006import java.util.stream.*; 007 008import Torello.HTML.*; 009import Torello.HTML.NodeSearch.*; 010import Torello.Java.*; 011 012import static Torello.Java.C.*; 013 014import Torello.JDUInternal.GeneralPurpose.JDUProcessor; 015import Torello.JDUInternal.HTMLProcessors.EmbedTag.EmbedTagTopDescription; 016import Torello.JDUInternal.ParseJavaSource.JavaSourceCodeFile; 017 018import Torello.JDUInternal.GeneralPurpose.Messager; 019import Torello.JDUInternal.GeneralPurpose.MessagerVerbose; 020 021import Torello.Java.ReadOnly.ReadOnlyMap; 022 023/** 024 * Maintains a suite of statistics about all Java project-wide source-code files. 025 * 026 * <BR />As the Upgrade Processors are executed, this class maintains a few statistics about the 027 * build, and produces the {@code Stats} HTML instance, which is subsequently linked to a 028 * {@code 'Stats'} button on output Java Doc Web-Pages - <I>and also returned to the user after 029 * calling the ugrader</I>. 030 * 031 * <BR /><BR /><EMBED CLASS='external-html' DATA-FILE-ID=UPSTATS> 032 */ 033public class Stats implements java.io.Serializable 034{ 035 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 036 protected static final long serialVersionUID = 1; 037 038 // Package-Level instances of 'Stats' will have their package-names saved here. 039 // For the "Complete-Project" Stats instance, this will be null. 040 private final String packageName; 041 042 // Each Package has it's own / recursive instance of 'Stats' 043 // For the Package-Level instances of 'Stats' - this field will be null. 044 private final Map<String, Stats> packageStatsMap; 045 046 /** 047 * Global Stats are maintained, but so are package-local statistics. This reetrieves the 048 * package-local statistics instance. 049 * @param packageName The name of one of the upgraded Java Packages, as a {@code String}. 050 * @return The package-level instance of {@code 'Stats'} for that package. 051 */ 052 public Stats getPackageStats(String packageName) 053 { return packageStatsMap.get(packageName); } 054 055 // A Pointer to the "Project-Global Embed-Tags Map" 056 private final ReadOnlyMap<String, String> globalTagsMap; 057 058 // A Count-Total for the "Project-Global Embed-Tags Map" 059 private final Map<String, Integer> globalTagsCount; 060 061 /** 062 * Retrieving a count of all Project-Global Tags is done with this getter. <I>It is important 063 * to remember that an instance of {@code 'Stats'} may be a <B>Project-Global</B> instance, or a 064 * <B>Package-Local</B> instance</I>. If {@code 'this'} instance of {@code Stats} is the 065 * 'Project-Global' instance, the integer count-values inside the returned-{@code Map} will be 066 * aggregate totals (for the whole project) of the number of times your External-HTML 067 * {@code <EMBED>} tags were used. 068 * 069 * <BR /><BR />If this method is invoked on one of the Package-Local {@code 'Stats'} instances, 070 * the returned-{@code Map} will hold integer count-values for the Project-Global 071 * {@code <EMBED>} tags were used <I>inside the particular package for which {@code 'this'} 072 * statistics-instance was built.</I> 073 * 074 * <BR /><BR /><B STYLE='color:red'>NOTE:</B> The complete dump of the statistics-tables for 075 * the Java HTML Jar Library may be viewed by clicking on the {@code 'Stats'} link in the top 076 * right corner of this page. The data-tables there show the exact data that's inside the 077 * {@code Map's}-tables of this class. 078 * 079 * @return If {@code 'this'} instance of {@code 'Stats'} is the 'Project-Global' instance, the 080 * returned-{@code Map} will be the 'Project-Totals' use-count for all Globally-Defined 081 * {@code <EMBED class='external-html ..>'} Tags. 082 * 083 * <BR /><BR />If {@code 'this'} instance of {@code 'Stats'} is a 'Package-Local' instance, 084 * the returned-{@code Map} will have <B>Package-Local use-counts</B> for all of the 085 * <B>Globallly-Defined Tags.</B> 086 */ 087 @SuppressWarnings("unchecked") 088 public Map<String, Integer> getGlobalTagsCount() 089 { return (HashMap<String, Integer>) ((HashMap<String, Integer>) globalTagsCount).clone(); } 090 091 // A reference pointer to the "Package-Local Embed-Tag Map", (ID's ==> FileNames) 092 // NOTE: For the top-level main 'Stats' instance, this will remain null 093 094 private final ReadOnlyMap<String, String> packageTagsMap; 095 096 // Keeps a count of the use of all "Package-Local Embed-Tags" 097 // NOTE: For the top-level main 'Stats' instance, this will remain null 098 099 private final Map<String, Integer> packageTagsCount; 100 101 /** 102 * This retrieves an integer count-{@code Map} of all Package-Local Embedded HTML 103 * (External-HTML) Tags. If {@code 'this'} instance of {@code 'Stats'} is the Top-Level, 104 * Project-Global instance of {@code 'Stats'}, this method returns null. 105 * 106 * @return A {@code Map} containing counts of the number of times a Package-Local 107 * {@code <EMBED CLASS='external-html'>} Tag has been used on web-pages that are inside 108 * that particular package. 109 * 110 * <BR /><BR />This method returns null if {@code 'this'} instance of {@code 'Stats'} is 111 * the Global-Instance, rather than one of the Package-Local Instances. 112 */ 113 @SuppressWarnings("unchecked") 114 public Map<String, Integer> getPackageTagsCount() 115 { 116 return (packageTagsCount == null) 117 ? null 118 : (HashMap<String, Integer>) ((HashMap<String, Integer>) packageTagsCount).clone(); 119 } 120 121 // This builds a "Global Stats" that doesn't have any Global Embed-Tags. This is the constructor 122 // used by configuration-class "Upgrade" in the "fields initializers" section. 123 // 124 // SPECIFICALLY: The following line is the "first initialization used". 125 // protected Stats stats = new Stats(); 126 // 127 // If the User registers a global Embed-Tags Map, then this instance is SIMPLY-DISCARDED 128 // (Garbage Collected), and a new instance assigned to that Upgrade Field. 129 // 130 // AGAIN: Usually this instance is built, **BUT** then replaced if the user configures the 131 // upgrade class with a Global Embed Tags map. In the Java HTML JAR an instance is 132 // built using this constructor, but then destoyed immediately after registering. 133 // This is not a big enough waste - when compared to the alternative (which is writing 134 // another "register map" method). 135 // 136 // FOR USERS WHO DO NOT REGISTER A GLOBAL EMBED TAGS MAP, THE INSTANCE CREATED BY THIS 137 // CONSTRFUCTOR - OBVIOUSLY - WON'T BE GARBAGE COLLECTED. 138 139 Stats() 140 { 141 this.packageName = null; 142 this.packageStatsMap = new HashMap<>(); 143 this.packageTagsMap = null; 144 this.packageTagsCount = null; 145 this.globalTagsMap = null; 146 this.globalTagsCount = null; 147 } 148 149 // Constructor for global-stats instance 150 // NO MESSGER USE 151 152 Stats(ReadOnlyMap<String, String> globalTagsMap) 153 { 154 // This is a 'JavaDocError' rather than a message to the messager because this should 155 // *NEVER* occur. At the time of the writing of this exception-check, this constructor is 156 // invoked from the 'Upgrade' Confguration class. A null-check is done there on th euser 157 // input. If that changes or moves, it should be thought of as "My Fault" not 158 // "Their Fault" - so this has to be a 'THROW' rather than a 'MESSAGER' error. 159 // 160 // Keep these here because this class seems Ultra-Simple at first glance, but because it 161 // is ALL ABOUT DATA, it is sort of more DIFFICULT than one might expect. 162 // 163 // The Exception/Errors in this class ARE ALL FOR MISTAKES that should NEVER happen, NO 164 // MATTER WHAT the user has entered or passed to the Upgrade-Configuration class. 165 166 if (globalTagsMap == null) Messager.assertFailCheckup( 167 "A null 'globalTagsMap' was passed to the Stats Constructor. If there are no " + 168 "Global Embed Tags being used with this Project, the Upgrade-Configuration class " + 169 "is supposed to be using the Stats-class zero-argument constructor" 170 ); 171 172 this.packageName = null; 173 this.packageStatsMap = new HashMap<>(); 174 175 // The "Global Stats" instance doesn't have PackageTags 176 // AGAIN: This constructor is the Constructor for the "Global Stats" instance. 177 178 this.packageTagsMap = null; 179 this.packageTagsCount = null; 180 181 this.globalTagsMap = globalTagsMap; 182 this.globalTagsCount = new HashMap<>(); 183 184 // This must be initialized here. Even if a Tag is not used, knowing that it's count 185 // is ZERO is helpful to the user. If we leave it null here, yes, that could be 186 // interpreted as a ZERO, but it looks nicer here, and at the end to put a zero, rather 187 // than leaving it null and reverse-checking the global-map. 188 189 Integer ZERO = Integer.valueOf(0); 190 191 // Initialize the PROJECT-GLOBAL tag-count map. 192 for (String embedTag : globalTagsMap.keySet()) this.globalTagsCount.put(embedTag, ZERO); 193 } 194 195 // Constructor for package-stats instances 196 private Stats(String packageName, ReadOnlyMap<String, String> packageTagsMap) 197 { 198 this.packageName = packageName; 199 this.packageStatsMap = null; // This instance **IS** a "Package Stats" 200 201 this.globalTagsMap = null; // This is not needed 202 this.globalTagsCount = new HashMap<>(); 203 204 this.packageTagsMap = packageTagsMap; 205 this.packageTagsCount = (packageTagsMap == null) ? null : new HashMap<>(); 206 207 Integer ZERO = Integer.valueOf(0); 208 209 if (packageTagsCount != null) 210 211 for (String embedTag : this.packageTagsMap.keySet()) 212 this.packageTagsCount.put(embedTag, ZERO); 213 } 214 215 // This is called by "MainFilesProcessor" right before processing the Java Doc Web-Pages 216 // for a particular Java Package. At this point in that code, the 'packageTagsMap' has just 217 // been read in from the 'upgrade-files/external-html/external-html-ids.properties' file. 218 // 219 // If the user didn't write any External-HTML Files, then the 'packageTagsMap' instance will 220 // be null. That is OK, that is only one of the many statistics that are maintained by this 221 // class. 222 // 223 // MESSAGER: 224 // 1) USES: assertFailGeneralPurpose 225 // 2) INVOKED-BY: RetrieveEmbedTagMapPropFiles - only once 226 // 3) RETURNS: NOTHING 227 // 4) THROWS: UpgradeException (assertFailGeneralPurpose) 228 // 229 // ONE ASSERT STATEMENT WHICH THEORETICALLY SHOULD BE UNREACHABLE 230 // ONLY SETS FileName if unreachable-code is actually reached. 231 // 232 // EXPORT_PORTAL METHOD 233 // This method is used by Package UserConfigReaders, and doesn't need to be exported to the user 234 // Stats.run is NOT STATIC!!! 235 236 void registerPackage( 237 String packageName, 238 ReadOnlyMap<String, String> packageTagsMap, 239 Stats topLevelStatsInstance 240 ) 241 { 242 // AGAIN: This should never be null, no matter what input the user has provided. If 243 // this is null, it means (mostly) that something else was changed (probably in 244 // class 'Upgrade' or 'MainFilesProcessor'). Throw this to signify that it is 245 // MY FAULT - NOT THEIR FAULT. 246 247 if (topLevelStatsInstance == null) 248 { 249 Messager.setCurrentFileName("No-File Processing", "Unreachable Code Reached"); 250 251 Messager.assertFailGeneralPurpose( 252 "The instance of Stats passed to topLevelStatsInstance is null.\n" + 253 "Niether the top-level 'Stats' instance, nor the Package-Local instances " + 254 "should ever be null.\n" + 255 "Currently attempting to build Package-Local 'Stats' instance for package: " + 256 " [" + BGREEN + packageName + RESET + "]\n" + 257 BRED + "NOTE:" + RESET + " This is the developers fault.", 258 null 259 ); 260 } 261 262 topLevelStatsInstance.packageStatsMap.put 263 (packageName, new Stats(packageName, packageTagsMap)); 264 } 265 266 /** The name of the Statistics HTML file saved to the root JavaDoc Directory. */ 267 protected static final String STATS_HTML_FILENAME = "Stats.html"; 268 269 270 // ******************************************************************************************** 271 // ******************************************************************************************** 272 // Stats Fields: BASIC 273 // ******************************************************************************************** 274 // ******************************************************************************************** 275 276 277 /** @return A count of the total number of lines of {@code '.java'} files. */ 278 public int numLines() { return numLines; } 279 private int numLines; 280 281 /** @return A count of the total number of bytes of {@code '.java'} files. */ 282 public int numBytes() { return numBytes; } 283 private int numBytes; 284 285 /** @return A count of the total number of HiLited HTML {@code <DIV>} Elements. */ 286 public int numHiLitedDivs() { return numHiLitedDivs; } 287 private int numHiLitedDivs = 0; 288 289 290 // ******************************************************************************************** 291 // ******************************************************************************************** 292 // Stats: Entity (METHOD, FIELD, CONSTRUCTOR, ANNOTATION_ELEM, ENUM_CONSTANT) 293 // ******************************************************************************************** 294 // ******************************************************************************************** 295 296 297 /** @return A count of the total number of methods found during the upgrade. */ 298 public int numMethods() { return numMethods; } 299 private int numMethods = 0; 300 301 /** @return A count of the total number of constructors found during the upgrade. */ 302 public int numConstructors() { return numConstructors; } 303 private int numConstructors = 0; 304 305 /** @return A count of the total number of fields found during the upgrade. */ 306 public int numFields() { return numFields; } 307 private int numFields = 0; 308 309 /** @return A count of the total number of annotation-elements found during the upgrade. */ 310 public int numAnnotationElems() { return numAnnotationElems; } 311 private int numAnnotationElems = 0; 312 313 /** @return A count of the total number of enum-constants found during the upgrade. */ 314 public int numEnumConstants() { return numEnumConstants; } 315 private int numEnumConstants = 0; 316 317 318 // ******************************************************************************************** 319 // ******************************************************************************************** 320 // Stats: HILITED-Entity (METHOD, FIELD, CONSTRUCTOR, ANNOTATION_ELEM, ENUM_CONSTANT) 321 // ******************************************************************************************** 322 // ******************************************************************************************** 323 324 325 /** @return A count of the total number of method bodies hilited by the upgrader. */ 326 public int numHiLitedMethods() { return numHiLitedMethods; } 327 private int numHiLitedMethods = 0; 328 329 /** @return A count of the total number of constructor bodies hilited by the upgrader. */ 330 public int numHiLitedConstructors() { return numHiLitedConstructors; } 331 private int numHiLitedConstructors = 0; 332 333 /** @return A count of the total number of field declarations hilited by the upgrader. */ 334 public int numHiLitedFields() { return numHiLitedFields; } 335 private int numHiLitedFields = 0; 336 337 /** 338 * @return A count of the total number of annotation-element declarations hilited by the 339 * upgrader. 340 */ 341 public int numHiLitedAnnotationElems() { return numHiLitedAnnotationElems; } 342 private int numHiLitedAnnotationElems = 0; 343 344 /** 345 * @return A count of the total number of enumeration-constant declarations hilited by the 346 * upgrader. 347 */ 348 public int numHiLitedEnumConstants() { return numHiLitedEnumConstants; } 349 private int numHiLitedEnumConstants = 0; 350 351 352 // ******************************************************************************************** 353 // ******************************************************************************************** 354 // Stats: DOCUMENTED-Entity (METHOD, FIELD, CONSTRUCTOR, ANNOTATION_ELEM, ENUM_CONSTANT) 355 // ******************************************************************************************** 356 // ******************************************************************************************** 357 358 359 /** @return A count of the total number of methods that were documented by Java Doc. */ 360 public int numDocumentedMethods() { return numDocumentedMethods; } 361 private int numDocumentedMethods = 0; 362 363 /** @return A count of the total number of constructors that were documented by Java Doc. */ 364 public int numDocumentedConstructors() { return numDocumentedConstructors; } 365 private int numDocumentedConstructors = 0; 366 367 /** @return A count of the total number of fields that were documented by Java Doc. */ 368 public int numDocumentedFields() { return numDocumentedFields; } 369 private int numDocumentedFields = 0; 370 371 /** 372 * @return A count of the total number of annotation-elements that were documented by 373 * Java Doc. 374 */ 375 public int numDocumentedAnnotationElems() { return numDocumentedAnnotationElems; } 376 private int numDocumentedAnnotationElems = 0; 377 378 /** 379 * @return A count of the total number of annotation-elements that were documented by 380 * Java Doc. 381 */ 382 public int numDocumentedEnumConstants() { return numDocumentedEnumConstants; } 383 private int numDocumentedEnumConstants = 0; 384 385 386 // ******************************************************************************************** 387 // ******************************************************************************************** 388 // Stats: STATIC-Entity (METHOD, FIELD) 389 // ******************************************************************************************** 390 // ******************************************************************************************** 391 392 393 /** @return A count of the total number of {@code static} methods found during the upgrade. */ 394 public int numStaticMethods() { return numStaticMethods; } 395 private int numStaticMethods = 0; 396 397 /** @return A count of the total number of {@code static} fields found during the upgrade. */ 398 public int numStaticFields() { return numStaticFields; } 399 private int numStaticFields = 0; 400 401 402 // ******************************************************************************************** 403 // ******************************************************************************************** 404 // Stats: FINAL-Entity (METHOD, FIELD, CONSTRUCTOR) 405 // ******************************************************************************************** 406 // ******************************************************************************************** 407 408 409 /** @return A count of the total number of {@code final} methods found by the upgrade. */ 410 public int numFinalMethods() { return numFinalMethods; } 411 private int numFinalMethods = 0; 412 413 /** @return A count of the total number of {@code final} constructors found by the upgrader. */ 414 public int numFinalConstructors() { return numFinalConstructors; } 415 private int numFinalConstructors = 0; 416 417 /** @return A count of the total number of {@code final} fields found by the upgrader. */ 418 public int numFinalFields() { return numFinalFields; } 419 private int numFinalFields = 0; 420 421 422 // ******************************************************************************************** 423 // ******************************************************************************************** 424 // Stats: PUBLIC-Entity (METHOD, FIELD, CONSTRUCTOR) 425 // ******************************************************************************************** 426 // ******************************************************************************************** 427 428 429 /** @return A count of the total number of {@code public} methods found by the upgrader. */ 430 public int numPublicMethods() { return numPublicMethods; } 431 private int numPublicMethods = 0; 432 433 /** @return A count of the total number of {@code public} constructors found by the upgrader.*/ 434 public int numPublicConstructors() { return numPublicConstructors; } 435 private int numPublicConstructors = 0; 436 437 /** @return A count of the total number of {@code public} fields found by the upgrader. */ 438 public int numPublicFields() { return numPublicFields; } 439 private int numPublicFields = 0; 440 441 442 // ******************************************************************************************** 443 // ******************************************************************************************** 444 // Stats: PROTECTED-Entity (METHOD, FIELD, CONSTRUCTOR) 445 // ******************************************************************************************** 446 // ******************************************************************************************** 447 448 449 /** @return The total number of {@code protected} methods found during the upgrade. */ 450 public int numProtectedMethods() { return numProtectedMethods; } 451 private int numProtectedMethods = 0; 452 453 /** @return The total number of {@code protected} constructors found during the upgrade. */ 454 public int numProtectedConstructors() { return numProtectedConstructors; } 455 private int numProtectedConstructors = 0; 456 457 /** @return The total number of {@code protected} fields found during the upgrade. */ 458 public int numProtectedFields() { return numProtectedFields; } 459 private int numProtectedFields = 0; 460 461 462 // ******************************************************************************************** 463 // ******************************************************************************************** 464 // Stats: PRIVATE-Entity (METHOD, FIELD, CONSTRUCTOR) 465 // ******************************************************************************************** 466 // ******************************************************************************************** 467 468 469 /** @return The total number of {@code private} methods found during the upgrade. */ 470 public int numPrivateMethods() { return numPrivateMethods; } 471 private int numPrivateMethods = 0; 472 473 /** @return The total number of {@code private} constructors found during the upgrade. */ 474 public int numPrivateConstructors() { return numPrivateConstructors; } 475 private int numPrivateConstructors = 0; 476 477 /** @return The total number of {@code private} fields found during the upgrade. */ 478 public int numPrivateFields() { return numPrivateFields; } 479 private int numPrivateFields = 0; 480 481 482 // ******************************************************************************************** 483 // ******************************************************************************************** 484 // Stats: OTHER-Entity (FIELD only) 485 // ******************************************************************************************** 486 // ******************************************************************************************** 487 488 489 /** @return A count of the total number of {@code transient} fields found during the upgrade.*/ 490 public int numTransientFields() { return numTransientFields; } 491 private int numTransientFields = 0; 492 493 /** @return A count of the total number of {@code volatile} fields found during the upgrade. */ 494 public int numVolatileFields() { return numVolatileFields; } 495 private int numVolatileFields = 0; 496 497 498 499 // ******************************************************************************************** 500 // ******************************************************************************************** 501 // Stats Per Package, **AND** Embed-Tags Stats 502 // ******************************************************************************************** 503 // ******************************************************************************************** 504 505 506 // ***Optimization Fields*** 507 // The same package will be referenced, over and over, until the package has completed 508 // These tags are used hundreds of times in some of the packages. 509 510 private String LAST_USED_packageName = null; 511 private Stats LAST_USED_packageStats = null; 512 513 514 // Increments the total-count by 1 for a particular embed-tag 515 // 516 // NOTE: The whole 'LAST_USED_' PHENOMENON is an optimization, so that these tables are not 517 // looked up in the Hashtable every single time they are used. 518 // 519 // MESSAGER: 520 // 1) INVOKES: assertFailGeneralPurpose (100% my fault, not there fault) 521 // 2) INVOKED-BY: **ONLY ONCE**, from 'EmbedTag', (inside a loop) 522 // 3) RETURN: NOTHING 523 // 4) THROWS: UpgradeException (assertFailGeneralPurpose) 524 525 void incrementTag(String packageName, String embedTag, boolean globalTagOrPackageTag) 526 { 527 if ( (this.LAST_USED_packageName == null) 528 || (! this.LAST_USED_packageName.equals(packageName))) 529 { 530 this.LAST_USED_packageName = packageName; 531 this.LAST_USED_packageStats = this.packageStatsMap.get(packageName); 532 533 // This should never happen, but if it does, this exception is more meaningful than 534 // NullPointerException. It isn't any better though! 535 // 536 // (IF NULL, THIS IS MY FAULT, NOT THEIR FAULT, and at the time of the writing of this 537 // code, THIS CANNOT HAPPEN. HOWEVER, if something is changed, then this exception 538 // throw is more intelligent than NPE) 539 540 if (this.LAST_USED_packageStats == null) 541 542 Messager.assertFailGeneralPurpose( 543 "The Package-Stats instance for Package [" + packageName + "] returned null " + 544 "from the Global-Stats field 'packageStatsMap'\n" + 545 "Processing Embed-Tag [" + BCYAN + embedTag + RESET + "], a " + 546 (globalTagOrPackageTag ? "Global" : "Package-Local") + " Tag.", 547 null 548 ); 549 } 550 551 if (globalTagOrPackageTag) 552 { 553 Integer globalCount = this.globalTagsCount.get(embedTag); 554 555 // This should never happen, but if it does, this exception is more meaningful than 556 // NullPointerException. It isn't any better though! 557 // 558 // SEE ABOVE COMMENT 559 560 if (globalCount == null) 561 562 Messager.assertFailGeneralPurpose( 563 "The Global-Stats instance returned a null count, but these are all " + 564 "supposed to have been initialized to zero.\n" + 565 "Processing Embed-Tag [" + BCYAN + embedTag + RESET + "], a Global Tag.", 566 null 567 ); 568 569 this.globalTagsCount.put(embedTag, globalCount + 1); 570 571 // These are **ALWAYS NULL** the first time they are used. 572 Integer i = this.LAST_USED_packageStats.globalTagsCount.get(embedTag); 573 574 this.LAST_USED_packageStats.globalTagsCount.put(embedTag, (i == null) ? 1 : (i+1)); 575 } 576 else 577 { 578 // These exception throws are being used more like Java 'assert' statements. If an 579 // error occurs, it means that I changed something else, somplace else, and forgot 580 // about this part. As of the time of the writing of this exception check, this 581 // field CAN NEVER BE NULL WHEN THIS LINE IS EXECUTED. 582 583 if (this.LAST_USED_packageStats.packageTagsCount == null) 584 585 Messager.assertFailGeneralPurpose( 586 "While processing Embed-Tags for package [" + packageName + "]\n" + 587 "The Package-Local Stats-Instance had a NULL-MAP reference for map " + 588 "'packageTagsCount'.\n" + 589 "Currently attempting to increment counter for (Package-Local) Embed-Tag " + 590 "[" + BCYAN + embedTag + RESET + "].", 591 null 592 ); 593 594 Integer packageCount = this.LAST_USED_packageStats.packageTagsCount.get(embedTag); 595 596 // EXCEPTION-THROW COMMENT: SAME AS ABOVE. This code is theoretically unreachable, 597 // but every developer has been known to change something else, somewhere else, and 598 // at the same time forgetting how that change might affect THIS CODE (below) 599 // 600 // HERE, if 'packageCount' were null, this would BY MY FAULT, NOT THE USERS FAULT. 601 602 if (packageCount == null) 603 { 604 if (embedTag.equals(EmbedTagTopDescription.JDHBI_RESERVED_EMBED_TAG_FILE_ID)) 605 this.LAST_USED_packageStats.packageTagsCount.put(embedTag, 1); 606 607 else Messager.assertFailGeneralPurpose( 608 "While retrieving Embed-Tag Count Data for Package-Local Embed-Tag " + 609 "[" + embedTag + "]\n" + 610 "Located in Package [" + packageName + "]\n" + 611 "The Embed-Tag-Count found in the packageTagsCount-Map had a null-Integer. " + 612 "But these are all initialized to zero.", 613 null 614 ); 615 } 616 617 else this.LAST_USED_packageStats.packageTagsCount.put(embedTag, packageCount + 1); 618 } 619 } 620 621 622 // ******************************************************************************************** 623 // ******************************************************************************************** 624 // Update Stats for a single File 625 // ******************************************************************************************** 626 // ******************************************************************************************** 627 628 629 // Increments all the counters by the value in the given parameters 630 // This is package-visible, because it really serves little purpose outside of this 631 // package. 632 // 633 // NOTE: 'jdhf' is only used for the "getMethods", "geFields" things. It is not asked for 634 // 'fileVec' 635 // 636 // MESSAGER: 637 // 1) INVOKES: assertFailGeneralPurpose 638 // 2) INVOKED-BY: THIS METHOD IS ONLY INVOKED ONCE, FROM DetailsFilesProcesor 639 // 3) RETURNS: void - NOTHING 640 // 4) THROWS: UpgradeException (assertFailGeneralPurpose) 641 // 642 // EXPORT_PORTAL METHOD 643 // This method is used by Package HTMLProcessors, and doesn't need to be exported to the user 644 // Stats.run is NOT STATIC!!! 645 646 void run( 647 JavaSourceCodeFile jscf, JavaDocHTMLFile jdhf, 648 int numHLM, int numHLC, int numHLF, int numHLAE, int numHLEC, 649 int numHLD 650 ) 651 { 652 Method[] mArr = jscf.getMethods(); 653 Constructor[] cArr = jscf.getConstructors(); 654 Field[] fArr = jscf.getFields(); 655 AnnotationElem[] eArr = jscf.getAnnotationElems(); 656 EnumConstant[] xArr = jscf.getEnumConstants(); 657 658 final Stats ps = this.packageStatsMap.get(jdhf.packageName); 659 660 // Currently, this has been verified to be impossible. If something changes, a 661 // 'JavaDocError' throw is the best way to handle it. Note that the 'cost' of doing 662 // this null-check is absolutely minimal. 663 664 if (ps == null) Messager.assertFailGeneralPurpose( 665 "While attempting to update the both the Global and the Package-Local " + 666 "Stats-Instance for JavaSourceCodeFile:\n " + 667 '[' + BYELLOW + jscf.fileName + RESET + '\n' + 668 "The Package-Local Stats-Instance that was returned from the Package-Stats Map " + 669 "was null.", 670 null 671 ); 672 673 // If this is an inner-class, then the number of lines in the class (and the number of 674 // bytes) will already have been counted when the Enclosing-Class was tallied. 675 // If this is an inner-class, just skip the counting of the lines/bytes for the class 676 677 if (! jdhf.isInner) 678 { 679 ps.numLines += jdhf.typeLineCount; 680 this.numLines += jdhf.typeLineCount; 681 ps.numBytes += jdhf.typeSizeChars; 682 this.numBytes += jdhf.typeSizeChars; 683 } 684 685 ps.numHiLitedDivs += numHLD; 686 this.numHiLitedDivs += numHLD; 687 688 ps.numMethods += mArr.length; 689 this.numMethods += mArr.length; 690 ps.numHiLitedMethods += numHLM; 691 this.numHiLitedMethods += numHLM; 692 ps.numDocumentedMethods += jdhf.numMethods(); 693 this.numDocumentedMethods += jdhf.numMethods(); 694 695 ps.numConstructors += cArr.length; 696 this.numConstructors += cArr.length; 697 ps.numHiLitedConstructors += numHLC; 698 this.numHiLitedConstructors += numHLC; 699 ps.numDocumentedConstructors += jdhf.numConstructors(); 700 this.numDocumentedConstructors += jdhf.numConstructors(); 701 702 ps.numFields += fArr.length; 703 this.numFields += fArr.length; 704 ps.numHiLitedFields += numHLF; 705 this.numHiLitedFields += numHLF; 706 ps.numDocumentedFields += jdhf.numFields(); 707 this.numDocumentedFields += jdhf.numFields(); 708 709 ps.numAnnotationElems += eArr.length; 710 this.numAnnotationElems += eArr.length; 711 ps.numHiLitedAnnotationElems += numHLAE; 712 this.numHiLitedAnnotationElems += numHLAE; 713 ps.numDocumentedAnnotationElems += jdhf.numAnnotationElems(); 714 this.numDocumentedAnnotationElems += jdhf.numAnnotationElems(); 715 716 ps.numEnumConstants += xArr.length; 717 this.numEnumConstants += xArr.length; 718 ps.numHiLitedEnumConstants += numHLEC; 719 this.numHiLitedEnumConstants += numHLEC; 720 ps.numDocumentedEnumConstants += jdhf.numEnumConstants(); 721 this.numDocumentedEnumConstants += jdhf.numEnumConstants(); 722 723 for (Method m : mArr) m.modifiers.forEach((String modifier) -> 724 { 725 switch (modifier) 726 { 727 case "static" : this.numStaticMethods++; 728 ps.numStaticMethods++; 729 break; 730 case "public" : this.numPublicMethods++; 731 ps.numPublicMethods++; 732 break; 733 case "protected" : this.numProtectedMethods++; 734 ps.numProtectedMethods++; 735 break; 736 case "private" : this.numPrivateMethods++; 737 ps.numPrivateMethods++; 738 break; 739 case "final" : this.numFinalMethods++; 740 ps.numFinalMethods++; 741 break; 742 } 743 }); 744 745 for (Constructor c : cArr) c.modifiers.forEach((String modifier) -> 746 { 747 switch (modifier) 748 { 749 case "public" : this.numPublicConstructors++; 750 ps.numPublicConstructors++; 751 break; 752 case "protected" : this.numProtectedConstructors++; 753 ps.numProtectedConstructors++; 754 break; 755 case "private" : this.numPrivateConstructors++; 756 ps.numPrivateConstructors++; 757 break; 758 case "final" : this.numFinalConstructors++; 759 ps.numFinalConstructors++; 760 break; 761 } 762 }); 763 764 for (Field f : fArr) f.modifiers.forEach((String modifier) -> 765 { 766 switch (modifier) 767 { 768 case "static" : this.numStaticFields++; 769 ps.numStaticFields++; 770 break; 771 case "public" : this.numPublicFields++; 772 ps.numPublicFields++; 773 break; 774 case "protected" : this.numProtectedFields++; 775 ps.numProtectedFields++; 776 break; 777 case "private" : this.numPrivateFields++; 778 ps.numPrivateFields++; 779 break; 780 case "final" : this.numFinalFields++; 781 ps.numFinalFields++; 782 break; 783 case "transient" : this.numTransientFields++; 784 ps.numTransientFields++; 785 break; 786 case "volatile" : this.numVolatileFields++; 787 ps.numVolatileFields++; 788 break; 789 } 790 }); 791 } 792 793 794 // ******************************************************************************************** 795 // ******************************************************************************************** 796 // To String 797 // ******************************************************************************************** 798 // ******************************************************************************************** 799 800 801 /** 802 * Generates a {@code String} that enapsulates all of the counters / running-totals inside 803 * this data statistic class. 804 * 805 * @return A {@code String} representation of this class. Only includes statistics about 806 * use of methods, constructors, fields etc... <B>DOES NOT INCLUDE</B> statistics regarding 807 * the use of the {@code <EMBED CLASS='external-html' ...>} tags. 808 */ 809 public String toString() 810 { 811 StringBuilder sb = new StringBuilder(); 812 813 for (String packageName : packageStatsMap.keySet()) sb.append( 814 "Stats for Package: [" + BCYAN + packageName + RESET + "]:\n\n" + 815 StrIndent.indent(toStringINTERNAL(packageStatsMap.get(packageName)), 4) + '\n' 816 ); 817 818 sb.append("UPGADE / BUILD TOTAL:\n\n" + toStringINTERNAL(this)); 819 820 return sb.toString(); 821 } 822 823 private static String toStringINTERNAL(Stats s) 824 { 825 return 826 StringParse.rightSpacePad("" + StringParse.commas(s.numLines), 12) + "Total Lines of Source Code\n" + 827 StringParse.rightSpacePad("" + StringParse.commas(s.numBytes), 12) + "Total Bytes of Source Code\n" + 828 '\n' + 829 StringParse.rightSpacePad("" + StringParse.commas(s.numHiLitedDivs), 12) + "HiLited DIV Tags\n" + 830 '\n' + 831 StringParse.rightSpacePad("" + StringParse.commas(s.numMethods), 12) + "Source Total Methods\n" + 832 StringParse.rightSpacePad("" + StringParse.commas(s.numFields), 12) + "Source Total Fields\n" + 833 StringParse.rightSpacePad("" + StringParse.commas(s.numConstructors), 12) + "Source Total Constructors\n" + 834 StringParse.rightSpacePad("" + StringParse.commas(s.numAnnotationElems), 12) + "Source Total Annotation Elements\n" + 835 StringParse.rightSpacePad("" + StringParse.commas(s.numEnumConstants), 12) + "Source Total Enumeration Constants\n" + 836 '\n' + 837 StringParse.rightSpacePad("" + StringParse.commas(s.numHiLitedMethods), 12) + "Method Bodies HiLited\n" + 838 StringParse.rightSpacePad("" + StringParse.commas(s.numHiLitedFields), 12) + "Fields Declarations HiLited\n" + 839 StringParse.rightSpacePad("" + StringParse.commas(s.numHiLitedConstructors), 12) + "Constructors Bodies HiLited\n" + 840 StringParse.rightSpacePad("" + StringParse.commas(s.numHiLitedAnnotationElems), 12) + "Annotation Elements HiLited\n" + 841 StringParse.rightSpacePad("" + StringParse.commas(s.numHiLitedEnumConstants), 12) + "Enumeration Constants HiLited\n" + 842 '\n' + 843 StringParse.rightSpacePad("" + StringParse.commas(s.numDocumentedMethods), 12) + "JavaDoc Documented Methods\n" + 844 StringParse.rightSpacePad("" + StringParse.commas(s.numDocumentedFields), 12) + "JavaDoc Documented Fields\n" + 845 StringParse.rightSpacePad("" + StringParse.commas(s.numDocumentedConstructors), 12) + "JavaDoc Documented Constructors\n" + 846 StringParse.rightSpacePad("" + StringParse.commas(s.numDocumentedAnnotationElems), 12) + "JavaDoc Documented Annotation Elements\n" + 847 StringParse.rightSpacePad("" + StringParse.commas(s.numDocumentedEnumConstants), 12) + "JavaDoc Documented Enumeration Constants\n" + 848 '\n' + 849 StringParse.rightSpacePad("" + StringParse.commas(s.numStaticMethods), 12) + "Static Methods\n" + 850 StringParse.rightSpacePad("" + StringParse.commas(s.numStaticFields), 12) + "Static Fields\n" + 851 '\n' + 852 StringParse.rightSpacePad("" + StringParse.commas(s.numFinalMethods), 12) + "Final Methods\n" + 853 StringParse.rightSpacePad("" + StringParse.commas(s.numFinalFields), 12) + "Final Fields\n" + 854 StringParse.rightSpacePad("" + StringParse.commas(s.numFinalConstructors), 12) + "Final Constructors\n" + 855 '\n' + 856 StringParse.rightSpacePad("" + StringParse.commas(s.numPublicMethods), 12) + "Public Methods\n" + 857 StringParse.rightSpacePad("" + StringParse.commas(s.numPublicFields), 12) + "Public Fields\n" + 858 StringParse.rightSpacePad("" + StringParse.commas(s.numPublicConstructors), 12) + "Public Constructors\n" + 859 '\n' + 860 StringParse.rightSpacePad("" + StringParse.commas(s.numProtectedMethods), 12) + "Protected Methods\n" + 861 StringParse.rightSpacePad("" + StringParse.commas(s.numProtectedFields), 12) + "Protected Fields\n" + 862 StringParse.rightSpacePad("" + StringParse.commas(s.numProtectedConstructors), 12) + "Protected Constructors\n" + 863 '\n' + 864 StringParse.rightSpacePad("" + StringParse.commas(s.numPrivateMethods), 12) + "Private Methods\n" + 865 StringParse.rightSpacePad("" + StringParse.commas(s.numPrivateFields), 12) + "Private Fields\n" + 866 StringParse.rightSpacePad("" + StringParse.commas(s.numPrivateConstructors), 12) + "Private Constructors\n" + 867 '\n' + 868 StringParse.rightSpacePad("" + StringParse.commas(s.numTransientFields), 12) + "Transient Fields\n" + 869 StringParse.rightSpacePad("" + StringParse.commas(s.numVolatileFields), 12) + "Volatile Fields\n"; 870 } 871 872 873 // ******************************************************************************************** 874 // ******************************************************************************************** 875 // Inserting Link into JavaDoc Directory MAIN-OVERVIEW FRAMES 876 // ******************************************************************************************** 877 // ******************************************************************************************** 878 879 880 private static final String HEADER = 881 "<HTML>\n<HEAD>\n" + 882 "<TITLE>Statistics</TITLE>\n" + 883 "<LINK rel='icon' type='image/jpg' href='favicon.jpg' />\n" + 884 "<LINK rel='stylesheet' type='text/css' href='stylesheets/Colors.css' />\n" + 885 "<LINK rel='stylesheet' type='text/css' href='stylesheets/Upgrader-Widgets.css' />\n" + 886 "</HEAD>\n" + 887 "<BODY CLASS=STATS>\n"; 888 889 private static final String FOOTER = "\n</BODY>\n</HTML>\n"; 890 891 // Writes a Java-Doc Viewable HTML File explaining the Statistics 892 // RETURN This shall return TRUE when the file was successfully written 893 // 894 // MESSAGER: 895 // 1) INVOKES: println, assertFailGeneralPurpose 896 // 2) INVOKED-BY: Only called once in Upgrade.upgrade, No Where Else 897 // 3) RETURNS: void - NOTHING 898 // 4) THROWS: UpgradeException (assertFailGeneralPurpose) 899 900 void saveStatsHTMLFile(String saveFileDirectory) 901 { 902 Messager.println("\nWriting Statistics to Root Java Doc Directory."); 903 904 StringBuilder html = new StringBuilder(); 905 906 html.append(HEADER); 907 908 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 909 // Regular Stats - Methods, Fields, etc... - (almost identical to: 'toString') 910 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 911 912 html.append("<TABLE CLASS=STATS>\n"); 913 914 for (Map.Entry<String, Stats> packageStats : packageStatsMap.entrySet()) 915 { 916 // Method, Constructor, Field, Counts etc... - COUNTS FOR EACH PACKAGE 917 html.append( 918 "\n\n\t<TR><TD COLSPAN=3> <BR /><BR /><BR /></TD></TR>\n" + 919 "\t<TR><TH ID='" + 920 packageStats.getKey() + // Using the Package-Name as the HTML-ID for finding it 921 "' COLSPAN=3>\n\t\tStats for Package: <SPAN CLASS=PNSTATS>" + 922 packageStats.getKey() + // Package-Name (as String) 923 "</SPAN></TH></TR>\n" + 924 toHTML_INTERNAL(packageStats.getValue()) + "\n\n" // Package-Stats (as Stats) 925 ); 926 927 // This was broken up into a separate method becuse it is so long 928 // 929 // NO MESSAGER, NO THROWS - EXCEPT ONE LINE OF Messager.println(...) 930 931 append_one_packages_embed_tag_statistics(packageStats, html); 932 } 933 934 935 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 936 // Method, Constructor, Field etc... - COUNT-TOTALS FOR COMPLETE PROJECT 937 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 938 939 html.append( 940 "\n\n\n\t<TR><TD COLSPAN=3> <BR /><BR /><BR /></TD></TR>\n" + 941 "\n\t<TR><TH COLSPAN=3><SPAN CLASS=PNTSTATS>UPGADE / BUILD TOTAL:</SPAN></TH></TR>" + 942 toHTML_INTERNAL(this) 943 ); 944 945 946 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 947 // Embed-Tag Count Totals ... - FOR COMPLETE PROJECT 948 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 949 950 html.append( 951 "\n\t<TR><TD COLSPAN=3> </TD></TR>\n" + 952 "\n\n\t<TR><TH COLSPAN=3><SPAN CLASS=PNTSTATS>Complete Upgrade Totals:" + 953 "</SPAN></TH></TR>\n" 954 ); 955 956 if (this.globalTagsMap != null) 957 958 // NO MESSAGER, NO THROWS 959 tagCountToHTML( 960 globalTagsCount, this.globalTagsMap, html, 961 true, // YES, Print the Zero-Count 962 true // This is the GLOBAL TagsMap Count 963 ); 964 965 html.append("</TABLE>\n"); 966 967 968 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 969 // Write File, Exit 970 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 971 972 html.append(FOOTER); 973 974 String saveFileName = saveFileDirectory + STATS_HTML_FILENAME; 975 976 try 977 { FileRW.writeFile(html, saveFileName); } 978 979 catch (Exception ioe) 980 { 981 Messager.setCurrentFileName 982 (saveFileName, "Computed Project-Statistics HTML-Page"); 983 984 Messager.assertFailGeneralPurpose 985 (ioe, "Exception Writing Stats.html - <A> Anchor Links will be broken.", null); 986 } 987 988 if (MessagerVerbose.isVerbose()) 989 MessagerVerbose.println("Wrote File: " + BYELLOW + saveFileName + RESET); 990 } 991 992 // This method was extracted out of the loop and turned into an independent method. 993 // It looks better this way. That's all. 994 // 995 // NO MESSAGER, NO THROWS - EXCEPT ONE LINE OF Messager.println(...) 996 997 private void append_one_packages_embed_tag_statistics 998 (Map.Entry<String, Stats> packageStats, StringBuilder html) 999 { 1000 Stats s = packageStats.getValue(); 1001 1002 if (MessagerVerbose.isVerbose()) MessagerVerbose.println 1003 ("Printing Stats to HTML for Package: " + packageStats.getKey()); 1004 1005 // Absolute number of "Package-Local Embed Tags" are used - regardless of whether there 1006 // were any "Package-Local Embed Tags" even defined. 1007 int nPkgTags = (s.packageTagsCount == null) ? 0 : s.packageTagsCount.size(); 1008 1009 // Absolute number for "Package-Local Use of Global Embed Tags" 1010 int nGblTags = (s.globalTagsCount == null) ? 0 : s.globalTagsCount.size(); 1011 1012 // IF A SPECIFIC PACKAGE DOES NOT USE <EMBED CLASS='external-html'> TAGS, SKIP IT. 1013 if ((nPkgTags == 0) && (nGblTags == 0)) return; 1014 1015 html.append( 1016 "\n\n\t<TR><TH COLSPAN=3>Embed Tag FILE-ID Counts for Package: " + 1017 "<SPAN CLASS=PNSTATS>" + packageStats.getKey() + "</SPAN></TH></TR>\n" 1018 ); 1019 1020 if (nGblTags > 0) // Package-Local USE OF *GLOBAL Embed-Tags 1021 { 1022 html.append( 1023 "\n\t<TR><TD COLSPAN=3> </TD></TR>\n" + 1024 "\n\t<TR><TD COLSPAN=3><B>Global <EMBED> Tags Used:</B></TD></TR>\n" 1025 ); 1026 1027 // NO MESSAGER, NO THROWS 1028 tagCountToHTML( 1029 s.globalTagsCount, this.globalTagsMap, html, 1030 false, // Don't mention zero-counts (there cannot be any, anyway) 1031 // Since this is "Package Use of Global-Tags", it's not important 1032 // 1033 true // This tells it that these are global-counts, so it prints it properly 1034 ); 1035 } 1036 1037 if (nPkgTags > 0) // Package-Local Tags 1038 { 1039 html.append( 1040 "\n\t<TR><TD COLSPAN=3> </TD></TR>\n" + 1041 "\n\t<TR><TD COLSPAN=3><B>Package-Local <EMBED> Tags Used:</B></TD></TR>\n" 1042 ); 1043 1044 // NO MESSAGER, NO THROWS 1045 tagCountToHTML( 1046 s.packageTagsCount, s.packageTagsMap, html, 1047 true, // Print the zero-counts, These are Package-Tags, so if the user didn't 1048 // did not use some tags, put a notice about it. 1049 // 1050 false // This tells it that these are local-counts, so it prints it properly 1051 ); 1052 } 1053 } 1054 1055 1056 // ******************************************************************************************** 1057 // ******************************************************************************************** 1058 // Generating Stats HTML Files 1059 // ******************************************************************************************** 1060 // ******************************************************************************************** 1061 1062 1063 // This merely builds an HTML table out of an instance of Stats 1064 // NOTE: It **DOES NOT** include the "Package-Level" stats Tables. 1065 // That is done recursively. 1066 // 1067 // NO MESSAGER, NO THROWS 1068 1069 private static String toHTML_INTERNAL(Stats s) 1070 { 1071 return 1072 "\t<TR CLASS=BLANK><TD COLSPAN=3> </TD>\n" + 1073 1074 "\t<TR><TD>" + StringParse.commas(s.numLines) + "</TD><TD COLSPAN=2>Total Lines of Source Code</TD></TR>\n" + 1075 "\t<TR><TD>" + StringParse.commas(s.numBytes) + "</TD><TD COLSPAN=2>Total Bytes of Source Code</TD></TR>\n" + 1076 "\t<TR CLASS=BLANK><TD COLSPAN=3> </TD>\n" + 1077 1078 "\t<TR><TD>" + StringParse.commas(s.numHiLitedDivs) + "</TD><TD COLSPAN=2>HiLited DIV Tags</TD></TR>\n" + 1079 "\t<TR CLASS=BLANK><TD COLSPAN=3> </TD>\n" + 1080 1081 "\t<TR><TD>" + StringParse.commas(s.numMethods) + "</TD><TD COLSPAN=2>Source Total Methods</TD></TR>\n" + 1082 "\t<TR><TD>" + StringParse.commas(s.numFields) + "</TD><TD COLSPAN=2>Source Total Fields</TD></TR>\n" + 1083 "\t<TR><TD>" + StringParse.commas(s.numConstructors) + "</TD><TD COLSPAN=2>Source Total Constructors</TD></TR>\n" + 1084 "\t<TR><TD>" + StringParse.commas(s.numAnnotationElems) + "</TD><TD COLSPAN=2>Source Total Annotation Elements</TD></TR>\n" + 1085 "\t<TR><TD>" + StringParse.commas(s.numEnumConstants) + "</TD><TD COLSPAN=2>Source Total Enumeration Constants</TD></TR>\n" + 1086 "\t<TR><TD COLSPAN=3> </TD>\n" + 1087 1088 "\t<TR><TD>" + StringParse.commas(s.numHiLitedMethods) + "</TD><TD COLSPAN=2>Method Bodies HiLited</TD></TR>\n" + 1089 "\t<TR><TD>" + StringParse.commas(s.numHiLitedFields) + "</TD><TD COLSPAN=2>Fields Declarations HiLited</TD></TR>\n" + 1090 "\t<TR><TD>" + StringParse.commas(s.numHiLitedConstructors) + "</TD><TD COLSPAN=2>Constructors Bodies HiLited</TD></TR>\n" + 1091 "\t<TR><TD>" + StringParse.commas(s.numHiLitedAnnotationElems) + "</TD><TD COLSPAN=2>Annotation Elements HiLited</TD></TR>\n" + 1092 "\t<TR><TD>" + StringParse.commas(s.numHiLitedEnumConstants) + "</TD><TD COLSPAN=2>Enumeration Constants HiLited</TD></TR>\n" + 1093 "\t<TR CLASS=BLANK><TD COLSPAN=3> </TD>\n" + 1094 1095 "\t<TR><TD>" + StringParse.commas(s.numDocumentedMethods) + "</TD><TD COLSPAN=2>JavaDoc Documented Methods</TD></TR>\n" + 1096 "\t<TR><TD>" + StringParse.commas(s.numDocumentedFields) + "</TD><TD COLSPAN=2>JavaDoc Documented Fields</TD></TR>\n" + 1097 "\t<TR><TD>" + StringParse.commas(s.numDocumentedConstructors) + "</TD><TD COLSPAN=2>JavaDoc Documented Constructors</TD></TR>\n" + 1098 "\t<TR><TD>" + StringParse.commas(s.numDocumentedAnnotationElems) + "</TD><TD COLSPAN=2>JavaDoc Documented Annotation Elements</TD></TR>\n" + 1099 "\t<TR><TD>" + StringParse.commas(s.numDocumentedEnumConstants) + "</TD><TD COLSPAN=2>JavaDoc Documented Enumeration Constants</TD></TR>\n" + 1100 "\t<TR CLASS=BLANK><TD COLSPAN=3> </TD>\n" + 1101 1102 "\t<TR><TD>" + StringParse.commas(s.numStaticMethods) + "</TD><TD COLSPAN=2>Static Methods</TD></TR>\n" + 1103 "\t<TR><TD>" + StringParse.commas(s.numStaticFields) + "</TD><TD COLSPAN=2>Static Fields</TD></TR>\n" + 1104 "\t<TR CLASS=BLANK><TD COLSPAN=3> </TD>\n" + 1105 1106 "\t<TR><TD>" + StringParse.commas(s.numFinalMethods) + "</TD><TD COLSPAN=2>Final Methods</TD></TR>\n" + 1107 "\t<TR><TD>" + StringParse.commas(s.numFinalFields) + "</TD><TD COLSPAN=2>Final Fields</TD></TR>\n" + 1108 "\t<TR><TD>" + StringParse.commas(s.numFinalConstructors) + "</TD><TD COLSPAN=2>Final Constructors</TD></TR>\n" + 1109 "\t<TR CLASS=BLANK><TD COLSPAN=3> </TD>\n" + 1110 1111 "\t<TR><TD>" + StringParse.commas(s.numPublicMethods) + "</TD><TD COLSPAN=2>Public Methods</TD></TR>\n" + 1112 "\t<TR><TD>" + StringParse.commas(s.numPublicFields) + "</TD><TD COLSPAN=2>Public Fields</TD></TR>\n" + 1113 "\t<TR><TD>" + StringParse.commas(s.numPublicConstructors) + "</TD><TD COLSPAN=2>Public Constructors</TD></TR>\n" + 1114 "\t<TR CLASS=BLANK><TD COLSPAN=3> </TD>\n" + 1115 1116 "\t<TR><TD>" + StringParse.commas(s.numProtectedMethods) + "</TD><TD COLSPAN=2>Protected Methods</TD></TR>\n" + 1117 "\t<TR><TD>" + StringParse.commas(s.numProtectedFields) + "</TD><TD COLSPAN=2>Protected Fields</TD></TR>\n" + 1118 "\t<TR><TD>" + StringParse.commas(s.numProtectedConstructors) + "</TD><TD COLSPAN=2>Protected Constructors</TD></TR>\n" + 1119 "\t<TR CLASS=BLANK><TD COLSPAN=3> </TD>\n" + 1120 1121 "\t<TR><TD>" + StringParse.commas(s.numPrivateMethods) + "</TD><TD COLSPAN=2>Private Methods</TD></TR>\n" + 1122 "\t<TR><TD>" + StringParse.commas(s.numPrivateFields) + "</TD><TD COLSPAN=2>Private Fields</TD></TR>\n" + 1123 "\t<TR><TD>" + StringParse.commas(s.numPrivateConstructors) + "</TD><TD COLSPAN=2>Private Constructors</TD></TR>\n" + 1124 "\t<TR CLASS=BLANK><TD COLSPAN=3> </TD>\n" + 1125 1126 "\t<TR><TD>" + StringParse.commas(s.numTransientFields) + "</TD><TD COLSPAN=2>Transient Fields</TD></TR>\n" + 1127 "\t<TR><TD>" + StringParse.commas(s.numVolatileFields) + "</TD><TD COLSPAN=2>Volatile Fields</TD></TR>\n" + 1128 "\t<TR CLASS=BLANK><TD COLSPAN=3> </TD>\n"; 1129 } 1130 1131 // This one works slightly differently than the previous "toHTML" function 1132 // It places the appended text inside the passed StringBuilder 1133 // 1134 // NO MESSAGER, NO THROWS 1135 1136 private static void tagCountToHTML( 1137 Map<String, Integer> embedTagsCount, 1138 ReadOnlyMap<String, String> embedTagsMap, 1139 StringBuilder sb, 1140 boolean printZeros, 1141 boolean globalOrLocal 1142 ) 1143 { 1144 StringBuilder zerosCountSB = new StringBuilder(); 1145 1146 sb.append("\t<TR><TD COLSPAN=3> </TD></TR>\n"); 1147 1148 for (ReadOnlyMap.Entry<String, String> embedTag : embedTagsMap.entrySet()) 1149 { 1150 Integer count = embedTagsCount.get(embedTag.getKey()); 1151 1152 if (count == null) continue; 1153 1154 String s = 1155 "\t<TR>" + 1156 "<TD>" + StringParse.commas(count) + "</TD>" + 1157 "<TD>" + embedTag.getKey() + "</TD>" + 1158 "<TD>" + embedTag.getValue() + "</TD>" + 1159 "</TR>\n"; 1160 1161 if (count > 0) sb.append(s); 1162 1163 if (printZeros && (count == 0)) zerosCountSB.append(s); 1164 } 1165 1166 sb.append("\t<TR><TD COLSPAN=3> </TD></TR>\n"); 1167 1168 if (printZeros && (zerosCountSB.length() > 0)) 1169 1170 sb.append( 1171 "\n\t<TR><TD COLSPAN=3> </TD></TR>\n" + 1172 "\n\t<TR><TD COLSPAN=3><B>Unused " + 1173 (globalOrLocal ? "Global" : "Package-Local ") + 1174 "<EMBED> Tags:</B></TD></TR>\n" + 1175 "\n\t<TR><TD COLSPAN=3> </TD></TR>\n" + 1176 zerosCountSB.toString() + 1177 "\n\t<TR><TD COLSPAN=3> </TD></TR>\n" 1178 ); 1179 } 1180 1181 1182 // ******************************************************************************************** 1183 // ******************************************************************************************** 1184 // Generating Stats Buttons 1185 // ******************************************************************************************** 1186 // ******************************************************************************************** 1187 1188 1189 // This is the "Stats" button that's inserted into the pages 1190 private static final Vector<HTMLNode> nodesToInsert = 1191 HTMLPage.getPageTokens("<LI><A>Stats</A></LI>\n", false); 1192 1193 // In the above defined Vector, the <LI> has an HTML Anchor <A> at Vector-index 1. 1194 private static final int ANCHOR_POS = 1; 1195 1196 // Used by: "ExtraFilesProcessor" 1197 // 1198 // MESSAGER: 1199 // 1) INVOKES: warning *ONLY* 1200 // 2) INVOKED-BY: *ONCE* ExtraFilesProcessor 1201 // 3) RETURNS: NOTHING 1202 // 4) THROWS: NOTHING INTENTIONAL 1203 // 1204 // EXPORT_PORTAL METHOD 1205 // This method is used by Package HTMLProcessors, and doesn't need to be exported to the user. 1206 1207 static void addStatsButton(Vector<HTMLNode> page, String dotDots, String packageName) 1208 { 1209 AVT avt = 1210 AVT.cmp("class", TextComparitor.C, "navList").and( 1211 AVT.cmp("title", TextComparitor.EQ, "Navigation")); 1212 1213 Vector<SubSection> navMenus = InnerTagPeekInclusive.all(page, avt, "ul"); 1214 1215 if (navMenus.size() < 2) 1216 { 1217 Messager.warning 1218 ("No Navigtion Menus Found, not adding a 'Stats.html' Link.", JDUProcessor.Stats); 1219 return; 1220 } 1221 1222 SubSection topNav = navMenus.elementAt(0); 1223 SubSection tailNav = navMenus.elementAt(1); 1224 1225 // MESSAGER: 1226 // 1) INVOKES: Messager.warning 1227 // 2) INVOKED-BY: HERE 1228 // 3) RETURN: 'false' if the Messager *WAS* used on warning 1229 // 4) THROWS: NO THROW STATEMENTS 1230 1231 if (! addStatsButton(topNav.html, tailNav.html, dotDots, packageName)) return; 1232 1233 ReplaceNodes.r(page, topNav); 1234 ReplaceNodes.r(page, tailNav); 1235 } 1236 1237 // Used by: "MainFilesProcessor" 1238 // Inserts a button into the Navigation Bar on a Java Doc HTML Page. 1239 // 1240 // MESSAGER: 1241 // 1) INVOKES: Messager.warning 1242 // 2) INVOKED-BY: Twice - MainFilesProcessor (once), addStatsButton (above) 1243 // 3) RETURN: 'false' if the Messager *WAS* used on warning 1244 // 4) THROWS: NO THROW STATEMENTS 1245 // 1246 // EXPORT_PORTAL METHOD 1247 // This method is used by Package HTMLProcessors, and doesn't need to be exported to the user. 1248 1249 @SuppressWarnings("unchecked") // The clone invocation 1250 static boolean addStatsButton( 1251 Vector<HTMLNode> navBarTop, Vector<HTMLNode> navBarBottom, 1252 String dotDots, String packageName 1253 ) 1254 { 1255 // Find: <ul class="navList" title="Navigation"> 1256 AVT avt = 1257 AVT.cmp("class", TextComparitor.C, "navList").and( 1258 AVT.cmp("title", TextComparitor.EQ, "Navigation")); 1259 1260 // Get the Pertinent Navigator-Menu. It is a sub-part of the overall Navigation-Bar 1261 // The Stats Button is added to the first Navigation-List <UL> of both the bottom 1262 // and top Navigation-Bar. 1263 1264 DotPair topDP = InnerTagFindInclusive.first(navBarTop, avt, "ul"); 1265 DotPair bottomDP = InnerTagFindInclusive.first(navBarBottom, avt, "ul"); 1266 1267 // Print some pointless warnings. This will one day break. Warning messages are better 1268 // than Unknown-Exceptions. Not everybody uses the Navigation-Menus, and what will 1269 // happen once a user runs this without them is currently unknown. 1270 1271 boolean topNull = topDP == null; 1272 boolean tailNull = bottomDP == null; 1273 1274 if (topNull && tailNull) 1275 { 1276 Messager.warning("This page does not have any Navigatin Menus", JDUProcessor.Stats); 1277 return false; 1278 } 1279 1280 else if (topNull || tailNull) 1281 { 1282 if (topNull) Messager.warning 1283 ("Page does not have a Top Navigation Menu.", JDUProcessor.Stats); 1284 1285 if (tailNull) Messager.warning 1286 ("Page does not have a Tail Navigation Menu.", JDUProcessor.Stats); 1287 1288 return false; 1289 } 1290 1291 // Clone the STATIC-FINAL 'nodesToInsert' Vector. 1292 Vector<HTMLNode> v = (Vector<HTMLNode>) nodesToInsert.clone(); 1293 1294 // The HTML <A HREF=...> elemet that needs the RELATIVE-PATH URL w/ 'dotDots' 1295 TagNode anchor = (TagNode) nodesToInsert.elementAt(ANCHOR_POS); 1296 1297 // Set the HREF for the anchor-url link 1298 anchor = anchor.setAV("HREF", dotDots + "Stats.html#" + packageName, SD.SingleQuotes); 1299 1300 // Replace the old HTML Anchor Element with the updated one having the 1301 // relative path String to the base Java Doc directory. 1302 1303 v.setElementAt(anchor, ANCHOR_POS); 1304 1305 // Insert the updated navigator-menu item into the page, AS THE LAST ELEMENT 1306 // of the menu (beginning at the node JUST-BEFORE the one located at navMenu.end) 1307 1308 /*if (! topNull) */ navBarTop.addAll(topDP.end, v); 1309 /*if (! tailNull) */ navBarBottom.addAll(bottomDP.end, v); 1310 1311 return true; 1312 } 1313}