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 */ 017 018package org.apache.commons.cli; 019 020import java.io.Serializable; 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.Collections; 024import java.util.HashMap; 025import java.util.HashSet; 026import java.util.LinkedHashMap; 027import java.util.List; 028import java.util.Map; 029 030/** 031 * Main entry-point into the library. 032 * <p> 033 * Options represents a collection of {@link Option} objects, which 034 * describe the possible options for a command-line. 035 * <p> 036 * It may flexibly parse long and short options, with or without 037 * values. Additionally, it may parse only a portion of a commandline, 038 * allowing for flexible multi-stage parsing. 039 * 040 * @see org.apache.commons.cli.CommandLine 041 * 042 * @version $Id: Options.java 1669814 2015-03-28 18:09:26Z britter $ 043 */ 044public class Options implements Serializable 045{ 046 /** The serial version UID. */ 047 private static final long serialVersionUID = 1L; 048 049 /** a map of the options with the character key */ 050 private final Map<String, Option> shortOpts = new LinkedHashMap<String, Option>(); 051 052 /** a map of the options with the long key */ 053 private final Map<String, Option> longOpts = new LinkedHashMap<String, Option>(); 054 055 /** a map of the required options */ 056 // N.B. This can contain either a String (addOption) or an OptionGroup (addOptionGroup) 057 // TODO this seems wrong 058 private final List<Object> requiredOpts = new ArrayList<Object>(); 059 060 /** a map of the option groups */ 061 private final Map<String, OptionGroup> optionGroups = new HashMap<String, OptionGroup>(); 062 063 /** 064 * Add the specified option group. 065 * 066 * @param group the OptionGroup that is to be added 067 * @return the resulting Options instance 068 */ 069 public Options addOptionGroup(OptionGroup group) 070 { 071 if (group.isRequired()) 072 { 073 requiredOpts.add(group); 074 } 075 076 for (Option option : group.getOptions()) 077 { 078 // an Option cannot be required if it is in an 079 // OptionGroup, either the group is required or 080 // nothing is required 081 option.setRequired(false); 082 addOption(option); 083 084 optionGroups.put(option.getKey(), group); 085 } 086 087 return this; 088 } 089 090 /** 091 * Lists the OptionGroups that are members of this Options instance. 092 * 093 * @return a Collection of OptionGroup instances. 094 */ 095 Collection<OptionGroup> getOptionGroups() 096 { 097 return new HashSet<OptionGroup>(optionGroups.values()); 098 } 099 100 /** 101 * Add an option that only contains a short name. 102 * The option does not take an argument. 103 * 104 * @param opt Short single-character name of the option. 105 * @param description Self-documenting description 106 * @return the resulting Options instance 107 * @since 1.3 108 */ 109 public Options addOption(String opt, String description) 110 { 111 addOption(opt, null, false, description); 112 return this; 113 } 114 115 /** 116 * Add an option that only contains a short-name. 117 * It may be specified as requiring an argument. 118 * 119 * @param opt Short single-character name of the option. 120 * @param hasArg flag signally if an argument is required after this option 121 * @param description Self-documenting description 122 * @return the resulting Options instance 123 */ 124 public Options addOption(String opt, boolean hasArg, String description) 125 { 126 addOption(opt, null, hasArg, description); 127 return this; 128 } 129 130 /** 131 * Add an option that contains a short-name and a long-name. 132 * It may be specified as requiring an argument. 133 * 134 * @param opt Short single-character name of the option. 135 * @param longOpt Long multi-character name of the option. 136 * @param hasArg flag signally if an argument is required after this option 137 * @param description Self-documenting description 138 * @return the resulting Options instance 139 */ 140 public Options addOption(String opt, String longOpt, boolean hasArg, String description) 141 { 142 addOption(new Option(opt, longOpt, hasArg, description)); 143 return this; 144 } 145 146 /** 147 * Adds an option instance 148 * 149 * @param opt the option that is to be added 150 * @return the resulting Options instance 151 */ 152 public Options addOption(Option opt) 153 { 154 String key = opt.getKey(); 155 156 // add it to the long option list 157 if (opt.hasLongOpt()) 158 { 159 longOpts.put(opt.getLongOpt(), opt); 160 } 161 162 // if the option is required add it to the required list 163 if (opt.isRequired()) 164 { 165 if (requiredOpts.contains(key)) 166 { 167 requiredOpts.remove(requiredOpts.indexOf(key)); 168 } 169 requiredOpts.add(key); 170 } 171 172 shortOpts.put(key, opt); 173 174 return this; 175 } 176 177 /** 178 * Retrieve a read-only list of options in this set 179 * 180 * @return read-only Collection of {@link Option} objects in this descriptor 181 */ 182 public Collection<Option> getOptions() 183 { 184 return Collections.unmodifiableCollection(helpOptions()); 185 } 186 187 /** 188 * Returns the Options for use by the HelpFormatter. 189 * 190 * @return the List of Options 191 */ 192 List<Option> helpOptions() 193 { 194 return new ArrayList<Option>(shortOpts.values()); 195 } 196 197 /** 198 * Returns the required options. 199 * 200 * @return read-only List of required options 201 */ 202 public List getRequiredOptions() 203 { 204 return Collections.unmodifiableList(requiredOpts); 205 } 206 207 /** 208 * Retrieve the {@link Option} matching the long or short name specified. 209 * The leading hyphens in the name are ignored (up to 2). 210 * 211 * @param opt short or long name of the {@link Option} 212 * @return the option represented by opt 213 */ 214 public Option getOption(String opt) 215 { 216 opt = Util.stripLeadingHyphens(opt); 217 218 if (shortOpts.containsKey(opt)) 219 { 220 return shortOpts.get(opt); 221 } 222 223 return longOpts.get(opt); 224 } 225 226 /** 227 * Returns the options with a long name starting with the name specified. 228 * 229 * @param opt the partial name of the option 230 * @return the options matching the partial name specified, or an empty list if none matches 231 * @since 1.3 232 */ 233 public List<String> getMatchingOptions(String opt) 234 { 235 opt = Util.stripLeadingHyphens(opt); 236 237 List<String> matchingOpts = new ArrayList<String>(); 238 239 for (String longOpt : longOpts.keySet()) 240 { 241 if (longOpt.startsWith(opt)) 242 { 243 matchingOpts.add(longOpt); 244 } 245 } 246 247 return matchingOpts; 248 } 249 250 /** 251 * Returns whether the named {@link Option} is a member of this {@link Options}. 252 * 253 * @param opt short or long name of the {@link Option} 254 * @return true if the named {@link Option} is a member of this {@link Options} 255 */ 256 public boolean hasOption(String opt) 257 { 258 opt = Util.stripLeadingHyphens(opt); 259 260 return shortOpts.containsKey(opt) || longOpts.containsKey(opt); 261 } 262 263 /** 264 * Returns whether the named {@link Option} is a member of this {@link Options}. 265 * 266 * @param opt long name of the {@link Option} 267 * @return true if the named {@link Option} is a member of this {@link Options} 268 * @since 1.3 269 */ 270 public boolean hasLongOption(String opt) 271 { 272 opt = Util.stripLeadingHyphens(opt); 273 274 return longOpts.containsKey(opt); 275 } 276 277 /** 278 * Returns whether the named {@link Option} is a member of this {@link Options}. 279 * 280 * @param opt short name of the {@link Option} 281 * @return true if the named {@link Option} is a member of this {@link Options} 282 * @since 1.3 283 */ 284 public boolean hasShortOption(String opt) 285 { 286 opt = Util.stripLeadingHyphens(opt); 287 288 return shortOpts.containsKey(opt); 289 } 290 291 /** 292 * Returns the OptionGroup the <code>opt</code> belongs to. 293 * @param opt the option whose OptionGroup is being queried. 294 * 295 * @return the OptionGroup if <code>opt</code> is part 296 * of an OptionGroup, otherwise return null 297 */ 298 public OptionGroup getOptionGroup(Option opt) 299 { 300 return optionGroups.get(opt.getKey()); 301 } 302 303 /** 304 * Dump state, suitable for debugging. 305 * 306 * @return Stringified form of this object 307 */ 308 @Override 309 public String toString() 310 { 311 StringBuilder buf = new StringBuilder(); 312 313 buf.append("[ Options: [ short "); 314 buf.append(shortOpts.toString()); 315 buf.append(" ] [ long "); 316 buf.append(longOpts); 317 buf.append(" ]"); 318 319 return buf.toString(); 320 } 321}