001package Torello.JavaDoc;
002
003import Torello.Java.*;
004import Torello.JDUInternal.Throwables.*;
005
006import Torello.JDUInternal.JDUProcessor;
007
008import static Torello.Java.C.*;
009
010import java.io.File;
011import java.util.Vector;
012
013/**
014 * A replacement for <CODE>System&#46;out, System&#46;err</CODE> and even the {@link StorageWriter}
015 * class used to send error messages to the terminal about upgrade progress.  
016 * 
017 * <BR /><BR /><EMBED CLASS='external-html' DATA-FILE-ID=JDMESSAGER>
018 */
019public class Messager
020{
021    private Messager() { }
022
023    // Error Message for {@code TypeNotPresentException}
024    static final String TNPE = 
025        "TypeNotPresentException thrown attempting to load Configuration Class.\n" +
026        "Class requires correct Package-Name, options are:\n" +
027        "    1) No Package-Name  2) Same Package-Name as the Package it's configuring";
028
029
030    // ********************************************************************************************
031    // ********************************************************************************************
032    // The Log Appendable
033    // ********************************************************************************************
034    // ********************************************************************************************
035
036
037    private static StorageWriter sw = new StorageWriter();
038
039    // This Appendable allows the user to pick a place to store the log-contents to disk, or just
040    // about any output-Appendable.  This java.lang.Appendable may be specified/configured with the
041    // class Upgrade - using the method: setLogFile
042    //
043    // NOTE: There are two methods for setting this field.  One allows the user to provide a file
044    //       name, and the other allows them to provide any free-formed java.lang.Appendable.
045
046    private static Appendable logAppendable = null;
047
048    // THIS METHOD IS NOT PUBLIC, THE LOG APPENDABLE IS SET BY THE USER IN CLASS "Upgrade"
049    static void setLogAppendable(Appendable lApp) { logAppendable = lApp; }
050
051    // MESSAGER: 
052    //  1) INVOKED-BY:  ExtraFilesProcessor (once!) and MainFilesProcessor (only once!)
053    //  2) USES:        assertFailGeneralPurpose
054    //  3) RETURNS:     void - NOTHING
055    //  4) THROWS:      JavaDocError (assertFailGeneralPurpose)
056
057    public static void ifLogCheckPointLog()
058    {
059        if (logAppendable == null) return;
060
061        String temp = C.toHTML(sw.getString(), true, true, true).replace("\t", "        ");
062
063        try
064        {
065            // Since log check-points are done after processing a JavaDoc File, this extra 
066            // "\n\n" just adds some space after each file has been printed.
067
068            logAppendable.append(temp); // + "\n\n");
069
070            // Clear the internal storage buffer.  Otherwise all the log-text would be re-written
071            // again at the next log check-point!
072
073            sw.erase();
074        }
075
076        catch (Exception e)
077        {
078            Messager.setCurrentFileName("User Provided Log", null);
079
080            Messager.assertFailGeneralPurpose(
081                e,
082                "Exception thrown while attempting to write to User-Provided Appendable-Log",
083                null
084            );
085        }
086    }
087
088
089    // ********************************************************************************************
090    // ********************************************************************************************
091    // Error-Message Set-Heading Methods
092    // ********************************************************************************************
093    // ********************************************************************************************
094
095
096    private static Integer indentation = 4;
097
098    private static String INDENT() { return (indentation==4) ? "    " : "        "; }
099
100    private static void printHeadingIfNecessary(JDUProcessor p)
101    {
102        if (indentation == 4)       printFileHeadingIfNecessary();
103        else if (indentation == 8)  printDetailHeadingIfNecessary();
104        else                        throw new UnreachableError();
105
106        sw.println
107            (INDENT() + "Processor [" + BCYAN + p.toString() + RESET + "] - " + p.explanation);
108    }
109
110    // The "current" Java Doc HTML File being analyzed
111    private static String fileName = null;
112
113    private static String fileNameKind = null;
114
115    // The first time that an error or warning is printed, the detail-section location must be
116    // printed at the top of the message.  All subsequent messges do not need this error
117    // header message.
118
119    private static boolean printedFirstFileName = false;
120
121    public /* Made Public With The Big-Move, was Package-Private */
122    static void setCurrentFileName(String fName, String fNameKind)
123    {
124        fileNameKind            = fNameKind;
125        fileName                = fName;
126        printedFirstFileName    = false;
127        indentation             = 4;
128
129        // Also clear the detail section
130        detailSection           = null;
131        printedFirstDetails     = false;
132    }
133
134    private static void printFileHeadingIfNecessary()
135    {
136        if (Messager.printedFirstFileName) return;
137
138        Messager.printedFirstFileName = true;
139
140        // There is at least one location where the "setCurrentFileName" sets a Directory
141        final String fileOrDir = fileName.endsWith(File.separator) ? "Directory: " : "File: ";
142
143        Messager.sw.println(
144            "Processing "+ fileOrDir +
145            "[" + BYELLOW + fileName + RESET + "]" +
146            ((fileNameKind != null) ? (", (" + fileNameKind + ")") : "") + ':'
147        );
148    }
149
150
151    // The "current" detail section about which error messages will be printed (if there are)
152    // any.
153
154    private static ReflHTML<?> detailSection = null;
155
156    // The "EmbedTag" processor treats the "TopDescription" as one of the details section.  It
157    // really isn't "a hack" - because the code is so long and the "Top Description" Embed Tag's
158    // are the exact same as the "Details" EmbedTag's.  This is also true for the "HiLiteDividers"
159
160    private static boolean topDescriptionAsDetails = false;
161
162    // The first time that an error or warning is printed, the detail-section location must be
163    // printed at the top of the message.  All subsequent messges do not need this error
164    // header message.
165
166    private static boolean printedFirstDetails = false;
167
168    public static void setCurrentDetailSection(ReflHTML<?> detailSection)
169    {
170        Messager.detailSection              = detailSection;
171        Messager.printedFirstDetails        = false;
172        Messager.topDescriptionAsDetails    = false;
173        Messager.indentation                = 8;
174    }
175
176    public static void setTopDescriptionSection()
177    {
178        Messager.detailSection              = null;
179        Messager.printedFirstDetails        = false;
180        Messager.topDescriptionAsDetails    = true;
181        Messager.indentation                = 8;
182    }
183
184    private static void printDetailHeadingIfNecessary()
185    {
186        printFileHeadingIfNecessary();
187
188        if (printedFirstDetails) return;
189
190        printedFirstDetails = true;
191
192        if (topDescriptionAsDetails) sw.println
193            ("    Processing [" + BCYAN + "Main CIET/Type Description, at top" + RESET + "]");
194
195        else
196        {
197            // This check was added when the class "Location" was built.  It is very much unknown
198            // how important this null-check is.  Remember that an 'UnreachableError' is always
199            // better than a null-pointer exception.
200
201            if ((detailSection.entity == null) || (detailSection.entity.location == null))
202                throw new UnreachableError();
203
204            // System.out.println("detailSection: " + detailSection);
205            // System.out.println("detailSection.entity: " + detailSection.entity);
206
207            String ln1 = (detailSection.entity.location.signatureStartLine != -1)
208                ? ("Signature Line [" + BGREEN + detailSection.entity.location.signatureStartLine +
209                    RESET + "]")
210                : null;
211
212            String ln2 = (detailSection.entity.location.jdcStartLine != -1)
213                ? ("JavaDoc Start Line [" + BGREEN + detailSection.entity.location.jdcStartLine +
214                    RESET + "]")
215                : null;
216
217            String line = "";
218
219            if (ln1 != null)        line = ln1 + ((ln2 != null) ? (", " + ln2) : "");
220            else if (ln2 != null)   line = ln2;
221
222            sw.println(
223                "    Processing " + BCYAN + detailSection.entityAsEnum.toString() + RESET +
224                    " Details Section " +
225                "for " + detailSection.entityAsEnum.toString() +
226                " [" + BRED + detailSection.entity.name + RESET + "], " +
227                line
228            );
229        }
230    }
231
232    private static JDUProcessor computeJDUProcessor(Throwable t)
233    {
234        StackTraceElement[] steArr = t.getStackTrace();
235
236        if (steArr.length == 0) steArr = t.fillInStackTrace().getStackTrace();
237
238        for (StackTraceElement ste : steArr)
239        {
240            String  className   = ste.getClassName();
241            int     pos         = className.lastIndexOf('.');
242
243            if (pos == -1) continue;
244
245            JDUProcessor p = JDUProcessor.valueOfOPT(className.substring(pos + 1));
246
247            if (p != null) return p;
248        }
249
250        return JDUProcessor.UNKNOWN;
251    }
252
253
254    // ********************************************************************************************
255    // ********************************************************************************************
256    // Simple print / println
257    // ********************************************************************************************
258    // ********************************************************************************************
259
260
261    /**
262     * Prints input {@code 's'}
263     * @param s Any {@code java.lang.String}
264     */
265    public static void print(String s)
266    { sw.print(s); }
267
268    /**
269     * Prints input {@code 's'}, followed by a newline.
270     * @param s Any {@code java.lang.String}
271     */
272    public static void println(String s)
273    { sw.println(s); }
274
275    /** Prints a newline character */
276    public static void println()
277    { sw.println(); }
278
279
280    // ********************************************************************************************
281    // ********************************************************************************************
282    // Printing Errors that Do Not Cause Program-Flow to Exit Immediately
283    // ********************************************************************************************
284    // ********************************************************************************************
285
286
287    private static int errorCount   = 0;
288    private static int warningCount = 0;
289
290    /**
291     * Allows a user to query the Messager regarding whether any errors have been logged which
292     * didn't actually stop the upgrader from continuing.
293     * 
294     * @return If there have been errors issued by the Upgrade Processors that did not actually
295     * force the Upgrade to halt, this method will return {@code TRUE}.
296     * 
297     * <BR /><BR />If no such errors have been encountered, this method returns {@code FALSE}
298     */
299    public static boolean hadErrors() { return errorCount > 0; }
300
301    /**
302     * Retrieve how many errors have been sent to the Messager.  Not all errors will cause the
303     * Upgrade Process to exit immediately.  This number is often - <I>but not necessarily</I> -
304     * zero.
305     * 
306     * @return The number of errors issued to the Messager since the start of the Upgrade.
307     */
308    public static int numErrors() { return errorCount; }
309
310    /**
311     * Allows a user to query the Messager regarding whether any warnings. 
312     * @return If there have been warnings this method will return {@code TRUE}.
313     */
314    public static boolean hadWarnings() { return warningCount > 0; }
315
316    /**
317     * Retrieve how many warnings have been sent to the Messager
318     * @return The number of warnings issued during the Upgrade Process
319     */
320    public static int numWarnings() { return warningCount; }
321
322
323    // ********************************************************************************************
324    // ********************************************************************************************
325    // BASIC PRINTING
326    // ********************************************************************************************
327    // ********************************************************************************************
328
329
330    /**
331     * Issue a warning to the Messager about any problem that may have cropped up during the
332     * upgrade.  The Messager will send the text to whatever output mechanism has been specified by
333     * the user, and increase the warning count.
334     * 
335     * @param message A message to be printed to the Messager's output.
336     * @param p The processor to which the message shall be ascribed when performing the printing.
337     */
338    public static void warning(String message, JDUProcessor p)
339    {
340        warningCount++;
341        printHeadingIfNecessary(p);
342
343        sw.println(
344            INDENT() + "Warning: " +
345            StrIndent.indentAfter2ndLine(message, 4 + indentation, true, true)
346        );
347    }
348
349
350    // ********************************************************************************************
351    // ********************************************************************************************
352    // PRINTING-ERROR'S, PRIVATE
353    // ********************************************************************************************
354    // ********************************************************************************************
355
356
357    private static void ASSERT_FAIL
358        (String oneLinerNote, String message, String signature, JDUProcessor jdup)
359    {
360        if (++errorCount > 25) throw new ReachedMaxErrors();
361        printHeadingIfNecessary(jdup);
362
363        signature = (signature != null)
364            ? ("Entity-Signature:\n" + StrIndent.indent((signature = signature.trim()), 4))
365            : "";
366
367        sw.println(
368            StrIndent.indent(
369                oneLinerNote +
370                StrIndent.indentAfter2ndLine(message.trim(), 4, true, true) + '\n' +
371                signature,
372                indentation
373            ));
374    }
375
376    private static void ASSERT_FAIL
377        (String oneLinerNote, Throwable t, String message, String signature, JDUProcessor jdup)
378    {
379        if (++errorCount > 25) throw new ReachedMaxErrors();
380        printHeadingIfNecessary(jdup);
381
382        signature = (signature != null)
383            ? ( "Entity-Signature:\n" + StrIndent.indent((signature=signature.trim()), 4) + '\n' +
384                "************************************************************************\n")
385            : "";
386
387        sw.println(
388            StrIndent.indent(
389                oneLinerNote + " (Exception Thrown)\n" +
390                "************************************************************************\n" +
391                EXCC.toString(t) + '\n' +
392                "************************************************************************\n" +
393                message + '\n' +
394                "************************************************************************\n" +
395                signature,
396                indentation
397            ));
398    }
399
400    private static void ERROR
401        (Throwable t, String message, boolean FATAL, boolean showST, JDUProcessor p)
402    {
403        if (++errorCount > 25) throw new ReachedMaxErrors();
404        printHeadingIfNecessary(p);
405
406        sw.println(
407            StrIndent.indent(
408                (FATAL ? "Fatal Error: " : "Error: ") + "Exception Thrown:\n" +
409                "************************************************************************\n" +
410                (showST
411                    ? EXCC.toString(t)
412                    : (
413                        "Exception-Name:    " + BRED + t.getClass().getCanonicalName() +
414                            RESET +'\n' +
415                        "Exception-Message: " + t.getMessage()
416                    )
417                ) + '\n' +
418                "************************************************************************\n" +
419                message + '\n' +
420                "************************************************************************\n",
421                indentation
422            ));
423    }
424
425    private static void ERROR(String message, boolean FATAL, JDUProcessor p)
426    {
427        if (++errorCount > 25) throw new ReachedMaxErrors();
428        printHeadingIfNecessary(p);
429
430        sw.println(
431            INDENT() + (FATAL ? "Fatail Error: " : "Error: ") + 
432            StrIndent.indentAfter2ndLine(message, 4 + indentation, true, true)
433        );
434    }
435
436
437    // ********************************************************************************************
438    // ********************************************************************************************
439    // Fatal-Assert: Throws to Stop Program-Execution Immediatley
440    // ********************************************************************************************
441    // ********************************************************************************************
442
443
444    /**
445     * Previously Unreleased.  Intended to be used like a Java Assert - meaning programming error
446     * that shouldn't occur.
447     * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=MSGR_CONV_RET_T>
448     * @param message The error message
449     * @return Nothing - throws a {@link JavaDocError}
450     */
451    public static <T> T assertFailCheckup(String message)
452    {
453        JavaDocError jde = new JavaDocError();
454        ASSERT_FAIL("Assertion-Checkup Error: ", message, null, computeJDUProcessor(jde));
455        throw jde;
456    }
457
458    /**
459     * Intended to be used like a Java Assert - meaning programming error that shouldn't occur.
460     * Intended for use specifically when parsing HTML.
461     *
462     * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=MSGR_CONV_RET_T>
463     * @param message The error message
464     * @param signature This parameter should contain the detail-signature, or 'null'
465     * @return Nothing - throws a {@link JavaDocHTMLParseException}
466     */
467    public static <T> T assertFailHTML(String message, String signature)
468    {
469        JavaDocHTMLParseException jdhpe = new JavaDocHTMLParseException(message, signature);
470
471        ASSERT_FAIL
472            ("Java-Doc HTML Parsing Error: ", message, signature, computeJDUProcessor(jdhpe));
473
474        throw jdhpe;
475    }
476
477    /**
478     * Intended to be used like a Java Assert - meaning programming error that shouldn't occur.
479     * Intended for use specifically when parsing HTML.
480     *
481     * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=MSGR_CONV_RET_T>
482     * @param t The throwable that caused this assert-fail
483     * @param message The error message
484     * @param signature This parameter should contain the detail-signature, or 'null'
485     * @return Nothing - throws a {@link JavaDocHTMLParseException}
486     */
487    public static <T> T assertFailHTML(Throwable t, String message, String signature)
488    {
489        JavaDocHTMLParseException jdhpe = new JavaDocHTMLParseException(message, t, signature);
490
491        ASSERT_FAIL
492            ("Java-Doc HTML Parsing Error: ", t, message, signature, computeJDUProcessor(jdhpe));
493
494        throw jdhpe;
495    }
496
497    /**
498     * Intended to be used like a Java Assert - meaning programming error that shouldn't occur.
499     * 
500     * <BR /><BR />Intended for use specifically when parsing Java Source-Code - <I>using the
501     * Java-Parser &trade; Source-Code Parsing Package:</I> <CODE>org.github.javaparser</CODE>
502     *
503     * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=MSGR_CONV_RET_T>
504     * @param message The error message
505     * @param signature This parameter should contain the detail-signature, or 'null'
506     * @return Nothing - throws a {@link SourceCodeParseException}
507     */
508    public static <T> T assertFailJavaParser(String message, String signature)
509    {
510        SourceCodeParseException scpe = new SourceCodeParseException(message, signature);
511
512        ASSERT_FAIL(
513            "Java-Parser Source-Code Parsing Error: ", message, signature,
514            computeJDUProcessor(scpe)
515        );
516
517        throw scpe;
518    }
519
520    /**
521     * Intended to be used like a Java Assert - meaning programming error that shouldn't occur.
522     * 
523     * <BR /><BR />Intended for use specifically when parsing Java Source-Code - <I>using the
524     * Java-Parser &trade; Source-Code Parsing Package:</I> <CODE>org.github.javaparser</CODE>
525     *
526     * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=MSGR_CONV_RET_T>
527     * @param t The throwable that caused this assert-fail
528     * @param message The error message
529     * @param signature This parameter should contain the detail-signature, or 'null'
530     * @return Nothing - throws a {@link SourceCodeParseException}
531     */
532    public static <T> T assertFailJavaParser(Throwable t, String message, String signature)
533    {
534        SourceCodeParseException scpe = new SourceCodeParseException(message, t, signature);
535
536        ASSERT_FAIL(
537            "Java-Parser Source-Code Parsing Error: ", t, message, signature,
538            computeJDUProcessor(scpe)
539        );
540
541        throw scpe;
542    }
543
544    /**
545     * Intended to be used like a Java Assert - meaning programming error that shouldn't occur.
546     * 
547     * <BR /><BR />Intended for use specifically when parsing Java Source-Code - <I>using the
548     * Sun-Oracle Source-Code Parsing Package:</I> <CODE>com.sun.source.tree</CODE>.
549     *
550     * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=MSGR_CONV_RET_T>
551     * @param message The error message
552     * @param signature This parameter should contain the detail-signature, or 'null'
553     * @return Nothing - throws a {@link SourceCodeParseException}
554     */
555    public static <T> T assertFailOracleParser(String message, String signature)
556    {
557        SourceCodeParseException scpe = new SourceCodeParseException(message, signature);
558
559        ASSERT_FAIL(
560            "Oracle-Sun Source-Code Parsing Error: ", message, signature,
561            computeJDUProcessor(scpe)
562        );
563
564        throw scpe;
565    }
566
567    /**
568     * Intended to be used like a Java Assert - meaning programming error that shouldn't occur.
569     * 
570     * <BR /><BR />Intended for use specifically when parsing Java Source-Code - <I>using the
571     * Sun-Oracle Source-Code Parsing Package:</I> <CODE>com.sun.source.tree</CODE>.
572     *
573     * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=MSGR_CONV_RET_T>
574     * @param t The throwable that caused this assert-fail
575     * @param message The error message
576     * @param signature This parameter should contain the detail-signature, or 'null'
577     * @return Nothing - throws a {@link SourceCodeParseException}
578     */
579    public static <T> T assertFailOracleParser(Throwable t, String message, String signature)
580    {
581        SourceCodeParseException scpe = new SourceCodeParseException(message, t, signature);
582
583        ASSERT_FAIL(
584            "Oracle-Sun  Source-Code Parsing Error: ", t, message, signature,
585            computeJDUProcessor(scpe)
586        );
587
588        throw scpe;
589    }
590
591    /**
592     * Previously Unreleased.  Intended to be used like a Java Assert - meaning programming error
593     * that shouldn't occur.  Intended for General-Purpose / unknown errors.
594     * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=MSGR_CONV_RET_T>
595     * @param message The error message
596     * @param signature This parameter should contain the detail-signature, or 'null'
597     * @return Nothing - throws a {@link UpgradeException}
598     */
599    public static <T> T assertFailGeneralPurpose(String message, String signature)
600    {
601        UpgradeException ue = new UpgradeException();
602        ASSERT_FAIL("Java-Doc Upgrader Error: ", message, signature, computeJDUProcessor(ue));
603        throw ue;
604    }
605
606    /**
607     * Previously Unreleased  Intended to be used like a Java Assert - meaning programming error
608     * that shouldn't occur.  Intended for General-Purpose / unknown errors.
609     * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=MSGR_CONV_RET_T>
610     * @param t The throwable that caused this assert-fail
611     * @param message The error message
612     * @param signature This parameter should contain the detail-signature, or 'null'
613     * @return Nothing - throws a {@link UpgradeException}
614     */
615    public static <T> T assertFailGeneralPurpose(Throwable t, String message, String signature)
616    {
617        UpgradeException ue = new UpgradeException();
618        ASSERT_FAIL("Java-Doc Upgrader Error: ", t, message, signature, computeJDUProcessor(ue));
619        throw ue;
620    }
621
622
623    // ********************************************************************************************
624    // ********************************************************************************************
625    // Fatal-User-Error: Throws to Stop Program-Execution Immediatley
626    // ********************************************************************************************
627    // ********************************************************************************************
628
629
630    /**
631     * Log an error to the Messager, and throw a {@link JavaDocError}
632     * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=MSGR_CONV_RET_T>
633     * @param message The error message
634     * @return Does not return anything.  This method is guaranteed to throw a {@link JavaDocError}
635     * @throws JavaDocError Always thrown
636     */
637    public static <T> T  userErrorHalt(String message)
638    {
639        JavaDocError jde = new JavaDocError();
640        ERROR(message, true /* FATAL */, computeJDUProcessor(jde));
641        throw jde;
642    }
643
644    /**
645     * Log an error to the Messager, and throw a {@link JavaDocError}
646     * @param <T> <EMBED CLASS='external-html' DATA-FILE-ID=MSGR_CONV_RET_T>
647     * @param t The exception or cause throwable that has produced the error.
648     * @param message The error message
649     * @return Does not return anything.  This method is guaranteed to throw a {@link JavaDocError}
650     * @throws JavaDocError Always thrown
651     */
652    public static <T> T userErrorHalt(Throwable t, String message)
653    {
654        JavaDocError jde = new JavaDocError();
655        ERROR(t, message, true /* FATAL */, true /* Show Stack-Trace */, computeJDUProcessor(jde));
656        throw jde;
657    }
658
659
660    // ********************************************************************************************
661    // ********************************************************************************************
662    // User-Error: Program-Flow Execution Continues
663    // ********************************************************************************************
664    // ********************************************************************************************
665
666
667    /**
668     * Log an error to the Messager
669     * 
670     * @param message The error message
671     * 
672     * @param p The Upgrade-Processor that has produced this error cannot be computed since a
673     * stack-trace cannot be obtained without throwing an unnecessary exception (which is extremely
674     * inefficient).  Therefore, the Upgrade-Processor must be explicity specified here, using this
675     * parameter.
676     */
677    public static void userErrorContinue(String message, JDUProcessor p)
678    { ERROR(message, false /* NON-FATAL */, p); }
679
680    /**
681     * Log an error to the Messager
682     * 
683     * @param t The exception or cause throwable that has produced the error.
684     * @param message The error message
685     * 
686     * @param p The Upgrade-Processor that has produced this error cannot be computed since a
687     * stack-trace cannot be obtained without throwing an unnecessary exception (which is extremely
688     * inefficient).  Therefore, the Upgrade-Processor must be explicity specified here, using this
689     * parameter.
690     */
691    public static void userErrorContinue(Throwable t, String message, JDUProcessor p)
692    { ERROR(t, message, false /* NON-FATAL */, false  /* Don't Show Stack-Trace */, p); }
693
694    /**
695     * Log an error to the Messager.  Guarantees that the Stack-Trace is printed.
696     * 
697     * @param t The exception or cause throwable that has produced the error.
698     * @param message The error message
699     * 
700     * @param p The Upgrade-Processor that has produced this error cannot be computed since a
701     * stack-trace cannot be obtained without throwing an unnecessary exception (which is extremely
702     * inefficient).  Therefore, the Upgrade-Processor must be explicity specified here, using this
703     * parameter.
704     */
705    public static void userErrorContinueST(Throwable t, String message, JDUProcessor p)
706    { ERROR(t, message, false /* NON-FATAL */, true  /* SHOW STACK TRACE */, p); }
707}