001package org.unix4j.command;
002
003import org.unix4j.context.ExecutionContext;
004import org.unix4j.processor.LineProcessor;
005
006/**
007 * A composite command joining two commands. The output of the
008 * {@link #getFirst() first} command is joined to the input of the
009 * {@link #getSecond() second} command.
010 */
011public class JoinedCommand<A extends Arguments<A>> implements Command<A> {
012
013        private final Command<A> first;
014        private final Command<?> second;
015
016        /**
017         * Constructor with first and second command in the join.
018         * 
019         * @param first
020         *            the first command in the join, whose output is joined to the
021         *            input of the second command
022         * @param second
023         *            the second command in the join, whose input is joined from the
024         *            output of the first command
025         * @throws NullPointerException
026         *             if any of the command arguments is null
027         * 
028         */
029        public JoinedCommand(Command<A> first, Command<?> second) {
030                if (first == null) {
031                        throw new NullPointerException("first command cannot be null");
032                }
033                if (second == null) {
034                        throw new NullPointerException("second command cannot be null");
035                }
036                this.first = first;
037                this.second = second;
038        }
039
040        public static <A extends Arguments<A>> JoinedCommand<A> join(Command<A> first, Command<?> second) {
041                return new JoinedCommand<A>(first, second);
042        }
043
044        /**
045         * Returns the first command of this joined command
046         * 
047         * @return the first command in the join
048         */
049        public Command<A> getFirst() {
050                return first;
051        }
052
053        /**
054         * Returns the second command of this joined command
055         * 
056         * @return the second command in the join
057         */
058        public Command<?> getSecond() {
059                return second;
060        }
061
062        /**
063         * Returns the joined command names, a string like "echo | grep"
064         * 
065         * @return the joined command names, a string like "echo | grep"
066         */
067        @Override
068        public String getName() {
069                return getFirst().getName() + " | " + getSecond().getName();
070        }
071
072        @Override
073        public A getArguments(ExecutionContext context) {
074                return getFirst().getArguments(context);
075        }
076
077        @Override
078        public Command<?> join(Command<?> next) {
079                return JoinedCommand.join(getFirst(), getSecond().join(next));
080        }
081
082        /**
083         * Executes this joined command redirecting the output of the first command
084         * such that it becomes the input of the second command.
085         * <p>
086         * The specified {@code output} object is passed to the second command's
087         * {@code execute(..)} method. The {@link LineProcessor} returned by the
088         * second command is passed to the {@code execute(..)} method of the first
089         * command, with the effect that the first command provides its output to
090         * the second command as input.
091         * 
092         * @param context
093         *            context object providing access to the current directory,
094         *            environment variables and other information useful for the
095         *            commands during their execution
096         * @param output
097         *            the output for the second command
098         */
099        @Override
100        public LineProcessor execute(ExecutionContext context, LineProcessor output) {
101                return getFirst().execute(context, getSecond().execute(context, output));
102        }
103
104        /**
105         * Returns the string representation of this joined command, consisting of
106         * first and second command including arguments and options.
107         * <p>
108         * An example string returned by a joined command is
109         * 
110         * <pre>
111         * &quot;echo -messages [Hello WORLD] | grep -matchString world -ignoreCase&quot;
112         * </pre>
113         * 
114         * @return the string representation of this joined command, such as
115         * 
116         *         <pre>
117         * &quot;echo -messages [Hello WORLD] | grep -matchString world -ignoreCase&quot;
118         * </pre>
119         */
120        @Override
121        public String toString() {
122                return first + " | " + second;
123        }
124
125}