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