001    package com.thaiopensource.util;
002    
003    public class OptionParser {
004      private final String optionSpec;
005      private char optionChar = 0;
006      private String optionArg = null;
007      private int argIndex = 0;
008      private int currentOptionIndex = 0;
009      private final String[] args;
010    
011      private static final char OPTION_CHAR = '-';
012    
013      public static class MissingArgumentException extends Exception { }
014    
015      public static class InvalidOptionException extends Exception { }
016    
017      public OptionParser(String optionSpec, String[] args) {
018        this.optionSpec = optionSpec;
019        this.args = new String[args.length];
020        System.arraycopy(args, 0, this.args, 0, args.length);
021      }
022    
023      public char getOptionChar() {
024        return optionChar;
025      }
026    
027      public String getOptionCharString() {
028        return new String(new char[]{optionChar});
029      }
030    
031      public String getOptionArg() {
032        return optionArg;
033      }
034    
035      public boolean moveToNextOption()
036        throws InvalidOptionException, MissingArgumentException {
037        if (currentOptionIndex > 0
038            && currentOptionIndex == args[argIndex].length()) {
039          currentOptionIndex = 0;
040          argIndex++;
041        }
042        if (currentOptionIndex == 0) {
043          if (argIndex >= args.length)
044            return false;
045          String arg = args[argIndex];
046          if (arg.length() < 2 || arg.charAt(0) != OPTION_CHAR)
047            return false;
048          if (arg.length() == 2 && arg.charAt(1) == OPTION_CHAR) {
049            argIndex++;
050            return false;
051          }
052          currentOptionIndex = 1;
053        }
054        optionChar = args[argIndex].charAt(currentOptionIndex++);
055        optionArg = null;
056        int i = optionSpec.indexOf(optionChar);
057        if (i < 0 || (optionChar == ':' && i > 0))
058          throw new InvalidOptionException();
059        if (i + 1 < optionSpec.length() && optionSpec.charAt(i + 1) == ':') {
060          if (currentOptionIndex < args[argIndex].length()) {
061            optionArg = args[argIndex].substring(currentOptionIndex);
062            currentOptionIndex = 0;
063            argIndex++;
064          }
065          else if (argIndex + 1 < args.length) {
066            optionArg = args[++argIndex];
067            ++argIndex;
068            currentOptionIndex = 0;
069          }
070          else
071            throw new MissingArgumentException();
072        }
073        return true;
074      }
075    
076      public String[] getRemainingArgs() {
077        String[] tem = new String[args.length - argIndex];
078        System.arraycopy(args, argIndex, tem, 0, tem.length);
079        return tem;
080      }
081    
082      public static void main(String[] args) {
083        String optSpec = args[0];
084        String[] tem = new String[args.length - 1];
085        System.arraycopy(args, 1, tem, 0, tem.length);
086        args = tem;
087        OptionParser opts = new OptionParser(optSpec, args);
088        try {
089          while (opts.moveToNextOption()) {
090            System.err.print("option " + opts.getOptionChar());
091            String arg = opts.getOptionArg();
092            if (arg == null)
093              System.err.println(" (no argument)");
094            else
095              System.err.println(" arg=" + arg);
096          }
097          args = opts.getRemainingArgs();
098          for (int i = 0; i < args.length; i++)
099            System.err.println("arg=" + args[i]);
100        }
101        catch (OptionParser.MissingArgumentException e) {
102          System.err.println("missing argument for option " + opts.getOptionChar());
103        }
104        catch (OptionParser.InvalidOptionException e) {
105          System.err.println("invalid option " + opts.getOptionChar());
106        }
107      }
108    }