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

com.yahoo.vespaget.CommandLineOptions Maven / Gradle / Ivy

There is a newer version: 8.441.21
Show newest version
// 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