1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | package Torello.JDUInternal.Features.STATS; import Torello.JavaDoc.*; import java.util.*; import java.util.stream.*; import Torello.HTML.*; import Torello.HTML.NodeSearch.*; import Torello.Java.*; import static Torello.Java.C.*; import Torello.Java.ReadOnly.ReadOnlyList; import Torello.JDUInternal.Parse.Java.JSCF.JavaSourceCodeFile; import Torello.JDUInternal.Messager.Where.JDUFeatures; import Torello.JDUInternal.Messager.Messager; import Torello.JDUInternal.Messager.MsgControl; import Torello.JDUInternal.Messager.MsgVerbose; import Torello.JDUInternal.Messager.Where.Where_Am_I; import Torello.Java.ReadOnly.ReadOnlyMap; import Torello.Java.ReadOnly.ReadOnlyTreeMap; // Maintains a suite of statistics about all Java project-wide source-code files. // // <BR />As the Upgrade Processors are executed, this class maintains a few statistics about the // build, and produces the {@code Stats} HTML instance, which is subsequently linked to a // {@code 'Stats'} button on output Java Doc Web-Pages - and also returned to the user after // calling the ugrader public class StatsInternal { private static final Where_Am_I WHERE_AM_I = JDUFeatures.STATS.asSubSection( StatsInternal.class, "Compute Statistics about the User's Project" ); // ******************************************************************************************** // ******************************************************************************************** // ***Optimization Fields*** // ******************************************************************************************** // ******************************************************************************************** // The same package will be referenced, over and over, until the package has completed // These tags are used hundreds of times in some of the packages. String LAST_USED_packageName = null; StatsInternal LAST_USED_packageStats = null; // Package-Level instances of 'Stats' will have their package-names saved here. // For the "Complete-Project" Stats instance, this will be null. public final String packageName; // Each Package has it's own / recursive instance of 'Stats' // For the Package-Level instances of 'Stats' - this field will be null. public final Map<String, StatsInternal> packageStatsMap; // A Pointer to the "Project-Global Embed-Tags Map" public final ReadOnlyMap<String, String> globalTagsMap; // A Count-Total for the "Project-Global Embed-Tags Map" public final Map<String, Integer> globalTagsCount; // A reference pointer to the "Package-Local Embed-Tag Map", (ID's ==> FileNames) // NOTE: For the top-level main 'Stats' instance, this will remain null public final ReadOnlyMap<String, String> packageTagsMap; // Keeps a count of the use of all "Package-Local Embed-Tags" // NOTE: For the top-level main 'Stats' instance, this will remain null public final Map<String, Integer> packageTagsCount; // ******************************************************************************************** // ******************************************************************************************** // 3 Constructors: 1) Top-Level (First / Empty), 2) Top-Level w/Map, 3) Java-Package // ******************************************************************************************** // ******************************************************************************************** // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // Constructor: Initial-Starting Instance (usually clobbered & Discarded) - Empty, Top-Level! // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // // This builds a "Global Stats" that doesn't have any Global Embed-Tags. This is the // constructor used by configuration-class "Upgrade" in the "fields initializers" section. // When the instance that is created by this constructor IS NOT CLOBBERED NOR DISCARDED, it // means that the user DID NOT register a Global Embed-Tags Map. // // SPECIFICALLY: The following line is the "first initialization used" (inside Class-Upgrade) // private StatsInternal stats = new StatsInternal(); // // If the User registers a global Embed-Tags Map, then this instance is SIMPLY-DISCARDED // (Garbage Collected), and a new instance assigned to the "StatsInternal" Upgrade Field // via the "setProjectGlobalEmbedTagsMap()" initialization-configuration method inside class // "Upgrade". // // AGAIN: Usually this instance is built, **BUT** then replaced if the user configures the // upgrade class with a Global Embed Tags map. In the Java HTML JAR an instance is // built using this constructor, but then destoyed immediately after registering. // This is not a big enough waste - when compared to the alternative (which is writing // another "register map" method). // // FOR USERS WHO DO NOT REGISTER A GLOBAL EMBED TAGS MAP, THE INSTANCE CREATED BY THIS // CONSTRFUCTOR - OBVIOUSLY - WON'T BE GARBAGE COLLECTED. public StatsInternal() { // This Constructor is used to build a "Global-Stats" instance, so therefore it doesn't // have a Java Package-Name with which it may be associated. this.packageName = null; // Hopefully, the user will provide some StatsInternal instances for Java-Packages within // his or her project... And when they do, StatsInternal will be ready! this.packageStatsMap = new HashMap<>(); // As an aside - if this constructor were used to construct "Package Stats Instances", then // these would be Non-Null-Empty Map & ReadOnlyMap instances. However, this constructor // is designed for being used to build the lone/singleton "Top Level Stats" instance. // // The Top-Level Stats instance isn't about a single Java-Package at all. It isn't an // "EMPTY" Java-Package (one in which the End-User simply didn't provide Embed-Tags, or an // Embed-Tags Map), *BUT RATHER* an instance which is counting the Global-Tags only. // // Here (and this *IS* the "complexity"), these *SHOULD* be null, rather than "Empty-Maps" this.packageTagsMap = null; // This is, indeed, a "Global-Tags" Instance this.packageTagsCount = null; // It is not a "Package-Tags" Instance - these are null! // Note this constructor is invoked, once, at the top of Class-Upgrade, and it is built // with the presumption that the user isn't planning on providing a "Global-Tags Map". // The decision isn't final until the Upgrade.upgrade() method is invoked, and the // JDU actually starts running... // // Until then, the user may further configure the Upgrade-Class, and does indeed have the // ability provide a Global-Tags Map. If he does, the instance that has been generated // by this constructor would be *DISCARDED* and Garbage-Collected.... this.globalTagsMap = ReadOnlyTreeMap.emptyROTM(); this.globalTagsCount = Map.of(); } // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // Constructor: The "Top-Level" or the "Project-Global" StatsInternal instance // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** public StatsInternal(ReadOnlyMap<String, String> globalTagsMap) { // This is a 'JavaDocError' rather than a message to the messager because this should // *NEVER* occur. At the time of the writing of this exception-check, this constructor is // invoked from the 'Upgrade' Confguration class. A null-check is done there on th euser // input. If that changes or moves, it should be thought of as "My Fault" not // "Their Fault" - so this has to be a 'THROW' rather than a 'MESSAGER' error. // // Keep these here because this class seems Ultra-Simple at first glance, but because it // is ALL ABOUT DATA, it is sort of more DIFFICULT than one might expect. // // The Exception/Errors in this class ARE ALL FOR MISTAKES that should NEVER happen, NO // MATTER WHAT the user has entered or passed to the Upgrade-Configuration class. if (globalTagsMap == null) Messager.assertFailCheckup( "A null 'globalTagsMap' was passed to the Stats Constructor. If there are no " + "Global Embed Tags being used with this Project, the Upgrade-Configuration class " + "is supposed to be using the Stats-class zero-argument constructor", WHERE_AM_I ); // This is the "Top-Level" StatsInternal Instance. It is for the Project-Wide Stats, and // it therefore DOES NOT have a Package-Name. It is not affiliated with any single Java // Package. this.packageName = null; // There will (extemely likely) be User-Packages added. this.packageStatsMap = new HashMap<>(); // The "Global Stats" (a.k.a. the "Top-Level" StatsInternal Instance) doesn't have any // Package-Tags // // AGAIN: This constructor is only used for building the "Global Stats" instance. this.packageTagsMap = null; // This is "null", rather than an Empty ReadOnlyMap this.packageTagsCount = null; // This is also "null", rather than an empty java.util.Map this.globalTagsMap = globalTagsMap; this.globalTagsCount = new HashMap<>(); // This must be initialized here. Even if a Tag is not used, knowing that it's count // is ZERO is helpful to the user. If we leave it null here, yes, that could be // interpreted as a ZERO, but it looks nicer here, and at the end to put a zero, rather // than leaving it null and reverse-checking the global-map. final Integer ZERO = Integer.valueOf(0); // Initialize the PROJECT-GLOBAL tag-count map. for (String embedTag : globalTagsMap.keySet()) this.globalTagsCount.put(embedTag, ZERO); } // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** // Constructor: User-Package, StatsInternal instances // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** private StatsInternal( final String packageName, final ReadOnlyMap<String, String> packageTagsMap, final ReadOnlyMap<String, String> globalTagsMap ) { this.packageName = packageName; if (packageTagsMap == null) Messager.assertFailCheckup( "A null 'packageTagsMap' was passed to the StatsInternal Constructor. If there are " + "no Package-Local Embed Tags being used an empty instance is supposed to be passed.", WHERE_AM_I ); // The "Top-Level" StatsInternal instance is a container. (Side-Note, it is not a tree, // but rather, just a container of "Package Instances" of StatsInternal). // // This constructor is assigned the modifier "private" - it is used, below, to register a // a User-Provided Java-Package instance. // // This isn't a "Tree-Like" Data-Structure, the Top-Level StatsInternal instance has a list // of StatsInternal instances - one for each Java-Package in the Users overall Java-Project // (a.k.a. the User's "Build"). this.packageStatsMap = null; // "Package" instances don't have "Sub-Packages" // "Package" instance don't need the "Global Tag Map" ref, but rather than leaving it null, // there is no harm in passing it to *this* constructor from the "registerPackage" method. // Remember, this constructor is private, meaning it can only be invoked from within this // class. The only place that this constructor is invoked is from the "registerPackage" // method, directly below the body of this constructor. // // this.globalTagsMap is just a simple, direct-copy, of the Map from the owner-stats // instance that "contains" this Package-Level StatsInternal instance... this.globalTagsMap = globalTagsMap; this.globalTagsCount = new HashMap<>(); // If there is a User-Provided Java-Project in which the user has not defined any <EMBED> // tags, and no "[pkg-dir]/upgrade-files/external-html-ids.properties" file was available, // then the "packageTagsMap" instance which is provided WILL NOT BE NULL, but rather it // will be a Non-Null-Empty-Map. this.packageTagsMap = packageTagsMap; this.packageTagsCount = new HashMap<>(); final Integer ZERO = Integer.valueOf(0); for (final String embedTag : this.packageTagsMap.keySet()) this.packageTagsCount.put(embedTag, ZERO); } // ******************************************************************************************** // ******************************************************************************************** // Register a new Java-Package // ******************************************************************************************** // ******************************************************************************************** // This is called by the "External HTML Initialization" Code. When this is invoked, a t this // point in that code, the 'packageTagsMap' has just been read in from the // 'upgrade-files/external-html/external-html-ids.properties' file. public void registerPackage( String packageName, ReadOnlyMap<String, String> packageTagsMap ) { this.packageStatsMap.put (packageName, new StatsInternal(packageName, packageTagsMap, this.globalTagsMap)); } // ******************************************************************************************** // ******************************************************************************************** // Stats Fields: BASIC - NOTE: ALL OF THESE ARE PACKAGE-PRIVATE // ******************************************************************************************** // ******************************************************************************************** // A count of the total number of lines of {@code '.java'} files int numLines; // A count of the total number of bytes of {@code '.java'} files. int numBytes; // A count of the total number of HiLited HTML {@code <DIV>} Elements. int numHiLitedDivs = 0; // A count of the total number of methods, ctors, fields, ae's and ec's found during upgrade int numMethods = 0, numConstructors = 0, numFields = 0, numAnnotationElems = 0, numEnumConstants = 0; // A count of the total number of method, ctor, field, ae and ec bodies hilited by the upgrade int numHiLitedMethods = 0, numHiLitedConstructors = 0, numHiLitedFields = 0, numHiLitedAnnotationElems = 0, numHiLitedEnumConstants = 0; // A count of the total number of entities that were documented by Java Doc. int numDocumentedMethods = 0, numDocumentedConstructors = 0, numDocumentedFields = 0, numDocumentedAnnotationElems = 0, numDocumentedEnumConstants = 0; // A count of the total number of static methods/fiedls found during the upgrade. int numStaticMethods = 0, numStaticFields = 0; // A count of the total number of final FCM found by the upgrade. int numFinalMethods = 0, numFinalConstructors = 0, numFinalFields = 0; // A count of the total number of public FCM found by the upgrader. int numPublicMethods = 0, numPublicConstructors = 0, numPublicFields = 0; // The total number of protected FCM found during the upgrade. int numProtectedMethods = 0, numProtectedConstructors = 0, numProtectedFields = 0; // The total number of private FCM found during the upgrade. int numPrivateMethods = 0, numPrivateConstructors = 0, numPrivateFields = 0; // A count of the total number of {@code transient} fields found during the upgrade. int numTransientFields = 0; // A count of the total number of {@code volatile} fields found during the upgrade. int numVolatileFields = 0; // ******************************************************************************************** // ******************************************************************************************** // If I can make the above fields be **PACKAGE-PRIVATE** - I SHALL DO SO !! // ******************************************************************************************** // ******************************************************************************************** // *** NOTE *** These methods are ONLY USED IN ONE LOCATION - THE CONSTRUCTOR FOR // Torello.JavaDoc.Stats // // ALSO: These are all **PUBLIC** Getters for **PACKAGE-PRIVATE** Fields ! public int numLines() { return this.numLines; } public int numBytes() { return this.numBytes; } public int numHiLitedDivs() { return this.numHiLitedDivs; } // A count of the total number of methods, ctors, fields, ae's and ec's found during upgrade public int numMethods() { return this.numMethods; } public int numConstructors() { return this.numConstructors; } public int numFields() { return this.numFields; } public int numAnnotationElems() { return this.numAnnotationElems; } public int numEnumConstants() { return this.numEnumConstants; } // A count of the total number of method, ctor, field, ae and ec bodies hilited by the upgrade public int numHiLitedMethods() { return this.numHiLitedMethods; } public int numHiLitedConstructors() { return this.numHiLitedConstructors; } public int numHiLitedFields() { return this.numHiLitedFields; } public int numHiLitedAnnotationElems() { return this.numHiLitedAnnotationElems; } public int numHiLitedEnumConstants() { return this.numHiLitedEnumConstants; } // A count of the total number of entities that were documented by Java Doc. public int numDocumentedMethods() { return this.numDocumentedMethods; } public int numDocumentedConstructors() { return this.numDocumentedConstructors; } public int numDocumentedFields() { return this.numDocumentedFields; } public int numDocumentedAnnotationElems() { return this.numDocumentedAnnotationElems; } public int numDocumentedEnumConstants() { return this.numDocumentedEnumConstants; } // A count of the total number of static methods/fiedls found during the upgrade. public int numStaticMethods() { return this.numStaticMethods; } public int numStaticFields() { return this.numStaticFields; } // A count of the total number of final FCM found by the upgrade. public int numFinalMethods() { return this.numFinalMethods; } public int numFinalConstructors() { return this.numFinalConstructors; } public int numFinalFields() { return this.numFinalFields; } // A count of the total number of public FCM found by the upgrader. public int numPublicMethods() { return this.numPublicMethods; } public int numPublicConstructors() { return this.numPublicConstructors; } public int numPublicFields() { return this.numPublicFields; } // The total number of protected FCM found during the upgrade. public int numProtectedMethods() { return this.numProtectedMethods; } public int numProtectedConstructors() { return this.numProtectedConstructors; } public int numProtectedFields() { return this.numProtectedFields; } // The total number of private FCM found during the upgrade. public int numPrivateMethods() { return this.numPrivateMethods; } public int numPrivateConstructors() { return this.numPrivateConstructors; } public int numPrivateFields() { return this.numPrivateFields; } // A count of the total number of {@code transient} fields found during the upgrade. public int numTransientFields() { return this.numTransientFields; } // A count of the total number of {@code volatile} fields found during the upgrade. public int numVolatileFields() { return this.numVolatileFields; } } |