View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.cli2.commandline;
18  
19  import java.util.LinkedList;
20  import java.util.List;
21  import java.util.ListIterator;
22  
23  import org.apache.commons.cli2.CommandLine;
24  import org.apache.commons.cli2.Group;
25  import org.apache.commons.cli2.Option;
26  import org.apache.commons.cli2.OptionException;
27  import org.apache.commons.cli2.WriteableCommandLine;
28  import org.apache.commons.cli2.resource.ResourceConstants;
29  import org.apache.commons.cli2.util.HelpFormatter;
30  
31  /**
32   * A class that implements the <code>Parser</code> interface can parse a
33   * String array according to the {@link Group}specified and return a
34   * {@link CommandLine}.
35   *
36   * @author John Keyes (john at integralsource.com)
37   */
38  public class Parser {
39      private HelpFormatter helpFormatter = new HelpFormatter();
40      private Option helpOption = null;
41      private String helpTrigger = null;
42      private Group group = null;
43  
44      /**
45       * Parse the arguments according to the specified options and properties.
46       *
47       * @param arguments
48       *            the command line arguments
49       *
50       * @return the list of atomic option and value tokens
51       * @throws OptionException
52       *             if there are any problems encountered while parsing the
53       *             command line tokens.
54       */
55      public CommandLine parse(final String[] arguments)
56          throws OptionException {
57          // build a mutable list for the arguments
58          final List argumentList = new LinkedList();
59  
60          // copy the arguments into the new list
61          for (int i = 0; i < arguments.length; i++) {
62              final String argument = arguments[i];
63  
64              // ensure non intern'd strings are used
65              // so that == comparisons work as expected
66              argumentList.add(new String(argument));
67          }
68  
69          // wet up a command line for this group
70          final WriteableCommandLine commandLine = new WriteableCommandLineImpl(group, argumentList);
71  
72          // pick up any defaults from the model
73          group.defaults(commandLine);
74  
75          // process the options as far as possible
76          final ListIterator iterator = argumentList.listIterator();
77          Object previous = null;
78  
79          while (group.canProcess(commandLine, iterator)) {
80              // peek at the next item and backtrack
81              final Object next = iterator.next();
82              iterator.previous();
83  
84              // if we have just tried to process this instance
85              if (next == previous) {
86                  // abort
87                  break;
88              }
89  
90              // remember previous
91              previous = next;
92  
93              group.process(commandLine, iterator);
94          }
95  
96          // if there are more arguments we have a problem
97          if (iterator.hasNext()) {
98              final String arg = (String) iterator.next();
99              throw new OptionException(group, ResourceConstants.UNEXPECTED_TOKEN, arg);
100         }
101 
102         // no need to validate if the help option is present
103         if (!commandLine.hasOption(helpOption) && !commandLine.hasOption(helpTrigger)) {
104             group.validate(commandLine);
105         }
106 
107         return commandLine;
108     }
109 
110     /**
111      * Parse the arguments according to the specified options and properties and
112      * displays the usage screen if the CommandLine is not valid or the help
113      * option was specified.
114      *
115      * @param arguments the command line arguments
116      * @return a valid CommandLine or null if the parse was unsuccessful
117      */
118     public CommandLine parseAndHelp(final String[] arguments) {
119         helpFormatter.setGroup(group);
120 
121         try {
122             // attempt to parse the command line
123             final CommandLine commandLine = parse(arguments);
124 
125             if (!commandLine.hasOption(helpOption) && !commandLine.hasOption(helpTrigger)) {
126                 return commandLine;
127             }
128         } catch (final OptionException oe) {
129             // display help regarding the exception
130             helpFormatter.setException(oe);
131         }
132 
133         // print help
134         helpFormatter.print();
135 
136         return null;
137     }
138 
139     /**
140      * Sets the Group of options to parse against
141      * @param group the group of options to parse against
142      */
143     public void setGroup(final Group group) {
144         this.group = group;
145     }
146 
147     /**
148      * Sets the HelpFormatter to use with the simplified parsing.
149      * @see #parseAndHelp(String[])
150      * @param helpFormatter the HelpFormatter to use with the simplified parsing
151      */
152     public void setHelpFormatter(final HelpFormatter helpFormatter) {
153         this.helpFormatter = helpFormatter;
154     }
155 
156     /**
157      * Sets the help option to use with the simplified parsing.  For example
158      * <code>--help</code>, <code>-h</code> and <code>-?</code> are often used.
159      * @see #parseAndHelp(String[])
160      * @param helpOption the help Option
161      */
162     public void setHelpOption(final Option helpOption) {
163         this.helpOption = helpOption;
164     }
165 
166     /**
167      * Sets the help option to use with the simplified parsing.  For example
168      * <code>--help</code>, <code>-h</code> and <code>-?</code> are often used.
169      * @see #parseAndHelp(String[])
170      * @param helpTrigger the trigger of the help Option
171      */
172     public void setHelpTrigger(final String helpTrigger) {
173         this.helpTrigger = helpTrigger;
174     }
175 }