gt: 			final int nEvents = dataStore.putEvents(events);
context: package buffer_bci.javaserver.network;
  
  import java.io.BufferedInputStream;
  import java.io.BufferedOutputStream;
  import java.io.IOException;
  import java.net.Socket;
  import java.net.SocketException;
  
  import buffer_bci.javaserver.Buffer;
  import buffer_bci.javaserver.FieldtripBufferMonitor;
  import buffer_bci.javaserver.data.Data;
  import buffer_bci.javaserver.data.DataModel;
  import buffer_bci.javaserver.data.Event;
  import buffer_bci.javaserver.data.Header;
  import buffer_bci.javaserver.exceptions.ClientException;
  import buffer_bci.javaserver.exceptions.DataException;
  
  /**
   * Thread for handling a single connection. Uses NetworkProtocol to
   * encode/decode messages. Uses a shared dataModel object for storing data.
   *
   * @author Wieke Kanters
   *
   */
  public class ConnectionThread extends Thread {
  	private final Socket socket;
  	private final DataModel dataStore;
  	public final String clientAdress;
  	private boolean disconnectedOnPurpose = false;
  	private FieldtripBufferMonitor monitor;
  	public final int clientID;
  	private final Buffer buffer;
  
  	/**
  	 * Constructor
  	 *
  	 * @param socket
  	 *            The socket for the connection.
  	 * @param dataStore
  	 *            The storage for all the data implementing the datamodel
  	 *            interface.
  	 */
  	public ConnectionThread(final int clientID, final Socket socket,
  			final DataModel dataStore, final Buffer buffer) {
  		this.clientID = clientID;
  		this.socket = socket;
  		this.dataStore = dataStore;
  		clientAdress = socket.getInetAddress().toString() + ":"
  				+ Integer.toString(socket.getPort());
  		this.buffer = buffer;
  	}
  
  	/**
  	 * Adds a FiedltripBufferMonitor to this thread.
  	 *
  	 * @param monitor
  	 */
  	public void addMonitor(final FieldtripBufferMonitor monitor) {
  		this.monitor = monitor;
  
  	}
  
  	/**
  	 * Disconnects the client connection and stops the thread.
  	 */
  	public void disconnect() {
  		try {
  			disconnectedOnPurpose = true;
  			socket.close();
  		} catch (final IOException e) {
  		}
  	}
  
  	/**
  	 * Removes all data from the store. Returns appropriate response.
  	 *
  	 * @param message
  	 * @return
  	 */
  	private byte[] handleFlushData(final Message message) {
  		try {
  
  			// Remove all data
  			dataStore.flushData();
  
  			// Return Okay and inform monitor
  			if (monitor != null) {
  				monitor.clientFlushedData(clientID, message.time);
  			}
  			return NetworkProtocol.encodeFlushOkay(message.order);
  
  		} catch (final DataException e) {
  			// Return error
  			return NetworkProtocol.encodeFlushError(message.order);
  
  		}
  	}
  
  	/**
  	 * Removes all events from the store. Returns appropriate response.
  	 *
  	 * @param message
  	 * @return
  	 */
  	private byte[] handleFlushEvents(final Message message) {
  		try {
  
  			// Remove all events
  			dataStore.flushEvents();
  
  			// Return Okay and inform monitor
  			if (monitor != null) {
  				monitor.clientFlushedEvents(clientID, message.time);
  			}
  			return NetworkProtocol.encodeFlushOkay(message.order);
  
  		} catch (final DataException e) {
  			// Return error
  			return NetworkProtocol.encodeFlushError(message.order);
  
  		}
  	}
  
  	/**
  	 * Removes all data from the store. Returns appropriate response.
  	 *
  	 * @param message
  	 * @return
  	 */
  	private byte[] handleFlushHeader(final Message message) {
  		try {
  
  			// Remove the header (and all the data & events);
  			dataStore.flushHeader();
  
  			// Return Okay and inform monitor
  			if (monitor != null) {
  				monitor.clientFlushedHeader(clientID, message.time);
  			}
  			return NetworkProtocol.encodeFlushOkay(message.order);
  
  		} catch (final DataException e) {
  			// Return error
  			return NetworkProtocol.encodeFlushError(message.order);
  
  		}
  	}
  
  	/**
  	 * Gets begin/end from the message and returns the appropriate data.
  	 *
  	 * @param message
  	 * @param input
  	 * @param output
  	 *            @
  	 */
  	private byte[] handleGetData(final Message message) {
  		try {
  
  			Data data;
  
  			// Check if a request for a specific range has been made.
  			if (message.buffer.capacity() > 0) {
  				// Get data request from message
  				final Request request = NetworkProtocol
  						.decodeRequest(message.buffer);
  
  				// Get the requested data
  				data = dataStore.getData(request);
  			} else {
  				data = dataStore.getData();
  			}
  
  			// Inform monitor
  			if (monitor != null) {
  				monitor.clientGetSamples(data.nSamples, clientID, message.time);
  			}
  
  			// Return message containing requested data
  			return NetworkProtocol.encodeData(data, message.order);
  
  		} catch (final DataException e) {
  			// Return error
  			return NetworkProtocol.encodeGetError(message.order);
  		}
  	}
  
  	/**
  	 * Encodes the requested events for sending it to the client.
  	 *
  	 * @param message
  	 * @return
  	 */
  	private byte[] handleGetEvent(final Message message) {
  		try {
  
  			Event[] events;
  
  			// Check if a request for a specific range has been made.
  			if (message.buffer.capacity() > 0) {
  				// Get data request from message
  				final Request request = NetworkProtocol
  						.decodeRequest(message.buffer);
  
  				// Get the requested data
  				events = dataStore.getEvents(request);
  			} else {
  				events = dataStore.getEvents();
  			}
  
  			// Inform monitor
  			if (monitor != null) {
  				monitor.clientGetEvents(events.length, clientID, message.time);
  			}
  
  			// Return message containing requested data
  			return NetworkProtocol.encodeEvents(events, message.order);
  
  		} catch (final DataException e) {
  			// Return error
  			return NetworkProtocol.encodeGetError(message.order);
  		}
  	}
  
  	/**
  	 * Encodes the header for sending it to the client.
  	 *
  	 * @param message
  	 * @param output
  	 *            @
  	 */
  	private byte[] handleGetHeader(final Message message) {
  		try {
  			final Header header = dataStore.getHeader();
  
  			// Inform monitor
  			if (monitor != null) {
  				monitor.clientGetHeader(clientID, message.time);
  			}
  			// Return message containing header
  			return NetworkProtocol.encodeHeader(header, message.order);
  
  		} catch (final DataException e) {
  			// Return error
  			return NetworkProtocol.encodeGetError(message.order);
  
  		}
  	}
  
  	/**
  	 * Grabs data from the message and stores it in the dataStore. Returns
  	 * appropriate response.
  	 *
  	 * @param message
  	 * @param output
  	 *            @
  	 */
  	private byte[] handlePutData(final Message message) {
  		try {
  			// Get data from message
  			final Data data = NetworkProtocol.decodeData(message.buffer);
  
  			// Store data
  			final int nSamples = dataStore.putData(data);
  
  			// Return okay and inform monitor
  			if (monitor != null) {
  				monitor.clientPutSamples(nSamples, clientID, data.nSamples,
  						message.time);
  			}
  			return NetworkProtocol.encodePutOkay(message.order);
  
  		} catch (final ClientException e) {
  			// Return error
  			return NetworkProtocol.encodeGetError(message.order);
  
  		} catch (final DataException e) {
  			// Return error
  			return NetworkProtocol.encodeGetError(message.order);
  
  		}
  
  	}
  
  	/**
  	 * Decodes the events from the message and stores them. Returns appropriate
  	 * response.
  	 *
  	 * @param message
  	 * @return
  	 */
  	private byte[] handlePutEvent(final Message message) {
  		try {
  			// Get the header from the message
  			final Event[] events = NetworkProtocol.decodeEvents(message.buffer);
  
  			// Store the header
  