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.Collection;
31 import java.util.Collections;
32 import java.util.EnumSet;
33 import java.util.Enumeration;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Locale;
40 import jalview.util.Platform;
42 public class ArgParser
44 private static final String NEGATESTRING = "no";
46 private static final String DEFAULTLINKEDID = "";
48 private static enum Opt
50 BOOLEAN, STRING, UNARY, MULTI, LINKED, NODUPLICATEVALUES
53 // These bootstrap args are simply parsed before a full parse of arguments and
54 // so are accessible at an earlier stage to (e.g.) set debug log leve, provide
55 // a props file (that might set log level), run headlessly, read an argfile
56 // instead of other args.
57 private static final Collection<Arg> bootstrapArgs = new ArrayList(
58 Arrays.asList(Arg.PROPS, Arg.DEBUG, Arg.HEADLESS, Arg.ARGFILE));
63 NOCALCULATION, NOMENUBAR, NOSTATUS, SHOWOVERVIEW, ANNOTATIONS, COLOUR,
64 FEATURES, GROOVY, GROUPS, HEADLESS, JABAWS, NOANNOTATION, NOANNOTATION2,
65 NODISPLAY, NOGUI, NONEWS, NOQUESTIONNAIRE, NOSORTBYTREE, NOUSAGESTATS,
66 OPEN, OPEN2, PROPS, QUESTIONNAIRE, SETPROP, SORTBYTREE, TREE, VDOC,
69 HELP("h"), CALCULATION, MENUBAR, STATUS, SHOWOVERVIEW, ANNOTATIONS,
70 COLOUR, FEATURES, GROOVY, GROUPS, HEADLESS, JABAWS, ANNOTATION,
71 ANNOTATION2, DISPLAY, GUI, NEWS, NOQUESTIONNAIRE, SORTBYTREE,
72 USAGESTATS, OPEN, OPEN2, PROPS, QUESTIONNAIRE, SETPROP, TREE, VDOC,
73 VSESS, OUTPUT, OUTPUTTYPE, SSANNOTATION, NOTEMPFAC, TEMPFAC,
74 TEMPFAC_LABEL, TEMPFAC_DESC, TEMPFAC_SHADING, TITLE, PAEMATRIX, WRAP,
75 NOSTRUCTURE, STRUCTURE, IMAGE, QUIT, DEBUG("d"), ARGFILE;
79 HELP.setOptions(Opt.UNARY);
80 CALCULATION.setOptions(true, Opt.BOOLEAN); // default "true" implies only
81 // expecting "--nocalculation"
82 MENUBAR.setOptions(true, Opt.BOOLEAN);
83 STATUS.setOptions(true, Opt.BOOLEAN);
84 SHOWOVERVIEW.setOptions(Opt.UNARY, Opt.LINKED);
85 ANNOTATIONS.setOptions(Opt.STRING, Opt.LINKED);
86 COLOUR.setOptions(Opt.STRING, Opt.LINKED);
87 FEATURES.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
88 GROOVY.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
89 GROUPS.setOptions(Opt.STRING, Opt.LINKED);
90 HEADLESS.setOptions(Opt.UNARY);
91 JABAWS.setOptions(Opt.STRING);
92 ANNOTATION.setOptions(true, Opt.BOOLEAN);
93 ANNOTATION2.setOptions(true, Opt.BOOLEAN);
94 DISPLAY.setOptions(true, Opt.BOOLEAN);
95 GUI.setOptions(true, Opt.BOOLEAN);
96 NEWS.setOptions(true, Opt.BOOLEAN);
97 NOQUESTIONNAIRE.setOptions(Opt.UNARY); // unary as --questionnaire=val
98 // expects a string value
99 SORTBYTREE.setOptions(true, Opt.BOOLEAN);
100 USAGESTATS.setOptions(true, Opt.BOOLEAN);
101 OPEN.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
102 OPEN2.setOptions(Opt.STRING, Opt.LINKED);
103 PROPS.setOptions(Opt.STRING);
104 QUESTIONNAIRE.setOptions(Opt.STRING);
105 SETPROP.setOptions(Opt.STRING);
106 TREE.setOptions(Opt.STRING);
108 VDOC.setOptions(Opt.UNARY);
109 VSESS.setOptions(Opt.UNARY);
111 OUTPUT.setOptions(Opt.STRING, Opt.LINKED);
112 OUTPUTTYPE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
114 SSANNOTATION.setOptions(Opt.BOOLEAN, Opt.LINKED);
115 NOTEMPFAC.setOptions(Opt.UNARY, Opt.LINKED);
116 TEMPFAC.setOptions(Opt.STRING, Opt.LINKED);
117 TEMPFAC_LABEL.setOptions(Opt.STRING, Opt.LINKED);
118 TEMPFAC_DESC.setOptions(Opt.STRING, Opt.LINKED);
119 TEMPFAC_SHADING.setOptions(Opt.BOOLEAN, Opt.LINKED);
120 TITLE.setOptions(Opt.STRING, Opt.LINKED);
121 PAEMATRIX.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
122 NOSTRUCTURE.setOptions(Opt.UNARY, Opt.LINKED);
123 STRUCTURE.setOptions(Opt.STRING, Opt.LINKED, Opt.MULTI);
124 WRAP.setOptions(Opt.BOOLEAN, Opt.LINKED);
125 IMAGE.setOptions(Opt.STRING, Opt.LINKED);
126 QUIT.setOptions(Opt.UNARY);
127 DEBUG.setOptions(Opt.BOOLEAN);
128 ARGFILE.setOptions(Opt.STRING);
131 private final String[] argNames;
133 private Opt[] argOptions;
135 private boolean defaultBoolValue = false;
137 public String toLongString()
139 StringBuilder sb = new StringBuilder();
140 sb.append("Arg: ").append(this.name());
141 for (String name : getNames())
143 sb.append(", '").append(name).append("'");
145 sb.append("\nOptions: ");
146 boolean first = true;
147 for (Opt o : argOptions)
153 sb.append(o.toString());
157 return sb.toString();
165 private Arg(String... names)
167 int length = (names == null || names.length == 0
168 || (names.length == 1 && names[0] == null)) ? 1
170 this.argNames = new String[length];
171 this.argNames[0] = this.getName();
173 System.arraycopy(names, 0, this.argNames, 1, names.length);
176 public String[] getNames()
181 public String getName()
183 return this.name().toLowerCase(Locale.ROOT).replace('_', '-');
187 public final String toString()
192 public boolean hasOption(Opt o)
194 if (argOptions == null)
196 for (Opt option : argOptions)
204 protected void setOptions(Opt... options)
206 setOptions(false, options);
209 protected void setOptions(boolean defaultBoolValue, Opt... options)
211 this.defaultBoolValue = defaultBoolValue;
212 argOptions = options;
215 protected boolean getDefaultBoolValue()
217 return defaultBoolValue;
221 public static class ArgValues
223 private static final String ID = "id";
227 private int argCount = 0;
229 private boolean boolValue = false;
231 private boolean negated = false;
233 private int boolIndex = -1;
235 private List<Integer> argsIndexes;
237 private List<ArgValue> argValueList;
239 private Map<String, ArgValue> idMap = new HashMap<>();
241 protected ArgValues(Arg a)
244 this.argValueList = new ArrayList<ArgValue>();
245 this.boolValue = arg.getDefaultBoolValue();
253 protected int getCount()
258 protected void incrementCount()
263 protected void setNegated(boolean b)
268 protected boolean isNegated()
273 protected void setBoolean(boolean b, int i)
279 protected boolean getBoolean()
281 return this.boolValue;
285 public String toString()
287 if (argValueList == null)
289 StringBuilder sb = new StringBuilder();
290 sb.append(arg.toLongString());
291 if (arg.hasOption(Opt.BOOLEAN) || arg.hasOption(Opt.UNARY))
292 sb.append("Boolean: ").append(boolValue).append("; Default: ")
293 .append(arg.getDefaultBoolValue()).append("; Negated: ")
294 .append(negated).append("\n");
295 if (arg.hasOption(Opt.STRING))
297 sb.append("Values:");
298 boolean first = true;
299 for (ArgValue av : argValueList)
301 String v = av.getValue();
305 sb.append(v).append("'");
310 sb.append("Count: ").append(argCount).append("\n");
311 return sb.toString();
314 protected void addValue()
319 protected void addValue(String val, int argIndex)
321 addArgValue(new ArgValue(val, argIndex));
324 protected void addArgValue(ArgValue av)
326 if ((!arg.hasOption(Opt.MULTI) && argValueList.size() > 0)
327 || (arg.hasOption(Opt.NODUPLICATEVALUES)
328 && argValueList.contains(av.getValue())))
330 if (argValueList == null)
332 argValueList = new ArrayList<ArgValue>();
334 SubVals sv = ArgParser.getSubVals(av.getValue());
337 String id = sv.get(ID);
341 argValueList.add(av);
344 protected boolean hasValue(String val)
346 return argValueList.contains(val);
349 protected ArgValue getArgValue()
351 if (arg.hasOption(Opt.MULTI))
352 Console.warn("Requesting single value for multi value argument");
353 return argValueList.size() > 0 ? argValueList.get(0) : null;
356 protected List<ArgValue> getArgValueList()
361 protected boolean hasId(String id)
363 return idMap.containsKey(id);
366 protected ArgValue getId(String id)
368 return idMap.get(id);
373 private List<String> vargs = null;
375 private boolean isApplet;
377 // private AppletParams appletParams;
379 public boolean isApplet()
384 public String nextValue()
386 return vargs.remove(0);
394 public String getValue(String arg)
396 return getValue(arg, false);
399 public String getValue(String arg, boolean utf8decode)
401 int index = vargs.indexOf(arg);
406 ret = vargs.get(index + 1).toString();
409 if (utf8decode && ret != null)
413 dc = URLDecoder.decode(ret, "UTF-8");
415 } catch (Exception e)
417 // TODO: log failure to decode
425 public Object getAppletValue(String key, String def, boolean asString)
428 return (appletParams == null ? null
429 : (value = appletParams.get(key.toLowerCase())) == null ? def
430 : asString ? "" + value : value);
435 private static final Map<String, Arg> argMap;
437 private Map<String, ArgValuesMap> linkedArgs = new HashMap<>();
439 private List<String> linkedOrder = null;
441 private List<Arg> argList;
445 argMap = new HashMap<>();
446 for (Arg a : EnumSet.allOf(Arg.class))
448 ARGNAME: 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)
472 vargs = new ArrayList<>();
473 isApplet = (args.length > 0 && args[0].startsWith("<applet"));
476 // appletParams = AppletParams.getAppletParams(args, vargs);
485 // AppletParams.getAppletParams(Platform.getAppletInfoAsMap(), vargs);
487 for (int i = 0; i < args.length; i++)
489 String arg = args[i].trim();
490 if (arg.charAt(0) == '-')
492 arg = arg.substring(1);
499 Enumeration<String> argE = Collections.enumeration(Arrays.asList(args));
501 while (argE.hasMoreElements())
503 String arg = argE.nextElement();
504 String argName = null;
506 String linkedId = null;
507 if (arg.startsWith("--"))
509 int equalPos = arg.indexOf('=');
512 argName = arg.substring(2, equalPos);
513 val = arg.substring(equalPos + 1);
517 argName = arg.substring(2);
519 int idOpen = argName.indexOf('[');
520 int idClose = argName.indexOf(']');
522 if (idOpen > -1 && idClose == argName.length() - 1)
524 linkedId = argName.substring(idOpen + 1, idClose);
525 argName = argName.substring(0, idOpen);
528 Arg a = argMap.get(argName);
529 // check for boolean prepended by "no"
530 boolean negated = false;
531 if (a == null && argName.startsWith(NEGATESTRING) && argMap
532 .containsKey(argName.substring(NEGATESTRING.length())))
534 argName = argName.substring(NEGATESTRING.length());
535 a = argMap.get(argName);
539 // check for config errors
543 Console.error("Argument '" + arg + "' not recognised. Ignoring.");
546 if (!a.hasOption(Opt.BOOLEAN) && negated)
548 // used "no" with a non-boolean option
549 Console.error("Argument '--" + NEGATESTRING + argName
550 + "' not a boolean option. Ignoring.");
553 if (!a.hasOption(Opt.STRING) && equalPos > -1)
555 // set --argname=value when arg does not accept values
556 Console.error("Argument '--" + argName
557 + "' does not expect a value (given as '" + arg
561 if (!a.hasOption(Opt.LINKED) && linkedId != null)
563 // set --argname[linkedId] when arg does not use linkedIds
564 Console.error("Argument '--" + argName
565 + "' does not expect a linked id (given as '" + arg
570 if (a.hasOption(Opt.STRING) && equalPos == -1)
572 // take next arg as value if required, and '=' was not found
573 if (!argE.hasMoreElements())
575 // no value to take for arg, which wants a value
576 Console.error("Argument '" + a.getName()
577 + "' requires a value, none given. Ignoring.");
580 val = argE.nextElement();
583 // use default linkedId for linked arguments
584 if (a.hasOption(Opt.LINKED) && linkedId == null)
585 linkedId = DEFAULTLINKEDID;
587 if (!linkedArgs.containsKey(linkedId))
588 linkedArgs.put(linkedId, new ArgValuesMap());
590 ArgValuesMap avm = linkedArgs.get(linkedId);
592 if (a.hasOption(Opt.NODUPLICATEVALUES) && avm.hasValue(a, val))
594 Console.error("Argument '--" + argName
595 + "' cannot contain a duplicate value ('" + val
596 + "'). Ignoring this and subsequent occurrences.");
600 // check for unique id
601 SubVals sv = ArgParser.getSubVals(val);
602 String id = sv.get(ArgValues.ID);
603 if (id != null && avm.hasId(a, id))
605 Console.error("Argument '--" + argName + "' has a duplicate id ('"
606 + id + "'). Ignoring.");
610 ArgValues avs = avm.getOrCreateArgValues(a);
613 avs = new ArgValues(a);
615 // store appropriate value
616 if (a.hasOption(Opt.STRING))
618 avs.addValue(val, argIndex);
620 else if (a.hasOption(Opt.BOOLEAN))
622 avs.setBoolean(!negated, argIndex);
623 avs.setNegated(negated);
625 else if (a.hasOption(Opt.UNARY))
627 avs.setBoolean(true, argIndex);
629 avs.incrementCount();
631 // store in appropriate place
632 if (a.hasOption(Opt.LINKED))
634 // allow a default linked id for single usage
635 if (linkedId == null)
636 linkedId = DEFAULTLINKEDID;
637 // store the order of linkedIds
638 if (linkedOrder == null)
639 linkedOrder = new ArrayList<>();
640 if (!linkedOrder.contains(linkedId))
641 linkedOrder.add(linkedId);
644 // store arg in the list of args used
646 argList = new ArrayList<>();
647 if (!argList.contains(a))
653 public boolean isSet(Arg a)
655 return a.hasOption(Opt.LINKED) ? isSet("", a) : isSet(null, a);
658 public boolean isSet(String linkedId, Arg a)
660 ArgValuesMap avm = linkedArgs.get(linkedId);
661 return avm == null ? false : avm.containsArg(a);
664 public boolean getBool(Arg a)
666 if (!a.hasOption(Opt.BOOLEAN) && !a.hasOption(Opt.UNARY))
668 Console.warn("Getting boolean from non boolean Arg '" + a.getName()
671 return a.hasOption(Opt.LINKED) ? getBool("", a) : getBool(null, a);
674 public boolean getBool(String linkedId, Arg a)
676 ArgValuesMap avm = linkedArgs.get(linkedId);
678 return a.getDefaultBoolValue();
679 ArgValues avs = avm.getArgValues(a);
680 return avs == null ? a.getDefaultBoolValue() : avs.getBoolean();
683 public List<String> linkedIds()
688 public ArgValuesMap linkedArgs(String id)
690 return linkedArgs.get(id);
694 public String toString()
696 StringBuilder sb = new StringBuilder();
697 sb.append("UNLINKED\n");
698 sb.append(argValuesMapToString(linkedArgs.get(null)));
699 if (linkedIds() != null)
701 sb.append("LINKED\n");
702 for (String id : linkedIds())
704 // already listed these as UNLINKED args
708 ArgValuesMap avm = linkedArgs(id);
709 sb.append("ID: '").append(id).append("'\n");
710 sb.append(argValuesMapToString(avm));
713 return sb.toString();
716 private static String argValuesMapToString(ArgValuesMap avm)
720 StringBuilder sb = new StringBuilder();
721 for (Arg a : avm.getArgKeys())
723 ArgValues v = avm.getArgValues(a);
724 sb.append(v.toString());
727 return sb.toString();
730 public static SubVals getSubVals(String item)
732 return new SubVals(item);
736 * A helper class to keep an index of argument position with argument values
738 public static class ArgValue
740 private int argIndex;
742 private String value;
746 protected ArgValue(String value, int argIndex)
749 this.argIndex = argIndex;
752 protected String getValue()
757 protected int getArgIndex()
762 protected void setId(String i)
767 protected String getId()
774 * A helper class to parse a string of the possible forms "content"
775 * "[index]content", "[keyName=keyValue]content" and return the integer index,
776 * the strings keyName and keyValue, and the content after the square brackets
777 * (if present). Values not set `will be -1 or null.
779 public static class SubVals
781 private static int NOTSET = -1;
783 private int index = NOTSET;
785 private Map<String, String> subVals = null;
787 private static char SEPARATOR = ';';
789 private String content = null;
791 public SubVals(String item)
793 this.parseVals(item);
796 public void parseVals(String item)
800 if (item.indexOf('[') == 0 && item.indexOf(']') > 1)
802 int openBracket = item.indexOf('[');
803 int closeBracket = item.indexOf(']');
804 String subvalsString = item.substring(openBracket + 1,
806 this.content = item.substring(closeBracket + 1);
807 boolean setIndex = false;
808 for (String subvalString : subvalsString
809 .split(Character.toString(SEPARATOR)))
811 int equals = subvalString.indexOf('=');
815 subVals = new HashMap<>();
816 subVals.put(subvalString.substring(0, equals),
817 subvalString.substring(equals + 1));
823 this.index = Integer.parseInt(subvalString);
825 } catch (NumberFormatException e)
827 Console.warn("Failed to obtain subvalue or index from '"
828 + item + "'. Setting index=0 and using content='"
842 public boolean notSet()
844 // notSet is true if content present but nonsensical
845 return index == NOTSET && subVals == null;
848 public String get(String key)
850 return subVals == null ? null : subVals.get(key);
853 public boolean has(String key)
855 return subVals == null ? false : subVals.containsKey(key);
858 public int getIndex()
863 public String getContent()
870 * Helper class to allow easy extraction of information about specific
871 * argument values (without having to check for null etc all the time)
873 protected static class ArgValuesMap
875 protected Map<Arg, ArgValues> m;
877 protected ArgValuesMap()
882 protected ArgValuesMap(Map<Arg, ArgValues> map)
887 private Map<Arg, ArgValues> getMap()
892 private void newMap()
894 m = new HashMap<Arg, ArgValues>();
897 private void newArg(Arg a)
902 m.put(a, new ArgValues(a));
905 protected void addArgValue(Arg a, ArgValue av)
907 if (getMap() == null)
908 m = new HashMap<Arg, ArgValues>();
910 if (!m.containsKey(a))
911 m.put(a, new ArgValues(a));
912 ArgValues avs = m.get(a);
916 protected ArgValues getArgValues(Arg a)
918 return m == null ? null : m.get(a);
921 protected ArgValues getOrCreateArgValues(Arg a)
923 ArgValues avs = m.get(a);
926 return getArgValues(a);
929 protected List<ArgValue> getArgValueList(Arg a)
931 ArgValues avs = getArgValues(a);
932 return avs == null ? new ArrayList<>() : avs.getArgValueList();
935 protected ArgValue getArgValue(Arg a)
937 List<ArgValue> vals = getArgValueList(a);
938 return (vals == null || vals.size() == 0) ? null : vals.get(0);
941 protected String getValue(Arg a)
943 ArgValue av = getArgValue(a);
944 return av == null ? null : av.getValue();
947 protected boolean containsArg(Arg a)
949 if (m == null || !m.containsKey(a))
951 return a.hasOption(Opt.STRING) ? getArgValue(a) != null
952 : this.getBoolean(a);
955 protected boolean hasValue(Arg a, String val)
957 if (m == null || !m.containsKey(a))
959 for (ArgValue av : getArgValueList(a))
961 String avVal = av.getValue();
962 if ((val == null && avVal == null)
963 || (val != null && val.equals(avVal)))
971 protected boolean getBoolean(Arg a)
973 ArgValues av = getArgValues(a);
974 return av == null ? false : av.getBoolean();
977 protected Set<Arg> getArgKeys()
982 protected ArgValue getClosestPreviousArgValueOfArg(ArgValue thisAv,
985 ArgValue closestAv = null;
986 int thisArgIndex = thisAv.getArgIndex();
987 ArgValues compareAvs = this.getArgValues(a);
988 int closestPreviousIndex = -1;
989 for (ArgValue av : compareAvs.getArgValueList())
991 int argIndex = av.getArgIndex();
992 if (argIndex < thisArgIndex && argIndex > closestPreviousIndex)
994 closestPreviousIndex = argIndex;
1001 protected ArgValue getClosestNextArgValueOfArg(ArgValue thisAv, Arg a)
1003 // this looks for the *next* arg that *might* be referring back to
1004 // a thisAv. Such an arg would have no subValues (if it does it should
1005 // specify an id in the subValues so wouldn't need to be guessed).
1006 ArgValue closestAv = null;
1007 int thisArgIndex = thisAv.getArgIndex();
1008 ArgValues compareAvs = this.getArgValues(a);
1009 int closestNextIndex = Integer.MAX_VALUE;
1010 for (ArgValue av : compareAvs.getArgValueList())
1012 int argIndex = av.getArgIndex();
1013 if (argIndex > thisArgIndex && argIndex < closestNextIndex)
1015 closestNextIndex = argIndex;
1022 protected ArgValue[] getArgValuesReferringTo(String key, String value,
1025 // this looks for the *next* arg that *might* be referring back to
1026 // a thisAv. Such an arg would have no subValues (if it does it should
1027 // specify an id in the subValues so wouldn't need to be guessed).
1028 List<ArgValue> avList = new ArrayList<>();
1029 Arg[] args = a == null ? (Arg[]) this.getMap().keySet().toArray()
1032 for (Arg keyArg : args)
1034 for (ArgValue av : this.getArgValueList(keyArg))
1039 return (ArgValue[]) avList.toArray();
1042 protected boolean hasId(Arg a, String id)
1044 ArgValues avs = this.getArgValues(a);
1045 return avs == null ? false : avs.hasId(id);
1048 protected ArgValue getId(Arg a, String id)
1050 ArgValues avs = this.getArgValues(a);
1051 return avs == null ? null : avs.getId(id);
1055 public static Map<Arg, String> bootstrapArgs(String[] args)
1057 Map<Arg, String> bootstrapArgMap = new HashMap<>();
1059 return bootstrapArgMap;
1060 Enumeration<String> argE = Collections.enumeration(Arrays.asList(args));
1061 while (argE.hasMoreElements())
1063 String arg = argE.nextElement();
1064 String argName = null;
1066 if (arg.startsWith("--"))
1068 int equalPos = arg.indexOf('=');
1071 argName = arg.substring(2, equalPos);
1072 val = arg.substring(equalPos + 1);
1076 argName = arg.substring(2);
1078 Arg a = argMap.get(argName);
1079 if (a != null && bootstrapArgs.contains(a))
1080 bootstrapArgMap.put(a, val);
1083 return bootstrapArgMap;
1086 public static ArgParser parseArgFile(String argFilename)
1088 List<String> argsList = null;
1089 File argFile = new File(argFilename);
1090 if (!argFile.exists())
1092 System.err.println("--" + Arg.ARGFILE.name().toLowerCase(Locale.ROOT)
1093 + "=\"" + argFilename + "\": File does not exist.");
1098 argsList = Files.readAllLines(Paths.get(argFilename));
1099 } catch (IOException e)
1101 System.err.println("--" + Arg.ARGFILE.name().toLowerCase(Locale.ROOT)
1102 + "=\"" + argFilename + "\": File could not be read.");
1105 return new ArgParser((String[]) argsList.toArray());