001package Torello.JavaDoc.Messager;
002
003import Torello.Java.StringParse;
004import Torello.Java.StrIndent;
005import Torello.Java.StrPrint;
006import Torello.Java.EXCC;
007
008import Torello.JavaDoc.ReflHTML;
009import Torello.JavaDoc.Declaration;
010
011import static Torello.Java.C.*;
012import static Torello.JavaDoc.Messager.Where_Am_I.LABEL_COLOR;
013
014import java.io.File;
015
016
017// This class exports two main methods named "ERROR".  These two methods are invoked by the
018// actual, "public", part of this Messager-Package.  The actual class "Messager" has quite a number
019// of "versions" of the two ERROR(...) Methods that are exported by this Package-Private class.
020// 
021// There is also a small "warning(...)" method that this class exports.  There is some likelihood
022// that this will be eliminated.  Early on it seemed like there could be the potential for many
023// User-Caused "Warning" Messages.  However, there really haven't been any, whatsoever.  That very
024// well could change with later code-reviews and bug-finding episodes.
025// 
026// NOT-SURE-YET !  For now, "warning(...)" will remain.
027// 
028// This entire class serves the primary purpose of "worrying about" all of the levels of
029// indentation that are needed to make the Error-Messages that the JDU generates actually look nice
030// and be readable.  The whole concept of printing the current working file-name and the current 
031// working processor name with proper indentation is accomplished by simply keeping a record every 
032// time the JDU moves onto a different file or uses a different processor.
033// 
034// It sort of is "that simple".  It's hard to make this "Messager Package" look simple, even though
035// it certainly is pretty simple.  Explaining what the JDU Error-Reporting Code is expected to do
036// is actually a little bit tricky.
037// 
038// The Packages "JDUInternal.MainJDU" and "JDUInternal.Features" (along with other
039// classes/packages) are all expected to report to this Messager whenever they have begun
040// processing the next Java-Doc '.html' Web-Page, or begun using the next ReflHTML "Feature" 
041// Processor.
042// 
043// Again, all this Messager class really does is export Two "ERROR" printing methods and one 
044// "WARNIGN" printing method (which isn't even used right now, except in single location).  These
045// "Error Printers" do a verifiable "ton" of work to make sure the Error-Messages which are 
046// printed to the User's Terminal have great indentation, are properly wrapped if the text goes
047// on too long, and that all heading information for the errors are properly printed above the
048// messages.
049// 
050// The actual JDU Classes in this package all make calls to class 'Messager', rather than
051// 'MsgPkgPrivate'.
052
053public class PrintMessage
054{
055    // ********************************************************************************************
056    // ********************************************************************************************
057    // Constructor & Field
058    // ********************************************************************************************
059    // ********************************************************************************************
060
061
062    private final PrintRecord   printRecord;
063    private final PrintHeading  printHeading;
064
065    PrintMessage(final PrintRecord printRecord, final PrintHeading printHeading)
066    {
067        this.printRecord    = printRecord;
068        this.printHeading   = printHeading;
069    }
070
071
072    // ********************************************************************************************
073    // ********************************************************************************************
074    // Two, very simple, PRIVATE, Static-Fields
075    // ********************************************************************************************
076    // ********************************************************************************************
077
078
079    // This is used *ONCE* to print decide whether to print a particular stack-trace.
080    // It's the kind of thing that I really need, but the end user really shouldn't even expect
081    // to see it.
082
083    private static final boolean DEBUGGING = true;
084
085    private static final String BLUE_LINE =
086        BLUE_BKGND + BWHITE + StringParse.nChars('*', 70) + RESET + '\n';
087
088
089    // ********************************************************************************************
090    // ********************************************************************************************
091    // Two Main, Configurable, Error Message Printers
092    // ********************************************************************************************
093    // ********************************************************************************************
094
095
096    // Does not have a "Throwable"
097    void ERROR(
098            final String        message,
099            final String        signature,
100            final boolean       FATAL,
101            final Where_Am_I    WHERE_AM_I
102        )
103    {
104        final String oneLinerNote = null;
105
106        this.printRecord.incErrorCountAndCheck();
107
108        this.printHeading.printHeadingIfNecessary(WHERE_AM_I);
109
110
111        // In the lines below, String.trim() is used.  This is *ALWAYS* OK - unless the
112        // String being trimmed starts with a UNIX Color-Code Escape-Sequence.  The first character
113        // of a UNIX Escape Sequence is (synonymously named "ESCAPE") '\u001B'
114        //
115        // Java's String.trim() seems to be trimming that chacter!
116        // 
117        // However since "signature" and oneLinerNote are not supposed to have any Color-Codes in 
118        // them, it should not matter right here!
119
120        final String sigStr = (signature == null)
121            ? ""
122            : (
123                '\n' +
124                LABEL_COLOR + " Entity-Signature " + RESET + '\n' +
125                StrIndent.indent((signature.trim().replace("\t", "    ")), 4) + '\n'
126            );
127
128        final String firstLineNote =
129            ' ' +
130            (FATAL ? "Fatal " : "") +
131            ((oneLinerNote != null) ? oneLinerNote.trim() : "Error") +
132            ' ';
133
134        final int firstWrap = 100 - firstLineNote.length();
135
136        this.printRecord.sb
137            .append(
138                StrIndent.indent(
139                    LABEL_COLOR + firstLineNote + RESET +
140                    ' ' +
141                    StrIndent.indentAfter2ndLine(
142                        StrPrint.wrapToIndentationPlus(
143                            message
144                                .replaceAll("^[\\s]+|[\\s]+$", "") // Cannot use 'trim()'
145                                .replace("\t", "    "),
146                            firstWrap,
147                            100,
148                            4
149                        ),
150                        4,
151                        true,
152                        true
153                    ) +
154                    '\n' +
155                    sigStr,
156                    this.printRecord.getIndentation()
157                ))
158            .append('\n');
159    }
160
161    // Has Throwable **AND** 'showST'
162    void ERROR(
163            final Throwable     t,
164            final String        message,
165            final String        signature,
166            final boolean       FATAL,
167            final boolean       showST,
168            final Where_Am_I    WHERE_AM_I
169        )
170    {
171        final String oneLinerNote = null;
172
173        this.printRecord.incErrorCountAndCheck();
174
175        this.printHeading.printHeadingIfNecessary(WHERE_AM_I);
176
177        final String sigStr = (signature == null)
178            ? ""
179            : (
180                LABEL_COLOR + " Entity-Signature " + RESET + '\n' +
181                StrIndent.indent((signature.trim().replace("\t", "    ")), 4) + '\n' +
182                BLUE_LINE
183            );
184
185        final String topNote = (oneLinerNote != null)
186            ? (LABEL_COLOR + ' ' + oneLinerNote.trim() + ' ' + RESET + 
187                " (Exception Thrown)\n")
188            : (
189                LABEL_COLOR + ' ' +
190                (FATAL ? "Fatal " : "") +
191                "Error, Exception Thrown " + RESET + '\n'
192            );
193
194        final String exceptionStr = (FATAL || showST)
195            ? EXCC.toString(t)
196            : (
197                LABEL_COLOR + " Exception-Name " + RESET + "    " +
198                    BRED + t.getClass().getCanonicalName() +
199                    RESET +'\n' +
200                LABEL_COLOR + " Exception-Message " + RESET + ' ' +
201                    t.getMessage() + '\n' +
202                LABEL_COLOR + " Abbreviated-Trace " + RESET + ' ' +
203                    (DEBUGGING ? " (Debugging-Mode On, Abbreviation Off)" : "") +
204                    '\n' + 
205                    (DEBUGGING ? EXCC.toString(t, 4) : EXCC.toStringMaxTraces(t, 2, 4))
206            );
207
208
209        // String.trim() ==> It trims the UNIX Escape-Sequence Character '\u001B'
210        // It is not supposed to, acording to Chat-GPT !!  But it does anyway!
211        // 
212        // System.out.println(exceptionStr.trim());
213        // System.out.println(exceptionStr.replaceAll("^[\\s]+|[\\s]+$", ""));
214        // Torello.Java.Q.BP();
215
216        this.printRecord.sb
217            .append(
218                StrIndent.indent(
219                    StrPrint.wrapToIndentationPlus(
220                        topNote +
221                        BLUE_LINE +
222                        exceptionStr
223                            .replaceAll("^[\\s]+|[\\s]+$", "") // Cannot use 'trim()'
224                            .replace("\t", "    ") +
225                            '\n' +
226                        BLUE_LINE +
227                        message
228                            .replaceAll("^[\\s]+|[\\s]+$", "") // Cannot use 'trim()'
229                            .replace("\t", "    ") +
230                            '\n' +
231                        BLUE_LINE +
232                        sigStr,
233                        100,
234                        100,
235                        4
236                    ),
237                    this.printRecord.getIndentation()
238                ))
239            .append('\n');
240    }
241
242
243    // ********************************************************************************************
244    // ********************************************************************************************
245    // Warning
246    // ********************************************************************************************
247    // ********************************************************************************************
248
249
250    // Does not wahave a "Throwable"
251    void WARNING(
252            final String        message,
253            final Where_Am_I    WHERE_AM_I
254        )
255    {
256        this.printRecord.incWarningCount();
257
258        this.printHeading.printHeadingIfNecessary(WHERE_AM_I);
259
260        this.printRecord.sb
261            .append(
262                StrPrint.wrapToIndentationPlus(
263                    this.printRecord.getIndentationStr() + 
264                    LABEL_COLOR + " Warning " + RESET + ' ' +
265
266                    StrIndent.indentAfter2ndLine(
267                        message.replace("\t", "    "),
268                        4 + this.printRecord.getIndentation(),
269                        true,
270                        true
271                    ),
272                    100,
273                    100,
274                    4
275                ) +
276                '\n'
277            )
278            .append('\n');
279    }
280}