001package org.unix4j.processor; 002 003import java.util.List; 004 005import org.unix4j.command.ExitValueException; 006import org.unix4j.io.Input; 007import org.unix4j.line.Line; 008 009/** 010 * A line processor for multiple inputs processing the same operation for each 011 * input object individually. An operation here is another {@link LineProcessor} 012 * reading the lines passed to it from the standard input. 013 * <p> 014 * The {@link #processLine(Line)} method does nothing and returns false 015 * indicating that the (standard) input is not read by this processor. The 016 * {@link #finish()} method reads the lines from the {@link Input} object passed 017 * to the constructor and passes them as input to the delegate processor 018 * performing the real work. 019 */ 020public class MultipleInputLineProcessor implements LineProcessor { 021 022 private final List<? extends Input> inputs; 023 private final InputProcessor processor; 024 private final LineProcessor output; 025 026 /** 027 * Constructor with input objects (usually file operands of the command) and 028 * the input processor of the command that reads from the standard input. 029 * 030 * @param inputs 031 * the input devices, usually file operands of the command 032 * @param processor 033 * the operation applied to every input in the given 034 * {@code inputs} list 035 */ 036 public MultipleInputLineProcessor(List<? extends Input> inputs, InputProcessor processor, LineProcessor output) { 037 this.inputs = inputs; 038 this.processor = processor; 039 this.output = output; 040 } 041 042 @Override 043 public boolean processLine(Line line) { 044 return false;// we want no input, we have it already 045 } 046 047 /** 048 * Performs the following operations to process all {@code Input} objects 049 * that have been passed to the constructor: 050 * <ol> 051 * <li>Calls {@link #beginMultiple(List, LineProcessor) beginMultiple(..)}</li> 052 * <li>Iterates over all input objects in sequence</li> 053 * <li>Calls {@link InputProcessor#begin(Input, LineProcessor)}</li> 054 * <li>Calls {@link InputProcessor#processLine(Input, Line, LineProcessor)} 055 * for every line in the current input</li> 056 * <li>Calls {@link InputProcessor#finish(Input, LineProcessor)}</li> 057 * <li>Calls {@link #finishMultiple(List, LineProcessor) finishMultiple(..)} 058 * </li> 059 * </ol> 060 */ 061 @Override 062 public void finish() { 063 beginMultiple(inputs, output); 064 for (int i = 0; i < inputs.size(); i++) { 065 final Input input = inputs.get(i); 066 try { 067 processor.begin(input, output); 068 for (final Line line : input) { 069 if (!processor.processLine(input, line, output)) { 070 break;// wants no more lines 071 } 072 } 073 processor.finish(input, output); 074 } catch (ExitValueException e) { 075 e.setInput(input); 076 throw e; 077 } 078 } 079 finishMultiple(inputs, output); 080 } 081 082 /** 083 * Called once at the beginning before iterating over the {@link Input} 084 * objects in the given {@code inputs} list. 085 * <p> 086 * The DEFAULT implementation performs no operation. 087 * 088 * @param inputs 089 * the input object being iterated next 090 * @param output 091 * the output to write to 092 */ 093 protected void beginMultiple(List<? extends Input> inputs, LineProcessor output) { 094 // default: no op 095 } 096 097 /** 098 * Called once at the end after iterating over the {@link Input} objects in 099 * the given {@code inputs} list. 100 * <p> 101 * The DEFAULT implementation calls {@link LineProcessor#finish() 102 * output.finish()}. 103 * 104 * @param inputs 105 * the input object being iterated next 106 * @param output 107 * the output to write to 108 */ 109 protected void finishMultiple(List<? extends Input> inputs, LineProcessor output) { 110 output.finish(); 111 } 112 113}