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 making note (by 032// updating a 'fileName' and 'Where_Am_I' internal / private field) whenever the JDU moves onto a 033// different file or a different HTML-Processor. 034// 035// It sort of is "that simple". The thing is that it is really difficult to make this "Messager 036// Package" look simple - even though it certainly is pretty simple. Explaining what the JDU 037// Error-Reporting Code is expected to do is actually a little bit tricky. I mean, all it really 038// is doing is printing what would other-wise be an exception throw - to the screen, and then 039// allowing Program Control-Flow to move onto the next thing that they do... 040// 041// Sporadically, througout the JDU, there are checks which necessitate that if errors hae occurred 042// then the JDU-Tool must exit. **FUNDAMENTALLY** - the entire purpose of a Messager-Class or 043// Messager-Package is to print as many errors as possible to the user's terminal before exiting 044// the application. When debugging a project, the user simply cannot be bothered with restarting 045// his ugrader by, laboriousy, once for each and every "documentation bug" that exists in his 046// upgrade configurations. 047// 048// If the JDK's 'javac' command printed only 1 error when compiling many files, and then exited 049// unti each bug found had been eliminated - NOBODY WOULD USE JAVA, JAVAC OR THE JDK AT ALL because 050// it would be thought of as way too slow! 051// 052// The Packages "JDUInternal.MainJDU" and "JDUInternal.Features" (along with other 053// classes/packages) are all expected to report to this Messager whenever they have begun 054// processing the next Java-Doc '.html' Web-Page, or begun using the next ReflHTML "Feature" 055// Processor. 056// 057// Again, all this Messager class really does is export Two "ERROR" printing methods and one 058// "WARNIGN" printing method (which isn't even used right now, except in single location). These 059// "Error Printers" do a verifiable "ton" of work to make sure the Error-Messages which are 060// printed to the User's Terminal have great indentation, are properly wrapped if the text goes 061// on too long, and that all heading information for the errors are properly printed above the 062// messages. 063// 064// The actual JDU Classes in this package all make calls to class 'Messager', rather than 065// 'MsgPkgPrivate'. 066 067/** 068 * This is an internally used class whose primary purpose is to generate the actual Java-Strings 069 * which are printed to the User's Terminal on Error. 070 * 071 * <BR /><BR /><EMBED CLASS='external-html' DATA-FILE-ID=PRINT_MESSAGE> 072 */ 073public class PrintMessage 074{ 075 // ******************************************************************************************** 076 // ******************************************************************************************** 077 // Constructor & Field 078 // ******************************************************************************************** 079 // ******************************************************************************************** 080 081 082 private final PrintRecord printRecord; 083 private final PrintHeading printHeading; 084 085 PrintMessage(final PrintRecord printRecord, final PrintHeading printHeading) 086 { 087 this.printRecord = printRecord; 088 this.printHeading = printHeading; 089 } 090 091 092 // ******************************************************************************************** 093 // ******************************************************************************************** 094 // Two, very simple, PRIVATE, Static-Fields 095 // ******************************************************************************************** 096 // ******************************************************************************************** 097 098 099 // This is used *ONCE* to print decide whether to print a particular stack-trace. 100 // It's the kind of thing that I really need, but the end user really shouldn't even expect 101 // to see it. 102 103 private static final boolean DEBUGGING = true; 104 105 private static final String BLUE_LINE = 106 BLUE_BKGND + BWHITE + StringParse.nChars('*', 70) + RESET + '\n'; 107 108 109 // ******************************************************************************************** 110 // ******************************************************************************************** 111 // Two Main, Configurable, Error Message Printers 112 // ******************************************************************************************** 113 // ******************************************************************************************** 114 115 116 // Does not have a "Throwable" 117 void ERROR( 118 final String message, 119 final String signature, 120 final boolean FATAL, 121 final Where_Am_I WHERE_AM_I 122 ) 123 { 124 final String oneLinerNote = null; 125 126 this.printRecord.incErrorCountAndCheck(); 127 128 this.printHeading.printHeadingIfNecessary(WHERE_AM_I); 129 130 131 // In the lines below, String.trim() is used. This is *ALWAYS* OK - unless the 132 // String being trimmed starts with a UNIX Color-Code Escape-Sequence. The first character 133 // of a UNIX Escape Sequence is (synonymously named "ESCAPE") '\u001B' 134 // 135 // Java's String.trim() seems to be trimming that chacter! 136 // 137 // However since "signature" and oneLinerNote are not supposed to have any Color-Codes in 138 // them, it should not matter right here! 139 140 final String sigStr = (signature == null) 141 ? "" 142 : ( 143 '\n' + 144 LABEL_COLOR + " Entity-Signature " + RESET + '\n' + 145 StrIndent.indent((signature.trim().replace("\t", " ")), 4) + '\n' 146 ); 147 148 final String firstLineNote = 149 ' ' + 150 (FATAL ? "Fatal " : "") + 151 ((oneLinerNote != null) ? oneLinerNote.trim() : "Error") + 152 ' '; 153 154 final int firstWrap = 100 - firstLineNote.length(); 155 156 this.printRecord.sb 157 .append( 158 StrIndent.indent( 159 LABEL_COLOR + firstLineNote + RESET + 160 ' ' + 161 StrIndent.indentAfter2ndLine( 162 StrPrint.wrapToIndentationPlus( 163 message 164 .replaceAll("^[\\s]+|[\\s]+$", "") // Cannot use 'trim()' 165 .replace("\t", " "), 166 firstWrap, 167 100, 168 4 169 ), 170 4, 171 true, 172 true 173 ) + 174 '\n' + 175 sigStr, 176 this.printRecord.getIndentation() 177 )) 178 .append('\n'); 179 } 180 181 // Has Throwable **AND** 'showST' 182 void ERROR( 183 final Throwable t, 184 final String message, 185 final String signature, 186 final boolean FATAL, 187 final boolean showST, 188 final Where_Am_I WHERE_AM_I 189 ) 190 { 191 final String oneLinerNote = null; 192 193 this.printRecord.incErrorCountAndCheck(); 194 195 this.printHeading.printHeadingIfNecessary(WHERE_AM_I); 196 197 final String sigStr = (signature == null) 198 ? "" 199 : ( 200 LABEL_COLOR + " Entity-Signature " + RESET + '\n' + 201 StrIndent.indent((signature.trim().replace("\t", " ")), 4) + '\n' + 202 BLUE_LINE 203 ); 204 205 final String topNote = (oneLinerNote != null) 206 ? (LABEL_COLOR + ' ' + oneLinerNote.trim() + ' ' + RESET + 207 " (Exception Thrown)\n") 208 : ( 209 LABEL_COLOR + ' ' + 210 (FATAL ? "Fatal " : "") + 211 "Error, Exception Thrown " + RESET + '\n' 212 ); 213 214 final String exceptionStr = (FATAL || showST) 215 ? EXCC.toString(t) 216 : ( 217 LABEL_COLOR + " Exception-Name " + RESET + " " + 218 BRED + t.getClass().getCanonicalName() + 219 RESET +'\n' + 220 LABEL_COLOR + " Exception-Message " + RESET + ' ' + 221 t.getMessage() + '\n' + 222 LABEL_COLOR + " Abbreviated-Trace " + RESET + ' ' + 223 (DEBUGGING ? " (Debugging-Mode On, Abbreviation Off)" : "") + 224 '\n' + 225 (DEBUGGING ? EXCC.toString(t, 4) : EXCC.toStringMaxTraces(t, 2, 4)) 226 ); 227 228 229 // String.trim() ==> It trims the UNIX Escape-Sequence Character '\u001B' 230 // It is not supposed to, acording to Chat-GPT !! But it does anyway! 231 // 232 // System.out.println(exceptionStr.trim()); 233 // System.out.println(exceptionStr.replaceAll("^[\\s]+|[\\s]+$", "")); 234 // Torello.Java.Q.BP(); 235 236 this.printRecord.sb 237 .append( 238 StrIndent.indent( 239 StrPrint.wrapToIndentationPlus( 240 topNote + 241 BLUE_LINE + 242 exceptionStr 243 .replaceAll("^[\\s]+|[\\s]+$", "") // Cannot use 'trim()' 244 .replace("\t", " ") + 245 '\n' + 246 BLUE_LINE + 247 message 248 .replaceAll("^[\\s]+|[\\s]+$", "") // Cannot use 'trim()' 249 .replace("\t", " ") + 250 '\n' + 251 BLUE_LINE + 252 sigStr, 253 100, 254 100, 255 4 256 ), 257 this.printRecord.getIndentation() 258 )) 259 .append('\n'); 260 } 261 262 263 // ******************************************************************************************** 264 // ******************************************************************************************** 265 // Warning 266 // ******************************************************************************************** 267 // ******************************************************************************************** 268 269 270 // Does not wahave a "Throwable" 271 void WARNING( 272 final String message, 273 final Where_Am_I WHERE_AM_I 274 ) 275 { 276 this.printRecord.incWarningCount(); 277 278 this.printHeading.printHeadingIfNecessary(WHERE_AM_I); 279 280 this.printRecord.sb 281 .append( 282 StrPrint.wrapToIndentationPlus( 283 this.printRecord.getIndentationStr() + 284 LABEL_COLOR + " Warning " + RESET + ' ' + 285 286 StrIndent.indentAfter2ndLine( 287 message.replace("\t", " "), 288 4 + this.printRecord.getIndentation(), 289 true, 290 true 291 ), 292 100, 293 100, 294 4 295 ) + 296 '\n' 297 ) 298 .append('\n'); 299 } 300}