import jalview.bin.Console;
import jalview.bin.Jalview;
import jalview.bin.argparser.Arg.Opt;
+import jalview.bin.argparser.Arg.Type;
import jalview.util.FileUtils;
import jalview.util.HttpUtils;
public class ArgParser
{
+ protected static final String SINGLEDASH = "-";
+
protected static final String DOUBLEDASH = "--";
- protected static final char EQUALS = '=';
+ public static final char EQUALS = '=';
protected static final String NEGATESTRING = "no";
// --argfile name
private static final String ARGFILEDIRNAME = "{argfiledirname}";
- // an output file wildcard to signify --output=*.ext is really --all --output
- // {basename}.ext
- private static final String OUTPUTWILDCARD = "*.";
-
// flag to say whether {n} subtitutions in output filenames should be made.
// Turn on and off with --substitutions and --nosubstitutions
// Start with it on
// or OPENED linkedIds
private boolean openedLinkedIds = false;
+ // flag to say whether the structure arguments should be applied to all
+ // structures with this linked id
+ private boolean allStructures = false;
+
protected static final Map<String, Arg> argMap;
protected Map<String, ArgValuesMap> linkedArgs = new HashMap<>();
if (argMap.containsKey(argName))
{
Console.warn("Trying to add argument name multiple times: '"
- + argName + "'"); // RESTORE THIS WHEN
- // MERGED
+ + argName + "'");
if (argMap.get(argName) != a)
{
Console.error(
openEachInitialFilenames = false;
}
- String argName = null;
- String val = null;
- List<String> globVals = null; // for Opt.GLOB only
- SubVals globSubVals = null; // also for use by Opt.GLOB only
- String linkedId = null;
+ // look for double-dash, e.g. --arg
if (arg.startsWith(DOUBLEDASH))
{
+ String argName = null;
+ String val = null;
+ List<String> globVals = null; // for Opt.GLOB only
+ SubVals globSubVals = null; // also for use by Opt.GLOB only
+ String linkedId = null;
+ Type type = null;
+
+ // look for equals e.g. --arg=value
int equalPos = arg.indexOf(EQUALS);
if (equalPos > -1)
{
{
argName = arg.substring(DOUBLEDASH.length());
}
+
+ // look for linked ID e.g. --arg[linkedID]
int idOpen = argName.indexOf('[');
int idClose = argName.indexOf(']');
-
if (idOpen > -1 && idClose == argName.length() - 1)
{
linkedId = argName.substring(idOpen + 1, idClose);
argName = argName.substring(0, idOpen);
}
+ // look for type modification e.g. --help-opening
+ int dashPos = argName.indexOf(SINGLEDASH);
+ if (dashPos > -1)
+ {
+ String potentialArgName = argName.substring(0, dashPos);
+ Arg potentialArg = argMap.get(potentialArgName);
+ if (potentialArg != null && potentialArg.hasOption(Opt.HASTYPE))
+ {
+ String typeName = argName.substring(dashPos + 1);
+ try
+ {
+ type = Type.valueOf(typeName);
+ } catch (IllegalArgumentException e)
+ {
+ type = Type.INVALID;
+ }
+ argName = argName.substring(0, dashPos);
+ }
+ }
+
Arg a = argMap.get(argName);
- // check for boolean prepended by "no"
+ // check for boolean prepended by "no" e.g. --nowrap
boolean negated = false;
- if (a == null && argName.startsWith(NEGATESTRING) && argMap
- .containsKey(argName.substring(NEGATESTRING.length())))
+ if (a == null)
{
- argName = argName.substring(NEGATESTRING.length());
- a = argMap.get(argName);
- negated = true;
+ if (argName.startsWith(NEGATESTRING) && argMap
+ .containsKey(argName.substring(NEGATESTRING.length())))
+ {
+ argName = argName.substring(NEGATESTRING.length());
+ a = argMap.get(argName);
+ negated = true;
+ }
+ else
+ {
+ // after all other args, look for Opt.PREFIXKEV args if still not
+ // found
+ for (Arg potentialArg : EnumSet.allOf(Arg.class))
+ {
+ if (potentialArg.hasOption(Opt.PREFIXKEV) && argName != null
+ && argName.startsWith(potentialArg.getName())
+ && equalPos > -1)
+ {
+ val = argName.substring(potentialArg.getName().length())
+ + EQUALS + val;
+ argName = argName.substring(0,
+ potentialArg.getName().length());
+ a = potentialArg;
+ break;
+ }
+ }
+ }
}
// check for config errors
openedLinkedIds = !negated;
allLinkedIds = false;
}
+ else if (a == Arg.ALLSTRUCTURES)
+ {
+ allStructures = !negated;
+ }
if (a.hasOption(Opt.STORED))
{
}
String autoCounterString = null;
- boolean usingAutoCounterLinkedId = false;
String defaultLinkedId = defaultLinkedId(false);
boolean usingDefaultLinkedId = false;
if (a.hasOption(Opt.LINKED))
{
if (linkedId == null)
{
- if (a.hasOption(Opt.OUTPUT) && a.hasOption(Opt.ALLOWALL)
+ if (a.hasOption(Opt.OUTPUTFILE) && a.hasOption(Opt.ALLOWALL)
&& val.startsWith(MATCHALLLINKEDIDS))
{
// --output=*.ext is shorthand for --all --output {basename}.ext
val = LINKEDIDDIRNAME + File.separator + LINKEDIDBASENAME
+ val.substring(MATCHALLLINKEDIDS.length());
}
- else if (a.hasOption(Opt.OUTPUT) && a.hasOption(Opt.ALLOWALL)
+ else if (a.hasOption(Opt.OUTPUTFILE)
+ && a.hasOption(Opt.ALLOWALL)
&& val.startsWith(MATCHOPENEDLINKEDIDS))
{
// --output=open*.ext is shorthand for --opened --output
+ arg);
}
}
- else if (linkedId.contains(LINKEDIDAUTOCOUNTER))
- {
- // turn {n} to the autoCounter
- autoCounterString = Integer.toString(linkedIdAutoCounter);
- linkedId = linkedId.replace(LINKEDIDAUTOCOUNTER,
- autoCounterString);
- usingAutoCounterLinkedId = true;
- Console.debug(
- "Changing linkedId to '" + linkedId + "' from " + arg);
- }
- else if (linkedId.contains(INCREMENTLINKEDIDAUTOCOUNTER))
+ else
{
- // turn {++n} to the incremented autoCounter
- autoCounterString = Integer.toString(++linkedIdAutoCounter);
- linkedId = linkedId.replace(INCREMENTLINKEDIDAUTOCOUNTER,
- autoCounterString);
- usingAutoCounterLinkedId = true;
- Console.debug(
- "Changing linkedId to '" + linkedId + "' from " + arg);
+ if (linkedId.contains(LINKEDIDAUTOCOUNTER))
+ {
+ // turn {n} to the autoCounter
+ autoCounterString = Integer.toString(linkedIdAutoCounter);
+ linkedId = linkedId.replace(LINKEDIDAUTOCOUNTER,
+ autoCounterString);
+ Console.debug("Changing linkedId to '" + linkedId + "' from "
+ + arg);
+ }
+ if (linkedId.contains(INCREMENTLINKEDIDAUTOCOUNTER))
+ {
+ // turn {++n} to the incremented autoCounter
+ autoCounterString = Integer.toString(++linkedIdAutoCounter);
+ linkedId = linkedId.replace(INCREMENTLINKEDIDAUTOCOUNTER,
+ autoCounterString);
+ Console.debug("Changing linkedId to '" + linkedId + "' from "
+ + arg);
+ }
}
}
}
// check for unique id
- SubVals idsv = new SubVals(val);
- String id = idsv.get(ArgValues.ID);
+ SubVals subvals = new SubVals(val);
+ boolean addNewSubVals = false;
+ String id = subvals.get(ArgValues.ID);
if (id != null && avm.hasId(a, id))
{
Console.error("Argument '" + a.argString()
continue;
}
- /* TODO
- * Change all avs.addValue() avs.setBoolean avs.setNegated() avs.incrementCount calls to checkfor linkedId == "*"
- * DONE, need to check
- */
+ // set allstructures to all non-primary structure options in this linked
+ // id if --allstructures has been set
+ if (allStructures
+ && (a.getType() == Type.STRUCTURE
+ || a.getType() == Type.STRUCTUREIMAGE)
+ && !a.hasOption(Opt.PRIMARY))
+ {
+ if (!subvals.has(Arg.ALLSTRUCTURES.getName()))
+ // && !subvals.has("structureid"))
+ {
+ subvals.put(Arg.ALLSTRUCTURES.getName(), "true");
+ addNewSubVals = true;
+ }
+ }
+
ArgValues avs = avm.getOrCreateArgValues(a);
// store appropriate String value(s)
{
String v = gve.nextElement();
SubVals vsv = new SubVals(globSubVals, v);
- addValue(linkedId, avs, vsv, v, argIndex++, true);
+ addValue(linkedId, type, avs, vsv, v, argIndex++, true);
// if we're using defaultLinkedId and the arg increments the
// counter:
if (gve.hasMoreElements() && usingDefaultLinkedId
}
else
{
- addValue(linkedId, avs, val, argIndex, true);
+ // addValue(linkedId, type, avs, val, argIndex, true);
+ addValue(linkedId, type, avs, addNewSubVals ? subvals : null,
+ val, argIndex, true);
}
}
else if (a.hasOption(Opt.BOOLEAN))
{
- setBoolean(linkedId, avs, !negated, argIndex);
+ setBoolean(linkedId, type, avs, !negated, argIndex);
setNegated(linkedId, avs, negated);
}
else if (a.hasOption(Opt.UNARY))
{
- setBoolean(linkedId, avs, true, argIndex);
+ setBoolean(linkedId, type, avs, true, argIndex);
}
// remove the '*' or 'open*' linkedId that should be empty if it was
else if (pos == Position.AFTER
&& avm.getClosestNextArgValueOfArg(av, a) != null)
value = avm.getClosestNextArgValueOfArg(av, a).getValue();
+
+ // look for allstructures subval for Type.STRUCTURE*
+ Arg arg = av.getArg();
+ if (value == null && arg.hasOption(Opt.PRIMARY)
+ && arg.getType() == Type.STRUCTURE
+ && !a.hasOption(Opt.PRIMARY) && (a.getType() == Type.STRUCTURE
+ || a.getType() == Type.STRUCTUREIMAGE))
+ {
+ ArgValue av2 = avm.getArgValueOfArgWithSubValKey(a,
+ Arg.ALLSTRUCTURES.getName());
+ if (av2 != null)
+ {
+ value = av2.getValue();
+ }
+ }
}
- else
+ if (value == null)
{
value = pref != null ? Cache.getDefault(pref, def) : def;
}
public static boolean getFromSubValArgOrPref(ArgValuesMap avm, Arg a,
SubVals sv, String key, String pref, boolean def)
{
+ return getFromSubValArgOrPref(avm, a, sv, key, pref, def, false);
+ }
+
+ public static boolean getFromSubValArgOrPref(ArgValuesMap avm, Arg a,
+ SubVals sv, String key, String pref, boolean def,
+ boolean invertPref)
+ {
if ((key == null && a == null) || (sv == null && a == null))
return false;
return avm.getBoolean(a);
// return preference or default
- return pref != null ? Cache.getDefault(pref, def) : def;
+ boolean prefVal = pref != null ? Cache.getDefault(pref, def) : false;
+ return pref != null ? (invertPref ? !prefVal : prefVal) : def;
}
// the following methods look for the "*" linkedId and add the argvalue to all
// linkedId ArgValues if it does.
// This version inserts the subvals sv into all created values
- private void addValue(String linkedId, ArgValues avs, SubVals sv,
- String v, int argIndex, boolean doSubs)
+ private void addValue(String linkedId, Type type, ArgValues avs,
+ SubVals sv, String v, int argIndex, boolean doSubs)
{
- this.argValueOperation(Op.ADDVALUE, linkedId, avs, sv, v, false,
+ this.argValueOperation(Op.ADDVALUE, linkedId, type, avs, sv, v, false,
argIndex, doSubs);
}
- private void addValue(String linkedId, ArgValues avs, String v,
+ private void addValue(String linkedId, Type type, ArgValues avs, String v,
int argIndex, boolean doSubs)
{
- this.argValueOperation(Op.ADDVALUE, linkedId, avs, null, v, false,
+ this.argValueOperation(Op.ADDVALUE, linkedId, type, avs, null, v, false,
argIndex, doSubs);
}
- private void setBoolean(String linkedId, ArgValues avs, boolean b,
- int argIndex)
+ private void setBoolean(String linkedId, Type type, ArgValues avs,
+ boolean b, int argIndex)
{
- this.argValueOperation(Op.SETBOOLEAN, linkedId, avs, null, null, b,
- argIndex, false);
+ this.argValueOperation(Op.SETBOOLEAN, linkedId, type, avs, null, null,
+ b, argIndex, false);
}
private void setNegated(String linkedId, ArgValues avs, boolean b)
{
- this.argValueOperation(Op.SETNEGATED, linkedId, avs, null, null, b, 0,
- false);
+ this.argValueOperation(Op.SETNEGATED, linkedId, null, avs, null, null,
+ b, 0, false);
}
private void incrementCount(String linkedId, ArgValues avs)
{
- this.argValueOperation(Op.INCREMENTCOUNT, linkedId, avs, null, null,
- false, 0, false);
+ this.argValueOperation(Op.INCREMENTCOUNT, linkedId, null, avs, null,
+ null, false, 0, false);
}
private enum Op
ADDVALUE, SETBOOLEAN, SETNEGATED, INCREMENTCOUNT
}
- // The following operations look for the "*" and "open*" linkedIds and add the
- // argvalue to all appropriate linkedId ArgValues if it does.
- // If subvals are supplied, they are inserted into all new set values.
- private void argValueOperation(Op op, String linkedId, ArgValues avs,
- SubVals sv, String v, boolean b, int argIndex, boolean doSubs)
+ private void argValueOperation(Op op, String linkedId, Type type,
+ ArgValues avs, SubVals sv, String v, boolean b, int argIndex,
+ boolean doSubs)
+ {
+ // default to merge subvals if subvals are provided
+ argValueOperation(op, linkedId, type, avs, sv, true, v, b, argIndex,
+ doSubs);
+ }
+
+ /*
+ * The following operations look for the "*" and "open*" linkedIds and add the
+ * argvalue to all appropriate linkedId ArgValues if it does.
+ * If subvals are supplied, they are inserted into all new set values.
+ *
+ * @param op The ArgParser.Op operation
+ * @param linkedId The String linkedId from the ArgValuesMap
+ * @param type The Arg.Type to attach to this ArgValue
+ * @param avs The ArgValues for this linkedId
+ * @param sv Use these SubVals on the ArgValue
+ * @param merge Merge the SubVals with any existing on the value. False will replace unless sv is null
+ * @param v The value of the ArgValue (may contain subvals).
+ * @param b The boolean value of the ArgValue.
+ * @param argIndex The argIndex for the ArgValue.
+ * @param doSubs Whether to perform substitutions on the subvals and value.
+ */
+ private void argValueOperation(Op op, String linkedId, Type type,
+ ArgValues avs, SubVals sv, boolean merge, String v, boolean b,
+ int argIndex, boolean doSubs)
{
Arg a = avs.arg();
{
if (doSubs)
{
- val = makeSubstitutions(v, id);
- sv = new SubVals(sv, val);
+ sv = new SubVals(sv, val, merge);
+ val = makeSubstitutions(sv.getContent(), id);
}
- tavs.addValue(sv, val, argIndex, true);
+ tavs.addValue(sv, type, val, argIndex, true);
}
else
{
{
val = makeSubstitutions(v, id);
}
- tavs.addValue(val, argIndex, true);
+ tavs.addValue(type, val, argIndex, true);
}
finaliseStoringArgValue(id, tavs);
break;
case SETBOOLEAN:
- tavs.setBoolean(b, argIndex, true);
+ tavs.setBoolean(type, b, argIndex, true);
finaliseStoringArgValue(id, tavs);
break;
val = makeSubstitutions(v, linkedId);
sv = new SubVals(sv, val);
}
- avs.addValue(sv, val, argIndex, false);
+ avs.addValue(sv, type, val, argIndex, false);
}
else
{
{
val = makeSubstitutions(v, linkedId);
}
- avs.addValue(val, argIndex, false);
+ avs.addValue(type, val, argIndex, false);
}
finaliseStoringArgValue(linkedId, avs);
break;
case SETBOOLEAN:
- avs.setBoolean(b, argIndex, false);
+ avs.setBoolean(type, b, argIndex, false);
finaliseStoringArgValue(linkedId, avs);
break;