All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.fracpete.wekavirtualenv.command.AbstractCommand Maven / Gradle / Ivy

/*
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see .
 */

/*
 * AbstractCommand.java
 * Copyright (C) 2017-2018 University of Waikato, Hamilton, NZ
 */

package com.github.fracpete.wekavirtualenv.command;

import com.github.fracpete.simpleargparse4j.ArgumentParser;
import com.github.fracpete.simpleargparse4j.ArgumentParserException;
import com.github.fracpete.simpleargparse4j.Namespace;
import com.github.fracpete.wekavirtualenv.core.InvalidEnvironmentException;
import com.github.fracpete.wekavirtualenv.core.MissingEnvironmentException;
import com.github.fracpete.wekavirtualenv.env.Environment;
import com.github.fracpete.wekavirtualenv.env.Environments;
import nz.ac.waikato.cms.jenericcmdline.core.OptionUtils;
import nz.ac.waikato.cms.locator.ClassLocator;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Ancestor for virtual environment commands.
 *
 * @author FracPete (fracpete at waikato dot ac dot nz)
 */
public abstract class AbstractCommand
  implements Comparable {

  /**
   * Container object for the command setup.
   */
  public static class CommandSetup
    implements Serializable {

    /** the parsed command. */
    public AbstractCommand command;

    /** the current command-line options. */
    public String[] options;
  }

  /** the environment to use. */
  protected Environment m_Env;

  /** for storing any errors. */
  protected StringBuilder m_Errors;

  /**
   * Initializes the command.
   */
  public AbstractCommand() {
    super();
    m_Errors = null;
  }

  /**
   * The name of the command (used on the commandline).
   *
   * @return		the name
   */
  public abstract String getName();

  /**
   * Returns a short help string.
   *
   * @return		the help string
   */
  public abstract String getHelp();

  /**
   * Generates a help screen.
   *
   * @param outputParser 	whether to output the help from the parser as well
   */
  public String generateHelpScreen(boolean requested, boolean outputParser) {
    StringBuilder	result;
    ArgumentParser	parser;

    result = new StringBuilder();
    if (requested) {
      result.append("Help requested");
      result.append("\n\n");
    }

    result.append(getName() + (requiresEnvironment() ? " " : "")
      + (getParser() != null ? " " : "")
      + (supportsAdditionalArguments() ? " " : "") + "\n");

    for (String line: getHelp().split("\n"))
      result.append("\t").append(line).append("\n");

    parser = getParser();
    if (outputParser && (parser != null)) {
      result.append("\n");
      result.append(parser.generateHelpScreen(false, false, false, true));
    }

    return result.toString();
  }

  /**
   * Returns whether it requires an environment.
   *
   * @return		true if required
   */
  public boolean requiresEnvironment() {
    return false;
  }

  /**
   * Stores and outputs the error message.
   *
   * @param msg		the message
   */
  protected void addError(String msg) {
    if (m_Errors == null)
      m_Errors = new StringBuilder();
    else
      m_Errors.append("\n");
    m_Errors.append(msg);
  }

  /**
   * Returns whether any errors were recorded.
   *
   * @return		true if errors present
   */
  public boolean hasErrors() {
    return (m_Errors != null);
  }

  /**
   * Returns the errors.
   *
   * @return		the errors, null if none present
   */
  public String getErrors() {
    if (m_Errors == null)
      return null;
    else
      return m_Errors.toString();
  }

  /**
   * Hook method for loading the environment.
   * 
* Instantiates the environment from the first parameter and removes this * parameter. * * @param options the options to parse */ public void loadEnv(String[] options) { if (options.length > 0) { m_Env = Environments.readEnv(options[0]); if (m_Env == null) throw new InvalidEnvironmentException(options[0]); options[0] = ""; } else { throw new MissingEnvironmentException(); } } /** * Sets the environment. * * @param value the environment */ public void setEnv(Environment value) { m_Env = value; } /** * Returns the environment, if any. * * @return the environment, null if none set */ public Environment getEnv() { return m_Env; } /** * Returns the parser to use for the arguments. * * @return the parser, null if no arguments to parse */ public ArgumentParser getParser() { return null; } /** * Returns whether the command utilizes additional arguments that get passed on. * * @return true if additional options */ public boolean supportsAdditionalArguments() { return false; } /** * Executes the command. * * @param ns the namespace of the parsed options, null if no options to parse * @param options additional command-line options * @return true if successful */ protected abstract boolean doExecute(Namespace ns, String[] options); /** * Executes the command. * * @param options the arguments for the command * @return true if successful */ public boolean execute(String[] options) { ArgumentParser parser; Namespace ns; parser = getParser(); ns = null; if (parser != null) { try { ns = parser.parseArgs(options, true); } catch (ArgumentParserException e) { parser.handleError(e); return !parser.getHelpRequested(); } } if (!supportsAdditionalArguments()) { options = compress(options); if (OptionUtils.joinOptions(options).trim().length() > 0) System.err.println("Unparsed options ('" + getName() + "' does pass on any options): " + OptionUtils.joinOptions(options)); options = new String[0]; } return doExecute(ns, options); } /** * Simply uses the command for comparing. * * @param o the other command to compare with * @return less than, equal to, or greater than zero * if the name is less than, equal to or greater */ @Override public int compareTo(AbstractCommand o) { return getName().compareTo(o.getName()); } /** * Checks whether the object is a command and has the same name. * * @param obj the object to compare with * @return true if the same command */ @Override public boolean equals(Object obj) { return (obj instanceof AbstractCommand) && (compareTo((AbstractCommand) obj) == 0); } /** * Lists all available commands. * * @return the commands */ public static List getCommands() { List result; List classes; AbstractCommand cmd; result = new ArrayList<>(); classes = ClassLocator.getSingleton().findClasses( AbstractCommand.class, new String[]{AbstractCommand.class.getPackage().getName()}); for (Class cls: classes) { try { cmd = (AbstractCommand) cls.newInstance(); result.add(cmd); } catch (Exception e) { // ignored } } Collections.sort(result); return result; } /** * Returns the command associated with the command name. * * @param name the name of the command * @return the command, null if not available */ public static AbstractCommand getCommand(String name) { AbstractCommand result; result = null; for (AbstractCommand cmd: getCommands()) { if (cmd.getName().equals(name)) { result = cmd; break; } } return result; } /** * Removes any empty strings from the array. * * @param options the options to compress * @return the compressed options */ public static String[] compress(String[] options) { List result; int i; result = new ArrayList<>(); for (i = 0; i < options.length; i++) { if (!options[i].isEmpty()) result.add(options[i]); } return result.toArray(new String[result.size()]); } /** * Configures the command setup. * * @param setup the setup to update * @param exit whether System.exit is allowed * @return the command, null if failed to configure */ public static boolean configureSetup(CommandSetup setup, boolean exit) { for (AbstractCommand c: AbstractCommand.getCommands()) { if (c.getName().equals(setup.options[0])) { setup.command = c; break; } } if (setup.command == null) { System.err.println("Unknown command: " + setup.options[0]); new Help().execute(new String[0]); if (exit) System.exit(1); else return false; } // remove command from array setup.options[0] = ""; setup.options = AbstractCommand.compress(setup.options); // check for help for (String option: setup.options) { if (option.equals("--help")) { System.out.println(setup.command.generateHelpScreen(true, true)); if (exit) System.exit(0); else return true; } } // environment name? if (setup.command.requiresEnvironment()) { try { setup.command.loadEnv(setup.options); setup.options = AbstractCommand.compress(setup.options); } catch (MissingEnvironmentException e) { System.err.println("No environment supplied!"); System.out.println(setup.command.generateHelpScreen(false, true)); if (exit) System.exit(1); else return false; } catch (InvalidEnvironmentException ie) { System.err.println("Invalid environment supplied: " + (setup.options[0])); new ListEnvs().execute(new String[0]); if (exit) System.exit(1); else return false; } } return true; } /** * Executes the command setup. * * @param setup the setup * @return true if successfully executed */ public static boolean executeSetup(CommandSetup setup) { boolean success; success = setup.command.execute(setup.options); if (!success) { if (setup.command.hasErrors()) System.err.println(setup.command.getErrors()); else System.err.println("Failed to execute command!"); return false; } return true; } /** * Parses the command-line options and executes the command if possible. * * @param args the options to use * @param exit if system exits are allowed * @return true if successful */ public static boolean parseArgs(String[] args, boolean exit) { CommandSetup setup; // output help if no options supplied if (args.length == 0) { new Help().execute(new String[0]); if (exit) System.exit(0); else return true; } // locate command setup = new CommandSetup(); setup.options = args.clone(); if (!configureSetup(setup, exit) || (setup.command == null)) return false; // execute return executeSetup(setup); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy