package cc.blynk.cli; import java.util.*; /** * Main entry-point into the library. * <p> * Options represents a collection of {@link Option} objects, which * describe the possible options for a command-line. * <p> * It may flexibly parse long and short options, with or without * values. Additionally, it may parse only a portion of a commandline, * allowing for flexible multi-stage parsing. * * * @version $Id: Options.java 1754332 2016-07-27 18:47:57Z britter $ */ public class Options { /** a map of the options with the character key */ private final Map<String, Option> shortOpts = new LinkedHashMap<>(); /** a map of the options with the long key */ private final Map<String, Option> longOpts = new LinkedHashMap<>(); /** a map of the required options */ // N.B. This can contain either a String (addOption) or an OptionGroup (addOptionGroup) // TODO this seems wrong private final List<Object> requiredOpts = new ArrayList<>(); /** a map of the option groups */ private final Map<String, OptionGroup> optionGroups = new LinkedHashMap<>(); /** * Lists the OptionGroups that are members of this Options instance. * * @return a Collection of OptionGroup instances. */ Collection<OptionGroup> getOptionGroups() { return new HashSet<>(optionGroups.values()); } /** * Add an option that only contains a short-name. * * <p> * It may be specified as requiring an argument. * </p> * * @param opt Short single-character name of the option. * @param hasArg flag signally if an argument is required after this option * @param description Self-documenting description * @return the resulting Options instance */ public Options addOption(String opt, boolean hasArg, String description) { addOption(opt, null, hasArg, description); return this; } /** * Add an option that contains a short-name and a long-name. * * <p> * It may be specified as requiring an argument. * </p> * * @param opt Short single-character name of the option. * @param longOpt Long multi-character name of the option. * @param hasArg flag signally if an argument is required after this option * @param description Self-documenting description * @return the resulting Options instance */ public Options addOption(String opt, String longOpt, boolean hasArg, String description) { addOption(new Option(opt, longOpt, hasArg, description)); return this; } /** * Adds an option instance * * @param opt the option that is to be added * @return the resulting Options instance */ public Options addOption(Option opt) { String key = opt.getKey(); // add it to the long option list if (opt.hasLongOpt()) { longOpts.put(opt.getLongOpt(), opt); } // if the option is required add it to the required list if (opt.isRequired()) { if (requiredOpts.contains(key)) { requiredOpts.remove(requiredOpts.indexOf(key)); } requiredOpts.add(key); } shortOpts.put(key, opt); return this; } /** * Returns the required options. * * @return read-only List of required options */ public List getRequiredOptions() { return Collections.unmodifiableList(requiredOpts); } /** * Retrieve the {@link Option} matching the long or short name specified. * * <p> * The leading hyphens in the name are ignored (up to 2). * </p> * * @param opt short or long name of the {@link Option} * @return the option represented by opt */ public Option getOption(String opt) { opt = Util.stripLeadingHyphens(opt); if (shortOpts.containsKey(opt)) { return shortOpts.get(opt); } return longOpts.get(opt); } /** * Returns the options with a long name starting with the name specified. * * @param opt the partial name of the option * @return the options matching the partial name specified, or an empty list if none matches * @since 1.3 */ public List<String> getMatchingOptions(String opt) { opt = Util.stripLeadingHyphens(opt); List<String> matchingOpts = new ArrayList<>(); // for a perfect match return the single option only if (longOpts.keySet().contains(opt)) { return Collections.singletonList(opt); } for (String longOpt : longOpts.keySet()) { if (longOpt.startsWith(opt)) { matchingOpts.add(longOpt); } } return matchingOpts; } /** * Returns whether the named {@link Option} is a member of this {@link Options}. * * @param opt short or long name of the {@link Option} * @return true if the named {@link Option} is a member of this {@link Options} */ public boolean hasOption(String opt) { opt = Util.stripLeadingHyphens(opt); return shortOpts.containsKey(opt) || longOpts.containsKey(opt); } /** * Returns whether the named {@link Option} is a member of this {@link Options}. * * @param opt long name of the {@link Option} * @return true if the named {@link Option} is a member of this {@link Options} * @since 1.3 */ public boolean hasLongOption(String opt) { opt = Util.stripLeadingHyphens(opt); return longOpts.containsKey(opt); } /** * Returns whether the named {@link Option} is a member of this {@link Options}. * * @param opt short name of the {@link Option} * @return true if the named {@link Option} is a member of this {@link Options} * @since 1.3 */ public boolean hasShortOption(String opt) { opt = Util.stripLeadingHyphens(opt); return shortOpts.containsKey(opt); } /** * Returns the OptionGroup the <code>opt</code> belongs to. * * @param opt the option whose OptionGroup is being queried. * @return the OptionGroup if <code>opt</code> is part of an OptionGroup, otherwise return null */ public OptionGroup getOptionGroup(Option opt) { return optionGroups.get(opt.getKey()); } /** * Dump state, suitable for debugging. * * @return Stringified form of this object */ @Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append("[ Options: [ short "); buf.append(shortOpts.toString()); buf.append(" ] [ long "); buf.append(longOpts); buf.append(" ]"); return buf.toString(); } }