001package org.unix4j.builder;
002
003import java.io.File;
004import java.io.OutputStream;
005import java.io.Writer;
006import java.util.ArrayList;
007import java.util.List;
008
009import org.unix4j.command.Command;
010import org.unix4j.command.ExitValueException;
011import org.unix4j.command.NoOp;
012import org.unix4j.context.DefaultExecutionContext;
013import org.unix4j.context.ExecutionContextFactory;
014import org.unix4j.io.BufferedOutput;
015import org.unix4j.io.FileOutput;
016import org.unix4j.io.NullOutput;
017import org.unix4j.io.Output;
018import org.unix4j.io.StdOutput;
019import org.unix4j.io.StreamOutput;
020import org.unix4j.io.StringOutput;
021import org.unix4j.io.WriterOutput;
022import org.unix4j.line.Line;
023import org.unix4j.operation.LineOperation;
024import org.unix4j.operation.AdHocCommand;
025
026/**
027 * Default implementation for a {@link CommandBuilder}. Builds a {@link NoOp}
028 * command if no command is {@link #join(Command) joined} to the command chain
029 * of this builder.
030 */
031public class DefaultCommandBuilder implements CommandBuilder {
032
033        private final ExecutionContextFactory contextFactory;
034        private Command<?> command = NoOp.INSTANCE;
035
036        /**
037         * Default constructor initialized to build a {@link NoOp} command if no
038         * command is {@link #join(Command) joined} to this builder's command chain.
039         * Uses a {@link DefaultExecutionContext} to execute commands.
040         */
041        public DefaultCommandBuilder() {
042                this(DefaultExecutionContext.FACTORY);
043        }
044
045        /**
046         * Constructor using the specified factory to create contexts for command
047         * execution. The builder is initialized with a {@link NoOp} command which
048         * will be replaced by the first command {@link #join(Command) joined} to 
049         * this builder's command chain. 
050         * 
051         * @param contextFactory
052         *            the factory used to create execution contexts that are passed
053         *            to the execute method when a command is executed
054         */
055        public DefaultCommandBuilder(ExecutionContextFactory contextFactory) {
056                this.contextFactory = contextFactory;
057        }
058
059        /**
060         * Returns the context factory used to create contexts for command
061         * execution. The returned factory has usually been passed to the
062         * constructor of this builder.
063         * 
064         * @return the factory used to create execution contexts that are passed to
065         *         the execute method when a command is executed
066         */
067        public ExecutionContextFactory getContextFactory() {
068                return contextFactory;
069        }
070
071        @Override
072        public CommandBuilder join(Command<?> command) {
073                if (command == null) {
074                        throw new NullPointerException("command argument cannot be null");
075                }
076                this.command = this.command.join(command);
077                return this;
078        }
079        
080        @Override
081        public CommandBuilder apply(LineOperation operation) {
082                return join(new AdHocCommand(operation));
083        }
084
085        @Override
086        public CommandBuilder reset() {
087                command = NoOp.INSTANCE;
088                return this;
089        }
090
091        @Override
092        public Command<?> build() {
093                return command;
094        }
095
096        @Override
097        public String toString() {
098                return command.toString();
099        }
100
101        @Override
102        public void toStdOut() {
103                toOutput(new StdOutput());
104        }
105
106        @Override
107        public List<Line> toLineList() {
108                final List<Line> lines = new ArrayList<Line>();
109                toOutput(new BufferedOutput(lines));
110                return lines;
111        }
112
113        @Override
114        public List<String> toStringList() {
115                final List<String> lines = new ArrayList<String>();
116                toOutput(new Output() {
117                        @Override
118                        public boolean processLine(Line line) {
119                                lines.add(line.getContent());
120                                return true;// we want more lines
121                        }
122
123                        @Override
124                        public void finish() {
125                                // no op
126                        }
127                });
128                return lines;
129        }
130
131        @Override
132        public void toOutput(Output output) {
133                final Command<?> command = build();
134                command.execute(getContextFactory().createExecutionContext(), output).finish();
135        }
136
137        @Override
138        public void toFile(String file) {
139                toFile(new File(file));
140        }
141
142        @Override
143        public void toFile(File file) {
144                toOutput(new FileOutput(file));
145        }
146
147        @Override
148        public void toOutputStream(OutputStream stream) {
149                toOutput(new StreamOutput(stream));
150        }
151
152        @Override
153        public void toWriter(Writer writer) {
154                toOutput(new WriterOutput(writer));
155        }
156
157        @Override
158        public void toDevNull() {
159                toOutput(NullOutput.DEFAULT);
160        }
161
162        @Override
163        public String toStringResult() {
164                final StringOutput out = new StringOutput();
165                toOutput(out);
166                return out.toString();
167        }
168
169        @Override
170        public int toExitValue() {
171                try {
172                        toDevNull();
173                        return 0;
174                } catch (ExitValueException e) {
175                        return e.getExitValue();
176                }
177        }
178}