001package Torello.JavaDoc; 002 003import Torello.HTML.*; 004import Torello.HTML.NodeSearch.*; 005import Torello.JDUInternal.HTMLProcessors.Other.*; 006import Torello.JDUInternal.ParseHTML.*; 007import Torello.Java.Additional.*; 008import Torello.Java.*; 009 010import Torello.Java.ReadOnly.ReadOnlyArrayList; 011import Torello.Java.ReadOnly.ReadOnlyList; 012 013import static Torello.Java.C.*; 014 015import Torello.JDUInternal.GeneralPurpose.Messager; 016 017import Torello.JDUInternal.ParseJavaSource.JavaSourceCodeFile; 018 019import Torello.JDUInternal.DataClasses.MainLoopData.JDHFHeaderFacts; 020 021import Torello.JDUInternal.DataClasses.ClassUpgradeData.UpgradePredicates; 022import Torello.JDUInternal.DataClasses.ClassUpgradeData.PathsAndTypes; 023 024import java.util.*; 025import java.util.regex.*; 026import java.util.stream.*; 027 028import java.io.File; 029import java.util.function.Predicate; 030import java.util.function.Function; 031 032/** 033 * Retains all information parsed from a <CODE>'.html'</CODE> Java-Doc web-page, and borrows 034 * any missing information that was found in the <CODE>'.java'</CODE> source-code file; note 035 * that an instance-reference of this class may be rerieved, and used, to further change a Java 036 * Doc page by registering a visitor-handler with the configuration class {@link Upgrade} by 037 * calling <B>{@link Upgrade#setExtraTasks(Consumer)}</B>. 038 * 039 * <EMBED CLASS='external-html' DATA-FILE-ID=PROG_MOD_HTML> 040 * <EMBED CLASS='external-html' DATA-FILE-ID=JD_HTML_F> 041 * 042 * @see JavaSourceCodeFile 043 */ 044@JDHeaderBackgroundImg(EmbedTagFileID="REFLECTION_HTML_CLASS") 045public final class JavaDocHTMLFile extends ParsedFile implements java.io.Serializable 046{ 047 /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */ 048 public static final long serialVersionUID = 1; 049 050 051 // ******************************************************************************************** 052 // ******************************************************************************************** 053 // Primary (Final) Fields 054 // ******************************************************************************************** 055 // ******************************************************************************************** 056 057 058 /** 059 * This provides the relative path-{@code String} from {@code 'this'} Java Doc generated 060 * {@code '.html'} File to the root Java Doc Directory. 061 */ 062 public final RelativePathStr dotDots; 063 064 // The HTML Vector for a Java Doc web-page 065 private final Vector<HTMLNode> fileVec; 066 067 // This is where the 'updated-vector' is saved after the changes have been recommitted. 068 private Vector<HTMLNode> updatedFileVec = null; 069 070 /** 071 * The HTML that occurs directly above the Summary-Tables is the header. The HTML that is 072 * located below the Detail-Entries is the footer. 073 */ 074 public final HeaderFooterHTML headerFooter; 075 076 /** 077 * This is the File-{@code URL} to use if a need to link to the corresponding 078 * {@code "/src-html/"} file is necessary. 079 * 080 * <BR /><BR />This is a <B STYLE='color: red;'>relative</B>-URL that contains the requisite 081 * number of 'dot-dots' to reach the file from the location where this Java Doc HTML File is 082 * located. 083 */ 084 public final String srcAsHTMLFileURL; 085 086 /** 087 * This is the File-{@code URL} to use if a need to link to the corresponding 088 * {@code "/hilite-files/"} file is necessary. 089 * 090 * <BR /><BR />This is a <B STYLE='color: red;'>relative</B>-URL that is relative to the file 091 * from the location where this Java Doc HTML File is located. Specifically, this 092 * {@code String} begins with the text {@code "/hilite-files/"}, followed by the type-name, 093 * and ending with the extension {@code ".java.html"} 094 */ 095 public final String hiLitedSrcFileURL; 096 097 098 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 099 // The HTML Details as Vector<ReflHTML<?>> 100 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 101 102 /** 103 * This is the list of all constructors in the "Constructor Details", stored as 104 * Reflection-HTML instances 105 */ 106 public final ReadOnlyList<ReflHTML<Constructor>> allConstructorDetails; 107 108 /** 109 * This is the list of all fields in the "Field Details", stored as Reflection-HTML 110 * instances 111 */ 112 public final ReadOnlyList<ReflHTML<Field>> allFieldDetails; 113 114 /** 115 * This is the list of all methods in the "Method Details", stored as Reflection-HTML 116 * instances 117 */ 118 public final ReadOnlyList<ReflHTML<Method>> allMethodDetails; 119 120 /** 121 * This is the list of all constants in the "Enumerated Constant Details", stored as 122 * Reflection-HTML instances 123 */ 124 public final ReadOnlyList<ReflHTML<EnumConstant>> allECDetails; 125 126 /** 127 * This is the list of all elements in the "Annotation Element Details", stored as 128 * Reflection-HTML instances 129 */ 130 public final ReadOnlyList<ReflHTML<AnnotationElem>> allAEDetails; 131 132 133 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 134 // The HTML Summaries as SummaryTableHTML 135 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 136 137 /** The HTML for a Method Summary */ 138 public final SummaryTableHTML<Method> methodSummaryTable; 139 140 /** The HTML for a Field Summary Table */ 141 public final SummaryTableHTML<Field> fieldSummaryTable; 142 143 /** The HTML for a Constructor Summary Table */ 144 public final SummaryTableHTML<Constructor> constructorSummaryTable; 145 146 /** The HTML for an Enum-Constant Summary Table */ 147 public final SummaryTableHTML<EnumConstant> ecSummaryTable; 148 149 /** The HTML for an Optional Annotation Element Summary Table */ 150 public final SummaryTableHTML<AnnotationElem> oaeSummaryTable; 151 152 /** The HTML for a Required Annotation Element Summary Table */ 153 public final SummaryTableHTML<AnnotationElem> raeSummaryTable; 154 155 /** The HTML for a Nested-Class (Inner-Class) Summary Table */ 156 public final SummaryTableHTML<NestedType> ntSummaryTable; 157 158 /** all non-null {@link SummaryTableHTML} instances */ 159 @SuppressWarnings("rawtypes") 160 private final Vector<SummaryTableHTML> allNonNullSummaryTables; 161 162 163 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 164 // Booleans for remembering whether a Details Section was removed completely 165 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 166 167 /** Identifies if this Java Doc HTML Page has had it's Method Details Removed */ 168 public final boolean methodDetailsRemoved; 169 170 /** Identifies if this Java Doc HTML Page has had it's Constructor Details Removed */ 171 public final boolean constructorDetailsRemoved; 172 173 /** Identifies if this Java Doc HTML Page has had it's Field Details Removed */ 174 public final boolean fieldDetailsRemoved; 175 176 /** Identifies if this Java Doc HTML Page has had it's Enumeration Constant Details Removed */ 177 public final boolean ecDetailsRemoved; 178 179 /** Identifies if this Java Doc HTML Page has had it's Annotation-Element Details Removed */ 180 public final boolean aeDetailsRemoved; 181 182 183 // ******************************************************************************************** 184 // ******************************************************************************************** 185 // Getters: Summaries 186 // ******************************************************************************************** 187 // ******************************************************************************************** 188 189 190 /** 191 * An {@code Iterator} that iterates the Summary Tables defined on this page. 192 * 193 * @return An Instance of {@code Iterator<SummaryTableHTML>}. 194 * 195 * <BR /><BR /><B STYLE='color: red;'>NOTE:</B> There is a <B>raw-type</B> used by the 196 * {@code Iterator} that is returned. If this method is invoked, it will either generate 197 * compiler warnings, or the @{@code SuppressWarnings("rawtypes")} annotation will need to be 198 * applied (and, likely, the suppressing of {@code "unchecked"} warnings will also have to be 199 * applied eventually) 200 */ 201 @SuppressWarnings("rawtypes") 202 public Iterator<SummaryTableHTML> allNonNullSummaryTables() 203 { return new RemoveUnsupportedIterator<>(allNonNullSummaryTables.iterator()); } 204 205 /** 206 * An {@code Stream} of the Summary Tables defined on this page. 207 * 208 * @return An Instance of {@code Stream<SummaryTableHTML>}. 209 * 210 * <BR /><BR /><B STYLE='color: red;'>NOTE:</B> There is a <B>raw-type</B> used by the 211 * {@code Stream} that is returned. If this method is invoked, it will either generate 212 * compiler warnings, or the @{@code SuppressWarnings("rawtypes")} annotation will need to be 213 * applied (and, likely, the suppressing of {@code "unchecked"} warnings will also have to be 214 * applied eventually) 215 */ 216 @SuppressWarnings("rawtypes") 217 public Stream<SummaryTableHTML> allNonNullSummaryTablesStream() 218 { return allNonNullSummaryTables.stream(); } 219 220 221 // ******************************************************************************************** 222 // ******************************************************************************************** 223 // Find Methods: Methods that accept a String / int 224 // ******************************************************************************************** 225 // ******************************************************************************************** 226 227 228 /** 229 * Returns a list as a {@code java.util.stream.Stream} of all Reflected-HTML-{@link Method} 230 * instances that have a name equal to {@code 'methodName'}. 231 * 232 * @param methodName The name of the method being searched for. 233 * 234 * @return A Java Stream containing all {@link Method}-{@link ReflHTML} instances that match 235 * the provided {@code 'methodName'} criteria. 236 */ 237 public Stream<ReflHTML<Method>> findMethodHTML(String methodName) 238 { 239 return allMethodDetails 240 .stream() 241 .filter((ReflHTML<Method> refl) -> refl.entity.name.equals(methodName)); 242 } 243 244 /** 245 * Returns a list as a {@code java.util.stream.Stream} of all Reflected-HTML-{@link Method} 246 * instances that have the specified number of parameters. 247 * 248 * @param numParameters The number of parameters contained by the {@link Method} being searched 249 * for. 250 * 251 * @return A Java Stream containing all {@link Method}-{@link ReflHTML} instances that match 252 * the provided {@code 'numParameters'} criteria. 253 */ 254 public Stream<ReflHTML<Method>> findMethodHTML(int numParameters) 255 { 256 return allMethodDetails 257 .stream() 258 .filter((ReflHTML<Method> refl) -> refl.entity.numParameters() == numParameters); 259 } 260 261 /** 262 * Returns a list as a {@code java.util.stream.Stream} of all 263 * Reflected-HTML-{@link Constructor} instances that have the specified number of parameters. 264 * 265 * @param numParameters The number of parameters contained by the {@link Constructor} being 266 * searched for. 267 * 268 * @return A Java Stream containing all {@link Constructor}-{@link ReflHTML} instances that 269 * match the provided {@code 'numParameters'} specifier. 270 */ 271 public Stream<ReflHTML<Constructor>> findConstructorHTML(int numParameters) 272 { 273 return allConstructorDetails 274 .stream() 275 .filter((ReflHTML<Constructor> refl) -> refl.entity.numParameters() == numParameters); 276 } 277 278 /** 279 * The Reflected-HTML Field having the specified name, or null if no such field exists 280 * 281 * @param fieldName The name of the field being searched 282 * 283 * @return The {@code ReflHTML<Field>} instance, from {@code 'this'} Java Doc Page, whose name 284 * matches {@code fieldName}, or null it wasn't found. 285 */ 286 public ReflHTML<Field> findFieldHTML(String fieldName) 287 { 288 for (ReflHTML<Field> f : allFieldDetails) if (f.entity.name.equals(fieldName)) return f; 289 return null; 290 } 291 292 /** 293 * The Reflected-HTML Enum-Constant having the specified name, or null if no such constant 294 * exists 295 * 296 * @param enumConstantName The name of the constant being searched 297 * 298 * @return The {@code ReflHTML<EnumConstant>} instance, from {@code 'this'} Java Doc Page, 299 * whose name matches {@code enumConstantName}, or null it wasn't found. 300 * 301 * @throws UpgradeException Only a Java {@link CIET}/Type {@code 'enum'} is allowed to declare 302 * Enum-Constants, and therefore this exception throws <I>when this method is invoked on a 303 * Java Doc HTML File that doesn't represent an {@code enum}.</I> 304 */ 305 public ReflHTML<EnumConstant> findECHTML(String enumConstantName) 306 { 307 if (this.ciet != CIET.ENUM) throw new UpgradeException( 308 "Finding Enumeration-Constants is only possible with HTML Files for Java 'enum' " + 309 "Type's. This file is of type [" + this.ciet.toString() + "]" 310 ); 311 312 for (ReflHTML<EnumConstant> ec : allECDetails) 313 if (ec.entity.name.equals(enumConstantName)) 314 return ec; 315 316 return null; 317 } 318 319 /** 320 * The Reflected-HTML Annotation-Element having the specified name, or null if no such element 321 * exists 322 * 323 * @param annotationElemName The name of the constant being searched 324 * 325 * @return The {@code ReflHTML<EnumConstant>} instance, from {@code 'this'} Java Doc Page, 326 * whose name matches {@code annotationElemName}, or null it wasn't found. 327 * 328 * @throws UpgradeException Only a Java {@link CIET}/Type {@code '@interface'} is allowed to 329 * declare Annotation-Elements, and therefore this exception throws <I>when this method is 330 * invoked on a Java Doc HTML File that doesn't represent an annotation.</I> 331 */ 332 public ReflHTML<AnnotationElem> findAEHTML(String annotationElemName) 333 { 334 if (this.ciet != CIET.ANNOTATION) throw new UpgradeException( 335 "Finding Annotation-Elements is only possible with HTML Files for Java '@interface' " + 336 "(Annotation) Type's. This file is of type [" + this.ciet.toString() + "]" 337 ); 338 339 for (ReflHTML<AnnotationElem> ae : allAEDetails) 340 if (ae.entity.name.equals(annotationElemName)) 341 return ae; 342 343 return null; 344 } 345 346 347 // ******************************************************************************************** 348 // ******************************************************************************************** 349 // Find Refl<HTML> Entities 350 // ******************************************************************************************** 351 // ******************************************************************************************** 352 353 354 /** 355 * Finds a matching {@link ReflHTML} instance whose internal {@code 'entity'} field has an 356 * ID number that matches input-parameter {@code 'declarationID'}. 357 * 358 * @param declarationID Whenever any instance of a sub-class of {@link Declaration} is created, 359 * it is given a unique id that uniquely identifies it across the entire life-cycle of the JVM 360 * that is currently running. 361 * 362 * @param c This must be a Java {@code java.lang.Class} from one of the following: 363 * {@link Constructor}, {@link Method}, {@link Field}, {@link EnumConstant} or 364 * {@link AnnotationElem}. 365 * 366 * <BR /><BR /><B>NOTE:</B> This class is very easily obtained by simple using the 367 * {@code 'enum'} field {@link Entity#upgraderReflectionClass}. To pass the appropriate class 368 * for a method, simply pass {@code Entity.METHOD.upgraderReflectionClass} to this parameter. 369 * 370 * <BR /><BR /><B>ALSO:</B> Even more easy (if you know the member/entity type), you can 371 * hard-code / hand-type the class yourself - for instance {@code Method.class}. If you were 372 * searching for a {@code ReflHTML<Field>}, you would pass {@code Field.class} to this 373 * parameter. 374 * 375 * @return The {@link ReflHTML} instance whose HTML describes the Method, Field, or Constructor 376 * etc... whose actual Reflected-class has an ID that matches {@code 'declarationID'}. Note 377 * that the second parameter {@code 'c'} is primarily used to "speed up" the search process. 378 * 379 * <DIV CLASS=EXAMPLE>{@code 380 * // Note the 'Method' being passed is Torello.JavaDoc.Method (not java.lang.reflect.Method) 381 * ReflHTML<Method> refl = jdhf.findEntity(someEntityID, Method.class); 382 * }</DIV> 383 * 384 * @throws IllegalArgumentException If the value passed to {@code 'declarationID'} is negative. 385 */ 386 @SuppressWarnings("unchecked") // Seems like the Java-Compiler is failing on this one. 387 public <ENTITY extends Declaration> ReflHTML<ENTITY> findReflHTML 388 (int declarationID, Class<ENTITY> c) 389 { 390 if (declarationID < 0) throw new IllegalArgumentException 391 ("You have passed a negative declarationID: " + declarationID); 392 393 if (Constructor.class.equals(c)) // This is **CLEARLY** not an unchecked cast! 394 for (ReflHTML<Constructor> r : allConstructorDetails) 395 { if (r.entity.id == declarationID) return (ReflHTML<ENTITY>) r; } 396 397 else if (Method.class.equals(c)) 398 for (ReflHTML<Method> r : allMethodDetails) 399 { if (r.entity.id == declarationID) return (ReflHTML<ENTITY>) r; } 400 401 else if (Field.class.equals(c)) 402 for (ReflHTML<Field> r : allFieldDetails) 403 { if (r.entity.id == declarationID) return (ReflHTML<ENTITY>) r; } 404 405 else if (EnumConstant.class.equals(c)) 406 for (ReflHTML<EnumConstant> r : allECDetails) 407 { if (r.entity.id == declarationID) return (ReflHTML<ENTITY>) r; } 408 409 else if (AnnotationElem.class.equals(c)) 410 for (ReflHTML<AnnotationElem> r : allAEDetails) 411 { if (r.entity.id == declarationID) return (ReflHTML<ENTITY>) r; } 412 413 return null; 414 } 415 416 417 // ******************************************************************************************** 418 // ******************************************************************************************** 419 // Constructor and Constructor-Helper 420 // ******************************************************************************************** 421 // ******************************************************************************************** 422 423 424 // MESSAGER 425 // 1) INVOKES: assertFailHTML 426 // 2) INVOKED-BY: MainFilesProcessor *ONLY* (once) 427 // 3) RETURNS: NOTHING, this is a constructor 428 // 4) THROWS: JavaDocHTMLParseException (assertFailHTML) 429 // 430 // NOTE: This makes many calls to the "ReflHTML" constructor, which obeys these 431 // Messager Rules as well. (Expects nothing, only uses assertFailHTML) 432 433 public JavaDocHTMLFile( 434 final UpgradePredicates predicates, 435 final PathsAndTypes pathsTypes, 436 final String jdHTMLFileName, 437 final JavaSourceCodeFile jscf, 438 final RelativePathStr dotDots, 439 final JDHFHeaderFacts jdhfHeaderFacts 440 ) 441 { 442 // The 'super' constructor must be on the first line. This is the signature of that 443 // Constructor. 444 // 445 // protected ParsedFile​( 446 // String fileName, String name, String packageName, CIET ciet, 447 // String[] genericParameters, String fullyQualifiedName 448 // ) 449 450 super( 451 jdHTMLFileName, // HTML File Name 452 jdhfHeaderFacts.simpleNameWithGenerics, // Un-Qualified-Name, Including GTP's (if any) 453 jdhfHeaderFacts.packageName, // The Java "Package Name" 454 jdhfHeaderFacts.ciet, // CIET, This is the source-code file 'kind' 455 jdhfHeaderFacts.genericParams, // List of "GTP Names" - if there are any 456 jdhfHeaderFacts.cietFullNameNoGenerics, // Fully Qualified Class Name, Without GTP's 457 // NOT USED: jdhfHeaderFacts.srcCodeFileName 458 jscf.startLineNumber, 459 jscf.endLineNumber, 460 jscf.jdStartLineNumber, 461 jscf.jdEndLineNumber, 462 jscf.typeLineCount, 463 jscf.typeSizeChars, 464 jscf.javaSrcFileAsStr 465 ); 466 467 468 // **************************************************************************************** 469 // **************************************************************************************** 470 // BEGINNING INITIALIZATIONS 471 // **************************************************************************************** 472 // **************************************************************************************** 473 474 475 // NOW, THIS IS PRIVATE, IT WASN'T IN THE PAST. 476 // Since breaking up the processing into small pieces (optimization), this MUST BE PRIVATE 477 478 final Vector<HTMLNode> fileVec = this.fileVec = jdhfHeaderFacts.fileVec; 479 480 // The relative-path string to the root javadoc directory (comprised of "../../..") 481 this.dotDots = dotDots; 482 483 // The mirros for @StaticFunctional **AND** JDHeaderBackgroundImg 484 this.annotationsMirror = jscf.annotationsMirror; 485 486 487 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 488 // URL to the corresponding "/src-html/" file (if it exists) - **INCLUDING LINE-NUMBERS** 489 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 490 // 491 // For "inner-classes", there is now a new-and-improved way to link to the JavaDoc source 492 // file. JavaDoc actually makes a mess out of **INNER-CLASSES** by making a duplicate / 493 // copy of the Java-Source-Code-As-HTML for each-and-every inner-class! This means that 494 // if there were say... 10 inner classes ... (as in Torello.Browser classes), there are 495 // 10 COPIES OF THE EXACT SAME FILES 496 // 497 // This helps clean that up... Note that the actual deletion of these duplicate src-file's 498 // is actually done by class "ExtraFilesProcessor" (right at the top of the class) 499 // 500 // NOTE: Perhaps the Java 17 JavaDoc doesn't make this seriously egregious error, but the 501 // JavaDoc released with JDK 11 seems to be doing that. I need to start upgrading 502 // for JDK 17 pretty soon... 503 // 504 // ALSO: Upgrade.getSrcHTMLFile(..) ==> a one-line of code HashMap lookup (no Messager) 505 506 this.srcAsHTMLFileURL = this.isInner 507 508 ? this.dotDots.fileSystem + pathsTypes.srcHTMLFiles.get( 509 this.packageName + '.' + 510 this.simpleName.substring(0, this.simpleName.indexOf('.')) 511 ) 512 : this.dotDots.fileSystem + pathsTypes.srcHTMLFiles.get(this.fullyQualifiedName); 513 514 /* 515 if (this.isInner) System.out.println( 516 "srcAsHTMLFile: " + this.srcAsHTMLFileURL + 517 "\n" + this.packageName + '.' + 518 this.simpleName.substring(0, this.simpleName.indexOf('.')) 519 ); 520 */ 521 522 523 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 524 // Get the Hilited Source File URL. This should be null if the file isn't being hilited. 525 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 526 // 527 // The class "NavButtons" will use this FileURL. The class HiLiteSrcCodeFile will actually 528 // do that hiliting. 529 530 if (! predicates.hiLiteSourceCodeFileFilter.test(this.fullyQualifiedName)) 531 this.hiLitedSrcFileURL = null; 532 533 else this.hiLitedSrcFileURL = 534 535 "hilite-files/" + 536 (this.isInner 537 ? this.simpleName.substring(0, this.simpleName.indexOf('.')) 538 : this.simpleName) + 539 ".java.html"; 540 541 542 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 543 // REMOVE THIS STUFF, **IF REQUESTED** DO THIS **BEFORE** THE PARSING EVEN STARTS 544 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 545 // 546 // The user has the option of removing an **ENTIRE** details section, on request. This is 547 // particularly useful for things like an "enum" that has lots of constants where each 548 // constant detail would be documented ad nauseum. This also used by the search-classes in 549 // the NodeSearch package where, for example, InnerTagFind has 100 methods, each of which 550 // take some slightly different variant of the exact same parameters. 551 // 552 // NOTE: The user even has the option of removing **ALL** Details (from all 553 // detail-sections) 554 // 555 // BTW: Every time you try to find where there is a test to check the value of 556 // "methodDetailsRemoved" or "methodDetailsRemoved", remember, these Detail-Removal 557 // Steps happen BEFORE THIS FILE'S HTML-CONTENT IS EVEN PARSED INTO Refl's !!! 558 // SO - NO, The class "DetailsProcessor" doesn't check these booleans before 559 // processing these ReflHTML's, because these Detail/ReflHTML's are never even created 560 // to begin with - Notice the Details.removeAllDetails happens, right here, right now. 561 562 if (predicates.removeAllDetailsFilter.test(this.fullyQualifiedName)) 563 { 564 try 565 { Details.removeAllDetails(fileVec); } 566 567 catch (Exception e) 568 { Messager.assertFailHTML(e, "Unexpected-Exception Removing Details HTML", null); } 569 570 this.methodDetailsRemoved = this.fieldDetailsRemoved = this.constructorDetailsRemoved = 571 this.ecDetailsRemoved = this.aeDetailsRemoved = true; 572 } 573 574 // Same-Story, but this only removes sub-sections of the generalized "Details Sections" on 575 // a Java-Doc Web-Page. The "Constructor Details" could be removed without removing the 576 // Method-Details at all. 577 578 else try 579 { 580 UpgradePredicates p = predicates; 581 582 if (this.methodDetailsRemoved = 583 p.removeAllMethodDetailsFilter.test(this.fullyQualifiedName)) 584 Details.removeAllDetails(fileVec, Entity.METHOD); 585 586 if (this.fieldDetailsRemoved = 587 p.removeAllFieldDetailsFilter.test(this.fullyQualifiedName)) 588 Details.removeAllDetails(fileVec, Entity.FIELD); 589 590 if (this.constructorDetailsRemoved = 591 p.removeAllConstructorDetailsFilter.test(this.fullyQualifiedName)) 592 Details.removeAllDetails(fileVec, Entity.CONSTRUCTOR); 593 594 if (this.ecDetailsRemoved = 595 p.removeAllECDetailsFilter.test(this.fullyQualifiedName)) 596 Details.removeAllDetails(fileVec, Entity.ENUM_CONSTANT); 597 598 if (this.aeDetailsRemoved = 599 p.removeAllAEDetailsFilter.test(this.fullyQualifiedName)) 600 Details.removeAllDetails(fileVec, Entity.ANNOTATION_ELEM); 601 } 602 603 catch (Exception e) 604 { 605 Messager.assertFailHTML(e, "Unexpected-Exception Removing Details HTML", null); 606 607 throw new UnreachableError(); 608 // Since this is a constructor, "return Messager..."" **CANNOT** work here.\ 609 // If this is not here => compiler gives "might not have been initialized" errors 610 } 611 612 613 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 614 // Header-Footer 615 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 616 // 617 // INVOKED-BY: JavaDocHTMLFile *ONLY* (once) 618 619 this.headerFooter = new HeaderFooterHTML(fileVec, this.ciet); 620 621 622 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 623 // Now add the CSS-Tags to the header & footer, do this here... 624 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 625 // 626 // INVOKED-BY: JavaDocHTMLFile Constructor (once) 627 628 if (predicates.cssTagsFilter.test(this.fullyQualifiedName)) 629 CSSTagsTopAndSumm.addTagsToDetailBanners(fileVec); 630 631 632 // **************************************************************************************** 633 // **************************************************************************************** 634 // DETAILS ENTRIES 635 // **************************************************************************************** 636 // **************************************************************************************** 637 638 639 HNLIInclusive iter; 640 Vector<HTMLNode> details; 641 DotPair dp; 642 643 644 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 645 // Parse the Java Doc HTML "Method Details", one by one. Add to internal Vectors. 646 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 647 648 Function<DotPair, ReflHTML<Method>> getMethod = (DotPair methodDetail) -> 649 { 650 // Retrieve the signature of the method from the Java Doc HTML 651 final DotPair signature = TagNodeFindInclusive.first 652 (fileVec, methodDetail.start, methodDetail.end, "pre"); 653 654 if (signature == null) Messager.assertFailHTML 655 ("Method Detail Section does not appear to have a Signature <PRE>", null); 656 657 // SignatureParse.parseECSignature: is called twice: 658 // Once from JavaDocHTMLFile-Constructor: using the Detail-HTML-Signature 659 // Once from SummaryTableHTML-Constructor: using the Summary-HTML-Signature 660 // 661 // USES: Messager.assertFailHTML() (JavaDocHTMLParseException) 662 663 final Method method = SignatureParse.parseMethodSignature 664 (Util.textNodesString(fileVec, signature), jscf, this); 665 666 // ParsedFile (parent-class) "addMethod" (it's a one-liner, no Messager) 667 addMethod(method); 668 669 return new ReflHTML<>( 670 method, methodDetail, fileVec, Entity.METHOD, 671 getDetailID(fileVec, methodDetail, method), 672 this.isInner ? this.srcAsHTMLFileURL : null 673 ); 674 }; 675 676 List<DotPair> l = Details.sectionAllDetailsDP(fileVec, Entity.METHOD); 677 678 this.allMethodDetails = new ReadOnlyArrayList<>(l, getMethod, l.size()); 679 680 681 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 682 // Parse the Java Doc HTML "Constructor Details", one by one. Add to internal Vectors. 683 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 684 685 Function<DotPair, ReflHTML<Constructor>> getConstructor = (DotPair constructorDetail) -> 686 { 687 // Retrieve the signature of the constructor from the Java Doc HTM 688 final DotPair signature = TagNodeFindInclusive.first 689 (fileVec, constructorDetail.start, constructorDetail.end, "pre"); 690 691 if (signature == null) Messager.assertFailHTML 692 ("Constructor Detail Section does not appear to have a Signature <PRE>", null); 693 694 // SignatureParse.parseConstructorSignature: is called twice: 695 // Once from JavaDocHTMLFile-Constructor: using the Detail-HTML-Signature 696 // Once from SummaryTableHTML-Constructor: using the Summary-HTML-Signature 697 // 698 // USES: Messager.assertFailHTML() (JavaDocHTMLParseException) 699 700 final Constructor constructor = SignatureParse.parseConstructorSignature 701 (Util.textNodesString(fileVec, signature), jscf, this); 702 703 // ParsedFile (parent-class) "addConstructor" (it's a one-liner, no Messager) 704 addConstructor(constructor); 705 706 return new ReflHTML<>( 707 constructor, constructorDetail, fileVec, Entity.CONSTRUCTOR, 708 getDetailID(fileVec, constructorDetail, constructor), 709 this.isInner ? this.srcAsHTMLFileURL : null 710 ); 711 }; 712 713 l = Details.sectionAllDetailsDP(fileVec, Entity.CONSTRUCTOR); 714 715 this.allConstructorDetails = new ReadOnlyArrayList<>(l, getConstructor, l.size()); 716 717 718 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 719 // Parse the Java Doc HTML "Field Details", one by one. Add to internal Vectors. 720 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 721 722 Function<DotPair, ReflHTML<Field>> getField = (DotPair fieldDetail) -> 723 { 724 // Retrieve the signature of the field from the Java Doc HTML 725 final DotPair signature = TagNodeFindInclusive.first 726 (fileVec, fieldDetail.start, fieldDetail.end, "pre"); 727 728 if (signature == null) Messager.assertFailHTML 729 ("Field Detail Section does not appear to have a Signature <PRE>", null); 730 731 // SignatureParse.parseFieldSignature: is called twice: 732 // Once from JavaDocHTMLFile-Constructor: using the Detail-HTML-Signature 733 // Once from SummaryTableHTML-Constructor: using the Summary-HTML-Signature 734 // 735 // USES: Messager.assertFailHTML() (JavaDocHTMLParseException) 736 // 737 // HERE, pass 'genericParameters' because Java Doc inserts the definition into 738 // the signature on the web-page. They have to be removed, or JP throws exception. 739 740 final Field field = SignatureParse.parseFieldSignature( 741 Util.textNodesString(fileVec, signature), 742 genericParameters.size() > 0, 743 jscf, this 744 ); 745 746 // ParsedFile (parent-class) "addField" (it's a one-liner, no Messager) 747 addField(field); 748 749 return new ReflHTML<>( 750 field, fieldDetail, fileVec, Entity.FIELD, 751 getDetailID(fileVec, fieldDetail, field), 752 this.isInner ? this.srcAsHTMLFileURL : null 753 ); 754 }; 755 756 l = Details.sectionAllDetailsDP(fileVec, Entity.FIELD); 757 758 this.allFieldDetails = new ReadOnlyArrayList<>(l, getField, l.size()); 759 760 761 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 762 // Parse the Java Doc HTML "Enumeration-Constant Details". Add to the internal Vectors. 763 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 764 765 Function<DotPair, ReflHTML<EnumConstant>> getEC = (DotPair ecDetail) -> 766 { 767 // Retrieve the signature of the enumeration-constant from the Java Doc HTML 768 final DotPair signature = TagNodeFindInclusive.first 769 (fileVec, ecDetail.start, ecDetail.end, "pre"); 770 771 if (signature == null) Messager.assertFailHTML 772 ("EC Detail Section does not appear to have a Signature <PRE>", null); 773 774 // SignatureParse.parseECSignature: is called twice: 775 // Once from JavaDocHTMLFile-Constructor: using the Detail-HTML-Signature 776 // Once from SummaryTableHTML-Constructor: using the Summary-HTML-Signature 777 // 778 // USES: Messager.assertFailHTML() (JavaDocHTMLParseException) 779 780 final EnumConstant ec = SignatureParse.parseECSignature 781 (Util.textNodesString(fileVec, signature), jscf, this); 782 783 // ParsedFile (parent-class) "addEnumConstant" (it's a one-liner, no Messager) 784 addEnumConstant(ec); 785 786 return new ReflHTML<EnumConstant>( 787 ec, ecDetail, fileVec, Entity.ENUM_CONSTANT, 788 getDetailID(fileVec, ecDetail, ec), 789 this.isInner ? this.srcAsHTMLFileURL : null 790 ); 791 }; 792 793 l = Details.sectionAllDetailsDP(fileVec, Entity.ENUM_CONSTANT); 794 795 this.allECDetails = new ReadOnlyArrayList<>(l, getEC, l.size()); 796 797 798 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 799 // Parse the Java Doc HTML "Annotation-Element Details". Add to the internal Vectors. 800 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 801 802 Function<DotPair, ReflHTML<AnnotationElem>> getAE = (DotPair aeDetail) -> 803 { 804 // Retrieve the signature of the annotation-element from the Java Doc HTML 805 final DotPair signature = TagNodeFindInclusive.first 806 (fileVec, aeDetail.start, aeDetail.end, "pre"); 807 808 if (signature == null) Messager.assertFailHTML 809 ("Detail Section does not appear to have a Signature <PRE>", null); 810 811 // SignatureParse.parseAESignature: is called twice: 812 // Once from JavaDocHTMLFile-Constructor: using the Detail-HTML-Signature 813 // Once from SummaryTableHTML-Constructor: using the Summary-HTML-Signature 814 // 815 // USES: Messager.assertFailHTML() (JavaDocHTMLParseException) 816 817 final AnnotationElem ae = SignatureParse.parseAESignature 818 (Util.textNodesString(fileVec, signature), jscf, this); 819 820 // ParsedFile (parent-class) "addAnnotationElem" (it's a one-liner, no Messager) 821 addAnnotationElem(ae); 822 823 return new ReflHTML<AnnotationElem>( 824 ae, aeDetail, fileVec, Entity.ANNOTATION_ELEM, 825 getDetailID(fileVec, aeDetail, ae), 826 this.isInner ? this.srcAsHTMLFileURL : null 827 ); 828 }; 829 830 l = Details.sectionAllDetailsDP(fileVec, Entity.ANNOTATION_ELEM); 831 832 this.allAEDetails = new ReadOnlyArrayList<>(l, getAE, l.size()); 833 834 835 // **************************************************************************************** 836 // **************************************************************************************** 837 // SUMMARIES ENTRIES 838 // **************************************************************************************** 839 // **************************************************************************************** 840 841 842 // if (! Q.YN(C.BGREEN + "Should this continue?" + C.RESET)) System.exit(1); 843 844 RetN r = SummaryTableHTML.parseAllSummaryTables(fileVec, jscf, this); 845 846 this.methodSummaryTable = r.GET(1); 847 this.fieldSummaryTable = r.GET(2); 848 this.constructorSummaryTable = r.GET(3); 849 this.ecSummaryTable = r.GET(4); 850 this.oaeSummaryTable = r.GET(5); 851 this.raeSummaryTable = r.GET(6); 852 this.ntSummaryTable = r.GET(7); 853 854 @SuppressWarnings("rawtypes") 855 Stream.Builder<SummaryTableHTML> b = Stream.builder(); 856 857 if (methodSummaryTable != null) b.accept(methodSummaryTable); 858 if (fieldSummaryTable != null) b.accept(fieldSummaryTable); 859 if (constructorSummaryTable != null) b.accept(constructorSummaryTable); 860 if (ecSummaryTable != null) b.accept(ecSummaryTable); 861 if (oaeSummaryTable != null) b.accept(oaeSummaryTable); 862 if (raeSummaryTable != null) b.accept(raeSummaryTable); 863 if (ntSummaryTable != null) b.accept(ntSummaryTable); 864 865 allNonNullSummaryTables = b.build().collect(Collectors.toCollection(Vector::new)); 866 } 867 868 869 // ******************************************************************************************** 870 // ******************************************************************************************** 871 // Retrieve a Detail CSS ID 872 // ******************************************************************************************** 873 // ******************************************************************************************** 874 875 876 // This just extracts the little HTML ID for the detail-element, This is used by the 877 // NavButton class 878 // 879 // NOTE: The HTML for an Annotation-Element (StaticFunction: "Excuses", "Excused") 880 // is every-so-slightly different. The <A ID=..> is AFTER the element 881 882 private static String getDetailID 883 (Vector<HTMLNode> fileVec, DotPair detailLoc, Declaration d) 884 { 885 // Usually this works, except for annotations (look before the top/start of the loc) 886 DotPair anchorLocation = InnerTagFindInclusive.last 887 (fileVec, detailLoc.start - 20, detailLoc.start, "a", "id"); 888 889 // If this is an AnnotationElement, ==> Look in ahead, (after the start), rather 890 // than behind, which is what was just done. 891 892 if (anchorLocation == null) if (d instanceof AnnotationElem) 893 anchorLocation = InnerTagFindInclusive.first 894 (fileVec, detailLoc.start, detailLoc.start + 20, "a", "id"); 895 896 // Since this error has never happened (except with AnnotationElements), we should 897 // presume that it will never happen, and if it does, an informative error message 898 // is printed. The Jump-Foward and Jump-Backward Navigation-Buttons help the UI a lot. 899 900 if (anchorLocation == null) Messager.assertFailHTML 901 ("No Anchor with ID Attribute Found for this Detail Element", d.signature); 902 903 /* 904 // Make sure that there is a small Comment with a white-space body in it. That's the 905 // best effort at checking / making sure this is the right <A ID>... 906 // 907 // NOTE: This has been eliminated, but I'm not exactly sure why. 908 909 CommentNode c = null; 910 boolean found = false; 911 912 for (int i = (anchorLocation.start + 1); i < anchorLocation.end; i++) 913 914 if ((c = fileVec.elementAt(i).ifCommentNode()) != null) 915 if (c.body.trim().length() == 0) 916 { found=true; break; } 917 918 if (! found) Messager.assertFailHTML 919 ("Anchor with ID does not have <!-- -->", d.signature); 920 */ 921 922 // Get the TagNode 923 TagNode tn = (TagNode) fileVec.elementAt(anchorLocation.start); 924 925 // The last sanity check is that the Anchor *DOES NOT* have an HREF=... (which almost 926 // all <A> Anchor Tags usually do). Except when used for these purposes, they are useless 927 // with an HREF=... Attribute 928 // 929 // If this one has an HREF=... presume it is the wrong one, and complain... 930 931 if (tn.has("href")) Messager.assertFailHTML 932 ("Anchor with ID also has HREF=... Attribute for this Detail Element", d.signature); 933 934 return tn.AV("id"); 935 } 936 937 938 // ******************************************************************************************** 939 // ******************************************************************************************** 940 // Links-Checker Access-Method 941 // ******************************************************************************************** 942 // ******************************************************************************************** 943 944 945 // StrReplace Helper String[]-Arrays 946 private static final String[] MATCH_STRS = { "%3C", "%3E", "%5B", "%5D" }; 947 private static final String[] REPLACE_STRS = { "<" , ">", "[", "]" }; 948 949 // This Retrieves all CSS-ID's and all <A HREF=...> (the HREF part) from every HTMLNode in 950 // this set, and checks returns them as two TreeSet's. 951 // 952 // Ret2.a: All CSS-ID's found on the page - *NOTE*, this is the *POST-PROCESSED* page 953 // Ret2.b: All HREF Attributes inside of every <A>/Anchor on this page 954 // 955 // This is called by the LinksChecker class 956 957 public /* Made Public With The Big-Move, was Package-Private */ 958 Ret2<TreeSet<String>, TreeSet<String>> allIDsAndHREFs() 959 { 960 TreeSet<String> allIDs = new TreeSet<>(); 961 TreeSet<String> allHREFs = new TreeSet<>(); 962 TagNode tn; 963 964 for (HTMLNode n : updatedFileVec) 965 966 if ((tn = n.openTagPWA()) != null) 967 { 968 String id = tn.AV("id"); 969 String href = tn.AV("href"); 970 971 if (id != null) allIDs.add(id); 972 973 if (href != null) 974 { 975 if (href.equals("#top")) continue; 976 977 if (StrCmpr.startsWithXOR( 978 href, "http://", "https://", "/", 979 "javascript:" 980 )) 981 continue; 982 983 allHREFs.add(StrReplace.r(href, MATCH_STRS, REPLACE_STRS)); 984 } 985 } 986 987 return new Ret2<>(allIDs, allHREFs); 988 } 989 990 991 // ******************************************************************************************** 992 // ******************************************************************************************** 993 // simple features exported by this class. 994 // ******************************************************************************************** 995 // ******************************************************************************************** 996 997 998 // Checks the validity of the HTML on a Java Doc Web-page 999 // @return The Balance Report, generated by class {@link Balance}. The ;identifies any 1000 // potential unmatched HTML tags. 1001 // 1002 // EXPORT_PORTAL METHOD 1003 // This method is used by Package HTMLProcessors, and doesn't need to be exported to the user. 1004 1005 Hashtable<String, Integer> checkValidity() 1006 { 1007 if (updatedFileVec == null) Messager.assertFailGeneralPurpose 1008 ("For some odd reason, the updatedFileVec has not been set", null); 1009 1010 return Balance.checkNonZero(Balance.check(updatedFileVec)); 1011 } 1012 1013 // Saves the Vectorized-HTML back to the file on disk from whence it was loaded. 1014 // @throws IOException This propogates any / all exceptions which might be thrown when 1015 // trying to write the file to the file-system. 1016 // 1017 // EXPORT_PORTAL METHOD 1018 // This method is used by Package HTMLProcessors, and doesn't need to be exported to the user. 1019 1020 void commitFileToDisk() throws java.io.IOException 1021 { 1022 if (updatedFileVec == null) Messager.assertFailGeneralPurpose 1023 ("For some odd reason, the updatedFileVec has not been set", null); 1024 1025 FileRW.writeFile(Util.pageToString(this.updatedFileVec), this.fileName); 1026 } 1027 1028 // Collates and inserts any changes made to the Sub-Sections back into the main page 1029 // 1030 // NO MESSAGER, NO THROWS, THE DATA IS ALL PRIVATE 1031 // 1032 // EXPORT_PORTAL METHOD 1033 // This method is used by Package HTMLProcessors, and doesn't need to be exported to the user. 1034 1035 @SuppressWarnings("unchecked") // The Vector<Replaceable> cast 1036 void commitChanges() 1037 { 1038 final TreeSet<Replaceable> replaceables = new TreeSet<>(); 1039 1040 allNonNullSummaryTables.forEach( 1041 (@SuppressWarnings("rawtypes") SummaryTableHTML sTable) -> 1042 replaceables.addAll((Vector<Replaceable>) sTable.allReplaceables()) 1043 ); 1044 1045 for (ReflHTML<Method> r : allMethodDetails) 1046 replaceables.addAll(r.allReplaceables()); 1047 1048 for (ReflHTML<Field> r : allFieldDetails) 1049 replaceables.addAll(r.allReplaceables()); 1050 1051 for (ReflHTML<Constructor> r : allConstructorDetails) 1052 replaceables.addAll(r.allReplaceables()); 1053 1054 for (ReflHTML<AnnotationElem> r : allAEDetails) 1055 replaceables.addAll(r.allReplaceables()); 1056 1057 for (ReflHTML<EnumConstant> r : allECDetails) 1058 replaceables.addAll(r.allReplaceables()); 1059 1060 replaceables.addAll(headerFooter.allReplaceables()); 1061 1062 this.updatedFileVec = ReplaceNodes.r(fileVec, replaceables, false).a; 1063 } 1064 1065 1066 // ******************************************************************************************** 1067 // ******************************************************************************************** 1068 // THE NEW-THING: Garbage-Collector Helper? 1069 // ******************************************************************************************** 1070 // ******************************************************************************************** 1071 // 1072 // Does this help? Is this "good" for the Garbage-Collect? Is this going to speed it up, 1073 // or slow it down? This is just a "C-Styled" FREE or DESTORY method... 1074 // It isn't publicly visible anyway... 1075 1076 void clear() 1077 { 1078 headerFooter.clear(); 1079 1080 // private final Vector<SummaryTableHTML> allNonNullSummaryTables; 1081 for (@SuppressWarnings("rawtypes") SummaryTableHTML st : allNonNullSummaryTables) 1082 st.clear(); 1083 } 1084}