1 package jalview.bin.argparser;
4 import java.util.ArrayList;
5 import java.util.Collections;
6 import java.util.HashMap;
8 import java.util.Locale;
12 import jalview.bin.Cache;
13 import jalview.bin.Console;
14 import jalview.bin.argparser.Arg.Opt;
15 import jalview.bin.argparser.Arg.Type;
16 import jalview.util.FileUtils;
19 * Helper class to allow easy extraction of information about specific argument
20 * values (without having to check for null etc all the time)
22 public class ArgValuesMap
24 private List<ArgInfo> argInfoList = new ArrayList<>();
26 protected Map<Arg, ArgValues> m;
28 private String linkedId;
30 protected ArgValuesMap(String linkedId)
32 this.linkedId = linkedId;
36 protected ArgValuesMap(String linkedId, Map<Arg, ArgValues> map)
38 this.linkedId = linkedId;
42 public String getLinkedId()
47 private Map<Arg, ArgValues> getMap()
54 m = new HashMap<Arg, ArgValues>();
57 private void newArg(Arg a)
62 m.put(a, new ArgValues(a));
65 public ArgValues getArgValues(Arg a)
67 return m == null ? null : m.get(a);
70 public ArgValues getOrCreateArgValues(Arg a)
72 ArgValues avs = m.get(a);
75 return getArgValues(a);
78 public List<ArgValue> getArgValueList(Arg a)
80 ArgValues avs = getArgValues(a);
81 return avs == null ? new ArrayList<>() : avs.getArgValueList();
84 public ArgValue getArgValue(Arg a)
86 List<ArgValue> vals = getArgValueList(a);
87 return (vals == null || vals.size() == 0) ? null : vals.get(0);
90 public String getValue(Arg a)
92 ArgValue av = getArgValue(a);
93 return av == null ? null : av.getValue();
96 public boolean containsArg(Arg a)
98 if (m == null || !m.containsKey(a))
100 return a.hasOption(Opt.STRING) ? getArgValue(a) != null : true;
103 public boolean hasValue(Arg a, String val)
105 if (m == null || !m.containsKey(a))
107 for (ArgValue av : getArgValueList(a))
109 String avVal = av.getValue();
110 if ((val == null && avVal == null)
111 || (val != null && val.equals(avVal)))
119 public boolean getBoolean(Arg a)
121 ArgValues av = getArgValues(a);
122 return av == null ? false : av.getBoolean();
125 public Set<Arg> getArgKeys()
130 public ArgValue getArgValueOfArgWithSubValKey(Arg a, String svKey)
132 return getArgValueOfArgWithSubValKey(a, svKey, false);
135 public ArgValue getArgValueOfArgWithSubValKey(Arg a, String svKey,
138 ArgValues avs = this.getArgValues(a);
143 List<ArgValue> compareAvs = avs.getArgValueList();
144 for (int i = 0; i < compareAvs.size(); i++)
146 int index = last ? compareAvs.size() - 1 - i : i;
147 ArgValue av = compareAvs.get(index);
148 SubVals sv = av.getSubVals();
149 if (sv.has(svKey) && !sv.get(svKey).equals("false"))
157 public ArgValue getClosestPreviousArgValueOfArg(ArgValue thisAv, Arg a)
159 ArgValue closestAv = null;
160 int thisArgIndex = thisAv.getArgIndex();
161 ArgValues compareAvs = this.getArgValues(a);
162 int closestPreviousIndex = -1;
163 for (ArgValue av : compareAvs.getArgValueList())
165 int argIndex = av.getArgIndex();
166 if (argIndex < thisArgIndex && argIndex > closestPreviousIndex)
168 closestPreviousIndex = argIndex;
175 public ArgValue getClosestNextArgValueOfArg(ArgValue thisAv, Arg a,
178 // this looks for the *next* arg that *might* be referring back to
179 // a thisAv. Such an arg would have no subValues (if it does it should
180 // specify an id in the subValues so wouldn't need to be guessed).
181 ArgValue closestAv = null;
182 int thisArgIndex = thisAv.getArgIndex();
185 ArgValues compareAvs = this.getArgValues(a);
186 int closestNextIndex = Integer.MAX_VALUE;
187 for (ArgValue av : compareAvs.getArgValueList())
189 int argIndex = av.getArgIndex();
190 if (argIndex > thisArgIndex && argIndex < closestNextIndex)
192 closestNextIndex = argIndex;
197 // check if withinType this closestAv doesn't belong to the next primary arg
199 if (withinType && closestAv != null)
201 int nextPrimaryArgOfSameTypeIndex = Integer.MAX_VALUE;
202 for (Arg tmpA : this.getArgKeys())
204 // interested in Opt.PRIMARY args of the same type
205 if (tmpA.getType() == a.getType() && tmpA.hasOption(Opt.PRIMARY))
207 for (ArgValue tmpAv : getArgValueList(tmpA))
209 int tmpArgIndex = tmpAv.getArgIndex();
210 if (tmpArgIndex > thisArgIndex
211 && tmpArgIndex < nextPrimaryArgOfSameTypeIndex)
213 nextPrimaryArgOfSameTypeIndex = tmpArgIndex;
218 if (nextPrimaryArgOfSameTypeIndex < closestAv.getArgIndex())
220 // looks licke closestAv actually belongs to a different primary Arg
228 // TODO this is incomplete and currently unused (fortunately)
229 public ArgValue[] getArgValuesReferringTo(String key, String value, Arg a)
231 // this looks for the *next* arg that *might* be referring back to
232 // a thisAv. Such an arg would have no subValues (if it does it should
233 // specify an id in the subValues so wouldn't need to be guessed).
234 List<ArgValue> avList = new ArrayList<>();
235 Arg[] args = a == null ? (Arg[]) this.getMap().keySet().toArray()
238 for (Arg keyArg : args)
240 for (ArgValue av : this.getArgValueList(keyArg))
245 return (ArgValue[]) avList.toArray();
248 public boolean hasId(Arg a, String id)
250 ArgValues avs = this.getArgValues(a);
251 return avs == null ? false : avs.hasId(id);
254 public ArgValue getId(Arg a, String id)
256 ArgValues avs = this.getArgValues(a);
257 return avs == null ? null : avs.getId(id);
261 * This method returns the basename of the first --append or --open value.
262 * Used primarily for substitutions in output filenames.
264 public String getBasename()
266 return getDirBasenameOrExtension(false, false, false);
270 * This method returns the basename of the first --append or --open value.
271 * Used primarily for substitutions in output filenames.
273 public String getExtension()
275 return getDirBasenameOrExtension(false, true, false);
279 * This method returns the dirname of the first --append or --open value.
280 * Used primarily for substitutions in output filenames.
282 public String getDirname()
284 return getDirBasenameOrExtension(true, false, false);
287 public String getDirBasenameOrExtension(boolean dirname,
288 boolean extension, boolean absoluteDirname)
290 String filename = null;
291 String appendVal = getValue(Arg.APPEND);
292 String openVal = getValue(Arg.OPEN);
293 if (appendVal != null)
294 filename = appendVal;
295 if (filename == null && openVal != null)
297 if (filename == null)
300 File file = new File(filename);
303 return FileUtils.getDirname(file);
305 return extension ? FileUtils.getExtension(file)
306 : FileUtils.getBasename(file);
310 * Checks if there is an Arg with Opt
312 public boolean hasArgWithOption(Opt o)
314 for (Arg a : getArgKeys())
323 * ArgInfo is a more straightforward list of arguments and their info
326 public void addArgInfo(Arg arg, String value, SubVals subVals,
329 argInfoList.add(new ArgInfo(arg, value, subVals, argIndex));
332 public List<ArgInfo> getArgInfoList()
334 Collections.sort(argInfoList);
339 * get from following Arg of type a or subval of same name (lowercase)
341 public String getValueFromSubValOrArg(ArgValue av, Arg a, SubVals sv)
343 return getFromSubValArgOrPref(av, a, sv, null, null, null);
347 * get from following Arg of type a or subval key or preference pref or
350 public String getFromSubValArgOrPref(ArgValue av, Arg a, SubVals sv,
351 String key, String pref, String def)
353 return getFromSubValArgOrPref(a, ArgValuesMap.Position.AFTER, av, sv,
358 * get from following(AFTER), first occurence of (FIRST) or previous (BEFORE)
359 * Arg of type a or subval key or preference pref or default def
361 public String getFromSubValArgOrPref(Arg a, ArgValuesMap.Position pos,
362 ArgValue av, SubVals sv, String key, String pref, String def)
364 return getFromSubValArgOrPrefWithSubstitutions(null, a, pos, av, sv,
368 public String getFromSubValArgOrPrefWithSubstitutions(ArgParser ap, Arg a,
369 ArgValuesMap.Position pos, ArgValue av, SubVals sv, String key,
370 String pref, String def)
372 return getFromSubValArgOrPrefWithSubstitutionsWithinType(ap, a, pos, av,
373 sv, key, pref, def, true);
376 public String getFromSubValArgOrPrefWithSubstitutionsWithinType(
377 ArgParser ap, Arg a, ArgValuesMap.Position pos, ArgValue av,
378 SubVals sv, String key, String pref, String def,
384 if (sv != null && sv.has(key) && sv.get(key) != null)
386 value = ap == null ? sv.get(key)
387 : sv.getWithSubstitutions(ap, getLinkedId(), key);
389 else if (containsArg(a))
391 if (pos == ArgValuesMap.Position.FIRST && getValue(a) != null)
393 else if (pos == ArgValuesMap.Position.BEFORE
394 && getClosestPreviousArgValueOfArg(av, a) != null)
395 value = getClosestPreviousArgValueOfArg(av, a).getValue();
396 else if (pos == ArgValuesMap.Position.AFTER
397 && getClosestNextArgValueOfArg(av, a, withinType) != null)
398 value = getClosestNextArgValueOfArg(av, a, withinType).getValue();
400 // look for allstructures subval for Type.STRUCTURE
401 Arg arg = av.getArg();
402 if (value == null && arg.hasOption(Opt.PRIMARY)
403 && arg.getType() == Type.STRUCTURE
404 && !a.hasOption(Opt.PRIMARY) && (a.getType() == Type.STRUCTURE
405 // || a.getType() == Type.STRUCTUREIMAGE))
408 ArgValue av2 = getArgValueOfArgWithSubValKey(a,
409 Arg.ALLSTRUCTURES.getName());
412 value = av2.getValue();
418 value = pref != null ? Cache.getDefault(pref, def) : def;
423 public boolean getBoolFromSubValOrArg(Arg a, SubVals sv)
425 return getFromSubValArgOrPref(a, sv, null, null, false);
428 public boolean getFromSubValArgOrPref(Arg a, SubVals sv, String key,
429 String pref, boolean def)
431 return getFromSubValArgOrPref(a, sv, key, pref, def, false);
434 public boolean getFromSubValArgOrPref(Arg a, SubVals sv, String key,
435 String pref, boolean def, boolean invertPref)
437 if ((key == null && a == null) || (sv == null && a == null))
440 boolean usingArgKey = false;
447 String nokey = ArgParser.NEGATESTRING + key;
449 // look for key or nokey in subvals first (if using Arg check options)
452 // check for true boolean
453 if (sv.has(key) && sv.get(key) != null)
457 if (!(a.hasOption(Opt.BOOLEAN) || a.hasOption(Opt.UNARY)))
460 "Looking for boolean in subval from non-boolean/non-unary Arg "
465 return sv.get(key).toLowerCase(Locale.ROOT).equals("true");
468 // check for negative boolean (subval "no..." will be "true")
469 if (sv.has(nokey) && sv.get(nokey) != null)
473 if (!(a.hasOption(Opt.BOOLEAN)))
476 "Looking for negative boolean in subval from non-boolean Arg "
481 return !sv.get(nokey).toLowerCase(Locale.ROOT).equals("true");
487 return getBoolean(a);
489 // return preference or default
490 boolean prefVal = pref != null ? Cache.getDefault(pref, def) : false;
491 return pref != null ? (invertPref ? !prefVal : prefVal) : def;
494 public class ArgInfo implements Comparable<ArgInfo>
498 private String value;
500 private SubVals subVals;
502 private int argIndex;
504 public ArgInfo(Arg arg, String value, SubVals subVals, int argIndex)
508 this.subVals = subVals;
509 this.argIndex = argIndex;
517 public String value()
522 public SubVals subVals()
527 public int argIndex()
533 public int compareTo(ArgInfo ai2)
535 return Integer.compare(this.argIndex(), ai2.argIndex());
539 public static enum Position