
package uk.co.wingpath.io;

import java.io.*;
import uk.co.wingpath.util.*;

/**
* This interface specifies the basic operations to be provided by an I/O
* connection (e.g. socket or serial connection).
* <p>Implementations of this interface are normally thread-safe and
* guarantee atomicity of reads & writes.
*/

public interface Connection
{
    /**
    * Opens the connection.
    * @throws IOException if the connection cannot be opened.
    */
    void open ()
        throws IOException;

    /**
    * Closes the connection.
    */
    void close ();

    /**
    * Tests whether the connection is open.
    * @return {@code true} if the connection is open.
    */
    boolean isOpen ();

    /**
    * Gets the time that a successful read was last performed, or the time
    * that the connection was opened, whichever is the more recent.
    * The time is in nanoseconds, as returned by {@link System #nanoTime}.
    * @return time of last read or open.
    */
    long getTimeLastRead ();

    /**
    * Gets the time that a successful write was last performed, or the time
    * that the connection was opened, whichever is the more recent.
    * The time is in nanoseconds, as returned by {@link System #nanoTime}.
    * @return time of last write or open.
    */
    long getTimeLastWrite ();

    /**
    * Writes <code>length</code> bytes of data to the connection.
    * @param data array containing the data to be written.
    * @param offset offset in <code>data</code> of the first byte to be written.
    * @param length number of bytes to be written.
    * @throws IOException if the connection is closed or an I/O error occurs.
    * The connection may be closed if an I/O error occurs.
    */
    void write (byte [] data, int offset, int length)
        throws IOException, InterruptedException;

    /** Reads up to <code>length</code> bytes of data from the connection
    * into an array of bytes.
    * If <code>length</code> is zero, the method returns zero immediately.
    * Otherwise, if the timeout is exceeded before any bytes
    * have been read then an <code>InterruptedIOException</code> is
    * thrown.
    * Otherwise up to <code>length</code> bytes are read, without any
    * further waiting.
    * @param data the buffer into which the data is read.
    * @param offset the start offset in array <code>data</code> at which
    *   the data is written.
    * @param length the maximum number of bytes to read.
    * @param timeout maximum time (in milliseconds) to wait for data to be
    *   available. A zero timeout means that any data immediately available
    *   should be returned, without any significant waiting.
    * @param first <code>true</code> if the first "chunk" of a message is
    *   being read. <code>false</code> for subsequent chunks.
    * @return the number of bytes read.
    * @throws InterruptedIOException if a timeout occurs.
    * @throws RecoverableIOException if a recoverable error occurs.
    * @throws IOException if the connection is closed or an irrecoverable
    * I/O error occurs.
    * The connection may be closed if an I/O error occurs.
    * @throws InterruptedException if the thread is interrupted.
    */
    int read (byte [] data, int offset, int length, int timeout, boolean first)
        throws IOException, InterruptedIOException, InterruptedException;

    /**
    * Wait for all data written to have been transmitted.
    */
    public void drain ();

    /**
    * Discard any data in output buffers.
    * Note that there may be data in a hardware buffer that is not flushed
    * by this method (this could be regarded as a bug in the kernel device
    * driver).
    */
    public void flush ();

    /**
    * Gets a name that can be used to identify the connection.
    * If a name has been set using setName, that will be returned.
    * Otherwise, an attempt will be made to automatically generate one
    * (e.g. using the serial device name or IP address & port).
    * @return connection name.
    */
    public String getName ();

    /**
    * Sets the name that to be used to identify the connection (e.g. for
    * tracing).
    * @param name connection name.
    */
    public void setName (String name);
}

