001package Torello.Java.Additional; 002 003import Torello.JavaDoc.JDHeaderBackgroundImg; 004import Torello.Java.UnreachableError; 005 006// Used for the JavaDoc '@see' tag, a few lines directly-below 007import Torello.Java.OSCommands; 008 009import java.io.IOException; 010 011/** 012 * Builds a composite {@code java.lang.Appendable} using up to <B STYLE='color: red;'>three</B> 013 * independent input-parameter {@code Appendable's}. Character data appended to an instance of 014 * {@code TriAppendable} will, in turn, be appended to any of the input-{@code Appendable's} which 015 * have been provided to this class' constructor and are non-null. 016 * 017 * <BR /><BR />Passing null input-{@code Appendable's} <B STYLE='color: red;'><I>will not</I></B> 018 * cause this class to fail, and <B STYLE='color: red;'><I>will not</I></B> generate 019 * {@code NullPointerException's}. One of the primary values of this class is that the chunk of 020 * code that tests for a "Null Log" is done inside this class. 021 * 022 * <BR /><BR />The meaning of a "Null Log" is just that a user has decided against logging a tool 023 * or utility's output to any logger, and has passed 'null' to one of the log references in his 024 * code. 025 * 026 * @see OSCommands 027 */ 028@JDHeaderBackgroundImg 029 (EmbedTagFileID={"APPENDABLE_EXTENSION", "TRI_APPENDABLE_JDHBI", "BI_TRI_BOTH_JDHBI"}) 030public class TriAppendable implements Appendable 031{ 032 private final Appendable appendable; 033 034 /** 035 * Creates an instance of this class, using up to three input {@code Appendable's}. 036 * 037 * @param a Any {@code java.lang.Appendable}. This parameter may be null, and if it is it will 038 * be ignored. Passing null here, will not generated a {@code NullPointerException} 039 * 040 * @param b Any {@code java.lang.Appendable}. This parameter may be null, and if it is it will 041 * be ignored. Passing null here, will not generated a {@code NullPointerException} 042 * 043 * @param c Any {@code java.lang.Appendable}. This parameter may be null, and if it is it will 044 * be ignored. Passing null here, will not generated a {@code NullPointerException} 045 */ 046 public TriAppendable(Appendable a, Appendable b, Appendable c) 047 { 048 // Minor coding trick. Pretend this is a base-2 number, with three bits. I think this 049 // improves efficiency a tiny bit, since it isn't comparing the nulls over and over again. 050 // Here it checks the references for nulls only once. 051 052 int theSum = 053 ((a == null) ? 0 : 4) + 054 ((b == null) ? 0 : 2) + 055 ((c == null) ? 0 : 1); 056 057 // if ((a == null) && (b == null) && (c == null)) this.appendable = new Appendable() 058 if (theSum == 0) this.appendable = new Appendable() 059 { 060 public Appendable append(char ch) throws IOException 061 { return this; } 062 063 public Appendable append(CharSequence cs) throws IOException 064 { return this; } 065 066 public Appendable append(CharSequence cs, int start, int end) throws IOException 067 { return this; } 068 }; 069 070 // else if ((a == null) && (b == null) && (c != null)) this.appendable = new Appendable() 071 else if (theSum == 1) this.appendable = new Appendable() 072 { 073 public Appendable append(char ch) throws IOException 074 { c.append(ch); return this; } 075 076 public Appendable append(CharSequence cs) throws IOException 077 { c.append(cs); return this; } 078 079 public Appendable append(CharSequence cs, int start, int end) throws IOException 080 { c.append(cs, start, end); return this; } 081 }; 082 083 // else if ((a == null) && (b != null) && (c == null)) this.appendable = new Appendable() 084 else if (theSum == 2) this.appendable = new Appendable() 085 { 086 public Appendable append(char ch) throws IOException 087 { b.append(ch); return this; } 088 089 public Appendable append(CharSequence cs) throws IOException 090 { b.append(cs); return this; } 091 092 public Appendable append(CharSequence cs, int start, int end) throws IOException 093 { b.append(cs, start, end); return this; } 094 }; 095 096 // else if ((a == null) && (b != null) && (c != null)) this.appendable = new Appendable() 097 else if (theSum == 3) this.appendable = new Appendable() 098 { 099 public Appendable append(char ch) throws IOException 100 { b.append(ch); c.append(ch); return this; } 101 102 public Appendable append(CharSequence cs) throws IOException 103 { b.append(cs); c.append(cs); return this; } 104 105 public Appendable append(CharSequence cs, int start, int end) throws IOException 106 { b.append(cs, start, end); c.append(cs, start, end); return this; } 107 }; 108 109 // else if ((a != null) && (b == null) && (c == null)) this.appendable = new Appendable() 110 else if (theSum == 4) this.appendable = new Appendable() 111 { 112 public Appendable append(char ch) throws IOException 113 { a.append(ch); return this; } 114 115 public Appendable append(CharSequence cs) throws IOException 116 { a.append(cs); return this; } 117 118 public Appendable append(CharSequence cs, int start, int end) throws IOException 119 { a.append(cs, start, end); return this; } 120 }; 121 122 // else if ((a != null) && (b == null) && (c != null)) this.appendable = new Appendable() 123 else if (theSum == 5) this.appendable = new Appendable() 124 { 125 public Appendable append(char ch) throws IOException 126 { a.append(ch); c.append(ch); return this; } 127 128 public Appendable append(CharSequence cs) throws IOException 129 { a.append(cs); c.append(cs); return this; } 130 131 public Appendable append(CharSequence cs, int start, int end) throws IOException 132 { a.append(cs, start, end); c.append(cs, start, end); return this; } 133 }; 134 135 // else if ((a != null) && (b != null) && (c == null)) this.appendable = new Appendable() 136 else if (theSum == 6) this.appendable = new Appendable() 137 { 138 public Appendable append(char ch) throws IOException 139 { a.append(ch); b.append(ch); return this; } 140 141 public Appendable append(CharSequence cs) throws IOException 142 { a.append(cs); b.append(cs); return this; } 143 144 public Appendable append(CharSequence cs, int start, int end) throws IOException 145 { a.append(cs, start, end); b.append(cs, start, end); return this; } 146 }; 147 148 // else if ((a != null) && (b != null) && (c != null)) this.appendable = new Appendable() 149 else if (theSum == 7) this.appendable = new Appendable() 150 { 151 public Appendable append(char ch) throws IOException 152 { a.append(ch); b.append(ch); c.append(ch); return this; } 153 154 public Appendable append(CharSequence cs) throws IOException 155 { a.append(cs); b.append(cs); c.append(cs); return this; } 156 157 public Appendable append(CharSequence cs, int start, int end) throws IOException 158 { a.append(cs, start, end); b.append(cs, start, end); c.append(cs, start, end); return this; } 159 }; 160 161 // This appears (on cursory inspection) very "unreachable". However the java compiler 162 // doesn't seem to like it! (javac complains without this last line) 163 164 else throw new UnreachableError(); 165 } 166 167 /** 168 * Logs a {@code char} (input-parameter {@code 'ch'}) to any / all non-null 169 * {@code Appendable's} that were passed to this class' constructor. 170 * 171 * @param ch Any Java Character 172 * 173 * @throws IOException Throws if any of the underlying {@code Appendable's} throw 174 * {@code IOException} upon having their corresponding {@code append()}-method invoked. 175 */ 176 public Appendable append(char ch) throws IOException 177 { return this.appendable.append(ch); } 178 179 /** 180 * Logs a {@code CharSequence} (input-parameter {@code 'cs'}) to any / all non-null 181 * {@code Appendable's} that were passed to this class' constructor. 182 * 183 * @param cs Any Java {@code CharSequence} 184 * 185 * @throws IOException Throws if any of the underlying {@code Appendable's} throw 186 * {@code IOException} upon having their corresponding {@code append()}-method invoked. 187 */ 188 public Appendable append(CharSequence cs) throws IOException 189 { return this.appendable.append(cs); } 190 191 /** 192 * Logs a partial / substring {@code CharSequence} (input-parameter {@code 'cs'}) to any / all 193 * non-null {@code Appendable's} that were passed to this class' constructor. 194 * 195 * @param cs Any Java {@code CharSequence} 196 * 197 * @param start Position within {@code 'cs'} of the {@code substring's} first character to be 198 * appended 199 * 200 * @param end Position within {@code 'cs'} of the {@code substring's} last character to be 201 * appended 202 * 203 * @throws IOException Throws if any of the underlying {@code Appendable's} throw 204 * {@code IOException} upon having their corresponding {@code append()}-method invoked. 205 */ 206 public Appendable append(CharSequence cs, int start, int end) throws IOException 207 { return this.appendable.append(cs, start, end); } 208} 209