X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Fbin%2Fargparser%2FArgValuesMap.java;h=8a28b8780927d0cfc10fd764a44a15bf58e9f3ac;hb=ccc53e88e3260886f5d3bdacc619c0f374be9b8f;hp=cbc6faaa5525a0d594fb374db5889f43a5bbbc1a;hpb=a7474618cc5b839b6b33803f7e992d26b668244d;p=jalview.git diff --git a/src/jalview/bin/argparser/ArgValuesMap.java b/src/jalview/bin/argparser/ArgValuesMap.java index cbc6faa..8a28b87 100644 --- a/src/jalview/bin/argparser/ArgValuesMap.java +++ b/src/jalview/bin/argparser/ArgValuesMap.java @@ -1,13 +1,40 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ package jalview.bin.argparser; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; 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 jalview.bin.Cache; +import jalview.bin.Console; import jalview.bin.argparser.Arg.Opt; +import jalview.bin.argparser.Arg.Type; import jalview.util.FileUtils; /** @@ -16,18 +43,29 @@ import jalview.util.FileUtils; */ public class ArgValuesMap { + private List argInfoList = new ArrayList<>(); + protected Map m; - protected ArgValuesMap() + private String linkedId; + + protected ArgValuesMap(String linkedId) { + this.linkedId = linkedId; this.newMap(); } - protected ArgValuesMap(Map map) + protected ArgValuesMap(String linkedId, Map map) { + this.linkedId = linkedId; this.m = map; } + public String getLinkedId() + { + return linkedId; + } + private Map getMap() { return m; @@ -41,20 +79,13 @@ public class ArgValuesMap private void newArg(Arg a) { if (m == null) + { newMap(); + } if (!containsArg(a)) - m.put(a, new ArgValues(a)); - } - - protected void addArgValue(Arg a, ArgValue av) - { - if (getMap() == null) - m = new HashMap(); - - if (!m.containsKey(a)) - m.put(a, new ArgValues(a)); - ArgValues avs = m.get(a); - avs.addArgValue(av); + { + m.put(a, new ArgValues(a, this)); + } } public ArgValues getArgValues(Arg a) @@ -76,6 +107,112 @@ public class ArgValuesMap return avs == null ? new ArrayList<>() : avs.getArgValueList(); } + public List getArgValueListFromSubValOrArg(ArgValue av, Arg a, + SubVals sv) + { + return getArgValueListFromSubValArgOrPrefWithSubstitutionsWithinTypes( + null, a, Position.AFTER, av, sv, null, null, null, true, null); + } + + public List getArgValueListFromSubValArgOrPrefWithSubstitutionsWithinTypes( + ArgParser ap, Arg a, ArgValuesMap.Position pos, ArgValue av, + SubVals sv, String key, String pref, String def, + boolean withinTypes, Type type) + { + if (key == null) + { + key = a.getName(); + } + Set types = new HashSet<>(); + if (type == null) + { + types.addAll(Arrays.asList(av.getArg().getTypes())); + } + else + { + types.add(type); + } + List avList = new ArrayList<>(); + if (sv != null && sv.has(key) && sv.get(key) != null) + { + String value = ap == null ? sv.get(key) + : sv.getWithSubstitutions(ap, getLinkedId(), key); + // protected ArgValue(Arg a, SubVals sv, Type type, String content, int + // argIndex) + + ArgValue svav = new ArgValue(a, null, null, value, av.getArgIndex(), + false, null, this.getLinkedId()); + avList.add(svav); + } + else if (containsArg(a)) + { + if (pos == ArgValuesMap.Position.FIRST && getValue(a) != null) + avList.add(getArgValue(a)); + else if (pos == ArgValuesMap.Position.BEFORE + && getClosestPreviousArgValueOfArg(av, a) != null) + { + for (ArgValue tmpAv : getArgValues(a).getArgValueList()) + { + if (tmpAv.getArgIndex() >= av.getArgIndex()) + { + continue; + } + avList.add(tmpAv); + } + } + else if (pos == ArgValuesMap.Position.AFTER + && getClosestNextArgValueOfArg(av, a, withinTypes) != null) + { + for (ArgValue tmpAv : getArgValues(a).getArgValueList()) + { + if (tmpAv.getArgIndex() <= av.getArgIndex()) + { + continue; + } + avList.add(tmpAv); + } + } + } + + // check if withinType the avs don't belong to the next primary arg + // of this type. Checking for *any* shared type. + if (withinTypes && !avList.isEmpty()) + { + int nextPrimaryArgOfSameTypeIndex = Integer.MAX_VALUE; + // run through every Arg used in this ArgValuesMap + for (Arg tmpA : this.getArgKeys()) + { + // only interested in looking up to next Opt.PRIMARY args of the same + // type as av (or provided type) + if (tmpA.hasType(types) && tmpA.hasOption(Opt.PRIMARY)) + { + for (ArgValue tmpAv : getArgValueList(tmpA)) + { + int tmpArgIndex = tmpAv.getArgIndex(); + if (tmpArgIndex > av.getArgIndex() + && tmpArgIndex < nextPrimaryArgOfSameTypeIndex) + { + nextPrimaryArgOfSameTypeIndex = tmpArgIndex; + } + } + } + } + List tmpList = new ArrayList<>(); + for (ArgValue tmpAv : avList) + { + int tmpAvIndex = tmpAv.getArgIndex(); + if (av.getArgIndex() < tmpAvIndex + && tmpAvIndex < nextPrimaryArgOfSameTypeIndex) + { + tmpList.add(tmpAv); + } + } + avList = tmpList; + } + + return avList; + } + public ArgValue getArgValue(Arg a) { List vals = getArgValueList(a); @@ -122,6 +259,33 @@ public class ArgValuesMap return m.keySet(); } + public ArgValue getArgValueOfArgWithSubValKey(Arg a, String svKey) + { + return getArgValueOfArgWithSubValKey(a, svKey, false); + } + + public ArgValue getArgValueOfArgWithSubValKey(Arg a, String svKey, + boolean last) + { + ArgValues avs = this.getArgValues(a); + if (avs == null) + { + return null; + } + List compareAvs = avs.getArgValueList(); + for (int i = 0; i < compareAvs.size(); i++) + { + int index = last ? compareAvs.size() - 1 - i : i; + ArgValue av = compareAvs.get(index); + SubVals sv = av.getSubVals(); + if (sv.has(svKey) && !sv.get(svKey).equals("false")) + { + return av; + } + } + return null; + } + public ArgValue getClosestPreviousArgValueOfArg(ArgValue thisAv, Arg a) { ArgValue closestAv = null; @@ -140,13 +304,16 @@ public class ArgValuesMap return closestAv; } - public ArgValue getClosestNextArgValueOfArg(ArgValue thisAv, Arg a) + public ArgValue getClosestNextArgValueOfArg(ArgValue thisAv, Arg a, + boolean withinTypes) { // this looks for the *next* arg that *might* be referring back to // a thisAv. Such an arg would have no subValues (if it does it should // specify an id in the subValues so wouldn't need to be guessed). ArgValue closestAv = null; int thisArgIndex = thisAv.getArgIndex(); + if (!containsArg(a)) + return null; ArgValues compareAvs = this.getArgValues(a); int closestNextIndex = Integer.MAX_VALUE; for (ArgValue av : compareAvs.getArgValueList()) @@ -158,9 +325,39 @@ public class ArgValuesMap closestAv = av; } } + + // check if withinType this closestAv doesn't belong to the next primary arg + // of this type. Checking for *any* shared type. + if (withinTypes && closestAv != null) + { + int nextPrimaryArgOfSameTypeIndex = Integer.MAX_VALUE; + for (Arg tmpA : this.getArgKeys()) + { + // interested in Opt.PRIMARY args of the same type + if (tmpA.sharesType(a) && tmpA.hasOption(Opt.PRIMARY)) + { + for (ArgValue tmpAv : getArgValueList(tmpA)) + { + int tmpArgIndex = tmpAv.getArgIndex(); + if (tmpArgIndex > thisArgIndex + && tmpArgIndex < nextPrimaryArgOfSameTypeIndex) + { + nextPrimaryArgOfSameTypeIndex = tmpArgIndex; + } + } + } + } + if (nextPrimaryArgOfSameTypeIndex < closestAv.getArgIndex()) + { + // looks like closestAv actually belongs to a different primary Arg + return null; + } + } + return closestAv; } + // TODO this is incomplete and currently unused (fortunately) public ArgValue[] getArgValuesReferringTo(String key, String value, Arg a) { // this looks for the *next* arg that *might* be referring back to @@ -198,7 +395,16 @@ public class ArgValuesMap */ public String getBasename() { - return getDirOrBasename(false); + return getDirBasenameOrExtension(false, false, false); + } + + /* + * This method returns the basename of the first --append or --open value. + * Used primarily for substitutions in output filenames. + */ + public String getExtension() + { + return getDirBasenameOrExtension(false, true, false); } /* @@ -207,10 +413,11 @@ public class ArgValuesMap */ public String getDirname() { - return getDirOrBasename(true); + return getDirBasenameOrExtension(true, false, false); } - public String getDirOrBasename(boolean dirname) + public String getDirBasenameOrExtension(boolean dirname, + boolean extension, boolean absoluteDirname) { String filename = null; String appendVal = getValue(Arg.APPEND); @@ -223,7 +430,11 @@ public class ArgValuesMap return null; File file = new File(filename); - return dirname ? FileUtils.getDirname(file) + if (dirname) + { + return FileUtils.getDirname(file); + } + return extension ? FileUtils.getExtension(file) : FileUtils.getBasename(file); } @@ -239,4 +450,237 @@ public class ArgValuesMap } return false; } + + /* + * ArgInfo is a more straightforward list of arguments and their info + */ + + public void addArgInfo(Arg arg, String value, SubVals subVals, + int argIndex) + { + argInfoList.add(new ArgInfo(arg, value, subVals, argIndex)); + } + + public List getArgInfoList() + { + Collections.sort(argInfoList); + return argInfoList; + } + + /** + * get from following Arg of type a or subval of same name (lowercase) + */ + public String getValueFromSubValOrArg(ArgValue av, Arg a, SubVals sv) + { + return getFromSubValArgOrPref(av, a, sv, null, null, null); + } + + /** + * get from following Arg of type a or subval key or preference pref or + * default def + */ + public String getFromSubValArgOrPref(ArgValue av, Arg a, SubVals sv, + String key, String pref, String def) + { + return getFromSubValArgOrPref(a, Position.AFTER, av, sv, key, pref, + def); + } + + /** + * get from following(AFTER), first occurence of (FIRST) or previous (BEFORE) + * Arg of type a or subval key or preference pref or default def + */ + public String getFromSubValArgOrPref(Arg a, Position pos, ArgValue av, + SubVals sv, String key, String pref, String def) + { + return getFromSubValArgOrPrefWithSubstitutions(null, a, pos, av, sv, + key, pref, def); + } + + public String getFromSubValArgOrPrefWithSubstitutions(ArgParser ap, Arg a, + Position pos, ArgValue av, SubVals sv, String key, String pref, + String def) + { + return getFromSubValArgOrPrefWithSubstitutionsWithinTypes(ap, a, pos, + av, sv, key, pref, def, true); + } + + public String getFromSubValArgOrPrefWithSubstitutionsWithinTypes( + ArgParser ap, Arg a, Position pos, ArgValue av, SubVals sv, + String key, String pref, String def, boolean withinTypes) + { + if (key == null) + key = a.getName(); + String value = null; + if (sv != null && sv.has(key) && sv.get(key) != null) + { + value = ap == null ? sv.get(key) + : sv.getWithSubstitutions(ap, getLinkedId(), key); + } + else if (containsArg(a)) + { + if (pos == ArgValuesMap.Position.FIRST && getValue(a) != null) + value = getValue(a); + else if (pos == ArgValuesMap.Position.BEFORE + && getClosestPreviousArgValueOfArg(av, a) != null) + value = getClosestPreviousArgValueOfArg(av, a).getValue(); + else if (pos == ArgValuesMap.Position.AFTER + && getClosestNextArgValueOfArg(av, a, withinTypes) != null) + value = getClosestNextArgValueOfArg(av, a, withinTypes).getValue(); + + // look for allstructures subval for Type.STRUCTURE + Arg arg = av.getArg(); + if (value == null && arg.hasOption(Opt.PRIMARY) + && arg.hasType(Type.STRUCTURE) && !a.hasOption(Opt.PRIMARY) + && (a.getFirstType() == Type.STRUCTURE + // || a.getType() == Type.STRUCTUREIMAGE)) + )) + { + ArgValue av2 = getArgValueOfArgWithSubValKey(a, + Arg.ALLSTRUCTURES.getName()); + if (av2 != null) + { + value = av2.getValue(); + } + } + + if (value == null) + { + // look for --all --a occurrences + for (ArgValue tmpAv : this.getArgValueList(a)) + { + if (tmpAv.setByWildcardLinkedId()) + { + value = tmpAv.getValue(); + } + } + } + } + if (value == null) + { + value = pref != null ? Cache.getDefault(pref, def) : def; + } + return value; + } + + public boolean getBoolFromSubValOrArg(Arg a, SubVals sv) + { + return getFromSubValArgOrPref(a, sv, null, null, false); + } + + public boolean getFromSubValArgOrPref(Arg a, SubVals sv, String key, + String pref, boolean def) + { + return getFromSubValArgOrPref(a, sv, key, pref, def, false); + } + + public boolean getFromSubValArgOrPref(Arg a, SubVals sv, String key, + String pref, boolean def, boolean invertPref) + { + if ((key == null && a == null) || (sv == null && a == null)) + return false; + + boolean usingArgKey = false; + if (key == null) + { + key = a.getName(); + usingArgKey = true; + } + + String nokey = ArgParser.NEGATESTRING + key; + + // look for key or nokey in subvals first (if using Arg check options) + if (sv != null) + { + // check for true boolean + if (sv.has(key) && sv.get(key) != null) + { + if (usingArgKey) + { + if (!(a.hasOption(Opt.BOOLEAN) || a.hasOption(Opt.UNARY))) + { + Console.debug( + "Looking for boolean in subval from non-boolean/non-unary Arg " + + a.getName()); + return false; + } + } + return sv.get(key).toLowerCase(Locale.ROOT).equals("true"); + } + + // check for negative boolean (subval "no..." will be "true") + if (sv.has(nokey) && sv.get(nokey) != null) + { + if (usingArgKey) + { + if (!(a.hasOption(Opt.BOOLEAN))) + { + Console.debug( + "Looking for negative boolean in subval from non-boolean Arg " + + a.getName()); + return false; + } + } + return !sv.get(nokey).toLowerCase(Locale.ROOT).equals("true"); + } + } + + // check argvalues + if (containsArg(a)) + return getBoolean(a); + + // return preference or default + boolean prefVal = pref != null ? Cache.getDefault(pref, def) : false; + return pref != null ? (invertPref ? !prefVal : prefVal) : def; + } + + public class ArgInfo implements Comparable + { + private Arg arg; + + private String value; + + private SubVals subVals; + + private int argIndex; + + public ArgInfo(Arg arg, String value, SubVals subVals, int argIndex) + { + this.arg = arg; + this.value = value; + this.subVals = subVals; + this.argIndex = argIndex; + } + + public Arg arg() + { + return arg; + } + + public String value() + { + return value; + } + + public SubVals subVals() + { + return subVals; + } + + public int argIndex() + { + return argIndex; + } + + @Override + public int compareTo(ArgInfo ai2) + { + return Integer.compare(this.argIndex(), ai2.argIndex()); + } + } + + public static enum Position + { + FIRST, BEFORE, AFTER + } }