/** * Notifies all views of a context change. * * @param nodes new context set (may be {@code null} if root nodes are addressed) * @param quick quick switch * @param vw the calling view */ public void context(final Nodes nodes, final boolean quick, final View vw) { final Context ctx = gui.context; // add new entry if current node set has not been cached yet final Nodes newn = nodes.checkRoot(); final Nodes empty = new Nodes(new int[0], ctx.data(), ctx.marked.ftpos); final Nodes curr = quick ? ctx.current() : null; final Nodes cmp = quick ? curr : ctx.marked; if (cont[hist] == null ? cmp != null : cmp == null || !cont[hist].sameAs(cmp)) { checkHist(); if (quick) { // store history entry queries[hist] = ""; marked[hist] = new Nodes(ctx.data()); // add current entry cont[++hist] = curr; } else { // store history entry final String in = gui.input.getText(); queries[hist] = in; marked[hist] = ctx.marked; // add current entry cont[++hist] = newn; queries[hist] = in; marked[hist] = empty; } histsize = hist; } ctx.set(newn, empty); for (final View v : view) if (v != vw && v.visible()) v.refreshContext(true, quick); gui.refreshControls(); }
@Override public void execute(final GUI gui) { final boolean rt = gui.gprop.invert(GUIProp.FILTERRT); gui.stop(); // refresh buttons in input bar gui.refreshControls(); // refresh editor buttons gui.editor.refreshMark(); final Context ctx = gui.context; final boolean root = ctx.root(); final Data data = ctx.data(); if (!rt) { if (!root) { gui.notify.context(new Nodes(0, data), true, null); gui.notify.mark(ctx.current(), null); } } else { if (root) { gui.notify.mark(new Nodes(data), null); } else { final Nodes mark = ctx.marked; ctx.marked = new Nodes(data); gui.notify.context(mark, true, null); } } }
/** * Notifies all views of a selection change. * * @param mark marked nodes * @param vw the calling view */ public void mark(final Nodes mark, final View vw) { final Context ctx = gui.context; ctx.marked = mark; for (final View v : view) if (v != vw && v.visible()) v.refreshMark(); gui.filter.setEnabled(mark.size() != 0); gui.refreshControls(); }
@Override public void execute(final GUI gui) { // skip operation for root context final Context ctx = gui.context; if (ctx.root()) return; // jump to database root ctx.update(); gui.notify.context(ctx.current(), false, null); }
@Override public void execute(final GUI gui) { final Context ctx = gui.context; Nodes marked = ctx.marked; if (marked.size() == 0) { final int pre = gui.context.focused; if (pre == -1) return; marked = new Nodes(pre, ctx.data()); } gui.notify.context(marked, false, null); }
/** * Notifies all views of a selection change. The mode flag determines what happens: * * <ul> * <li>0: set currently focused node as marked node * <li>1: add currently focused node * <li>2: toggle currently focused node * </ul> * * @param mode mark mode * @param vw the calling view */ public void mark(final int mode, final View vw) { final int f = gui.context.focused; if (f == -1) return; final Context ctx = gui.context; Nodes nodes = ctx.marked; if (mode == 0) { nodes = new Nodes(f, ctx.data()); } else if (mode == 1) { nodes.union(new int[] {f}); } else { nodes.toggle(f); } mark(nodes, vw); }
/** * Moves around in the internal history and notifies all views of a context change. * * @param forward move forward or backward */ public void hist(final boolean forward) { final Context ctx = gui.context; final String query; if (forward) { if (hist == histsize) return; query = queries[++hist]; } else { if (hist == 0) return; marked[hist] = ctx.marked; query = queries[--hist]; } ctx.set(cont[hist], marked[hist]); gui.input.setText(query); for (final View v : view) if (v.visible()) v.refreshContext(forward, false); gui.refreshControls(); }
/** * Executes the command, prints the result to the specified output stream and returns a success * flag. * * @param ctx database context * @param os output stream * @return success flag. The {@link #info()} method returns information on a potential exception */ private boolean exec(final Context ctx, final OutputStream os) { // check if data reference is available final Data dt = ctx.data(); if (dt == null && data) return error(NO_DB_OPENED); // check permissions if (!ctx.perm(perm, dt != null ? dt.meta : null)) return error(PERM_REQUIRED_X, perm); // set updating flag updating = updating(ctx); try { // register process ctx.register(this); // run command and return success flag return run(ctx, os); } finally { // guarantee that process will be unregistered ctx.unregister(this); } }
/** * Removes existing history entries and sets an initial entry. * * @param ctx database context * @return {@link Data} reference, or {@code null} */ private Data initHistory(final Context ctx) { for (int h = 0; h < histsize; h++) { marked[h] = null; cont[h] = null; queries[h] = null; } hist = 0; histsize = 0; final Data data = ctx.data(); if (data != null) { // new database opened marked[0] = new Nodes(data); queries[0] = ""; } return data; }
/** * Opens the specified database. * * @param name name of database * @param ctx database context * @return data reference * @throws IOException I/O exception */ public static Data open(final String name, final Context ctx) throws IOException { synchronized (ctx.dbs) { Data data = ctx.dbs.pin(name); if (data == null) { // check if database exists if (!ctx.globalopts.dbexists(name)) throw new BaseXException(dbnf(name)); data = new DiskData(name, ctx); ctx.dbs.add(data); } // check permissions if (!ctx.perm(Perm.READ, data.meta)) { Close.close(data, ctx); throw new BaseXException(PERM_REQUIRED_X, Perm.READ); } return data; } }
/** * Creates an XQuery representation for the specified query. * * @param query query * @param ctx database context * @param root start from root node * @return query */ public static String find(final String query, final Context ctx, final boolean root) { // treat input as XQuery if (query.startsWith("/")) return query; final boolean r = root || ctx.root(); if (query.isEmpty()) return r ? "/" : "."; // parse user input final String qu = query.replaceAll(" \\+", " "); final String[] terms = split(qu); String pre = ""; String preds = ""; final String tag = "*"; for (String term : terms) { if (term.startsWith("@=")) { preds += "[@* = \"" + term.substring(2) + "\"]"; } else if (term.startsWith("=")) { preds += "[text() = \"" + term.substring(1) + "\"]"; } else if (term.startsWith("~")) { preds += "[text() contains text \"" + term.substring(1) + "\" using fuzzy]"; } else if (term.startsWith("@")) { if (term.length() == 1) continue; preds += "[@* contains text \"" + term.substring(1) + "\"]"; term = term.substring(1); // add valid name tests if (XMLToken.isName(token(term))) { pre += (r ? "" : ".") + "//@" + term + " | "; } } else { preds += "[text() contains text \"" + term + "\"]"; // add valid name tests if (XMLToken.isName(token(term))) { pre += (r ? "/" : "") + Axis.DESC + "::*:" + term + " | "; } } } if (pre.isEmpty() && preds.isEmpty()) return root ? "/" : "."; // create final string final TokenBuilder tb = new TokenBuilder(); tb.add(pre + (r ? "/" : "") + Axis.DESCORSELF + "::" + tag + preds); return tb.toString(); }
@Override public void execute(final GUI gui) { // skip operation for root context final Context ctx = gui.context; if (ctx.root()) return; // check if all nodes are document nodes boolean doc = true; final Data data = ctx.data(); for (final int pre : ctx.current().pres) doc &= data.kind(pre) == Data.DOC; if (doc) { // if yes, jump to database root ctx.update(); gui.notify.context(ctx.current(), false, null); } else { // otherwise, jump to parent nodes gui.execute(new Cs("..")); } }
@Override public void execute(final GUI gui) { final Context ctx = gui.context; final Nodes n = ctx.marked; ctx.copied = new Nodes(n.pres, n.data); }
/** * Closes the specified database if it is currently opened and only pinned once. * * @param ctx database context * @param db database to be closed * @return closed flag */ protected static boolean close(final Context ctx, final String db) { final boolean close = ctx.data() != null && db.equals(ctx.data().meta.name) && ctx.dbs.pins(db) == 1; return close && new Close().run(ctx); }