// ==========================================================================
// $Id: OptionMap.java,v 1.2 2002/09/09 20:12:30 hitoshi Exp $
// Option Map : a map of parsed command line option
// ==========================================================================
// Copyright (C) 2002 Yamauchi, Hitoshi
//
//   Max-Planck-Institut fuer Informatik AG4
//   Stuhlsatzenhausweg 85, 66123 Saarbruecken
//   http://www.mpi-sb.mpg.de/
// 
// This software can be redistributed only under GNU copyleft.
//
// @author Yamauchi Hitoshi »³Æâ ÀÆ
// ==========================================================================
// $Revision: 1.2 $
// $Date: 2002/09/09 20:12:30 $
// $Author: hitoshi $
// ==========================================================================
package de.mpg.mpisb.timerclock;

import  java.util.*;

/**
 * A utility for Option
 *   1. new and set the Options 
 *   2. parse command line arguments
 *   3. access with key
 * 
 * When a switch is not setted, it value is null then use get() to access.
 * Otherwise default value will be returned.
 */
public class OptionMap 
{
  /**
   * constructor
   */
  public OptionMap()
  {
    this.mOptions = null;
    this.mOptMap  = null;
  }

  /**
   * constructor
   */
  public OptionMap(Option [] options)
  {
    this.setOptions(options);
    this.mOptMap  = null;
  }

  /**
   * set option
   *  @param options 
   */
  public void setOptions(Option [] options)
  {
    this.mOptions = options;
  }

  /**
   * get options
   *  @return options
   */
  public Option [] peekOptions()
  {
    return(this.mOptions);
  }

  /** 
   * get String representation of this instance
   */
  public String toString()  
  {
    String r = "";
    for(Iterator i = this.mOptMap.keySet().iterator(); i.hasNext(); )
    {
      String key = (String)(i.next());
      r += (key + " :\t");
      Object val = this.mOptMap.get(key);
      if(val == null)
      {
	r += "null";
      }
      else
      {
	r += val.toString();
      }
      if(i.hasNext())
      {
	r += "\n";
      }
    }
    return(r);
  }
  
  /**
   * getOpts : analyze and set command line argument
   * @param args command line arguments
   */
  public void getOpts(String [] args)
  {
    this.mOptMap = new HashMap();
    Option.CommandLine cl = null;
    Map m = null;
    try {
      cl = Option.parseCommandLine(this.mOptions, args);
      m = cl.getOptions();
    }
    catch(IllegalArgumentException e)
    {
      System.out.println("Error! : " + e.getMessage());
      Option.printHelp(System.err, "\t", this.mOptions);
    }

    for(int i = 0; i < this.mOptions.length; i++)
    {
      if(m.get(this.mOptions[i].getName()) == null)
      {
	this.mOptMap.put(this.mOptions[i].getName(), 
			 this.mOptions[i].getDefaultValue());
      }
      else 
      {
	this.mOptMap.put(this.mOptions[i].getName(), 
			 m.get(this.mOptions[i].getName()));
      }
    }
  }
  
  /**
   * get option 
   */
  public Object get(String optionkey)
  {
    return(this.mOptMap.get(optionkey));    
  }

  /**
   * some utility for get option 
   */
  /**
   * get option : it should have a default value.
   */
  private Object getObjectOption(String optionkey)
  {
    if(this.mOptMap.get(optionkey) == null)
    {
      throw new RuntimeException("No such option is registered. " + optionkey);
    }
    return(this.mOptMap.get(optionkey));    
  }
  /**
   * get integer option 
   */
  public int getIntegerOption(String optionkey)
  {
    Object i = this.getObjectOption(optionkey);
    if(i instanceof Integer)
    {
      return(((Integer)i).intValue());
    }
    else 
    {
      throw new RuntimeException("The " + optionkey + " is not a integer.");
    }
  }
  /**
   * get double option 
   */
  public double getDoubleOption(String optionkey)
  {
    Object i = this.getObjectOption(optionkey);
    if(i instanceof Double)
    {
      return(((Double)i).doubleValue());
    }
    else 
    {
      throw new RuntimeException("The " + optionkey + " is not a Double.");
    }
  }
  /**
   * get string option 
   */
  public String getStringOption(String optionkey)
  {
    Object s = this.getObjectOption(optionkey);
    if(s instanceof String)
    {
      return((String)s);
    }
    else 
    {
      throw new RuntimeException("The " + optionkey + " is not a String.");
    }
  }
  /**
   * get boolean option
   */
  public boolean getBooleanOption(String optionkey)
  {
    Object b = this.getObjectOption(optionkey);
    if(b instanceof Boolean)
    {
      return(((Boolean)b).booleanValue());
    }
    else 
    {
      throw new RuntimeException("The " + optionkey + " is not a boolean.");
    }
  }
  
  /**
   * get help string
   */
  public String getHelpString()
  {
    return(Option.getHelpString("\t", this.mOptions));
  }

  // private variables
  private Option [] mOptions = null;
  private Map 	    mOptMap  = null;

  /*
   * test for OptionMap
   */
  public static void main(String [] arg)
  {
    Option[] options = 
    {
      new Option("help",   "h", Option.NO_ARG, Option.BOOLEAN, null, "print help"),
      new Option("verbose","v", Option.NO_ARG, Option.BOOLEAN, null, "verbose mode"),
      new Option("start-time", 	"s",  Option.REQUIRED_ARG, Option.INT, 
		 new Integer(100), "start time of the clock (seconds)"),
      new Option("font-name", 	"f",  Option.REQUIRED_ARG, Option.STRING, 
		 new String("Times Roman"), "font name"),
    };
    
    OptionMap opt = new OptionMap(options);
    opt.getOpts(arg);

    Option.printHelp(System.out, "\t", options);
    System.out.println(opt.toString());

    System.out.println("start-time = " + opt.getIntegerOption("start-time"));
  }
}
