mas01mj@640: /********************************************************** mas01mj@640: Copyright (c) 2006, 2007 mas01mj@640: Lee Feigenbaum ( lee AT thefigtrees DOT net ) mas01mj@640: Elias Torres ( elias AT torrez DOT us ) mas01mj@640: Wing Yung ( wingerz AT gmail DOT com ) mas01mj@640: All rights reserved. mas01mj@640: mas01mj@640: Permission is hereby granted, free of charge, to any person obtaining a copy of mas01mj@640: this software and associated documentation files (the "Software"), to deal in mas01mj@640: the Software without restriction, including without limitation the rights to mas01mj@640: use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies mas01mj@640: of the Software, and to permit persons to whom the Software is furnished to do mas01mj@640: so, subject to the following conditions: mas01mj@640: mas01mj@640: The above copyright notice and this permission notice shall be included in all mas01mj@640: copies or substantial portions of the Software. mas01mj@640: mas01mj@640: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR mas01mj@640: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, mas01mj@640: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE mas01mj@640: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER mas01mj@640: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, mas01mj@640: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE mas01mj@640: SOFTWARE. mas01mj@640: **********************************************************/ mas01mj@640: mas01mj@640: /** mas01mj@640: * Example client interactions mas01mj@640: * mas01mj@640: mas01mj@640: var sparqler = new SPARQL.Service("http://sparql.org/sparql"); mas01mj@640: sparqler.addDefaultGraph("http://thefigtrees.net/lee/ldf-card"); // inherited by all (future) queries mas01mj@640: sparqler.addNamedGraph("http://torrez.us/elias/foaf.rdf"); mas01mj@640: sparqler.setPrefix("foaf", "http://xmlns.com/foaf/0.1/"); // inherited by all (future) queries mas01mj@640: sparqler.setPrefix("rdf", "http://xmlns.com/foaf/0.1/"); mas01mj@640: mas01mj@640: sparqler.setRequestHeader("Authentication", "Basic: " + basicAuthString); mas01mj@640: mas01mj@640: //sparqler.wantOutputAs("application/json"); // for now we only do JSON mas01mj@640: mas01mj@640: var query = sparqler.createQuery(); mas01mj@640: query.addDefualtGraph(...) query.addNamedGraph(...) query.setPrefix(...) query.setRequestHeader(...) // this query only mas01mj@640: mas01mj@640: // query forms: mas01mj@640: mas01mj@640: // passes standard JSON results object to success callback mas01mj@640: query.setPrefix("ldf", "http://thefigtrees.net/lee/ldf-card#"); mas01mj@640: query.query("SELECT ?who ?mbox WHERE { ldf:LDF foaf:knows ?who . ?who foaf:mbox ?mbox }", mas01mj@640: {failure: onFailure, success: function(json) { for (var x in json.head.vars) { ... } ...}} mas01mj@640: ); mas01mj@640: mas01mj@640: // passes boolean value to success callback mas01mj@640: query.ask("ASK ?person WHERE { ?person foaf:knows [ foaf:name "Dan Connolly" ] }", mas01mj@640: {failure: onFailure, success: function(bool) { if (bool) ... }} mas01mj@640: ); mas01mj@640: mas01mj@640: // passes a single vector (array) of values representing a single column of results to success callback mas01mj@640: query.setPrefix("ldf", "http://thefigtrees.net/lee/ldf-card#"); mas01mj@640: var addresses = query.selectValues("SELECT ?mbox WHERE { _:someone foaf:mbox ?mbox }", mas01mj@640: {failure: onFailure, success: function(values) { for (var i = 0; i < values.length; i++) { ... values[i] ...} } } mas01mj@640: ); mas01mj@640: mas01mj@640: // passes a single value representing a single row of a single column (variable) to success callback mas01mj@640: query.setPrefix("ldf", "http://thefigtrees.net/lee/ldf-card#"); mas01mj@640: var myAddress = query.selectSingleValue("SELECT ?mbox WHERE {ldf:LDF foaf:mbox ?mbox }", mas01mj@640: {failure: onFailure, success: function(value) { alert("value is: " + value); } } mas01mj@640: ); mas01mj@640: mas01mj@640: // shortcuts for all of the above (w/o ability to set any query-specific graphs or prefixes) mas01mj@640: sparqler.query(...) sparqler.ask(...) sparqler.selectValues(...) sparqler.selectSingleValue(...) mas01mj@640: mas01mj@640: mas01mj@640: */ mas01mj@640: mas01mj@640: var SPARQL = {}; // SPARQL namespace mas01mj@640: mas01mj@640: mas01mj@640: /** mas01mj@640: * Both SPARQL service objects and SPARQL query objects receive one query utility method mas01mj@640: * per entry in this dictionary. The key is the name of the method, and the value is a function mas01mj@640: * that transforms the standard JSON output into a more useful form. The return value of a mas01mj@640: * transformation function is passed into any 'success' callback function provided when the query mas01mj@640: * is issued. The following transformations are included: mas01mj@640: * + query -- identity transform; returns the JSON structure unchanged mas01mj@640: * + ask -- for ASK queries; returns a boolean value indicating the answer to the query mas01mj@640: * + selectValues -- for SELECT queries with a single variable; returns an array containing mas01mj@640: * the answers to the query mas01mj@640: * + selectSingleValue -- for SELECT queries returning one column with one row; returns the mas01mj@640: * value in the first (and presumably, only) cell in the resultset mas01mj@640: * + selectValueArrays -- for SELECT queries returning independent columns; returns a hash mas01mj@640: * keyed on variable name with values as arrays of answers for that variable. Useful mas01mj@640: * for UNION queries. mas01mj@640: * Note that all of the transformations that return values directly lose any type information mas01mj@640: * and the ability to distinguish between URIs, blank nodes, and literals. mas01mj@640: */ mas01mj@640: SPARQL._query_transformations = { mas01mj@640: query: function (o) { return o; }, mas01mj@640: ask: function (o) { return o["boolean"]; }, mas01mj@640: selectValues: function (o) { mas01mj@640: var v = o.head.vars[0]; // assume one variable mas01mj@640: var values = []; mas01mj@640: for (var i = 0; i < o.results.bindings.length; i++) mas01mj@640: values.push(o.results.bindings[i][v].value); mas01mj@640: return values; mas01mj@640: }, mas01mj@640: selectSingleValue: function(o) { return o.results.bindings[0][o.head.vars[0]].value; }, mas01mj@640: selectValueArrays: function(o) { mas01mj@640: // factor by value (useful for UNION queries) mas01mj@640: var ret = {}; mas01mj@640: for (var i = 0; i < o.head.vars.length; i++) mas01mj@640: ret[o.head.vars[i]] = []; mas01mj@640: for (var i = 0; i < o.results.bindings.length; i++) mas01mj@640: for (var v in o.results.bindings[i]) mas01mj@640: if (ret[v] instanceof Array) ret[v].push(o.results.bindings[i][v].value); mas01mj@640: return ret; mas01mj@640: }, mas01mj@640: selectValueHashes: function(o) { mas01mj@640: var hashes = []; mas01mj@640: for (var i = 0; i < o.results.bindings.length; i++) { mas01mj@640: var hash = {}; mas01mj@640: for (var v in o.results.bindings[i]) mas01mj@640: hash[v] = o.results.bindings[i][v].value; mas01mj@640: hashes.push(hash); mas01mj@640: } mas01mj@640: return hashes; mas01mj@640: } mas01mj@640: }; mas01mj@640: mas01mj@640: SPARQL.statistics = { mas01mj@640: queries_sent : 0, mas01mj@640: successes : 0, mas01mj@640: failures : 0 mas01mj@640: }; mas01mj@640: mas01mj@640: // A SPARQL service represents a single endpoint which implements the HTTP (GET or POST) mas01mj@640: // bindings of the SPARQL Protocol. It provides convenience methods to set dataset and mas01mj@640: // prefix options for all queries created for this endpoint. mas01mj@640: SPARQL.Service = function(endpoint) { mas01mj@640: //--------------- mas01mj@640: // private fields mas01mj@640: var _endpoint = endpoint; mas01mj@640: var _default_graphs = []; mas01mj@640: var _named_graphs = []; mas01mj@640: var _prefix_map = {}; mas01mj@640: var _method = 'POST'; mas01mj@640: var _output = 'json'; mas01mj@640: var _max_simultaneous = 0; mas01mj@640: var _request_headers = {}; mas01mj@640: mas01mj@640: //---------- mas01mj@640: // accessors mas01mj@640: this.endpoint = function() { return _endpoint; }; mas01mj@640: this.defaultGraphs = function() { return _default_graphs; }; mas01mj@640: this.namedGraphs = function() { return _named_graphs; }; mas01mj@640: this.prefixes = function() { return _prefix_map; }; mas01mj@640: this.method = function() { return _method; }; mas01mj@640: this.output = function() { return _output; }; mas01mj@640: this.maxSimultaneousQueries = function() { return _max_simultaneous; }; mas01mj@640: this.requestHeaders = function() { return _request_headers; }; mas01mj@640: mas01mj@640: //--------- mas01mj@640: // mutators mas01mj@640: function _add_graphs(toAdd, arr) { mas01mj@640: if (toAdd instanceof Array) mas01mj@640: for (var i = 0; i < toAdd.length; i++) arr.push(toAdd[i]); mas01mj@640: else mas01mj@640: arr.push(toAdd); mas01mj@640: } mas01mj@640: this.addDefaultGraph = function(g) { _add_graphs(g, this.defaultGraphs()); }; mas01mj@640: this.addNamedGraph = function(g) { _add_graphs(g, this.namedGraphs()); }; mas01mj@640: this.setPrefix = function(p, u) { this.prefixes()[p] = u; }; mas01mj@640: this.createQuery = function(p) { return new SPARQL.Query(this, p); }; mas01mj@640: this.setMethod = function(m) { mas01mj@640: if (m != 'GET' && m != 'POST') throw("HTTP methods other than GET and POST are not supported."); mas01mj@640: _method = m; mas01mj@640: }; mas01mj@640: this.setOutput = function(o) { _output = o; }; mas01mj@640: this.setMaxSimultaneousQueries = function(m) { _max_simultaneous = m; }; mas01mj@640: this.setRequestHeader = function(h, v) { _request_headers[h] = v; }; mas01mj@640: mas01mj@640: //--------------- mas01mj@640: // protected methods (should only be called within this module mas01mj@640: this._active_queries = 0; mas01mj@640: this._queued_queries = []; mas01mj@640: this._next_in_queue = 0; mas01mj@640: this._canRun = function() { return this.maxSimultaneousQueries() <= 0 || this._active_queries < this.maxSimultaneousQueries();}; mas01mj@640: this._queue = function(q,f, p) { mas01mj@640: if (!p) p = 0; mas01mj@640: if (p > 0) { mas01mj@640: for (var i = 0; i < this._queued_queries.length; i++) { mas01mj@640: if (this._queued_queries[i] != null && this._queued_queries[i][2] < p) { mas01mj@640: this._queued_queries.splice(i, 0, [q, f, p]); mas01mj@640: return; mas01mj@640: } mas01mj@640: } mas01mj@640: } mas01mj@640: this._queued_queries.push([q,f,p]); mas01mj@640: }; mas01mj@640: this._markRunning = function(q) { this._active_queries++; }; mas01mj@640: this._markDone = function(q) { mas01mj@640: this._active_queries--; mas01mj@640: //document.getElementById('log').innerHTML+="query done. " + this._active_queries + " queries still active.
"; mas01mj@640: if (this._queued_queries[this._next_in_queue] != null && this._canRun()) { mas01mj@640: var a = this._queued_queries[this._next_in_queue]; mas01mj@640: this._queued_queries[this._next_in_queue++] = null; mas01mj@640: // a[0] is query object, a[1] is function to run query mas01mj@640: //document.getElementById('log').innerHTML += "running query from Q
"; mas01mj@640: a[1](); mas01mj@640: } mas01mj@640: }; mas01mj@640: mas01mj@640: //--------------- mas01mj@640: // public methods mas01mj@640: mas01mj@640: // use our varied transformations to create the various shortcut methods of actually mas01mj@640: // issuing queries without explicitly creating a query object mas01mj@640: for (var query_form in SPARQL._query_transformations) { mas01mj@640: // need the extra function to properly scope query_form (qf) mas01mj@640: this[query_form] = (function(qf) { mas01mj@640: return function(queryString, callback) { mas01mj@640: var q = this.createQuery(); mas01mj@640: q._doQuery(queryString, callback, SPARQL._query_transformations[qf]); mas01mj@640: }; mas01mj@640: })(query_form); mas01mj@640: } mas01mj@640: mas01mj@640: //------------ mas01mj@640: // constructor mas01mj@640: mas01mj@640: if (!_endpoint) mas01mj@640: return null; mas01mj@640: mas01mj@640: return this; mas01mj@640: } mas01mj@640: mas01mj@640: /** mas01mj@640: * A SPARQL query object should be created using the createQuery method of a SPARQL mas01mj@640: * service object. It allows prefixes and datasets to be defined specifically for mas01mj@640: * a single query, and provides introspective methods to see the query string and the mas01mj@640: * full (HTTP GET) URL of the query. mas01mj@640: */ mas01mj@640: SPARQL.Query = function(service, priority) { mas01mj@640: //--------------- mas01mj@640: // private fields mas01mj@640: var _conn = null; mas01mj@640: var _service = service; mas01mj@640: var _default_graphs = clone_obj(service.defaultGraphs()); // prevent future updates from affecting us mas01mj@640: var _named_graphs = clone_obj(service.namedGraphs()); mas01mj@640: var _prefix_map = clone_obj(service.prefixes()); mas01mj@640: var _user_query = ''; // doesn't include auto-generated prefix declarations mas01mj@640: var _method = service.method(); mas01mj@640: var _output = service.output(); mas01mj@640: var _priority = priority || 0; mas01mj@640: var _request_headers = clone_obj(service.requestHeaders()); mas01mj@640: mas01mj@640: //------------------ mas01mj@640: // private functions mas01mj@640: function _create_json(text) { mas01mj@640: if (!text) mas01mj@640: return null; mas01mj@640: // make sure this is safe JSON mas01mj@640: // see: http://www.ietf.org/internet-drafts/draft-crockford-jsonorg-json-03.txt mas01mj@640: mas01mj@640: // (1) strip out quoted strings mas01mj@640: var no_strings = text.replace(/"(\\.|[^"\\])*"/g, ''); mas01mj@640: // (2) make sure that all the characters are explicitly part of the JSON grammar mas01mj@640: // (in particular, note as discussed in the IETF submission, there are no assignments mas01mj@640: // or function invocations allowed by this reg. exp.) mas01mj@640: var hasBadCharacter = /[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(no_strings); mas01mj@640: // (3) evaluate the JSON string, returning its contents mas01mj@640: if (!hasBadCharacter) { mas01mj@640: try { mas01mj@640: return eval('(' + text + ')'); mas01mj@640: } catch (e) { mas01mj@640: return null; mas01mj@640: } mas01mj@640: } mas01mj@640: return null; mas01mj@640: } mas01mj@640: mas01mj@640: function clone_obj(o) { mas01mj@640: var o2 = o instanceof Array ? [] : {}; mas01mj@640: for(var x in o) {o2[x] = o[x];} mas01mj@640: return o2; mas01mj@640: } mas01mj@640: mas01mj@640: //---------------- mas01mj@640: // private methods mas01mj@640: this._doCallback = function(cb, which, arg) { mas01mj@640: //document.getElementById('log').innerHTML += "_doCallback ...
"; mas01mj@640: var user_data = "argument" in cb ? cb.argument : null; mas01mj@640: if (which in cb) { mas01mj@640: if (cb.scope) { mas01mj@640: cb[which].apply(cb.scope, [arg, user_data]); mas01mj@640: } else { mas01mj@640: cb[which](arg, user_data); mas01mj@640: } mas01mj@640: } mas01mj@640: } mas01mj@640: mas01mj@640: this._queryFailure = function(xhr, arg) { mas01mj@640: SPARQL.statistics.failures++; mas01mj@640: _service._markDone(this); mas01mj@640: this._doCallback(arg.callback, 'failure', xhr /* just pass through the connection response object */); mas01mj@640: }; mas01mj@640: this._querySuccess = function(xhr, arg) { mas01mj@640: //alert(xhr.responseText); mas01mj@640: SPARQL.statistics.successes++; mas01mj@640: _service._markDone(this); mas01mj@640: this._doCallback(arg.callback, 'success', arg.transformer( mas01mj@640: _output == 'json' ? _create_json(xhr.responseText) : xhr.responseText mas01mj@640: )); mas01mj@640: }; mas01mj@640: mas01mj@640: function getXmlHttpRequest(url) { mas01mj@640: // right now, this only does Firefox (Opera? Safari?) mas01mj@640: return new XMLHttpRequest(); mas01mj@640: } mas01mj@640: mas01mj@640: this._doQuery = function(queryString, callback, transformer) { mas01mj@640: _user_query = queryString; mas01mj@640: if (_service._canRun()) { mas01mj@640: try { mas01mj@640: if (_method != 'POST' && _method != 'GET') mas01mj@640: throw("HTTP methods other than GET and POST are not supported."); mas01mj@640: mas01mj@640: var url = _method == 'GET' ? this.queryUrl() : this.service().endpoint(); mas01mj@640: var xhr = getXmlHttpRequest(url); mas01mj@640: var content = null; mas01mj@640: mas01mj@640: try { mas01mj@640: if (!document.domain || (url.match(/^https?:\/\//) && url.slice(7, document.domain.length + 7) != document.domain && window.netscape && netscape.security && netscape.security.PrivilegeManager)) { mas01mj@640: netscape.security.PrivilegeManager.enablePrivilege( "UniversalBrowserRead"); mas01mj@640: netscape.security.PrivilegeManager.enablePrivilege( "UniversalXPConnect"); mas01mj@640: } mas01mj@640: } catch(e) { mas01mj@640: alert("Cross-site requests prohibited. You will only be able to SPARQL the origin site: " + e); mas01mj@640: return; mas01mj@640: } mas01mj@640: mas01mj@640: xhr.open(_method, url, true /* async */); mas01mj@640: mas01mj@640: // set the headers, including the content-type for POSTed queries mas01mj@640: for (var header in this.requestHeaders()) mas01mj@640: if (typeof(this.requestHeaders()[header]) != "function") mas01mj@640: xhr.setRequestHeader(header, this.requestHeaders()[header]); mas01mj@640: if (_method == 'POST') { mas01mj@640: xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); mas01mj@640: content = this.queryParameters(); mas01mj@640: } mas01mj@640: mas01mj@640: SPARQL.statistics.queries_sent++; mas01mj@640: _service._markRunning(this); mas01mj@640: mas01mj@640: var callbackData = { mas01mj@640: scope:this, mas01mj@640: success: this._querySuccess, mas01mj@640: failure: this._queryFailure, mas01mj@640: argument: { mas01mj@640: transformer: transformer, mas01mj@640: callback: callback mas01mj@640: } mas01mj@640: }; mas01mj@640: mas01mj@640: // I've seen some strange race-condition behavior (strange since normally mas01mj@640: // JS is single-threaded, so synchronization conditions don't occur barring mas01mj@640: // reentrancy) with onreadystatechange. Instead, we poll asynchronously to mas01mj@640: // determine when the request is done. mas01mj@640: var token = window.setInterval( mas01mj@640: function () { mas01mj@640: if (xhr.readyState == 4) { // ready! mas01mj@640: // clear this handler mas01mj@640: window.clearInterval(token); mas01mj@640: // we check the status to know which callback to call mas01mj@640: if (xhr.status >= 200 && xhr.status < 300) mas01mj@640: callbackData.success.apply(callbackData.scope, [xhr, callbackData.argument]); mas01mj@640: else mas01mj@640: callbackData.failure.apply(callbackData.scope, [xhr, callbackData.argument]); mas01mj@640: } mas01mj@640: }, mas01mj@640: 200 /* maybe this should be customizable */ mas01mj@640: ); mas01mj@640: mas01mj@640: xhr.send(content); mas01mj@640: } catch (e) { mas01mj@640: alert("Error sending SPARQL query: " + e); mas01mj@640: } mas01mj@640: } else { mas01mj@640: var self = this; mas01mj@640: _service._queue(self, function() { self._doQuery(queryString, callback, transformer); }, _priority); mas01mj@640: } mas01mj@640: }; mas01mj@640: mas01mj@640: mas01mj@640: //---------- mas01mj@640: // accessors mas01mj@640: this.request = function() { return _conn; }; mas01mj@640: this.service = function() { return _service; }; mas01mj@640: this.defaultGraphs = function() { return _default_graphs; }; mas01mj@640: this.namedGraphs = function() { return _named_graphs; }; mas01mj@640: this.prefixes = function() { return _prefix_map; }; mas01mj@640: this.method = function() { return _method; }; mas01mj@640: this.requestHeaders = function() { return _request_headers; }; mas01mj@640: mas01mj@640: mas01mj@640: /** mas01mj@640: * Returns the SPARQL query represented by this object. The parameter, which can mas01mj@640: * be omitted, determines whether or not auto-generated PREFIX clauses are included mas01mj@640: * in the returned query string. mas01mj@640: */ mas01mj@640: this.queryString = function(excludePrefixes) { mas01mj@640: var preamble = ''; mas01mj@640: if (!excludePrefixes) { mas01mj@640: for (var prefix in this.prefixes()) { mas01mj@640: if(typeof(this.prefixes()[prefix]) != 'string') continue; mas01mj@640: preamble += 'PREFIX ' + prefix + ': <' + this.prefixes()[prefix] + '> '; mas01mj@640: } mas01mj@640: } mas01mj@640: return preamble + _user_query; mas01mj@640: }; mas01mj@640: mas01mj@640: /** mas01mj@640: * Returns the HTTP query parameters to invoke this query. This includes entries for mas01mj@640: * all of the default graphs, the named graphs, the SPARQL query itself, and an mas01mj@640: * output parameter to specify JSON (or other) output is desired. mas01mj@640: */ mas01mj@640: this.queryParameters = function () { mas01mj@640: var urlQueryString = ''; mas01mj@640: var i; mas01mj@640: mas01mj@640: // add default and named graphs to the protocol invocation mas01mj@640: for (i = 0; i < this.defaultGraphs().length; i++) urlQueryString += 'default-graph-uri=' + encodeURIComponent(this.defaultGraphs()[i]) + '&'; mas01mj@640: for (i = 0; i < this.namedGraphs().length; i++) urlQueryString += 'named-graph-uri=' + encodeURIComponent(this.namedGraphs()[i]) + '&'; mas01mj@640: mas01mj@640: // specify JSON output (currently output= supported by latest Joseki) (or other output) mas01mj@640: urlQueryString += 'output=' + _output + '&soft-limit=-1&'; mas01mj@640: return urlQueryString + 'query=' + encodeURIComponent(this.queryString()); mas01mj@640: } mas01mj@640: mas01mj@640: /** mas01mj@640: * Returns the HTTP GET URL to invoke this query. (Note that this returns a full HTTP GET URL mas01mj@640: * even if this query is set to actually use POST.) mas01mj@640: */ mas01mj@640: this.queryUrl = function() { mas01mj@640: var url = this.service().endpoint() + '?'; mas01mj@640: return url + this.queryParameters(); mas01mj@640: }; mas01mj@640: mas01mj@640: //--------- mas01mj@640: // mutators mas01mj@640: function _add_graphs(toAdd, arr) { mas01mj@640: if (toAdd instanceof Array) mas01mj@640: for (var i = 0; i < toAdd.length; i++) arr.push(toAdd[i]); mas01mj@640: else mas01mj@640: arr.push(toAdd); mas01mj@640: } mas01mj@640: this.addDefaultGraph = function(g) { _add_graphs(g, this.defaultGraphs()); }; mas01mj@640: this.addNamedGraph = function(g) { _add_graphs(g, this.namedGraphs()); }; mas01mj@640: this.setPrefix = function(p, u) { this.prefixes()[p] = u; }; mas01mj@640: this.setMethod = function(m) { mas01mj@640: if (m != 'GET' && m != 'POST') throw("HTTP methods other than GET and POST are not supported."); mas01mj@640: _method = m; mas01mj@640: }; mas01mj@640: this.setRequestHeader = function(h, v) { _request_headers[h] = v; }; mas01mj@640: mas01mj@640: //--------------- mas01mj@640: // public methods mas01mj@640: mas01mj@640: // use our varied transformations to create the various methods of actually issuing mas01mj@640: // queries mas01mj@640: for (var query_form in SPARQL._query_transformations) { mas01mj@640: // need the extra function to properly scope query_form (qf) mas01mj@640: this[query_form] = (function(qf) { mas01mj@640: return function(queryString, callback) { mas01mj@640: this._doQuery(queryString, callback, SPARQL._query_transformations[qf]); mas01mj@640: }; mas01mj@640: })(query_form); mas01mj@640: } mas01mj@640: mas01mj@640: mas01mj@640: //------------ mas01mj@640: // constructor mas01mj@640: mas01mj@640: return this; mas01mj@640: } mas01mj@640: mas01mj@640: // Nothing to see here, yet. mas01mj@640: SPARQL.QueryUtilities = { mas01mj@640: }; mas01mj@640: