'use strict';
import Transport from './transport';
import Prefix from './prefix';
import GraphPattern from './graph-pattern';
import GroupGraphPattern from './group-graph-pattern';
import * as QueryTypes from './query-types';
export default class Query {
/**
* The Query is the root object for all SPARQL requests
*
* @class Query
* @constructor
* @param {String} endpoint - URL of the SPARQL endpoint
*/
constructor(endpoint) {
this.reset();
this._transport = new Transport(endpoint);
}
/**
* Sets the base IRI
*
* @method base
* @param {String} content - BASE string
*/
base(content) {
this._config.base = content;
}
/**
* Sets the prefix(es) for the query
*
* @method prefix
* @param {Prefix|String|Array} content - A single Prefix string or object or an array of Prefix objects or strings
* @returns {Query} - Returns current instance (chainable)
*/
prefix(content) {
this.addArrayOrSingle(content, this.addPrefix);
return this;
}
/**
* Add a prefix to the query
*
* @method addPrefix
* @param {Prefix|String|Array} content - A single Prefix string or object
*/
addPrefix(content) {
if (content instanceof Prefix) {
this._config.prefixes.push(content);
} else if (typeof content === 'string') {
this._config.prefixes.push(new Prefix(content));
}
}
/**
* Get the Prefix objects of the Query
*
* @method getPrefixes
* @returns {Array}
*/
getPrefixes() {
return this._config.prefixes;
}
/**
* Remove all Prefixes from the Query
*
* @method clearPrefixes
*/
clearPrefixes() {
this._config.prefixes = [];
}
/**
* Set the current query to SELECT
*
* @method select
* @param {String} content - Arguments given to the SELECT statement
* @param {String} modifier - Optional modifier to be added (e.g. DISTINCT)
* @returns {Query} - Returns current instance (chainable)
*/
select(content, modifier) {
this._config.query = new QueryTypes.Select(content, modifier);
return this;
}
/**
* Set the current query to DESCRIBE
*
* @method describe
* @param {String} content - Arguments given to the DESCRIBE statement
* @returns {Query} - Returns current instance (chainable)
*/
describe(content) {
this._config.query = new QueryTypes.Describe(content);
return this;
}
/**
* Set the current query to ASK
*
* @method ask
* @returns {Query} - Returns current instance (chainable)
*/
ask() {
this._config.query = new QueryTypes.Ask();
return this;
}
/**
* Set the current query to CONSTRUCT
*
* @method construct
* @param {Triple|Array} triples - One or more Triples to be used for a DESCRIBE GraphPattern
* @returns {Query} - Returns current instance (chainable)
*/
construct(triples) {
this._config.query = new QueryTypes.Construct(triples);
return this;
}
/**
* Set dataset clause
*
* @method from
* @param {String|Array} content - One or more strings with dataset clauses (without FROM or NAMED)
* @param {Boolean} named - Optional flag to set clause to NAMED
* @returns {Query} - Returns current instance (chainable)
*/
from(content, named = false) {
this.addArrayOrSingle(content, (element) => {
this._config.datasetClause.push(`FROM${named ? ' NAMED' : ''} ${element}`);
});
return this;
}
/**
* Get current dataset clauses
*
* @method getDatasetClauses
* @returns {Array}
*/
getDatasetClauses() {
return this._config.datasetClause;
}
/**
* Clear current dataset clauses
*
* @method clearDatasetClauses
*/
clearDatasetClauses() {
this._config.datasetClause = [];
}
/**
* Set where clause
*
* @method where
* @param {String|Array} content - A GraphPattern or a GroupGraphPattern object
* @returns {Query} - Returns current instance (chainable)
*/
where(content) {
if (content instanceof GraphPattern ||
content instanceof GroupGraphPattern) {
this._config.whereClause = content;
} else {
throw new Error('TypeError: Where clause must be a graph pattern.');
}
return this;
}
/**
* Get current where clause
*
* @method getWhereClause
* @returns {GraphPattern|GroupGraphPattern}
*/
getWhereClause() {
return this._config.whereClause;
}
/**
* Set order for query
*
* @method order
* @param {String} content - Order string without ORDER BY
* @returns {Query} - Returns current instance (chainable)
*/
order(content) {
if (typeof content === 'string') {
this._config.solutionModifiers.push(`ORDER BY ${content}`);
} else {
throw new Error(`Input for ORDER must be string but is ${typeof content}.`);
}
return this;
}
/**
* Set limit for query
*
* @method limit
* @param {Number} count - Limit count
* @returns {Query} - Returns current instance (chainable)
*/
limit(count) {
if (typeof count === 'number') {
this._config.solutionModifiers.push(`LIMIT ${count}`);
} else {
throw new Error(`Input for LIMIT must be number but is ${typeof count}.`);
}
return this;
}
/**
* Set limit for offset
*
* @method offset
* @param {Number} count - Offset count
* @returns {Query} - Returns current instance (chainable)
*/
offset(count) {
if (typeof count === 'number') {
this._config.solutionModifiers.push(`OFFSET ${count}`);
} else {
throw new Error(`Input for OFFSET must be number but is ${typeof count}.`);
}
return this;
}
/**
* Execute query
*
* @method exec
* @returns {Promise} - Returns a Promise with will yield a Result object
*/
exec() {
return this._transport.submit(this.toString());
}
/**
* Retrieves the SPARQL string representation of the current instance, adding the FILTER keyword.
*
* @method toString
* @param {Boolean} isSubquery - If set, skips the BASE and PREFIX parts for inclusion as a subquery
* @returns {String}
*/
toString(isSubQuery = false) {
var queryString = '';
if (!isSubQuery) {
if (this._config.base) {
queryString += `BASE ${this._config.base}`;
}
if (this._config.prefixes.length > 0) {
for (let prefix of this._config.prefixes) {
queryString += `${prefix.toString()} `;
}
}
}
if (this._config.query) {
queryString += this._config.query.toString();
} else {
throw new Error(`TypeError: Query type must be defined.`);
}
if (Array.isArray(this._config.datasetClause)) {
queryString += `${this._config.datasetClause.join(' ')} `;
} else {
throw new Error(`TypeError: Dataset clause should be array but is ${typeof this._config.datasetClause}`);
}
if (this._config.whereClause) {
queryString += `WHERE ${this._config.whereClause.toString()}`;
} else {
throw new Error(`TypeError: Where clause is not defined!`);
}
if (Array.isArray(this._config.solutionModifiers)) {
for (let mod of this._config.solutionModifiers) {
queryString += ` ${mod.toString()}`;
}
}
return queryString;
}
/**
* Reset query (endpoint setting stays)
*
* @method reset
*/
reset() {
this._config = {
base: null,
prefixes: [],
query: null,
subQueries: [],
datasetClause: [],
whereClause: null,
solutionModifiers: []
};
}
addArrayOrSingle(content, addFunction) {
if (Array.isArray(content)) {
for (var element of content) {
addFunction(element);
}
} else {
addFunction(content);
}
}
}