All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.osgl.util.Output Maven / Gradle / Ivy

The newest version!
package org.osgl.util;

/*-
 * #%L
 * Java Tool
 * %%
 * Copyright (C) 2014 - 2018 OSGL (Open Source General Library)
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;

/**
 * `Output` is an {@link Appendable} with extra methods to append {@link ByteBuffer} and
 * `byte[]`.
 *
 * An `Output` is a stateful object, it can be {@link #open() opened} and {@link #close() closed}.
 *
 * An `Output` instance can create {@link OutputStream} or {@link Writer} based on itself.
 *
 * **Note** the behavior differences between an `Output` and an `Appendable`: when a char sequence
 * is `null`, nothing will be appended to the `Output` while a literal `null` will be appended
 * to the `Appendable`
 *
 * Depending on implementation `Output` might be or not be thread safe.
 */
public interface Output extends Appendable, Closeable, Flushable {

    /**
     * Prepare this `Output` instance for appending. If any append method
     * is called before calling `open()`, then `open()` will be called
     * implicitly before appending happens.
     */
    void open();

    /**
     * Close this `Output` instance. Call to any append method after
     * the `Output` is closed will result in {@link IllegalStateException}
     */
    void close();

    /**
     * Flushes the output.  If the output has saved any characters from the
     * various append() methods in a buffer, write them immediately to their
     * intended destination.  Then, if that destination is another character or
     * byte stream, flush it.  Thus one flush() invocation will flush all the
     * buffers in a chain of Writers and OutputStreams.
     *
     * 

If the intended destination of this output is an abstraction provided * by the underlying operating system, for example a file, then flushing the * stream guarantees only that bytes previously written to the stream are * passed to the operating system for writing; it does not guarantee that * they are actually written to a physical device such as a disk drive. */ void flush(); /** * Appends the specified character sequence to this Output. * *

Depending on which class implements the character sequence * csq, the entire sequence may not be appended. For * instance, if csq is a {@link java.nio.CharBuffer} then * the subsequence to append is defined by the buffer's position and limit. * * @param csq * The character sequence to append. If csq is * null, then nothing will be appended * @return A reference to this Output */ Output append(CharSequence csq); /** * Appends a subsequence of the specified character sequence to this * Output. * *

An invocation of this method of the form out.append(csq, start, * end) when csq is not null, behaves in * exactly the same way as the invocation * *

     *     out.append(csq.subSequence(start, end)) 
* * @param csq * The character sequence from which a subsequence will be * appended. If csq is null, then nothing * will be appended. * @param start * The index of the first character in the subsequence * @param end * The index of the character following the last character in the * subsequence * @return A reference to this Output * @throws IndexOutOfBoundsException * If start or end are negative, start * is greater than end, or end is greater than * csq.length() */ Output append(CharSequence csq, int start, int end); /** * Appends the specified character to this Output. * * @param c * The character to append * @return A reference to this Output */ Output append(char c); /** * Appends a byte array to this `Output`. * * @param bytes * The byte array will be appended. * @return A reference to this `Output` */ Output append(byte[] bytes); /** * Appends a subsequence of the specified byte array to this * Output. * *

An invocation of this method of the form out.append(bytes, start, * end) when bytes is not null, behaves in * exactly the same way as the invocation * *

     *     out.append(csq.subSequence(start, end)) 
* * @param bytes * The byte array from which a subsequence will be * appended. If bytes is null, then nothing * will be appended. * @param start * The index of the first character in the subsequence * @param end * The index of the character following the last character in the * subsequence * @return A reference to this Output * @throws IndexOutOfBoundsException * If start or end are negative, start * is greater than end, or end is greater than * csq.length() */ Output append(byte[] bytes, int start, int end); /** * Appends a byte to this `Output`. * * @param b * A byte will be appended. * @return A reference to this `Output`. */ Output append(byte b); /** * Appends the specified buffer into this Appendable. * * @param buffer * The buffer to append. * @return A reference to this Output */ Output append(ByteBuffer buffer); /** * Create an {@link OutputStream} based on this `Output` instance. * * Calling to this method before calling to any other method including * `asOutputStream()` itself will result in {@link IllegalStateException}. * * @return an {@link OutputStream} reference backed by this `Output`. */ OutputStream asOutputStream(); /** * Create an {@link Writer} based on this `Output` instance. * * Calling to this method before calling to any other method including * `asOutputStream()` itself will result in {@link IllegalStateException}. * * @return an {@link Writer} reference backed by this `Output`. */ Writer asWriter(); class Adaptors { public static Output of(final OutputStream os) { if (os instanceof Output) { return (Output) os; } final Writer w = new OutputStreamWriter(os); return new Output() { @Override public void open() { } @Override public void close() { IO.close(os); } @Override public void flush() { IO.flush(os); } @Override public Output append(CharSequence csq) { IO.append(csq, w); return this; } @Override public Output append(CharSequence csq, int start, int end) { IO.append(csq.subSequence(start, end), w); return this; } @Override public Output append(char c) { IO.append(c, w); return this; } @Override public Output append(byte[] bytes) { IO.append(bytes, os); return this; } @Override public Output append(byte[] bytes, int start, int end) { try { os.write(bytes, start, end); } catch (IOException e) { throw E.ioException(e); } return this; } @Override public Output append(byte b) { IO.append(b, os); return this; } @Override public Output append(ByteBuffer buffer) { int len = buffer.remaining(); byte[] bytes = new byte[len]; buffer.get(bytes); return append(bytes); } @Override public OutputStream asOutputStream() { return os; } @Override public Writer asWriter() { return w; } }; } public static Output of(final Writer w) { final OutputStream os = new WriterOutputStream(w, StandardCharsets.UTF_8); return new Output() { @Override public void open() { } @Override public void close() { IO.close(w); } @Override public void flush() { IO.flush(w); } @Override public Output append(CharSequence csq) { IO.append(csq, w); return this; } @Override public Output append(CharSequence csq, int start, int end) { IO.append(csq.subSequence(start, end), w); return this; } @Override public Output append(char c) { IO.append(c, w); return this; } @Override public Output append(byte[] bytes) { IO.append(bytes, os); return this; } @Override public Output append(byte[] bytes, int start, int end) { try { os.write(bytes, start, end); } catch (IOException e) { throw E.ioException(e); } return this; } @Override public Output append(byte b) { IO.append(b, os); return this; } @Override public Output append(ByteBuffer buffer) { int len = buffer.remaining(); byte[] bytes = new byte[len]; buffer.get(bytes); return append(bytes); } @Override public OutputStream asOutputStream() { return os; } @Override public Writer asWriter() { return w; } }; } public static Output of(final Appendable appendable) { if (appendable instanceof Output) { return (Output) appendable; } return new Output() { @Override public void open() { } @Override public void close() { } @Override public void flush() { } @Override public Output append(CharSequence csq) { if (null == csq) { return this; } try { appendable.append(csq); } catch (IOException e) { throw E.ioException(e); } return this; } @Override public Output append(CharSequence csq, int start, int end) { if (null == csq) { return this; } try { appendable.append(csq, start, end); } catch (IOException e) { throw E.ioException(e); } return this; } @Override public Output append(char c) { try { appendable.append(c); } catch (IOException e) { throw E.ioException(e); } return this; } @Override public Output append(byte[] bytes) { if (null == bytes) { return this; } append(ByteBuffer.wrap(bytes)); return this; } @Override public Output append(byte[] bytes, int start, int end) { append(ByteBuffer.wrap(bytes, start, end)); return this; } @Override public Output append(byte b) { append((char) (b & 0xFF)); return this; } @Override public Output append(ByteBuffer buffer) { try { appendable.append(buffer.asCharBuffer()); } catch (IOException e) { throw E.ioException(e); } return this; } @Override public OutputStream asOutputStream() { return Adaptors.asOutputStream(this); } @Override public Writer asWriter() { return Adaptors.asWriter(this); } }; } public static OutputStream asOutputStream(final Output output) { return new OutputStream() { @Override public void write(int b) { output.append((byte) b); } @Override public void write(byte[] b) { output.append(b); } @Override public void write(byte[] b, int off, int len) { output.append(b, off, len); } @Override public void flush() { output.flush(); } @Override public void close() { output.close(); } }; } public static Writer asWriter(final Output output) { return new Writer() { @Override public void write(char[] c, int off, int len) { if ((off < 0) || (off > c.length) || (len < 0) || ((off + len) > c.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } output.append(CharBuffer.wrap(c, off, len)); } @Override public void flush() { output.flush(); } @Override public void close() { output.close(); } }; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy