001package org.unix4j.unix.head; 002 003import java.io.File; 004import java.util.Arrays; 005import java.util.List; 006 007import org.unix4j.command.AbstractCommand; 008import org.unix4j.context.ExecutionContext; 009import org.unix4j.io.FileInput; 010import org.unix4j.io.Input; 011import org.unix4j.line.Line; 012import org.unix4j.line.SimpleLine; 013import org.unix4j.processor.DefaultInputProcessor; 014import org.unix4j.processor.InputProcessor; 015import org.unix4j.processor.LineProcessor; 016import org.unix4j.processor.MultipleInputLineProcessor; 017import org.unix4j.processor.RedirectInputLineProcessor; 018import org.unix4j.unix.Head; 019import org.unix4j.util.FileUtil; 020 021/** 022 * Implementation of the {@link Head head} command. 023 */ 024class HeadCommand extends AbstractCommand<HeadArguments> { 025 public HeadCommand(HeadArguments arguments) { 026 super(Head.NAME, arguments); 027 if (arguments.isCountSet() && arguments.getCount() < 0) { 028 throw new IllegalArgumentException("count cannot be negative: " + arguments); 029 } 030 } 031 032 @Override 033 public LineProcessor execute(ExecutionContext context, final LineProcessor output) { 034 final HeadArguments args = getArguments(context); 035 036 //input from file(s)? 037 if (args.isFilesSet()) { 038 final List<FileInput> inputs = FileInput.multiple(args.getFiles()); 039 return getFileInputProcessor(inputs, context, output, args); 040 } else if (args.isPathsSet()) { 041 final List<File> files = FileUtil.expandFiles(context.getCurrentDirectory(), args.getPaths()); 042 final List<FileInput> inputs = FileInput.multiple(files); 043 return getFileInputProcessor(inputs, context, output, args); 044 } else if (args.isInputsSet()) { 045 final List<Input> inputs = Arrays.asList(args.getInputs()); 046 return getFileInputProcessor(inputs, context, output, args); 047 } 048 049 //read from standard input 050 return getStandardInputProcessor(context, output, args); 051 } 052 053 private AbstractHeadProcessor getStandardInputProcessor(ExecutionContext context, LineProcessor output, HeadArguments args) { 054 if (args.isChars()) { 055 //count chars 056 return new HeadCharsProcessor(this, context, output); 057 } else { 058 //count lines 059 return new HeadLinesProcessor(this, context, output); 060 } 061 } 062 063 private LineProcessor getFileInputProcessor(List<? extends Input> inputs, final ExecutionContext context, final LineProcessor output, HeadArguments args) { 064 final AbstractHeadProcessor headProcessor = getStandardInputProcessor(context, output, args); 065 if (inputs.size() <= 1 || args.isSuppressHeaders()) { 066 return new RedirectInputLineProcessor(inputs, headProcessor); 067 } else { 068 //write header line per file 069 final InputProcessor inputProcessor = new DefaultInputProcessor() { 070 private boolean firstFile = true; 071 @Override 072 public void begin(Input input, LineProcessor standardInputProcessor) { 073 if (firstFile) { 074 firstFile = false; 075 } else { 076 output.processLine(Line.EMPTY_LINE); 077 } 078 final String fileInfo = input instanceof FileInput ? ((FileInput)input).getFileInfo(context.getCurrentDirectory()) : input.toString(); 079 output.processLine(new SimpleLine("==> " + fileInfo + " <==")); 080 } 081 082 @Override 083 public void finish(Input input, LineProcessor output) { 084 super.finish(input, output); 085 headProcessor.resetCounter(); 086 } 087 }; 088 return new MultipleInputLineProcessor(inputs, inputProcessor, headProcessor); 089 } 090 } 091}