1 package jalview.bin.argparser;
4 import java.util.AbstractMap;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.HashMap;
8 import java.util.HashSet;
12 import java.util.stream.Collectors;
14 import jalview.bin.argparser.Arg.Opt;
15 import jalview.bin.argparser.Arg.Type;
16 import jalview.util.FileUtils;
18 public class BootstrapArgs
21 private Map<Arg, List<Map.Entry<Type, String>>> bootstrapArgMap = new HashMap<>();
23 private Set<File> argFiles = new HashSet<>();
25 public static BootstrapArgs getBootstrapArgs(String[] args)
27 List<String> argList = new ArrayList<>(Arrays.asList(args));
28 return new BootstrapArgs(argList);
31 public static BootstrapArgs getBootstrapArgs(List<String> args)
33 return new BootstrapArgs(args);
36 private BootstrapArgs(List<String> args)
41 private void parse(List<String> args, File inArgFile)
45 // avoid looping argFiles
46 if (inArgFile != null)
48 if (argFiles.contains(inArgFile))
51 "Looped argfiles detected: '" + inArgFile.getPath() + "'");
54 argFiles.add(inArgFile);
57 for (int i = 0; i < args.size(); i++)
59 String arg = args.get(i);
60 // look for double-dash, e.g. --arg
61 if (arg.startsWith(ArgParser.DOUBLEDASH))
63 String argName = null;
67 arg = arg.substring(ArgParser.DOUBLEDASH.length());
69 // look for equals e.g. --arg=value
70 int equalPos = arg.indexOf(ArgParser.EQUALS);
72 && ArgParser.argMap.containsKey(arg.substring(0, equalPos)))
74 argName = arg.substring(0, equalPos);
75 val = arg.substring(equalPos + 1);
77 // check for boolean prepended by "no"
78 else if (arg.startsWith(ArgParser.NEGATESTRING)
79 && ArgParser.argMap.containsKey(
80 arg.substring(ArgParser.NEGATESTRING.length())))
82 argName = arg.substring(ArgParser.NEGATESTRING.length());
85 else if (ArgParser.argMap.containsKey(arg))
92 // look for type modification e.g. --help-opening
93 int dashPos = arg.indexOf(ArgParser.SINGLEDASH);
96 String potentialArgName = arg.substring(0, dashPos);
97 Arg potentialArg = ArgParser.argMap.get(potentialArgName);
98 if (potentialArg != null && potentialArg.hasOption(Opt.HASTYPE))
100 argName = arg.substring(0, dashPos);
101 String typeName = arg.substring(dashPos + 1);
102 type = Type.valueOf(typeName);
107 Arg a = ArgParser.argMap.get(argName);
109 if (a == null || !a.hasOption(Opt.BOOTSTRAP))
111 // not a valid bootstrap arg
115 if (a.hasOption(Opt.STRING))
117 List<String> vals = null;
120 vals = ArgParser.getShellGlobbedFilenameValues(a, args, i + 1);
124 if (a.hasOption(Opt.GLOB))
126 vals = FileUtils.getFilenamesFromGlob(val);
130 vals = new ArrayList<>();
134 addAll(a, type, vals);
136 if (a == Arg.ARGFILE)
138 for (String filename : vals)
140 File argFile = new File(filename);
141 parse(ArgParser.readArgFile(argFile), argFile);
153 public boolean contains(Arg a)
155 return bootstrapArgMap.containsKey(a);
158 public boolean containsType(Type t)
160 for (List<Map.Entry<Type, String>> l : bootstrapArgMap.values())
162 for (Map.Entry<Type, String> e : l)
171 public List<Arg> getArgsOfType(Type t)
173 return getArgsOfType(t, new Opt[] {});
176 public List<Arg> getArgsOfType(Type t, Opt... opts)
178 List<Arg> args = new ArrayList<>();
179 for (Arg a : bootstrapArgMap.keySet())
181 if (!a.hasAllOptions(opts))
184 List<Map.Entry<Type, String>> l = bootstrapArgMap.get(a);
185 if (l.stream().anyMatch(e -> e.getKey() == t))
193 public List<Map.Entry<Type, String>> getList(Arg a)
195 return bootstrapArgMap.get(a);
198 public List<String> getValueList(Arg a)
200 return bootstrapArgMap.get(a).stream().map(e -> e.getValue())
201 .collect(Collectors.toList());
204 private List<Map.Entry<Type, String>> getOrCreateList(Arg a)
206 List<Map.Entry<Type, String>> l = getList(a);
209 l = new ArrayList<>();
215 private void putList(Arg a, List<Map.Entry<Type, String>> l)
217 bootstrapArgMap.put(a, l);
221 * Creates a new list if not used before,
222 * adds the value unless the existing list is non-empty
223 * and the arg is not MULTI (so first expressed value is
226 private void add(Arg a, Type t, String s)
228 List<Map.Entry<Type, String>> l = getOrCreateList(a);
229 if (a.hasOption(Opt.MULTI) || l.size() == 0)
235 private void addAll(Arg a, Type t, List<String> al)
237 List<Map.Entry<Type, String>> l = getOrCreateList(a);
238 if (a.hasOption(Opt.MULTI))
245 else if (l.size() == 0 && al.size() > 0)
247 l.add(entry(t, al.get(0)));
251 private static Map.Entry<Type, String> entry(Type t, String s)
253 return new AbstractMap.SimpleEntry<Type, String>(t, s);
257 * Retrieves the first value even if MULTI.
258 * A convenience for non-MULTI args.
260 public String get(Arg a)
262 if (!bootstrapArgMap.containsKey(a))
264 List<Map.Entry<Type, String>> aL = bootstrapArgMap.get(a);
265 return (aL == null || aL.size() == 0) ? null : aL.get(0).getValue();
268 public boolean getBoolean(Arg a, boolean d)
270 if (!bootstrapArgMap.containsKey(a))
272 return Boolean.parseBoolean(get(a));
275 public boolean getBoolean(Arg a)
277 if (!(a.hasOption(Opt.BOOLEAN) || a.hasOption(Opt.UNARY)))
281 if (bootstrapArgMap.containsKey(a))
282 return Boolean.parseBoolean(get(a));
284 return a.getDefaultBoolValue();