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

org.yamcs.cli.Command Maven / Gradle / Ivy

There is a newer version: 5.10.9
Show newest version
package org.yamcs.cli;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.function.IntFunction;

import org.yamcs.Plugin;
import org.yamcs.PluginManager;
import org.yamcs.PluginMetadata;
import org.yamcs.YamcsVersion;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterDescription;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.internal.Console;
import com.google.protobuf.Message;
import com.google.protobuf.util.JsonFormat;
import com.google.protobuf.util.JsonFormat.Printer;

/**
 * This represents a command together with its options and subcommands
 *
 * 
 * yamcs <options> subcmd <options> subcmd <options>...
 * 
*/ public abstract class Command { protected static Console console = JCommander.getConsole(); // called to exit the VM, overwritten in unit tests protected static IntFunction exitFunction = status -> { System.exit(status); return null; }; protected JCommander jc = new JCommander(this); protected Map subCommands = new LinkedHashMap<>(); protected Command selectedCommand; private final String name; protected final Command parent; @Parameter(names = { "-h", "--help" }, description = "Show usage", help = true) private boolean help; public Command(String name, Command parent) { this.name = name; this.parent = parent; jc.setProgramName(getFullCommandName()); } protected void addSubCommand(Command cmd) { subCommands.put(cmd.name, cmd); jc.addCommand(cmd.name, cmd); } public void parse(String... args) { int k = 0; try { if (subCommands.isEmpty()) { jc.parse(args); } else { while (k < args.length) { if (args[k].startsWith("-")) { k += getArity(args[k]); } else { break; } k++; } jc.parse(Arrays.copyOf(args, k)); } if (help) { console.println(getUsage()); exit(0); } } catch (ParameterException e) { console.println(e.getMessage()); console.println(getUsage()); exit(1); } if (subCommands.isEmpty()) { return; } // Special case. Global --version flag prints version info and quits if (getRootCommand().version) { console.println("yamcs " + YamcsVersion.VERSION + ", build " + YamcsVersion.REVISION); PluginManager pluginManager; try { pluginManager = new PluginManager(); for (Plugin plugin : ServiceLoader.load(Plugin.class)) { PluginMetadata meta = pluginManager.getMetadata(plugin.getClass()); console.println(meta.getName() + " " + meta.getVersion()); } } catch (IOException e) { throw new UncheckedIOException(e); } exit(0); } if (k == args.length) { console.println(getUsage()); exit(1); } String subcmdName = args[k]; selectedCommand = subCommands.get(subcmdName); if (selectedCommand == null) { String fullcmd = getFullCommandName(); StringBuilder sb = new StringBuilder(); sb.append(fullcmd).append(": '").append(subcmdName) .append("'").append(" is not a valid command name. See '") .append(fullcmd) .append(" -h'"); console.println(sb.toString()); exit(1); } selectedCommand.parse(Arrays.copyOfRange(args, k + 1, args.length)); } OutputFormat getFormat() { return getRootCommand().format; } private YamcsAdminCli getRootCommand() { Command command = this; while (command.parent != null) { command = command.parent; } return (YamcsAdminCli) command; } int getArity(String arg) { for (ParameterDescription pd : jc.getParameters()) { if (Arrays.asList(pd.getParameter().names()).contains(arg)) { return getArity(pd); } } throw new ParameterException("Unknown option '" + arg + "'"); } int getArity(ParameterDescription pd) { Class fieldType = pd.getParameterized().getType(); if ((fieldType == boolean.class || fieldType == Boolean.class)) { return 0; } return pd.getParameter().arity() == -1 ? 1 : pd.getParameter().arity(); } String getFullCommandName() { List a = new ArrayList<>(); Command c = this; while (c != null) { a.add(c); c = c.parent; } StringBuilder sb = new StringBuilder(); for (int i = a.size() - 1;; i--) { sb.append(a.get(i).getName()); if (i == 0) { break; } sb.append(" "); } return sb.toString(); } String printJsonArray(List messages) { StringBuilder buf = new StringBuilder("["); Printer printer = JsonFormat.printer(); try { for (int i = 0; i < messages.size(); i++) { if (i != 0) { buf.append(", "); } printer.appendTo(messages.get(i), buf); } } catch (IOException e) { throw new IllegalStateException(e); } return buf.append("]").toString(); } public String getName() { return name; } void execute() throws Exception { if (selectedCommand == null) { throw new IllegalStateException("Please implement the execute method in " + this); } else { selectedCommand.execute(); } } void validate() throws ParameterException { if (selectedCommand != null) { selectedCommand.validate(); } } public String getUsage() { StringBuilder out = new StringBuilder(); out.append("usage: " + getFullCommandName()).append(" "); List sorted = jc.getParameters(); Collections.sort(sorted, parameterDescriptionComparator); if (!sorted.isEmpty()) { out.append("[]"); } if (!subCommands.isEmpty()) { out.append(" []"); } if (jc.getMainParameter() != null) { out.append(" "); if (jc.getMainParameter().getParameter().required()) { out.append(jc.getMainParameterDescription()); } else { out.append("[").append(jc.getMainParameterDescription()).append("]"); } } out.append("\n"); if (!sorted.isEmpty()) { int maxLength = 3 + sorted.stream().map(pd -> pd.getNames().length()).max(Integer::max).get(); out.append("Options:\n"); for (ParameterDescription pd : sorted) { String descr = pd.getDescription(); String[] descrArray = descr.split("\\n"); out.append(String.format(" %-" + maxLength + "s %s\n", pd.getNames(), descrArray[0])); for (int i = 1; i < descrArray.length; i++) { String format = "%-" + (maxLength + pd.getNames().length() + 1) + "s%s\n"; out.append(String.format(format, "", descrArray[i])); } } } if (!subCommands.isEmpty()) { out.append("Commands:\n"); int maxLength = subCommands.values().stream().mapToInt(c -> c.getName().length()).max().getAsInt(); for (Command c : subCommands.values()) { String descr = jc.getCommandDescription(c.getName()); String[] descrArray = descr.split("\\n"); out.append(String.format(" %-" + maxLength + "s %s\n", c.getName(), descrArray[0])); for (int i = 1; i < descrArray.length; i++) { String format = "%-" + (maxLength + c.getName().length() + 3) + "s%s\n"; out.append(String.format(format, "", descrArray[i])); } } } return out.toString(); } protected static void exit(int status) { exitFunction.apply(status); } private Comparator parameterDescriptionComparator = (p0, p1) -> { return p0.getLongestName().compareTo(p1.getLongestName()); }; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy