001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.cli2.commandline; 018 019import java.util.LinkedList; 020import java.util.List; 021import java.util.ListIterator; 022 023import org.apache.commons.cli2.CommandLine; 024import org.apache.commons.cli2.Group; 025import org.apache.commons.cli2.Option; 026import org.apache.commons.cli2.OptionException; 027import org.apache.commons.cli2.WriteableCommandLine; 028import org.apache.commons.cli2.resource.ResourceConstants; 029import org.apache.commons.cli2.util.HelpFormatter; 030 031/** 032 * A class that implements the <code>Parser</code> interface can parse a 033 * String array according to the {@link Group}specified and return a 034 * {@link CommandLine}. 035 * 036 * @author John Keyes (john at integralsource.com) 037 */ 038public class Parser { 039 private HelpFormatter helpFormatter = new HelpFormatter(); 040 private Option helpOption = null; 041 private String helpTrigger = null; 042 private Group group = null; 043 044 /** 045 * Parse the arguments according to the specified options and properties. 046 * 047 * @param arguments 048 * the command line arguments 049 * 050 * @return the list of atomic option and value tokens 051 * @throws OptionException 052 * if there are any problems encountered while parsing the 053 * command line tokens. 054 */ 055 public CommandLine parse(final String[] arguments) 056 throws OptionException { 057 // build a mutable list for the arguments 058 final List argumentList = new LinkedList(); 059 060 // copy the arguments into the new list 061 for (int i = 0; i < arguments.length; i++) { 062 final String argument = arguments[i]; 063 064 // ensure non intern'd strings are used 065 // so that == comparisons work as expected 066 argumentList.add(new String(argument)); 067 } 068 069 // wet up a command line for this group 070 final WriteableCommandLine commandLine = new WriteableCommandLineImpl(group, argumentList); 071 072 // pick up any defaults from the model 073 group.defaults(commandLine); 074 075 // process the options as far as possible 076 final ListIterator iterator = argumentList.listIterator(); 077 Object previous = null; 078 079 while (group.canProcess(commandLine, iterator)) { 080 // peek at the next item and backtrack 081 final Object next = iterator.next(); 082 iterator.previous(); 083 084 // if we have just tried to process this instance 085 if (next == previous) { 086 // abort 087 break; 088 } 089 090 // remember previous 091 previous = next; 092 093 group.process(commandLine, iterator); 094 } 095 096 // if there are more arguments we have a problem 097 if (iterator.hasNext()) { 098 final String arg = (String) iterator.next(); 099 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}