sparnatural
Version:
Visual client-side SPARQL query builder and knowledge graph exploration tool
124 lines • 5.29 kB
JavaScript
import { UrlFetcher } from "./UrlFetcher";
export class SparqlHandlerFactory {
constructor(lang, localCacheDataTtl, extraHeaders, customizedSparqlHandler, catalog) {
this.lang = lang;
this.localCacheDataTtl = localCacheDataTtl;
this.extraHeaders = extraHeaders;
this.customizedSparqlHandler = customizedSparqlHandler;
this.catalog = catalog;
}
buildSparqlHandler(endpoints) {
// if customized handler, use it
if (this.customizedSparqlHandler) {
return this.customizedSparqlHandler;
}
// if more than one endpoint
if (endpoints.length > 1) {
// extract selected endpoints from full catalog
let subCatalog = this.catalog.extractSubCatalog(endpoints);
return new MultipleEndpointSparqlHandler(new UrlFetcher(this.localCacheDataTtl, this.extraHeaders), subCatalog, this.lang);
}
else {
// only one single endpoint
let endpoint = endpoints[0];
return new EndpointSparqlHandler(new UrlFetcher(this.localCacheDataTtl, this.extraHeaders), endpoint);
}
}
}
/**
* Executes a SPARQL query against a remote endpoint at a known URL
*/
export class EndpointSparqlHandler {
constructor(urlFetcher, sparqlEndpointUrl) {
this.urlFetcher = urlFetcher,
this.sparqlEndpointUrl = sparqlEndpointUrl;
}
buildUrl(sparql) {
var separator = this.sparqlEndpointUrl.indexOf("?") > 0 ? "&" : "?";
var url = this.sparqlEndpointUrl +
separator +
this.buildParameters(sparql);
return url;
}
buildParameters(sparql) {
return "query=" + encodeURIComponent(sparql) + "&format=json";
}
executeSparqlPost(sparql, callback, errorCallback) {
let url = this.sparqlEndpointUrl;
const headers = new Headers();
headers.append("Content-Type", "application/x-www-form-urlencoded");
headers.append("Accept", "application/sparql-results+json,*/*;q=0.9");
return this.urlFetcher.fetchUrlWithParameters(url, {
method: "POST",
body: this.buildParameters(sparql),
headers: headers
}, callback, errorCallback);
}
executeSparqlGet(sparql, callback, errorCallback) {
let url = this.buildUrl(sparql);
this.urlFetcher.fetchUrl(url, callback, errorCallback);
}
executeSparql(sparql, callback, errorCallback) {
if (sparql.length < 1024)
this.executeSparqlGet(sparql, callback, errorCallback);
else
this.executeSparqlPost(sparql, callback, errorCallback);
}
}
/**
* Executes a SPARQL query against multiple endpoints
* and returns the results merged in a single result set
* with an extra column to express the source
*/
export class MultipleEndpointSparqlHandler {
constructor(urlFetcher, catalog, lang) {
// name of the extra column to add in the result set to express the endpoint
this.extraColumnName = "group";
this.urlFetcher = urlFetcher,
this.catalog = catalog;
this.addExtraEndpointColumn = true;
this.lang = lang;
}
executeSparql(sparql, callback, errorCallback) {
const promises = [];
for (const i in this.catalog.getServices()) {
let fetcher = new EndpointSparqlHandler(this.urlFetcher, this.catalog.getServices()[i].getEndpointURL());
promises[promises.length] = new Promise((resolve, reject) => {
fetcher.executeSparql(sparql, (data) => { resolve({ endpoint: this.catalog.getServices()[i], sparqlResult: data }); }, (error) => { reject(error); });
});
}
// then wait for all Promises
Promise.all(promises).then((values) => {
let finalResult = {};
// copy the same head as first result, with an extra "endpoint" column
finalResult.head = values[0].sparqlResult.head;
finalResult.head.vars.push(this.extraColumnName);
// prepare the "results" section
finalResult.results = {
// same distinct as first result
distinct: values[0].sparqlResult.results.distinct,
// never ordered
ordered: false,
// prepare bindings section
bindings: []
};
// then for each SPARQL results of structure {endpoint : xx, sparqlJson: {...}}
for (const v of values) {
// add an extra "endpoint" column with the endpoint at the end of each binding
finalResult.results.bindings.push(
// remap each binding to add the endpoint column at the end
// then unpack the array
...v.sparqlResult.results.bindings.map((b) => {
if (this.addExtraEndpointColumn) {
b[this.extraColumnName] = { type: "literal", value: v.endpoint.getTitle(this.lang) };
}
return b;
}));
}
// TODO : handle errors
// and then call the callback
callback(finalResult);
});
}
}
//# sourceMappingURL=SparqlHandler.js.map