Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Output RDF/JS terms #80

Merged
merged 46 commits into from
Jul 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
f6090a0
Added dependency on N3
namedgraph Mar 9, 2019
24d0e65
Added TestDataFactory which imitates the pre-RDF/JS behavior to avoid…
namedgraph Mar 10, 2019
55d9d52
Added createLangLiteral() in JISON for language literals
namedgraph Mar 10, 2019
867d9d5
Refactored TestDataFactory.literal() to differentiate between lang ta…
namedgraph Mar 10, 2019
b02b90e
Removed unused XSD constants
namedgraph Mar 10, 2019
31a0c27
Removed quotes from typed literal output
namedgraph Mar 10, 2019
06348fb
TestDataFactory.literal() quotes xsd:integer values because so does S…
namedgraph Mar 10, 2019
d9b7a9f
Added n3 1.x as dependency
namedgraph Mar 11, 2019
4cd7986
Added package-lock.json file
namedgraph Mar 11, 2019
882e73f
Removed duplicate declaration of n3 dependency
namedgraph Mar 11, 2019
2cd5b06
String literals in JISON are handled using createTypedLiteral() as well
namedgraph Mar 11, 2019
76999c6
Fix string parsing.
RubenVerborgh Mar 14, 2019
2699f0e
Set specific N3.js version.
RubenVerborgh Mar 14, 2019
c431f2d
Fix space.
RubenVerborgh Mar 14, 2019
dcf5483
Simplify true/false case.
RubenVerborgh Mar 14, 2019
44cc174
Fix bug with json representation of VALUES
simonvbrae Jul 16, 2019
d115ec6
Change parser tests to work using the N3 DataFactory
simonvbrae Jul 16, 2019
e2c6cff
Fix assert that wasn't updated
simonvbrae Jul 16, 2019
43b6218
Fix bug with RDF type url not getting output as a NamedNode
simonvbrae Jul 16, 2019
80555a1
Move comparing function to test-setup.js
simonvbrae Jul 16, 2019
5c2e6be
Fix a parser bug related to typedLiterals
simonvbrae Jul 18, 2019
8535802
Fix bug related to VALUES in query
simonvbrae Jul 18, 2019
11a30a8
Fix a bug causing namedNodes to get parsed as strings
simonvbrae Jul 18, 2019
f253fc0
Fix RDF_ constants
simonvbrae Jul 18, 2019
9b3f8c8
Change generator so tests succeed again
simonvbrae Jul 18, 2019
07a1637
Migrate from to expect from jest and add custom matcher
simonvbrae Jul 18, 2019
62f763f
Add BlankNode name prefixes support
simonvbrae Jul 19, 2019
a99aa97
Drop Node 4 support.
RubenVerborgh Jul 19, 2019
96105b7
Refrase comment for clarification
simonvbrae Jul 22, 2019
14bbeb6
Add e_ prefix only if not present
simonvbrae Jul 22, 2019
9d207e4
Add comment
simonvbrae Jul 23, 2019
28ed2a8
Code cleanup & refactoring
simonvbrae Jul 23, 2019
c976ace
Replace termToString calls that had Variable as only input
simonvbrae Jul 23, 2019
89082d5
Update tests
simonvbrae Jul 23, 2019
f510a38
Refactor so only string input to toEntity is '*'
simonvbrae Jul 23, 2019
e02b294
Refactor toEntity to manually to termToString work
simonvbrae Jul 23, 2019
ea36aa7
Remove rdf-string from dependencies
simonvbrae Jul 23, 2019
78f0ea3
Replace isString with a more strict test where possible
simonvbrae Jul 23, 2019
42e274b
Move expect to devDependencies
simonvbrae Jul 24, 2019
791ee6d
Use regex instead of substr to remove prefix
simonvbrae Jul 27, 2019
219eec7
Make matcher more strict
simonvbrae Jul 30, 2019
0028d28
Add Wildcard to parser
simonvbrae Jul 30, 2019
0c00589
Adjust generator to expect Wildcard
simonvbrae Jul 30, 2019
bca26f4
PR review changes
simonvbrae Jul 30, 2019
54f83f6
Add value property so users dont have to deal with undefined there
simonvbrae Jul 30, 2019
fa2f7a7
Code cleanup for PR
simonvbrae Jul 31, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
language: node_js
node_js:
- "4"
- "6"
- "8"
- "10"
- "12"
- "lts/*"
- "node"

before_script:
Expand Down
63 changes: 36 additions & 27 deletions lib/SparqlGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ Generator.prototype.toQuery = function (q) {
if (q.distinct)
query += 'DISTINCT ';

if (q.variables)
if (q.variables){
query += mapJoin(q.variables, undefined, function (variable) {
return isString(variable) ? this.toEntity(variable) :
'(' + this.toExpression(variable.expression) + ' AS ' + variable.variable + ')';
return isTerm(variable) ? this.toEntity(variable) :
'(' + this.toExpression(variable.expression) + ' AS ' + variableToString(variable.variable) + ')';
}, this) + ' ';
}
else if (q.template)
query += this.group(q.template, true) + this._newline;

Expand All @@ -51,7 +52,7 @@ Generator.prototype.toQuery = function (q) {
if (q.group)
query += 'GROUP BY ' + mapJoin(q.group, undefined, function (it) {
var result = isString(it.expression) ? it.expression : '(' + this.toExpression(it.expression) + ')';
return it.variable ? '(' + result + ' AS ' + it.variable + ')' : result;
return it.variable ? '(' + result + ' AS ' + variableToString(it.variable) + ')' : result;
}, this) + this._newline;
if (q.having)
query += 'HAVING (' + mapJoin(q.having, undefined, this.toExpression, this) + ')' + this._newline;
Expand Down Expand Up @@ -156,7 +157,7 @@ Generator.prototype.filter = function (filter) {
};

Generator.prototype.bind = function (bind) {
return 'BIND(' + this.toExpression(bind.expression) + ' AS ' + bind.variable + ')';
return 'BIND(' + this.toExpression(bind.expression) + ' AS ' + variableToString(bind.variable) + ')';
};

Generator.prototype.optional = function (optional) {
Expand Down Expand Up @@ -189,7 +190,7 @@ Generator.prototype.values = function (valuesList) {
return 'VALUES ' + lparen + keys.join(' ') + rparen + ' {' + this._newline +
mapJoin(valuesList.values, this._newline, function (values) {
return ' ' + lparen + mapJoin(keys, undefined, function (key) {
return values[key] !== undefined ? this.toEntity(values[key]) : 'UNDEF';
return values[key] ? this.toEntity(values[key]) : 'UNDEF';
}, this) + rparen;
}, this) + this._newline + '}';
};
Expand All @@ -201,14 +202,14 @@ Generator.prototype.service = function (service) {

// Converts the parsed expression object into a SPARQL expression
Generator.prototype.toExpression = function (expr) {
if (isString(expr))
if (isTerm(expr)) {
return this.toEntity(expr);

}
switch (expr.type.toLowerCase()) {
case 'aggregate':
return expr.aggregation.toUpperCase() +
'(' + (expr.distinct ? 'DISTINCT ' : '') + this.toExpression(expr.expression) +
(expr.separator ? '; SEPARATOR = ' + this.toEntity('"' + expr.separator + '"') : '') + ')';
(expr.separator ? '; SEPARATOR = ' + '"' + expr.separator.replace(escape, escapeReplacer) + '"' : '') + ')';
case 'functioncall':
return this.toEntity(expr.function) + '(' + mapJoin(expr.args, ', ', this.toExpression, this) + ')';
case 'operation':
Expand All @@ -227,9 +228,9 @@ Generator.prototype.toExpression = function (expr) {
case '-':
case '*':
case '/':
return (isString(args[0]) ? this.toEntity(args[0]) : '(' + this.toExpression(args[0]) + ')') +
return (isTerm(args[0]) ? this.toEntity(args[0]) : '(' + this.toExpression(args[0]) + ')') +
' ' + operator + ' ' +
(isString(args[1]) ? this.toEntity(args[1]) : '(' + this.toExpression(args[1]) + ')');
(isTerm(args[1]) ? this.toEntity(args[1]) : '(' + this.toExpression(args[1]) + ')');
// Unary operators
case '!':
return '!(' + this.toExpression(args[0]) + ')';
Expand All @@ -255,30 +256,31 @@ Generator.prototype.toExpression = function (expr) {

// Converts the parsed entity (or property path) into a SPARQL entity
Generator.prototype.toEntity = function (value) {
// regular entity
if (isString(value)) {
switch (value[0]) {
if (isTerm(value)) {
switch (value.termType) {
// variable, * selector, or blank node
case '?':
case '$':
case '*':
case '_':
return value;
case 'Wildcard':
return '*';
case 'Variable':
return variableToString(value);
case 'BlankNode':
return '_:' + value.value;
// literal
case '"':
var match = value.match(/^"([^]*)"(?:(@.+)|\^\^(.+))?$/) || {},
lexical = match[1] || '', language = match[2] || '', datatype = match[3];
value = '"' + lexical.replace(escape, escapeReplacer) + '"' + language;
if (datatype) {
if (datatype === XSD_INTEGER && /^\d+$/.test(lexical))
case 'Literal':
var lexical = value.value || '', language = value.language || '', datatype = value.datatype;
value = '"' + lexical.replace(escape, escapeReplacer) + '"';
if (language){
value += '@' + language;
} else if (datatype) {
if (datatype.value === XSD_INTEGER && /^\d+$/.test(lexical))
// Add space to avoid confusion with decimals in broken parsers
return lexical + ' ';
value += '^^' + this.encodeIRI(datatype);
value += '^^' + this.encodeIRI(datatype.value);
}
return value;
// IRI
default:
return this.encodeIRI(value);
return this.encodeIRI(value.value);
}
}
// property path
Expand Down Expand Up @@ -355,9 +357,16 @@ Generator.prototype.toUpdate = function (update) {
// Indents each line of the string
Generator.prototype.indent = function(text) { return text.replace(/^/gm, this._indent); }

function variableToString(variable){
return '?' + variable.value;
}

// Checks whether the object is a string
function isString(object) { return typeof object === 'string'; }

// Checks whether the object is a Term
function isTerm(object) { return !!object.termType; }

// Maps the array with the given function, and joins the results using the separator
function mapJoin(array, sep, func, self) {
return array.map(func, self).join(isString(sep) ? sep : ' ');
Expand Down
29 changes: 29 additions & 0 deletions lib/Wildcard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
var Term = require('n3').DataFactory.internal.Term;

// Wildcard constructor
class Wildcard extends Term {
constructor() {
super('');
return WILDCARD || this;
}

equals(other) {
return other && (this.termType === other.termType);
}
}

Object.defineProperty(Wildcard.prototype, 'value', {
enumerable: true,
value: '*',
});

Object.defineProperty(Wildcard.prototype, 'termType', {
enumerable: true,
value: 'Wildcard',
});


// Wildcard singleton
var WILDCARD = new Wildcard();

module.exports.Wildcard = Wildcard;
Loading