001package org.unix4j.unix.wc;
002
003import org.unix4j.context.ExecutionContext;
004import org.unix4j.io.FileInput;
005import org.unix4j.io.Input;
006import org.unix4j.line.Line;
007import org.unix4j.processor.LineProcessor;
008
009import java.util.List;
010import java.util.NavigableMap;
011import java.util.TreeMap;
012
013/**
014 * Input processor for line, word and char count for multiple input files.
015 */
016class WcMultipleFilesProcessor implements LineProcessor {
017        private final ExecutionContext context;
018        private final NavigableMap<String, Counters> inputCounters;
019        private final Counters totals;
020    private final WcArguments args;
021    private final List<? extends Input> inputs;
022    private final LineProcessor output;
023    private Counters currentInputCounter;
024
025    public WcMultipleFilesProcessor(final ExecutionContext context, final List<? extends Input> inputs, final LineProcessor output, WcArguments args) {
026        this.context = context;
027        this.inputCounters = new TreeMap<>();
028        this.currentInputCounter = new Counters(args);
029        this.totals = new Counters(args);
030        this.args = args;
031        this.inputs = inputs;
032        this.output = output;
033        }
034
035    @Override
036    public boolean processLine(Line line) {
037        return false; // we want no input, we have it already
038    }
039
040    @Override
041    public void finish() {
042        for (final Input input: inputs) {
043            for (final Line line : input) {
044                currentInputCounter.update(line);
045            }
046            finishSingleInput(input);
047        }
048        writeOutput();
049        closeInputs();
050    }
051
052        private void finishSingleInput(Input input) {
053                final String fileInfo = input instanceof FileInput ? ((FileInput)input).getFileInfo(context.getCurrentDirectory()) : input.toString();
054                totals.updateTotal(currentInputCounter);
055        inputCounters.put(fileInfo, currentInputCounter);
056        currentInputCounter = new Counters(args);
057        }
058
059        private void writeOutput() {
060        int fixedWidthOfColumnsInOutput = totals.getFixedWidthOfColumnsInOutput();
061        for(final String fileInfo: inputCounters.keySet()){
062            final Counters inputCounter = inputCounters.get(fileInfo);
063            inputCounter.writeCountsLineWithFileInfo(output, fileInfo, fixedWidthOfColumnsInOutput);
064        }
065        totals.writeCountsLineWithFileInfo(output, "total", fixedWidthOfColumnsInOutput);
066        }
067
068        private void closeInputs() {
069        for (final Input input : inputs) {
070            input.close();
071        }
072    }
073}