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

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

The newest version!
/*
 *   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.command.filter.AbstractFilter;
import com.github.fracpete.wekavirtualenv.command.filter.FilterSetup;
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.core.Utils;
import nz.ac.waikato.cms.jenericcmdline.core.OptionUtils;
import nz.ac.waikato.cms.locator.ClassLocator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

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

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

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

  /** the output listeners. */
  protected Set m_OutputListeners;

  /**
   * Initializes the command.
   */
  public AbstractCommand() {
    super();
    initialize();
  }

  /**
   * For initializing the members.
   */
  protected void initialize() {
    m_Errors          = null;
    m_OutputListeners = new HashSet<>();
  }

  /**
   * 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() ? " " : "")
      + (this instanceof CommandWithFilterSupport ? " | output filter(s)" : "")+ "\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
   * @param t 		the associated exception
   */
  public void addError(String msg, Throwable t) {
    addError(msg + "\n" + Utils.throwableToString(t));
  }

  /**
   * Stores and outputs the error message.
   *
   * @param msg		the message
   */
  public 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();
  }

  /**
   * Adds the output listener.
   *
   * @param l		the listener
   */
  public void addOutputListener(OutputListener l) {
    m_OutputListeners.add(l);
  }

  /**
   * Removes the output listener.
   *
   * @param l		the listener
   */
  public void removeOutputListener(OutputListener l) {
    m_OutputListeners.remove(l);
  }

  /**
   * Outputs the specified string to either stdout or stderr.
   *
   * @param line	the line to output
   * @param stdout	whether to output on stdout or stderr
   */
  @Override
  public void println(String line, boolean stdout) {
    if (stdout)
      System.out.println(line);
    else
      System.err.println(line);
    for (OutputListener l: m_OutputListeners)
      l.outputOccurred(line, stdout);
  }

  /**
   * Outputs the specified message on stderr.
   *
   * @param msg		the message to output
   * @param t 		the exception
   */
  @Override
  public void println(String msg, Throwable t) {
    println(msg + "\n" + Utils.throwableToString(t), false);
  }

  /**
   * 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 = CommandUtils.compress(options); if (OptionUtils.joinOptions(options).trim().length() > 0) System.err.println("Unparsed options ('" + getName() + "' does not 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(Command 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 Command) && (compareTo((Command) obj) == 0); } /** * Lists all available commands. * * @return the commands */ public static List getCommands() { List result; List classes; Command cmd; result = new ArrayList<>(); classes = ClassLocator.getSingleton().findClasses( Command.class, new String[]{Command.class.getPackage().getName()}); for (Class cls: classes) { try { cmd = (Command) 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 Command getCommand(String name) { Command result; result = null; for (Command cmd: getCommands()) { if (cmd.getName().equals(name)) { result = cmd; break; } } return result; } /** * Adds the filter to the command. * * @param setup the setup to add the filter to * @param exit whether to allow System.exit * @param filterArgs the filter arguments * @return true if successfully added */ protected static boolean addFilter(CommandSetup setup, boolean exit, List filterArgs) { FilterSetup filterSetup; filterSetup = new FilterSetup(); filterSetup.options = filterArgs.toArray(new String[filterArgs.size()]); if (!AbstractFilter.configure(filterSetup)) { System.err.println("Failed to configure filter: " + OptionUtils.joinOptions(filterArgs.toArray(new String[filterArgs.size()]))); if (exit) System.exit(1); else return false; } else { if (setup.command instanceof CommandWithFilterSupport) { ((CommandWithFilterSupport) setup.command).addFilter(filterSetup.filter); } else { System.err.println("Command '" + setup.command.getName() + "' does not support filters!"); if (exit) System.exit(1); else return false; } } filterArgs.clear(); return true; } /** * 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) { List filterArgs; int firstFilterPos; int i; setup.command = AbstractCommand.getCommand(setup.options[0]); 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 = CommandUtils.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 = CommandUtils.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; } } // filters? firstFilterPos = -1; filterArgs = new ArrayList<>(); for (i = 0; i < setup.options.length; i++) { if (setup.options[i].equals("|")) { if (filterArgs.size() > 0) { if (!addFilter(setup, exit, filterArgs)) return false; } if (firstFilterPos == -1) firstFilterPos = i; filterArgs = new ArrayList<>(); continue; } if (firstFilterPos > -1) filterArgs.add(setup.options[i]); } if (firstFilterPos > -1) { if (filterArgs.size() > 0) { if (!addFilter(setup, exit, filterArgs)) return false; } setup.options = CommandUtils.removeFrom(setup.options, firstFilterPos); } 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 - 2024 Weber Informatics LLC | Privacy Policy