001package Torello.JavaDoc;
002
003import Torello.HTML.HTMLNode;
004import Torello.HTML.SubSection;
005import Torello.HTML.Replaceable;
006import Torello.HTML.Util;
007
008import Torello.Java.StrPrint;
009import static Torello.Java.C.*;
010
011import Torello.JDUInternal.Messager.Messager;
012import Torello.JDUInternal.Messager.Where.JDUUserAPI;
013import Torello.JDUInternal.Messager.Where.Where_Am_I;
014
015import Torello.JDUInternal.Parse.HTML.HeaderFooter.D1_HeaderFooterRec;
016
017import java.util.Vector;
018
019/**
020 * Encapsulates the HTML placed both the top and the bottom of a JavaDoc Web-Page, including the
021 * Navigation-Bar HTML, the Package-Name, Type-Signature and other Banner-Labesl.
022 * 
023 * <EMBED CLASS='external-html' DATA-FILE-ID=PROG_MOD_HTML>
024 * <EMBED CLASS='external-html' DATA-FILE-ID=HEADER_FOOTER>
025 */
026@JDHeaderBackgroundImg(EmbedTagFileID="REFLECTION_HTML_CLASS")
027public class HeaderFooterHTML
028{
029    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
030    protected static final long serialVersionUID = 1;
031
032    // When the Messager Reports its errors, this class passes this reference to the Messager
033    // to facilitate the printing of that information (What class encountered an error or warning
034    // that needs to be printed by the Messager).
035
036    private static final Where_Am_I WHERE_AM_I = JDUUserAPI.HeaderFooterHTML;
037
038
039    // ********************************************************************************************
040    // ********************************************************************************************
041    // Constructor - Fields are computed in package: Torello.JDUInternal.Parse.HTML.Other
042    // ********************************************************************************************
043    // ********************************************************************************************
044
045
046    // This constructor is invoked by JavaDocHTMLFile
047    // The work for this constructor has since been moved into a class inside package:
048    // 
049    // Torello.JDUInternal.Parse.HTML.Other
050    // 
051    // Keeping HTML-Parsing code in a separate, internal, package allows me to "localize" the
052    // complicated parsing code into a single location - far away from the end user.  This code
053    // is dependent upon which of the Java-Doc Versions is being used.
054    // 
055    // Since October of 2024, HTML-Parsing Code has been moved to a single, JDUInternal,
056    // suite of directories that are much easier to manage.  This constructor, for instance, just
057    // block copies the fields from one of those JDUInternal Data-Record Classes.
058
059    HeaderFooterHTML
060        (final Torello.JDUInternal.Parse.HTML.HeaderFooter.D1_HeaderFooterRec internalDataRec)
061    {
062        this.head               = internalDataRec.head;
063        this.topNavBar          = internalDataRec.topNavBar;
064        this.packageInfo        = internalDataRec.packageInfo;
065        this.title              = internalDataRec.title;
066        this.inheritance        = internalDataRec.inheritance;
067        this.defListsAboveSig   = internalDataRec.defListsAboveSig;
068        this.signature          = internalDataRec.signature;
069        this.description        = internalDataRec.description;
070        this.defListsBelowDesc  = internalDataRec.defListsBelowDesc;
071        this.bottomNavBar       = internalDataRec.bottomNavBar;
072    }
073
074
075    // ********************************************************************************************
076    // ********************************************************************************************
077    // Private Replaceable-HTML Fields
078    // ********************************************************************************************
079    // ********************************************************************************************
080
081
082    private final SubSection head;
083    private final SubSection topNavBar;
084    private final SubSection packageInfo;
085    private final SubSection title;
086    private final SubSection inheritance;
087    private final Replaceable defListsAboveSig;
088    private final SubSection signature;
089    private final Replaceable description;
090    private final Replaceable defListsBelowDesc;
091    private final SubSection bottomNavBar;
092
093
094    // ********************************************************************************************
095    // ********************************************************************************************
096    // Public Accessor Methods
097    // ********************************************************************************************
098    // ********************************************************************************************
099
100
101    /**
102     * Retrieve the HTML {@code <HEAD>}.
103     * 
104     * @return An HTML-{@code Vector} containing all elements between the opening-{@code <HEAD>}
105     * and closing-{@code </HEAD>} tags.  This method shall never return null, nor will it return
106     * an empty-{@code Vector}
107     */
108    public Vector<HTMLNode> head()
109    { return this.head.html; }
110
111    /**
112     * Retrieve the Navigation-Bar HTML at the top of a Java Doc Page.
113     * 
114     * @return An HTML-{@code Vector} containing all elements in the Top Navigation-Bar.  If there
115     * is no Navigation-Bar at the top, <I>then this method shall return null.</I>
116     */
117    public Vector<HTMLNode> topNavBar()
118    { return (this.topNavBar != null) ? this.topNavBar.html : null; }
119
120    /**
121     * Retrieve the Type's Package-Information, as an HTML-{@code Vector}.
122     * 
123     * @return An HTML-{@code Vector} containing all elements in the package label at the top of a
124     * Java-Doc Page.  This method shall never return null, nor will it return an
125     * empty-{@code Vector}
126     */
127    public Vector<HTMLNode> packageInfo()
128    { return this.packageInfo.html; }
129
130    /**
131     * Retrieve the title of the page, as an HTML-{@code Vector}
132     * 
133     * @return An HTML-{@code Vector} containing all elements in the title.  This method shall
134     * never return null, nor will it return an empty-{@code Vector}
135     */
136    public Vector<HTMLNode> title()
137    { return this.title.html; }
138
139    /**
140     * Get the HTML for the Type's inheritance {@code <UL>'s}-List.
141     * 
142     * @return An HTML-{@code Vector} containing all elements in the Type Inheritance List.  If
143     * the Type is an {@code Interface} that does not have any inheriting-types, or an
144     * {@code @Annotation}, <I>then this method shall return null.</I>
145     */
146    public Vector<HTMLNode> inheritance()
147    { return (this.inheritance != null) ? this.inheritance.html : null; }
148
149    /**
150     * Get any Definition-Lists that occur above the Type's Signature, which is at the top.
151     * 
152     * @return An HTML-{@code Vector} containing all elements in the definition {@code <DL>} lists
153     * below the Yellow-Box Description.  This method shall <I>never return null</I>.  If there are
154     * no such lists, then an empty HTML-{@code Vector} is returned.
155     * 
156     * <BR /><BR />It is perfectly acceptable to add HTML-Content to an empty-list.  Here, it would
157     * place such content directly above the Type-Signature {@code <PRE>} box that is located at
158     * the top of the page.
159     */
160    public Vector<HTMLNode> defListsAboveSig()
161    { return this.defListsAboveSig.currentNodes(); }
162
163    /**
164     * Retrieve the signature HTML from the top of the page.
165     * 
166     * @return An HTML-{@code Vector} containing all elements in the Type-Signature {@code <PRE>}
167     * Element.  This is located at the top of the class, and is box with a shadow border.  This
168     * method shall never return null, nor will it return an empty-{@code Vector}
169     */
170    public Vector<HTMLNode> signature()
171    { return this.signature.html; }
172
173    /**
174     * Retrieve the description from the top of the page, as HTML.
175     * 
176     * @return An HTML-{@code Vector} containing all elements in the description, which is a
177     * Yellow box at the top of the page.  This method shall <I>never return null</I>.  If there
178     * is no such HTML divider, then an empty HTML-{@code Vector} is returned.
179     * 
180     * <BR /><BR />It is perfectly acceptable to add HTML-Content to an empty-list.  Here, it would
181     * place such content directly below the Yellow-Description box that is located at the top of
182     * the page.
183     */
184    public Vector<HTMLNode> description()
185    { return this.description.currentNodes(); }
186
187    /**
188     * Get any Definition-Lists that occur below the Yellow-Box Signature.
189     * 
190     * @return An HTML-{@code Vector} containing all elements in the definition {@code <DL>} lists
191     * below the Yellow-Box Description.  This method shall <I>never return null</I>.  If there are
192     * no such lists, then an empty HTML-{@code Vector} is returned.
193     * 
194     * <BR /><BR />It is perfectly acceptable to add HTML-Content to an empty-list.  Here, it would
195     * place such content directly below the Yellow-Description box that is located at the top of
196     * the page.
197     */
198    public Vector<HTMLNode> defListsBelowDesc()
199    { return this.defListsBelowDesc.currentNodes(); }
200
201    /**
202     * Retrieve the Navigation-Bar HTML at the bottom of a Java Doc Page.
203     * 
204     * @return An HTML-{@code Vector} containing all elements in the Bottom Navigation-Bar.  If
205     * there is no Navigation-Bar at the top, <I>then this method shall return null.</I>
206     */
207    public Vector<HTMLNode> bottomNavBar()
208    { return (this.bottomNavBar != null) ? this.bottomNavBar.html : null; }
209
210
211    // ********************************************************************************************
212    // ********************************************************************************************
213    // DEBUG-PRINTING
214    // ********************************************************************************************
215    // ********************************************************************************************
216
217
218    private static final String STARS =
219        BYELLOW + "\n*****************************************\n" + RESET;
220
221    /**
222     * Prints an abbreviated-version of the contents of this instance, to a user-provided
223     * {@code Appendable}.  If the HTML requires more than four lines of text, only the first four
224     * lines are printed.
225     * 
226     * @param a This may be any Java Appendable.  If an {@code IOException} is thrown while writing
227     * to this {@code Appendable}, it will be caught an wrapped in an
228     * {@code IllegalArgumentException}, with the {@code IOException} set as the {@code cause}.
229     * 
230     * @throws IllegalArgumentException If {@code 'a'} throws an {@code IOException}
231     * @see StrPrint#firstNLines(String, int)
232     * @see Util#pageToString(Vector)
233     */
234    public void debugPrint(Appendable a)
235    {
236        try 
237        {
238            a.append(
239                STARS + BCYAN + "this.head" + RESET + ':' + STARS +
240                StrPrint.firstNLines(Util.pageToString(head.html), 4) +
241                '\n'
242            );
243
244            if (topNavBar != null) a.append(
245                STARS + BCYAN + "this.topNavBar" + RESET + ':' + STARS +
246                StrPrint.firstNLines(Util.pageToString(topNavBar.html), 4) +
247                '\n'
248            );
249            else a.append(STARS + BRED + "this.topNavBar is null" + RESET + STARS);
250
251            a.append(
252                STARS + BCYAN + "this.packageInfo" + RESET + ':' + STARS +
253                StrPrint.firstNLines(Util.pageToString(packageInfo.html), 4) +
254                '\n'
255            );
256
257            a.append(
258                STARS + BCYAN + "this.title" + RESET + ':' + STARS +
259                StrPrint.firstNLines(Util.pageToString(title.html), 4) +
260                '\n'
261            );
262
263            if (inheritance != null) a.append(
264                STARS + BCYAN + "this.inheritance" + RESET + ':' + STARS +
265                StrPrint.firstNLines(Util.pageToString(inheritance.html), 4) +
266                '\n'
267            );
268            else a.append(STARS + BRED + "this.inheritance is null" + RESET + STARS);
269
270            if (defListsAboveSig.currentSize() > 0) a.append(
271                STARS + BCYAN + "this.defListsAboveSig" + RESET + ':' + STARS +
272                StrPrint.firstNLines(Util.pageToString(defListsAboveSig.currentNodes()), 4) +
273                '\n'
274            );
275            else a.append(STARS + BRED + "this.defListsAboveSig is empty" + RESET + STARS);
276
277            a.append(
278                STARS + BCYAN + "this.signature" + RESET + ':' + STARS +
279                StrPrint.firstNLines(Util.pageToString(signature.html), 4) +
280                '\n'
281            );
282
283            if (description.currentSize() > 0) a.append(
284                STARS + BCYAN + "this.description" + RESET + ':' + STARS +
285                StrPrint.firstNLines(Util.pageToString(description.currentNodes()), 4) +
286                '\n'
287            );
288            else a.append(STARS + BRED + "this.description is empty" + RESET + STARS);
289
290            if (defListsBelowDesc.currentSize() > 0) a.append(
291                STARS + BCYAN + "this.defListsBelowDesc" + RESET + ':' + STARS +
292                StrPrint.firstNLines(Util.pageToString(defListsBelowDesc.currentNodes()), 4) +
293                '\n'
294            );
295            else a.append(STARS + BRED + "this.defListsBelowDesc is empty" + RESET + STARS);
296
297            if (bottomNavBar != null) a.append(
298                STARS + BCYAN + "this.bottomNavBar" + RESET + ':' + STARS +
299                StrPrint.firstNLines(Util.pageToString(bottomNavBar.html), 4) +
300                '\n'
301            );
302            else a.append(STARS + BRED + "this.bottomNavBar is null" + RESET + STARS);
303        }
304        catch (java.io.IOException ioe)
305        {
306            throw new IllegalArgumentException(
307                "Your Appendable instance has caused an IOException to throw.  See getCause() " +
308                "for details", ioe
309            );
310        }
311    }
312
313
314    // ********************************************************************************************
315    // ********************************************************************************************
316    // At the end of the processing of a JavaDoc Web-Page, this gets all the changes that were made
317    // ********************************************************************************************
318    // ********************************************************************************************
319
320
321    Vector<Replaceable> allReplaceables()
322    {
323        Vector<Replaceable> ret = new Vector<>();
324
325        ret.add(head);              // Required, always present
326
327        if (topNavBar != null) ret.add(topNavBar);
328
329        ret.add(packageInfo);       // Required, always present
330        ret.add(title);             // Required, always present
331
332        if (inheritance != null) ret.add(inheritance);
333
334        ret.add(defListsAboveSig);  // A "Replaceable" is never null.
335        ret.add(signature);         // Required, always present
336        ret.add(description);       // A "Replaceable" is never null.
337        ret.add(defListsBelowDesc); // A "Replaceable" is never null.
338
339        if (bottomNavBar != null) ret.add(bottomNavBar);
340
341        return ret;
342    }
343
344
345    // ********************************************************************************************
346    // ********************************************************************************************
347    // THE NEW-THING: Garbage-Collector Helper?
348    // ********************************************************************************************
349    // ********************************************************************************************
350    // 
351    // Does this help?  Is this "good" for the Garbage-Collect?  Is this going to speed it up,
352    // or slow it down?  This is just a "C-Styled" FREE or DESTORY method...
353    // It isn't publicly visible anyway...
354
355    void clear()
356    {
357        // private final SubSection head;
358        // Guaranteed: Never Null, or Messager.assertFailHTML
359
360        head.html.clear();
361        head.html = null;
362
363        // private final SubSection topNavBar;
364        // Maybe they don't have one
365
366        if (topNavBar != null)
367        {
368            topNavBar.html.clear();
369            topNavBar.html = null;
370        }
371
372        // private final SubSection packageInfo;
373        // Guaranteed: Never Null, or Messager.assertFailHTML
374        // NOTE: This may one day change...
375
376        if (packageInfo != null)
377        {
378            packageInfo.html.clear();
379            packageInfo.html = null;
380        }
381
382        // private final SubSection title;
383        // Guaranteed: Never Null, or Messager.assertFailHTML
384
385        title.html.clear();
386        title.html = null;
387
388        // private final SubSection inheritance;
389        // Maybe they don't have one
390
391        if (inheritance != null)
392        {
393            inheritance.html.clear();
394            inheritance.html = null;
395        }
396
397        // private final Replaceable defListsAboveSig;
398        // THIS IS A REPLACEABLE: It won't be null, but it may be empty
399
400        if (SubSection.class.isAssignableFrom(defListsAboveSig.getClass()))
401        {
402            ((SubSection) defListsAboveSig).html.clear();
403            ((SubSection) defListsAboveSig).html = null;
404        }
405        else if (defListsAboveSig.currentSize() > 0) defListsAboveSig.clearHTML();
406
407        // private final SubSection signature;
408        // Guaranteed: Never Null, or Messager.assertFailHTML
409
410        signature.html.clear();
411        signature.html = null;
412
413        // private final Replaceable description;
414        // THIS IS A REPLACEABLE: It won't be null, but it may be empty
415
416        if (SubSection.class.isAssignableFrom(description.getClass()))
417        {
418            ((SubSection) description).html.clear();
419            ((SubSection) description).html = null;
420        }
421        else if (description.currentSize() > 0) description.clearHTML();
422
423        // private final Replaceable defListsBelowDesc;
424        // THIS IS A REPLACEABLE: It won't be null, but it may be empty
425
426        if (SubSection.class.isAssignableFrom(defListsBelowDesc.getClass()))
427        {
428            ((SubSection) defListsBelowDesc).html.clear();
429            ((SubSection) defListsBelowDesc).html = null;
430        }
431        else if (defListsBelowDesc.currentSize() > 0) defListsBelowDesc.clearHTML();
432
433        // private final SubSection bottomNavBar;
434        // Maybe they don't have one
435
436        if (bottomNavBar != null)
437        {
438            bottomNavBar.html.clear();
439            bottomNavBar.html = null;
440        }
441    }
442}