001package org.unix4j.unix.grep; 002 003import org.unix4j.command.AbstractCommand; 004import org.unix4j.context.ExecutionContext; 005import org.unix4j.io.FileInput; 006import org.unix4j.io.Input; 007import org.unix4j.io.NullInput; 008import org.unix4j.processor.DefaultInputProcessor; 009import org.unix4j.processor.InputLineProcessor; 010import org.unix4j.processor.InputProcessor; 011import org.unix4j.processor.LineProcessor; 012import org.unix4j.processor.MultipleInputLineProcessor; 013import org.unix4j.unix.Grep; 014import org.unix4j.util.FileUtil; 015 016import java.io.File; 017import java.util.Arrays; 018import java.util.List; 019 020/** 021 * Implementation of the {@link Grep grep} command. 022 */ 023class GrepCommand extends AbstractCommand<GrepArguments> { 024 public GrepCommand(GrepArguments arguments) { 025 super(Grep.NAME, arguments); 026 } 027 028 @Override 029 public LineProcessor execute(ExecutionContext context, LineProcessor output) { 030 final GrepArguments args = getArguments(context); 031 032 //from file? 033 if (args.isFilesSet()) { 034 final List<FileInput> inputs = FileInput.multiple(args.getFiles()); 035 return getFileInputProcessor(inputs, context, output, args); 036 } else if (args.isPathsSet()) { 037 final List<File> files = FileUtil.expandFiles(context.getCurrentDirectory(), args.getPaths()); 038 final List<FileInput> inputs = FileInput.multiple(files); 039 return getFileInputProcessor(inputs, context, output, args); 040 } else if (args.isInputsSet()) { 041 final List<Input> inputs = Arrays.asList(args.getInputs()); 042 return getFileInputProcessor(inputs, context, output, args); 043 } 044 045 //from standard input 046 return getStandardInputProcessor(context, output, args); 047 } 048 049 private LineMatcher getMatcher(GrepArguments args) { 050 final LineMatcher matcher; 051 if (args.isFixedStrings()) { 052 if (args.isWholeLine()) { 053 matcher = args.isIgnoreCase() ? new FixedStringMatcher.WholeLineIgnoreCase(args) : new FixedStringMatcher.WholeLine(args); 054 } else { 055 matcher = args.isIgnoreCase() ? new FixedStringMatcher.IgnoreCase(args) : new FixedStringMatcher.Standard(args); 056 } 057 } else { 058 matcher = new RegexpMatcher(args); 059 } 060 return args.isInvertMatch() ? new InvertedMatcher(matcher) : matcher; 061 } 062 063 private LineProcessor getStandardInputProcessor(ExecutionContext context, LineProcessor output, GrepArguments args) { 064 final LineMatcher matcher = getMatcher(args); 065 if (args.isCount()) { 066 return new CountMatchingLinesInputProcessor(this, context, output, matcher); 067 } else if (args.isMatchingFiles()) { 068 return new WriteFilesWithMatchingLinesProcessor(this, context, output, matcher); 069 } else if (args.isLineNumber()) { 070 return new WriteMatchingLinesWithLineNumberProcessor(this, context, output, matcher); 071 } 072 return new WriteMatchingLinesProcessor(this, context, output, matcher); 073 } 074 075 private LineProcessor getFileInputProcessor(List<? extends Input> inputs, ExecutionContext context, LineProcessor output, GrepArguments args) { 076 switch (inputs.size()) { 077 case 0: 078 return getInputProcessor(NullInput.INSTANCE, context, output, args); 079 case 1: 080 return getInputProcessor(inputs.get(0), context, output, args); 081 default: 082 return getMultipleFilesInputProcessor(inputs, context, output, args); 083 } 084 } 085 086 private LineProcessor getInputProcessor(Input input, ExecutionContext context, LineProcessor output, GrepArguments args) { 087 if (args.isCount()) { 088 final LineMatcher matcher = getMatcher(args); 089 final LineProcessor lineProcessor = new CountMatchingLinesProcessor(this, context, output, matcher); 090 return new InputLineProcessor(input, new DefaultInputProcessor(), lineProcessor); 091 } else if (args.isMatchingFiles()) { 092 final LineMatcher matcher = getMatcher(args); 093 final InputProcessor inputProcessor = new WriteFilesWithMatchingLinesProcessor(this, context, output, matcher); 094 return new InputLineProcessor(input, inputProcessor, output); 095 } else if (args.isLineNumber()) { 096 final LineMatcher matcher = getMatcher(args); 097 final LineProcessor lineProcessor = new WriteMatchingLinesWithLineNumberProcessor(this, context, output, matcher); 098 return new InputLineProcessor(input, new DefaultInputProcessor(), lineProcessor); 099 } else { 100 final LineMatcher matcher = getMatcher(args); 101 final LineProcessor lineProcessor = new WriteMatchingLinesProcessor(this, context, output, matcher); 102 return new InputLineProcessor(input, new DefaultInputProcessor(), lineProcessor); 103 } 104 } 105 106 private LineProcessor getMultipleFilesInputProcessor(List<? extends Input> inputs, ExecutionContext context, LineProcessor output, GrepArguments args) { 107 if (args.isCount()) { 108 final LineMatcher matcher = getMatcher(args); 109 final InputProcessor inputProcessor = new CountMatchingLinesInputProcessor(this, context, output, matcher); 110 return new MultipleInputLineProcessor(inputs, inputProcessor, output); 111 } else if (args.isMatchingFiles()) { 112 final LineMatcher matcher = getMatcher(args); 113 final InputProcessor inputProcessor = new WriteFilesWithMatchingLinesProcessor(this, context, output, matcher); 114 return new MultipleInputLineProcessor(inputs, inputProcessor, output); 115 } else if (args.isLineNumber()) { 116 final LineMatcher matcher = getMatcher(args); 117 final LineProcessor inputProcessor = new WriteMatchingLinesProcessor(this, context, output, matcher); 118 return new MultipleInputLineProcessor(inputs, 119 new WriteMatchingLinesInputProcessor(this, context, matcher), inputProcessor); 120 } else { 121 final LineMatcher matcher = getMatcher(args); 122 final InputProcessor inputProcessor = new WriteMatchingLinesInputProcessor(this, context, matcher); 123 return new MultipleInputLineProcessor(inputs, inputProcessor, output); 124 } 125 } 126}