--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.bin;
+
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import jalview.util.Platform;
+
+public class ArgParser
+{
+ private static final String NEGATESTRING = "no";
+
+ private static final String DEFAULTLINKEDID = "";
+
+ private static enum Opt
+ {
+ BOOLEAN, STRING, UNARY, MULTI, LINKED, ORDERED
+ }
+
+ public enum Arg
+ {
+ /*
+ NOCALCULATION, NOMENUBAR, NOSTATUS, SHOWOVERVIEW, ANNOTATIONS, COLOUR,
+ FEATURES, GROOVY, GROUPS, HEADLESS, JABAWS, NOANNOTATION, NOANNOTATION2,
+ NODISPLAY, NOGUI, NONEWS, NOQUESTIONNAIRE, NOSORTBYTREE, NOUSAGESTATS,
+ OPEN, OPEN2, PROPS, QUESTIONNAIRE, SETPROP, SORTBYTREE, TREE, VDOC,
+ VSESS;
+ */
+ HELP("h"), CALCULATION, MENUBAR, STATUS, SHOWOVERVIEW, ANNOTATIONS,
+ COLOUR, FEATURES, GROOVY, GROUPS, HEADLESS, JABAWS, ANNOTATION,
+ ANNOTATION2, DISPLAY, GUI, NEWS, NOQUESTIONNAIRE, SORTBYTREE,
+ USAGESTATS, OPEN, OPEN2, PROPS, QUESTIONNAIRE, SETPROP, TREE, VDOC,
+ VSESS, OUTPUT, OUTPUTTYPE, SSANNOTATION, NOTEMPFAC, TEMPFAC,
+ TEMPFAC_LABEL, TEMPFAC_DESC, TEMPFAC_SHADING, TITLE, PAEMATRIX, WRAP,
+ NOSTRUCTURE, STRUCTURE, IMAGE, QUIT, DEBUG("d");
+
+ static
+ {
+ HELP.setOptions(Opt.UNARY);
+ CALCULATION.setOptions(true, Opt.BOOLEAN); // default "true" implies only
+ // expecting "--nocalculation"
+ MENUBAR.setOptions(true, Opt.BOOLEAN);
+ STATUS.setOptions(true, Opt.BOOLEAN);
+ SHOWOVERVIEW.setOptions(Opt.UNARY, Opt.LINKED);
+ ANNOTATIONS.setOptions(Opt.STRING, Opt.LINKED);
+ COLOUR.setOptions(Opt.STRING, Opt.LINKED);
+ FEATURES.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
+ GROOVY.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
+ GROUPS.setOptions(Opt.STRING, Opt.LINKED);
+ HEADLESS.setOptions(Opt.UNARY);
+ JABAWS.setOptions(Opt.STRING);
+ ANNOTATION.setOptions(true, Opt.BOOLEAN);
+ ANNOTATION2.setOptions(true, Opt.BOOLEAN);
+ DISPLAY.setOptions(true, Opt.BOOLEAN);
+ GUI.setOptions(true, Opt.BOOLEAN);
+ NEWS.setOptions(true, Opt.BOOLEAN);
+ NOQUESTIONNAIRE.setOptions(Opt.UNARY); // unary as --questionnaire=val
+ // expects a string value
+ SORTBYTREE.setOptions(true, Opt.BOOLEAN);
+ USAGESTATS.setOptions(true, Opt.BOOLEAN);
+ OPEN.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
+ OPEN2.setOptions(Opt.STRING, Opt.LINKED);
+ PROPS.setOptions(Opt.STRING);
+ QUESTIONNAIRE.setOptions(Opt.STRING);
+ SETPROP.setOptions(Opt.STRING);
+ TREE.setOptions(Opt.STRING);
+
+ VDOC.setOptions(Opt.UNARY);
+ VSESS.setOptions(Opt.UNARY);
+
+ OUTPUT.setOptions(Opt.STRING, Opt.LINKED);
+ OUTPUTTYPE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
+
+ SSANNOTATION.setOptions(Opt.BOOLEAN, Opt.LINKED);
+ NOTEMPFAC.setOptions(Opt.UNARY, Opt.LINKED);
+ TEMPFAC.setOptions(Opt.STRING, Opt.LINKED);
+ TEMPFAC_LABEL.setOptions(Opt.STRING, Opt.LINKED);
+ TEMPFAC_DESC.setOptions(Opt.STRING, Opt.LINKED);
+ TEMPFAC_SHADING.setOptions(Opt.BOOLEAN, Opt.LINKED);
+ TITLE.setOptions(Opt.STRING, Opt.LINKED);
+ PAEMATRIX.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
+ NOSTRUCTURE.setOptions(Opt.UNARY, Opt.LINKED);
+ STRUCTURE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
+ WRAP.setOptions(Opt.BOOLEAN, Opt.LINKED);
+ IMAGE.setOptions(Opt.STRING, Opt.LINKED);
+ QUIT.setOptions(Opt.UNARY);
+ DEBUG.setOptions(Opt.BOOLEAN);
+ }
+
+ private final String[] argNames;
+
+ private Opt[] argOptions;
+
+ private boolean defaultBoolValue = false;
+
+ private int argIndex = -1;
+
+ public String toLongString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Arg: ").append(this.name());
+ for (String name : getNames())
+ {
+ sb.append(", '").append(name).append("'");
+ }
+ sb.append("\nOptions: ");
+ boolean first = true;
+ for (Opt o : argOptions)
+ {
+ if (!first)
+ {
+ sb.append(", ");
+ }
+ sb.append(o.toString());
+ first = false;
+ }
+ sb.append("\n");
+ return sb.toString();
+ }
+
+ private Arg()
+ {
+ this(new String[0]);
+ }
+
+ private Arg(String... names)
+ {
+ int length = (names == null || names.length == 0
+ || (names.length == 1 && names[0] == null)) ? 1
+ : names.length + 1;
+ this.argNames = new String[length];
+ this.argNames[0] = this.getName();
+ if (length > 1)
+ System.arraycopy(names, 0, this.argNames, 1, names.length);
+ }
+
+ public String[] getNames()
+ {
+ return argNames;
+ }
+
+ public String getName()
+ {
+ return this.name().toLowerCase(Locale.ROOT).replace('_', '-');
+ }
+
+ @Override
+ public final String toString()
+ {
+ return getName();
+ }
+
+ public boolean hasOption(Opt o)
+ {
+ if (argOptions == null)
+ return false;
+ for (Opt option : argOptions)
+ {
+ if (o == option)
+ return true;
+ }
+ return false;
+ }
+
+ protected void setOptions(Opt... options)
+ {
+ setOptions(false, options);
+ }
+
+ protected void setOptions(boolean defaultBoolValue, Opt... options)
+ {
+ this.defaultBoolValue = defaultBoolValue;
+ argOptions = options;
+ }
+
+ protected boolean getDefaultBoolValue()
+ {
+ return defaultBoolValue;
+ }
+
+ private void setArgIndex(int i)
+ {
+ this.argIndex = i;
+ }
+
+ protected int getArgIndex()
+ {
+ return this.argIndex;
+ }
+ }
+
+ public static class ArgValues
+ {
+ private Arg arg;
+
+ private int argCount = 0;
+
+ private boolean boolValue = false;
+
+ private boolean negated = false;
+
+ private int singleArgIndex = -1;
+
+ private List<Integer> argsIndexes;
+
+ private List<ArgValue> argsList;
+
+ protected ArgValues(Arg a)
+ {
+ this.arg = a;
+ this.argsList = new ArrayList<ArgValue>();
+ this.boolValue = arg.getDefaultBoolValue();
+ }
+
+ public Arg arg()
+ {
+ return arg;
+ }
+
+ protected int getCount()
+ {
+ return argCount;
+ }
+
+ protected void incrementCount()
+ {
+ argCount++;
+ }
+
+ protected void setNegated(boolean b)
+ {
+ this.negated = b;
+ }
+
+ protected boolean isNegated()
+ {
+ return this.negated;
+ }
+
+ protected void setBoolean(boolean b)
+ {
+ this.boolValue = b;
+ }
+
+ protected boolean getBoolean()
+ {
+ return this.boolValue;
+ }
+
+ @Override
+ public String toString()
+ {
+ if (argsList == null)
+ return null;
+ StringBuilder sb = new StringBuilder();
+ sb.append(arg.toLongString());
+ if (arg.hasOption(Opt.BOOLEAN) || arg.hasOption(Opt.UNARY))
+ sb.append("Boolean: ").append(boolValue).append("; Default: ")
+ .append(arg.getDefaultBoolValue()).append("; Negated: ")
+ .append(negated).append("\n");
+ if (arg.hasOption(Opt.STRING))
+ {
+ sb.append("Values:");
+ boolean first = true;
+ for (ArgValue av : argsList)
+ {
+ String v = av.getValue();
+ if (!first)
+ sb.append(",");
+ sb.append("\n '");
+ sb.append(v).append("'");
+ first = false;
+ }
+ sb.append("\n");
+ }
+ sb.append("Count: ").append(argCount).append("\n");
+ return sb.toString();
+ }
+
+ protected void addValue()
+ {
+ addValue(null, -1);
+ }
+
+ protected void addValue(String val, int argIndex)
+ {
+ addValue(val, argIndex, false);
+ }
+
+ protected void addValue(String val, int argIndex, boolean noDuplicates)
+ {
+ if ((!arg.hasOption(Opt.MULTI) && argsList.size() > 0)
+ || (noDuplicates && argsList.contains(val)))
+ return;
+ if (argsList == null)
+ {
+ argsList = new ArrayList<ArgValue>();
+ }
+ argsList.add(new ArgValue(val, argIndex));
+ }
+
+ protected boolean hasValue(String val)
+ {
+ return argsList.contains(val);
+ }
+
+ protected ArgValue getArgValue()
+ {
+ if (arg.hasOption(Opt.MULTI))
+ Console.warn("Requesting single value for multi value argument");
+ return argsList.size() > 0 ? argsList.get(0) : null;
+ }
+
+ /*
+ protected String getValue()
+ {
+ ArgValue av = getArgValue();
+ return av == null ? null : av.getValue();
+ }
+ */
+
+ protected List<ArgValue> getArgValueList()
+ {
+ return argsList;
+ }
+ }
+
+ // old style
+ private List<String> vargs = null;
+
+ private boolean isApplet;
+
+ // private AppletParams appletParams;
+
+ public boolean isApplet()
+ {
+ return isApplet;
+ }
+
+ public String nextValue()
+ {
+ return vargs.remove(0);
+ }
+
+ public int getSize()
+ {
+ return vargs.size();
+ }
+
+ public String getValue(String arg)
+ {
+ return getValue(arg, false);
+ }
+
+ public String getValue(String arg, boolean utf8decode)
+ {
+ int index = vargs.indexOf(arg);
+ String dc = null, ret = null;
+ if (index != -1)
+ {
+ ret = vargs.get(index + 1).toString();
+ vargs.remove(index);
+ vargs.remove(index);
+ if (utf8decode && ret != null)
+ {
+ try
+ {
+ dc = URLDecoder.decode(ret, "UTF-8");
+ ret = dc;
+ } catch (Exception e)
+ {
+ // TODO: log failure to decode
+ }
+ }
+ }
+ return ret;
+ }
+
+ /*
+ public Object getAppletValue(String key, String def, boolean asString)
+ {
+ Object value;
+ return (appletParams == null ? null
+ : (value = appletParams.get(key.toLowerCase())) == null ? def
+ : asString ? "" + value : value);
+ }
+ */
+
+ // new style
+ private static final Map<String, Arg> argMap;
+
+ private Map<String, HashMap<Arg, ArgValues>> linkedArgs = new HashMap<>();
+
+ private List<String> linkedOrder = null;
+
+ private List<Arg> argList;
+
+ static
+ {
+ argMap = new HashMap<>();
+ for (Arg a : EnumSet.allOf(Arg.class))
+ {
+ ARGNAME: for (String argName : a.getNames())
+ {
+ if (argMap.containsKey(argName))
+ {
+ Console.warn("Trying to add argument name multiple times: '"
+ + argName + "'"); // RESTORE THIS WHEN MERGED
+ if (argMap.get(argName) != a)
+ {
+ Console.error(
+ "Trying to add argument name multiple times for different Args: '"
+ + argMap.get(argName).getName() + ":" + argName
+ + "' and '" + a.getName() + ":" + argName
+ + "'");
+ }
+ continue ARGNAME;
+ }
+ argMap.put(argName, a);
+ }
+ }
+ }
+
+ public ArgParser(String[] args)
+ {
+ // old style
+ vargs = new ArrayList<>();
+ isApplet = (args.length > 0 && args[0].startsWith("<applet"));
+ if (isApplet)
+ {
+ // appletParams = AppletParams.getAppletParams(args, vargs);
+ }
+ else
+ {
+ if (Platform.isJS())
+
+ {
+ isApplet = true;
+ // appletParams =
+ // AppletParams.getAppletParams(Platform.getAppletInfoAsMap(), vargs);
+ }
+ for (int i = 0; i < args.length; i++)
+ {
+ String arg = args[i].trim();
+ if (arg.charAt(0) == '-')
+ {
+ arg = arg.substring(1);
+ }
+ vargs.add(arg);
+ }
+ }
+
+ // new style
+ Enumeration<String> argE = Collections.enumeration(Arrays.asList(args));
+ int argIndex = 0;
+ while (argE.hasMoreElements())
+ {
+ String arg = argE.nextElement();
+ String argName = null;
+ String val = null;
+ String linkedId = null;
+ if (arg.startsWith("--"))
+ {
+ int equalPos = arg.indexOf('=');
+ if (equalPos > -1)
+ {
+ argName = arg.substring(2, equalPos);
+ val = arg.substring(equalPos + 1);
+ }
+ else
+ {
+ argName = arg.substring(2);
+ }
+ int idOpen = argName.indexOf('[');
+ int idClose = argName.indexOf(']');
+
+ if (idOpen > -1 && idClose == argName.length() - 1)
+ {
+ linkedId = argName.substring(idOpen + 1, idClose);
+ argName = argName.substring(0, idOpen);
+ }
+
+ Arg a = argMap.get(argName);
+ // check for boolean prepended by "no"
+ boolean negated = false;
+ if (a == null && argName.startsWith(NEGATESTRING) && argMap
+ .containsKey(argName.substring(NEGATESTRING.length())))
+ {
+ argName = argName.substring(NEGATESTRING.length());
+ a = argMap.get(argName);
+ negated = true;
+ }
+
+ // check for config errors
+ if (a == null)
+ {
+ // arg not found
+ Console.error("Argument '" + arg + "' not recognised. Ignoring.");
+ continue;
+ }
+ if (!a.hasOption(Opt.BOOLEAN) && negated)
+ {
+ // used "no" with a non-boolean option
+ Console.error("Argument '--" + NEGATESTRING + argName
+ + "' not a boolean option. Ignoring.");
+ continue;
+ }
+ if (!a.hasOption(Opt.STRING) && equalPos > -1)
+ {
+ // set --argname=value when arg does not accept values
+ Console.error("Argument '--" + argName
+ + "' does not expect a value (given as '" + arg
+ + "'). Ignoring.");
+ continue;
+ }
+ if (!a.hasOption(Opt.LINKED) && linkedId != null)
+ {
+ // set --argname[linkedId] when arg does not use linkedIds
+ Console.error("Argument '--" + argName
+ + "' does not expect a linked id (given as '" + arg
+ + "'). Ignoring.");
+ continue;
+ }
+
+ if (a.hasOption(Opt.STRING) && equalPos == -1)
+ {
+ // take next arg as value if required, and '=' was not found
+ if (!argE.hasMoreElements())
+ {
+ // no value to take for arg, which wants a value
+ Console.error("Argument '" + a.getName()
+ + "' requires a value, none given. Ignoring.");
+ continue;
+ }
+ val = argE.nextElement();
+ }
+
+ // use default linkedId for linked arguments
+ if (a.hasOption(Opt.LINKED) && linkedId == null)
+ linkedId = DEFAULTLINKEDID;
+
+ if (!linkedArgs.containsKey(linkedId))
+ linkedArgs.put(linkedId, new HashMap<>());
+
+ Map<Arg, ArgValues> valuesMap = linkedArgs.get(linkedId);
+ if (!valuesMap.containsKey(a))
+ valuesMap.put(a, new ArgValues(a));
+
+ ArgValues values = valuesMap.get(a);
+ if (values == null)
+ {
+ values = new ArgValues(a);
+ }
+ // store appropriate value
+ if (a.hasOption(Opt.STRING))
+ {
+ values.addValue(val, argIndex);
+ }
+ else if (a.hasOption(Opt.BOOLEAN))
+ {
+ values.setBoolean(!negated);
+ values.setNegated(negated);
+ }
+ else if (a.hasOption(Opt.UNARY))
+ {
+ values.setBoolean(true);
+ }
+ values.incrementCount();
+
+ // store in appropriate place
+ if (a.hasOption(Opt.LINKED))
+ {
+ // allow a default linked id for single usage
+ if (linkedId == null)
+ linkedId = DEFAULTLINKEDID;
+ // store the order of linkedIds
+ if (linkedOrder == null)
+ linkedOrder = new ArrayList<>();
+ if (!linkedOrder.contains(linkedId))
+ linkedOrder.add(linkedId);
+ }
+ // store the ArgValues
+ valuesMap.put(a, values);
+
+ // store arg in the list of args
+ if (argList == null)
+ argList = new ArrayList<>();
+ if (!argList.contains(a))
+ argList.add(a);
+ }
+ }
+ }
+
+ public boolean isSet(Arg a)
+ {
+ return a.hasOption(Opt.LINKED) ? isSet("", a) : isSet(null, a);
+ }
+
+ public boolean isSet(String linkedId, Arg a)
+ {
+ Map<Arg, ArgValues> m = linkedArgs.get(linkedId);
+ return m == null ? false : m.containsKey(a);
+ }
+
+ public boolean getBool(Arg a)
+ {
+ if (!a.hasOption(Opt.BOOLEAN) && !a.hasOption(Opt.UNARY))
+ {
+ Console.warn("Getting boolean from non boolean Arg '" + a.getName()
+ + "'.");
+ }
+ return a.hasOption(Opt.LINKED) ? getBool("", a) : getBool(null, a);
+ }
+
+ public boolean getBool(String linkedId, Arg a)
+ {
+ Map<Arg, ArgValues> m = linkedArgs.get(linkedId);
+ if (m == null)
+ return a.getDefaultBoolValue();
+ ArgValues v = m.get(a);
+ return v == null ? a.getDefaultBoolValue() : v.getBoolean();
+ }
+
+ public List<String> linkedIds()
+ {
+ return linkedOrder;
+ }
+
+ public HashMap<Arg, ArgValues> linkedArgs(String id)
+ {
+ return linkedArgs.get(id);
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("UNLINKED\n");
+ sb.append(argMapToString(linkedArgs.get(null)));
+ if (linkedIds() != null)
+ {
+ sb.append("LINKED\n");
+ for (String id : linkedIds())
+ {
+ // already listed these as UNLINKED args
+ if (id == null)
+ continue;
+
+ Map<Arg, ArgValues> m = linkedArgs(id);
+ sb.append("ID: '").append(id).append("'\n");
+ sb.append(argMapToString(m));
+ }
+ }
+ return sb.toString();
+ }
+
+ private static String argMapToString(Map<Arg, ArgValues> m)
+ {
+ if (m == null)
+ return null;
+ StringBuilder sb = new StringBuilder();
+ for (Arg a : m.keySet())
+ {
+ ArgValues v = m.get(a);
+ sb.append(v.toString());
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+
+ public static SubVals getSubVals(String item)
+ {
+ return new SubVals(item);
+ }
+
+ /**
+ * A helper class to keep an index of argument position with argument values
+ */
+ public static class ArgValue
+ {
+ private int argIndex;
+
+ private String value;
+
+ protected ArgValue(String value, int argIndex)
+ {
+ this.value = value;
+ this.argIndex = argIndex;
+ }
+
+ protected String getValue()
+ {
+ return value;
+ }
+
+ protected int getArgIndex()
+ {
+ return argIndex;
+ }
+ }
+
+ /**
+ * A helper class to parse a string of the possible forms "content"
+ * "[index]content", "[keyName=keyValue]content" and return the integer index,
+ * the strings keyName and keyValue, and the content after the square brackets
+ * (if present). Values not set `will be -1 or null.
+ */
+ public static class SubVals
+ {
+ private static int NOTSET = -1;
+
+ private int index = NOTSET;
+
+ private Map<String, String> subVals = null;
+
+ private static char SEPARATOR = ';';
+
+ private String content = null;
+
+ public SubVals(String item)
+ {
+ this.parseVals(item);
+ }
+
+ public void parseVals(String item)
+ {
+ if (item.indexOf('[') == 0 && item.indexOf(']') > 1)
+ {
+ int openBracket = item.indexOf('[');
+ int closeBracket = item.indexOf(']');
+ String subvalsString = item.substring(openBracket + 1,
+ closeBracket);
+ this.content = item.substring(closeBracket + 1);
+ boolean setIndex = false;
+ for (String subvalString : subvalsString
+ .split(Character.toString(SEPARATOR)))
+ {
+ int equals = subvalString.indexOf('=');
+ if (equals > -1)
+ {
+ if (subVals == null)
+ subVals = new HashMap<>();
+ subVals.put(subvalString.substring(0, equals),
+ subvalString.substring(equals + 1));
+ }
+ else
+ {
+ try
+ {
+ this.index = Integer.parseInt(subvalString);
+ setIndex = true;
+ } catch (NumberFormatException e)
+ {
+ Console.warn("Failed to obtain subvalue or index from '"
+ + item + "'. Setting index=0 and using content='"
+ + content + "'.");
+ }
+ }
+ }
+ if (!setIndex)
+ this.index = NOTSET;
+ }
+ else
+ {
+ this.content = item;
+ }
+ }
+
+ public boolean notSet()
+ {
+ // notSet is true if content present but nonsensical
+ return index == NOTSET && subVals == null;
+ }
+
+ public String get(String key)
+ {
+ return subVals == null ? null : subVals.get(key);
+ }
+
+ public boolean has(String key)
+ {
+ return subVals == null ? false : subVals.containsKey(key);
+ }
+
+ public int getIndex()
+ {
+ return index;
+ }
+
+ public String getContent()
+ {
+ return content;
+ }
+ }
+
+ /**
+ * Helper class to allow easy extraction of information about specific
+ * argument values (without having to check for null etc all the time)
+ */
+ protected static class ArgValuesMap
+ {
+ protected Map<Arg, ArgValues> m;
+
+ protected ArgValuesMap(Map<Arg, ArgValues> map)
+ {
+ this.m = map;
+ }
+
+ protected ArgValues getArgValues(Arg a)
+ {
+ return m == null ? null : m.get(a);
+ }
+
+ protected List<ArgValue> getArgValueList(Arg a)
+ {
+ ArgValues av = getArgValues(a);
+ return av == null ? null : av.getArgValueList();
+ }
+
+ protected ArgValue getArgValue(Arg a)
+ {
+ List<ArgValue> vals = getArgValueList(a);
+ return (vals == null || vals.size() == 0) ? null : vals.get(0);
+ }
+
+ protected String getValue(Arg a)
+ {
+ ArgValue av = getArgValue(a);
+ return av == null ? null : av.getValue();
+ }
+
+ protected boolean hasValue(Arg a)
+ {
+ if (!m.containsKey(a))
+ return false;
+ return getArgValue(a) != null;
+ }
+
+ protected boolean getBoolean(Arg a)
+ {
+ ArgValues av = getArgValues(a);
+ return av == null ? false : av.getBoolean();
+ }
+ }
+
+ private static final Collection<String> bootstrapArgs = new ArrayList(
+ Arrays.asList("props", "debug"));
+
+ public static Map<String, String> bootstrapArgs(String[] args)
+ {
+ Map<String, String> argMap = new HashMap<>();
+ if (args == null)
+ return argMap;
+ Enumeration<String> argE = Collections.enumeration(Arrays.asList(args));
+ while (argE.hasMoreElements())
+ {
+ String arg = argE.nextElement();
+ String argName = null;
+ String val = null;
+ if (arg.startsWith("--"))
+ {
+ int equalPos = arg.indexOf('=');
+ if (equalPos > -1)
+ {
+ argName = arg.substring(2, equalPos);
+ val = arg.substring(equalPos + 1);
+ }
+ else
+ {
+ argName = arg.substring(2);
+ }
+ if (bootstrapArgs.contains(argName))
+ argMap.put(argName, val);
+ }
+ }
+ return argMap;
+ }
+}
\ No newline at end of file