/*******************************************************************************
* Copyright (c) 2013 Rene Schneider, GEBIT Solutions GmbH and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package de.gebit.integrity.runner.console;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* A very simple command line parser.
*
* @author Rene Schneider - initial API and implementation
*
*/
public class SimpleCommandLineParser {
/**
* Prefix for short params.
*/
private static final String SHORT_PARAMETER_PREFIX = "-";
/**
* Prefix for long params.
*/
private static final String LONG_PARAMETER_PREFIX = "--";
/**
* All available command-line options.
*/
private List<Option> options = new ArrayList<Option>();
/**
* Add one or more options.
*
* @param someOptions
*/
public void addOptions(Option... someOptions) {
for (Option tempOption : someOptions) {
options.add(tempOption);
}
}
/**
* Parses the given parameters and returns all parameters that could not be matched.
*
* @param someParameters
* the parameters to parse
* @return the remaining unmatched parameters
* @throws IllegalArgumentException
*/
public String[] parseAndReturnRemaining(String[] someParameters) throws IllegalArgumentException {
List<String> tempRemainingParams = new ArrayList<String>();
outer: for (int i = 0; i < someParameters.length; i++) {
for (Option tempOption : options) {
if (tempOption.matches(someParameters[i])) {
if (tempOption instanceof ValueOption) {
i++;
if (i < someParameters.length) {
((ValueOption<?>) tempOption).addValue(someParameters[i]);
} else {
throw new IllegalArgumentException(
"A value is required for parameter '" + someParameters[i - 1] + "'");
}
}
continue outer;
}
}
tempRemainingParams.add(someParameters[i]);
}
return tempRemainingParams.toArray(new String[0]);
}
/**
* Creates a help message to print out on the command line, based on the command line options registered.
*
* @param aRemainingParamsHelp
* the text to attach at the end of the "command line"
* @return the help message string
*/
public String getHelp(String aRemainingParamsHelp) {
StringBuffer tempBuffer = new StringBuffer();
tempBuffer.append("Parameters:");
for (Option tempOption : options) {
String tempCommandLine = tempOption.getCommandLine();
if (tempCommandLine != null) {
tempBuffer.append(" ");
tempBuffer.append(tempCommandLine);
}
}
tempBuffer.append(aRemainingParamsHelp);
tempBuffer.append(System.getProperty("line.separator"));
tempBuffer.append(System.getProperty("line.separator"));
for (Option tempOption : options) {
tempBuffer.append(tempOption.getHelpLine());
tempBuffer.append(System.getProperty("line.separator"));
}
return tempBuffer.toString();
}
/**
* Base class for command line options.
*
*
* @author Rene Schneider - initial API and implementation
*
*/
public static abstract class Option {
/**
* The short name of the option. Usually just one character.
*/
private String shortName;
/**
* The long name of the option, generally a comprehendable, but not-too-long string.
*/
private String longName;
/**
* The command line help string for this option.
*/
private String commandLine;
/**
* The description for the help.
*/
private String description;
/**
* Creates a new Option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
* @param aDescription
* The command line help string for this option.
* @param aCommandLine
* The description for the help.
*/
protected Option(String aShortName, String aLongName, String aDescription, String aCommandLine) {
if (aShortName == null && aLongName == null) {
throw new IllegalArgumentException("You must provide either a short or long name!");
}
shortName = aShortName;
longName = aLongName;
description = aDescription;
commandLine = aCommandLine;
}
/**
* Checks whether this matches a given parameter.
*
* @param aParameter
* the parameter
* @return true if a match is found, false otherwise
*/
protected boolean matches(String aParameter) {
return (shortName != null && aParameter.length() > 1 && aParameter.startsWith(SHORT_PARAMETER_PREFIX)
&& shortName.equals(aParameter.substring(1)))
| (longName != null && aParameter.length() > 2 && aParameter.startsWith(LONG_PARAMETER_PREFIX)
&& longName.equals(aParameter.substring(2)));
}
public String getShortName() {
return shortName;
}
public String getLongName() {
return longName;
}
public String getDescription() {
return description;
}
public String getCommandLine() {
return commandLine;
}
/**
* Returns the line for the parameter help.
*/
public String getHelpLine() {
StringBuilder tempLine = new StringBuilder();
if (shortName != null) {
tempLine.append(SHORT_PARAMETER_PREFIX + shortName);
if (longName != null) {
tempLine.append(" or " + LONG_PARAMETER_PREFIX + longName);
}
} else if (longName != null) {
tempLine.append(LONG_PARAMETER_PREFIX + longName);
}
if (description != null) {
tempLine.append(": ");
tempLine.append(description);
}
return tempLine.toString();
}
}
/**
* A boolean command line option.
*
*
* @author Rene Schneider - initial API and implementation
*
*/
public static class BooleanOption extends Option {
/**
* The value.
*/
private boolean value;
/**
* Creates a new boolean option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
*/
public BooleanOption(String aShortName, String aLongName) {
this(aShortName, aLongName, null);
}
/**
* Creates a new boolean option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
*/
public BooleanOption(String aShortName, String aLongName, String aDescription) {
this(aShortName, aLongName, aDescription, null);
}
/**
* Creates a new boolean option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
* @param aDescription
* The command line help string for this option.
* @param aCommandLine
* The description for the help.
*/
public BooleanOption(String aShortName, String aLongName, String aDescription, String aCommandLine) {
super(aShortName, aLongName, aDescription, aCommandLine);
}
@Override
protected boolean matches(String aParameter) {
if (super.matches(aParameter)) {
value = true;
return true;
} else {
return false;
}
}
public boolean isSet() {
return value;
}
}
/**
* A base class for an option that has one or more values. Generally, all options can have multiple values, with the
* first one defined being returned if only one result is requested.
*
*
* @author Rene Schneider - initial API and implementation
*
* @param <X>
*/
public static abstract class ValueOption<X extends Object> extends Option {
/**
* The value.
*/
private List<X> values = new ArrayList<X>();
/**
* Creates a new value option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
* @param aDescription
* The command line help string for this option.
* @param aCommandLine
* The description for the help.
*/
protected ValueOption(String aShortName, String aLongName, String aDescription, String aCommandLine) {
super(aShortName, aLongName, aDescription, aCommandLine);
}
public X getValue() {
return (values.size() > 0 ? values.get(0) : null);
}
/**
* Returns the value found in the parameters from the user.
*
* @param aDefault
* the default to return if the param is not set
* @return the value from the user or the default
*/
public X getValue(X aDefault) {
if (values.size() == 0) {
return aDefault;
} else {
return values.get(0);
}
}
/**
* Returns all the values found in the parameters from the user.
*
* @return the values from the user (may be an empty list if none were given)
*/
public List<X> getValues() {
return values;
}
/**
* Sets the value.
*
* @param aValue
* the value
*/
protected abstract void addValue(String aValue);
/**
* Adds the given value internally to the list of values.
*
* @param aValue
* the value to add
*/
protected void addValueInternal(X aValue) {
values.add(aValue);
}
}
/**
* String option.
*
*
* @author Rene Schneider - initial API and implementation
*
*/
public static class StringOption extends ValueOption<String> {
/**
* Creates a new String option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
*/
public StringOption(String aShortName, String aLongName) {
this(aShortName, aLongName, null);
}
/**
* Creates a new String option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
* @param aDescription
* The command line help string for this option.
*/
public StringOption(String aShortName, String aLongName, String aDescription) {
this(aShortName, aLongName, aDescription, null);
}
/**
* Creates a new String option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
* @param aDescription
* The command line help string for this option.
* @param aCommandLine
* The description for the help.
*/
public StringOption(String aShortName, String aLongName, String aDescription, String aCommandLine) {
super(aShortName, aLongName, aDescription, aCommandLine);
}
/**
* Sets a value.
*/
@Override
protected void addValue(String aValue) {
addValueInternal(aValue);
}
}
/**
* Integer option.
*
*
* @author Rene Schneider - initial API and implementation
*
*/
public static class IntegerOption extends ValueOption<Integer> {
/**
* Creates an integer option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
*/
public IntegerOption(String aShortName, String aLongName) {
this(aShortName, aLongName, null);
}
/**
* Creates a new integer option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
* @param aDescription
* The command line help string for this option.
*/
public IntegerOption(String aShortName, String aLongName, String aDescription) {
this(aShortName, aLongName, aDescription, null);
}
/**
* Creates a new integer option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
* @param aDescription
* The command line help string for this option.
* @param aCommandLine
* The description for the help.
*/
public IntegerOption(String aShortName, String aLongName, String aDescription, String aCommandLine) {
super(aShortName, aLongName, aDescription, aCommandLine);
}
/**
* Sets a value.
*/
@Override
protected void addValue(String aValue) {
addValueInternal(Integer.parseInt(aValue));
}
}
/**
* Decimal option.
*
*
* @author Rene Schneider - initial API and implementation
*
*/
public static class DecimalOption extends ValueOption<BigDecimal> {
/**
* Creates a new decimal option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
*/
public DecimalOption(String aShortName, String aLongName) {
this(aShortName, aLongName, null);
}
/**
* Creates a new decimal option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
* @param aDescription
* The command line help string for this option.
*/
public DecimalOption(String aShortName, String aLongName, String aDescription) {
this(aShortName, aLongName, aDescription, null);
}
/**
* Creates a new decimal option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
* @param aDescription
* The command line help string for this option.
* @param aCommandLine
* The description for the help.
*/
public DecimalOption(String aShortName, String aLongName, String aDescription, String aCommandLine) {
super(aShortName, aLongName, aDescription, aCommandLine);
}
/**
* Sets a value.
*/
@Override
protected void addValue(String aValue) {
addValueInternal(new BigDecimal(aValue));
}
}
/**
* Long option.
*
*
* @author Rene Schneider - initial API and implementation
*
*/
public static class LongOption extends ValueOption<Long> {
/**
* Creates a long option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
*/
public LongOption(String aShortName, String aLongName) {
this(aShortName, aLongName, null);
}
/**
* Creates a new integer option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
* @param aDescription
* The command line help string for this option.
*/
public LongOption(String aShortName, String aLongName, String aDescription) {
this(aShortName, aLongName, aDescription, null);
}
/**
* Creates a new integer option.
*
* @param aShortName
* The short name of the option. Usually just one character.
* @param aLongName
* The long name of the option, generelly a comprehendable, but not-too-long string.
* @param aDescription
* The command line help string for this option.
* @param aCommandLine
* The description for the help.
*/
public LongOption(String aShortName, String aLongName, String aDescription, String aCommandLine) {
super(aShortName, aLongName, aDescription, aCommandLine);
}
/**
* Sets a value.
*/
@Override
protected void addValue(String aValue) {
addValueInternal(Long.parseLong(aValue));
}
}
}