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