001package Torello.JavaDoc;
002
003import Torello.HTML.HTMLNode;
004import Torello.HTML.TagNode;
005import Torello.HTML.Replaceable;
006import Torello.HTML.Util;
007import Torello.HTML.Balance;
008import Torello.HTML.Replacement;
009
010import Torello.Java.StrCmpr;
011import Torello.Java.StrIndent;
012import Torello.Java.StrReplace;
013import Torello.Java.FileRW;
014
015import Torello.Java.Additional.Ret2;
016
017import Torello.Java.ReadOnly.ReadOnlyList;
018
019import static Torello.Java.C.*;
020
021import Torello.JDUInternal.Messager.Where.JDUUserAPI;
022import Torello.JDUInternal.Messager.Messager;
023import Torello.JDUInternal.Messager.Where.Where_Am_I;
024
025import java.util.*;
026import java.util.regex.*;
027import java.util.stream.*;
028
029import java.io.File;
030import java.util.function.Predicate;
031import java.util.function.Function;
032
033/**
034 * Retains all information parsed from a <CODE>'&#46;html'</CODE> Java-Doc web-page, and borrows
035 * any missing information that was found in the <CODE>'&#46;java'</CODE> source-code file; note
036 * that an instance-reference of this class may be rerieved, and used, to further change a Java
037 * Doc page by registering a visitor-handler with the configuration class {@link Upgrade} by
038 * calling <B>{@link Upgrade#setExtraTasks(Consumer)}</B>.
039 * 
040 * <EMBED CLASS='external-html' DATA-FILE-ID=PROG_MOD_HTML>
041 * <EMBED CLASS='external-html' DATA-FILE-ID=JD_HTML_F>
042 */
043@JDHeaderBackgroundImg(EmbedTagFileID="REFLECTION_HTML_CLASS")
044public final class JavaDocHTMLFile extends ParsedFile implements java.io.Serializable
045{
046    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID>  */
047    public static final long serialVersionUID = 1;
048
049    // When the Messager Reports its errors, this class passes this reference to the Messager
050    // to facilitate the printing of that information (What class encountered an error or warning
051    // that needs to be printed by the Messager).
052    // 
053    // This is officially Package-Private (rather than private, which it normally is), because
054    // this Class is large enough to have justified breaking it up into smaller, private/hidden
055    // "Helper-Chunks".  I like that expression.
056    // 
057    // The "Helper-Chunks" are in the same package, and they need access to this field
058
059    static final Where_Am_I WHERE_AM_I = JDUUserAPI.JavaDocHTMLFile;
060
061
062    // ********************************************************************************************
063    // ********************************************************************************************
064    // Constructor
065    // ********************************************************************************************
066    // ********************************************************************************************
067
068
069    // This Constructor does very little work.  It is not a completely empty body, but the vast 
070    // majority of the field computations for this class are done in the package:
071    // 
072    // Torello.JDUInternal.Parse.HTML.JDHF
073    // 
074    // This Constructor mostly copies its Field-Values from Data-Records that have been computed
075    // in the classes in that package.  There is a brief amount of computation done here, below.
076    // 
077    // Keeping HTML-Parsing code in a separate, internal, package allows me to "localize" the
078    // complicated parsing code into a single location - far away from the end user.  This code
079    // is dependent upon which of the Java-Doc Versions is being used.
080    // 
081    // Since October of 2024, HTML-Parsing Code has been moved to a single, JDUInternal,
082    // suite of directories that are much easier to manage.  This constructor, for instance, just
083    // block copies nearly all of the fields from one of those JDUInternal Data-Record Classes.
084
085    public JavaDocHTMLFile(
086            final Torello.JDUInternal.MainJDU.ClassUpgradeData.UpgradePredicates    predicates,
087            final Torello.JDUInternal.MainJDU.ClassUpgradeData.PathsAndTypes        pathsTypes,
088
089            // Full-Path of this JavaDoc HTML-File
090            final String jdHTMLFileName,
091
092            // Same as above, but only the Directory-Name is included - File-Name has been removed
093            final String javaDocPackageDirName,
094
095            // Java-Doc Package-Directory Name where Hi-Lited Source-Files are stored for this pkg
096            final String javaDocPkgHiLitedSrcCodeDirName,
097
098            final Torello.JDUInternal.Parse.Java.JSCF.JavaSourceCodeFile jscf,
099
100            final RelativePathStr dotDots,
101
102            // August 2024: Stopped passing JDHFHeaderFacts, rip it apart, pass these instead
103            final String                simpleNameWithContainersAndGenerics,
104            final String                packageName,
105            final CIET                  ciet,
106            final ReadOnlyList<String>  genericParameters,
107            final String                cietFullNameNoGenerics,
108            final Vector<HTMLNode>      fileVec,
109
110            // The Members-Entites of this CIET/Type (Methods, Fields, Constructors, EC's & AE's)
111            final Torello.JDUInternal.Parse.HTML.JDHF.MemberDetails.D1_JDHFMembers jdhfMembers,
112
113
114            // This was moved out of this constructor body, and into the S2_LoopFiles...
115            // This is needed to build the JDHFMembers instance.  Now, therefore, it has to be
116            // passed into this constructor
117
118            final String srcAsHTMLFileURL,
119
120            // New class which handles any / all User-Requested Details removal
121            final Torello.JDUInternal.Parse.HTML.JDHF.D2_RemovedDetails removedDetails,
122
123
124            // The Package-Summary HTML-File
125            // The User may obtain access to this file, via the reference stored inside of this
126            // Class.
127            //
128            // March 28th, 2025
129    
130            final PackageSummaryHTML pkgSummaryHTML
131        )
132    {
133        super(
134            jdHTMLFileName,
135
136            // java.util.Map.Entry<K, V>  ==>  Map.Entry<K, V>
137            simpleNameWithContainersAndGenerics,
138
139            // java.util.Map.Entry<K, V>  ==>  java.util
140            packageName,
141
142            // java.util.Map.Entry<K, V>  ==>  CIET.CLASS
143            ciet,
144
145            // java.util.Map.Entry<K, V>  ==>  "K", and "V"
146            genericParameters,
147
148            // java.util.Map.Entry<K, V>  ==>  java.util.Map.Entry
149            cietFullNameNoGenerics,
150
151            // java.util.Map.Entry<K, V>  ==?  Entry
152            jscf.typeNameJOW,
153
154            jscf.startLineNumber,
155            jscf.endLineNumber,
156            jscf.jdStartLineNumber,
157            jscf.jdEndLineNumber,
158            jscf.typeLineCount,
159            jscf.typeSizeChars,
160            jscf.javaSrcFileAsStr,
161
162            jdhfMembers.methods,
163            jdhfMembers.fields,
164            jdhfMembers.constructors,
165            jdhfMembers.enumConstants,
166            jdhfMembers.annotationElements,
167
168
169            // I think this is the right way to do things...  This might change one day to ensure
170            // that only Nested-Types that are visible on the Java-Doc Page are actually included
171            // in this list
172            // 
173            // For now, any Inner-Type that is identified by the Source-Code Parser will be visible
174            // in an instance of JDHF - EVEN IF JAVADOC DID NOT CREATE ANY HTML FOR THAT NESTED-TYPE
175
176            jscf.nestedTypes
177        );
178
179
180        // ****************************************************************************************
181        // ****************************************************************************************
182        // BEGINNING INITIALIZATIONS
183        // ****************************************************************************************
184        // ****************************************************************************************
185
186
187        this.fileVec = fileVec;
188
189        // The directory name of the 'javadoc/' sub-directory that contained this '.html' File
190        this.javaDocPackageDirName = javaDocPackageDirName;
191
192
193        // The directory name of the 'javadoc/' sub-directory that contains any / all Hi-Lited 
194        // HTML-Files for this particular package.
195
196        this.javaDocPkgHiLitedSrcCodeDirName = javaDocPkgHiLitedSrcCodeDirName;
197
198        // The relative-path string to the root javadoc directory (comprised of "../../..")
199        this.dotDots = dotDots;
200
201        // The mirros for @StaticFunctional **AND** JDHeaderBackgroundImg
202        this.typeAnnotationMirrors = jscf.typeAnnotationMirrors;
203
204
205        // This used to be computed inside this constructor body.  Now it is computed inside the
206        // Main Processing Loop for JDHF Files
207
208        this.srcAsHTMLFileURL = srcAsHTMLFileURL;
209
210
211        // March, 2025: The User has access to the parsed 'package-summary.html' File
212        // This has been parsed for many years, but a way to actually access this file (other than
213        // internally), was not provided until recently.
214
215        this.pkgSummaryHTML = pkgSummaryHTML;
216
217
218        // ****************************************************************************************
219        // ****************************************************************************************
220        // DETAILS ENTRIES - Computed in Class JDHFMembers Constructor (October 2024)
221        // ****************************************************************************************
222        // ****************************************************************************************
223
224
225        // These are all ReadOnlyList's of Torello.JavaDoc.ReflHTML<? extends Declaration>
226        this.allMethodDetails       = jdhfMembers.methodsREFL;
227        this.allFieldDetails        = jdhfMembers.fieldsREFL;
228        this.allConstructorDetails  = jdhfMembers.ctorsREFL;
229        this.allECDetails           = jdhfMembers.ecREFL;
230        this.allAEDetails           = jdhfMembers.aeREFL;
231
232
233        // ****************************************************************************************
234        // ****************************************************************************************
235        // User-Requested Details-Removal:  Done in separate; class, just copy over the booleans
236        // ****************************************************************************************
237        // ****************************************************************************************
238
239
240        // These are all booleans.  These are only TRUE if (and only if) the User has requested
241        // that all Details for a particular section have, indeed, been removed.
242
243        this.methodDetailsRemoved       = removedDetails.methodDetailsRemoved;
244        this.fieldDetailsRemoved        = removedDetails.fieldDetailsRemoved;
245        this.constructorDetailsRemoved  = removedDetails.constructorDetailsRemoved;
246        this.ecDetailsRemoved           = removedDetails.ecDetailsRemoved;
247        this.aeDetailsRemoved           = removedDetails.aeDetailsRemoved;
248
249
250        // ****************************************************************************************
251        // ****************************************************************************************
252        // Compute the Hilited Source File URL.
253        // ****************************************************************************************
254        // ****************************************************************************************
255
256
257        // The class "NavButtons" will use this FileURL.  The class HiLiteSrcCodeFile will actually
258        // do that hiliting.
259        // 
260        // This should be null if the file isn't being hilited.
261
262        if (! predicates.hiLiteSourceCodeFileFilter.test(this.fullNameNoGenerics))
263            this.hiLitedSrcFileURL = null;
264
265        else this.hiLitedSrcFileURL =
266
267            "hilite-files/" +
268
269            // The Top-Level Parent-Container HiLited '.html' File is the one to use.  This code is
270            // making sure to "re-use" the already hilited parent container class!
271
272            (this.isInner
273                ? this.simpleNameWithPossibleContainers.substring
274                    (0, this.simpleNameWithPossibleContainers.indexOf('.'))
275                : this.simpleNameWithPossibleContainers) +
276            ".java.html";
277
278
279        // ****************************************************************************************
280        // ****************************************************************************************
281        // Header & Footer
282        // ****************************************************************************************
283        // ****************************************************************************************
284
285
286        // All this does is facilitating moving the constructor body to package:
287        // Torello.JDUInternal.Parse.HTML.Other
288        // 
289        // The User's API is all contained in:
290        // Torello.JavaDoc.HeaderFooterHTML
291        // 
292        // This makes it easier for the user to read & understand the stuff he needs, and much more
293        // importantly, the complicated Parse-HTML is essentially completely contained in package:
294        // 
295        // Torello.JDUInternal.Parse
296
297        this.headerFooter = new HeaderFooterHTML
298            (new Torello.JDUInternal.Parse.HTML.HeaderFooter.D1_HeaderFooterRec
299                (fileVec, this.ciet /*, jscf Passed to make debugging this record easier */));
300
301        // Now add the CSS-Tags to the header & footer, do this here...
302        if (predicates.cssTagsFilter.test(this.fullNameNoGenerics))
303            Torello.JDUInternal.Features.INSERT_CSS_TAGS.API_CSSTagsTopAndSumm
304                .addTagsToDetailBanners(fileVec);
305
306
307        // ****************************************************************************************
308        // ****************************************************************************************
309        // SUMMARIES ENTRIES
310        // ****************************************************************************************
311        // ****************************************************************************************
312
313
314        // if (! Q.YN(C.BGREEN + "Should this continue?" + C.RESET)) System.exit(1);
315
316        Torello.JDUInternal.Parse.HTML.SummaryTable.D1_AllSummaryTables allSummTables =
317
318            Torello.JDUInternal.Parse.HTML.SummaryTable.API_GetSummaryTables.build(
319                fileVec, jscf, this,
320
321
322                // NOTE: There is a "bang" / "not" / "exclamation point" because the name of this
323                //       filter is parameter is "retainRemoveDescriptions"
324                // 
325                // But the name of this filter is "SummaryRemoveFilter"
326                // I have tested this thing. 
327
328                ! predicates.summaryRemoveFilter.test(this.fullNameNoGenerics)
329            );
330
331
332        this.methodSummaryTable         = allSummTables.methodSummaryTable;
333        this.fieldSummaryTable          = allSummTables.fieldSummaryTable;
334        this.constructorSummaryTable    = allSummTables.constructorSummaryTable;
335        this.ecSummaryTable             = allSummTables.ecSummaryTable;
336        this.raeSummaryTable            = allSummTables.raeSummaryTable;
337        this.oaeSummaryTable            = allSummTables.oaeSummaryTable;
338        this.ntSummaryTable             = allSummTables.ntSummaryTable;
339
340        this.allNonNullSummaryTables = allSummTables.allNonNullSummaryTables;
341    }
342
343
344    // ********************************************************************************************
345    // ********************************************************************************************
346    // END CONSTRUCTOR !!!
347    // ********************************************************************************************
348    // ********************************************************************************************
349
350
351    // ********************************************************************************************
352    // ********************************************************************************************
353    // Primary (Final) Fields
354    // ********************************************************************************************
355    // ********************************************************************************************
356
357
358    /**
359     * This provides the relative path-{@code String} from {@code 'this'} Java Doc generated
360     * {@code '.html'} File to the root Java Doc Directory.
361     */
362    public final RelativePathStr dotDots;
363
364    /**
365     * Directory-Name of the Java-Doc Sub-Directory that contains this Java-Doc
366     * {@code '.html'}-File.  This sub-directory should just be the name of the Root Java-Doc
367     * Directory, with this class' Full Package-Name appended to it.
368     * 
369     * <BR /><BR />If the JPMS (Java Platform Module System) has been used by a User-Project
370     * that contains multiple Java-Modules, then this directory shall also be pre-fixed with the
371     * relevant module containing this directory.
372     */
373    public final String javaDocPackageDirName;
374
375    /**
376     * Directory-Name of the Java-Doc Sub-Directory that contains the Hi-Lited Source-Code
377     * {@code '.html'}-Files for the Java-Classes which are included in the Java-Package to which
378     * this particular Java-Class belongs.
379     * 
380     * <BR /><BR />Unless instructed otherwise, the JDU spends effort to provide Syntax-HiLited
381     * {@code '.html'}-Files for each and every one of the Classes in a User's Java-Project.  These
382     * files are each saved in the Hi-Lite Directory that is germaine / relevant for the given
383     * Java-Package to which the given Java-Class belongs.
384     */
385    public final String javaDocPkgHiLitedSrcCodeDirName;
386
387    /**
388     * Directory-Name of the Java-Doc Sub-Directory that 
389     */
390
391    // The HTML Vector for a Java Doc web-page
392    private final Vector<HTMLNode> fileVec;
393
394    // This is where the 'updated-vector' is saved after the changes have been recommitted.
395    private Vector<HTMLNode> updatedFileVec = null;
396
397    /**
398     * The HTML that occurs directly above the Summary-Tables is the header.  The HTML that is
399     * located below the Detail-Entries is the footer.
400     */
401    public final HeaderFooterHTML headerFooter;
402
403    /**
404     * This is the File-{@code URL} to use if a need to link to the corresponding
405     * {@code "/src-html/"} file is necessary.
406     * 
407     * <BR /><BR />This is a <B STYLE='color: red;'>relative</B>-URL that contains the requisite
408     * number of 'dot-dots' to reach the file from the location where this Java Doc HTML File is
409     * located.
410     */
411    public final String srcAsHTMLFileURL;
412
413    /**
414     * This is the File-{@code URL} to use if a need to link to the corresponding
415     * {@code "/hilite-files/"} file is necessary.
416     * 
417     * <BR /><BR />This is a <B STYLE='color: red;'>relative</B>-URL that is relative to the file
418     * from the location where this Java Doc HTML File is located.  Specifically, this
419     * {@code String} begins with the text {@code "/hilite-files/"}, followed by the type-name,
420     * and ending with the extension {@code ".java.html"}
421     */
422    public final String hiLitedSrcFileURL;
423
424    /**
425     * This is a reference to the parsed, {@code 'package-summary.html'} File for the Project's
426     * 'Java-Package' to which this class belongs.
427     */
428    public final PackageSummaryHTML pkgSummaryHTML;
429
430
431    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
432    // The HTML Details as Vector<ReflHTML<?>>
433    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
434
435    /**
436     * This is the list of all constructors in the "Constructor Details", stored as
437     * Reflection-HTML instances
438     */
439    public final ReadOnlyList<ReflHTML<Constructor>> allConstructorDetails;
440
441    /**
442     * This is the list of all fields in the "Field Details", stored as Reflection-HTML
443     * instances
444     */
445    public final ReadOnlyList<ReflHTML<Field>> allFieldDetails;
446
447    /**
448     * This is the list of all methods in the "Method Details", stored as Reflection-HTML
449     * instances
450     */
451    public final ReadOnlyList<ReflHTML<Method>> allMethodDetails;
452
453    /**
454     * This is the list of all constants in the "Enumerated Constant Details", stored as
455     * Reflection-HTML instances
456     */
457    public final ReadOnlyList<ReflHTML<EnumConstant>> allECDetails;
458
459    /**
460     * This is the list of all elements in the "Annotation Element Details", stored as
461     * Reflection-HTML instances
462     */
463    public final ReadOnlyList<ReflHTML<AnnotationElem>> allAEDetails;
464
465
466    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
467    // The HTML Summaries as SummaryTableHTML
468    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
469
470    /** The HTML for a Method Summary */
471    public final SummaryTableHTML<Method> methodSummaryTable;
472
473    /** The HTML for a Field Summary Table */
474    public final SummaryTableHTML<Field> fieldSummaryTable;
475
476    /** The HTML for a Constructor Summary Table */
477    public final SummaryTableHTML<Constructor> constructorSummaryTable;
478
479    /** The HTML for an Enum-Constant Summary Table */
480    public final SummaryTableHTML<EnumConstant> ecSummaryTable;
481
482    /** The HTML for an Optional Annotation Element Summary Table */
483    public final SummaryTableHTML<AnnotationElem> oaeSummaryTable;
484
485    /** The HTML for a Required Annotation Element Summary Table */
486    public final SummaryTableHTML<AnnotationElem> raeSummaryTable;
487
488    /** The HTML for a Nested-Class (Inner-Class) Summary Table */
489    public final SummaryTableHTML<NestedType> ntSummaryTable;
490
491    /** all non-null {@link SummaryTableHTML} instances */
492    @SuppressWarnings("rawtypes")
493    public final ReadOnlyList<SummaryTableHTML> allNonNullSummaryTables;
494
495
496    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
497    // Booleans for remembering whether a Details Section was removed completely
498    // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
499
500    /** Identifies if this Java Doc HTML Page has had it's Method Details Removed */
501    public final boolean methodDetailsRemoved;
502
503    /** Identifies if this Java Doc HTML Page has had it's Constructor Details Removed */
504    public final boolean constructorDetailsRemoved;
505
506    /** Identifies if this Java Doc HTML Page has had it's Field Details Removed */
507    public final boolean fieldDetailsRemoved;
508
509    /** Identifies if this Java Doc HTML Page has had it's Enumeration Constant Details Removed */
510    public final boolean ecDetailsRemoved;
511
512    /** Identifies if this Java Doc HTML Page has had it's Annotation-Element Details Removed */
513    public final boolean aeDetailsRemoved;
514
515
516    // ********************************************************************************************
517    // ********************************************************************************************
518    // Find Methods: Methods that accept a String / int
519    // ********************************************************************************************
520    // ********************************************************************************************
521
522
523    /**
524     * Returns a list as a {@code java.util.stream.Stream} of all Reflected-HTML-{@link Method}
525     * instances that have a name equal to {@code 'methodName'}.
526     * 
527     * @param methodName The name of the method being searched for.
528     * 
529     * @return A Java Stream containing all {@link Method}-{@link ReflHTML} instances that match
530     * the provided {@code 'methodName'} criteria.
531     */
532    public Stream<ReflHTML<Method>> findMethodHTML(String methodName)
533    {
534        return allMethodDetails
535            .stream()
536            .filter((ReflHTML<Method> refl) -> refl.entity.name.equals(methodName));
537    }
538
539    /**
540     * Returns a list as a {@code java.util.stream.Stream} of all Reflected-HTML-{@link Method}
541     * instances that have the specified number of parameters.
542     * 
543     * @param numParameters The number of parameters contained by the {@link Method} being searched
544     * for.
545     * 
546     * @return A Java Stream containing all {@link Method}-{@link ReflHTML} instances that match
547     * the provided {@code 'numParameters'} criteria.
548     */
549    public Stream<ReflHTML<Method>> findMethodHTML(int numParameters)
550    {
551        return allMethodDetails
552            .stream()
553            .filter((ReflHTML<Method> refl) -> refl.entity.numParameters() == numParameters);
554    }
555    
556    /**
557     * Returns a list as a {@code java.util.stream.Stream} of all
558     * Reflected-HTML-{@link Constructor} instances that have the specified number of parameters.
559     * 
560     * @param numParameters The number of parameters contained by the {@link Constructor} being
561     * searched for.
562     * 
563     * @return A Java Stream containing all {@link Constructor}-{@link ReflHTML} instances that
564     * match the provided {@code 'numParameters'} specifier.
565     */
566    public Stream<ReflHTML<Constructor>> findConstructorHTML(int numParameters)
567    {
568        return allConstructorDetails
569            .stream()
570            .filter((ReflHTML<Constructor> refl) -> refl.entity.numParameters() == numParameters);
571    }
572
573    /**
574     * The Reflected-HTML Field having the specified name, or null if no such field exists
575     * 
576     * @param fieldName The name of the field being searched
577     * 
578     * @return The {@code ReflHTML<Field>} instance, from {@code 'this'} Java Doc Page, whose name
579     * matches {@code fieldName}, or null it wasn't found.
580     */
581    public ReflHTML<Field> findFieldHTML(String fieldName)
582    {
583        for (ReflHTML<Field> f : allFieldDetails) if (f.entity.name.equals(fieldName)) return f;
584        return null;
585    }
586
587    /**
588     * The Reflected-HTML Enum-Constant having the specified name, or null if no such constant
589     * exists
590     * 
591     * @param enumConstantName The name of the constant being searched
592     * 
593     * @return The {@code ReflHTML<EnumConstant>} instance, from {@code 'this'} Java Doc Page,
594     * whose name matches {@code enumConstantName}, or null it wasn't found.
595     * 
596     * @throws UpgradeException Only a Java {@link CIET}/Type {@code 'enum'} is allowed to declare
597     * Enum-Constants, and therefore this exception throws <I>when this method is invoked on a
598     * Java Doc HTML File that doesn't represent an {@code enum}.</I>
599     */
600    public ReflHTML<EnumConstant> findECHTML(String enumConstantName)
601    {
602        if (this.ciet != CIET.ENUM) throw new UpgradeException(
603            "Finding Enumeration-Constants is only possible with HTML Files for Java 'enum' " +
604            "Type's.  This file is of type [" + this.ciet.toString() + "]"
605        );
606
607        for (ReflHTML<EnumConstant> ec : allECDetails)
608            if (ec.entity.name.equals(enumConstantName))
609                return ec;
610
611        return null;
612    }
613
614    /**
615     * The Reflected-HTML Annotation-Element having the specified name, or null if no such element
616     * exists
617     * 
618     * @param annotationElemName The name of the constant being searched
619     * 
620     * @return The {@code ReflHTML<EnumConstant>} instance, from {@code 'this'} Java Doc Page,
621     * whose name matches {@code annotationElemName}, or null it wasn't found.
622     * 
623     * @throws UpgradeException Only a Java {@link CIET}/Type {@code '@interface'} is allowed to
624     * declare Annotation-Elements, and therefore this exception throws <I>when this method is
625     * invoked on a Java Doc HTML File that doesn't represent an annotation.</I>
626     */
627    public ReflHTML<AnnotationElem> findAEHTML(String annotationElemName)
628    {
629        if (this.ciet != CIET.ANNOTATION) throw new UpgradeException(
630            "Finding Annotation-Elements is only possible with HTML Files for Java '@interface' " +
631            "(Annotation) Type's.  This file is of type [" + this.ciet.toString() + "]"
632        );
633
634        for (ReflHTML<AnnotationElem> ae : allAEDetails)
635            if (ae.entity.name.equals(annotationElemName))
636                return ae;
637
638        return null;
639    }
640
641
642    // ********************************************************************************************
643    // ********************************************************************************************
644    // Find Refl<HTML> Entities
645    // ********************************************************************************************
646    // ********************************************************************************************
647
648
649    /**
650     * Finds a matching {@link ReflHTML} instance whose internal {@code 'entity'} field has an
651     * ID number that matches input-parameter {@code 'declarationID'}.
652     * 
653     * @param declarationID Whenever any instance of a sub-class of {@link Declaration} is created,
654     * it is given a unique id that uniquely identifies it across the entire life-cycle of the JVM
655     * that is currently running.
656     * 
657     * @param c This must be a Java {@code java.lang.Class} from one of the following:
658     * {@link Constructor}, {@link Method}, {@link Field}, {@link EnumConstant} or
659     * {@link AnnotationElem}.
660     * 
661     * <BR /><BR /><B>NOTE:</B> This class is very easily obtained by simple using the
662     * {@code 'enum'} field {@link Entity#upgraderReflectionClass}.  To pass the appropriate class
663     * for a method, simply pass {@code Entity.METHOD.upgraderReflectionClass} to this parameter.
664     * 
665     * <BR /><BR /><B>ALSO:</B> Even more easy (if you know the member/entity type), you can
666     * hard-code / hand-type the class yourself - for instance {@code Method.class}.  If you were
667     * searching for a {@code ReflHTML<Field>}, you would pass {@code Field.class} to this
668     * parameter.
669     * 
670     * @return The {@link ReflHTML} instance whose HTML describes the Method, Field, or Constructor
671     * etc... whose actual Reflected-class has an ID that matches {@code 'declarationID'}.  Note
672     * that the second parameter {@code 'c'} is primarily used to "speed up" the search process.
673     * 
674     * <DIV CLASS=EXAMPLE>{@code
675     * // Note the 'Method' being passed is Torello.JavaDoc.Method (not java.lang.reflect.Method)
676     * ReflHTML<Method> refl = jdhf.findEntity(someEntityID, Method.class);
677     * }</DIV>
678     * 
679     * @throws IllegalArgumentException If the value passed to {@code 'declarationID'} is negative.
680     */
681    @SuppressWarnings("unchecked") // Seems like the Java-Compiler is failing on this one.
682    public <ENTITY extends Declaration> ReflHTML<ENTITY> findReflHTML
683        (int declarationID, Class<ENTITY> c)
684    {
685        if (declarationID < 0) throw new IllegalArgumentException
686            ("You have passed a negative declarationID: " + declarationID);
687
688        if (Constructor.class.equals(c)) // This is **CLEARLY** not an unchecked cast!
689            for (ReflHTML<Constructor> r : allConstructorDetails)
690                { if (r.entity.id == declarationID) return (ReflHTML<ENTITY>) r; }
691
692        else if (Method.class.equals(c))
693            for (ReflHTML<Method> r : allMethodDetails)
694                { if (r.entity.id == declarationID) return (ReflHTML<ENTITY>) r; }
695
696        else if (Field.class.equals(c))
697            for (ReflHTML<Field> r : allFieldDetails)
698                { if (r.entity.id == declarationID) return (ReflHTML<ENTITY>) r; }
699
700        else if (EnumConstant.class.equals(c))
701            for (ReflHTML<EnumConstant> r : allECDetails)
702                { if (r.entity.id == declarationID) return (ReflHTML<ENTITY>) r; }
703
704        else if (AnnotationElem.class.equals(c))
705            for (ReflHTML<AnnotationElem> r : allAEDetails)
706                { if (r.entity.id == declarationID) return (ReflHTML<ENTITY>) r; }
707
708        return null;
709    }
710
711
712    // ********************************************************************************************
713    // ********************************************************************************************
714    // Links-Checker Access-Method
715    // ********************************************************************************************
716    // ********************************************************************************************
717
718
719    // StrReplace Helper String[]-Arrays
720    private static final String[] MATCH_STRS    = { "%3C", "%3E", "%5B", "%5D" };
721    private static final String[] REPLACE_STRS  = { "&lt;" , "&gt;", "[", "]" };
722
723
724    // This Retrieves all CSS-ID's and all <A HREF=...> (the HREF part) from every HTMLNode in
725    // this set, and checks returns them as two TreeSet's.
726    //
727    // Ret2.a: All CSS-ID's found on the page - *NOTE*, this is the *POST-PROCESSED* page
728    // Ret2.b: All HREF Attributes inside of every <A>/Anchor on this page
729    //
730    // This is called by the LinksChecker class
731
732    public Ret2<TreeSet<String>, TreeSet<String>> allIDsAndHREFs()
733    {
734        TreeSet<String> allIDs      = new TreeSet<>();
735        TreeSet<String> allHREFs    = new TreeSet<>();
736        TagNode         tn          = null;
737
738        for (HTMLNode n : updatedFileVec)
739
740            if ((tn = n.openTagPWA()) != null)
741            {
742                String id   = tn.AV("id");
743                String href = tn.AV("href");
744
745                if (id != null) allIDs.add(id);
746
747                if (href != null)
748                {
749                    if (href.equals("#top")) continue;
750
751                    if (StrCmpr.startsWithXOR(
752                            href, "http://", "https://", "/",
753                            "javascript:"
754                    ))
755                        continue;
756
757                    allHREFs.add(StrReplace.r(href, MATCH_STRS, REPLACE_STRS));
758                }
759            }
760
761        return new Ret2<>(allIDs, allHREFs);
762    }
763
764
765    // ********************************************************************************************
766    // ********************************************************************************************
767    // Internal Utility Methods
768    // ********************************************************************************************
769    // ********************************************************************************************
770
771
772    // Checks the validity of the HTML on a Java Doc Web-page
773    // @return The Balance Report, generated by class {@link Balance}.  The ;identifies any
774    // potential unmatched HTML tags.
775    //
776    // EXPORT_PORTAL METHOD
777    // This method is used by Package HTMLProcessors, and doesn't need to be exported to the user.
778
779    Hashtable<String, Integer> checkValidity()
780    {
781        if (updatedFileVec == null) Messager.assertFailGeneralPurpose(
782            "For some odd reason, the updatedFileVec has not been set",
783            null,
784            WHERE_AM_I
785        );
786
787        return Balance.checkNonZero(Balance.check(updatedFileVec));
788    }
789
790    // Saves the Vectorized-HTML back to the file on disk from whence it was loaded.
791    // @throws IOException This propogates any / all exceptions which might be thrown when
792    // trying to write the file to the file-system.
793    //
794    // EXPORT_PORTAL METHOD
795    // This method is used by Package HTMLProcessors, and doesn't need to be exported to the user.
796
797    void commitFileToDisk() throws java.io.IOException
798    {
799        if (updatedFileVec == null) Messager.assertFailGeneralPurpose(
800            "For some odd reason, the updatedFileVec has not been set",
801            null,
802            WHERE_AM_I
803        );
804
805        FileRW.writeFile(Util.pageToString(this.updatedFileVec), this.fileName);
806    }
807
808
809    // Collates and inserts any changes made to the Sub-Sections back into the main page
810    //
811    // NO MESSAGER, NO THROWS, THE DATA IS ALL PRIVATE
812    //
813    // EXPORT_PORTAL METHOD
814    // This method is used by Package HTMLProcessors, and doesn't need to be exported to the user.
815
816    @SuppressWarnings("unchecked") // The Vector<Replaceable> cast
817    void commitChanges()
818    {
819        final TreeSet<Replaceable> replaceables = new TreeSet<>();
820
821        allNonNullSummaryTables.forEach(
822            (@SuppressWarnings("rawtypes") SummaryTableHTML sTable) ->
823                replaceables.addAll((Vector<Replaceable>) sTable.allReplaceables())
824        );
825
826        for (ReflHTML<Method> r : allMethodDetails)
827            replaceables.addAll(r.allReplaceables());
828
829        for (ReflHTML<Field> r : allFieldDetails)
830            replaceables.addAll(r.allReplaceables());
831
832        for (ReflHTML<Constructor> r : allConstructorDetails)
833            replaceables.addAll(r.allReplaceables());
834
835        for (ReflHTML<AnnotationElem> r : allAEDetails)
836            replaceables.addAll(r.allReplaceables());
837
838        for (ReflHTML<EnumConstant> r : allECDetails)
839            replaceables.addAll(r.allReplaceables());
840
841        replaceables.addAll(headerFooter.allReplaceables());
842
843
844        // This is one of those "assert" moments.  This exception is not EVER supposed to throw, 
845        // however, if it does, it is likely because of some grave error that was made inside of
846        // this class Constructor.  When this happens, it is better to print the file name that has
847        // caused this exception throw, quickly.
848        // 
849        // Generally UNHANDLED EXCEPTIONS are supposed to signify a more serious design flaw, so
850        // it is better (IMHO) to just let them bubble up to the top, and FIX THE BUG ASAP.
851        // 
852        // If this throws, make sure the print the file-name, and hope it is easy to figure out
853        // what just happened.
854
855        try 
856            { this.updatedFileVec = Replacement.run(fileVec, replaceables, false).a; }
857
858        catch (Torello.HTML.ReplaceablesOverlappingException e)
859        {
860            System.out.println(
861                '\n' +
862                "Currently Processing - this.fileName:\n" +
863                "    [" + BYELLOW + this.fileName + RESET + "]\n" +
864                "ParsedFile.quickSummary():\n" +
865                StrIndent.indent(this.quickSummary(), 4)
866            );
867
868            throw e;
869        }
870    }
871
872
873    // ********************************************************************************************
874    // ********************************************************************************************
875    // THE NEW-THING: Garbage-Collector Helper?
876    // ********************************************************************************************
877    // ********************************************************************************************
878    //
879    // Does this help?  Is this "good" for the Garbage-Collect?  Is this going to speed it up,
880    // or slow it down?  This is just a "C-Styled" FREE or DESTORY method...
881    // It isn't publicly visible anyway...
882
883    void clear()
884    {
885        headerFooter.clear();
886
887        // private final Vector<SummaryTableHTML> allNonNullSummaryTables;
888        for (@SuppressWarnings("rawtypes") SummaryTableHTML st : allNonNullSummaryTables)
889            st.clear();
890    }
891
892
893}