// second token
private void process(String str) {
        QuotedStringTokenizer tok = new QuotedStringTokenizer(str);
        String cmd = tok.nextToken().trim();
        String retstr = "";
        if (cmd.equals("no-op")) {
            // Does nothing
        }
        // syntax:    vnmrjcmd('SQ start [<macro>]')
        else if (cmd.equals(START)) {
            mgr.setExecuting(true);
            mgr.setPaused(false);
        }
        // syntax:    vnmrjcmd('SQ pause [<macro>]')
        else if (cmd.equals(PAUSE)) {
            mgr.setExecuting(false);
            mgr.setPaused(true);
        }
        // syntax:    vnmrjcmd('SQ stop [<macro>]')
        else if (cmd.equals(STOP)) {
            mgr.setExecuting(false);
            mgr.setPaused(false);
        }
        // syntax:    vnmrjcmd('SQ NormalMode [<macro>]')
        else if (cmd.equalsIgnoreCase(NORMAL_MODE)) {
            mgr.setMode(NORMAL_MODE);
        }
        // syntax:    vnmrjcmd('SQ SubmitMode [<macro>]')
        else if (cmd.equalsIgnoreCase(SUBMIT_MODE)) {
            mgr.setMode(SUBMIT_MODE);
        }
        // syntax:    vnmrjcmd('SQ read filename.xml [<macro>]')
        else if (cmd.equals(READ)) {
            String fn = tok.nextToken().trim();
            if (mgr.isExecuting()) {
                postWarning("cannot load a new study while queue is executing");
                return;
            } else {
                String path = FileUtil.openPath(fn);
                if (path == null) {
                    postError("cannot load study file " + fn);
                    return;
                }
                mgr.newTree(path);
		// set sqdirs[jviewport]=path
		sendSQpath(path);
            }
        }
        // syntax:    vnmrjcmd('SQ write filename.xml [<macro>]')
        else if (cmd.equals(WRITE)) {
            String fn = tok.nextToken().trim();
            String path = FileUtil.savePath(fn);
            if (path == null) {
                postError("could not write study file " + fn);
                return;
            }
            mgr.save(path);
	    // set sqdirs[jviewport]=path
	    sendSQpath(path);
        }
        // syntax:    vnmrjcmd('SQ nwrite filename.xml [<macro>]')
        else if (cmd.equals(NWRITE)) {
            String id;
            String path;
            if (tok.hasMoreTokens())
                id = tok.nextToken().trim();
            else {
                postError("insufficient command arguments SQ " + cmd);
                return;
            }
            if (tok.hasMoreTokens())
                path = FileUtil.savePath(tok.nextToken().trim());
            else {
                postError("insufficient command arguments SQ " + cmd);
                return;
            }
            VElement dst = mgr.getElement(id);
            if (dst == null) {
                if ( ! id.equals("tmpstudy"))
                   postError("invalid node id " + id);
                return;
            }
            mgr.writeElement(dst, path);
        }
        // syntax:    vnmrjcmd('SQ setids')
        else if (cmd.equals(SETIDS)) {
            mgr.setIds();
        }
        // syntax:    vnmrjcmd('SQ nesting = {true,false}")
        else if (cmd.equals(NESTING)) {
            String token;
            if (tok.hasMoreTokens())
                token = tok.nextToken().trim();
            else {
                postError("insufficient command arguments " + "SQ " + cmd);
                return;
            }
            if (!token.equals("=")) {
                postError("syntax error " + "SQ " + str);
                return;
            }
            if (tok.hasMoreTokens())
                token = tok.nextToken().trim();
            else {
                postError("insufficient command arguments " + "SQ " + cmd);
                return;
            }
            if (token.equals("no") || token.equals("false"))
                mgr.setAllowNesting(false);
            else if (token.equals("yes") || token.equals("true"))
                mgr.setAllowNesting(true);
        }
        // syntax:    vnmrjcmd('SQ validate {move,copy,all,none}")
        else if (cmd.equals(VALIDATE)) {
            String token;
            if (tok.hasMoreTokens())
                token = tok.nextToken().trim();
            else {
                postError("insufficient command arguments " + "SQ " + cmd);
                return;
            }
            mgr.setValidateMove(false);
            mgr.setValidateCopy(false);
            if (token.equals("all")) {
                mgr.setValidateMove(true);
                mgr.setValidateCopy(true);
                return;
            } else if (token.equals("move")) {
                mgr.setValidateMove(true);
                return;
            } else if (token.equals("copy")) {
                mgr.setValidateCopy(true);
                return;
            } else if (token.equals("none")) {
                mgr.setValidateMove(false);
                mgr.setValidateCopy(false);
                return;
            } else {
                postError("syntax error " + "SQ " + str);
                return;
            }
        }
        // syntax:    vnmrjcmd('SQ delete <id>")
        else if (cmd.equals(DELETE)) {
            String id;
            if (tok.hasMoreTokens())
                id = tok.nextToken();
            else {
                postError("insufficient command arguments " + "SQ " + cmd);
                return;
            }
            if (getCondition(id) == ProtocolBuilder.ALL) {
                mgr.clearTree();
		// set sqdirs[jviewport]=''
		sendSQpath("");
            } else {
                VElement obj = mgr.getElement(id);
                if (obj == null) {
                    if ( ! id.equals("tmpstudy")) {
                       postError("node " + id + " not found " + "SQ " + cmd);
                    }
                    return;
                }
                mgr.deleteElement(obj);
            }
        }
        else if (cmd.equals(ADD_QUEUE)) {
            String queueDir = tok.nextToken();
            mgr.addQueue(queueDir);
        }
        // syntax: vnmrjcmd('SQ add <file> [<cond>] [<dst>] [<macro>]')
        //         vnmrjcmd('SQ add new <type> [<cond>] [<dst>] [<macro>]')
        else if (cmd.equals(ADD)) {
            String id = tok.nextToken().trim();
            String fn = null;
            String type = "protocol";
            if (id.equals("new")) {
                type = tok.nextToken();
                Messages.postDebug("SQ", "--- SQ ADD: type=" + type);
                if (type.equals("action"))
                    fn = new_action_file;
                else
                    fn = new_protocol_file;
            } else
                fn = id;
            String path = FileUtil.openPath(fn);
            if (path == null) {
                postError("cannot read protocol file " + fn);
                return;
            }
            id = null;
            if (tok.hasMoreTokens()) {
                id = tok.nextToken();
                int cond = getCondition(id);
                if (cond != 0) {
                    mgr.setInsertMode(cond);
                    id = tok.nextToken().trim();
                }
            }
            VElement dst;
            if (id == null)
                dst = mgr.lastElement();
            else
                dst = mgr.getElement(id);
            if (dst == null) {
                if ( ! id.equals("tmpstudy"))
                   postError("invalid node id " + id);
                mgr.setInsertMode(0);
                return;
            }
            mgr.insertProtocol(dst, path);
            mgr.setInsertMode(0);
            new_elem = mgr.getSelected();
        }
        // syntax: vnmrjcmd('SQ move <src> [<cond>] <dst> [true,false] [<macro>]')
        else if (cmd.equals(MOVE)) {
            String id;
            boolean ignorelock = false;
            if (tok.hasMoreTokens())
                id = tok.nextToken().trim();
            else {
//                postError("insufficient command arguments SQ " + cmd);
                return;
            }
            VElement src = mgr.getElement(id);
            if (tok.hasMoreTokens())
                id = tok.nextToken().trim();
            else {
//                postError("insufficient command arguments SQ " + cmd);
                return;
            }
            int cond = getCondition(id);
            if (cond != 0) {
                mgr.setInsertMode(cond);
                if (tok.hasMoreTokens())
                    id = tok.nextToken().trim();
            }
            VElement dst = mgr.getElement(id);
            if (dst == null) {
                if ( ! id.equals("tmpstudy"))
                   postError("invalid node id " + id);
                mgr.setInsertMode(0);
                return;
            }
            if (tok.hasMoreTokens()) {
                String s = tok.nextToken().trim();
                if (s.equals("false"))
                    ignorelock = true;
                else if (s.equals("true"))
                    ignorelock = false;
                else
                    retstr = s;
            }
            mgr.moveElement(src, dst, ignorelock);
            mgr.setInsertMode(0);
        }
        // syntax: vnmrjcmd('SQ {lmove,pmove} <src> [<cond>] <dst> [<macro>]')
        else if (cmd.equals(PMOVE) || cmd.equals(LMOVE)) {
            String id;
            if (tok.hasMoreTokens())
                id = tok.nextToken().trim();
            else {
                postError("insufficient command arguments SQ " + cmd);
                return;
            }
            VElement src = mgr.getElement(id);
            if (tok.hasMoreTokens())
                id = tok.nextToken().trim();
            else {
                postError("insufficient command arguments SQ " + cmd);
                return;
            }
            int cond = getCondition(id);
            if (cond != 0) {
                mgr.setInsertMode(cond);
                id = tok.nextToken().trim();
            }
            VElement dst = mgr.getElement(id);
            if (dst == null) {
                if ( ! id.equals("tmpstudy"))
                   postError("invalid node id " + id);
                mgr.setInsertMode(0);
                return;
            }
            boolean bpmove = false;
            if (cmd.equals(PMOVE))
                bpmove = true;
            boolean ballownesting = mgr.allowNesting();
            if (bpmove && !ballownesting)
                mgr.setAllowNesting(true);
            ArrayList alist = (ArrayList) mgr.getHiddenNodes().clone();
            if (!bpmove)
                mgr.showElementAll("true");
            mgr.moveElement(src, dst, true);
            mgr.setHiddenNodes(alist);
            if (bpmove)
                mgr.setAllowNesting(ballownesting);
            else
                mgr.hideElements();
            mgr.setInsertMode(0);
        }
        // syntax: vnmrjcmd('SQ show <attr> <id> [<macro>]')
        else if (cmd.equals(SHOW)) {
            String value;
            if (tok.hasMoreTokens())
                value = tok.nextToken().trim();
            else {
                postError("insufficient command arguments SQ " + cmd);
                return;
            }
            ArrayList aListElem = new ArrayList();
            while (tok.hasMoreTokens()) {
                String id = tok.nextToken().trim();
                VElement src = mgr.getElement(id);
                if (src == null)
                {
                   if ( ! id.equals("tmpstudy"))
                      postError("invalid node id " + id);
                }
                else
                {
                    aListElem.add(src);
                }
            }
            mgr.showElement(aListElem, value);
        }
        // syntax: vnmrjcmd('SQ copy <id> <cond> <dst> [<macro>]')
        else if (cmd.equals(COPY)) {
            String id_src;
            String id_dst;
            if (tok.hasMoreTokens())
                id_src = tok.nextToken().trim();
            else {
                postError("insufficient command arguments SQ " + cmd);
                return;
            }
            if (tok.hasMoreTokens())
                id_dst = tok.nextToken().trim();
            else {
                postError("insufficient command arguments SQ " + cmd);
                return;
            }
            int cond = getCondition(id_dst);
            if (cond != 0) {
                mgr.setInsertMode(cond);
                id_dst = tok.nextToken().trim();
            }
            VElement dst = mgr.getElement(id_dst);
            if (dst == null) {
                if ( ! id_dst.equals("tmpstudy"))
                   postError("invalid node id " + id_dst);
                return;
            }
            VElement src = mgr.getElement(id_src);
            if (src == null) {
                src = mgr.readElement(id_src, dst);
                if (src == null) {
                    if ( ! id_src.equals("tmpstudy"))
                       postError("invalid node id " + id_src);
                    return;
                }
            } else
                mgr.copyElement(src, dst);
        }
        // syntax: vnmrjcmd('SQ {get,set} <type> [<cond> <id>] <attr> <val> [<macro>]')
        else if (cmd.equals(SET) || cmd.equals(GET)) {
            String arg;
            // first token
            if (tok.hasMoreTokens())
                arg = tok.nextToken().trim();
            else {
                postError("insufficient command arguments SQ " + cmd);
                return;
            }
            // second token
            if (!tok.hasMoreTokens()) {
                postError("insufficient command arguments SQ " + cmd);
                return;
            }
            int type = 0;
            int scope = 0;
            int cond = getCondition(arg);
            String apar = null;
            String vpar = null;
            String id = null;
            VElement obj = null;
            switch (cond) {
            case ProtocolBuilder.FIRST:
            case ProtocolBuilder.ALL:
                arg = tok.nextToken();
                type = getType(arg);
                scope = getScope(arg);
                apar = tok.nextToken();
                vpar = tok.nextToken();
                break;
            default:
                type = getType(arg);
                if (type == 0 || type == ProtocolBuilder.NEW) {
                    if (type == ProtocolBuilder.NEW) {
                        if (new_elem == null) {
                            postError("must call SQ add before using new");
                            return;
                        }
                        obj = new_elem;
                    } else {
                        // e.g. set p2.a2 Lock on
                        obj = mgr.getElement(arg);
                        if (obj == null) {
                            // NB: This can happen when chempack adds protocols
                            // Ugly but harmless error
                            Messages.postDebug("SQ",
                                               "unknown identifier SQ " + str);
                            return;
                        }
                    }
                    cond = ProtocolBuilder.ONE;
                    type = ProtocolBuilder.ANY;
                    scope = SINGLE;
                } else {
                    // e.g. set actions > p2.a2 Lock on
                    scope = getScope(arg);
                    arg = tok.nextToken().trim();
                    cond = getCondition(arg);
                    if (scope == SINGLE) {
                        // e.g. set actions after p2.a2 Lock on
                        if (cond == ProtocolBuilder.GT)
                            cond = ProtocolBuilder.AFTER;
                        else if (cond == ProtocolBuilder.LT)
                            cond = ProtocolBuilder.BEFORE;
                    }
                    if (cond == 0) {
                        id = arg;
                        cond = ProtocolBuilder.ONE;
                    } else
                        id = tok.nextToken();
                    obj = mgr.getElement(id);
                }
                apar = tok.nextToken();
                vpar = tok.nextToken();
                if (vpar.startsWith("\"")) {
                    try {
                        vpar = vpar.substring(1) + tok.nextToken("\"");
                    } catch (NoSuchElementException e) {
                        vpar = vpar.substring(1, vpar.length() - 1);
                    }
                }
                break;
            } // switch
            if (apar == null || vpar == null) {
                postError("syntax error " + "SQ " + str);
                return;
            }
            ArrayList list;
            // looking for nodes in id will return a null list if id does not exist
            if ((obj == null) && (cond == ProtocolBuilder.EQ) )
               list = new ArrayList();
            else
               list = mgr.getElements(obj, cond, type);
            if (cmd.equals(SET)) {
                for (int i = 0; i < list.size(); i++) {
                    obj = (VElement) list.get(i);
                    mgr.setAttribute(obj, apar, vpar);
                }
                //mgr.invalidateTree();
            } else { // get
                if (scope == SINGLE) {
                    if (list.size() > 1) {
                        postError("syntax error " + "SQ " + str);
                        return;
                    }
                    String alist = apar + "=`";
                    String vlist = vpar + "=`";
                    if (list.size() == 1) {
                        obj = (VElement) list.get(0);
                        list = mgr.getAttributes(obj);
                        for (int i = 0; i < list.size(); i += 2) {
                            String name = (String) list.get(i);
                            String value = (String) list.get(i + 1);
                            alist += name;
                            vlist += value;
                            if (i < list.size() - 2) {
                                alist += "`,`";
                                vlist += "`,`";
                            }
                        }
                    }
                    alist += "`";
                    vlist += "`";
                    retstr = alist + " " + vlist;
                } else {
                    retstr = vpar + "=`";
                    for (int i = 0; i < list.size(); i++) {
                        obj = (VElement) list.get(i);
                        String value = obj.getAttribute(apar);
                        retstr += value;
                        if (i < list.size() - 1)
                            retstr += "`,`";
                    }
                    retstr += "`";
                }
            }
        } else if (cmd.equals(WATCH)) {
            // E.g.: vnmrjcmd('SQ watch auto ', cursqexp, autodir, svfdir)
            ArrayList<String> args = new ArrayList<String>();
            while (tok.hasMoreTokens()) {
                args.add(tok.nextToken());
            }
             if (!SQUpdater.processCommand(this, args.toArray(new String[0]))) {
                 Messages.postDebug("Bad format for 'watch' cmd: " + str);
             }
//            if (tok.countTokens() != 3) {
//                Messages.postDebug("Bad format for 'watch' cmd: " + str);
//            } else {
//                String studydir = tok.nextToken();
//                String autodir = tok.nextToken();
//                String datadir = tok.nextToken();
//                SQUpdater.startUpdates(this, studydir, autodir, datadir);
//            }
        } else {
            postError("command not recognized " + "SQ " + cmd);
            return;
        }
        while (tok.hasMoreTokens())
            retstr += " " + tok.nextToken().trim();
        if (retstr.length() > 0) {
            setDebug(retstr);
            Util.sendToVnmr(retstr);
        }
    }
return;
}
// second token
if (!tok.hasMoreTokens()) {
postError("insufficient command arguments SQ " + cmd);
// syntax: vnmrjcmd('SQ {get,set} <type> [<cond> <id>] <attr> <val> [<macro>]')
else if (cmd.equals(SET) || cmd.equals(GET)) {
String arg;
// first token
if (tok.hasMoreTokens())
arg = tok.nextToken().trim();
else {
postError("insufficient command arguments SQ " + cmd);
return;
}
// second token
if (!tok.hasMoreTokens()) {
postError("insufficient command arguments SQ " + cmd);
return;
}
int type = 0;
int scope = 0;
int cond = getCondition(arg);
String apar = null;
String vpar = null;
String id = null;
if (src == null) {
src = mgr.readElement(id_src, dst);
if (src == null) {
if ( ! id_src.equals("tmpstudy"))
postError("invalid node id " + id_src);
return;
}
} else
mgr.copyElement(src, dst);
}
// syntax: vnmrjcmd('SQ {get,set} <type> [<cond> <id>] <attr> <val> [<macro>]')
else if (cmd.equals(SET) || cmd.equals(GET)) {
String arg;
// first token
if (tok.hasMoreTokens())
arg = tok.nextToken().trim();
else {
postError("insufficient command arguments SQ " + cmd);
return;
}
// second token
if (!tok.hasMoreTokens()) {
postError("insufficient command arguments SQ " + cmd);
return;
}
int type = 0;
int scope = 0;
int cond = getCondition(arg);
String apar = null;
String vpar = null;
String id = null;
VElement obj = null;
switch (cond) {
case ProtocolBuilder.FIRST:
case ProtocolBuilder.ALL:
arg = tok.nextToken();
type = getType(arg);
scope = getScope(arg);
apar = tok.nextToken();
vpar = tok.nextToken();
break;