Package edu.cmu.cs.ark.yc.config

Source Code of edu.cmu.cs.ark.yc.config.AppConfig

package edu.cmu.cs.ark.yc.config;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;

import com.martiansoftware.jsap.CommandLineTokenizer;
import com.martiansoftware.jsap.FlaggedOption;
import com.martiansoftware.jsap.JSAP;
import com.martiansoftware.jsap.JSAPException;
import com.martiansoftware.jsap.JSAPResult;
import com.martiansoftware.jsap.StringParser;
import com.martiansoftware.jsap.Switch;
import com.martiansoftware.jsap.stringparsers.FileStringParser;

import edu.cmu.cs.ark.yc.config.stringparsers.KeyValueParser;
import edu.cmu.cs.ark.yc.config.stringparsers.PositiveDoubleStringParser;
import edu.cmu.cs.ark.yc.config.stringparsers.PositiveIntegerStringParser;

/**
* This is an extension of <a href="http://martiansoftware.com/jsap/">Java Simple Argument Parser (JSAP)</a> that allows the use of a default <i>"configuration file"</i> using the <code>--config-file</code> option.
* <p>
* Through the <code>--config-file</code> option, {@link AppConfig} will append the contents of the configuration file to the given arguments.
* <p>
* A configuration file is essentially a text file with the command line arguments. These arguments can be separated across multiple lines and there can be comments (lines prefixed with the <code>#</code> character).
* <p>
* An example configuration file: <blockquote> <code># set the lambdas<br>
* --lambda 5,6,7<br>
* # verbose settings<br>
* --verbose</code> </blockquote>
*
* @see JSAP
* @author Yanchuan Sim
* @version 0.2
*/
public class AppConfig extends JSAP
{
  /**
   * {@link StringParser} for positive integers.
   */
  public static final PositiveIntegerStringParser POSITIVE_INTEGER_PARSER = new PositiveIntegerStringParser();

  /**
   * {@link StringParser} for positivedoubles.
   */
  public static final PositiveDoubleStringParser  POSITIVE_DOUBLE_PARSER  = new PositiveDoubleStringParser();

  /**
   * {@link StringParser} for files.
   */
  public static final FileStringParser            FILE_PARSER             = FileStringParser.getParser();

  /**
   * {@link StringParser} for key-value pairs.
   */
  public static final KeyValueParser              KEYVALUE_PARSER         = new KeyValueParser();

  /**
   * Name of this application
   */
  private final String                            name;

  /**
   * Description string for this application
   */
  private final String                            description;

  /**
   * Whether to enable the <code>--config-file</code> option
   */
  private final boolean                           enable_config;

  private boolean                                 exit_after_help;

  /**
   * Creates a new application configuration whose name is <code>name</code> and a short description about the application.
   * <p>
   * The <code>-h/--help</code>, <code>-c/--config-file</code> options are enabled and the program exits after displaying usage information (see {@link #AppConfig(String, String, boolean, boolean, boolean)}).
   *
   * @param name
   *          name of application
   * @param description
   *          short description of app.
   */
  public AppConfig(String name, String description)
  {
    super();
    this.name = name;
    this.description = description;
    this.enable_config = true;
    this.exit_after_help = true;

    init(true);
  }

  /**
   * Creates a new application configuration whose name is <code>name</code> and a short description about the application.
   * <p>
   * The <code>-h/--help</code> is enabled and the program exits after displaying usage information (see {@link #AppConfig(String, String, boolean, boolean, boolean)}).
   *
   * @param name
   *          name of application
   * @param description
   *          short description of app.
   * @param enableConfigFile
   *          enable the use of a <code>--config-file</code> option where default settings are loaded from
   */
  public AppConfig(String name, String description, boolean enableConfigFile)
  {
    super();
    this.name = name;
    this.description = description;
    this.enable_config = enableConfigFile;
    this.exit_after_help = true;

    init(true);
  }

  /**
   * Creates a new application configuration whose name is <code>name</code> and a short description about the application.
   * <p>
   * The program exits after displaying usage information (see {@link #AppConfig(String, String, boolean, boolean, boolean)}).
   *
   * @param name
   *          name of application
   * @param description
   *          short description of app.
   * @param enableConfigFile
   *          enable the use of a -c/--config-file option where default settings are loaded from
   * @param addHelpArgument
   *          enable the use of a -h/--help flag
   */
  public AppConfig(String name, String description, boolean enableConfigFile, boolean addHelpArgument)
  {
    super();
    this.name = name;
    this.description = description;
    this.enable_config = enableConfigFile;
    this.exit_after_help = true;

    init(addHelpArgument);
  }

  /**
   * Creates a new application configuration whose name is <code>name</code> and a short description about the application.
   *
   * @param name
   *          name of application
   * @param description
   *          short description of app.
   * @param enableConfigFile
   *          enable the use of a -c/--config-file option where default settings are loaded from
   * @param addHelpArgument
   *          enable the use of a -h/--help flag
   * @param exitAfterHelp
   *          whether to exit after displaying usage information when user chooses <code>-h/--help</code>
   */
  public AppConfig(String name, String description, boolean enableConfigFile, boolean addHelpArgument, boolean exitAfterHelp)
  {
    super();
    this.name = name;
    this.description = description;
    this.enable_config = enableConfigFile;
    this.exit_after_help = exitAfterHelp;

    init(addHelpArgument);
  }

  private void init(boolean addHelpArgument)
  {
    try
    {
      if (addHelpArgument)
        this.registerParameter(new Switch("help", 'h', "help", "Displays this usage information."));

      if (enable_config)
        this.registerParameter(new FlaggedOption("config-file", FileStringParser.getParser().setMustExist(true).setMustBeFile(true), null, false, JSAP.NO_SHORTFLAG, "config-file", "Load configutation options from here."));
    }
    catch (JSAPException e)
    {
      e.printStackTrace();
      System.exit(-1);
    }
  }

  /**
   * Tokenizes <code>cmdLine</code> and passes it to {@link #parse(String[])}.
   *
   * @param cmdLine
   *          An array of command line arguments to parse.
   */
  @Override
  public JSAPResult parse(String cmdLine)
  {
    return parse(CommandLineTokenizer.tokenize(cmdLine));
  }

  /**
   * Overloads {@link JSAP#parse(String[])} by providing help messages, and more importantly, checking and loading configuration settings from file automatically.
   *
   * @param args
   *          An array of command line arguments to parse.
   */
  @Override
  public JSAPResult parse(String[] args)
  {
    JSAPResult result = super.parse(args);

    if (result.contains("help"))
    {
      displayUsage();
      if (exit_after_help)
        System.exit(0);

      return result;
    }

    // if we find a config-file being specified, read it and append it to our
    // arguments!
    if (enable_config && result.contains("config-file"))
    {
      try
      {
        String[] config_commands = CommandLineTokenizer.tokenize(getArgumentsFromFile(result.getFile("config-file")));

        String[] combined_commands = new String[args.length + config_commands.length];
        for (int i = 0; i < args.length; i++)
          combined_commands[i] = args[i];
        for (int i = 0; i < config_commands.length; i++)
          combined_commands[args.length + i] = config_commands[i];

        result = super.parse(combined_commands);
      }
      catch (IOException e)
      {
        result.addException("config-file", e);
      }
    }

    if (result.contains("help") && result.getBoolean("help"))
    {
      displayUsage();
      if (exit_after_help)
        System.exit(0);
    }

    return result;
  }

  /**
   * Displays errors that occurred during parsing of command line argument.
   *
   * @param result
   *          display error messages from this {@link JSAPResult} object.
   */
  public void displayHelp(JSAPResult result)
  {
    for (@SuppressWarnings("unchecked")
    Iterator<String> iter = result.getBadParameterIDIterator(); iter.hasNext();)
    {
      String id = iter.next();
      for (Exception e : result.getExceptionArray(id))
        System.err.format("%s: %s\n", id == null ? name : id, e.getMessage());
    }
    System.err.println();
    System.err.println("Use argument -h/--help to display detailed usage information.");
  }

  /**
   * Displays usage information for this application.
   */
  public void displayUsage()
  {
    System.err.format("Usage: %s %s\n", name, this.getUsage());
    System.err.println(description);
    System.err.println();
    System.err.println("Available options are:");
    System.err.println(this.getHelp());
  }

  /**
   * Concatenates multiple non commented lines from a text file, i.e get command line from a multiline text file.
   * <p>
   * <blockquote><b>Note</b>: Assumes utf-8 encoding.</blockquote>
   *
   * @param config_file
   *          a {@link File} object pointing to the user selected configuration file.
   * @return non-commented strings concatenated together.
   * @throws IOException
   *           when there is an I/O error reading the file.
   */
  public static String getArgumentsFromFile(File config_file) throws IOException
  {
    BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(config_file), "utf-8"));
    String line;
    StringBuilder sb = new StringBuilder();
    while ((line = br.readLine()) != null)
    {
      line = line.trim();
      if (line.startsWith("#") || line.isEmpty())
        continue;

      sb.append(line);
      sb.append(' ');
    }
    br.close();

    return sb.toString();
  }
}
TOP

Related Classes of edu.cmu.cs.ark.yc.config.AppConfig

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.