Merge branch 'develop' into spike/JAL-4047/JAL-4048_columns_in_sequenceID
[jalview.git] / src / jalview / bin / ArgParser.java
diff --git a/src/jalview/bin/ArgParser.java b/src/jalview/bin/ArgParser.java
deleted file mode 100644 (file)
index c7527c8..0000000
+++ /dev/null
@@ -1,1107 +0,0 @@
-/*
- * 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.io.File;
-import java.io.IOException;
-import java.net.URLDecoder;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-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 java.util.Set;
-
-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, NODUPLICATEVALUES
-  }
-
-  // These bootstrap args are simply parsed before a full parse of arguments and
-  // so are accessible at an earlier stage to (e.g.) set debug log leve, provide
-  // a props file (that might set log level), run headlessly, read an argfile
-  // instead of other args.
-  private static final Collection<Arg> bootstrapArgs = new ArrayList(
-          Arrays.asList(Arg.PROPS, Arg.DEBUG, Arg.HEADLESS, Arg.ARGFILE));
-
-  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"), ARGFILE;
-
-    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);
-      ARGFILE.setOptions(Opt.STRING);
-    }
-
-    private final String[] argNames;
-
-    private Opt[] argOptions;
-
-    private boolean defaultBoolValue = false;
-
-    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;
-    }
-  }
-
-  public static class ArgValues
-  {
-    private static final String ID = "id";
-
-    private Arg arg;
-
-    private int argCount = 0;
-
-    private boolean boolValue = false;
-
-    private boolean negated = false;
-
-    private int boolIndex = -1;
-
-    private List<Integer> argsIndexes;
-
-    private List<ArgValue> argValueList;
-
-    private Map<String, ArgValue> idMap = new HashMap<>();
-
-    protected ArgValues(Arg a)
-    {
-      this.arg = a;
-      this.argValueList = 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, int i)
-    {
-      this.boolValue = b;
-      this.boolIndex = i;
-    }
-
-    protected boolean getBoolean()
-    {
-      return this.boolValue;
-    }
-
-    @Override
-    public String toString()
-    {
-      if (argValueList == 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 : argValueList)
-        {
-          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)
-    {
-      addArgValue(new ArgValue(val, argIndex));
-    }
-
-    protected void addArgValue(ArgValue av)
-    {
-      if ((!arg.hasOption(Opt.MULTI) && argValueList.size() > 0)
-              || (arg.hasOption(Opt.NODUPLICATEVALUES)
-                      && argValueList.contains(av.getValue())))
-        return;
-      if (argValueList == null)
-      {
-        argValueList = new ArrayList<ArgValue>();
-      }
-      SubVals sv = ArgParser.getSubVals(av.getValue());
-      if (sv.has(ID))
-      {
-        String id = sv.get(ID);
-        av.setId(id);
-        idMap.put(id, av);
-      }
-      argValueList.add(av);
-    }
-
-    protected boolean hasValue(String val)
-    {
-      return argValueList.contains(val);
-    }
-
-    protected ArgValue getArgValue()
-    {
-      if (arg.hasOption(Opt.MULTI))
-        Console.warn("Requesting single value for multi value argument");
-      return argValueList.size() > 0 ? argValueList.get(0) : null;
-    }
-
-    protected List<ArgValue> getArgValueList()
-    {
-      return argValueList;
-    }
-
-    protected boolean hasId(String id)
-    {
-      return idMap.containsKey(id);
-    }
-
-    protected ArgValue getId(String id)
-    {
-      return idMap.get(id);
-    }
-  }
-
-  // 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;
-    String 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, ArgValuesMap> 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 ArgValuesMap());
-
-        ArgValuesMap avm = linkedArgs.get(linkedId);
-
-        if (a.hasOption(Opt.NODUPLICATEVALUES) && avm.hasValue(a, val))
-        {
-          Console.error("Argument '--" + argName
-                  + "' cannot contain a duplicate value ('" + val
-                  + "'). Ignoring this and subsequent occurrences.");
-          continue;
-        }
-
-        // check for unique id
-        SubVals sv = ArgParser.getSubVals(val);
-        String id = sv.get(ArgValues.ID);
-        if (id != null && avm.hasId(a, id))
-        {
-          Console.error("Argument '--" + argName + "' has a duplicate id ('"
-                  + id + "'). Ignoring.");
-          continue;
-        }
-
-        ArgValues avs = avm.getOrCreateArgValues(a);
-        if (avs == null)
-        {
-          avs = new ArgValues(a);
-        }
-        // store appropriate value
-        if (a.hasOption(Opt.STRING))
-        {
-          avs.addValue(val, argIndex);
-        }
-        else if (a.hasOption(Opt.BOOLEAN))
-        {
-          avs.setBoolean(!negated, argIndex);
-          avs.setNegated(negated);
-        }
-        else if (a.hasOption(Opt.UNARY))
-        {
-          avs.setBoolean(true, argIndex);
-        }
-        avs.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 arg in the list of args used
-        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)
-  {
-    ArgValuesMap avm = linkedArgs.get(linkedId);
-    return avm == null ? false : avm.containsArg(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)
-  {
-    ArgValuesMap avm = linkedArgs.get(linkedId);
-    if (avm == null)
-      return a.getDefaultBoolValue();
-    ArgValues avs = avm.getArgValues(a);
-    return avs == null ? a.getDefaultBoolValue() : avs.getBoolean();
-  }
-
-  public List<String> linkedIds()
-  {
-    return linkedOrder;
-  }
-
-  public ArgValuesMap linkedArgs(String id)
-  {
-    return linkedArgs.get(id);
-  }
-
-  @Override
-  public String toString()
-  {
-    StringBuilder sb = new StringBuilder();
-    sb.append("UNLINKED\n");
-    sb.append(argValuesMapToString(linkedArgs.get(null)));
-    if (linkedIds() != null)
-    {
-      sb.append("LINKED\n");
-      for (String id : linkedIds())
-      {
-        // already listed these as UNLINKED args
-        if (id == null)
-          continue;
-
-        ArgValuesMap avm = linkedArgs(id);
-        sb.append("ID: '").append(id).append("'\n");
-        sb.append(argValuesMapToString(avm));
-      }
-    }
-    return sb.toString();
-  }
-
-  private static String argValuesMapToString(ArgValuesMap avm)
-  {
-    if (avm == null)
-      return null;
-    StringBuilder sb = new StringBuilder();
-    for (Arg a : avm.getArgKeys())
-    {
-      ArgValues v = avm.getArgValues(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;
-
-    private String id;
-
-    protected ArgValue(String value, int argIndex)
-    {
-      this.value = value;
-      this.argIndex = argIndex;
-    }
-
-    protected String getValue()
-    {
-      return value;
-    }
-
-    protected int getArgIndex()
-    {
-      return argIndex;
-    }
-
-    protected void setId(String i)
-    {
-      id = i;
-    }
-
-    protected String getId()
-    {
-      return id;
-    }
-  }
-
-  /**
-   * 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 == null)
-        return;
-      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()
-    {
-      this.newMap();
-    }
-
-    protected ArgValuesMap(Map<Arg, ArgValues> map)
-    {
-      this.m = map;
-    }
-
-    private Map<Arg, ArgValues> getMap()
-    {
-      return m;
-    }
-
-    private void newMap()
-    {
-      m = new HashMap<Arg, ArgValues>();
-    }
-
-    private void newArg(Arg a)
-    {
-      if (m == null)
-        newMap();
-      if (!containsArg(a))
-        m.put(a, new ArgValues(a));
-    }
-
-    protected void addArgValue(Arg a, ArgValue av)
-    {
-      if (getMap() == null)
-        m = new HashMap<Arg, ArgValues>();
-
-      if (!m.containsKey(a))
-        m.put(a, new ArgValues(a));
-      ArgValues avs = m.get(a);
-      avs.addArgValue(av);
-    }
-
-    protected ArgValues getArgValues(Arg a)
-    {
-      return m == null ? null : m.get(a);
-    }
-
-    protected ArgValues getOrCreateArgValues(Arg a)
-    {
-      ArgValues avs = m.get(a);
-      if (avs == null)
-        newArg(a);
-      return getArgValues(a);
-    }
-
-    protected List<ArgValue> getArgValueList(Arg a)
-    {
-      ArgValues avs = getArgValues(a);
-      return avs == null ? new ArrayList<>() : avs.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 containsArg(Arg a)
-    {
-      if (m == null || !m.containsKey(a))
-        return false;
-      return a.hasOption(Opt.STRING) ? getArgValue(a) != null
-              : this.getBoolean(a);
-    }
-
-    protected boolean hasValue(Arg a, String val)
-    {
-      if (m == null || !m.containsKey(a))
-        return false;
-      for (ArgValue av : getArgValueList(a))
-      {
-        String avVal = av.getValue();
-        if ((val == null && avVal == null)
-                || (val != null && val.equals(avVal)))
-        {
-          return true;
-        }
-      }
-      return false;
-    }
-
-    protected boolean getBoolean(Arg a)
-    {
-      ArgValues av = getArgValues(a);
-      return av == null ? false : av.getBoolean();
-    }
-
-    protected Set<Arg> getArgKeys()
-    {
-      return m.keySet();
-    }
-
-    protected ArgValue getClosestPreviousArgValueOfArg(ArgValue thisAv,
-            Arg a)
-    {
-      ArgValue closestAv = null;
-      int thisArgIndex = thisAv.getArgIndex();
-      ArgValues compareAvs = this.getArgValues(a);
-      int closestPreviousIndex = -1;
-      for (ArgValue av : compareAvs.getArgValueList())
-      {
-        int argIndex = av.getArgIndex();
-        if (argIndex < thisArgIndex && argIndex > closestPreviousIndex)
-        {
-          closestPreviousIndex = argIndex;
-          closestAv = av;
-        }
-      }
-      return closestAv;
-    }
-
-    protected ArgValue getClosestNextArgValueOfArg(ArgValue thisAv, Arg a)
-    {
-      // this looks for the *next* arg that *might* be referring back to
-      // a thisAv. Such an arg would have no subValues (if it does it should
-      // specify an id in the subValues so wouldn't need to be guessed).
-      ArgValue closestAv = null;
-      int thisArgIndex = thisAv.getArgIndex();
-      ArgValues compareAvs = this.getArgValues(a);
-      int closestNextIndex = Integer.MAX_VALUE;
-      for (ArgValue av : compareAvs.getArgValueList())
-      {
-        int argIndex = av.getArgIndex();
-        if (argIndex > thisArgIndex && argIndex < closestNextIndex)
-        {
-          closestNextIndex = argIndex;
-          closestAv = av;
-        }
-      }
-      return closestAv;
-    }
-
-    protected ArgValue[] getArgValuesReferringTo(String key, String value,
-            Arg a)
-    {
-      // this looks for the *next* arg that *might* be referring back to
-      // a thisAv. Such an arg would have no subValues (if it does it should
-      // specify an id in the subValues so wouldn't need to be guessed).
-      List<ArgValue> avList = new ArrayList<>();
-      Arg[] args = a == null ? (Arg[]) this.getMap().keySet().toArray()
-              : new Arg[]
-              { a };
-      for (Arg keyArg : args)
-      {
-        for (ArgValue av : this.getArgValueList(keyArg))
-        {
-
-        }
-      }
-      return (ArgValue[]) avList.toArray();
-    }
-
-    protected boolean hasId(Arg a, String id)
-    {
-      ArgValues avs = this.getArgValues(a);
-      return avs == null ? false : avs.hasId(id);
-    }
-
-    protected ArgValue getId(Arg a, String id)
-    {
-      ArgValues avs = this.getArgValues(a);
-      return avs == null ? null : avs.getId(id);
-    }
-  }
-
-  public static Map<Arg, String> bootstrapArgs(String[] args)
-  {
-    Map<Arg, String> bootstrapArgMap = new HashMap<>();
-    if (args == null)
-      return bootstrapArgMap;
-    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);
-        }
-        Arg a = argMap.get(argName);
-        if (a != null && bootstrapArgs.contains(a))
-          bootstrapArgMap.put(a, val);
-      }
-    }
-    return bootstrapArgMap;
-  }
-
-  public static ArgParser parseArgFile(String argFilename)
-  {
-    List<String> argsList = null;
-    File argFile = new File(argFilename);
-    if (!argFile.exists())
-    {
-      System.err.println("--" + Arg.ARGFILE.name().toLowerCase(Locale.ROOT)
-              + "=\"" + argFilename + "\": File does not exist.");
-      System.exit(2);
-    }
-    try
-    {
-      argsList = Files.readAllLines(Paths.get(argFilename));
-    } catch (IOException e)
-    {
-      System.err.println("--" + Arg.ARGFILE.name().toLowerCase(Locale.ROOT)
-              + "=\"" + argFilename + "\": File could not be read.");
-      System.exit(3);
-    }
-    return new ArgParser((String[]) argsList.toArray());
-  }
-}
\ No newline at end of file