@SuppressWarnings("AccessStaticViaInstance")
    protected static Options createOptions() {
        Options options = new Options();
        options.addOption("h", "help", false, "Show this syntax page.");

        options.addOption(Option.builder("d")
                .longOpt("datahandler")
                .hasArg(true)
                .argName("target")
                .desc("Send results to the given target.")
                .build());

        options.addOption(Option.builder("s")
                .longOpt("selection")
                .hasArg(true)
                .argName("selection")
                .desc("What documents to visit.")
                .build());

        options.addOption(Option.builder("f")
                .longOpt("from")
                .hasArg(true)
                .argName("timestamp")
                .desc("Only visit from the given timestamp (microseconds).")
                .type(Number.class)
                .build());

        options.addOption(Option.builder("t")
                .longOpt("to")
                .hasArg(true)
                .argName("timestamp")
                .desc("Only visit up to the given timestamp (microseconds).")
                .type(Number.class).build());

        options.addOption(Option.builder("l")
                .longOpt("fieldset")
                .hasArg(true)
                .argName("fieldset")
                .desc("Retrieve the specified fields only (see https://docs.vespa.ai/en/documents.html#fieldsets). Default is [document].")
                .build());

        options.addOption(Option.builder()
                .longOpt("visitinconsistentbuckets")
                .hasArg(false)
                .desc("Don't wait for inconsistent buckets to become consistent.")
                .build());

        options.addOption(Option.builder("m")
                .longOpt("maxpending")
                .hasArg(true)
                .argName("num")
                .desc("Maximum pending messages to data handlers per storage visitor.")
                .type(Number.class)
                .build());

        options.addOption(Option.builder()
                .longOpt("maxpendingsuperbuckets")
                .hasArg(true)
                .argName("num")
                .desc("Maximum pending visitor messages from the vespa-visit client. If set, dynamic throttling of visitors will be disabled!")
                .type(Number.class)
                .build());

        options.addOption(Option.builder("b")
                .longOpt("maxbuckets")
                .hasArg(true)
                .argName("num")
                .desc("Maximum buckets per visitor.")
                .type(Number.class)
                .build());

        options.addOption("i", "printids", false, "Display only document identifiers.");

        options.addOption(Option.builder("p")
                .longOpt("progress")
                .hasArg(true)
                .argName("file")
                .desc("Use given file to track progress.")
                .build());

        options.addOption(Option.builder("o")
                .longOpt("timeout")
                .hasArg(true)
                .argName("milliseconds")
                .desc("Time out visitor after given time.")
                .type(Number.class)
                .build());

        options.addOption(Option.builder("u")
                .longOpt("buckettimeout")
                .hasArg(true)
                .argName("milliseconds")
                .desc("Fail visitor if visiting a single bucket takes longer than this (default same as timeout)")
                .type(Number.class)
                .build());

        options.addOption(Option.builder()
                .longOpt("visitlibrary")
                .hasArg(true)
                .argName("string")
                .desc("Use the given visitor library.")
                .build());

        options.addOption(Option.builder()
                .longOpt("libraryparam")
                .numberOfArgs(2)
                .argName("key> <val")
                .desc("Give the following parameter to the visitor.")
                .build());

        options.addOption("r", "visitremoves", false, "Include information about removed documents.");

        options.addOption(Option.builder("c")
                .longOpt("cluster")
                .hasArg(true)
                .argName("cluster")
                .desc("Visit the given cluster.")
                .build());

        options.addOption("v", "verbose", false, "Indent XML, show progress and info on STDERR.");

        options.addOption(Option.builder()
                .longOpt("statistics")
                .hasArg(true)
                .argName("args")
                .desc("Use CountVisitor for document statistics. Use comma-separated arguments.")
                .build());

        options.addOption(Option.builder()
                .longOpt("abortonclusterdown")
                .hasArg(false)
                .desc("Abort if cluster is down.")
                .build());

        options.addOption(Option.builder()
                .longOpt("maxtotalhits")
                .hasArg(true)
                .argName("num")
                .desc("Abort visiting when we have received this many total documents. This is only an approximate number, all pending work will be completed and those documents will also be returned.")
                .type(Number.class)
                .build());

        options.addOption(Option.builder()
                .longOpt("processtime")
                .hasArg(true)
                .argName("num")
                .desc("Sleep this amount of millisecs before processing message. (Debug option for pretending to be slow client)")
                .type(Number.class)
                .build());
        options.addOption(Option.builder()
                .longOpt("priority")
                .hasArg(true)
                .argName("name")
                .desc("Priority used for each visitor. Defaults to NORMAL_3. " +
                        "Use with care to avoid starving lower prioritized traffic in the cluster")
                .build());

        options.addOption(Option.builder()
                .longOpt("tracelevel")
                .hasArg(true)
                .argName("level")
                .desc("Tracelevel ([0-9]) to use for debugging purposes")
                .type(Number.class)
                .build());

        options.addOption(Option.builder()
                .longOpt("skipbucketsonfatalerrors")
                .hasArg(false)
                .desc("Skip visiting super buckets with fatal error codes.")
                .build());

        options.addOption(Option.builder()
                .longOpt("jsonoutput")
                .desc("Output documents as JSON (default format)")
                .hasArg(false)
                .build());

        options.addOption(Option.builder()
                .longOpt("jsonl")
                .desc("Output documents as JSONL (JSON Lines format)")
                .hasArg(false)
                .build());

        options.addOption(Option.builder("x")
              .longOpt("xmloutput")
              .desc("Output documents as XML (deprecated)")
              .hasArg(false)
              .build());

        options.addOption(Option.builder()
                .longOpt("bucketspace")
                .hasArg(true)
                .argName("space")
                .desc(String.format("Bucket space to visit ('%s' or '%s'). If not specified, '%s' is used.",
                        FixedBucketSpaces.defaultSpace(), FixedBucketSpaces.globalSpace(), FixedBucketSpaces.defaultSpace()))
                .build());

        // TODO Vespa 9: replace with --longtensors ?
        options.addOption(Option.builder()
                .longOpt("shorttensors")
                .desc("Output JSON tensors in short form. Will be the default on Vespa 9")
                .hasArg(false)
                .build());

        options.addOption(Option.builder()
                .longOpt("slices")
                .desc("Split the document corpus into this number of independent slices. " +
                      "This lets multiple, concurrent series of visitors advance the same logical " +
                      "visit independently, by specifying a different --sliceid for each.")
                .hasArg(true)
                .type(Number.class)
                .build());

        options.addOption(Option.builder()
                .longOpt("sliceid")
                .desc("The slice number of the visit represented by this visitor. " +
                      "This number must be non-negative and less than the number of slices specified for the visit.")
                .hasArg(true)
                .type(Number.class)
                .build());

        options.addOption(Option.builder()
                .longOpt("nullrender")
                .desc("Process documents, but do not render any output. Overrides all other output options. " +
                      "Used to benchmark whether document rendering is the bottleneck when processing documents.")
                .hasArg(false)
                .build());

        return options;
    }
Client using visiting, used by the vespa-visit command line tool.

@author Einar M R Rosenvinge
vespaclient-java/src/main/java/com/yahoo/vespavisit/VdsVisit.java