001package Torello.Java.Additional; 002 003import Torello.JavaDoc.JDHeaderBackgroundImg; 004import Torello.Java.Verbosity; 005 006// Used for the JavaDoc '@see' tag, a few lines directly-below 007import Torello.HTML.Tools.Images.ImageScraper; 008 009/** 010 * Another Logging-Helper class. This interface builds on the {@link AppendableSafe} class, and 011 * in this case it meaans that the internal {@code Appendable} that is wrapped by this one is an 012 * instance of {@link AppendableSafe} - <I>rather than the Standard-Java 013 * {@code java.lang.Appendable} interface</I>. 014 * 015 * <BR /><BR />The purpose of the {@link AppendableSafe} class is merely to prevent Java's 016 * Checked-Exception {@code 'IOException'}, and replace it with any number of unchecked 017 * {@code Throwable} options. The purpose of this class is merely to add several convenience 018 * fields ({@link #hasLog} and {@link#level}) so that in the course of writing output-log code, a 019 * programmer is not bogged-down with 'Verbose Log Code' (Logging code that is, itself, extremely 020 * verbose-looking). 021 * 022 * @see ImageScraper 023 * @see AppendableSafe 024 */ 025@JDHeaderBackgroundImg(EmbedTagFileID={"APPENDABLE_EXTENSION", "APPENDABLE_LOG_JDHBI"}) 026public class AppendableLog implements Appendable 027{ 028 // ******************************************************************************************** 029 // ******************************************************************************************** 030 // Fields 031 // ******************************************************************************************** 032 // ******************************************************************************************** 033 034 035 /** Four space-characters. */ 036 public static final String I4 = " "; 037 038 /** Eight space-characters. */ 039 public static final String I8 = I4 + I4; 040 041 /** Twelve space-characters. */ 042 public static final String I12 = I8 + I4; 043 044 /** Sixteen space-characters. */ 045 public static final String I16 = I8 + I8; 046 047 /** 048 * The actual log, itself. 049 * 050 * <BR /><BR />This field may be passed and assigned null by the constructor. The user should 051 * be aware to take some care if null log's are allowed in your code. This just means that 052 * there are circumstances where logging is to be "turned off". In such cases, make sure to 053 * write code that chcks whether the log is null before printing to it. (Make sure to avoid 054 * throwing {@code NullPointerException}) 055 * 056 * <BR /><BR />This is an instance of {@link AppendableSafe} because the actual class 057 * {@code java.lang.Appendable} has methods all of which throw {@code IOException}. The 058 * {@link AppendableSafe} class wraps those method calls and blocks the unchecked 059 * {@code IOException's}. 060 * 061 * @see AppendableSafe 062 */ 063 public final AppendableSafe log; 064 065 /** 066 * Simple way for the user to identify whether or not a null {@code 'appendable'} parameter was 067 * passed to this class Constructor. If null was passed to {@link #log}, then this 068 * {@code boolean} will be false. 069 */ 070 public final boolean hasLog; 071 072 /** This is nothing more than the enum {@link Verbosity} field {@link Verbosity#level}. */ 073 public final int level; 074 075 076 // ******************************************************************************************** 077 // ******************************************************************************************** 078 // Constructor 079 // ******************************************************************************************** 080 // ******************************************************************************************** 081 082 083 /** 084 * Construct an instance of this class. The {@code 'appendable'} parameter, if non-null, is 085 * immediately wrapped into an {@link AppendableSafe} instance, and configured to throw 086 * {@link AppendableError} rather than {@code IOException} when / if the internal method throws 087 * any {@code IOException's}. 088 * 089 * @param appendable This may be any instance of {@code java.lang.Appendable}. 090 * 091 * @param verbosity An instance of the {@link Verbosity} enum. If parameter 092 * {@code 'appendable'} is null, then this paramter may also be null. However if 093 * {@code 'appendable'} is non-null, then this may not be null either - or an exception shall 094 * throw. 095 * 096 * @throws NullPointerException If parameter {@code 'appendable'} is non-null, but parameter 097 * {@code 'verbosity'} is null, then a {@code NullPointerException} will throw. 098 */ 099 public AppendableLog(Appendable appendable, Verbosity verbosity) 100 { 101 if (appendable == null) 102 { 103 this.log = null; 104 this.hasLog = false; 105 this.level = 0; 106 } 107 108 else 109 { 110 this.log = new AppendableSafe(appendable, AppendableSafe.USE_APPENDABLE_ERROR); 111 this.hasLog = true; 112 this.level = verbosity.level; // throws NPE 113 } 114 } 115 116 /** 117 * Construct an instance of this class. Since there are several ways to configure the internal 118 * {@link AppendableSafe} instance, this constructor allows a user to simply pass an already 119 * built instance of {@code AppendableSafe} as a parameter. 120 * 121 * @param appendableSafe This may be any instance of {@link AppendableSafe}. The primary 122 * purpose of this class is to shunt the {@code IOException} that is thrown by 123 * {@code java.lang.Appendable} methods, and either suppress them, or re-wrap them into an 124 * unchecked-{@code Throwable}. 125 * 126 * <BR /><BR />Being able to leave off the {@code throws IOException} when writing log 127 * code makes the process much easier. 128 * 129 * @param verbosity An instance of the {@link Verbosity} enum. If parameter 130 * {@code 'appendableSafe'} is null, then this paramter may also be null. However if 131 * {@code 'appendableSafe'} is non-null, then this may not be null either - or an exception 132 * shall throw. 133 * 134 * @throws NullPointerException If parameter {@code 'appendableSafe'} is non-null, but 135 * parameter {@code 'verbosity'} is null, then a {@code NullPointerException} will throw. 136 */ 137 public AppendableLog(AppendableSafe appendableSafe, Verbosity verbosity) 138 { 139 if (appendableSafe == null) 140 { 141 this.log = null; 142 this.hasLog = false; 143 this.level = 0; 144 } 145 146 else 147 { 148 this.log = appendableSafe; 149 this.hasLog = true; 150 this.level = verbosity.level; // throws NPE 151 } 152 } 153 154 155 // ******************************************************************************************** 156 // ******************************************************************************************** 157 // java.lang.Appendable Methods 158 // ******************************************************************************************** 159 // ******************************************************************************************** 160 161 162 /** 163 * Appends the specified character to this {@code Appendable}. 164 * 165 * <BR /><BR /><SPAN CLASS=CopiedJDK>Description copied from class: 166 * {@code java.lang.Appendable}, <B>JDK 1.8</B></SPAN> 167 * 168 * @param c The character to append 169 * @return A reference to this {@code Appendable}. 170 * 171 * @throws NullPointerException If the {@code AppendableSafe} instance field ({@link #log}) was 172 * passed null during construction of {@code 'this'} instance. 173 */ 174 public AppendableSafe append(char c) 175 { return this.log.append(c); } 176 177 /** 178 * Appends the specified character sequence to this {@code Appendable}. 179 * 180 * <BR /><BR />Depending on which class implements the character sequence {@code 'csq'}, the 181 * entire sequence may not be appended. For instance, if {@code 'csq'} is a 182 * {@code 'CharBuffer'} the subsequence to append is defined by the buffer's position and limit. 183 * 184 * <BR /><BR /><SPAN CLASS=CopiedJDK>Description copied from class: 185 * {@code java.lang.Appendable}, <B>JDK 1.8</B></SPAN> 186 * 187 * @param csq The character sequence to append. If csq is null, then the four characters "null" 188 * are appended to this {@code Appendable}. 189 * 190 * @return A reference to this {@code Appendable}. 191 * 192 * @throws NullPointerException If the {@code AppendableSafe} instance field ({@link #log}) was 193 * passed null during construction of {@code 'this'} instance. 194 */ 195 public AppendableSafe append(CharSequence csq) 196 { return this.log.append(csq); } 197 198 /** 199 * Appends a subsequence of the specified character sequence to this {@code Appendable}. 200 * 201 * <BR /><BR />An invocation of this method of the form {@code out.append(csq, start, end)} 202 * when {@code 'csq'} is not null, behaves in exactly the same way as the invocation: 203 * 204 * <DIV CLASS=LOC>{@code 205 * out.append(csq.subSequence(start, end)) 206 * }</DIV> 207 * 208 * <BR /><BR /><SPAN CLASS=CopiedJDK>Description copied from class: 209 * {@code java.lang.Appendable}, <B>JDK 1.8</B></SPAN> 210 * 211 * @param csq The character sequence from which a subsequence will be appended. If csq is null, 212 * then the four characters "null" are appended to this {@code Appendable}. 213 * 214 * @param start The index of the first character in the subsequence 215 * @param end The index of the character following the last character in the subsequence 216 * 217 * @return A reference to this {@code Appendable}. 218 * 219 * @throws NullPointerException If the {@code AppendableSafe} instance field ({@link #log}) was 220 * passed null during construction of {@code 'this'} instance. 221 */ 222 public AppendableSafe append(CharSequence csq, int start, int end) 223 { return this.log.append(csq, start, end); } 224 225 226 // ******************************************************************************************** 227 // ******************************************************************************************** 228 // More Appendable Methods 229 // ******************************************************************************************** 230 // ******************************************************************************************** 231 232 233 /** 234 * Appends four character spaces of indentation, and then appends {@code String}-parameter 235 * {@code's'}. 236 * 237 * @return A reference to this {@code Appendable}. 238 * 239 * @throws NullPointerException If the {@code AppendableSafe} instance field ({@link #log}) was 240 * passed null during construction of {@code 'this'} instance. 241 */ 242 public AppendableSafe appendI4(String s) 243 { return this.log.append(I4).append(s); } 244 245 /** 246 * Appends eight character spaces of indentation, and then appends {@code String}-parameter 247 * {@code's'}. 248 * 249 * @return A reference to this {@code Appendable}. 250 * 251 * @throws NullPointerException If the {@code AppendableSafe} instance field ({@link #log}) was 252 * passed null during construction of {@code 'this'} instance. 253 */ 254 public AppendableSafe appendI8(String s) 255 { return this.log.append(I8).append(s); } 256 257 /** 258 * Appends twelve character spaces of indentation, and then appends {@code String}-parameter 259 * {@code's'}. 260 * 261 * @return A reference to this {@code Appendable}. 262 * 263 * @throws NullPointerException If the {@code AppendableSafe} instance field ({@link #log}) was 264 * passed null during construction of {@code 'this'} instance. 265 */ 266 public AppendableSafe appendI12(String s) 267 { return this.log.append(I12).append(s); } 268 269 /** 270 * Appends sixteen character spaces of indentation, and then appends {@code String}-parameter 271 * {@code's'}. 272 * 273 * @return A reference to this {@code Appendable}. 274 * 275 * @throws NullPointerException If the {@code AppendableSafe} instance field ({@link #log}) was 276 * passed null during construction of {@code 'this'} instance. 277 */ 278 public AppendableSafe appendI16(String s) 279 { return this.log.append(I16).append(s); } 280 281 282 // ******************************************************************************************** 283 // ******************************************************************************************** 284 // Boolean-Test Methods 285 // ******************************************************************************************** 286 // ******************************************************************************************** 287 288 289 /** 290 * Quick check that can be used to test whether or not to print to a log. The purpose of an 291 * instance of {@link Verbosity} is that logging information is only printed to an output log 292 * if the user has requested a certain level of verbosity. 293 * 294 * <BR /><BR />This method will return {@code TRUE} if the user has requested logging, and 295 * this instance' internal {@link #level} field is equal to parameter {@code 'level'}. 296 * 297 * @param level An integer that should correspond to the enum {@link Verbosity} internal field 298 * {@link Verbosity#level}. 299 * 300 * @return {@code TRUE} if - 301 * 302 * <BR /><BR /><UL CLASS=JDUL> 303 * <LI><B>{@link #hasLog}</B> is also {@code TRUE}</LI> 304 * <LI><B>{@link #level}</B> equals value passed to parameter {@code 'level'}</LI> 305 * </UL> 306 * 307 * <BR />Returns {@code FALSE} otherwise 308 */ 309 public boolean levelEQ(int level) 310 { 311 if (hasLog) return (this.level == level); 312 return false; 313 } 314 315 /** 316 * Quick check that can be used to test whether or not to print to a log. The purpose of an 317 * instance of {@link Verbosity} is that logging information is only printed to an output log 318 * if the user has requested a certain level of verbosity. 319 * 320 * <BR /><BR />This method will return {@code TRUE} if the user has requested logging, and 321 * this instance' internal {@link #level} field is greater than or equal to parameter 322 * {@code 'level'}. 323 * 324 * @param level An integer that should correspond to the enum {@link Verbosity} internal field 325 * {@link Verbosity#level}. 326 * 327 * @return {@code TRUE} if - 328 * 329 * <BR /><BR /><UL CLASS=JDUL> 330 * 331 * <LI> Field <B>{@link #hasLog}</B> is also {@code TRUE}</LI> 332 * 333 * <LI> Field <B>{@link #level}</B> is greater than or equal to value passed to parameter 334 * {@code 'level'} 335 * </LI> 336 * </UL> 337 * 338 * <BR />Returns {@code FALSE} otherwise 339 */ 340 public boolean levelGTEQ(int level) 341 { 342 if (hasLog) return (this.level >= level); 343 return false; 344 } 345}