001package Torello.HTML;
002
003import java.util.*;
004import java.util.function.BiConsumer;
005import java.util.concurrent.locks.*;
006
007import static Torello.Java.C.*;
008
009import Torello.Java.LV;
010
011import Torello.JavaDoc.StaticFunctional;
012import Torello.JavaDoc.Excuse;
013
014/**
015 * A fast way to print Web-Page {@code Vector's} to a {@code String}.
016 * <EMBED CLASS='external-html' DATA-FILE-ID=DEBUG>
017 */
018@StaticFunctional(Excused="lastWasNewLine", Excuses=Excuse.FLAG)
019public class Debug
020{
021    private Debug() { }
022
023    /**
024     * Convenience Method.
025     * <BR />Invokes: {@link #print(Vector, int, int, BiConsumer)}
026     * <BR />Requests: Print entire {@code 'page' (Vector)}
027     */
028    public static String print
029        (Vector<? extends HTMLNode> page, BiConsumer<HTMLNode, StringBuffer> printerVersion)
030    { return print(page, 0, -1, printerVersion); }
031
032    /**
033     * Convenience Method.
034     * <BR />Invokes: {@link #print(Vector, int, int, BiConsumer)}
035     * <BR />Requests: Print entire {@code SubSection}
036     */
037    public static String print(SubSection sec, BiConsumer<HTMLNode, StringBuffer> printerVersion)
038    { return print(sec.html, 0, -1, printerVersion); }
039
040    /**
041     * Convenience Method.
042     * <BR />Invokes: {@link #print(Vector, int, int, BiConsumer)}
043     * <BR />Requests: Print {@code 'page'} sub-range defined by parameter {@code 'dp'}
044     */
045    public static String print(
046            Vector<? extends HTMLNode> page, DotPair dp,
047            BiConsumer<HTMLNode, StringBuffer> printerVersion
048        )
049    { return print(page, dp.start, dp.end + 1, printerVersion); } 
050
051    /**
052     * Converts HTML to a {@code String} - adding readable notes &amp; messages.  This will print
053     * every node in the vectorized-html between starting-index {@code int sPos} (inclusively) and
054     * ending-index {@code int ePos}, exclusively.
055     * 
056     * @param page Any vectorized-html page or sub-page.
057     * 
058     * @param sPos The printing of nodes will begin at position {@code 'sPos'} - inclusively.
059     * 
060     * @param ePos The node at element-position will not be printed (exclusive), and the one
061     * previous shall print.
062     * 
063     * @param printerVersion The complicated-looking function-pointer comes from the package
064     * {@code 'java.util.function.'} The literal code to pass to this parameter would be:
065     * <SPAN STYLE="color: blue; font-weight: bold;">Debug::A, Debug::B ... Debug::K</SPAN>.  The
066     * programmer may also create a print-function if so desired, and pass that using a
067     * function-pointer or a {@code lambda-expression}
068     * 
069     * @return a pretty printed {@code String} of the nodes in this {@code Vector}.
070     * @throws IndexOutOfBoundsException <EMBED CLASS='external-html' DATA-FILE-ID=VIOOBEX>
071     * @see LV
072     */
073    public static String print(
074            Vector<? extends HTMLNode> page, int sPos, int ePos,
075            BiConsumer<HTMLNode, StringBuffer> printerVersion
076        )
077    {
078        LV              l   = new LV(page, sPos, ePos);
079        StringBuffer    sb  = new StringBuffer();
080
081        for (int i=l.start; i < l.end; i++)
082            printerVersion.accept(page.elementAt(i), sb);
083
084        return sb.toString();
085    }
086
087    /**
088     * Converts HTML to a {@code String} - adding readable notes &amp; messages.  This version
089     * shall only print nodes whose index "is pointed to" by the elements of the position-index
090     * array parameter {@code int[] posArr}.
091     * 
092     * @param page Any vectorized-html page or sub-page.
093     * 
094     * @param posArr This is an array of index-pointers into the vectorized-html webpage
095     * parameter 'page.'  These arrays are usually created by calls to the {@code package
096     * NodeSearch} using classes with the <B>{@code 'Find'} Key-Word</B>.  Such classes return
097     * integer-arrays of pointers to nodes that matched a specific search criteria.
098     * 
099     * @param printerVersion The complicated-looking function-pointer comes from the package
100     * 'java.util.function.' The literal code to pass to this parameter would be:
101     * <SPAN STYLE="color: blue; font-weight: bold;">Debug::A, Debug::B ... Debug::K</SPAN>.  The
102     * programmer may also create a print-function if so desired, and pass that using a
103     * function-pointer or a {@code lambda-expression}.
104     * 
105     * @return a pretty printed {@code String} of the nodes in this {@code Vector} pointed-to by
106     * the elements of {@code 'posArr'}
107     * 
108     * @throws ArrayIndexOutOfBoundsException If any of the elements in {@code 'posArr'} contain
109     * index-pointers that are out of range of {@code Vector} parameter {@code 'page'}, then java
110     * will, naturally, throw this exception.
111     */
112    public static String print(
113            Vector<? extends HTMLNode> page, int[] posArr,
114            BiConsumer<HTMLNode, StringBuffer> printerVersion
115        )
116    {
117        StringBuffer sb  = new StringBuffer();
118        for (int i : posArr) printerVersion.accept(page.elementAt(i), sb);
119        return sb.toString();
120    }
121
122    /**
123     * Converts HTML to a {@code String} - adding readable notes &amp; messages.  This version
124     * shall only print nodes whose index "is pointed to" by the elements of the position-index
125     * array parameter {@code int[] posArr}.
126     * 
127     * <BR /><BR /><B CLASS=JDDescLabel>Note about Usability:</B>
128     * 
129     * <BR />This version of print can be invaluable during debugging when trolling through pages
130     * of HTML is reduced to only the indexes that are indicated by an index-pointer array.  The
131     * addition of a "radix" means that some nodes before and after the identified node can be
132     * looked at too.
133     * 
134     * @param page Any vectorized-html page or sub-page.
135     * 
136     * @param posArr This is an array of index-pointers into the vectorized-html webpage
137     * parameter {@code 'page'}.  These arrays are usually created by calls to the {@code package
138     * NodeSearch} using classes with the <B>{@code 'Find'} Key-Word</B>.  Such classes return
139     * integer-arrays of pointers to nodes that matched a specific search criteria.
140     * 
141     * @param radix The number of nodes, in both the forward and reverse directions, to include
142     * in the output for a match.
143     * 
144     * @param nodesHaveBeenSkippedString This will be printed whenever the print-logic has skipped
145     * nodes in the list during printing.  An example of a good {@code String} to use would just be
146     * {@code Sting s = "***** Nodes Skipped *****\n";}, but any choice will do - so long as it
147     * gives the appearance the during printing there are "blank spots" that skipped some of the
148     * content of the html.
149     * 
150     * @param addColorCurlyBracesToRequestedNodes If this is {@code TRUE}, and the
151     * {@code class Shell.C} has its color {@code String} evaluated, because the program is running
152     * on some acceptable version of UNIX, then a bright-green colored curly-brace set will
153     * surround each node that is explicitly a member of the index-pointer-array, parameter
154     * {@code 'posArr'}
155     * 
156     * <BR /><BR />If this is unclear, this method prints every node that is pointed-to by the
157     * {@code 'posArr'} parameter. In addition to these nodes, it will print {@code 'radix'} nodes
158     * before and {@code 'radix'} nodes after each of the elements pointed to by the
159     * {@code 'posArr'} parameter.  When viewing the output, if it is important to know which nodes
160     * are explicitly in the 'request-list' then adding bright-green curly braces to those output
161     * nodes will differentiate them from other nodes that are being printed because of the
162     * {@code radix} parameter.
163     * 
164     * @param printerVersion The complicated-looking function-pointer comes from the package
165     * {@code 'java.util.function.'} The literal code to pass to this parameter would be:
166     * <SPAN STYLE="color: blue; font-weight: bold;">Debug::A, Debug::B ... Debug::K</SPAN>.  The
167     * programmer may also create a print-function if so desired, and pass that using a
168     * function-pointer or a {@code lambda-expression}
169     * 
170     * @return a pretty printed {@code String} of the nodes in this {@code Vector} pointed-to by
171     * the elements of {@code 'posArr'}, surrounded by {@code 'radix'} number of nodes in either
172     * direction.
173     * 
174     * @throws ArrayIndexOutOfBoundsException If any of the elements in {@code posArr} contain
175     * index-pointers that are out of range of {@code Vector}-parameter {@code 'page'}, then java
176     * will, naturally, throw this exception
177     * 
178     * @see Torello.Java.C
179     */
180    public static String print(
181            Vector<? extends HTMLNode> page, int[] posArr, int radix,
182            String nodesHaveBeenSkippedString,
183            boolean addColorCurlyBracesToRequestedNodes,
184            BiConsumer<HTMLNode, StringBuffer> printerVersion
185        )
186    {
187        StringBuffer sb = new StringBuffer();
188
189        // Used internally to print-curly braces
190        TreeSet<Integer> ts = null;
191
192        // Initialize it if the curly-braces are requested
193        if (addColorCurlyBracesToRequestedNodes)
194        {
195            ts = new TreeSet<>();
196            for (int pos : posArr) ts.add(Integer.valueOf(pos));
197        }
198
199        int start   = 0;
200        int end     = 0;
201
202        for (int i : posArr)
203        {
204            // Start at precisely the current index-pointer MINUS the radix.
205            // OR ... If the loop is about to "reprint" a node because the radix is larger than the
206            //        space between two consecutive nodes - then start at the node just after the
207            //        last node that was printed.
208
209            start = Math.max(i - radix, end + 1);
210    
211            // A large radix might get the loop past the end of the vector, AVOID THAT.
212            if (start > (page.size() - 1)) break;
213
214
215            // If the next node to be printed is immediately after the previous node that was
216            // printed IN THE UNDERLYING HTML, then no nodes have been skipped, so don't print the
217            // "nodesHaveBeenSkippedString" ... otherwise print it!
218
219            if (start > (end + 1)) sb.append(nodesHaveBeenSkippedString);
220
221            // Make sure not to go past the last node in the string, or exception will throw.
222            end = Math.min(i + radix, (page.size() - 1));
223
224
225            // It is possible that 'start' is greater than 'end' (too much overlap), in which case
226            // the outer loop will continue on to the next index-pointer.
227            // NOTE: uses 'j <= end' NOT 'j < end' !!! (TRICKY)
228
229            if (addColorCurlyBracesToRequestedNodes)
230
231                for (int j=start; j <= end; j++)
232                {
233                    boolean addColorBrackets = ts.contains(Integer.valueOf(j));
234
235                    if (addColorBrackets)
236                        sb.append(BGREEN + "{" + RESET);
237
238                    printerVersion.accept(page.elementAt(j), sb);
239
240                    if (addColorBrackets)
241                        sb.append(BGREEN + "}" + RESET);
242                }
243
244            else
245                for (int j=start; j <= end; j++)
246                    printerVersion.accept(page.elementAt(j), sb);
247        }
248
249        return sb.toString();
250    }
251
252
253    // ********************************************************************************************
254    // ********************************************************************************************
255    // Protected, Internal Print Methods
256    // ********************************************************************************************
257    // ********************************************************************************************
258
259
260    /**
261     * Prints an HTML Element ({@code TagNode, TextNode} or {@code CommentNode}) using
262     * <CODE><B>Print Style 'A'</B></CODE> 
263     * 
264     * @param n An {@code HTMLNode} that will print to the {@code StringBuffer}
265     * @param sb the {@code StringBuffer} that is receiving the print command.
266     * @see TagNode#str
267     */
268    public static void A(HTMLNode n, StringBuffer sb)
269    {
270        String name = n.getClass().getSimpleName();
271
272
273        // Extremely Unlikely Programmer has extended HTMLNode, but just in case, to prevent
274        // exception.
275
276        if (name.equals("")) name = "Anonymous Class";
277
278        sb.append("[" + name + ":" + n.str + "]");
279    }
280
281    /**
282     * Prints an HTML Element ({@code TagNode, TextNode} or {@code CommentNode}) using
283     * <CODE><B>Print Style 'B'</B></CODE> 
284     * 
285     * @param n An {@code HTMLNode} that will print to the {@code StringBuffer}
286     * @param sb the {@code StringBuffer} that is receiving the print command.
287     * @see TagNode#str
288     */
289    public static void B(HTMLNode n, StringBuffer sb)
290    {
291        String name = n.getClass().getSimpleName();
292
293
294        // Extremely Unlikely Programmer has extended HTMLNode, but just in case, to prevent
295        // exception.
296
297        if (name.equals("")) name = "Anonymous Class";
298
299        sb.append("[" + name + ", StrLen=" + n.str.length() + ": " + n.str + "]");
300    }
301
302    /**
303     * Prints an HTML Element ({@code TagNode, TextNode} or {@code CommentNode}) using
304     * <CODE><B>Print Style 'C'</B></CODE> 
305     * 
306     * @param n An {@code HTMLNode} that will print to the {@code StringBuffer}
307     * @param sb the {@code StringBuffer} that is receiving the print command.
308     * 
309     * @see TagNode#str
310     * @see TagNode#tok
311     * @see TagNode#isClosing
312     */
313    public static void C(HTMLNode n, StringBuffer sb)
314    {
315        String name = n.getClass().getSimpleName();
316
317
318        // Extremely Unlikely Programmer has extended HTMLNode, but just in case, to prevent
319        // exception.
320
321        if  (name.equals("")) name = "Anonymous Class";
322
323        if (n.isTagNode()) sb.append(
324            "[" + name + ", n.tok=" + ((TagNode) n).tok + ", " +
325            "n.isClosing=" + ((TagNode) n).isClosing + ": " + n.str + "]"
326        );
327
328        else
329            sb.append("[" + name + ": " + n.str + "]");
330    }
331
332    /**
333     * Prints an HTML Element ({@code TagNode, TextNode} or {@code CommentNode}) using
334     * <CODE><B>Print Style 'D'</B></CODE> 
335     * 
336     * @param n An {@code HTMLNode} that will print to the {@code StringBuffer}
337     * @param sb the {@code StringBuffer} that is receiving the print command.
338     * 
339     * @see TagNode#str
340     * @see TagNode#tok
341     * @see TagNode#isClosing
342     */
343    public static void D(HTMLNode n, StringBuffer sb)
344    {
345        String name = n.getClass().getSimpleName();
346
347
348        // Extremely Unlikely Programmer has extended HTMLNode, but just in case, to prevent
349        // exception.
350
351        if  (name.equals("")) name = "Anonymous Class";
352
353        if (n.isTagNode()) sb.append(
354            "[" + name + ", StrLen=" + n.str.length() + ", n.tok=" + ((TagNode) n).tok + ", " +
355            "n.isClosing=" + ((TagNode) n).isClosing + ": " + n.str + "]"
356        );
357
358        else
359            sb.append("[" + name + ", StrLen=" + n.str.length() + ": " + n.str + "]");
360    }
361
362    /**
363     * Prints an HTML Element ({@code TagNode, TextNode} or {@code CommentNode}) using
364     * <CODE><B>Print Style 'E'</B></CODE> 
365     * 
366     * @param n An {@code HTMLNode} that will print to the {@code StringBuffer}
367     * @param sb the {@code StringBuffer} that is receiving the print command.
368     * 
369     * @see TagNode#str
370     * @see TagNode#tok
371     * @see TagNode#isClosing
372     */
373    public static void E(HTMLNode n, StringBuffer sb)
374    {
375        String name = n.getClass().getSimpleName();
376
377
378        // Extremely Unlikely Programmer has extended HTMLNode, but just in case, to prevent
379        // exception.
380
381        if  (name.equals("")) name = "Anonymous Class";
382
383        if (n.isTagNode()) sb.append(
384            "[" + name + ", StrLen=" + n.str.length() + ", n.tok=" + ((TagNode) n).tok + ", " +
385            "n.isClosing=" + ((TagNode) n).isClosing + "]\n[" + n.str + "]\n"
386        );
387
388        else
389            sb.append("[" + name + ", StrLen=" + n.str.length() + "]\n[" + n.str + "]\n");
390    }
391
392    /**
393     * Prints an HTML Element ({@code TagNode, TextNode} or {@code CommentNode}) using
394     * <CODE><B>Print Style 'F'</B></CODE> 
395     * 
396     * @param n An {@code HTMLNode} that will print to the {@code StringBuffer}
397     * @param sb the {@code StringBuffer} that is receiving the print command.
398     * 
399     * @see TagNode#str
400     * @see TagNode#isClosing
401     * @see TagNode#toStringAV()
402     */
403    public static void F(HTMLNode n, StringBuffer sb)
404    {
405        String name = n.getClass().getSimpleName();
406
407
408        // Extremely Unlikely Programmer has extended HTMLNode, but just in case, to prevent
409        // exception.
410
411        if (name.equals("")) name = "Anonymous Class";
412
413        if (n.isTagNode() && (! ((TagNode) n).isClosing))
414            sb.append(((TagNode) n).toStringAV());
415
416        else
417            sb.append("[" + name + ", StrLen=" + n.str.length() + "]\n[" + n.str + "]\n");
418    }
419
420    /** Method 'G' is a hack - uses a global variable - THIS IS A HACK.  DO NOT WORRY ABOUT IT. */
421    private static boolean lastWasNewLine = false;
422
423    /**
424     * Prints an HTML Element ({@code TagNode, TextNode} or {@code CommentNode}) using
425     * <CODE><B>Print Style 'G'</B></CODE>
426     * 
427     * <BR /><BR /><B CLASS=JDDescLabel>Thread Safety Point:</B>
428     * <BR />Print Style G <I>is not {@code Thread} safe!</I>.
429     * 
430     * @param n An {@code HTMLNode} that will print to the {@code StringBuffer}
431     * @param sb the {@code StringBuffer} that is receiving the print command.
432     * 
433     * @see TagNode#str
434     * @see TagNode#tok
435     * @see TagNode#isClosing
436     * @see TagNode#toStringAV()
437     */
438    public static void G(HTMLNode n, StringBuffer sb)
439    {
440        String name = n.getClass().getSimpleName();
441
442        // Extremely Unlikely Programmer has extended HTMLNode, but just in case, to prevent
443        // exception.
444
445        if (name.equals("")) name = "Anonymous Class";
446
447        TagNode tn = null;
448
449        if (    n.isTagNode()
450            &&  (! (tn = (TagNode) n).isClosing)
451            &&  (tn.str.length() > (tn.tok.length() + 4))
452        )
453        {
454            sb.append((lastWasNewLine ? "" : "\n") + ((TagNode) n).toStringAV());
455            lastWasNewLine = true;
456        }
457
458        else
459        {
460            sb.append("[" + name + ", StrLen=" + n.str.length() + ": " + n.str + "]");
461            lastWasNewLine = false;
462        };
463    }
464
465    /**
466     * Prints an HTML Element ({@code TagNode, TextNode} or {@code CommentNode}) using
467     * <CODE><B>Print Style 'H'</B></CODE> 
468     * 
469     * @param n An {@code HTMLNode} that will print to the {@code StringBuffer}
470     * @param sb the {@code StringBuffer} that is receiving the print command.
471     * 
472     * @see C
473     * @see C#RESET
474     * @see C#BRED
475     * @see C#BCYAN
476     * @see TagNode#str
477     * @see TagNode#tok
478     * @see TagNode#isClosing
479     */
480    public static void H(HTMLNode n, StringBuffer sb)
481    {
482        String name = n.getClass().getSimpleName();
483
484
485        // Extremely Unlikely Programmer has extended HTMLNode, but just in case, to prevent
486        // exception.
487
488        if (name.equals("")) name = "Anonymous Class";
489
490        if (n.isTagNode()) sb.append(
491            "[" + name + ", StrLen=" + BCYAN + n.str.length() + RESET + ", " +
492            "n.tok=" + BCYAN + ((TagNode) n).tok + RESET +", " +
493            "n.isClosing=" + BCYAN + ((TagNode) n).isClosing + RESET + "]" +
494            "[" + BRED + n.str + RESET + "]"
495        );
496
497        else sb.append(
498            "[" + name + ", StrLen=" + BCYAN + n.str.length() + RESET + ": " +
499            BRED + n.str + RESET + "]"
500        );
501    }
502
503    /**
504     * Prints an HTML Element ({@code TagNode, TextNode} or {@code CommentNode}) using
505     * <CODE><B>Print Style 'I'</B></CODE> 
506     * 
507     * @param n An {@code HTMLNode} that will print to the {@code StringBuffer}
508     * @param sb the {@code StringBuffer} that is receiving the print command.
509     * 
510     * @see C
511     * @see C#RESET
512     * @see C#BRED
513     * @see C#BCYAN
514     * @see TagNode#str
515     * @see TagNode#tok
516     */
517    public static void I(HTMLNode n, StringBuffer sb)
518    {
519        String name = n.getClass().getSimpleName();
520
521
522        // Extremely Unlikely Programmer has extended HTMLNode, but just in case, to prevent
523        // exception.
524
525        if (name.equals("")) name = "Anonymous Class";
526
527        if (n.isTagNode())  sb.append(
528            "[" + name + ", StrLen=" + BCYAN + n.str.length() + RESET + ", " +
529            "n.tok=" + BCYAN + ((TagNode) n).tok + RESET + ", " +
530            "n.isClosing=" + BCYAN + ((TagNode) n).isClosing + RESET + "]\n" +
531            "[" + BRED + n.str + RESET + "]\n"
532        );
533
534        else sb.append(
535            "[" + name + ", StrLen=" + BCYAN + n.str.length() + RESET + "]\n" +
536            "[" + BRED + n.str + RESET + "]\n"
537        );
538    }
539
540    /**
541     * Prints an HTML Element ({@code TagNode, TextNode} or {@code CommentNode}) using
542     * <CODE><B>Print Style 'J'</B></CODE> 
543     * 
544     * @param n An {@code HTMLNode} that will print to the {@code StringBuffer}
545     * @param sb the {@code StringBuffer} that is receiving the print command.
546     * 
547     * @see C
548     * @see C#RESET
549     * @see C#BRED
550     * @see C#BYELLOW
551     * @see TagNode#str
552     */
553    public static void J(HTMLNode n, StringBuffer sb)
554    {
555        String name = n.getClass().getSimpleName();
556
557
558        // Extremely Unlikely Programmer has extended HTMLNode, but just in case, to prevent
559        // exception.
560
561        if (name.equals("")) name = "Anonymous Class";
562
563        if (n.isTagNode())
564            sb.append("[" + BRED + n.str + RESET + "]");
565
566        else if (n.isCommentNode())
567            sb.append("[" + BYELLOW + n.str + RESET + "]");
568
569        else
570            sb.append("[" + n.str + "]");
571    }
572
573    /**
574     * Prints an HTML Element ({@code TagNode, TextNode} or {@code CommentNode}) using
575     * <CODE><B>Print Style 'K'</B></CODE> 
576     * 
577     * @param n An {@code HTMLNode} that will print to the {@code StringBuffer}
578     * @param sb the {@code StringBuffer} that is receiving the print command.
579     * 
580     * @see C
581     * @see C#RESET
582     * @see C#BRED
583     * @see C#BYELLOW
584     * @see TagNode#str
585     */
586    public static void K(HTMLNode n, StringBuffer sb)
587    {
588        String name = n.getClass().getSimpleName();
589
590        // Extremely Unlikely Programmer has extended HTMLNode, but just in case, to prevent exception.
591        if  (name.equals("")) name = "Anonymous Class";
592
593        if (n.isTagNode())
594            sb.append("[" + BRED + n.str + RESET + "]\n");
595
596        else if (n.isCommentNode())
597            sb.append("[" + BYELLOW + n.str + RESET + "]\n");
598
599        else
600            sb.append("[" + n.str + "]\n");
601    }
602}