com.codetaco.cli.impl.CmdLineImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cli Show documentation
Show all versions of cli Show documentation
A command line parser for Java
package com.codetaco.cli.impl;
import com.codetaco.cli.CliException;
import com.codetaco.cli.annotation.Arg;
import com.codetaco.cli.annotation.ArgCallback;
import com.codetaco.cli.annotation.Args;
import com.codetaco.cli.impl.criteria.ICmdLineArgCriteria;
import com.codetaco.cli.impl.directive.EquDirective;
import com.codetaco.cli.impl.input.Token;
import com.codetaco.cli.impl.parser.CommandLineParser;
import com.codetaco.cli.impl.parser.IParserInput;
import com.codetaco.cli.impl.parser.NamespaceParser;
import com.codetaco.cli.impl.parser.XmlParser;
import com.codetaco.cli.impl.type.BooleanCLA;
import com.codetaco.cli.impl.type.CLAFactory;
import com.codetaco.cli.impl.type.ClaType;
import com.codetaco.cli.impl.type.CmdLineCLA;
import com.codetaco.cli.impl.type.DefaultCLA;
import com.codetaco.cli.impl.type.ICmdLineArg;
import com.codetaco.cli.impl.usage.UsageBuilder;
import com.codetaco.cli.impl.variables.VariableAssigner;
import com.codetaco.cli.impl.variables.VariablePuller;
import com.codetaco.math.Equ;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
public final class CmdLineImpl implements ICmdLine, Cloneable {
static public ClassLoader ClassLoader = CmdLineImpl.class.getClassLoader();
private final static Logger logger = LoggerFactory.getLogger(CmdLineImpl.class);
public static final String INCLUDE_FILE_PREFIX = "@";
private static final String MaxHelpCommandName = "help";
private static final char MinHelpCommandName = '?';
private static final char NegateCommandName = '!';
static private void checkForUnusedInput(Token[] tokens) {
if (tokenCount(tokens) > 0) {
StringBuilder extraInput = new StringBuilder();
for (Token token : tokens) {
if (token.isUsed()) {
continue;
}
extraInput.append(token.getValue());
}
throw CliException.builder().cause(new ParseException("extraneous input is not valid: " + extraInput.toString(), 0)).build();
}
}
static public String format(String format,
Object... args) {
String result = format;
for (Object arg : args) {
result = result.replaceFirst("\\{\\}", arg.toString());
}
return result;
}
public void load(Object target,
String... args) {
CmdLineImpl.ClassLoader = target.getClass().getClassLoader();
IParserInput data = CommandLineParser.getInstance(getCommandPrefix(),
true,
args);
parse(data, target);
}
public void loadProperties(Object target,
File propertyFile) {
try {
CmdLineImpl.ClassLoader = target.getClass().getClassLoader();
IParserInput data = NamespaceParser.getInstance(propertyFile);
parse(data, target);
} catch (Exception e) {
throw CliException.builder().cause(e).build();
}
}
public void loadProperties(Object target,
String... args) {
CmdLineImpl.ClassLoader = target.getClass().getClassLoader();
IParserInput data = NamespaceParser.getInstance(args);
parse(data, target);
}
public void loadXml(Object target,
File propertyFile) {
try {
CmdLineImpl.ClassLoader = target.getClass().getClassLoader();
IParserInput data = XmlParser.getInstance(propertyFile);
parse(data, target);
} catch (Exception e) {
throw CliException.builder().cause(e).build();
}
}
public void loadXml(Object target,
String... args) {
CmdLineImpl.ClassLoader = target.getClass().getClassLoader();
IParserInput data = XmlParser.getInstance(args);
parse(data, target);
}
static public int matchingArgs(List> bestArgs,
List> possibleArgs,
Token token,
boolean includeAlreadyParsed) {
int maxTokenLengthUsed = -1;
Iterator> aIter = possibleArgs.iterator();
while (aIter.hasNext()) {
ICmdLineArg> arg = aIter.next();
if (arg.isParsed() && !includeAlreadyParsed) {
continue;
}
int sal = arg.salience(token);
if (sal == maxTokenLengthUsed) {
bestArgs.add(arg);
}
if (sal > 0 && sal > maxTokenLengthUsed) {
maxTokenLengthUsed = sal;
bestArgs.clear();
bestArgs.add(arg);
}
}
/*
* It is a special case if the entered arg is exactly the same length as
* one of the best args. Typically, more than one best arg is considered
* an error. But this will remove all but the one that has the exact
* same length. So no error will occur. Args like "archive" and
* "archiveAll" will conflict when "arc" is entered but "archive" will
* return "archive" as the only best arg.
*/
if (bestArgs.size() > 1) {
for (ICmdLineArg> barg : bestArgs) {
if (barg.getKeyword().equalsIgnoreCase(token.getWordCommand())) {
bestArgs.clear();
bestArgs.add(barg);
break;
}
}
}
return maxTokenLengthUsed;
}
static private boolean mostSalient(List> possibleArgs,
Token[] tokens,
int tokenIdx,
List> args)
throws ParseException {
if (!tokens[tokenIdx].isCommand()) {
return false;
}
List> bestArgs = new ArrayList<>();
matchingArgs(bestArgs, possibleArgs, tokens[tokenIdx], true);
if (bestArgs.size() == 0) {
return false;
}
if (bestArgs.size() == 1) {
ICmdLineArg> arg = bestArgs.get(0);
if (arg != null) {
args.add(arg);
arg.setParsed(true);
if (tokens[tokenIdx].isWordCommand()) {
tokens[tokenIdx].setUsed(true);
return true;
}
// max must be 1 at this point since verbose must match
// entire tokens
tokens[tokenIdx].removeCharCommand();
return true;
}
return false;
}
Iterator> bIter = bestArgs.iterator();
StringBuilder bldr = new StringBuilder();
bldr.append("ambiguous token ");
bldr.append(tokens[tokenIdx].getValue());
bldr.append(" matches ");
while (bIter.hasNext()) {
bldr.append(bIter.next().getKeyword());
bldr.append(' ');
}
throw new ParseException(bldr.toString(), -1);
}
static private int parseGroup(CmdLineCLA group,
Token[] tokens,
int _tokenIndex,
Object target)
throws ParseException, IOException {
StringBuilder str = null;
int tlex = 0;
int tokenIndex = _tokenIndex;
for (tokenIndex++; tokenIndex < tokens.length; tokenIndex++) {
if (tokens[tokenIndex].isUsed()) {
continue;
}
if (tokens[tokenIndex].isGroupStart()) {
tlex++;
if (tlex == 1) {
tokens[tokenIndex].setUsed(true);
str = new StringBuilder();
continue;
}
}
if (tokens[tokenIndex].isGroupEnd()) {
tlex--;
if (tlex == 0) {
tokens[tokenIndex].setUsed(true);
group.setValue(group.convert(str.toString(), false, target));
continue;
}
}
if (tlex == 0) {
tokenIndex--; // reuse last token later
break;
}
if (tokens[tokenIndex].isLiteral()) {
/*
* Always quote the value in case it was quoted. It doesn't hurt
* to unnecessarily quote. But it would hurt not to quote at
* all.
*/
String value = tokens[tokenIndex].getValue();
value = replaceEscapes(value);
boolean singlequote = value.contains("'");
boolean doublequote = value.contains("\"");
char delim;
if (singlequote) {
if (doublequote) {
delim = '"';
value = value.replace("\"", "\\\"");
} else {
delim = '"';
}
} else {
delim = '\'';
}
str.append(delim);
str.append(value);
str.append(delim);
str.append(" ");
} else {
str.append(tokens[tokenIndex].getValue());
str.append(" ");
}
tokens[tokenIndex].setUsed(true);
}
if (tlex != 0) {
throw new ParseException("Missing " + tlex + " right bracket(s)", 0);
}
validateMultipleEntries(group);
return tokenIndex;
}
static private void parseOrphaned(Token[] tokens) throws ParseException {
StringBuilder bldr = new StringBuilder();
for (int t = 0; t < tokens.length; t++) {
if (!tokens[t].isUsed()) {
bldr.append(tokens[t].getValue());
bldr.append(' ');
}
}
if (bldr.length() != 0) {
throw new ParseException("unexpected input: " + bldr.toString(), -1);
}
}
static private int parseValues(ICmdLineArg arg,
Token[] tokens,
int t)
throws ParseException {
int tokenIndex = t;
/*
* take remainder of the token if any as parm 1
*/
boolean aValueWasFound = false;
if (!tokens[tokenIndex].isUsed()) {
// skip the dash
arg.setValue(
arg.convert(tokens[tokenIndex].remainderValue(), arg.isCaseSensitive(), null));
tokens[tokenIndex].setUsed(true);
aValueWasFound = true;
}
/*
* take any following non-dash parms
*/
if (!aValueWasFound || arg.isMultiple()) {
for (tokenIndex++; tokenIndex < tokens.length; tokenIndex++) {
if (arg.isMultiple() && arg.size() == arg.getMultipleMax()) {
tokenIndex--; // make sure to allow reuse of - token
break;
}
if (tokens[tokenIndex].isUsed()) {
continue;
}
if (!tokens[tokenIndex].isCommand()) {
arg.setValue(arg.convert(tokens[tokenIndex].getValue(), (arg.isCaseSensitive()),
null));
tokens[tokenIndex].setUsed(true);
if (!arg.isMultiple()) {
break;
}
} else {
tokenIndex--; // make sure to allow reuse of - token
break;
}
}
}
validateMultipleEntries(arg);
if (arg.hasValue() && arg.getCriteria() != null) {
for (int v = 0; v < arg.size(); v++) {
/*
* The user may have entered in a partial value. If the value
* can be normalized to something in the criteria then we will
* use the normalized value. This pretty much only applies to
* lists even though it is implemented on all criteria.
*/
arg.setValue(v,
arg.getCriteria().normalizeValue(arg.getValue(v), arg.isCaseSensitive()));
if (!arg.getCriteria().isSelected((Comparable) arg.getValue(v),
arg.isCaseSensitive())) {
throw new ParseException(arg.getValue(v) + " is not valid for " + arg,
-1);
}
}
}
return tokenIndex;
}
static private String replaceEscapes(String value) {
boolean backslash = value.contains("\\");
if (backslash) {
return value.replace("\\", "\\\\");
}
return value;
}
static private int tokenCount(Token[] tokens) {
int cnt = 0;
for (int t = 0; t < tokens.length; t++) {
if (!tokens[t].isUsed()) {
cnt++;
}
}
return cnt;
}
/**
* Verify the multiple requirement if any. Use group->values().size().
*/
static private void validateMultipleEntries(ICmdLineArg> arg) throws ParseException {
if (arg.isRequiredValue() && !arg.hasValue()) {
throw new ParseException("missing a required value for " + arg, -1);
}
if (arg.hasValue() && arg.size() > 1 && !arg.isMultiple()) {
throw new ParseException("multiple values not allowed for " + arg, -1);
}
if (arg.hasValue() && arg.isMultiple()) {
if (arg.size() < arg.getMultipleMin()) {
throw new ParseException("insufficient required values for " + arg, -1);
}
if (arg.size() > arg.getMultipleMax()) {
throw new ParseException("excessive required values for " + arg, -1);
}
}
}
/**
* Set by the factory when this is created.
*/
private int uniqueId;
private String name;
private String help;
private char commandPrefix;
private char notPrefix;
private final List defaultIncludeDirectories = new ArrayList<>();
private IParserInput originalInput;
private List> allPossibleArgs = new ArrayList<>();
private List> _namedBooleans = null;
private List> _namedValueArgs = null;
private List> _namedGroups = null;
private List> _positional = null;
private List parseExceptions = new ArrayList<>();
private int depth;
public CmdLineImpl(String _name,
String _help,
char _commandPrefix,
char _notPrefix) {
super();
depth = 0;
commandPrefix = _commandPrefix;
notPrefix = _notPrefix;
setName(_name);
if (_help != null) {
setHelp(_help);
}
/*-
final String defaultHelp = INCLUDE_FILE_PREFIX
+
" will import a specification from filename. You can return an cli to its default value with "
+ commandPrefix
+ notPrefix
+ " ; eg: "
+ commandPrefix
+ "debug and "
+ commandPrefix
+ "help can be turned off with "
+ commandPrefix
+ notPrefix
+ "debug,help";
if (help == null)
setHelp(defaultHelp + "\n");
else
setHelp(help + "\n\n" + defaultHelp + "\n");
*/
}
@Override
public void add(ICmdLineArg> arg) {
allPossibleArgs.add(arg);
}
@Override
public void add(int index,
ICmdLineArg> arg) {
allPossibleArgs.add(index, arg);
}
@Override
public void addDefaultIncludeDirectory(File defaultIncludeDirectory) {
defaultIncludeDirectories.add(defaultIncludeDirectory);
}
@Override
public List> allArgs() {
return allPossibleArgs;
}
private List allAvailableInstanceFields(Class> targetClass) {
List fields = new ArrayList<>();
allAvailableInstanceFields(targetClass, fields);
return fields;
}
private void allAvailableInstanceFields(Class> targetClass,
List fields) {
for (Field field : targetClass.getDeclaredFields()) {
if (field.isAnnotationPresent(Arg.class) || field.isAnnotationPresent(Args.class)) {
fields.add(field);
}
}
Class> superclass = targetClass.getSuperclass();
if (superclass != null && superclass != Object.class)
/*
* Recursive from here, up the hierarchy of classes all the way to
* the top.
*/ {
allAvailableInstanceFields(targetClass.getSuperclass(), fields);
}
}
@Override
public void applyDefaults() {
Iterator> aIter = allPossibleArgs.iterator();
while (aIter.hasNext()) {
ICmdLineArg> arg = aIter.next();
if (arg instanceof DefaultCLA) {
((DefaultCLA) arg).applyDefaults(commandPrefix, allPossibleArgs);
} else {
arg.applyDefaults();
}
}
}
@Override
public ICmdLineArg> arg(String commandToken) {
if (commandToken == null) {
return null;
}
List> bestArgs = new ArrayList<>();
matchingArgs(bestArgs, allPossibleArgs, new Token(commandPrefix, commandToken), true);
if (bestArgs.size() == 0)
// throw new ParseException(commandToken + " is unknown", -1);
{
return null;
}
if (bestArgs.size() > 1)
// throw new ParseException(commandToken + " is ambiguous", -1);
{
return null;
}
return bestArgs.get(0);
}
@Override
public ICmdLineArg> argForVariableName(String variableName) {
if (variableName == null) {
return null;
}
for (ICmdLineArg> arg : allPossibleArgs) {
if (arg.getVariable() != null) {
if (arg.getVariable().equals(variableName)) {
return arg;
}
}
}
throw CliException.builder().cause(new ParseException(variableName + " not found or not annotated with @Arg", 0)).build();
}
@Override
public void asDefinedType(StringBuilder sb) {
// should not be called.
}
@Override
public Object asEnum(String _name,
Object[] _possibleConstants) {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in an Enum", 0)).build();
}
@Override
public Object[] asEnumArray(String _name,
Object[] _possibleConstants) {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in an Enum[]", 0)).build();
}
@Override
public void assignVariables(Object target) {
try {
Iterator> aIter = allPossibleArgs.iterator();
while (aIter.hasNext()) {
ICmdLineArg> arg = aIter.next();
if (arg instanceof CmdLineCLA) {
CmdLineCLA cmdArg = (CmdLineCLA) arg;
for (ICmdLine cl : cmdArg.getValues()) {
Object newtarget = VariableAssigner.getInstance()
.newGroupVariable(cmdArg, target,
cl.argForVariableName(cmdArg.getFactoryArgName()));
if (newtarget == null) {
newtarget = target;
}
cl.assignVariables(newtarget);
}
} else if (arg.getVariable() != null && arg.hasValue()) {
if (target instanceof Object[]) {
Object[] targetArray = (Object[]) target;
VariableAssigner.getInstance().assign(arg, targetArray[targetArray.length - 1]);
} else if (target instanceof List) {
VariableAssigner.getInstance().assign(arg,
((List>) target).get(((List>) target).size() - 1));
} else {
VariableAssigner.getInstance().assign(arg, target);
}
}
}
checkForAnnotationPostParseCallback(target);
} catch (Exception e) {
throw CliException.builder().cause(e).build();
}
}
void checkForAnnotationPostParseCallback(Object target) throws ParseException {
for (Method method : target.getClass().getDeclaredMethods()) {
if (method.isAnnotationPresent(ArgCallback.class)) {
try {
ArgCallback cb = method.getAnnotation(ArgCallback.class);
if (cb.postParse()) {
method.setAccessible(true);
method.invoke(target);
}
} catch (IllegalAccessException | IllegalArgumentException e) {
throw new ParseException(e.getMessage(), 0);
} catch (InvocationTargetException e) {
throw (ParseException) e.getTargetException();
}
}
}
}
void attemptAnnotationCompile(Class> targetClass,
boolean topLevel,
List> alreadySeen,
String[] excludeArgsByVariableName) throws ParseException, IOException {
/*
* Recursive needs to be allowed. Not sure how to stop incorrect
* recursion other than to let the resulting stack overflow occur.
*/
/*-
if (alreadySeen.contains(targetClass))
throw new ParseException("recursive cli definition at " +
targetClass.toString(), 0);
*/
alreadySeen.add(targetClass);
try {
for (Field oneField : allAvailableInstanceFields(targetClass)) {
if (isFieldExcluded(oneField, excludeArgsByVariableName)) {
continue;
}
Args args = oneField.getAnnotation(Args.class);
if (args == null) {
Arg argAnnotation = oneField.getAnnotation(Arg.class);
compileArgAnnotation(oneField, argAnnotation, alreadySeen,
excludeArgsByVariableName);
} else {
for (Arg argAnnotation : args.value()) {
compileArgAnnotation(oneField, argAnnotation, alreadySeen,
excludeArgsByVariableName);
}
}
}
} finally {
alreadySeen.remove(targetClass);
}
if (topLevel) {
createSystemGeneratedArguments(CLAFactory.getInstance(), this);
parseExceptions = postCompileAnalysis();
if (!parseExceptions.isEmpty()) {
for (ParseException pe : parseExceptions) {
logger.warn(pe.getMessage());
}
if (parseExceptions.size() == 1) {
throw parseExceptions.get(0);
}
throw new ParseException("multiple parse exceptions", 0);
}
}
}
private void checkRequired() throws ParseException {
StringBuilder bldr = new StringBuilder();
Iterator> aIter = allPossibleArgs.iterator();
while (aIter.hasNext()) {
ICmdLineArg> arg = aIter.next();
if (arg.isRequired() && !arg.isParsed()) {
bldr.append(arg.toString());
bldr.append(" ");
}
}
if (bldr.length() != 0) {
throw new ParseException("missing required parameters: " + bldr.toString(), -1);
}
}
@Override
public ICmdLine clone() throws CloneNotSupportedException {
CmdLineImpl clone = (CmdLineImpl) super.clone();
clone.allPossibleArgs = new ArrayList<>();
Iterator> aIter = allPossibleArgs.iterator();
while (aIter.hasNext()) {
clone.allPossibleArgs.add(aIter.next().clone());
}
clone.setDepth(getDepth() + 1);
return clone;
}
@Override
public int compareTo(ICmdLine o) {
return 0;
}
private void compileArgAnnotation(Field oneField,
Arg argAnnotation,
List> alreadySeen,
String[] excludeArgsByVariableName) throws ParseException, IOException {
ICmdLineArg> arg = CLAFactory.getInstance().instanceFor(
commandPrefix,
oneField,
argAnnotation);
if (!argAnnotation.variable().equals("")) {
/*
* This actually annotating an embedded class, probably because it
* can not be modified. The previous annotation will be the
* subparser that this cli should be added to.
*/
CmdLineCLA subparser = (CmdLineCLA) argForVariableName(oneField.getName());
if (subparser == null) {
throw new ParseException("invalid variable reference: " + argAnnotation.variable(),
0);
}
subparser.templateCmdLine.add(arg);
return;
}
add(arg);
if (arg instanceof CmdLineCLA) {
CmdLineImpl embedded = new CmdLineImpl(arg.getKeyword() == null
? ("" + arg.getKeychar())
: ("" + arg.getKeychar() + "," + arg.getKeyword()),
"",
commandPrefix,
notPrefix);
((CmdLineCLA) arg).templateCmdLine = embedded;
Class> embeddedTarget;
try {
if (arg.getInstanceClass() != null) {
embeddedTarget = CmdLineImpl.ClassLoader
.loadClass(arg.getInstanceClass());
} else {
embeddedTarget = CLAFactory.instanceType(oneField);
}
} catch (ClassNotFoundException e) {
throw new ParseException(e.getMessage(), 0);
}
embedded.attemptAnnotationCompile(embeddedTarget, false, alreadySeen,
argAnnotation.excludeArgs());
}
}
@Override
public ICmdLine convert(String valueStr) {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
@Override
public ICmdLine convert(String valueStr,
boolean caseSensitive,
Object target) {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
void createSystemGeneratedArguments(CLAFactory factory,
ICmdLine cmdline) throws ParseException {
ICmdLineArg> sysgen;
sysgen = ClaType.DEFAULT.argumentInstance(commandPrefix, notPrefix, null);
sysgen.setMultiple(1);
sysgen.setHelp("Return one or more arguments to their initial states.");
sysgen.setSystemGenerated(true);
cmdline.add(sysgen);
sysgen = ClaType.BOOLEAN.argumentInstance(commandPrefix, MinHelpCommandName, null);
sysgen.setHelp("Show a help message.");
sysgen.setSystemGenerated(true);
cmdline.add(sysgen);
sysgen = ClaType.BOOLEAN.argumentInstance(commandPrefix, commandPrefix, MaxHelpCommandName);
sysgen.setHelp("Show a very abbreviated help message.");
sysgen.setSystemGenerated(true);
cmdline.add(sysgen);
sysgen = ClaType.BOOLEAN.argumentInstance(commandPrefix, commandPrefix,
MaxHelpCommandName + ":1");
sysgen.setHelp("Show a help message.");
sysgen.setSystemGenerated(true);
cmdline.add(sysgen);
sysgen = ClaType.BOOLEAN.argumentInstance(commandPrefix, commandPrefix,
MaxHelpCommandName + ":2");
sysgen.setHelp("Show a brief description with the help message.");
sysgen.setSystemGenerated(true);
cmdline.add(sysgen);
sysgen = ClaType.BOOLEAN.argumentInstance(commandPrefix, commandPrefix,
MaxHelpCommandName + ":3");
sysgen.setHelp("Show the most detailed help message.");
sysgen.setSystemGenerated(true);
cmdline.add(sysgen);
}
private void crossCheck() {
/*
* not yet, but probably needs a new criteria class
*/
}
@Override
public String defaultInstanceClass() {
return null;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
CmdLineImpl other = (CmdLineImpl) obj;
if (name == null) {
return other.name == null;
} else {
return name.equals(other.name);
}
}
@Override
public void exportCommandLine(StringBuilder str) {
/*
* Making sure that anything the user may have changed still gets the
* default if necessary.
*/
applyDefaults();
CommandLineParser.unparseTokens(allPossibleArgs, str);
}
@Override
public void exportNamespace(String prefix,
StringBuilder out) {
/*
* Making sure that anything the user may have changed still gets the
* default if necessary.
*/
applyDefaults();
NamespaceParser.unparseTokens(prefix, allPossibleArgs, out);
}
@Override
public void exportXml(String tag,
StringBuilder out) {
if (tag != null && tag.length() > 0) {
out.append("<").append(tag).append(">");
}
applyDefaults();
XmlParser.unparseTokens(allPossibleArgs, out);
if (tag != null && tag.length() > 0) {
out.append("").append(tag).append(">");
}
}
private void extractArgumentsFromTokens(Token[] tokens,
Object target,
List> args) throws ParseException, IOException {
if (tokenCount(tokens) > 0) {
parseDirectives(args, tokens, target);
}
if (tokenCount(tokens) > 0) {
parseIncludeFiles(args, tokens, target);
}
if (tokenCount(tokens) > 0) {
parseNamedBoolean(args, tokens);
}
if (isUsageRun()) {
return;
}
if (tokenCount(tokens) > 0) {
parseNamedGroups(args, tokens, target);
}
if (tokenCount(tokens) > 0) {
parseNamedValueArgs(args, tokens);
}
if (tokenCount(tokens) > 0) {
parsePositional(args, tokens);
}
if (tokenCount(tokens) > 0) {
parseOrphaned(tokens);
}
}
@Override
public String genericClassName() {
return null;
}
@Override
public Pattern getCamelCaps() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
@Override
public char getCommandPrefix() {
return commandPrefix;
}
@Override
public ICmdLineArgCriteria> getCriteria() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
public List getDefaultIncludeDirectories() {
return defaultIncludeDirectories;
}
@Override
public List getDefaultValues() {
return null;
}
@Override
public Object getDelegateOrValue() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
@Override
public Object getDelegateOrValue(int occurrence) {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
int getDepth() {
return depth;
}
@Override
public String getEnumClassName() {
// should not be called.
return null;
}
@Override
public String getFactoryArgName() {
return null;
}
@Override
public String getFactoryMethodName() {
return null;
}
@Override
public String getFormat() {
return null;
}
@Override
public String getHelp() {
return help;
}
@Override
public String getInstanceClass() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
@Override
public Character getKeychar() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return ' ';
}
@Override
public String getKeyword() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
@Override
public String getMetaphone() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
@Override
public int getMultipleMax() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return 0;
}
@Override
public int getMultipleMin() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return 0;
}
@Override
public String getName() {
return name;
}
@Override
public List getParseExceptions() {
return parseExceptions;
}
@Override
public int getUniqueId() {
return uniqueId;
}
@Override
public ICmdLine getValue() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
@Override
public List getValues() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
@Override
public ICmdLine getValue(int index) {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
@Override
public byte[] getValueAsbyteArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a byte[]", 0)).build();
}
@Override
public Byte[] getValueAsByteArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a Byte[]", 0)).build();
}
@Override
public Calendar[] getValueAsCalendarArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a Calendar[]", 0)).build();
}
@Override
public Character[] getValueAsCharacterArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a Character[]", 0)).build();
}
@Override
public char[] getValueAscharArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a char[]", 0)).build();
}
@Override
public Date[] getValueAsDateArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a Date[]", 0)).build();
}
@Override
public ZonedDateTime[] getValueAsZonedDateTimeArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a ZonedDateTime[]", 0)).build();
}
@Override
public DateTimeFormatter getValueAsDateTimeFormatter() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a DateTimeFormatter", 0)).build();
}
@Override
public DateTimeFormatter[] getValueAsDateTimeFormatterArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a DateTimeFormatter[]", 0)).build();
}
@Override
public double[] getValueAsdoubleArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a double[]", 0)).build();
}
@Override
public Double[] getValueAsDoubleArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a Double[]", 0)).build();
}
@Override
public Equ getValueAsEquation() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in an Equ", 0)).build();
}
@Override
public Equ[] getValueAsEquationArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a Equ[]", 0)).build();
}
@Override
public File[] getValueAsFileArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a File[]", 0)).build();
}
@Override
public URL[] getValueAsURLArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a URL[]", 0)).build();
}
@Override
public float[] getValueAsfloatArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a float[]", 0)).build();
}
@Override
public Float[] getValueAsFloatArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a Float[]", 0)).build();
}
@Override
public int[] getValueAsintArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a int[]", 0)).build();
}
@Override
public Integer[] getValueAsIntegerArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a Integer[]", 0)).build();
}
@Override
public LocalDate[] getValueAsLocalDateArray() {
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a LocalDate[]", 0)).build();
}
@Override
public LocalDateTime[] getValueAsLocalDateTimeArray() {
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a LocalDateTime[]", 0)).build();
}
@Override
public LocalTime[] getValueAsLocalTimeArray() {
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a LocalTime[]", 0)).build();
}
@Override
public long[] getValueAslongArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a long[]", 0)).build();
}
@Override
public Long[] getValueAsLongArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a Long[]", 0)).build();
}
@Override
public Pattern getValueAsPattern() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a Pattern", 0)).build();
}
@Override
public Pattern[] getValueAsPatternArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a Pattern[]", 0)).build();
}
@Override
public SimpleDateFormat getValueAsSimpleDateFormat() {
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a SimpleDateFormat", 0)).build();
}
@Override
public SimpleDateFormat[] getValueAsSimpleDateFormatArray() {
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a SimpleDateFormat[]", 0)).build();
}
@Override
public String[] getValueAsStringArray() {
// should not be called.
throw CliException.builder().cause(new ParseException("invalid to store " + toString() + " in a String[]", 0)).build();
}
@Override
public String getVariable() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
private Token handleDirective(Token[] tokens,
int directiveIdx,
int parmStart,
int parmEnd) throws ParseException, IOException {
int originalInputStart = tokens[parmStart].getInputStartX();
int originalInputEnd = tokens[parmEnd].getInputEndX();
String data = originalInput.substring(originalInputStart, originalInputEnd + 1);
String directiveName = tokens[directiveIdx].getValue().toLowerCase();
if ("_".equals(directiveName) || "=".equals(directiveName)) {
return new EquDirective(data).replaceToken(tokens, parmStart, parmEnd);
}
throw new ParseException("Unknown directive: " + tokens[directiveIdx], 0);
}
@Override
public int hashCode() {
int prime = 31;
int result = 1;
result = prime * result + ((name == null)
? 0
: name.hashCode());
return result;
}
@Override
public boolean hasValue() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return false;
}
@Override
public int indexOf(ICmdLineArg> arg) {
return allPossibleArgs.indexOf(arg);
}
@Override
public boolean isCaseSensitive() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return false;
}
public boolean isCompiled() {
return !allPossibleArgs.isEmpty();
}
private boolean isFieldExcluded(Field oneField,
String[] excludeArgsByVariableName) {
for (int f = 0; f < excludeArgsByVariableName.length; f++) {
if (oneField.getName().equalsIgnoreCase(excludeArgsByVariableName[f])) {
return true;
}
}
return false;
}
@Override
public boolean isMetaphoneAllowed() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return false;
}
@Override
public boolean isMultiple() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return false;
}
@Override
public boolean isParsed() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return false;
}
@Override
public boolean isPositional() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return false;
}
@Override
public boolean isRequired() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return false;
}
@Override
public boolean isRequiredValue() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return false;
}
@Override
public boolean isSystemGenerated() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return false;
}
public boolean isUsageRun() {
boolean isUr = false;
ICmdLineArg> arg = arg("" + commandPrefix + MinHelpCommandName);
isUr = arg != null && arg.isParsed();
if (isUr) {
return true;
}
arg = arg("" + commandPrefix + commandPrefix + MaxHelpCommandName);
isUr = arg != null && arg.isParsed();
if (isUr) {
return true;
}
arg = arg("" + commandPrefix + commandPrefix + MaxHelpCommandName + ":1");
isUr = arg != null && arg.isParsed();
if (isUr) {
return true;
}
arg = arg("" + commandPrefix + commandPrefix + MaxHelpCommandName + ":2");
isUr = arg != null && arg.isParsed();
return isUr;
}
/**
* Attempt to find the specification file in one of several places. We start with the exact name that is given. Then
* we
* remove the path and replace the path part with known places where specification files may be found. We only
* report
* an error if it could not be found at all.
*/
private Token[] loadCommandLineParserIncludeFile(String filename) throws ParseException {
File specFile = new File(filename);
/*
* Find the file.
*/
String nameOnly = specFile.getName();
if (!specFile.exists()) {
for (File dir : defaultIncludeDirectories) {
specFile = new File(dir, nameOnly);
if (specFile.exists()) {
break;
}
}
}
IParserInput clp;
try {
clp = CommandLineParser.getInstance(commandPrefix, specFile);
return clp.parseTokens();
} catch (IOException e) {
throw new ParseException(INCLUDE_FILE_PREFIX + nameOnly + " could not be found", 0);
}
}
private List> namedBooleans() {
if (_namedBooleans != null) {
return _namedBooleans;
}
_namedBooleans = new ArrayList<>();
Iterator> aIter = allPossibleArgs.iterator();
while (aIter.hasNext()) {
ICmdLineArg> arg = aIter.next();
if (!arg.isPositional() && !arg.isRequiredValue()) {
_namedBooleans.add(arg);
}
}
return _namedBooleans;
}
private List> namedGroups() {
if (_namedGroups != null) {
return _namedGroups;
}
_namedGroups = new ArrayList<>();
Iterator> aIter = allPossibleArgs.iterator();
while (aIter.hasNext()) {
ICmdLineArg> arg = aIter.next();
if (!arg.isPositional() && arg instanceof CmdLineCLA) {
_namedGroups.add(arg);
}
}
return _namedGroups;
}
private List> namedValueArgs() {
if (_namedValueArgs != null) {
return _namedValueArgs;
}
_namedValueArgs = new ArrayList<>();
Iterator> aIter = allPossibleArgs.iterator();
while (aIter.hasNext()) {
ICmdLineArg> arg = aIter.next();
if (!arg.isPositional() && arg.isRequiredValue()) {
_namedValueArgs.add(arg);
}
}
return _namedValueArgs;
}
@Override
public Object parse(IParserInput data) {
try {
parseTokens(data, null);
return null;
} catch (Exception e) {
throw CliException.builder().cause(e).build();
}
}
@Override
public Object parse(IParserInput data,
Object target) {
try {
if (!isCompiled()) {
if (target == null) {
attemptAnnotationCompile(data.getClass(), true, new ArrayList<>(),
new String[]{});
} else {
CmdLineImpl.ClassLoader = target.getClass().getClassLoader();
attemptAnnotationCompile(target.getClass(), true, new ArrayList<>(),
new String[]{});
}
}
parseTokens(data, target);
return target;
} catch (Exception e) {
throw CliException.builder().cause(e).build();
}
}
@Override
public Object parse(Object target,
String... args) {
try {
if (target != null) {
CmdLineImpl.ClassLoader = target.getClass().getClassLoader();
}
IParserInput data = CommandLineParser.getInstance(getCommandPrefix(), args);
if (!isCompiled()) {
if (target == null) {
attemptAnnotationCompile(data.getClass(), true, new ArrayList<>(),
new String[]{});
} else {
attemptAnnotationCompile(target.getClass(), true, new ArrayList<>(),
new String[]{});
}
}
parseTokens(data, target);
return target;
} catch (Exception e) {
throw CliException.builder().cause(e).build();
}
}
@Override
public Object parse(String... args) {
try {
IParserInput data = CommandLineParser.getInstance(getCommandPrefix(), args);
parseTokens(data, null);
return null;
} catch (Exception e) {
throw CliException.builder().cause(e).build();
}
}
private void parseDirectives(List> args,
Token[] tokens,
Object target) throws ParseException, IOException {
for (int t = 0; t < tokens.length; t++) {
if (!tokens[t].isUsed()) {
if (tokens[t].isParserDirective()) {
/*
* A Parser directive always starts with an underscore. It
* must be followed by (). It can also be a single '='
* followed immediately by a '('. This indicates an
* equation.
*/
tokens[t].setUsed(true);
/*
* token + 1 = (
*
* find corresponding ) token #
*/
int parmStart = t + 1;
int parmEnd = -1;
int lex = 0;
for (int e = parmStart; e < tokens.length; e++) {
tokens[e].setUsed(true);
if (tokens[e].isGroupStart()) {
lex++;
continue;
}
if (tokens[e].isGroupEnd()) {
lex--;
if (lex == 0) {
parmEnd = e;
break;
}
}
}
if (parmEnd == -1) {
throw new ParseException("unended directive: " + tokens[t], 0);
}
/*
* Start and end tokens by requirement are () and not really
* part of the directive, so skip over them.
*/
tokens[t] = handleDirective(tokens, t, parmStart + 1, parmEnd - 1);
continue;
}
}
}
}
private void parseIncludeFiles(List> args,
Token[] tokens,
Object target) throws ParseException, IOException {
for (int t = 0; t < tokens.length; t++) {
if (!tokens[t].isUsed()) {
if (tokens[t].isIncludeFile()) {
/*
* An include file always starts with @ and is immediately
* followed by the filename. However, the file name might be
* the next token if it was quoted or there was some
* whitespace after the @. And it would otherwise be the
* remainder of the @ token.
*/
tokens[t].setUsed(true);
Token[] newTokens = null;
if (tokens[t].getValue().length() > 1) {
newTokens = loadCommandLineParserIncludeFile(
tokens[t].getValue().substring(1));
} else {
int filenameT = t + 1;
if (filenameT >= tokens.length) {
throw new ParseException(
"end of input found instead of include directive file name", 0);
}
if (!tokens[filenameT].isLiteral()) {
throw new ParseException("missing include directive file name, found \""
+ tokens[filenameT].toString()
+ "\"", 0);
}
tokens[filenameT].setUsed(true);
newTokens = loadCommandLineParserIncludeFile(tokens[filenameT].getValue());
}
extractArgumentsFromTokens(newTokens, target, args);
if (isUsageRun()) {
args.clear();
return;
}
continue;
}
}
}
}
private void parseNamedBoolean(List> args,
Token[] tokens) throws ParseException {
List> possibleArgs = namedBooleans();
int tlex = 0;
for (int t = 0; t < tokens.length; t++) {
if (!tokens[t].isUsed()) {
if (tokens[t].isGroupStart()) {
tlex++;
continue;
}
if (tokens[t].isGroupEnd()) {
tlex--;
continue;
}
if (tlex == 0) {
int holdArgCnt = args.size();
while (mostSalient(possibleArgs, tokens, t, args)) {
if (holdArgCnt < args.size()) { // arg was found
BooleanCLA arg = (BooleanCLA) args.get(args.size() - 1);
if (arg.getKeychar() != null && arg.getKeychar() == MinHelpCommandName) {
System.out.println(UsageBuilder.getWriter(this, 1).toString());
return;
}
if (arg.getKeyword() != null
&& arg.getKeyword().equalsIgnoreCase(MaxHelpCommandName)) {
System.out.println(UsageBuilder.getWriter(this, 3).toString());
return;
}
if (arg.getKeyword() != null
&& arg.getKeyword().equalsIgnoreCase(MaxHelpCommandName + ":1")) {
System.out.println(UsageBuilder.getWriter(this, 1).toString());
return;
}
if (arg.getKeyword() != null
&& arg.getKeyword().equalsIgnoreCase(MaxHelpCommandName + ":2")) {
System.out.println(UsageBuilder.getWriter(this, 2).toString());
return;
}
}
}
}
}
}
if (tlex != 0) {
throw new ParseException("Unmatched bracket", 0);
}
}
private void parseNamedGroups(List> args,
Token[] tokens,
Object target) throws ParseException, IOException {
List> possibleArgs = namedGroups();
for (int t = 0; t < tokens.length; t++) {
if (!tokens[t].isUsed()) {
int holdArgCnt = args.size();
mostSalient(possibleArgs, tokens, t, args);
if (holdArgCnt < args.size()) {
t = parseGroup((CmdLineCLA) args.get(args.size() - 1), tokens, t, target);
}
}
}
}
private void parseNamedValueArgs(List> args,
Token[] tokens) throws ParseException, IOException {
List> possibleArgs = namedValueArgs();
int tlex = 0;
for (int t = 0; t < tokens.length; t++) {
if (!tokens[t].isUsed()) {
if (tokens[t].isGroupStart()) {
tlex++;
continue;
}
if (tokens[t].isGroupEnd()) {
tlex--;
continue;
}
if (tlex == 0) {
int holdArgCnt = args.size();
mostSalient(possibleArgs, tokens, t, args);
if (holdArgCnt < args.size()) {
t = parseValues(args.get(args.size() - 1), tokens, t);
}
}
}
}
if (tlex != 0) {
throw new ParseException("Unmatched bracket", 0);
}
}
private void parsePositional(List> args,
Token[] tokens) throws ParseException, IOException {
List> possibleArgs = positional();
Iterator> pIter = possibleArgs.iterator();
int t = 0;
while (pIter.hasNext()) {
ICmdLineArg> arg = pIter.next();
for (; t < tokens.length; t++) {
if (!tokens[t].isUsed()) {
/*
* - and -- commands are mutually exclusive from
* positionals.
*/
if (tokens[t].isCommand()) {
continue;
}
if (arg instanceof CmdLineCLA) {
t = parseGroup((CmdLineCLA) arg, tokens, --t, null);
} else {
t = parseValues(arg, tokens, t);
}
args.add(arg);
break;
}
}
}
}
private List> parseTokens(IParserInput data,
Object target) throws ParseException, IOException {
if (!isCompiled()) {
throw new ParseException("parser must be compiled", 0);
}
originalInput = data;
Token[] tokens = data.parseTokens();
resetArgs();
List> args = new ArrayList<>();
extractArgumentsFromTokens(tokens, target, args);
if (isUsageRun()) {
args.clear();
return args;
}
checkForUnusedInput(tokens);
applyDefaults();
checkRequired();
crossCheck();
/*
* Only start this process when the top level cmdline is exiting. That
* means that everything is parsed into the value holders and now we can
* start making instances.
*/
if (getDepth() == 0) {
assignVariables(target);
}
return args;
}
private List> positional() {
if (_positional != null) {
return _positional;
}
_positional = new ArrayList<>();
Iterator> aIter = allPossibleArgs.iterator();
while (aIter.hasNext()) {
ICmdLineArg> arg = aIter.next();
if (arg.isPositional()) {
_positional.add(arg);
}
}
return _positional;
}
List postCompileAnalysis() {
List localExceptions = new ArrayList<>();
/*
* scanforward keeps redundant errors from appearing
*/
boolean scanforward = false;
for (ICmdLineArg> arg1 : allPossibleArgs) {
scanforward = false;
for (ICmdLineArg> arg2 : allPossibleArgs) {
if (arg1 == arg2) {
scanforward = true;
continue;
}
if (!scanforward) {
continue;
}
if (arg1.getKeychar() > ' ' && arg1.getKeychar() == arg2.getKeychar()) {
localExceptions.add(new ParseException(
format("duplicate short name, found \"{}\"' and \"{}\"", arg1, arg2),
0));
}
if (arg1.getKeyword() != null
&& arg1.getKeyword().equalsIgnoreCase(arg2.getKeyword())) {
localExceptions.add(new ParseException(
format("duplicate long name, found \"{}\"' and \"{}\"", arg1, arg2),
0));
}
if (arg1.isMetaphoneAllowed() && arg2.isMetaphoneAllowed()
&& arg1.getMetaphone() != null
&& arg1.getMetaphone().equals(arg2.getMetaphone())) {
localExceptions.add(new ParseException(
format("duplicate values for metaphone, found \"{}\"' and \"{}\"", arg1,
arg2),
0));
}
if (arg1.isMetaphoneAllowed() && arg1.getMetaphone() != null
&& arg1.getMetaphone().toString().equals(arg2.getKeyword())) {
localExceptions.add(new ParseException(
format("metaphone equals long name, found \"{}\"' and \"{}\"", arg1,
arg2),
0));
}
if (arg1.isPositional() && arg1.isMultiple() && arg2.isPositional()) {
localExceptions.add(new ParseException(
format("a multi-value positional cli must be the only positional cli, found \"{}\"' and \"{}\"",
arg1, arg2),
0));
}
}
}
return localExceptions;
}
/**
* Pulls the values of the variables back into the arguments. This is usually in preparation for an export. When
* used
* in conjunction with a properties file, for instance, this allows the program to periodically update the
* properties
* and then pull them back into the properties file on disk.
*/
@Override
public void pull(Object variableSource) {
try {
reset();
Iterator> aIter = allPossibleArgs.iterator();
while (aIter.hasNext()) {
ICmdLineArg> arg = aIter.next();
if (arg.getVariable() != null) {
try {
VariablePuller.getInstance().pull(arg, variableSource);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new ParseException(e.getMessage(), 0);
}
}
}
} catch (Exception e) {
throw CliException.builder().cause(e).build();
}
}
@Override
public void remove(ICmdLineArg> arg) {
allPossibleArgs.remove(arg);
}
@Override
public void remove(int argIndex) {
allPossibleArgs.remove(argIndex);
}
@Override
public void reset() {
// n/a
}
private void resetArgs() {
Iterator> aIter = allPossibleArgs.iterator();
while (aIter.hasNext()) {
ICmdLineArg> arg = aIter.next();
arg.reset();
}
}
@Override
public ICmdLineArg resetCriteria() {
// intentionally left blank
return this;
}
@Override
public int salience(Token word) {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return 0;
}
@Override
public ICmdLineArg setCaseSensitive(boolean bool) {
return this;
}
@Override
public ICmdLineArg setDefaultValue(String defaultValue) {
return this;
}
void setDepth(
int _depth) {
depth = _depth;
}
@Override
public ICmdLineArg setEnumCriteria(String enumClassName) {
return null;
}
@Override
public ICmdLineArg setEnumCriteriaAllowError(String enumClassName) {
return null;
}
@Override
public ICmdLineArg setFactoryArgName(String argName) {
return this;
}
@Override
public ICmdLineArg setFactoryMethodName(String methodName) {
return this;
}
@Override
public ICmdLineArg setFormat(String format) {
return this;
}
@Override
public ICmdLineArg setHelp(String _help) {
help = _help;
return this;
}
@Override
public ICmdLineArg setInstanceClass(String classString) {
return this;
}
@Override
public ICmdLineArg setKeychar(Character _keychar) {
return this;
}
@Override
public ICmdLineArg setKeyword(String _keyword) {
return this;
}
@Override
public ICmdLineArg setListCriteria(String[] values) {
return this;
}
@Override
public ICmdLineArg setMetaphoneAllowed(boolean bool) {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
return null;
}
@Override
public ICmdLineArg setMultiple(boolean bool) {
return this;
}
@Override
public ICmdLineArg setMultiple(int min) {
return this;
}
@Override
public ICmdLineArg setMultiple(int min,
int max) {
return this;
}
public void setName(String _name) {
name = _name;
}
@Override
public void setObject(Object value) {
// nothing to do
}
@Override
public ICmdLineArg setParsed(boolean bool) {
return this;
}
@Override
public ICmdLineArg setPositional(boolean bool) {
return this;
}
@Override
public ICmdLineArg setRangeCriteria(String min,
String max) {
return this;
}
@Override
public ICmdLineArg setRegxCriteria(String pattern) {
return this;
}
@Override
public ICmdLineArg setRequired(boolean bool) {
return this;
}
@Override
public ICmdLineArg setRequiredValue(boolean bool) {
return this;
}
@Override
public ICmdLineArg setSystemGenerated(boolean bool) {
return this;
}
@Override
public void setType(ClaType claType) {
// n/a
}
@Override
public void setUniqueId(int uId) {
uniqueId = uId;
}
@Override
public void setValue(ICmdLine value) {
// intentionally left blank
}
@Override
public void setValue(int index,
ICmdLine value) {
// intentionally left blank
}
@Override
public ICmdLineArg setVariable(String string) {
return this;
}
@Override
public int size() {
int cnt = 0;
Iterator> aIter = allPossibleArgs.iterator();
while (aIter.hasNext()) {
ICmdLineArg> arg = aIter.next();
if (arg instanceof DefaultCLA) {
continue;
}
if (arg.isParsed()) {
cnt++;
}
}
return cnt;
}
@Override
public boolean supportsCaseSensitive() {
return false;
}
@Override
public boolean supportsDefaultValues() {
return false;
}
@Override
public boolean supportsExcludeArgs() {
return false;
}
@Override
public boolean supportsFactoryArgName() {
return false;
}
@Override
public boolean supportsFactoryMethod() {
return false;
}
@Override
public boolean supportsFormat() {
return false;
}
@Override
public boolean supportsHelp() {
return false;
}
@Override
public boolean supportsInList() {
return false;
}
@Override
public boolean supportsInstanceClass() {
return false;
}
@Override
public boolean supportsLongName() {
return false;
}
@Override
public boolean supportsMatches() {
return false;
}
@Override
public boolean supportsMetaphone() {
return false;
}
@Override
public boolean supportsMultimax() {
return false;
}
@Override
public boolean supportsMultimin() {
return false;
}
@Override
public boolean supportsPositional() {
return false;
}
@Override
public boolean supportsRange() {
return false;
}
@Override
public boolean supportsRequired() {
return false;
}
@Override
public boolean supportsShortName() {
return false;
}
@Override
public void useDefaults() {
/*
* This is only here as a place-holder so that this class can be a sub
* command line as well as a top level.
*/
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy