2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
24 import java.io.IOException;
25 import java.net.URLDecoder;
26 import java.nio.file.Files;
27 import java.nio.file.Paths;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collections;
31 import java.util.EnumSet;
32 import java.util.Enumeration;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Locale;
39 public class ArgParser
41 private static final String NEGATESTRING = "no";
43 private static final String DEFAULTLINKEDID = "";
45 private static enum Opt
47 BOOLEAN, STRING, UNARY, MULTI, LINKED, NODUPLICATEVALUES, BOOTSTRAP
50 // These bootstrap args are simply parsed before a full parse of arguments and
51 // so are accessible at an earlier stage to (e.g.) set debug log leve, provide
52 // a props file (that might set log level), run headlessly, read an argfile
53 // instead of other args.
54 private static final List<Arg> bootstrapArgs;
59 NOCALCULATION, NOMENUBAR, NOSTATUS, SHOWOVERVIEW, ANNOTATIONS, COLOUR,
60 FEATURES, GROOVY, GROUPS, HEADLESS, JABAWS, NOANNOTATION, NOANNOTATION2,
61 NODISPLAY, NOGUI, NONEWS, NOQUESTIONNAIRE, NOSORTBYTREE, NOUSAGESTATS,
62 OPEN, OPEN2, PROPS, QUESTIONNAIRE, SETPROP, SORTBYTREE, TREE, VDOC,
65 HELP("h"), CALCULATION, MENUBAR, STATUS, SHOWOVERVIEW, ANNOTATIONS,
66 COLOUR, FEATURES, GROOVY, GROUPS, HEADLESS, JABAWS, ANNOTATION,
67 ANNOTATION2, DISPLAY, GUI, NEWS, NOQUESTIONNAIRE, SORTBYTREE,
68 USAGESTATS, OPEN, OPEN2, PROPS, QUESTIONNAIRE, SETPROP, TREE, VDOC,
69 VSESS, OUTPUT, OUTPUTTYPE, SSANNOTATION, NOTEMPFAC, TEMPFAC,
70 TEMPFAC_LABEL, TEMPFAC_DESC, TEMPFAC_SHADING, TITLE, PAEMATRIX, WRAP,
71 NOSTRUCTURE, STRUCTURE, IMAGE, QUIT, DEBUG("d"), QUIET("q"), ARGFILE;
75 HELP.setOptions(Opt.UNARY);
76 CALCULATION.setOptions(true, Opt.BOOLEAN); // default "true" implies only
77 // expecting "--nocalculation"
78 MENUBAR.setOptions(true, Opt.BOOLEAN);
79 STATUS.setOptions(true, Opt.BOOLEAN);
80 SHOWOVERVIEW.setOptions(Opt.UNARY, Opt.LINKED);
81 ANNOTATIONS.setOptions(Opt.STRING, Opt.LINKED);
82 COLOUR.setOptions(Opt.STRING, Opt.LINKED);
83 FEATURES.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
84 GROOVY.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
85 GROUPS.setOptions(Opt.STRING, Opt.LINKED);
86 HEADLESS.setOptions(Opt.UNARY, Opt.BOOTSTRAP);
87 JABAWS.setOptions(Opt.STRING);
88 ANNOTATION.setOptions(true, Opt.BOOLEAN);
89 ANNOTATION2.setOptions(true, Opt.BOOLEAN);
90 DISPLAY.setOptions(true, Opt.BOOLEAN);
91 GUI.setOptions(true, Opt.BOOLEAN);
92 NEWS.setOptions(true, Opt.BOOLEAN);
93 NOQUESTIONNAIRE.setOptions(Opt.UNARY); // unary as --questionnaire=val
94 // expects a string value
95 SORTBYTREE.setOptions(true, Opt.BOOLEAN);
96 USAGESTATS.setOptions(true, Opt.BOOLEAN);
97 OPEN.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
98 OPEN2.setOptions(Opt.STRING, Opt.LINKED);
99 PROPS.setOptions(Opt.STRING, Opt.BOOTSTRAP);
100 QUESTIONNAIRE.setOptions(Opt.STRING);
101 SETPROP.setOptions(Opt.STRING);
102 TREE.setOptions(Opt.STRING);
104 VDOC.setOptions(Opt.UNARY);
105 VSESS.setOptions(Opt.UNARY);
107 OUTPUT.setOptions(Opt.STRING, Opt.LINKED);
108 OUTPUTTYPE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
110 SSANNOTATION.setOptions(Opt.BOOLEAN, Opt.LINKED);
111 NOTEMPFAC.setOptions(Opt.UNARY, Opt.LINKED);
112 TEMPFAC.setOptions(Opt.STRING, Opt.LINKED);
113 TEMPFAC_LABEL.setOptions(Opt.STRING, Opt.LINKED);
114 TEMPFAC_DESC.setOptions(Opt.STRING, Opt.LINKED);
115 TEMPFAC_SHADING.setOptions(Opt.BOOLEAN, Opt.LINKED);
116 TITLE.setOptions(Opt.STRING, Opt.LINKED);
117 PAEMATRIX.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
118 NOSTRUCTURE.setOptions(Opt.UNARY, Opt.LINKED);
119 STRUCTURE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
120 WRAP.setOptions(Opt.BOOLEAN, Opt.LINKED);
121 IMAGE.setOptions(Opt.STRING, Opt.LINKED);
122 QUIT.setOptions(Opt.UNARY);
123 DEBUG.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
124 QUIET.setOptions(Opt.UNARY, Opt.MULTI, Opt.BOOTSTRAP);
125 ARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.BOOTSTRAP);
128 private final String[] argNames;
130 private Opt[] argOptions;
132 private boolean defaultBoolValue = false;
134 public String toLongString()
136 StringBuilder sb = new StringBuilder();
137 sb.append("Arg: ").append(this.name());
138 for (String name : getNames())
140 sb.append(", '").append(name).append("'");
142 sb.append("\nOptions: ");
143 boolean first = true;
144 for (Opt o : argOptions)
150 sb.append(o.toString());
154 return sb.toString();
162 private Arg(String... names)
164 int length = (names == null || names.length == 0
165 || (names.length == 1 && names[0] == null)) ? 1
167 this.argNames = new String[length];
168 this.argNames[0] = this.getName();
170 System.arraycopy(names, 0, this.argNames, 1, names.length);
173 public String[] getNames()
178 public String getName()
180 return this.name().toLowerCase(Locale.ROOT).replace('_', '-');
184 public final String toString()
189 public boolean hasOption(Opt o)
191 if (argOptions == null)
193 for (Opt option : argOptions)
201 protected void setOptions(Opt... options)
203 setOptions(false, options);
206 protected void setOptions(boolean defaultBoolValue, Opt... options)
208 this.defaultBoolValue = defaultBoolValue;
209 argOptions = options;
212 protected boolean getDefaultBoolValue()
214 return defaultBoolValue;
218 public static class ArgValues
220 private static final String ID = "id";
224 private int argCount = 0;
226 private boolean boolValue = false;
228 private boolean negated = false;
230 private int boolIndex = -1;
232 private List<Integer> argsIndexes;
234 private List<ArgValue> argValueList;
236 private Map<String, ArgValue> idMap = new HashMap<>();
238 protected ArgValues(Arg a)
241 this.argValueList = new ArrayList<ArgValue>();
242 this.boolValue = arg.getDefaultBoolValue();
250 protected int getCount()
255 protected void incrementCount()
260 protected void setNegated(boolean b)
265 protected boolean isNegated()
270 protected void setBoolean(boolean b, int i)
276 protected boolean getBoolean()
278 return this.boolValue;
282 public String toString()
284 if (argValueList == null)
286 StringBuilder sb = new StringBuilder();
287 sb.append(arg.toLongString());
288 if (arg.hasOption(Opt.BOOLEAN) || arg.hasOption(Opt.UNARY))
289 sb.append("Boolean: ").append(boolValue).append("; Default: ")
290 .append(arg.getDefaultBoolValue()).append("; Negated: ")
291 .append(negated).append("\n");
292 if (arg.hasOption(Opt.STRING))
294 sb.append("Values:");
295 boolean first = true;
296 for (ArgValue av : argValueList)
298 String v = av.getValue();
302 sb.append(v).append("'");
307 sb.append("Count: ").append(argCount).append("\n");
308 return sb.toString();
311 protected void addValue()
316 protected void addValue(String val, int argIndex)
318 addArgValue(new ArgValue(val, argIndex));
321 protected void addArgValue(ArgValue av)
323 if ((!arg.hasOption(Opt.MULTI) && argValueList.size() > 0)
324 || (arg.hasOption(Opt.NODUPLICATEVALUES)
325 && argValueList.contains(av.getValue())))
327 if (argValueList == null)
329 argValueList = new ArrayList<ArgValue>();
331 SubVals sv = ArgParser.getSubVals(av.getValue());
334 String id = sv.get(ID);
338 argValueList.add(av);
341 protected boolean hasValue(String val)
343 return argValueList.contains(val);
346 protected ArgValue getArgValue()
348 if (arg.hasOption(Opt.MULTI))
349 Console.warn("Requesting single value for multi value argument");
350 return argValueList.size() > 0 ? argValueList.get(0) : null;
353 protected List<ArgValue> getArgValueList()
358 protected boolean hasId(String id)
360 return idMap.containsKey(id);
363 protected ArgValue getId(String id)
365 return idMap.get(id);
370 private List<String> vargs = null;
372 private boolean isApplet;
374 // private AppletParams appletParams;
376 public boolean isApplet()
381 public String nextValue()
383 return vargs.remove(0);
391 public String getValue(String arg)
393 return getValue(arg, false);
396 public String getValue(String arg, boolean utf8decode)
398 int index = vargs.indexOf(arg);
403 ret = vargs.get(index + 1).toString();
406 if (utf8decode && ret != null)
410 dc = URLDecoder.decode(ret, "UTF-8");
412 } catch (Exception e)
414 // TODO: log failure to decode
422 public Object getAppletValue(String key, String def, boolean asString)
425 return (appletParams == null ? null
426 : (value = appletParams.get(key.toLowerCase())) == null ? def
427 : asString ? "" + value : value);
432 private static final Map<String, Arg> argMap;
434 private Map<String, ArgValuesMap> linkedArgs = new HashMap<>();
436 private List<String> linkedOrder = null;
438 private List<Arg> argList;
442 argMap = new HashMap<>();
443 bootstrapArgs = new ArrayList<>();
444 for (Arg a : EnumSet.allOf(Arg.class))
446 if (a.hasOption(Opt.BOOTSTRAP))
447 bootstrapArgs.add(a);
448 for (String argName : a.getNames())
450 if (argMap.containsKey(argName))
452 Console.warn("Trying to add argument name multiple times: '"
453 + argName + "'"); // RESTORE THIS WHEN MERGED
454 if (argMap.get(argName) != a)
457 "Trying to add argument name multiple times for different Args: '"
458 + argMap.get(argName).getName() + ":" + argName
459 + "' and '" + a.getName() + ":" + argName
464 argMap.put(argName, a);
469 public ArgParser(String[] args)
471 this(Arrays.asList(args));
474 public ArgParser(List<String> args)
476 Enumeration<String> argE = Collections.enumeration(args);
478 while (argE.hasMoreElements())
480 String arg = argE.nextElement();
481 String argName = null;
483 String linkedId = null;
484 if (arg.startsWith("--"))
486 int equalPos = arg.indexOf('=');
489 argName = arg.substring(2, equalPos);
490 val = arg.substring(equalPos + 1);
494 argName = arg.substring(2);
496 int idOpen = argName.indexOf('[');
497 int idClose = argName.indexOf(']');
499 if (idOpen > -1 && idClose == argName.length() - 1)
501 linkedId = argName.substring(idOpen + 1, idClose);
502 argName = argName.substring(0, idOpen);
505 Arg a = argMap.get(argName);
506 // check for boolean prepended by "no"
507 boolean negated = false;
508 if (a == null && argName.startsWith(NEGATESTRING) && argMap
509 .containsKey(argName.substring(NEGATESTRING.length())))
511 argName = argName.substring(NEGATESTRING.length());
512 a = argMap.get(argName);
516 // check for config errors
520 Console.error("Argument '" + arg + "' not recognised. Ignoring.");
523 if (!a.hasOption(Opt.BOOLEAN) && negated)
525 // used "no" with a non-boolean option
526 Console.error("Argument '--" + NEGATESTRING + argName
527 + "' not a boolean option. Ignoring.");
530 if (!a.hasOption(Opt.STRING) && equalPos > -1)
532 // set --argname=value when arg does not accept values
533 Console.error("Argument '--" + argName
534 + "' does not expect a value (given as '" + arg
538 if (!a.hasOption(Opt.LINKED) && linkedId != null)
540 // set --argname[linkedId] when arg does not use linkedIds
541 Console.error("Argument '--" + argName
542 + "' does not expect a linked id (given as '" + arg
547 if (a.hasOption(Opt.STRING) && equalPos == -1)
549 // take next arg as value if required, and '=' was not found
550 if (!argE.hasMoreElements())
552 // no value to take for arg, which wants a value
553 Console.error("Argument '" + a.getName()
554 + "' requires a value, none given. Ignoring.");
557 val = argE.nextElement();
560 // use default linkedId for linked arguments
561 if (a.hasOption(Opt.LINKED) && linkedId == null)
562 linkedId = DEFAULTLINKEDID;
564 if (!linkedArgs.containsKey(linkedId))
565 linkedArgs.put(linkedId, new ArgValuesMap());
567 ArgValuesMap avm = linkedArgs.get(linkedId);
569 if (a.hasOption(Opt.NODUPLICATEVALUES) && avm.hasValue(a, val))
571 Console.error("Argument '--" + argName
572 + "' cannot contain a duplicate value ('" + val
573 + "'). Ignoring this and subsequent occurrences.");
577 // check for unique id
578 SubVals sv = ArgParser.getSubVals(val);
579 String id = sv.get(ArgValues.ID);
580 if (id != null && avm.hasId(a, id))
582 Console.error("Argument '--" + argName + "' has a duplicate id ('"
583 + id + "'). Ignoring.");
587 ArgValues avs = avm.getOrCreateArgValues(a);
590 avs = new ArgValues(a);
592 // store appropriate value
593 if (a.hasOption(Opt.STRING))
595 avs.addValue(val, argIndex);
597 else if (a.hasOption(Opt.BOOLEAN))
599 avs.setBoolean(!negated, argIndex);
600 avs.setNegated(negated);
602 else if (a.hasOption(Opt.UNARY))
604 avs.setBoolean(true, argIndex);
606 avs.incrementCount();
608 // store in appropriate place
609 if (a.hasOption(Opt.LINKED))
611 // allow a default linked id for single usage
612 if (linkedId == null)
613 linkedId = DEFAULTLINKEDID;
614 // store the order of linkedIds
615 if (linkedOrder == null)
616 linkedOrder = new ArrayList<>();
617 if (!linkedOrder.contains(linkedId))
618 linkedOrder.add(linkedId);
621 // store arg in the list of args used
623 argList = new ArrayList<>();
624 if (!argList.contains(a))
630 public boolean isSet(Arg a)
632 return a.hasOption(Opt.LINKED) ? isSet("", a) : isSet(null, a);
635 public boolean isSet(String linkedId, Arg a)
637 ArgValuesMap avm = linkedArgs.get(linkedId);
638 return avm == null ? false : avm.containsArg(a);
641 public boolean getBool(Arg a)
643 if (!a.hasOption(Opt.BOOLEAN) && !a.hasOption(Opt.UNARY))
645 Console.warn("Getting boolean from non boolean Arg '" + a.getName()
648 return a.hasOption(Opt.LINKED) ? getBool("", a) : getBool(null, a);
651 public boolean getBool(String linkedId, Arg a)
653 ArgValuesMap avm = linkedArgs.get(linkedId);
655 return a.getDefaultBoolValue();
656 ArgValues avs = avm.getArgValues(a);
657 return avs == null ? a.getDefaultBoolValue() : avs.getBoolean();
660 public List<String> linkedIds()
665 public ArgValuesMap linkedArgs(String id)
667 return linkedArgs.get(id);
671 public String toString()
673 StringBuilder sb = new StringBuilder();
674 sb.append("UNLINKED\n");
675 sb.append(argValuesMapToString(linkedArgs.get(null)));
676 if (linkedIds() != null)
678 sb.append("LINKED\n");
679 for (String id : linkedIds())
681 // already listed these as UNLINKED args
685 ArgValuesMap avm = linkedArgs(id);
686 sb.append("ID: '").append(id).append("'\n");
687 sb.append(argValuesMapToString(avm));
690 return sb.toString();
693 private static String argValuesMapToString(ArgValuesMap avm)
697 StringBuilder sb = new StringBuilder();
698 for (Arg a : avm.getArgKeys())
700 ArgValues v = avm.getArgValues(a);
701 sb.append(v.toString());
704 return sb.toString();
707 public static SubVals getSubVals(String item)
709 return new SubVals(item);
713 * A helper class to keep an index of argument position with argument values
715 public static class ArgValue
717 private int argIndex;
719 private String value;
723 protected ArgValue(String value, int argIndex)
726 this.argIndex = argIndex;
729 protected String getValue()
734 protected int getArgIndex()
739 protected void setId(String i)
744 protected String getId()
751 * A helper class to parse a string of the possible forms "content"
752 * "[index]content", "[keyName=keyValue]content" and return the integer index,
753 * the strings keyName and keyValue, and the content after the square brackets
754 * (if present). Values not set `will be -1 or null.
756 public static class SubVals
758 private static int NOTSET = -1;
760 private int index = NOTSET;
762 private Map<String, String> subVals = null;
764 private static char SEPARATOR = ';';
766 private String content = null;
768 public SubVals(String item)
770 this.parseVals(item);
773 public void parseVals(String item)
777 if (item.indexOf('[') == 0 && item.indexOf(']') > 1)
779 int openBracket = item.indexOf('[');
780 int closeBracket = item.indexOf(']');
781 String subvalsString = item.substring(openBracket + 1,
783 this.content = item.substring(closeBracket + 1);
784 boolean setIndex = false;
785 for (String subvalString : subvalsString
786 .split(Character.toString(SEPARATOR)))
788 int equals = subvalString.indexOf('=');
792 subVals = new HashMap<>();
793 subVals.put(subvalString.substring(0, equals),
794 subvalString.substring(equals + 1));
800 this.index = Integer.parseInt(subvalString);
802 } catch (NumberFormatException e)
804 Console.warn("Failed to obtain subvalue or index from '"
805 + item + "'. Setting index=0 and using content='"
819 public boolean notSet()
821 // notSet is true if content present but nonsensical
822 return index == NOTSET && subVals == null;
825 public String get(String key)
827 return subVals == null ? null : subVals.get(key);
830 public boolean has(String key)
832 return subVals == null ? false : subVals.containsKey(key);
835 public int getIndex()
840 public String getContent()
847 * Helper class to allow easy extraction of information about specific
848 * argument values (without having to check for null etc all the time)
850 protected static class ArgValuesMap
852 protected Map<Arg, ArgValues> m;
854 protected ArgValuesMap()
859 protected ArgValuesMap(Map<Arg, ArgValues> map)
864 private Map<Arg, ArgValues> getMap()
869 private void newMap()
871 m = new HashMap<Arg, ArgValues>();
874 private void newArg(Arg a)
879 m.put(a, new ArgValues(a));
882 protected void addArgValue(Arg a, ArgValue av)
884 if (getMap() == null)
885 m = new HashMap<Arg, ArgValues>();
887 if (!m.containsKey(a))
888 m.put(a, new ArgValues(a));
889 ArgValues avs = m.get(a);
893 protected ArgValues getArgValues(Arg a)
895 return m == null ? null : m.get(a);
898 protected ArgValues getOrCreateArgValues(Arg a)
900 ArgValues avs = m.get(a);
903 return getArgValues(a);
906 protected List<ArgValue> getArgValueList(Arg a)
908 ArgValues avs = getArgValues(a);
909 return avs == null ? new ArrayList<>() : avs.getArgValueList();
912 protected ArgValue getArgValue(Arg a)
914 List<ArgValue> vals = getArgValueList(a);
915 return (vals == null || vals.size() == 0) ? null : vals.get(0);
918 protected String getValue(Arg a)
920 ArgValue av = getArgValue(a);
921 return av == null ? null : av.getValue();
924 protected boolean containsArg(Arg a)
926 if (m == null || !m.containsKey(a))
928 return a.hasOption(Opt.STRING) ? getArgValue(a) != null
929 : this.getBoolean(a);
932 protected boolean hasValue(Arg a, String val)
934 if (m == null || !m.containsKey(a))
936 for (ArgValue av : getArgValueList(a))
938 String avVal = av.getValue();
939 if ((val == null && avVal == null)
940 || (val != null && val.equals(avVal)))
948 protected boolean getBoolean(Arg a)
950 ArgValues av = getArgValues(a);
951 return av == null ? false : av.getBoolean();
954 protected Set<Arg> getArgKeys()
959 protected ArgValue getClosestPreviousArgValueOfArg(ArgValue thisAv,
962 ArgValue closestAv = null;
963 int thisArgIndex = thisAv.getArgIndex();
964 ArgValues compareAvs = this.getArgValues(a);
965 int closestPreviousIndex = -1;
966 for (ArgValue av : compareAvs.getArgValueList())
968 int argIndex = av.getArgIndex();
969 if (argIndex < thisArgIndex && argIndex > closestPreviousIndex)
971 closestPreviousIndex = argIndex;
978 protected ArgValue getClosestNextArgValueOfArg(ArgValue thisAv, Arg a)
980 // this looks for the *next* arg that *might* be referring back to
981 // a thisAv. Such an arg would have no subValues (if it does it should
982 // specify an id in the subValues so wouldn't need to be guessed).
983 ArgValue closestAv = null;
984 int thisArgIndex = thisAv.getArgIndex();
985 ArgValues compareAvs = this.getArgValues(a);
986 int closestNextIndex = Integer.MAX_VALUE;
987 for (ArgValue av : compareAvs.getArgValueList())
989 int argIndex = av.getArgIndex();
990 if (argIndex > thisArgIndex && argIndex < closestNextIndex)
992 closestNextIndex = argIndex;
999 protected ArgValue[] getArgValuesReferringTo(String key, String value,
1002 // this looks for the *next* arg that *might* be referring back to
1003 // a thisAv. Such an arg would have no subValues (if it does it should
1004 // specify an id in the subValues so wouldn't need to be guessed).
1005 List<ArgValue> avList = new ArrayList<>();
1006 Arg[] args = a == null ? (Arg[]) this.getMap().keySet().toArray()
1009 for (Arg keyArg : args)
1011 for (ArgValue av : this.getArgValueList(keyArg))
1016 return (ArgValue[]) avList.toArray();
1019 protected boolean hasId(Arg a, String id)
1021 ArgValues avs = this.getArgValues(a);
1022 return avs == null ? false : avs.hasId(id);
1025 protected ArgValue getId(Arg a, String id)
1027 ArgValues avs = this.getArgValues(a);
1028 return avs == null ? null : avs.getId(id);
1032 public static ArgParser parseArgFiles(List<String> argFilenames)
1034 List<String> argsList = new ArrayList<>();
1035 for (String argFilename : argFilenames)
1037 File argFile = new File(argFilename);
1038 if (!argFile.exists())
1041 .println("--" + Arg.ARGFILE.name().toLowerCase(Locale.ROOT)
1042 + "=\"" + argFilename + "\": File does not exist.");
1047 argsList.addAll(Files.readAllLines(Paths.get(argFilename)));
1048 } catch (IOException e)
1051 "--" + Arg.ARGFILE.name().toLowerCase(Locale.ROOT) + "=\""
1052 + argFilename + "\": File could not be read.");
1056 return new ArgParser(argsList);
1059 public static class BootstrapArgs
1062 private static Map<Arg, List<String>> bootstrapArgMap = new HashMap<>();
1064 private BootstrapArgs(String[] args)
1069 public static BootstrapArgs getBootstrapArgs(String[] args)
1071 return new BootstrapArgs(args);
1074 private void init(String[] args)
1078 Enumeration<String> argE = Collections
1079 .enumeration(Arrays.asList(args));
1080 while (argE.hasMoreElements())
1082 String arg = argE.nextElement();
1083 String argName = null;
1085 if (arg.startsWith("--"))
1087 int equalPos = arg.indexOf('=');
1090 argName = arg.substring(2, equalPos);
1091 val = arg.substring(equalPos + 1);
1095 argName = arg.substring(2);
1098 Arg a = argMap.get(argName);
1099 if (a != null && bootstrapArgs.contains(a))
1101 if (!bootstrapArgMap.containsKey(a)
1102 || bootstrapArgMap.get(a) == null)
1104 List<String> aL = new ArrayList<>();
1106 bootstrapArgMap.put(a, aL);
1108 else if (a.hasOption(Opt.MULTI))
1110 List<String> aL = bootstrapArgMap.get(a); // already established
1113 bootstrapArgMap.put(a, aL);
1120 public boolean contains(Arg a)
1122 return bootstrapArgMap.containsKey(a);
1125 public List<String> getList(Arg a)
1127 return bootstrapArgMap.get(a);
1130 public String get(Arg a)
1132 if (bootstrapArgMap.containsKey(a))
1134 List<String> aL = bootstrapArgMap.get(a);
1135 return (aL == null || aL.size() == 0) ? null : aL.get(0);