/* Copyright (c) 2001-2010, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb.lib;

import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.Writer;

/**
 * @todo - finer-grained synchronization to reduce average
 * potential monitor contention
 */

/**
 * Provides Closable semantics ordinarily missing in a
 * {@link java.io.CharArrayWriter}. <p>
 *
 * Accumulates output in a character array that automatically grows as needed.<p>
 *
 * Data is retrieved using <tt>toCharArray()</tt>, <tt>toCharArrayReader()</tt>
 * and <tt>toString()</tt>. <p>
 *
 * {@link #close() Closing} a <tt>ClosableCharArrayWriter</tt> prevents
 * further write operations, but all other operations will succeed until after
 * the first invocation of {@link #free() free()}.<p>
 *
 * Freeing a <tt>ClosableCharArrayWriter</tt> closes the writer and
 * releases its internal buffer, preventing successful invocation of all
 * operations, with the exception of <tt>size()<tt>, <tt>close()</tt>,
 * <tt>isClosed()</tt>, <tt>free()</tt> and <tt>isFreed()</tt>. <p>
 *
 * This class is especially useful when an accumulating writer must be
 * handed off to an extenal client under contract that the writer should
 * exhibit true Closable behaviour, both in response to internally tracked
 * events and to client invocation of the <tt>Writer.close()</tt> method.
 *
 * @author boucherb@users
 * @version 1.8.x
 * @since 1.8.x
 */
public class ClosableCharArrayWriter extends Writer {

    /**
     * Data buffer.
     */
    protected char[] buf;

    /**
     * # of valid characters in buffer.
     */
    protected int count;

    /**
     * Whether this writer is closed.
     */
    protected boolean closed;

    /**
     * Whether this writer is freed.
     */
    protected boolean freed;

    /**
     * Creates a new writer. <p>
     *
     * The buffer capacity is initially 32 characters, although its size
     * automatically increases when necessary.
     */
    public ClosableCharArrayWriter() {
        this(32);
    }

    /**
     * Creates a new writer with a buffer capacity of the specified
     * <tt>size</tt>, in characters.
     *
     * @param size the initial size.
     * @exception IllegalArgumentException if <tt>size</tt> is negative.
     */
    public ClosableCharArrayWriter(int size) throws IllegalArgumentException {

        if (size < 0) {
            throw new IllegalArgumentException("Negative initial size: "
                                               + size);    // NOI18N
        }

        buf = new char[size];
    }

    /**
     * Writes the specified single character.
     *
     * @param c the single character to be written.
     * @throws java.io.IOException if an I/O error occurs.
     *      In particular, an <tt>IOException</tt> may be thrown
     *      if this writer has been {@link #close() closed}.
     */
    public synchronized void write(int c) throws IOException {

        checkClosed();

        int newcount = count + 1;

        if (newcount > buf.length) {
            buf = copyOf(buf, Math.max(buf.length << 1, newcount));
        }

        buf[count] = (char) c;
        count      = newcount;
    }

    /**
     * Writes the designated portion of the designated character array <p>.
     *
     * @param c the source character sequence.
     * @param off the start offset in the source character sequence.
     * @param len the number of characters to write.
     * @throws java.io.IOException if an I/O error occurs.
     *      In particular, an <tt>IOException</tt> may be thrown
     *      if this writer has been {@link #close() closed}.
     */
    public synchronized void write(char c[], int off,
                                   int len) throws IOException {

        checkClosed();

        if ((off < 0) || (off > c.length) || (len < 0)
                || ((off + len) > c.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }

        int newcount = count + len;

        if (newcount > buf.length) {
            buf = copyOf(buf, Math.max(buf.length << 1, newcount));
        }

        System.arraycopy(c, off, buf, count, len);

        count = newcount;
    }

    /**
     * Efficiently writes the designated portion of the designated string. <p>
     *
     * The operation occurs as if by calling
     * <tt>str.getChars(off, off + len, buf, count)</tt>. <p>
     *
     * @param str the string from which to write
     * @param off the start offset in the string.
     * @param len the number of characters to write.
     * @throws java.io.IOException if an I/O error occurs.
     *      In particular, an <tt>IOException</tt> may be thrown
     *      if this writer has been {@link #close() closed}.
     */
    public synchronized void write(String str, int off,
                                   int len) throws IOException {

        checkClosed();

        int strlen = str.length();

        if ((off < 0) || (off > strlen) || (len < 0) || ((off + len) > strlen)
                || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }

        int newcount = count + len;

        if (newcount > buf.length) {
            buf = copyOf(buf, Math.max(buf.length << 1, newcount));
        }

        str.getChars(off, off + len, buf, count);

        count = newcount;
    }

    /**
     * By default, does nothing. <p>
     *
     * @throws java.io.IOException if an I/O error occurs.
     *      In particular, an <tt>IOException</tt> may be thrown
     *      if this writer has been {@link #close() closed}.
     */
    public void flush() throws IOException {
        checkClosed();
    }

    /**
     * Writes the complete contents of this writer's buffered data to the
     * specified writer. <p>
     *
     * The operation occurs as if by calling <tt>out.write(buf, 0, count)</tt>.
     *
     * @param out the writer to which to write the data.
     * @throws java.io.IOException if an I/O error occurs.
     *      In particular, an <tt>IOException</tt> may be thrown
     *      if this writer has been {@link #free() freed}.
     */
    public synchronized void writeTo(Writer out) throws IOException {

        checkFreed();

        if (count > 0) {
            out.write(buf, 0, count);
        }
    }

    /**
     * Returns the current capacity of this writer's data buffer.
     *
     * @return  the current capacity (the length of the internal
     *          data array)
     * @throws java.io.IOException if an I/O error occurs.
     *      In particular, an <tt>IOException</tt> may be thrown
     *      if this writer has been {@link #free() freed}.
     */
    public synchronized int capacity() throws IOException {

        checkFreed();

        return buf.length;
    }

    /**
     * Resets the <tt>count</tt> field of this writer to zero, so that all
     * currently accumulated output is effectively discarded. Further write
     * operations will reuse the allocated buffer space.
     *
     * @see #count
     * @throws java.io.IOException if an I/O error occurs.
     *      In particular, an <tt>IOException</tt> may be thrown
     *      if this output stream has been {@link #close() closed}.
     */
    public synchronized void reset() throws IOException {

        checkClosed();

        count = 0;
    }

    /**
     * Attempts to reduce this writer's buffer capacity to its current size. <p>
     *
     * If the buffer is larger than necessary to hold its current sequence of
     * characters, then it may be resized to become more space efficient.
     * Calling this method may, but is not required to, affect the value
     * returned by a subsequent call to the {@link #capacity()} method.
     */
    public synchronized void trimToSize() throws IOException {

        checkFreed();

        if (buf.length > count) {
            buf = copyOf(buf, count);
        }
    }

    /**
     * Creates a newly allocated character array. Its size is the current
     * size of this writer and the valid contents of the buffer
     * have been copied into it.
     *
     * @return the current contents of this writer, as a character array.
     * @see #size()
     * @throws java.io.IOException if an I/O error occurs.
     *      In particular, an <tt>IOException</tt> may be thrown
     *      if this writer has been {@link #free() freed}.
     */
    public synchronized char[] toCharArray() throws IOException {

        checkFreed();

        return copyOf(buf, count);
    }

    /**
     * Returns the current size of this writer's accumulated character data.
     *
     * @return the value of the <tt>count</tt> field, which is the number
     *      of valid characters accumulated in this writer.
     * @see #count
     * @throws java.io.IOException never
     */
    public synchronized int size() throws IOException {
        return count;
    }

    /**
     * Sets the size of this writer's accumulated character data. <p>
     *
     * @param   newSize the new size of this writer's accumulated data
     * @throws  ArrayIndexOutOfBoundsException if new size is negative
     */
    public synchronized void setSize(int newSize) {

        if (newSize < 0) {
            throw new ArrayIndexOutOfBoundsException(newSize);
        } else if (newSize > buf.length) {
            buf = copyOf(buf, Math.max(buf.length << 1, newSize));
        }

        count = newSize;
    }

    /**
     * Performs an effecient (zero-copy) conversion of the character data
     * accumulated in this writer to a reader. <p>
     *
     * To ensure the integrity of the resulting reader, {@link #free()
     * free} is invoked upon this writer as a side-effect.
     *
     * @return a reader representing this writer's accumulated
     *      character data
     * @throws java.io.IOException if an I/O error occurs.
     *      In particular, an <tt>IOException</tt> may be thrown
     *      if this writer has been {@link #free() freed}.
     */
    public synchronized CharArrayReader toCharArrayReader()
    throws IOException {

        checkFreed();

        CharArrayReader reader = new CharArrayReader(buf, 0, count);

        //System.out.println("toCharArrayReader::buf.length: " + buf.length);
        free();

        return reader;
    }

    /**
     * Converts this writer's accumulated data into a string.
     *
     * @return String constructed from this writer's accumulated data
     * @throws RuntimeException may be thrown if this writer has been
     *      {@link #free() freed}.
     */
    public synchronized String toString() {

        try {
            checkFreed();
        } catch (IOException ex) {
            throw new RuntimeException(ex.toString());
        }

        return new String(buf, 0, count);
    }

    /**
     * Closes this object for further writing. <p>
     *
     * Other operations may continue to succeed until after the first invocation
     * of {@link #free() free()}. <p>
     *
     * @throws java.io.IOException if an I/O error occurs (default: never)
     */
    public synchronized void close() throws IOException {
        closed = true;
    }

    /**
     * @return <tt>true</tt> if this writer is closed, else <tt>false</tt>
     */
    public synchronized boolean isClosed() {
        return closed;
    }

    /**
     * Closes this object and releases the underlying buffer for
     * garbage collection. <p>
     *
     * @throws java.io.IOException if an I/O error occurs while closing
     *      this writer (default: never).
     */
    public synchronized void free() throws IOException {

        closed = true;
        freed  = true;
        buf    = null;
        count  = 0;
    }

    /**
     * @return <tt>true</tt> if this writer is freed; else <tt>false</tt>.
     */
    public synchronized boolean isFreed() {
        return freed;
    }

    /**
     * @throws java.io.IOException if this writer is closed.
     */
    protected synchronized void checkClosed() throws IOException {

        if (closed) {
            throw new IOException("writer is closed.");    // NOI18N
        }
    }

    /**
     * @throws java.io.IOException if this writer is freed.
     */
    protected synchronized void checkFreed() throws IOException {

        if (freed) {
            throw new IOException("write buffer is freed.");    // NOI18N
        }
    }

    /**
     * Retrieves a copy of <tt>original</tt> with the given
     * <tt>newLength</tt>. <p>
     *
     * @param original the object to copy
     * @param newLength the length of the copy
     * @return copy of <tt>original</tt> with the given <tt>newLength</tt>
     */
    protected char[] copyOf(char[] original, int newLength) {

        char[] copy = new char[newLength];

        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));

        return copy;
    }
}
