package com.github.triceo.splitlog;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.IOUtils;

abstract class AbstractLogTailer {

    private final LogWatch watch;

    protected AbstractLogTailer(final LogWatch watch) {
        this.watch = watch;
    }

    /**
     * Retrieve messages that this tailer has been notified of.
     * 
     * @return Messages we are aware of, in their original order.
     */
    public abstract List<Message> getMessages();

    protected LogWatch getWatch() {
        return this.watch;
    }

    public boolean isTerminated() {
        return this.watch.isTerminated(this);
    }

    /**
     * Notify the tailer of a new message in the watched log. Must never be
     * called by users, just from the library code.
     * 
     * @param msg
     *            The message.
     */
    protected abstract void notifyOfMessage(Message msg);

    /**
     * Mark the current location in the tail by a custom message. It is up to
     * the implementors to decide whether or not a tag inserted at the same time
     * twice is inserted twice, or the second tag overwrites the first.
     * 
     * @param tagLine
     *            Text of the message.
     */
    public abstract void tag(String tagLine);

    /**
     * Will block until a message arrives, for which the condition is true.
     * 
     * @param condition
     *            Condition that needs to be true for the method to unblock.
     * @return Whether the message actually arrived, or the method unblocked due
     *         to some other reason.
     */
    public abstract boolean waitFor(MessageCondition condition);

    /**
     * Will block until a message arrives, for which the condition is true. If
     * none arrives before the timeout, it unblocks anyway.
     * 
     * @param condition
     *            Condition that needs to be true for the method to unblock.
     * @return Whether the message actually arrived, or the method unblocked due
     *         to some other reason.
     */
    public abstract boolean waitFor(MessageCondition condition, long timeout, TimeUnit unit);

    /**
     * Will output the log, including tags, into a stream.
     * 
     * @param stream
     *            Target.
     * @return True if written, false otherwise.
     */
    public boolean write(final OutputStream stream) {
        BufferedWriter w = null;
        try {
            w = new BufferedWriter(new OutputStreamWriter(stream, "UTF-8"));
            for (final Message msg : this.getMessages()) {
                w.write(msg.toString());
                w.newLine();
            }
            return true;
        } catch (final IOException ex) {
            return false;
        } finally {
            IOUtils.closeQuietly(w);
        }
    }

}

@@ -2295,15 +2295,24 @@
 put 
-the log
+all the messages
 , in
@@ -2502,24 +2502,995 @@
 m stream) %7B%0A
+        return this.write(stream, new MessageCondition() %7B%0A%0A            public boolean accept(final Message msg) %7B%0A                // accept every message%0A                return true;%0A            %7D%0A%0A        %7D);%0A    %7D%0A%0A    /**%0A     * Will output the messages, including tags, that meet a specific condition,%0A     * into a stream.%0A     * %0A     * @param stream%0A     *            Target.%0A     * @param condition%0A     *            When this object's %7B@link MessageCondition#accept(Message)%7D%0A     *            returns true on a message, the message will be included in the%0A     *            stream.%0A     * @return True if written, false otherwise.%0A     */%0A    public boolean write(final OutputStream stream, final MessageCondition condition) %7B%0A        if (stream == null) %7B%0A            throw new IllegalArgumentException(%22Stream may not be null.%22);%0A        %7D else if (condition == null) %7B%0A            throw new IllegalArgumentException(%22Condition may not be null.%22);%0A        %7D%0A
         Buff
@@ -3656,24 +3656,118 @@
 ssages()) %7B%0A
+                if (!condition.accept(msg)) %7B%0A                    continue;%0A                %7D%0A
             
@@ -3997,17 +3997,16 @@
       %7D%0A
+
     %7D%0A
-%0A
 %7D%0A

Allow messages to be filtered out from writing.