package de.skuzzle.polly.sdk;
import java.io.IOException;
import java.util.List;
import de.skuzzle.polly.sdk.eventlistener.MessageEvent;
/**
* <p>Conversations provide an easy way to read several inputs from one user within one
* command. It can be used similar to an {@link InputStream}. You can create a
* new conversation using any of the create methods of the {@link ConversationManager}
* </p>
*
* <p>Calling any of the {@link #readLine()} methods will cause the current thread to
* block until the user for which this conversation was created wrote a line on the
* channel for which this conversation was created. {@link #writeLine(String)} is a
* convenient way for replying (it wraps
* {@link IrcManager#sendMessage(String, String, Object)}</p>
*
* <p>Message from other users or from the same user on a different channel are ignored
* by the conversation.</p>
*
* <p>Please note: As Conversations are thread-blocking and usually called during
* execution of a command they may block pollys event system. If all event threads are
* blocked, no further {@link MessageEvent}s can be fired thus causing polly to run into
* a deadlock (as the conversations are waiting for the MessageEvent which
* unblocks them).</p>
*
* <p>To prevent any trouble ensure to always close conversations and using them
* thoughtfully. Additionally, polly may shutdown idling conversations in order to
* gain a further event threads. You may also define a timeout after which your
* conversation is closed automatically.</p>
*
* <p>Once a conversation has been closed, it cannot further be used. You can check
* whether the conversation can still be used you may use
* {@link #isDisposed()}</p>
*
* <p>Here is an example of how to create and use conversations:</p>
* <pre>
* protected boolean executeOnBoth(User executer, String channel,
* Signature signature) throws CommandException {
*
* IrcUser u = new IrcUser(executer.getCurrentNickName(), "", "");
* Conversation c = null;
* try {
* c = this.getMyPolly().conversations().create(getMyPolly(), executer, channel);
*
* c.writeLine("Please insert your desired username:");
* String name = c.readStringLine();
* c.writeLine("Now insert your password");
* String password = c.readStringLine();
* c.writeLine("Please retype your password");
* String retype = c.readStringLine();
* if (!retype.equals(password)) {
* c.writeLine("Passwords do not match.");
* }
* c.writeLine(c.getHistory().toString());
* } catch (Exception e) {
* this.reply(channel, e.getMessage());
* } finally {
* if (c != null) {
* c.close();
* }
* }
*
* return false;
* }
* </pre>
*
* @author Simon
*
*/
public interface Conversation extends Disposable {
/**
* Wrapper method for {@link #readLine()} which returns the message-string from the
* incoming {@link MessageEvent}.
*
* @return The String the user wrote.
* @throws IOException If this thread was interrupted while waiting for the incoming
* message or an invalid cross thread call happened.
* @throws InterruptedException If the conversation is closed while waiting for an
* incoming line.
* @throws IllegalStateException If this Conversation is closed.
*/
public abstract String readStringLine() throws IOException, InterruptedException;
/**
* Waits until the user for which this conversation was created wrote a line on the
* channel for which this conversation was created.
* One conersation can only be read from one thread. If you call readLine() from two
* different threads, this will cause an IOException.
*
* @return The {@link MessageEvent} of the incoming message.
* @throws IOException If this thread was interrupted while waiting for the incoming
* message or an invalid cross thread call happened.
* @throws InterruptedException If the conversation is closed while waiting for an
* incoming line.
* @throws IllegalStateException If this Conversation is closed.
*/
public abstract MessageEvent readLine() throws IOException, InterruptedException;
/**
* Writes the given line on the channel for which this conversation was created. This
* method is just a wrapper for {@link IrcManager#sendMessage(String, String)}.
*
* @param line The line to send to the channel.
* @throws IllegalStateException If this Conversation is closed.
*/
public abstract void writeLine(String line);
/**
* Gets a list of all {@link MessageEvent}s that this conversation received.
*
* @return A list of {@link MessageEvent}s
*/
public abstract List<MessageEvent> getHistory();
/**
* Determines whether this conversation is idle. An idle conversation will be
* automatically closed by polly.
*
* @return If this conversation is idle.
*/
public abstract boolean isIdle();
/**
* <p>Closes this conversation. After closing, you cannot use this conversation any
* more to read or write lines.</p>
* <p>This is a no-exception wrapper for {@link #dispose()}</p>
*/
public abstract void close();
}