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, CLOSE, DEBUG("d"), QUIET("q"),
76 HELP.setOptions(Opt.UNARY);
77 CALCULATION.setOptions(true, Opt.BOOLEAN); // default "true" implies only
78 // expecting "--nocalculation"
79 MENUBAR.setOptions(true, Opt.BOOLEAN);
80 STATUS.setOptions(true, Opt.BOOLEAN);
81 SHOWOVERVIEW.setOptions(Opt.UNARY, Opt.LINKED);
82 ANNOTATIONS.setOptions(Opt.STRING, Opt.LINKED);
83 COLOUR.setOptions(Opt.STRING, Opt.LINKED);
84 FEATURES.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
85 GROOVY.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
86 GROUPS.setOptions(Opt.STRING, Opt.LINKED);
87 HEADLESS.setOptions(Opt.UNARY, Opt.BOOTSTRAP);
88 JABAWS.setOptions(Opt.STRING);
89 ANNOTATION.setOptions(true, Opt.BOOLEAN);
90 ANNOTATION2.setOptions(true, Opt.BOOLEAN);
91 DISPLAY.setOptions(true, Opt.BOOLEAN);
92 GUI.setOptions(true, Opt.BOOLEAN);
93 NEWS.setOptions(true, Opt.BOOLEAN);
94 NOQUESTIONNAIRE.setOptions(Opt.UNARY); // unary as --questionnaire=val
95 // expects a string value
96 SORTBYTREE.setOptions(true, Opt.BOOLEAN);
97 USAGESTATS.setOptions(true, Opt.BOOLEAN);
98 OPEN.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
99 OPEN2.setOptions(Opt.STRING, Opt.LINKED);
100 PROPS.setOptions(Opt.STRING, Opt.BOOTSTRAP);
101 QUESTIONNAIRE.setOptions(Opt.STRING);
102 SETPROP.setOptions(Opt.STRING);
103 TREE.setOptions(Opt.STRING);
105 VDOC.setOptions(Opt.UNARY);
106 VSESS.setOptions(Opt.UNARY);
108 OUTPUT.setOptions(Opt.STRING, Opt.LINKED);
109 OUTPUTTYPE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
111 SSANNOTATION.setOptions(Opt.BOOLEAN, Opt.LINKED);
112 NOTEMPFAC.setOptions(Opt.UNARY, Opt.LINKED);
113 TEMPFAC.setOptions(Opt.STRING, Opt.LINKED);
114 TEMPFAC_LABEL.setOptions(Opt.STRING, Opt.LINKED);
115 TEMPFAC_DESC.setOptions(Opt.STRING, Opt.LINKED);
116 TEMPFAC_SHADING.setOptions(Opt.BOOLEAN, Opt.LINKED);
117 TITLE.setOptions(Opt.STRING, Opt.LINKED);
118 PAEMATRIX.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
119 NOSTRUCTURE.setOptions(Opt.UNARY, Opt.LINKED);
120 STRUCTURE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
121 WRAP.setOptions(Opt.BOOLEAN, Opt.LINKED);
122 IMAGE.setOptions(Opt.STRING, Opt.LINKED);
123 QUIT.setOptions(Opt.UNARY);
124 CLOSE.setOptions(Opt.UNARY, Opt.LINKED);
125 DEBUG.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
126 QUIET.setOptions(Opt.UNARY, Opt.MULTI, Opt.BOOTSTRAP);
127 ARGFILE.setOptions(Opt.STRING, Opt.MULTI, Opt.BOOTSTRAP);
130 private final String[] argNames;
132 private Opt[] argOptions;
134 private boolean defaultBoolValue = false;
136 public String toLongString()
138 StringBuilder sb = new StringBuilder();
139 sb.append("Arg: ").append(this.name());
140 for (String name : getNames())
142 sb.append(", '").append(name).append("'");
144 sb.append("\nOptions: ");
145 boolean first = true;
146 for (Opt o : argOptions)
152 sb.append(o.toString());
156 return sb.toString();
164 private Arg(String... names)
166 int length = (names == null || names.length == 0
167 || (names.length == 1 && names[0] == null)) ? 1
169 this.argNames = new String[length];
170 this.argNames[0] = this.getName();
172 System.arraycopy(names, 0, this.argNames, 1, names.length);
175 public String[] getNames()
180 public String getName()
182 return this.name().toLowerCase(Locale.ROOT).replace('_', '-');
186 public final String toString()
191 public boolean hasOption(Opt o)
193 if (argOptions == null)
195 for (Opt option : argOptions)
203 protected void setOptions(Opt... options)
205 setOptions(false, options);
208 protected void setOptions(boolean defaultBoolValue, Opt... options)
210 this.defaultBoolValue = defaultBoolValue;
211 argOptions = options;
214 protected boolean getDefaultBoolValue()
216 return defaultBoolValue;
220 public static class ArgValues
222 private static final String ID = "id";
226 private int argCount = 0;
228 private boolean boolValue = false;
230 private boolean negated = false;
232 private int boolIndex = -1;
234 private List<Integer> argsIndexes;
236 private List<ArgValue> argValueList;
238 private Map<String, ArgValue> idMap = new HashMap<>();
240 protected ArgValues(Arg a)
243 this.argValueList = new ArrayList<ArgValue>();
244 this.boolValue = arg.getDefaultBoolValue();
252 protected int getCount()
257 protected void incrementCount()
262 protected void setNegated(boolean b)
267 protected boolean isNegated()
272 protected void setBoolean(boolean b, int i)
278 protected boolean getBoolean()
280 return this.boolValue;
284 public String toString()
286 if (argValueList == null)
288 StringBuilder sb = new StringBuilder();
289 sb.append(arg.toLongString());
290 if (arg.hasOption(Opt.BOOLEAN) || arg.hasOption(Opt.UNARY))
291 sb.append("Boolean: ").append(boolValue).append("; Default: ")
292 .append(arg.getDefaultBoolValue()).append("; Negated: ")
293 .append(negated).append("\n");
294 if (arg.hasOption(Opt.STRING))
296 sb.append("Values:");
297 boolean first = true;
298 for (ArgValue av : argValueList)
300 String v = av.getValue();
304 sb.append(v).append("'");
309 sb.append("Count: ").append(argCount).append("\n");
310 return sb.toString();
313 protected void addValue()
318 protected void addValue(String val, int argIndex)
320 addArgValue(new ArgValue(val, argIndex));
323 protected void addArgValue(ArgValue av)
325 if ((!arg.hasOption(Opt.MULTI) && argValueList.size() > 0)
326 || (arg.hasOption(Opt.NODUPLICATEVALUES)
327 && argValueList.contains(av.getValue())))
329 if (argValueList == null)
331 argValueList = new ArrayList<ArgValue>();
333 SubVals sv = ArgParser.getSubVals(av.getValue());
336 String id = sv.get(ID);
340 argValueList.add(av);
343 protected boolean hasValue(String val)
345 return argValueList.contains(val);
348 protected ArgValue getArgValue()
350 if (arg.hasOption(Opt.MULTI))
351 Console.warn("Requesting single value for multi value argument");
352 return argValueList.size() > 0 ? argValueList.get(0) : null;
355 protected List<ArgValue> getArgValueList()
360 protected boolean hasId(String id)
362 return idMap.containsKey(id);
365 protected ArgValue getId(String id)
367 return idMap.get(id);
372 private List<String> vargs = null;
374 private boolean isApplet;
376 // private AppletParams appletParams;
378 public boolean isApplet()
383 public String nextValue()
385 return vargs.remove(0);
393 public String getValue(String arg)
395 return getValue(arg, false);
398 public String getValue(String arg, boolean utf8decode)
400 int index = vargs.indexOf(arg);
405 ret = vargs.get(index + 1).toString();
408 if (utf8decode && ret != null)
412 dc = URLDecoder.decode(ret, "UTF-8");
414 } catch (Exception e)
416 // TODO: log failure to decode
424 public Object getAppletValue(String key, String def, boolean asString)
427 return (appletParams == null ? null
428 : (value = appletParams.get(key.toLowerCase())) == null ? def
429 : asString ? "" + value : value);
434 private static final Map<String, Arg> argMap;
436 private Map<String, ArgValuesMap> linkedArgs = new HashMap<>();
438 private List<String> linkedOrder = null;
440 private List<Arg> argList;
444 argMap = new HashMap<>();
445 bootstrapArgs = new ArrayList<>();
446 for (Arg a : EnumSet.allOf(Arg.class))
448 if (a.hasOption(Opt.BOOTSTRAP))
449 bootstrapArgs.add(a);
450 for (String argName : a.getNames())
452 if (argMap.containsKey(argName))
454 Console.warn("Trying to add argument name multiple times: '"
455 + argName + "'"); // RESTORE THIS WHEN MERGED
456 if (argMap.get(argName) != a)
459 "Trying to add argument name multiple times for different Args: '"
460 + argMap.get(argName).getName() + ":" + argName
461 + "' and '" + a.getName() + ":" + argName
466 argMap.put(argName, a);
471 public ArgParser(String[] args)
473 this(Arrays.asList(args));
476 public ArgParser(List<String> args)
478 Enumeration<String> argE = Collections.enumeration(args);
480 while (argE.hasMoreElements())
482 String arg = argE.nextElement();
483 String argName = null;
485 String linkedId = null;
486 if (arg.startsWith("--"))
488 int equalPos = arg.indexOf('=');
491 argName = arg.substring(2, equalPos);
492 val = arg.substring(equalPos + 1);
496 argName = arg.substring(2);
498 int idOpen = argName.indexOf('[');
499 int idClose = argName.indexOf(']');
501 if (idOpen > -1 && idClose == argName.length() - 1)
503 linkedId = argName.substring(idOpen + 1, idClose);
504 argName = argName.substring(0, idOpen);
507 Arg a = argMap.get(argName);
508 // check for boolean prepended by "no"
509 boolean negated = false;
510 if (a == null && argName.startsWith(NEGATESTRING) && argMap
511 .containsKey(argName.substring(NEGATESTRING.length())))
513 argName = argName.substring(NEGATESTRING.length());
514 a = argMap.get(argName);
518 // check for config errors
522 Console.error("Argument '" + arg + "' not recognised. Ignoring.");
525 if (!a.hasOption(Opt.BOOLEAN) && negated)
527 // used "no" with a non-boolean option
528 Console.error("Argument '--" + NEGATESTRING + argName
529 + "' not a boolean option. Ignoring.");
532 if (!a.hasOption(Opt.STRING) && equalPos > -1)
534 // set --argname=value when arg does not accept values
535 Console.error("Argument '--" + argName
536 + "' does not expect a value (given as '" + arg
540 if (!a.hasOption(Opt.LINKED) && linkedId != null)
542 // set --argname[linkedId] when arg does not use linkedIds
543 Console.error("Argument '--" + argName
544 + "' does not expect a linked id (given as '" + arg
549 if (a.hasOption(Opt.STRING) && equalPos == -1)
551 // take next arg as value if required, and '=' was not found
552 if (!argE.hasMoreElements())
554 // no value to take for arg, which wants a value
555 Console.error("Argument '" + a.getName()
556 + "' requires a value, none given. Ignoring.");
559 val = argE.nextElement();
562 // use default linkedId for linked arguments
563 if (a.hasOption(Opt.LINKED) && linkedId == null)
564 linkedId = DEFAULTLINKEDID;
566 if (!linkedArgs.containsKey(linkedId))
567 linkedArgs.put(linkedId, new ArgValuesMap());
569 ArgValuesMap avm = linkedArgs.get(linkedId);
571 if (a.hasOption(Opt.NODUPLICATEVALUES) && avm.hasValue(a, val))
573 Console.error("Argument '--" + argName
574 + "' cannot contain a duplicate value ('" + val
575 + "'). Ignoring this and subsequent occurrences.");
579 // check for unique id
580 SubVals sv = ArgParser.getSubVals(val);
581 String id = sv.get(ArgValues.ID);
582 if (id != null && avm.hasId(a, id))
584 Console.error("Argument '--" + argName + "' has a duplicate id ('"
585 + id + "'). Ignoring.");
589 ArgValues avs = avm.getOrCreateArgValues(a);
592 avs = new ArgValues(a);
594 // store appropriate value
595 if (a.hasOption(Opt.STRING))
597 avs.addValue(val, argIndex);
599 else if (a.hasOption(Opt.BOOLEAN))
601 avs.setBoolean(!negated, argIndex);
602 avs.setNegated(negated);
604 else if (a.hasOption(Opt.UNARY))
606 avs.setBoolean(true, argIndex);
608 avs.incrementCount();
610 // store in appropriate place
611 if (a.hasOption(Opt.LINKED))
613 // allow a default linked id for single usage
614 if (linkedId == null)
615 linkedId = DEFAULTLINKEDID;
616 // store the order of linkedIds
617 if (linkedOrder == null)
618 linkedOrder = new ArrayList<>();
619 if (!linkedOrder.contains(linkedId))
620 linkedOrder.add(linkedId);
623 // store arg in the list of args used
625 argList = new ArrayList<>();
626 if (!argList.contains(a))
632 public boolean isSet(Arg a)
634 return a.hasOption(Opt.LINKED) ? isSet("", a) : isSet(null, a);
637 public boolean isSet(String linkedId, Arg a)
639 ArgValuesMap avm = linkedArgs.get(linkedId);
640 return avm == null ? false : avm.containsArg(a);
643 public boolean getBool(Arg a)
645 if (!a.hasOption(Opt.BOOLEAN) && !a.hasOption(Opt.UNARY))
647 Console.warn("Getting boolean from non boolean Arg '" + a.getName()
650 return a.hasOption(Opt.LINKED) ? getBool("", a) : getBool(null, a);
653 public boolean getBool(String linkedId, Arg a)
655 ArgValuesMap avm = linkedArgs.get(linkedId);
657 return a.getDefaultBoolValue();
658 ArgValues avs = avm.getArgValues(a);
659 return avs == null ? a.getDefaultBoolValue() : avs.getBoolean();
662 public List<String> linkedIds()
667 public ArgValuesMap linkedArgs(String id)
669 return linkedArgs.get(id);
673 public String toString()
675 StringBuilder sb = new StringBuilder();
676 sb.append("UNLINKED\n");
677 sb.append(argValuesMapToString(linkedArgs.get(null)));
678 if (linkedIds() != null)
680 sb.append("LINKED\n");
681 for (String id : linkedIds())
683 // already listed these as UNLINKED args
687 ArgValuesMap avm = linkedArgs(id);
688 sb.append("ID: '").append(id).append("'\n");
689 sb.append(argValuesMapToString(avm));
692 return sb.toString();
695 private static String argValuesMapToString(ArgValuesMap avm)
699 StringBuilder sb = new StringBuilder();
700 for (Arg a : avm.getArgKeys())
702 ArgValues v = avm.getArgValues(a);
703 sb.append(v.toString());
706 return sb.toString();
709 public static SubVals getSubVals(String item)
711 return new SubVals(item);
715 * A helper class to keep an index of argument position with argument values
717 public static class ArgValue
719 private int argIndex;
721 private String value;
725 protected ArgValue(String value, int argIndex)
728 this.argIndex = argIndex;
731 protected String getValue()
736 protected int getArgIndex()
741 protected void setId(String i)
746 protected String getId()
753 * A helper class to parse a string of the possible forms "content"
754 * "[index]content", "[keyName=keyValue]content" and return the integer index,
755 * the strings keyName and keyValue, and the content after the square brackets
756 * (if present). Values not set `will be -1 or null.
758 public static class SubVals
760 private static int NOTSET = -1;
762 private int index = NOTSET;
764 private Map<String, String> subVals = null;
766 private static char SEPARATOR = ';';
768 private String content = null;
770 public SubVals(String item)
772 this.parseVals(item);
775 public void parseVals(String item)
779 if (item.indexOf('[') == 0 && item.indexOf(']') > 1)
781 int openBracket = item.indexOf('[');
782 int closeBracket = item.indexOf(']');
783 String subvalsString = item.substring(openBracket + 1,
785 this.content = item.substring(closeBracket + 1);
786 boolean setIndex = false;
787 for (String subvalString : subvalsString
788 .split(Character.toString(SEPARATOR)))
790 int equals = subvalString.indexOf('=');
794 subVals = new HashMap<>();
795 subVals.put(subvalString.substring(0, equals),
796 subvalString.substring(equals + 1));
802 this.index = Integer.parseInt(subvalString);
804 } catch (NumberFormatException e)
806 Console.warn("Failed to obtain subvalue or index from '"
807 + item + "'. Setting index=0 and using content='"
821 public boolean notSet()
823 // notSet is true if content present but nonsensical
824 return index == NOTSET && subVals == null;
827 public String get(String key)
829 return subVals == null ? null : subVals.get(key);
832 public boolean has(String key)
834 return subVals == null ? false : subVals.containsKey(key);
837 public int getIndex()
842 public String getContent()
849 * Helper class to allow easy extraction of information about specific
850 * argument values (without having to check for null etc all the time)
852 protected static class ArgValuesMap
854 protected Map<Arg, ArgValues> m;
856 protected ArgValuesMap()
861 protected ArgValuesMap(Map<Arg, ArgValues> map)
866 private Map<Arg, ArgValues> getMap()
871 private void newMap()
873 m = new HashMap<Arg, ArgValues>();
876 private void newArg(Arg a)
881 m.put(a, new ArgValues(a));
884 protected void addArgValue(Arg a, ArgValue av)
886 if (getMap() == null)
887 m = new HashMap<Arg, ArgValues>();
889 if (!m.containsKey(a))
890 m.put(a, new ArgValues(a));
891 ArgValues avs = m.get(a);
895 protected ArgValues getArgValues(Arg a)
897 return m == null ? null : m.get(a);
900 protected ArgValues getOrCreateArgValues(Arg a)
902 ArgValues avs = m.get(a);
905 return getArgValues(a);
908 protected List<ArgValue> getArgValueList(Arg a)
910 ArgValues avs = getArgValues(a);
911 return avs == null ? new ArrayList<>() : avs.getArgValueList();
914 protected ArgValue getArgValue(Arg a)
916 List<ArgValue> vals = getArgValueList(a);
917 return (vals == null || vals.size() == 0) ? null : vals.get(0);
920 protected String getValue(Arg a)
922 ArgValue av = getArgValue(a);
923 return av == null ? null : av.getValue();
926 protected boolean containsArg(Arg a)
928 if (m == null || !m.containsKey(a))
930 return a.hasOption(Opt.STRING) ? getArgValue(a) != null
931 : this.getBoolean(a);
934 protected boolean hasValue(Arg a, String val)
936 if (m == null || !m.containsKey(a))
938 for (ArgValue av : getArgValueList(a))
940 String avVal = av.getValue();
941 if ((val == null && avVal == null)
942 || (val != null && val.equals(avVal)))
950 protected boolean getBoolean(Arg a)
952 ArgValues av = getArgValues(a);
953 return av == null ? false : av.getBoolean();
956 protected Set<Arg> getArgKeys()
961 protected ArgValue getClosestPreviousArgValueOfArg(ArgValue thisAv,
964 ArgValue closestAv = null;
965 int thisArgIndex = thisAv.getArgIndex();
966 ArgValues compareAvs = this.getArgValues(a);
967 int closestPreviousIndex = -1;
968 for (ArgValue av : compareAvs.getArgValueList())
970 int argIndex = av.getArgIndex();
971 if (argIndex < thisArgIndex && argIndex > closestPreviousIndex)
973 closestPreviousIndex = argIndex;
980 protected ArgValue getClosestNextArgValueOfArg(ArgValue thisAv, Arg a)
982 // this looks for the *next* arg that *might* be referring back to
983 // a thisAv. Such an arg would have no subValues (if it does it should
984 // specify an id in the subValues so wouldn't need to be guessed).
985 ArgValue closestAv = null;
986 int thisArgIndex = thisAv.getArgIndex();
987 ArgValues compareAvs = this.getArgValues(a);
988 int closestNextIndex = Integer.MAX_VALUE;
989 for (ArgValue av : compareAvs.getArgValueList())
991 int argIndex = av.getArgIndex();
992 if (argIndex > thisArgIndex && argIndex < closestNextIndex)
994 closestNextIndex = argIndex;
1001 protected ArgValue[] getArgValuesReferringTo(String key, String value,
1004 // this looks for the *next* arg that *might* be referring back to
1005 // a thisAv. Such an arg would have no subValues (if it does it should
1006 // specify an id in the subValues so wouldn't need to be guessed).
1007 List<ArgValue> avList = new ArrayList<>();
1008 Arg[] args = a == null ? (Arg[]) this.getMap().keySet().toArray()
1011 for (Arg keyArg : args)
1013 for (ArgValue av : this.getArgValueList(keyArg))
1018 return (ArgValue[]) avList.toArray();
1021 protected boolean hasId(Arg a, String id)
1023 ArgValues avs = this.getArgValues(a);
1024 return avs == null ? false : avs.hasId(id);
1027 protected ArgValue getId(Arg a, String id)
1029 ArgValues avs = this.getArgValues(a);
1030 return avs == null ? null : avs.getId(id);
1034 public static ArgParser parseArgFiles(List<String> argFilenames)
1036 List<String> argsList = new ArrayList<>();
1037 for (String argFilename : argFilenames)
1039 File argFile = new File(argFilename);
1040 if (!argFile.exists())
1043 .println("--" + Arg.ARGFILE.name().toLowerCase(Locale.ROOT)
1044 + "=\"" + argFilename + "\": File does not exist.");
1049 argsList.addAll(Files.readAllLines(Paths.get(argFilename)));
1050 } catch (IOException e)
1053 "--" + Arg.ARGFILE.name().toLowerCase(Locale.ROOT) + "=\""
1054 + argFilename + "\": File could not be read.");
1058 return new ArgParser(argsList);
1061 public static class BootstrapArgs
1064 private static Map<Arg, List<String>> bootstrapArgMap = new HashMap<>();
1066 private BootstrapArgs(String[] args)
1071 public static BootstrapArgs getBootstrapArgs(String[] args)
1073 return new BootstrapArgs(args);
1076 private void init(String[] args)
1080 Enumeration<String> argE = Collections
1081 .enumeration(Arrays.asList(args));
1082 while (argE.hasMoreElements())
1084 String arg = argE.nextElement();
1085 String argName = null;
1087 if (arg.startsWith("--"))
1089 int equalPos = arg.indexOf('=');
1092 argName = arg.substring(2, equalPos);
1093 val = arg.substring(equalPos + 1);
1097 argName = arg.substring(2);
1100 Arg a = argMap.get(argName);
1101 if (a != null && bootstrapArgs.contains(a))
1103 if (!bootstrapArgMap.containsKey(a)
1104 || bootstrapArgMap.get(a) == null)
1106 List<String> aL = new ArrayList<>();
1108 bootstrapArgMap.put(a, aL);
1110 else if (a.hasOption(Opt.MULTI))
1112 List<String> aL = bootstrapArgMap.get(a); // already established
1115 bootstrapArgMap.put(a, aL);
1122 public boolean contains(Arg a)
1124 return bootstrapArgMap.containsKey(a);
1127 public List<String> getList(Arg a)
1129 return bootstrapArgMap.get(a);
1132 public String get(Arg a)
1134 if (bootstrapArgMap.containsKey(a))
1136 List<String> aL = bootstrapArgMap.get(a);
1137 return (aL == null || aL.size() == 0) ? null : aL.get(0);