001package org.unix4j.unix.grep;
002
003import org.unix4j.command.AbstractCommand;
004import org.unix4j.context.ExecutionContext;
005import org.unix4j.io.FileInput;
006import org.unix4j.processor.InputProcessor;
007import org.unix4j.processor.LineProcessor;
008import org.unix4j.processor.MultipleInputLineProcessor;
009import org.unix4j.processor.RedirectInputLineProcessor;
010import org.unix4j.unix.Grep;
011import org.unix4j.util.FileUtil;
012
013import java.io.File;
014import java.util.List;
015
016/**
017 * Implementation of the {@link Grep grep} command.
018 */
019class GrepCommand extends AbstractCommand<GrepArguments> {
020        public GrepCommand(GrepArguments arguments) {
021                super(Grep.NAME, arguments);
022        }
023
024        @Override
025        public LineProcessor execute(ExecutionContext context, LineProcessor output) {
026                final GrepArguments args = getArguments(context);
027
028                //from file?
029                if (args.isFilesSet()) {
030                        final List<FileInput> inputs = FileInput.multiple(args.getFiles());
031                        return getFileInputProcessor(inputs, context, output, args);
032                } else if (args.isPathsSet()) {
033                        final List<File> files = FileUtil.expandFiles(context.getCurrentDirectory(), args.getPaths());
034                        final List<FileInput> inputs = FileInput.multiple(files);
035                        return getFileInputProcessor(inputs, context, output, args);
036                }
037
038                //from standard input
039                return getStandardInputProcessor(context, output, args);
040        }
041
042        private LineMatcher getMatcher(GrepArguments args) {
043                final LineMatcher matcher;
044                if (args.isFixedStrings()) {
045                        if (args.isWholeLine()) {
046                                matcher = args.isIgnoreCase() ? new FixedStringMatcher.WholeLineIgnoreCase(args) : new FixedStringMatcher.WholeLine(args);
047                        } else {
048                                matcher = args.isIgnoreCase() ? new FixedStringMatcher.IgnoreCase(args) : new FixedStringMatcher.Standard(args);
049                        }
050                } else {
051                        matcher = new RegexpMatcher(args);
052                }
053                return args.isInvertMatch() ? new InvertedMatcher(matcher) : matcher;
054        }
055
056        private LineProcessor getStandardInputProcessor(ExecutionContext context, LineProcessor output, GrepArguments args) {
057                final LineMatcher matcher = getMatcher(args);
058                if (args.isCount()) {
059                        return new CountMatchingLinesInputProcessor(this, context, output, matcher);
060                } else if (args.isMatchingFiles()) {
061                        return new WriteFilesWithMatchingLinesProcessor(this, context, output, matcher);
062                } else if (args.isLineNumber()) {
063                        return new WriteMatchingLinesWithLineNumberProcessor(this, context, output, matcher);
064                }
065                return new WriteMatchingLinesProcessor(this, context, output, matcher);
066        }
067        private LineProcessor getFileInputProcessor(List<FileInput> inputs, ExecutionContext context, LineProcessor output, GrepArguments args) {
068                if (args.isCount()) {
069                        final LineMatcher matcher = getMatcher(args);
070                        final InputProcessor processor = new CountMatchingLinesInputProcessor(this, context, output, matcher);
071                        return new MultipleInputLineProcessor(inputs, processor, output);
072                } else if (args.isMatchingFiles()) {
073                        final LineMatcher matcher = getMatcher(args);
074                        final InputProcessor processor = new WriteFilesWithMatchingLinesProcessor(this, context, output, matcher);
075                        return new MultipleInputLineProcessor(inputs, processor, output);
076                } else if (args.isLineNumber()) {
077                        final LineMatcher matcher = getMatcher(args);
078                        final LineProcessor processor = new WriteMatchingLinesProcessor(this, context, output, matcher);
079                        return new MultipleInputLineProcessor(inputs,
080                                        new WriteMatchingLinesInputProcessor(this, context, matcher), processor);
081                }
082                //standard input
083                final LineProcessor standardInputProcessor = getStandardInputProcessor(context, output, args);
084                return new RedirectInputLineProcessor(inputs, standardInputProcessor);
085        }
086}