package org.unsynchronized; import java.io.*; import java.util.*; /** * Simple getopt()-like implementation. */ public class Getopt { private Map<String, Integer> options; private List<String> otherargs; private Map<String, String> descriptions; private Map<String, List<String>> optvals; public class OptionParseException extends Exception { public static final long serialVersionUID = 2898924890585885551L; public OptionParseException(String message) { super(message); } } /** * Gets the list arguments specified that were *not* options or their arguments, in * the order they were specified. * * @return the list of non-option String arguments */ public List<String> getOtherArguments() { return otherargs; } /** * Gets the set of all options specified, as well as the list of their arguments. * * @return a map of all options specified; values are lists of arguments */ public Map<String, List<String>> getOptionValues() { return optvals; } /** * Constructor. * * @param options Map of options to parse. The key should be an option string (including * any initial dashes), and the value should be an Integer representing the number of * arguments to parse following the option. * @param descriptions Map of option descriptions. */ public Getopt(Map<String, Integer> options, Map<String, String> descriptions) { this.options = options; this.descriptions = descriptions; } /** * Constructor. */ public Getopt() { this.options = new HashMap<String, Integer>(); this.descriptions = new HashMap<String, String>(); } /** * Determines whether or not the option was specified when the arguments were parsed. * * @return true iff the argument was specified (with the correct number of arguments). */ public boolean hasOption(String opt) { return optvals.containsKey(opt); } /** * Gets the list of arguments for a given option, or null if the option wasn't * specified. * * @param option the option * @return the list of arguments for option */ public List<String> getArguments(String option) { return optvals.get(option); } /** * Add an option to the internal set, including the number of arguments and the * description. * * @param option option string, including any leading dashes * @param arguments number of arguments * @param description description of the option */ public void addOption(String option, int arguments, String description) { options.put(option, arguments); descriptions.put(option, description); } /** * Do the parsing/validation. * @param args arguments to parse * @throws OptionParseException if a parse error occurs (the exception message will * have details) */ public void parse(String[] args) throws OptionParseException { this.otherargs = new ArrayList<String>(); this.optvals = new HashMap<String, List<String>>(); for(int i = 0; i < args.length; i++) { if(optvals != null) { Integer count = options.get(args[i]); if(count != null) { ArrayList<String> al = new ArrayList<String>(count.intValue()); for(int j = 0; j < count; j++) { if(i+1+j >= args.length) { throw new OptionParseException("expected " + count + " arguments after " + args[i]); } al.add(args[i+1+j]); } List<String> oldal = optvals.get(args[i]); if(oldal == null) { optvals.put(args[i], al); } else { oldal.addAll(al); } i += count; continue; } } otherargs.add(args[i]); } } /** * Get a tabular description of all options and their descriptions, one per line. */ public String getDescriptionString() { String linesep = System.getProperty("line.separator"); StringBuffer sb = new StringBuffer(); if(options != null && options.size() > 0) { sb.append("Options:").append(linesep); TreeSet<String> opts = new TreeSet<String>(this.options.keySet()); for(String opt: opts) { sb.append(" ").append(opt); for(int i = 0; i < options.get(opt); i++) { sb.append(" arg").append(i+1); } sb.append(": ").append(descriptions.get(opt)).append(linesep); } } return sb.toString(); } public static void main(String[] args) { try { HashMap<String, Integer> options = new HashMap<String, Integer>(); Getopt go = new Getopt(); go.addOption("-optzero", 0, "zero-arg constructor"); go.addOption("-optone", 1, "one-arg constructor"); go.addOption("-opttwo", 2, "two-arg constructor"); go.parse(args); System.out.println(go.getDescriptionString()); System.out.println("options:"); Map<String, List<String>> optvals = go.getOptionValues(); for(String opt: optvals.keySet()) { System.out.print(" " + opt); for(String optval: optvals.get(opt)) { System.out.print(" " + optval); } System.out.println(""); } System.out.println(""); System.out.println("otherargs:"); for(String arg: go.getOtherArguments()) { System.out.println(" " + arg); } } catch (Throwable t) { t.printStackTrace(); } } }