/** * Returns a serializer for the given output stream. Optional output declarations within the query * will be included in the serializer instance. * * @param os output stream * @return serializer instance * @throws IOException query exception * @throws QueryException query exception */ public Serializer getSerializer(final OutputStream os) throws IOException, QueryException { compile(); try { return Serializer.get(os, qc.serParams()); } catch (final QueryIOException ex) { throw ex.getCause(); } }
/** * Parses the query. * * @throws QueryException query exception */ public void parse() throws QueryException { if (parsed) return; try { qc.parseMain(query, null, sc); } finally { parsed = true; updating = qc.updating; } }
/** * Returns a result iterator. * * @return result iterator * @throws QueryException query exception */ public Iter iter() throws QueryException { parse(); return qc.iter(); }
/** * Compiles the query. * * @throws QueryException query exception */ public void compile() throws QueryException { parse(); qc.compile(); }
/** * Parses the query. * * @throws QueryException query exception */ public void parse() throws QueryException { if (parsed) return; parsed = true; qc.parseMain(query, null, sc); updating = qc.updating; }
/** * Returns a tree representation of the query plan. * * @return root node */ public FDoc plan() { return new FDoc().add(qc.plan()); }
/** * Returns query information. * * @return query information */ public String info() { return qc.info(); }
@Override public void databases(final LockResult lr) { qc.databases(lr); }
/** * Returns the number of performed updates after query execution, or {@code 0}. * * @return number of updates */ public int updates() { return updating ? qc.updates().size() : 0; }
/** * Binds the context value with a specified type, using the same rules as for {@link #bind binding * variables}. * * @param value value to be bound * @param type type (may be {@code null}) * @return self reference * @throws QueryException query exception */ public QueryProcessor context(final Object value, final String type) throws QueryException { qc.context(value, type, sc); return this; }
/** * Binds the HTTP context to the query processor. * * @param value HTTP context * @return self reference */ public QueryProcessor http(final Object value) { qc.http(value); return this; }
/** * Binds the context value. * * @param value XQuery value to be bound * @return self reference */ public QueryProcessor context(final Value value) { qc.context(value, sc); return this; }
/** * Binds an XQuery value to a global variable. * * @param name name of variable * @param value value to be bound * @return self reference * @throws QueryException query exception */ public QueryProcessor bind(final String name, final Value value) throws QueryException { qc.bind(name, value, sc); return this; }
/** * Evaluates the specified query and returns the result. * * @return result of query * @throws QueryException query exception */ public Result execute() throws QueryException { parse(); return qc.execute(); }
/** * Returns a result value. * * @return result value * @throws QueryException query exception */ public Value value() throws QueryException { parse(); return qc.iter().value(); }
@Override public void close() { qc.close(); }
/** * Evaluates the specified function and creates a response. * * @throws Exception exception (including unexpected ones) */ void create() throws Exception { // bind variables final StaticFunc sf = function.function; final Expr[] args = new Expr[sf.args.length]; function.bind(http, args, error); // wrap function with a function call final MainModule mm = new MainModule(sf, args); // assign main module and http context and register process query.mainModule(mm); query.http(http); query.context.register(query); String redirect = null, forward = null; RestXqRespBuilder resp = null; try { // compile and evaluate query query.compile(); final Iter iter = query.iter(); Item item = iter.next(); // handle response element if (item != null && item instanceof ANode) { final ANode node = (ANode) item; // send redirect to browser if (REST_REDIRECT.eq(node)) { final ANode ch = node.children().next(); if (ch == null || ch.type != NodeType.TXT) throw function.error(NO_VALUE, node.name()); redirect = string(ch.string()).trim(); return; } // server-side forwarding if (REST_FORWARD.eq(node)) { final ANode ch = node.children().next(); if (ch == null || ch.type != NodeType.TXT) throw function.error(NO_VALUE, node.name()); forward = string(ch.string()).trim(); return; } if (REST_RESPONSE.eq(node)) { resp = new RestXqRespBuilder(); resp.build(node, function, iter, http); return; } } // HEAD method must return a single response element if (function.methods.size() == 1 && function.methods.contains(HTTPMethod.HEAD.name())) throw function.error(HEAD_METHOD); // serialize result final SerializerOptions sp = function.output; http.sopts(sp); http.initResponse(); final Serializer ser = Serializer.get(http.res.getOutputStream(), sp); for (; item != null; item = iter.next()) ser.serialize(item); ser.close(); } finally { query.close(); query.context.unregister(query); if (redirect != null) { http.res.sendRedirect(redirect); } else if (forward != null) { http.req.getRequestDispatcher(forward).forward(http.req, http.res); } else if (resp != null) { if (resp.status != 0) http.status(resp.status, resp.message, resp.error); http.res.getOutputStream().write(resp.cache.toArray()); } } }
/** * This function is called by the GUI; use {@link #iter()} or {@link #value()} instead. Caches and * returns the result of the specified query. If all nodes are of the same database instance, the * returned value will be of type {@link DBNodes}. * * @param max maximum number of results to cache (negative: return all values) * @return result of query * @throws QueryException query exception */ public Value cache(final int max) throws QueryException { parse(); return qc.cache(max); }