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 }