001package Torello.Java.Additional;
002
003import Torello.JavaDoc.JDHeaderBackgroundImg;
004
005import java.io.IOException;
006
007/**
008 * An implementation of the standard Java <CODE>'Appendable'</CODE> interface that keeps an
009 * internal log of all text-data that 'passes through' the <CODE>Appendable</CODE>.
010 * 
011 * <EMBED CLASS='external-html' DATA-FILE-ID=APPENDABLE_TAP>
012 */
013@JDHeaderBackgroundImg(EmbedTagFileID={"APPENDABLE_EXTENSION", "APPENDABLE_TAP_JDHBI"})
014public class AppendableTap implements Appendable
015{
016    private Appendable outputAppendable;
017
018    private StringBuffer sb = new StringBuffer();
019
020    /**
021     * Builds an instance of this class.  The provided instance of {@code Appendable}
022     * will receive all {@code append()} invocations that are sent to {@code 'this'}
023     * instance of {@code AppendTap}.  It is important to note that only the 
024     * {@code append()} calls sent to <B>this</B> class first will be 'tapped' (logged
025     * and kept in an internal {@code StringBuffer} instance).  Any invocations that are
026     * made independently on the provided {@code Appendable} <I>will not be saved by this
027     * class.</I>
028     *
029     * @param appendable This may be any java {@code Appendable}.  Any messages sent to this
030     * class will be sent to this input {@code Appendable} as well.
031     */
032    public AppendableTap(Appendable appendable)
033    { this.outputAppendable = appendable; }
034
035    /**
036     * Logs input-parameter character {@code 'c'} to an internal {@code StringBuffer}, and then
037     * subsequently sends {@code 'c'} to the user-provided {@code Appendable}.
038     *
039     * @param c Any character data.
040     *
041     * @return {@code 'this'} instance of {@code AppendableTap} shall be returned, for convenience.
042     */
043    public synchronized Appendable append(char c) throws IOException
044    {
045        sb.append(c); 
046        return outputAppendable.append(c);
047    }
048
049    /**
050     * Logs input-parameter {@code CharSequence 's'} to an internal {@code StringBuffer}, and
051     * then subsequently sends {@code 's'} to the user-provided {@code Appendable}.
052     *
053     * @param s Any {@code String} data.
054     *
055     * @return {@code 'this'} instance of {@code AppendableTap} shall be returned, for convenience.
056     */
057    public synchronized Appendable append(CharSequence s) throws IOException
058    {
059        sb.append(s);
060        return outputAppendable.append(s);
061    }
062
063    /**
064     * Logs a substring of input-parameter {@code CharSequence 's'} defined by the {@code int}
065     * parameters {@code 'start'} and {@code 'end'}.
066     * 
067     * This operation would be equivalent to calling the {@code String} method
068     * {@code String.substring(start, end)} on the input {@code CharSequence} prior to logging
069     * this character data, and sending it to the user-provided {@code Appendable}.
070     *
071     * @param s This may be any Java {@code CharSequence}
072     *
073     * @param start The first character (inclusive) in the sub-string / sub-sequence of the input 
074     * {@code CharSequence} to log, and pass-on.
075     *
076     * @param end The last character (exclusive) of the input sub-string / sub-sequence of the
077     * {@code CharSequence} to log, and pass-on.
078     *
079     * @return {@code 'this'} instance of {@code AppendableTap} shall be returned, for convenience.
080     */
081    public synchronized Appendable append(CharSequence s, int start, int end) throws IOException
082    { 
083        sb.append(s, start, end); 
084        return outputAppendable.append(s, start, end);
085    }
086
087    /**
088     * Retrieves the text-data that has been sent to this {@code AppendableTap}
089     * 
090     * <BR /><BR /><B>NOTE:</B> Invoking this method has no effect on the underlying
091     * output (user-provided - at construction time) {@code Appendable}.
092     *
093     * @return Any character or text data that has been received by {@code 'this'} instance
094     * of {@code AppendableTap} through any of its {@code append(...)} methods.
095     */
096    public synchronized String getString()
097    {
098        String s = sb.toString();
099        sb.setLength(0);
100        sb.append(s);
101        return s;
102    }
103
104    /**
105     * Resets or 'clears' the contents of the internal {@code StringBuffer} 'tap', and returns
106     * the contents that were saved.
107     * @return Returns the contents of the internal storage, and clears the contents.
108     */
109    public synchronized String poll()
110    {
111        String s = sb.toString();
112        sb.setLength(0);
113        return s;
114    }
115
116    /** Clears the 'tap' of all contents */
117    public synchronized void clear() { sb.setLength(0); }
118}