001package org.unix4j.io;
002
003import org.unix4j.line.Line;
004
005import java.io.IOException;
006import java.io.Writer;
007
008/**
009 * Output device based on a {@link Writer}.
010 */
011public class WriterOutput implements Output {
012
013        private final Writer writer;
014        private final boolean closeWriterOnFinish;
015
016        private Line lastTerminatedLine;
017        private Line lastLine;
018
019        public WriterOutput(Writer writer) {
020                this(writer, false);
021        }
022
023        protected WriterOutput(Writer writer, boolean closeWriterOnFinish) {
024                this.writer = writer;
025                this.closeWriterOnFinish = closeWriterOnFinish;
026                init();
027        }
028
029        private void init() {
030                lastTerminatedLine = Line.EMPTY_LINE;
031                lastLine = null;
032        }
033
034        /**
035         * Returns the underlying writer that was passed to the constructor.
036         * 
037         * @return the writer that was passed to the constructor.
038         */
039        protected Writer getWriter() {
040                return writer;
041        }
042
043        @Override
044        public boolean processLine(Line line) {
045                try {
046                        if (lastLine != null) {
047                                writer.write(lastTerminatedLine.getLineEnding());
048                        }
049                        writer.write(line.getContent());
050                } catch (IOException e) {
051                        throw new RuntimeException(e);
052                }
053                lastLine = line;
054                if (line.getLineEndingLength() > 0) {
055                        lastTerminatedLine = line;
056                }
057                return true;
058        }
059
060        @Override
061        public void finish() {
062                try {
063                        if (lastLine != null && writeLastLineEnding()) {
064                                writer.write(lastLine.getLineEnding());
065                        }
066                        if (closeWriterOnFinish) {
067                                writer.close();
068                        } else {
069                                writer.flush();
070                        }
071                        init();
072                } catch (IOException e) {
073                        throw new RuntimeException(e);
074                }
075        }
076
077        /**
078         * Returns true if the last line ending should be written.
079         * <p>
080         * This default implementation always returns true, but certain subclasses
081         * such as {@link StringOutput} sometimes return false when the last line
082         * should <i>not</i> be terminated with a line ending.
083         * 
084         * @return true if the last line ending should be written, and false
085         *         otherwise
086         */
087        protected boolean writeLastLineEnding() {
088                return true;
089        }
090
091}