emma

 = optdef;
    }
  }
}

/* Location:
 * Qualified Name:     com.vladium.util.args.OptsParser.OptDefMetadata
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package com.vladium.util.args;

import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

final class OptsParser$Opts
  implements IOptsParser.IOpts
{
  private final List m_opts;
  private final Map m_nameMap;
  private final Map m_patternMap;
  private String[] m_freeArgs;
  private List m_errors;
  private int m_usageRequestLevel;
  private static final int DEFAULT_ERROR_WIDTH = 80;
  
  public int usageRequestLevel()
  {
    return m_usageRequestLevel;
  }
  
  public void error(PrintWriter out, int width)
  {
    Iterator i;
    if (hasErrors()) {
      for (i = m_errors.iterator(); i.hasNext();) {
        out.println(i.next());
      }
    }
  }
  
  public String[] getFreeArgs()
  {
    if (hasErrors()) {
      throw new IllegalStateException(errorsToString());
    }
    return m_freeArgs;
  }
  
  public IOptsParser.IOpt[] getOpts()
  {
    if (hasErrors()) {
      return null;
    }
    if (m_opts.isEmpty()) {
      return EMPTY_OPT_ARRAY;
    }
    IOptsParser.IOpt[] result = new IOptsParser.IOpt[m_opts.size()];
    m_opts.toArray(result);
    
    return result;
  }
  
  public IOptsParser.IOpt[] getOpts(String pattern)
  {
    if (hasErrors()) {
      return null;
    }
    List patternOpts = (List)m_patternMap.get(pattern);
    if ((patternOpts == null) || (patternOpts.isEmpty())) {
      return EMPTY_OPT_ARRAY;
    }
    IOptsParser.IOpt[] result = new IOptsParser.IOpt[patternOpts.size()];
    patternOpts.toArray(result);
    
    return result;
  }
  
  public boolean hasArg(String name)
  {
    if (hasErrors()) {
      throw new IllegalStateException(errorsToString());
    }
    return m_nameMap.containsKey(name);
  }
  
  OptsParser$Opts()
  {
    m_opts = new ArrayList();
    m_nameMap = new HashMap();
    m_patternMap = new HashMap();
  }
  
  void addOpt(OptsParser.Opt opt, OptsParser.OptDef optdef, String occuranceName)
  {
    if (opt == null) {
      throw new IllegalArgumentException("null input: opt");
    }
    if (optdef == null) {
      throw new IllegalArgumentException("null input: optdef");
    }
    if (occuranceName == null) {
      throw new IllegalArgumentException("null input: occuranceName");
    }
    m_opts.add(opt);
    
    String[] names = optdef.getNames();
    boolean isPattern = opt.getPatternPrefix() != null;
    if (isPattern)
    {
      String unprefixedName = occuranceName.substring(opt.getPatternPrefix().length());
      for (int n = 0; n < names.length; n++) {
        m_nameMap.put(names[n].concat(unprefixedName), opt);
      }
      String canonicalPattern = optdef.getCanonicalName();
      
      List patternList = (List)m_patternMap.get(canonicalPattern);
      if (patternList == null)
      {
        patternList = new ArrayList();
        for (int n = 0; n < names.length; n++) {
          m_patternMap.put(names[n], patternList);
        }
      }
      patternList.add(opt);
    }
    else
    {
      for (int n = 0; n < names.length; n++) {
        m_nameMap.put(names[n], opt);
      }
    }
  }
  
  OptsParser.Opt getOpt(String occuranceName)
  {
    if (occuranceName == null) {
      throw new IllegalArgumentException("null input: occuranceName");
    }
    return (OptsParser.Opt)m_nameMap.get(occuranceName);
  }
  
  void setFreeArgs(String[] args, int start)
  {
    if (args == null) {
      throw new IllegalArgumentException("null input: args");
    }
    if ((start < 0) || (start > args.length)) {
      throw new IllegalArgumentException("invalid start index: " + start);
    }
    m_freeArgs = new String[args.length - start];
    System.arraycopy(args, start, m_freeArgs, 0, m_freeArgs.length);
  }
  
  void setUsageRequested(int level)
  {
    m_usageRequestLevel = level;
  }
  
  void addError(String msg)
  {
    if (msg != null)
    {
      if (m_errors == null) {
        m_errors = new ArrayList();
      }
      m_errors.add(msg);
    }
  }
  
  boolean hasErrors()
  {
    return (m_errors != null) && (!m_errors.isEmpty());
  }
  
  String errorsToString()
  {
    if (!hasErrors()) {
      return "<no errors>";
    }
    CharArrayWriter caw = new CharArrayWriter();
    PrintWriter pw = new PrintWriter(caw);
    
    error(pw, 80);
    pw.flush();
    
    return caw.toString();
  }
  
  private static final IOptsParser.IOpt[] EMPTY_OPT_ARRAY = new IOptsParser.IOpt[0];
}

/* Location:
 * Qualified Name:     com.vladium.util.args.OptsParser.Opts
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package com.vladium.util.args;

final class OptsParser$Token
{
  static final int EOF_ID = 0;
  static final int STRING_ID = 1;
  static final int COLON_ID = 2;
  static final int SEMICOLON_ID = 3;
  static final int COMMA_ID = 4;
  static final int LBRACKET_ID = 5;
  static final int RBRACKET_ID = 6;
  static final int OPTIONAL_ID = 7;
  static final int REQUIRED_ID = 8;
  static final int CARD_ID = 9;
  static final int VALUES_ID = 10;
  static final int TEXT_ID = 11;
  static final int REQUIRES_ID = 12;
  static final int EXCLUDES_ID = 13;
  static final int MERGEABLE_ID = 14;
  static final int DETAILEDONLY_ID = 15;
  static final int PATTERN_ID = 16;
  
  OptsParser$Token(int ID, String value)
  {
    if (value == null) {
      throw new IllegalArgumentException("null input: value");
    }
    m_ID = ID;
    m_value = value;
  }
  
  int getID()
  {
    return m_ID;
  }
  
  String getValue()
  {
    return m_value;
  }
  
  public String toString()
  {
    return m_ID + ": [" + m_value + "]";
  }
  
  static final Token EOF = new Token(0, "<EOF>");
  static final Token COLON = new Token(2, ":");
  static final Token SEMICOLON = new Token(3, ";");
  static final Token COMMA = new Token(4, ",");
  static final Token LBRACKET = new Token(5, "{");
  static final Token RBRACKET = new Token(6, "}");
  static final Token OPTIONAL = new Token(7, "optional");
  static final Token REQUIRED = new Token(8, "required");
  static final Token VALUES = new Token(10, "values");
  static final Token REQUIRES = new Token(12, "requires");
  static final Token EXCLUDES = new Token(13, "excludes");
  static final Token MERGEABLE = new Token(14, "mergeable");
  static final Token DETAILEDONLY = new Token(15, "detailedonly");
  static final Token PATTERN = new Token(16, "pattern");
  private final int m_ID;
  private final String m_value;
}

/* Location:
 * Qualified Name:     com.vladium.util.args.OptsParser.Token
 * Java Class Version: 1.2 (46.0)
 * JD-Core Version:    0.7.1
 */
package com.vladium.util.args;

import com.vladium.util.IConstants;
import com.vladium.util.ResourceLoader;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

final class OptsParser
  implements IOptsParser
{
  private final String m_msgPrefix;
  private final OptDefMetadata m_metadata;
  private static final int CANONICAL_OPT_PREFIX = 1;
  
  public synchronized void usage(PrintWriter out, int level, int width)
  {
    String prefix = OPT_PREFIXES[1];
    for (Iterator i = m_metadata.getOptDefs(); i.hasNext();)
    {
      OptDef optdef = (OptDef)i.next();
      if ((level >= 2) || (!optdef.isDetailedOnly()))
      {
        StringBuffer line = new StringBuffer("  ");
        
        String canonicalName = optdef.getCanonicalName();
        boolean isPattern = optdef.isPattern();
        
        line.append(prefix);
        line.append(canonicalName);
        if (isPattern) {
          line.append('*');
        }
        String[] names = optdef.getNames();
        for (int n = 0; n < names.length; n++)
        {
          String name = names[n];
          if (!name.equals(canonicalName))
          {
            line.append(", ");
            
            line.append(prefix);
            line.append(name);
            if (isPattern) {
              line.append('*');
            }
          }
        }
        String vmnemonic = optdef.getValueMnemonic();
        if (vmnemonic != null)
        {
          line.append(' ');
          line.append(vmnemonic);
        }
        int padding = 16 - line.length();
        if (padding < 2)
        {
          out.println(line);
          
          line.setLength(0);
          for (int p = 0; p < 16; p++) {
            line.append(' ');
          }
        }
        else
        {
          for (int p = 0; p < padding; p++) {
            line.append(' ');
          }
        }
        if (optdef.isRequired()) {
          line.append("{required} ");
        }
        line.append(optdef.getDescription());
        
        out.println(line);
      }
    }
    if (level < 2)
    {
      OptDef usageOptDef = m_metadata.getUsageOptDef();
      if ((usageOptDef != null) && (usageOptDef.getNames() != null) && (usageOptDef.getNames().length > 1))
      {
        out.println();
        out.println("  {use '" + usageOptDef.getNames()[1] + "' option to see detailed usage help}");
      }
    }
  }
  
  public synchronized IOptsParser.IOpts parse(String[] args)
  {
    if (args == null) {
      throw new IllegalArgumentException("null input: args");
    }
    Opts opts = new Opts();
    
    String[] nv = new String[2];
    String[] pp = new String[1];
    
    int state = 0;
    OptDef optdef = null;
    Opt opt = null;
    String value = null;
    int valueCount = 0;
    for (int a = 0; a < args.length;)
    {
      String av = args[a];
      if (av == null) {
        throw new IllegalArgumentException("null input: args[" + a + "]");
      }
      switch (state)
      {
      case 0: 
        if (isOpt(av, valueCount, optdef))
        {
          valueCount = 0;
          
          getOptNameAndValue(av, nv);
          
          String optName = nv[0];
          optdef = m_metadata.getOptDef(optName, pp);
          if (optdef == null)
          {
            opts.addError(formatMessage("unknown option '" + optName + "'"));
            
            state = 3;
          }
          else
          {
            String canonicalName = getOptCanonicalName(optName, optdef);
            String patternPrefix = pp[0];
            
            opt = opts.getOpt(canonicalName);
            if (optdef.isMergeable())
            {
              if (opt == null)
              {
                opt = new Opt(optName, canonicalName, patternPrefix);
                opts.addOpt(opt, optdef, optName);
              }
            }
            else if (opt == null)
            {
              opt = new Opt(optName, canonicalName, patternPrefix);
              opts.addOpt(opt, optdef, optName);
            }
            else
            {
              opts.addError(formatMessage("option '" + optName + "' cannot be specified more than once"));
              
              state = 3;
            }
            value = nv[1];
            if (value == null) {
              a++;
            }
            state = 1;
          }
        }
        else
        {
          state = 2;
        }
        break;
      case 1: 
        if (value != null)
        {
          valueCount = 1;
          
          int[] cardinality = optdef.getValueCardinality();
          if (cardinality[1] < 1)
          {
            opts.addError(formatMessage("option '" + opt.getName() + "' does not accept values: '" + value + "'"));
            
            state = 3;
          }
          else
          {
            a++;
            opt.addValue(value);
          }
        }
        else
        {
          value = args[a];
          
          int[] cardinality = optdef.getValueCardinality();
          if (isOpt(value, valueCount, optdef))
          {
            if (valueCount < cardinality[0])
            {
              opts.addError(formatMessage("option '" + opt.getName() + "' does not accept fewer than " + cardinality[0] + " value(s)"));
              
              state = 3;
            }
            else
            {
              state = 0;
            }
          }
          else if (valueCount < cardinality[1])
          {
            valueCount++;
            a++;
            opt.addValue(value);
          }
          else
          {
            state = 2;
          }
        }
        value = null;
        
        break;
      case 2: 
        if (isOpt(args[a], valueCount, optdef)) {
          state = 0;
        } else {
          opts.setFreeArgs(args, a);
        }
        break;
      case 3: 
        break label629;
      }
    }
    label629:
    if (a == args.length) {
      if (opt != null)
      {
        int[] cardinality = optdef.getValueCardinality();
        if (valueCount < cardinality[0]) {
          opts.addError(formatMessage("option '" + opt.getName() + "' does not accept fewer than " + cardinality[0] + " value(s)"));
        }
      }
      else
      {
        opts.setFreeArgs(args, a);
      }
    }
    IOptsParser.IOpt[] specified = opts.getOpts();
    if (specified != null)
    {
      Set required = new HashSet();
      required.addAll(m_metadata.getRequiredOpts());
      for (int s = 0; s < specified.length; s++) {
        required.remove(specified[s].getCanonicalName());
      }
      Iterator i;
      if (!required.isEmpty()) {
        for (i = required.iterator(); i.hasNext();) {
          opts.addError(formatMessage("missing required option '" + (String)i.next() + "'"));
        }
      }
      for (int s = 0; s < specified.length; s++)
      {
        IOptsParser.IOpt opt = specified[s];
        OptDef optdef = m_metadata.getOptDef(opt.getCanonicalName(), null);
        
        String[] requires = optdef.getRequiresSet();
        if (requires != null) {
          for (int r = 0; r < requires.length; r++) {
            if (opts.getOpt(requires[r]) == null) {
              opts.addError(formatMessage("option '" + opt.getName() + "' requires option '" + requires[r] + "'"));
            }
          }
        }
        String[] excludes = optdef.getExcludesSet();
        if (excludes != null) {
          for (int x = 0; x < excludes.length; x++)
          {
            Opt xopt = opts.getOpt(excludes[x]);
            if (xopt != null) {
              opts.addError(formatMessage("option '" + opt.getName() + "' cannot be used with option '" + xopt.getName() + "'"));
            }
          }
        }
        if (optdef.isUsage()) {
          opts.setUsageRequested(opt.getName().equals(opt.getCanonicalName()) ? 1 : 2);
        }
      }
    }
    return opts;
  }
  
  private static String getOptCanonicalName(String n, OptDef optdef)
  {
    if (optdef.isPattern())
    {
      String canonicalPattern = optdef.getCanonicalName();
      String[] patterns = optdef.getNames();
      for (int p = 0; p < patterns.length; p++)
      {
        String pattern = patterns[p];
        if (n.startsWith(pattern)) {
          return canonicalPattern.concat(n.substring(pattern.length()));
        }
      }
      throw new IllegalStateException("failed to detect pattern prefix for [" + n + "]");
    }
    return optdef.getCanonicalName();
  }
  
  private static boolean isOpt(String av, int valueCount, OptDef optdef)
  {
    if (optdef != null)
    {
      int[] cardinality = optdef.getValueCardinality();
      if (valueCount < cardinality[1]) {
        return false;
      }
    }
    for (int p = 0; p < OPT_PREFIXES.length; p++) {
      if (av.startsWith(OPT_PREFIXES[p])) {
        return av.length() > OPT_PREFIXES[p].length();
      }
    }
    return false;
  }
  
  private static void getOptNameAndValue(String av, String[] nv)
  {
    nv[0] = null;
    nv[1] = null;
    for (int p = 0; p < OPT_PREFIXES.length; p++) {
      if ((av.startsWith(OPT_PREFIXES[p])) && (av.length() > OPT_PREFIXES[p].length()))
      {
        String name = av.substring(OPT_PREFIXES[p].length());
        
        char separator = '\000';
        int sindex = Integer.MAX_VALUE;
        for (int s = 0; s < OPT_VALUE_SEPARATORS.length; s++)
        {
          int index = name.indexOf(OPT_VALUE_SEPARATORS[s]);
          if ((index > 0) && (index < sindex))
          {
            separator = OPT_VALUE_SEPARATORS[s];
            sindex = index;
          }
        }
        if (separator != 0)
        {
          nv[0] = name.substring(0, sindex);
          nv[1] = name.substring(sindex + 1);
        }
        else
        {
          nv[0] = name;
        }
        return;
      }
    }
  }
  
  static final class Opt
    implements IOptsParser.IOpt
  {
    private final String m_name;
    private final String m_canonicalName;
    private final String m_patternPrefix;
    private ArrayList m_values;
    
    public String getName()
    {
      return m_name;
    }
    
    public String getCanonicalName()
    {
      return m_canonicalName;
    }
    
    public int getValueCount()
    {
      if (m_values == null) {
        return 0;
      }
      return m_values.size();
    }
    
    public String getFirstValue()
    {
      if (m_values == null) {
        return null;
      }
      return (String)m_values.get(0);
    }
    
    public String[] getValues()
    {
      if (m_values == null) {
        return IConstants.EMPTY_STRING_ARRAY;
      }
      String[] result = new String[m_values.size()];
      m_values.toArray(result);
      
      return result;
    }
    
    public String getPatternPrefix()
    {
      return m_patternPrefix;
    }
    
    public String toString()
    {
      StringBuffer s = new StringBuffer(m_name);
      if (!m_canonicalName.equals(m_name)) {
        s.append(" [" + m_canonicalName + "]");
      }
      if (m_values != null)
      {
        s.append(": ");
        s.append(m_values);
      }
      return s.toString();
    }
    
    Opt(String name, String canonicalName, String patternPrefix)
    {
      m_name = name;
      m_canonicalName = canonicalName;
      m_patternPrefix = patternPrefix;
    }
    
    void addValue(String value)
    {
      if (value == null) {
        throw new IllegalArgumentException("null input: value");
      }
      if (m_values == null) {
        m_values = new ArrayList();
      }
      m_values.add(value);
    }
  }
  
  static final class Opts
    implements IOptsParser.IOpts
  {
    private final List m_opts;
    private final Map m_nameMap;
    private final Map m_patternMap;
    private String[] m_freeArgs;
    private List m_errors;
    private int m_usageRequestLevel;
    private static final int DEFAULT_ERROR_WIDTH = 80;
    
    public int usageRequestLevel()
    {
      return m_usageRequestLevel;
    }
    
    public void error(PrintWriter out, int width)
    {
      Iterator i;
      if (hasErrors()) {
        for (i = m_errors.iterator(); i.hasNext();) {
          out.println(i.next());
        }
      }
    }
    
    public String[] getFreeArgs()
    {
      if (hasErrors()) {
        throw new IllegalStateException(errorsToString());
      }
      return m_freeArgs;
    }
    
    public IOptsParser.IOpt[] getOpts()
    {
      if (hasErrors()) {
        return null;
      }
      if (m_opts.isEmpty()) {
        return EMPTY_OPT_ARRAY;
      }
      IOptsParser.IOpt[] result = new IOptsParser.IOpt[m_opts.size()];
      m_opts.toArray(result);
      
      return result;
    }
    
    public IOptsParser.IOpt[] getOpts(String pattern)
    {
      if (hasErrors()) {
        return null;
      }
      List patternOpts = (List)m_patternMap.get(pattern);
      if ((patternOpts == null) || (patternOpts.isEmpty())) {
        return EMPTY_OPT_ARRAY;
      }
      IOptsParser.IOpt[] result = new IOptsParser.IOpt[patternOpts.size()];
      patternOpts.toArray(result);
      
      return result;
    }
    
    public boolean hasArg(String name)
    {
      if (hasErrors()) {
        throw new IllegalStateException(errorsToString());
      }
      return m_nameMap.containsKey(name);
    }
    
    Opts()
    {
      m_opts = new ArrayList();
      m_nameMap = new HashMap();
      m_patternMap = new HashMap();
    }
    
    void addOpt(OptsParser.Opt opt, OptsParser.OptDef optdef, String occuranceName)
    {
      if (opt == null) {
        throw new IllegalArgumentException("null input: opt");
      }
      if (optdef == null) {
        throw new IllegalArgumentException("null input: optdef");
      }
      if (occuranceName == null) {
        throw new IllegalArgumentException("null input: occuranceName");
      }
      m_opts.add(opt);
      
      String[] names = optdef.getNames();
      boolean isPattern = opt.getPatternPrefix() != null;
      if (isPattern)
      {
        String unprefixedName = occuranceName.substring(opt.getPatternPrefix().length());
        for (int n = 0; n < names.length; n++) {
          m_nameMap.put(names[n].concat(unprefixedName), opt);
        }
        String canonicalPattern = optdef.getCanonicalName();
        
        List patternList = (List)m_patternMap.get(canonicalPattern);
        if (patternList == null)
        {
          patternList = new ArrayList();
          for (int n = 0; n < names.length; n++) {
            m_patternMap.put(names[n], patternList);
          }
        }
        patternList.add(opt);
      }
      else
      {
        for (int n = 0; n < names.length; n++) {
          m_nameMap.put(names[n], opt);
        }
      }
    }
    
    OptsParser.Opt getOpt(String occuranceName)
    {
      if (occuranceName == null) {
        throw new IllegalArgumentException("null input: occuranceName");
      }
      return (OptsParser.Opt)m_nameMap.get(occuranceName);
    }
    
    void setFreeArgs(String[] args, int start)
    {
      if (args == null) {
        throw new IllegalArgumentException("null input: args");
      }
      if ((start < 0) || (start > args.length)) {
        throw new IllegalArgumentException("invalid start index: " + start);
      }
      m_freeArgs = new String[args.length - start];
      System.arraycopy(args, start, m_freeArgs, 0, m_freeArgs.length);
    }
    
    void setUsageRequested(int level)
    {
      m_usageRequestLevel = level;
    }
    
    void addError(String msg)
    {
      if (msg != null)
      {
        if (m_errors == null) {
          m_errors = new ArrayList();
        }
        m_errors.add(msg);
      }
    }
    
    boolean hasErrors()
    {
      return (m_errors != null) && (!m_errors.isEmpty());
    }
    
    String errorsToString()
    {
      if (!hasErrors()) {
        return "<no errors>";
      }
      CharArrayWriter caw = new CharArrayWriter();
      PrintWriter pw = new PrintWriter(caw);
      
      error(pw, 80);
      pw.flush();
      
      return caw.toString();
    }
    
    private static final IOptsParser.IOpt[] EMPTY_OPT_ARRAY = new IOptsParser.IOpt[0];
  }
  
  static final class OptDef
  {
    OptDef(boolean usage)
    {
      m_usage = usage;
    }
    
    boolean isUsage()
    {
      return m_usage;
    }
    
    String getCanonicalName()
    {
      return m_names[0];
    }
    
    String[] getNames()
    {
      return m_names;
    }
    
    boolean isRequired()
    {
      return m_required;
    }
    
    String getValueMnemonic()
    {
      return m_valueMnemonic;
    }
    
    boolean isMergeable()
    {
      return m_mergeable;
    }
    
    boolean isDetailedOnly()
    {
      return m_detailedOnly;
    }
    
    boolean isPattern()
    {
      return m_pattern;
    }
    
    int[] getValueCardinality()
    {
      return m_valueCardinality;
    }
    
    String[] getRequiresSet()
    {
      return m_requiresSet;
    }
    
    String[] getExcludesSet()
    {
      return m_excludesSet;
    }
    
    String getDescription()
    {
      return m_description;
    }
    
    void setNames(String[] names)
    {
      if (names == null) {
        throw new IllegalArgumentException("null input: names");
      }
      m_names = names;
    }
    
    void setRequired(boolean required)
    {
      m_required = required;
    }
    
    void setValueMnemonic(String mnemonic)
    {
      if (mnemonic == null) {
        throw new IllegalArgumentException("null input: mnemonic");
      }
      m_valueMnemonic = mnemonic;
    }
    
    void setMergeable(boolean mergeable)
    {
      m_mergeable = mergeable;
    }
    
    void setDetailedOnly(boolean detailedOnly)
    {
      m_detailedOnly = detailedOnly;
    }
    
    void setPattern(boolean pattern)
    {
      m_pattern = pattern;
    }
    
    void setValueCardinality(int[] cardinality)
    {
      if ((cardinality == null) || (cardinality.length != 2)) {
        throw new IllegalArgumentException("null or invalid input: cardinality");
      }
      m_valueCardinality = cardinality;
    }
    
    void setRequiresSet(String[] names)
    {
      if (names == null) {
        throw new IllegalArgumentException("null input: names");
      }
      m_requiresSet = (names.length > 0 ? names : null);
    }
    
    void setExcludesSet(String[] names)
    {
      if (names == null) {
        throw new IllegalArgumentException("null input: names");
      }
      m_excludesSet = (names.length > 0 ? names : null);
    }
    
    void setDescription(String description)
    {
      if (description == null) {
        throw new IllegalArgumentException("null input: description");
      }
      m_description = description;
    }
    
    static final int[] C_ZERO = { 0, 0 };
    static final int[] C_ONE = { 1, 1 };
    static final int[] C_ZERO_OR_ONE = { 0, 1 };
    static final int[] C_ZERO_OR_MORE = { 0, Integer.MAX_VALUE };
    static final int[] C_ONE_OR_MORE = { 1, Integer.MAX_VALUE };
    private final boolean m_usage;
    private String[] m_names;
    private boolean m_required;
    private String m_valueMnemonic;
    private boolean m_mergeable;
    private boolean m_detailedOnly;
    private boolean m_pattern;
    private int[] m_valueCardinality;
    private String[] m_requiresSet;
    private String[] m_excludesSet;
    private String m_description;
  }
  
  static final class OptDefMetadata
  {
    final List m_optdefs;
    final Map m_optdefMap;
    final Set m_requiredOpts;
    final Map m_patternOptDefMap;
    private OptsParser.OptDef m_usageOptDef;
    
    OptDefMetadata()
    {
      m_optdefs = new ArrayList();
      m_optdefMap = new HashMap();
      m_requiredOpts = new HashSet();
      m_patternOptDefMap = new HashMap();
    }
    
    OptsParser.OptDef getOptDef(String name, String[] prefixout)
    {
      if (name == null) {
        throw new IllegalArgumentException("null input: name");
      }
      if (prefixout != null) {
        prefixout[0] = null;
      }
      OptsParser.OptDef result = (OptsParser.OptDef)m_optdefMap.get(name);
      if (result == null)
      {
        Iterator ps = m_patternOptDefMap.entrySet().iterator();
        while (ps.hasNext())
        {
          Map.Entry entry = (Map.Entry)ps.next();
          String pattern = (String)entry.getKey();
          if (name.startsWith(pattern))
          {
            if (prefixout != null) {
              prefixout[0] = pattern;
            }
            result = (OptsParser.OptDef)entry.getValue();
            break;
          }
        }
      }
      return result;
    }
    
    Iterator getOptDefs()
    {
      return m_optdefs.iterator();
    }
    
    OptsParser.OptDef getPatternOptDefs(String pattern)
    {
      if (pattern == null) {
        throw new IllegalArgumentException("null input: pattern");
      }
      return (OptsParser.OptDef)m_patternOptDefMap.get(pattern);
    }
    
    Set getRequiredOpts()
    {
      return m_requiredOpts;
    }
    
    OptsParser.OptDef getUsageOptDef()
    {
      return m_usageOptDef;
    }
    
    void addOptDef(OptsParser.OptDef optdef)
    {
      if (optdef == null) {
        throw new IllegalArgumentException("null input: optdef");
      }
      Map map = optdef.isPattern() ? m_patternOptDefMap : m_optdefMap;
      String[] names = optdef.getNames();
      for (int n = 0; n < names.length; n++)
      {
        if (map.containsKey(names[n])) {
          throw new IllegalArgumentException("duplicate option name [" + names[n] + "]");
        }
        map.put(names[n], optdef);
      }
      m_optdefs.add(optdef);
      if (optdef.isRequired()) {
        m_requiredOpts.add(optdef.getCanonicalName());
      }
      if (optdef.isUsage())
      {
        if (m_usageOptDef != null) {
          throw new IllegalArgumentException("usage optdef set already");
        }
        m_usageOptDef = optdef;
      }
    }
  }
  
  static final class MetadataParser
  {
    private Reader m_in;
    private List m_opts;
    private OptsParser.Token m_token;
    private int m_currentChar;
    private static final Map KEYWORDS;
    
    OptsParser.OptDef[] parse(Reader in)
    {
      if (in == null) {
        throw new IllegalArgumentException("null input: in");
      }
      m_in = in;
      
      nextChar();
      nextToken();
      while (m_token != OptsParser.Token.EOF)
      {
        if (m_opts == null) {
          m_opts = new ArrayList();
        }
        m_opts.add(optdef());
      }
      OptsParser.OptDef[] result;
      OptsParser.OptDef[] result;
      if ((m_opts == null) || (m_opts.size() == 0))
      {
        result = EMPTY_OPTDEF_ARRAY;
      }
      else
      {
        result = new OptsParser.OptDef[m_opts.size()];
        m_opts.toArray(result);
      }
      m_in = null;
      m_opts = null;
      
      return result;
    }
    
    OptsParser.OptDef optdef()
    {
      OptsParser.OptDef optdef = new OptsParser.OptDef(false);
      
      optdef.setNames(optnamelist());
      accept(2);
      optmetadata(optdef);
      accept(3);
      
      return optdef;
    }
    
    String[] optnamelist()
    {
      return namelist();
    }
    
    void optmetadata(OptsParser.OptDef optdef)
    {
      switch (m_token.getID())
      {
      case 8: 
        accept();
        optdef.setRequired(true);
        
        break;
      case 7: 
        accept();
        optdef.setRequired(false);
        
        break;
      default: 
        throw new IllegalArgumentException("parse error: invalid token " + m_token + ", expected " + OptsParser.Token.REQUIRED + " or " + OptsParser.Token.OPTIONAL);
      }
      accept(4);
      if (m_token.getID() == 14)
      {
        accept();
        optdef.setMergeable(true);
        
        accept(4);
      }
      if (m_token.getID() == 15)
      {
        accept();
        optdef.setDetailedOnly(true);
        
        accept(4);
      }
      if (m_token.getID() == 16)
      {
        accept();
        optdef.setPattern(true);
        
        accept(4);
      }
      accept(10);
      accept(2);
      optdef.setValueCardinality(cardinality());
      
      accept(4);
      if (m_token.getID() == 1)
      {
        optdef.setValueMnemonic(m_token.getValue());
        accept();
        
        accept(4);
      }
      if (m_token.getID() == 12)
      {
        accept();
        
        accept(5);
        optdef.setRequiresSet(namelist());
        accept(6);
        
        accept(4);
      }
      if (m_token.getID() == 13)
      {
        accept();
        
        accept(5);
        optdef.setExcludesSet(namelist());
        accept(6);
        
        accept(4);
      }
      optdef.setDescription(accept(11).getValue());
    }
    
    int[] cardinality()
    {
      OptsParser.Token result = accept(9);
      if ("0".equals(result.getValue())) {
        return OptsParser.OptDef.C_ZERO;
      }
      if ("1".equals(result.getValue())) {
        return OptsParser.OptDef.C_ONE;
      }
      return OptsParser.OptDef.C_ZERO_OR_ONE;
    }
    
    String[] namelist()
    {
      List _result = new ArrayList();
      
      _result.add(accept(1).getValue());
      while (m_token.getID() == 4)
      {
        accept();
        _result.add(accept(1).getValue());
      }
      String[] result = new String[_result.size()];
      _result.toArray(result);
      
      return result;
    }
    
    OptsParser.Token accept()
    {
      OptsParser.Token current = m_token;
      nextToken();
      
      return current;
    }
    
    OptsParser.Token accept(int tokenID)
    {
      OptsParser.Token current = m_token;
      if (m_token.getID() == tokenID) {
        nextToken();
      } else {
        throw new IllegalArgumentException("parse error: invalid token [" + m_token + "], expected type [" + tokenID + "]");
      }
      return current;
    }
    
    void nextToken()
    {
      consumeWS();
      switch (m_currentChar)
      {
      case -1: 
        m_token = OptsParser.Token.EOF; break;
      case 58: 
        nextChar();
        m_token = OptsParser.Token.COLON;
        
        break;
      case 59: 
        nextChar();
        m_token = OptsParser.Token.SEMICOLON;
        
        break;
      case 44: 
        nextChar();
        m_token = OptsParser.Token.COMMA;
        
        break;
      case 123: 
        nextChar();
        m_token = OptsParser.Token.LBRACKET;
        
        break;
      case 125: 
        nextChar();
        m_token = OptsParser.Token.RBRACKET;
        
        break;
      case 48: 
        nextChar();
        m_token = new OptsParser.Token(9, "0");
        
        break;
      case 49: 
        nextChar();
        m_token = new OptsParser.Token(9, "1");
        
        break;
      case 63: 
        nextChar();
        m_token = new OptsParser.Token(9, "?");
        
        break;
      case 39: 
        StringBuffer value = new StringBuffer();
        
        nextChar();
        while (m_currentChar != 39)
        {
          value.append((char)m_currentChar);
          nextChar();
        }
        nextChar();
        
        m_token = new OptsParser.Token(1, value.toString());
        
        break;
      case 34: 
        StringBuffer value = new StringBuffer();
        
        nextChar();
        while (m_currentChar != 34)
        {
          value.append((char)m_currentChar);
          nextChar();
        }
        nextChar();
        
        m_token = new OptsParser.Token(11, value.toString());
        
        break;
      default: 
        StringBuffer value = new StringBuffer();
        while (Character.isLetter((char)m_currentChar))
        {
          value.append((char)m_currentChar);
          nextChar();
        }
        OptsParser.Token token = (OptsParser.Token)KEYWORDS.get(value.toString());
        if (token == null) {
          throw new IllegalArgumentException("parse error: unrecognized keyword [" + value + "]");
        }
        m_token = token;
      }
    }
    
    private void consumeWS()
    {
      if (m_currentChar == -1) {
        return;
      }
      while (Character.isWhitespace((char)m_currentChar)) {
        nextChar();
      }
    }
    
    private void nextChar()
    {
      try
      {
        m_currentChar = m_in.read();
      }
      catch (IOException ioe)
      {
        throw new RuntimeException("I/O error while parsing: " + ioe);
      }
    }
    
    private static final OptsParser.OptDef[] EMPTY_OPTDEF_ARRAY = new OptsParser.OptDef[0];
    
    static
    {
      KEYWORDS = new HashMap(17);
      
      KEYWORDS.put(OptsParser.Token.OPTIONAL.getValue(), OptsParser.Token.OPTIONAL);
      KEYWORDS.put(OptsParser.Token.REQUIRED.getValue(), OptsParser.Token.REQUIRED);
      KEYWORDS.put(OptsParser.Token.VALUES.getValue(), OptsParser.Token.VALUES);
      KEYWORDS.put(OptsParser.Token.REQUIRES.getValue(), OptsParser.Token.REQUIRES);
      KEYWORDS.put(OptsParser.Token.EXCLUDES.getValue(), OptsParser.Token.EXCLUDES);
      KEYWORDS.put(OptsParser.Token.MERGEABLE.getValue(), OptsParser.Token.MERGEABLE);
      KEYWORDS.put(OptsParser.Token.DETAILEDONLY.getValue(), OptsParser.Token.DETAILEDONLY);
      KEYWORDS.put(OptsParser.Token.PATTERN.getValue(), OptsParser.Token.PATTERN);
    }
  }
  
  OptsParser(String metadataResourceName, ClassLoader loader, String[] usageOpts)
  {
    this(metadataResourceName, loader, null, usageOpts);
  }
  
  OptsParser(String metadataResourceName, ClassLoader loader, String msgPrefix, String[] usageOpts)
  {
    if (metadataResourceName == null) {
      throw new IllegalArgumentException("null input: metadataResourceName");
    }
    m_msgPrefix = msgPrefix;
    
    InputStream in = null;
    try
    {
      in = ResourceLoader.getResourceAsStream(metadataResourceName, loader);
      if (in == null) {
        throw new IllegalArgumentException("resource [" + metadataResourceName + "] could not be loaded via [" + loader + "]");
      }
      Reader rin = new InputStreamReader(in);
      
      m_metadata = parseOptDefMetadata(rin, usageOpts);
    }
    finally
    {
      if (in != null) {
        try
        {
          in.close();
        }
        catch (IOException ignore) {}
      }
    }
  }
  
  private static final class Token
  {
    static final int EOF_ID = 0;
    static final int STRING_ID = 1;
    static final int COLON_ID = 2;
    static final int SEMICOLON_ID = 3;
    static final int COMMA_ID = 4;
    static final int LBRACKET_ID = 5;
    static final int RBRACKET_ID = 6;
    static final int OPTIONAL_ID = 7;
    static final int REQUIRED_ID = 8;
    static final int CARD_ID = 9;
    static final int VALUES_ID = 10;
    static final int TEXT_ID = 11;
    static final int REQUIRES_ID = 12;
    static final int EXCLUDES_ID = 13;
    static final int MERGEABLE_ID = 14;
    static final int DETAILEDONLY_ID = 15;
    static final int PATTERN_ID = 16;
    
    Token(int ID, String value)
    {
      if (value == null) {
        throw new IllegalArgumentException("null input: value");
      }
      m_ID = ID;
      m_value = value;
    }
    
    int getID()
    {
      return m_ID;
    }
    
    String getValue()
    {
      return m_value;
    }
    
    public String toString()
    {
      return m_ID + ": [" + m_value + "]";
    }
    
    static final Token EOF = new Token(0, "<EOF>");
    static final Token COLON = new Token(2, ":");
    static final Token SEMICOLON = new Token(3, ";");
    static final Token COMMA = new Token(4, ",");
    static final Token LBRACKET = new Token(5, "{");
    static final Token RBRACKET = new Token(6, "}");
    static final Token OPTIONAL = new Token(7, "optional");
    static final Token REQUIRED = new Token(8, "required");
    static final Token VALUES = new Token(10, "values");
    static final Token REQUIRES = new Token(12, "requires");
    static final Token EXCLUDES = new Token(13, "excludes");
    static final Token MERGEABLE = new Token(14, "mergeable");
    static final Token DETAILEDONLY = new Token(15, "detailedonly");
    static final Token PATTERN = new Token(16, "pattern");
    private final int m_ID;
    private final String m_value;
  }
  
  private static OptDefMetadata parseOptDefMetadata(Reader in, String[] usageOpts)
  {
    MetadataParser parser = new MetadataParser();
    OptDef[] optdefs = parser.parse(in);
    
    OptDefMetadata result = new OptDefMetadata();
    for (int o = 0; o < optdefs.length; o++) {
      result.addOptDef(optdefs[o]);
    }
    if (usageOpts != null)
    {
      OptDef usage = new OptDef(true);
      
      usage.setNames(usageOpts);
      usage.setDescription("display usage information");
      usage.setValueCardinality(OptDef.C_ZERO);
      usage.setRequired(false);
      usage.setDetailedOnly(false);
      usage.setMergeable(false);
      
      result.addOptDef(usage);
    }
    for (int o = 0; o < optdefs.length; o++)
    {
      OptDef optdef = optdefs[o];
      
      String[] requires = optdef.getRequiresSet();
      if (requires !
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2017. Infinite Loop Ltd