X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fbin%2Fargparser%2FBootstrapArgs.java;h=4b7b180a799d8f83ff90fdd53a7f152b01e45459;hb=65ed1da9a1710a9ce132c7edfce54955dc1ddf99;hp=f6b592b810cc354adade98d2c09bad47a9ad3eb3;hpb=988d7abeef3e08d01ff8ebb918325d95caae70b7;p=jalview.git diff --git a/src/jalview/bin/argparser/BootstrapArgs.java b/src/jalview/bin/argparser/BootstrapArgs.java index f6b592b..4b7b180 100644 --- a/src/jalview/bin/argparser/BootstrapArgs.java +++ b/src/jalview/bin/argparser/BootstrapArgs.java @@ -1,18 +1,32 @@ package jalview.bin.argparser; +import java.io.File; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import jalview.bin.argparser.Arg.Opt; +import jalview.bin.argparser.Arg.Type; import jalview.util.FileUtils; public class BootstrapArgs { // only need one - private Map> bootstrapArgMap = new HashMap<>(); + private Map>> bootstrapArgMap = new HashMap<>(); + + private Set argFiles = new HashSet<>(); + + private Set argsOptions = new HashSet<>(); + + private Set argsTypes = new HashSet<>(); public static BootstrapArgs getBootstrapArgs(String[] args) { @@ -20,47 +34,122 @@ public class BootstrapArgs return new BootstrapArgs(argList); } + public static BootstrapArgs getBootstrapArgs(List args) + { + return new BootstrapArgs(args); + } + private BootstrapArgs(List args) { - parse(args); + parse(args, null); } - private void parse(List args) + private void parse(List args, File inArgFile) { if (args == null) return; + // avoid looping argFiles + if (inArgFile != null) + { + if (argFiles.contains(inArgFile)) + { + System.err.println( + "Looped argfiles detected: '" + inArgFile.getPath() + "'"); + return; + } + argFiles.add(inArgFile); + } + for (int i = 0; i < args.size(); i++) { String arg = args.get(i); - String argName = null; - String val = null; + // look for double-dash, e.g. --arg if (arg.startsWith(ArgParser.DOUBLEDASH)) { + String argName = null; + String val = null; + Type type = null; // remove "--" - arg = arg.substring(ArgParser.DOUBLEDASH.length()); - int equalPos = arg.indexOf('='); - if (equalPos > -1 - && ArgParser.argMap.containsKey(arg.substring(0, equalPos))) + argName = arg.substring(ArgParser.DOUBLEDASH.length()); + + // look for equals e.g. --arg=value + int equalPos = argName.indexOf(ArgParser.EQUALS); + if (equalPos > -1) { - argName = arg.substring(0, equalPos); - val = arg.substring(equalPos + 1); + val = argName.substring(equalPos + 1); + argName = argName.substring(0, equalPos); } + // check for boolean prepended by "no" - else if (arg.startsWith(ArgParser.NEGATESTRING) + if (argName.startsWith(ArgParser.NEGATESTRING) && ArgParser.argMap.containsKey( - arg.substring(ArgParser.NEGATESTRING.length()))) + argName.substring(ArgParser.NEGATESTRING.length()))) { - argName = arg.substring(ArgParser.NEGATESTRING.length()); val = "false"; + argName = argName.substring(ArgParser.NEGATESTRING.length()); + } + + // look for type modification e.g. --help-opening + int dashPos = argName.indexOf(ArgParser.SINGLEDASH); + if (dashPos > -1) + { + String potentialArgName = argName.substring(0, dashPos); + Arg potentialArg = ArgParser.argMap.get(potentialArgName); + if (potentialArg != null && potentialArg.hasOption(Opt.HASTYPE)) + { + String typeName = argName.substring(dashPos + 1); + try + { + type = Type.valueOf(typeName.toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException e) + { + type = Type.INVALID; + } + argName = argName.substring(0, dashPos); + } + } + + // after all other args, look for Opt.PREFIX args if still not found + if (!ArgParser.argMap.containsKey(argName)) + { + for (Arg potentialArg : EnumSet.allOf(Arg.class)) + { + if (potentialArg.hasOption(Opt.PREFIXKEV) && argName != null + && argName.startsWith(potentialArg.getName()) + && val != null) + { + val = argName.substring(potentialArg.getName().length()) + + ArgParser.EQUALS + val; + argName = argName.substring(0, + potentialArg.getName().length()); + break; + } + } } - else if (ArgParser.argMap.containsKey(arg)) + + if (ArgParser.argMap.containsKey(argName) && val == null) { - argName = arg; val = "true"; } Arg a = ArgParser.argMap.get(argName); + if (a != null) + { + for (Opt opt : a.getOptions()) + { + if (!argsOptions.contains(opt)) + { + argsOptions.add(opt); + } + } + Type t = a.getType(); + if (!argsTypes.contains(t)) + { + argsTypes.add(t); + } + } + if (a == null || !a.hasOption(Opt.BOOTSTRAP)) { // not a valid bootstrap arg @@ -69,22 +158,37 @@ public class BootstrapArgs if (a.hasOption(Opt.STRING)) { + List vals = null; if (equalPos == -1) { - addAll(a, ArgParser.getShellGlobbedFilenameValues(a, args, - i + 1)); + vals = ArgParser.getShellGlobbedFilenameValues(a, args, i + 1); } else { if (a.hasOption(Opt.GLOB)) - addAll(a, FileUtils.getFilenamesFromGlob(val)); + { + vals = FileUtils.getFilenamesFromGlob(val); + } else - add(a, val); + { + vals = new ArrayList<>(); + vals.add(val); + } + } + addAll(a, type, vals); + + if (a == Arg.ARGFILE) + { + for (String filename : vals) + { + File argFile = new File(filename); + parse(ArgParser.readArgFile(argFile), argFile); + } } } else { - add(a, val); + add(a, type, val); } } } @@ -95,14 +199,55 @@ public class BootstrapArgs return bootstrapArgMap.containsKey(a); } - public List getList(Arg a) + public boolean containsType(Type t) + { + for (List> l : bootstrapArgMap.values()) + { + for (Map.Entry e : l) + { + if (e.getKey() == t) + return true; + } + } + return false; + } + + public List getArgsOfType(Type t) + { + return getArgsOfType(t, new Opt[] {}); + } + + public List getArgsOfType(Type t, Opt... opts) + { + List args = new ArrayList<>(); + for (Arg a : bootstrapArgMap.keySet()) + { + if (!a.hasAllOptions(opts)) + continue; + + List> l = bootstrapArgMap.get(a); + if (l.stream().anyMatch(e -> e.getKey() == t)) + { + args.add(a); + } + } + return args; + } + + public List> getList(Arg a) { return bootstrapArgMap.get(a); } - private List getOrCreateList(Arg a) + public List getValueList(Arg a) { - List l = getList(a); + return bootstrapArgMap.get(a).stream().map(e -> e.getValue()) + .collect(Collectors.toList()); + } + + private List> getOrCreateList(Arg a) + { + List> l = getList(a); if (l == null) { l = new ArrayList<>(); @@ -111,7 +256,7 @@ public class BootstrapArgs return l; } - private void putList(Arg a, List l) + private void putList(Arg a, List> l) { bootstrapArgMap.put(a, l); } @@ -122,41 +267,110 @@ public class BootstrapArgs * and the arg is not MULTI (so first expressed value is * retained). */ - private void add(Arg a, String s) + private void add(Arg a, Type t, String s) { - List l = getOrCreateList(a); + List> l = getOrCreateList(a); if (a.hasOption(Opt.MULTI) || l.size() == 0) { - l.add(s); + l.add(entry(t, s)); } } - private void addAll(Arg a, List al) + private void addAll(Arg a, Type t, List al) { - List l = getOrCreateList(a); + List> l = getOrCreateList(a); if (a.hasOption(Opt.MULTI)) { - l.addAll(al); + for (String s : al) + { + l.add(entry(t, s)); + } } + else if (l.size() == 0 && al.size() > 0) + { + l.add(entry(t, al.get(0))); + } + } + + private static Map.Entry entry(Type t, String s) + { + return new AbstractMap.SimpleEntry(t, s); } /* * Retrieves the first value even if MULTI. * A convenience for non-MULTI args. */ - public String get(Arg a) + public String getValue(Arg a) { if (!bootstrapArgMap.containsKey(a)) return null; - List aL = bootstrapArgMap.get(a); - return (aL == null || aL.size() == 0) ? null : aL.get(0); + List> aL = bootstrapArgMap.get(a); + return (aL == null || aL.size() == 0) ? null : aL.get(0).getValue(); + } + + public boolean getBoolean(Arg a, boolean d) + { + if (!bootstrapArgMap.containsKey(a)) + return d; + return Boolean.parseBoolean(getValue(a)); } public boolean getBoolean(Arg a) { - if (!bootstrapArgMap.containsKey(a) - || !(a.hasOption(Opt.BOOLEAN) || a.hasOption(Opt.UNARY))) + if (!(a.hasOption(Opt.BOOLEAN) || a.hasOption(Opt.UNARY))) + { return false; - return Boolean.parseBoolean(get(a)); + } + if (bootstrapArgMap.containsKey(a)) + { + return Boolean.parseBoolean(getValue(a)); + } + else + { + return a.getDefaultBoolValue(); + } + } + + public boolean argsHaveOption(Opt opt) + { + return argsOptions.contains(opt); + } + + public boolean argsHaveType(Type type) + { + return argsTypes.contains(type); + } + + public boolean isHeadless() + { + boolean isHeadless = false; + if (this.argsHaveType(Type.HELP)) + { + // --help, --help-all, ... specified => headless + isHeadless = true; + } + else if (this.contains(Arg.VERSION)) + { + // --version specified => headless + isHeadless = true; + } + else if (this.contains(Arg.GUI)) + { + // --gui specified => forced NOT headless + isHeadless = !this.getBoolean(Arg.GUI); + } + else if (this.contains(Arg.HEADLESS)) + { + // --headless, --noheadless specified => use value + isHeadless = this.getBoolean(Arg.HEADLESS); + } + else if (this.argsHaveOption(Opt.OUTPUTFILE)) + { + // --output file.fa, --image pic.png, --structureimage struct.png => + // assume headless unless above has been already specified + isHeadless = true; + } + return isHeadless; } }