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;'>two</B> 013 * independent input-parameter {@code Appendable's}. Character data appended to an instance of 014 * {@code BiAppendable} 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", "BI_APPENDABLE_JDHBI", "BI_TRI_BOTH_JDHBI"}) 030public class BiAppendable implements Appendable 031{ 032 private final Appendable appendable; 033 034 /** 035 * Creates an instance of this class, using up to two 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 public BiAppendable(Appendable a, Appendable b) 044 { 045 // Minor coding trick. Pretend this is a base-2 number, with three bits. I think this 046 // improves efficiency a tiny bit, since it isn't comparing the nulls over and over again. 047 // Here it checks the references for nulls only once. 048 049 int theSum = 050 ((a == null) ? 0 : 2) + 051 ((b == null) ? 0 : 1); 052 053 // if ((a == null) && (b == null)) this.appendable = new Appendable() 054 if (theSum == 0) this.appendable = new Appendable() 055 { 056 public Appendable append(char ch) throws IOException 057 { return this; } 058 059 public Appendable append(CharSequence cs) throws IOException 060 { return this; } 061 062 public Appendable append(CharSequence cs, int start, int end) throws IOException 063 { return this; } 064 }; 065 066 // else if ((a == null) && (b != null)) this.appendable = new Appendable() 067 else if (theSum == 1) this.appendable = new Appendable() 068 { 069 public Appendable append(char ch) throws IOException 070 { b.append(ch); return this; } 071 072 public Appendable append(CharSequence cs) throws IOException 073 { b.append(cs); return this; } 074 075 public Appendable append(CharSequence cs, int start, int end) throws IOException 076 { b.append(cs, start, end); return this; } 077 }; 078 079 // else if ((a != null) && (b == null)) this.appendable = new Appendable() 080 else if (theSum == 2) this.appendable = new Appendable() 081 { 082 public Appendable append(char ch) throws IOException 083 { a.append(ch); return this; } 084 085 public Appendable append(CharSequence cs) throws IOException 086 { a.append(cs); return this; } 087 088 public Appendable append(CharSequence cs, int start, int end) throws IOException 089 { a.append(cs, start, end); return this; } 090 }; 091 092 // else if ((a != null) && (b != null)) this.appendable = new Appendable() 093 else if (theSum == 3) this.appendable = new Appendable() 094 { 095 public Appendable append(char ch) throws IOException 096 { a.append(ch); b.append(ch); return this; } 097 098 public Appendable append(CharSequence cs) throws IOException 099 { a.append(cs); b.append(cs); return this; } 100 101 public Appendable append(CharSequence cs, int start, int end) throws IOException 102 { a.append(cs, start, end); b.append(cs, start, end); return this; } 103 }; 104 105 // This appears (on cursory inspection) very "unreachable". However the java compiler 106 // doesn't seem to like it! (javac complains without this last line) 107 108 else throw new UnreachableError(); 109 } 110 111 /** 112 * Logs a {@code char} (input-parameter {@code 'ch'}) to any / all non-null 113 * {@code Appendable's} that were passed to this class' constructor. 114 * 115 * @param ch Any Java Character 116 * 117 * @throws IOException Throws if any of the underlying {@code Appendable's} throw 118 * {@code IOException} upon having their corresponding {@code append()}-method invoked. 119 */ 120 public Appendable append(char ch) throws IOException 121 { return this.appendable.append(ch); } 122 123 /** 124 * Logs a {@code CharSequence} (input-parameter {@code 'cs'}) to any / all non-null 125 * {@code Appendable's} that were passed to this class' constructor. 126 * 127 * @param cs Any Java {@code CharSequence} 128 * 129 * @throws IOException Throws if any of the underlying {@code Appendable's} throw 130 * {@code IOException} upon having their corresponding {@code append()}-method invoked. 131 */ 132 public Appendable append(CharSequence cs) throws IOException 133 { return this.appendable.append(cs); } 134 135 /** 136 * Logs a partial / substring {@code CharSequence} (input-parameter {@code 'cs'}) to any / all 137 * non-null {@code Appendable's} that were passed to this class' constructor. 138 * 139 * @param cs Any Java {@code CharSequence} 140 * 141 * @param start Position within {@code 'cs'} of the {@code substring's} first character to be 142 * appended 143 * 144 * @param end Position within {@code 'cs'} of the {@code substring's} last character to be 145 * appended 146 * 147 * @throws IOException Throws if any of the underlying {@code Appendable's} throw 148 * {@code IOException} upon having their corresponding {@code append()}-method invoked. 149 */ 150 public Appendable append(CharSequence cs, int start, int end) throws IOException 151 { return this.appendable.append(cs, start, end); } 152}