com.yahoo.vespaget.CommandLineOptions Maven / Gradle / Ivy
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespaget;
import com.yahoo.document.fieldset.DocumentOnly;
import com.yahoo.document.fieldset.DocIdOnly;
import com.yahoo.documentapi.messagebus.protocol.DocumentProtocol;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
/**
* This class is responsible for parsing the command line arguments and print the help page.
*
* @author bjorncs
*/
public class CommandLineOptions {
public static final String HELP_OPTION = "help";
public static final String PRINTIDS_OPTION = "printids";
public static final String FIELDSET_OPTION = "fieldset";
public static final String CLUSTER_OPTION = "cluster";
public static final String ROUTE_OPTION = "route";
public static final String CONFIGID_OPTION = "configid";
public static final String SHOWDOCSIZE_OPTION = "showdocsize";
public static final String TIMEOUT_OPTION = "timeout";
public static final String NORETRY_OPTION = "noretry";
public static final String TRACE_OPTION = "trace";
public static final String PRIORITY_OPTION = "priority";
public static final String JSONOUTPUT_OPTION = "jsonoutput";
public static final String XMLOUTPUT_OPTION = "xmloutput";
public static final String SHORTTENSORS_OPTION = "shorttensors";
public static final String DIRECTTENSORS_OPTION = "directtensors";
private final Options options = createOptions();
private final InputStream stdIn;
public CommandLineOptions(InputStream stdIn) {
this.stdIn = stdIn;
}
public CommandLineOptions() {
this(System.in);
}
@SuppressWarnings("AccessStaticViaInstance")
private static Options createOptions() {
Options options = new Options();
options.addOption(Option.builder("h")
.hasArg(false)
.desc("Show this syntax page.")
.longOpt(HELP_OPTION)
.build());
options.addOption(Option.builder("i")
.hasArg(false)
.desc("Show only identifiers of retrieved documents.")
.longOpt(PRINTIDS_OPTION)
.build());
options.addOption(Option.builder("f")
.hasArg(true)
.desc("Retrieve the specified fields only (see https://docs.vespa.ai/en/documents.html#fieldsets) (default '" + DocumentOnly.NAME + "')")
.longOpt(FIELDSET_OPTION)
.argName("fieldset").build());
options.addOption(Option.builder("u")
.hasArg(true)
.desc("Send request to the given content cluster.")
.longOpt(CLUSTER_OPTION)
.argName("cluster").build());
options.addOption(Option.builder("r")
.hasArg(true)
.desc("Send request to the given messagebus route.")
.longOpt(ROUTE_OPTION)
.argName("route").build());
options.addOption(Option.builder("c")
.hasArg(true)
.desc("Use the specified config id for messagebus configuration.")
.longOpt(CONFIGID_OPTION)
.argName("configid").build());
options.addOption(Option.builder("s")
.hasArg(false)
.desc("Show binary size of document.")
.longOpt(SHOWDOCSIZE_OPTION).build());
options.addOption(Option.builder("t")
.hasArg(true)
.desc("Set timeout for the request in seconds (default 0).")
.longOpt(TIMEOUT_OPTION)
.argName("timeout")
.type(Number.class).build());
options.addOption(Option.builder("n")
.hasArg(false)
.desc("Do not retry operation on transient errors, as is default.")
.longOpt(NORETRY_OPTION).build());
options.addOption(Option.builder("a")
.hasArg(true)
.desc("Trace level to use (default 0).")
.longOpt(TRACE_OPTION)
.argName("trace")
.type(Number.class).build());
options.addOption(Option.builder("p")
.hasArg(true)
.desc("Priority (default 6).")
.longOpt(PRIORITY_OPTION)
.argName("priority").build());
options.addOption(Option.builder("j")
.hasArg(false)
.desc("JSON output (default format)")
.longOpt(JSONOUTPUT_OPTION).build());
options.addOption(Option.builder("x")
.hasArg(false)
.desc("XML output")
.longOpt(XMLOUTPUT_OPTION).build());
// TODO Vespa 9: replace with --longtensors ?
options.addOption(Option.builder()
.longOpt(SHORTTENSORS_OPTION)
.desc("Output JSON tensors in short form. Will be the default on Vespa 9")
.hasArg(false)
.build());
return options;
}
public void printHelp() {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(
"vespa-get [documentid...]", "Fetch a document from a Vespa Content cluster.", options,
"If one or more document identifier are specified, these documents will be " +
"retrieved. Otherwise, document identifiers (separated with line break) will be read from standard in.\n",
false);
}
public ClientParameters parseCommandLineArguments(String[] args) throws IllegalArgumentException {
try {
CommandLineParser clp = new DefaultParser();
CommandLine cl = clp.parse(options, args);
boolean printIdsOnly = cl.hasOption(PRINTIDS_OPTION);
String fieldSet = cl.getOptionValue(FIELDSET_OPTION, "");
String cluster = cl.getOptionValue(CLUSTER_OPTION, "");
String route = cl.getOptionValue(ROUTE_OPTION, "");
String configId = cl.getOptionValue(CONFIGID_OPTION, "");
boolean help = cl.hasOption(HELP_OPTION);
boolean noRetry = cl.hasOption(NORETRY_OPTION);
boolean showDocSize = cl.hasOption(SHOWDOCSIZE_OPTION);
boolean jsonOutput = cl.hasOption(JSONOUTPUT_OPTION);
boolean xmlOutput = cl.hasOption(XMLOUTPUT_OPTION);
boolean shortTensors = cl.hasOption(SHORTTENSORS_OPTION);
boolean directTensors = cl.hasOption(DIRECTTENSORS_OPTION);
int trace = getTrace(cl);
DocumentProtocol.Priority priority = getPriority(cl);
double timeout = getTimeout(cl);
Iterator documentIds = getDocumentIds(cl);
if (jsonOutput && xmlOutput) {
throw new IllegalArgumentException("Cannot combine both xml and json output");
}
if (printIdsOnly && !fieldSet.isEmpty()) {
throw new IllegalArgumentException("Field set option can not be used in combination with print ids option.");
}
if (printIdsOnly) {
fieldSet = DocIdOnly.NAME;
} else if (fieldSet.isEmpty()) {
fieldSet = DocumentOnly.NAME;
}
if (!cluster.isEmpty() && !route.isEmpty()) {
throw new IllegalArgumentException("Cluster and route options are mutually exclusive.");
}
if (route.isEmpty() && cluster.isEmpty()) {
route = "default-get";
}
if (trace < 0 || trace > 9) {
throw new IllegalArgumentException("Invalid tracelevel: " + trace);
}
if (configId.isEmpty()) {
configId = "client";
}
ClientParameters.Builder paramsBuilder = new ClientParameters.Builder();
return paramsBuilder
.setDocumentIds(documentIds)
.setConfigId(configId)
.setFieldSet(fieldSet)
.setHelp(help)
.setPrintIdsOnly(printIdsOnly)
.setNoRetry(noRetry)
.setCluster(cluster)
.setRoute(route)
.setShowDocSize(showDocSize)
.setTraceLevel(trace)
.setPriority(priority)
.setTimeout(timeout)
.setJsonOutput(!xmlOutput)
.setTensorShortForm(shortTensors)
.setTensorDirectValues(directTensors)
.build();
} catch (ParseException pe) {
throw new IllegalArgumentException(pe.getMessage());
}
}
private Iterator getDocumentIds(CommandLine cl) {
// Fetch document ids from stdin if no ids are passed in as command line arguments
List documentIds = List.of(cl.getArgs());
// WARNING: CommandLine.getArgs may return a single empty string as the only element
if (documentIds.isEmpty() ||
documentIds.size() == 1 && documentIds.get(0).isEmpty()) {
return new Scanner(stdIn);
} else {
return documentIds.iterator();
}
}
private static double getTimeout(CommandLine cl) throws ParseException {
Number timeoutObj = (Number) cl.getParsedOptionValue(TIMEOUT_OPTION);
return timeoutObj != null ? timeoutObj.doubleValue() : 0;
}
private static int getTrace(CommandLine cl) throws ParseException {
Number traceObj = (Number) cl.getParsedOptionValue(TRACE_OPTION);
return traceObj != null ? traceObj.intValue() : 0;
}
private static DocumentProtocol.Priority getPriority(CommandLine cl) throws ParseException {
String priority = cl.getOptionValue(PRIORITY_OPTION, "NORMAL_2");
return parsePriority(priority);
}
private static DocumentProtocol.Priority parsePriority(String name) {
try {
return DocumentProtocol.Priority.valueOf(name);
} catch (IllegalArgumentException e) {
}
try {
int n = Integer.parseInt(name);
for (DocumentProtocol.Priority priority : DocumentProtocol.Priority.values()) {
if (priority.getValue() == n) {
return priority;
}
}
} catch (NumberFormatException e) {
}
throw new IllegalArgumentException("Invalid priority: " + name);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy