com.yahoo.system.CommandLineParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vespajlib Show documentation
Show all versions of vespajlib Show documentation
Library for use in Java components of Vespa. Shared code which do
not fit anywhere else.
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.system;
import java.util.*;
/**
* Simple command line parser, handling multiple arguments and multiple unary and binary switches starting with -.
*
* Terms used:
*
* progname -binaryswitch foo -unaryswitch argument1 argument2
*
* @author vegardh
*/
public class CommandLineParser {
private static final HashSet helpSwitches = new HashSet<>();
private final List inputStrings;
private final Map legalUnarySwitches = new HashMap<>();
private final Map legalBinarySwitches = new HashMap<>();
private final List unarySwitches = new ArrayList<>();
private final Map binarySwitches = new HashMap<>();
private final List arguments = new ArrayList<>();
private final Map requiredUnarySwitches = new HashMap<>();
private final Map requiredBinarySwitches = new HashMap<>();
private String progname = "progname";
private String argumentExplanation;
private int minArguments = 0;
private int maxArguments = Integer.MAX_VALUE;
private String helpText;
private boolean helpSwitchUsed = false;
static {
helpSwitches.add("-h");
helpSwitches.add("-help");
helpSwitches.add("--help");
helpSwitches.add("-?");
}
public CommandLineParser(String[] cmds) {
inputStrings = List.of(cmds);
}
public CommandLineParser(String progname, String[] cmds) {
this.progname=progname;
inputStrings = List.of(cmds);
}
/**
* Parses the command line
* @throws IllegalArgumentException if a parse error occured
*/
public void parse() {
for (Iterator it = inputStrings.iterator() ; it.hasNext() ; ) {
String i = it.next();
if (isHelpSwitch(i)) {
helpSwitchUsed = true;
usageAndThrow();
}
if (i.startsWith("-")) {
if (!isLegalSwitch(i)) {
usageAndThrow();
} else if (legalUnarySwitches.keySet().contains(i)) {
unarySwitches.add(i);
} else if (legalBinarySwitches.keySet().contains(i)) {
if (!it.hasNext()) {
throw new IllegalArgumentException(i+ " requires value");
} else {
String val = it.next();
binarySwitches.put(i, val);
}
}
} else {
arguments.add(i);
}
}
if (!requiredUnarySwitches.isEmpty() && !getUnarySwitches().containsAll(requiredUnarySwitches.keySet())) {
usageAndThrow();
}
if (!requiredBinarySwitches.isEmpty() && !getBinarySwitches().keySet().containsAll(requiredBinarySwitches.keySet())) {
usageAndThrow();
}
if (getArguments().size()maxArguments) {
usageAndThrow();
}
}
private boolean isHelpSwitch(String i) {
return helpSwitches.contains(i);
}
void usageAndThrow() {
StringBuffer error_sb = new StringBuffer();
error_sb.append("\nusage: ").append(progname).append(" ");
if (argumentExplanation!=null) {
error_sb.append(argumentExplanation);
}
if (!legalUnarySwitches.isEmpty()) error_sb.append("\nSwitches:\n");
error_sb.append("-h This help text\n");
for (Map.Entry e : legalUnarySwitches.entrySet()) {
error_sb.append(e.getKey()).append(" ").append(e.getValue()).append("\n");
}
for (Map.Entry e : legalBinarySwitches.entrySet()) {
error_sb.append(e.getKey()).append(" <").append(e.getValue()).append(">\n");
}
if (helpText!=null) {
error_sb.append("\n").append(helpText).append("\n");
}
throw new IllegalArgumentException(error_sb.toString());
}
private boolean isLegalSwitch(String s) {
return (legalUnarySwitches.containsKey(s) || legalBinarySwitches.containsKey(s));
}
/**
* Add a legal unary switch such as "-d"
*/
public void addLegalUnarySwitch(String s, String explanation) {
if (legalBinarySwitches.containsKey(s)) {
throw new IllegalArgumentException(s +" already added as a binary switch");
}
legalUnarySwitches.put(s, explanation);
}
public void addLegalUnarySwitch(String s) {
addLegalUnarySwitch(s, null);
}
/**
* Adds a required switch, such as -p
*/
public void addRequiredUnarySwitch(String s, String explanation) {
addLegalUnarySwitch(s, explanation);
requiredUnarySwitches.put(s, explanation);
}
/**
* Add a legal binary switch such as "-f /foo/bar"
*/
public void addLegalBinarySwitch(String s, String explanation) {
if (legalUnarySwitches.containsKey(s)) {
throw new IllegalArgumentException(s +" already added as a unary switch");
}
legalBinarySwitches.put(s, explanation);
}
/**
* Adds a legal binary switch without explanation
*/
public void addLegalBinarySwitch(String s) {
addLegalBinarySwitch(s, null);
}
/**
* Adds a required binary switch
*/
public void addRequiredBinarySwitch(String s, String explanation) {
addLegalBinarySwitch(s, explanation);
requiredBinarySwitches.put(s, explanation);
}
/**
* The unary switches that were given on the command line
*/
public List getUnarySwitches() {
return unarySwitches;
}
/**
* The binary switches that were given on the command line
*/
public Map getBinarySwitches() {
return binarySwitches;
}
/**
* All non-switch strings that were given on the command line
*/
public List getArguments() {
return arguments;
}
/**
* Sets the argument explanation used in printing method, i.e. "names,..."
*/
public void setArgumentExplanation(String argumentExplanation) {
this.argumentExplanation = argumentExplanation;
}
public void setExtendedHelpText(String text) {
this.helpText=text;
}
public String getHelpText() {
return helpText;
}
/**
* Sets minimum number of required arguments
*/
public void setMinArguments(int minArguments) {
this.minArguments = minArguments;
}
/**
* Sets the maximum number of allowed arguments
*/
public void setMaxArguments(int maxArguments) {
this.maxArguments = maxArguments;
}
public boolean helpSwitchUsed() {
return helpSwitchUsed;
}
}