001package org.unix4j.io; 002 003import java.util.ArrayList; 004import java.util.LinkedList; 005import java.util.List; 006 007import org.unix4j.line.Line; 008import org.unix4j.util.LineUtil; 009 010/** 011 * Output device storing all written lines in memory in a {@link List}. 012 */ 013public class BufferedOutput implements Output { 014 015 private final List<Line> buffer; 016 017 /** 018 * Constructor using an {@link ArrayList} as backing buffer for the lines. 019 */ 020 public BufferedOutput() { 021 this(new ArrayList<Line>()); 022 } 023 024 /** 025 * Constructor using the specified list as line buffer. The buffer is NOT 026 * cloned, that is, changes to the buffer affect this {@code BufferedOutput} 027 * and vice versa. 028 * 029 * @param buffer 030 * the line buffer used "as is" without cloning 031 */ 032 public BufferedOutput(List<Line> buffer) { 033 this.buffer = buffer; 034 } 035 036 @Override 037 public boolean processLine(Line line) { 038 buffer.add(line); 039 return true; 040 } 041 042 @Override 043 public void finish() { 044 // nothing to do 045 } 046 047 /** 048 * Returns a list-like representation of the lines contained in this buffer. 049 * Some users might also consider {@link #toMultiLineString()} instead. 050 * 051 * @return a list-like string representation of the buffered lines 052 */ 053 @Override 054 public String toString() { 055 return buffer.toString(); 056 } 057 058 /** 059 * Returns a multi-line representation of the lines in this buffer. The last 060 * line is never terminated, all other lines are terminated with guarantee 061 * even if the line itself has an empty line ending string. 062 * 063 * @return a multi-line string of the buffered lines, without line 064 * termination for the last line 065 * @see LineUtil#toMultiLineString(List) 066 */ 067 public String toMultiLineString() { 068 return LineUtil.toMultiLineString(buffer); 069 } 070 071 /** 072 * Writes the buffered output lines to the specified {@code output} device. 073 * This buffered output devices does not change, that is, all lines will 074 * still be contained in the buffer after calling this method. 075 * 076 * @param output 077 * the output device to write to 078 */ 079 public void writeTo(Output output) { 080 boolean more = true; 081 for (int i = 0; i < buffer.size() && more; i++) { 082 more = output.processLine(buffer.get(i)); 083 } 084 output.finish(); 085 } 086 087 /** 088 * Returns a {@link BufferedInput} with all lines contained in this 089 * {@code BufferedOutput}. The lists used as buffer in this 090 * {@link BufferedOutput} and the returned {@link BufferedInput} are NOT 091 * shared, meaning that subsequent modifications of this 092 * {@code BufferedOutput} are not reflected in the returned 093 * {@code BufferedInput}. 094 * 095 * @return a {@code BufferdInput} object reflecting the current snapshot of 096 * lines in this {@code BufferedOutput} 097 */ 098 public BufferedInput asInput() { 099 return new BufferedInput(new LinkedList<Line>(buffer)); 100 } 101 102 /** 103 * Returns a new list with the lines currently stored by this 104 * {@code BufferdOutput} object. 105 * 106 * @return a new list with the lines of this buffer 107 */ 108 public List<Line> asList() { 109 return new ArrayList<Line>(buffer); 110 } 111 112 /** 113 * Returns the number of lines currently stored by this 114 * {@code BufferedOutput} object. 115 * 116 * @return the number of lines in the buffer 117 */ 118 public int size() { 119 return buffer.size(); 120 } 121 122 /** 123 * Clears all lines in this buffer. 124 * 125 * @return this buffer for chained calls 126 */ 127 public BufferedOutput clear() { 128 buffer.clear(); 129 return this; 130 } 131}