terminusdb 12.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Contributing.md +36 -0
- package/LICENSE +201 -0
- package/README.md +175 -0
- package/RELEASE_NOTES.md +462 -0
- package/dist/index.html +22 -0
- package/dist/terminusdb-client.min.js +3 -0
- package/dist/terminusdb-client.min.js.LICENSE.txt +188 -0
- package/dist/terminusdb-client.min.js.map +1 -0
- package/dist/typescript/index.d.ts +14 -0
- package/dist/typescript/lib/accessControl.d.ts +554 -0
- package/dist/typescript/lib/axiosInstance.d.ts +2 -0
- package/dist/typescript/lib/connectionConfig.d.ts +381 -0
- package/dist/typescript/lib/const.d.ts +54 -0
- package/dist/typescript/lib/dispatchRequest.d.ts +17 -0
- package/dist/typescript/lib/errorMessage.d.ts +25 -0
- package/dist/typescript/lib/query/woqlBuilder.d.ts +75 -0
- package/dist/typescript/lib/query/woqlCore.d.ts +341 -0
- package/dist/typescript/lib/query/woqlDoc.d.ts +63 -0
- package/dist/typescript/lib/query/woqlLibrary.d.ts +718 -0
- package/dist/typescript/lib/query/woqlPrinter.d.ts +71 -0
- package/dist/typescript/lib/query/woqlQuery.d.ts +833 -0
- package/dist/typescript/lib/typedef.d.ts +624 -0
- package/dist/typescript/lib/utils.d.ts +199 -0
- package/dist/typescript/lib/valueHash.d.ts +146 -0
- package/dist/typescript/lib/viewer/chartConfig.d.ts +62 -0
- package/dist/typescript/lib/viewer/chooserConfig.d.ts +38 -0
- package/dist/typescript/lib/viewer/documentFrame.d.ts +44 -0
- package/dist/typescript/lib/viewer/frameConfig.d.ts +74 -0
- package/dist/typescript/lib/viewer/frameRule.d.ts +145 -0
- package/dist/typescript/lib/viewer/graphConfig.d.ts +73 -0
- package/dist/typescript/lib/viewer/objectFrame.d.ts +212 -0
- package/dist/typescript/lib/viewer/streamConfig.d.ts +23 -0
- package/dist/typescript/lib/viewer/tableConfig.d.ts +66 -0
- package/dist/typescript/lib/viewer/terminusRule.d.ts +75 -0
- package/dist/typescript/lib/viewer/viewConfig.d.ts +47 -0
- package/dist/typescript/lib/viewer/woqlChart.d.ts +1 -0
- package/dist/typescript/lib/viewer/woqlChooser.d.ts +56 -0
- package/dist/typescript/lib/viewer/woqlGraph.d.ts +26 -0
- package/dist/typescript/lib/viewer/woqlPaging.d.ts +1 -0
- package/dist/typescript/lib/viewer/woqlResult.d.ts +128 -0
- package/dist/typescript/lib/viewer/woqlRule.d.ts +96 -0
- package/dist/typescript/lib/viewer/woqlStream.d.ts +31 -0
- package/dist/typescript/lib/viewer/woqlTable.d.ts +102 -0
- package/dist/typescript/lib/viewer/woqlView.d.ts +49 -0
- package/dist/typescript/lib/woql.d.ts +1267 -0
- package/dist/typescript/lib/woqlClient.d.ts +1216 -0
- package/index.js +28 -0
- package/lib/.eslintrc +1 -0
- package/lib/accessControl.js +988 -0
- package/lib/axiosInstance.js +5 -0
- package/lib/connectionConfig.js +765 -0
- package/lib/const.js +59 -0
- package/lib/dispatchRequest.js +236 -0
- package/lib/errorMessage.js +110 -0
- package/lib/query/woqlBuilder.js +234 -0
- package/lib/query/woqlCore.js +934 -0
- package/lib/query/woqlDoc.js +177 -0
- package/lib/query/woqlLibrary.js +1015 -0
- package/lib/query/woqlPrinter.js +476 -0
- package/lib/query/woqlQuery.js +1865 -0
- package/lib/typedef.js +248 -0
- package/lib/utils.js +817 -0
- package/lib/valueHash.js_old +581 -0
- package/lib/viewer/chartConfig.js +411 -0
- package/lib/viewer/chooserConfig.js +234 -0
- package/lib/viewer/documentFrame.js +206 -0
- package/lib/viewer/frameConfig.js +469 -0
- package/lib/viewer/frameRule.js +519 -0
- package/lib/viewer/graphConfig.js +345 -0
- package/lib/viewer/objectFrame.js +1550 -0
- package/lib/viewer/streamConfig.js +82 -0
- package/lib/viewer/tableConfig.js +310 -0
- package/lib/viewer/terminusRule.js +196 -0
- package/lib/viewer/viewConfig.js +219 -0
- package/lib/viewer/woqlChart.js +17 -0
- package/lib/viewer/woqlChooser.js +171 -0
- package/lib/viewer/woqlGraph.js +295 -0
- package/lib/viewer/woqlPaging.js +148 -0
- package/lib/viewer/woqlResult.js +258 -0
- package/lib/viewer/woqlRule.js +312 -0
- package/lib/viewer/woqlStream.js +27 -0
- package/lib/viewer/woqlTable.js +332 -0
- package/lib/viewer/woqlView.js +107 -0
- package/lib/woql.js +1693 -0
- package/lib/woqlClient.js +2091 -0
- package/package.json +110 -0
|
@@ -0,0 +1,934 @@
|
|
|
1
|
+
/* eslint-disable no-underscore-dangle */
|
|
2
|
+
/* eslint-disable no-use-before-define */
|
|
3
|
+
/* eslint-disable guard-for-in */
|
|
4
|
+
/* eslint-disable no-restricted-syntax */
|
|
5
|
+
/* eslint-disable no-unused-vars */
|
|
6
|
+
/* eslint-disable consistent-return */
|
|
7
|
+
/* eslint-disable camelcase */
|
|
8
|
+
/* eslint-disable no-redeclare */
|
|
9
|
+
/* eslint-disable no-plusplus */
|
|
10
|
+
/* eslint-disable block-scoped-var */
|
|
11
|
+
/* eslint-disable no-var */
|
|
12
|
+
/* eslint-disable vars-on-top */
|
|
13
|
+
/* eslint-disable no-param-reassign */
|
|
14
|
+
/// /@ts-check
|
|
15
|
+
const UTILS = require('../utils');
|
|
16
|
+
const WOQLPrinter = require('./woqlPrinter');
|
|
17
|
+
const { Var, Vars, Doc } = require('./woqlDoc');
|
|
18
|
+
|
|
19
|
+
// eslint-disable-next-line no-unused-vars
|
|
20
|
+
const typedef = require('../typedef');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {Object} WOQLJson - JSON-LD representation of a WOQL query
|
|
24
|
+
* @property {string} @type - The WOQL operation type
|
|
25
|
+
* @property {*} [subject] - Subject for triple patterns
|
|
26
|
+
* @property {*} [predicate] - Predicate for triple patterns
|
|
27
|
+
* @property {*} [object] - Object for triple patterns
|
|
28
|
+
* @property {WOQLJson[]} [and] - Array of queries for 'And' operations
|
|
29
|
+
* @property {WOQLJson[]} [or] - Array of queries for 'Or' operations
|
|
30
|
+
* @property {WOQLJson} [query] - Nested query
|
|
31
|
+
* @property {string[]} [variables] - Variable list for 'Select' operations
|
|
32
|
+
* @property {string} [graph] - Graph identifier
|
|
33
|
+
* @property {*} [consequent] - Consequent for path queries
|
|
34
|
+
* @property {string} [path_pattern] - Pattern for path queries
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* defines the internal functions of the woql query object - the
|
|
39
|
+
* language API is defined in WOQLQuery
|
|
40
|
+
* @module WOQLQuery
|
|
41
|
+
* @constructor
|
|
42
|
+
* @param {object} [query] json-ld query for initialisation
|
|
43
|
+
* @returns {WOQLQuery}
|
|
44
|
+
*/
|
|
45
|
+
/* function WOQLQuery(query) {
|
|
46
|
+
this.query = query || {};
|
|
47
|
+
this.errors = [];
|
|
48
|
+
this.cursor = this.query;
|
|
49
|
+
this.chain_ended = false;
|
|
50
|
+
this.contains_update = false;
|
|
51
|
+
// operators which preserve global paging
|
|
52
|
+
this.paging_transitive_properties = ['select', 'from', 'start', 'when', 'opt', 'limit'];
|
|
53
|
+
|
|
54
|
+
this.update_operators = [
|
|
55
|
+
'AddTriple',
|
|
56
|
+
'DeleteTriple',
|
|
57
|
+
'AddQuad',
|
|
58
|
+
'DeleteQuad',
|
|
59
|
+
'InsertDocument',
|
|
60
|
+
'DeleteDocument',
|
|
61
|
+
'UpdateDocument',
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
this.vocab = this.loadDefaultVocabulary();
|
|
65
|
+
// object used to accumulate triples from fragments to support usage like node("x").label("y");
|
|
66
|
+
this.tripleBuilder = false;
|
|
67
|
+
return this;
|
|
68
|
+
} */
|
|
69
|
+
|
|
70
|
+
class WOQLQuery {
|
|
71
|
+
triple_builder_context = {};
|
|
72
|
+
|
|
73
|
+
query = null;
|
|
74
|
+
|
|
75
|
+
counter = 1;
|
|
76
|
+
|
|
77
|
+
errors = [];
|
|
78
|
+
|
|
79
|
+
cursor = {};
|
|
80
|
+
|
|
81
|
+
chain_ended = false;
|
|
82
|
+
|
|
83
|
+
contains_update = false;
|
|
84
|
+
|
|
85
|
+
// operators which preserve global paging
|
|
86
|
+
paging_transitive_properties = ['select', 'from', 'start', 'when', 'opt', 'limit'];
|
|
87
|
+
|
|
88
|
+
update_operators = [
|
|
89
|
+
'AddTriple',
|
|
90
|
+
'DeleteTriple',
|
|
91
|
+
'AddQuad',
|
|
92
|
+
'DeleteQuad',
|
|
93
|
+
'InsertDocument',
|
|
94
|
+
'DeleteDocument',
|
|
95
|
+
'UpdateDocument',
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
vocab = this.loadDefaultVocabulary();
|
|
99
|
+
|
|
100
|
+
// object used to accumulate triples from fragments to support usage like node("x").label("y");
|
|
101
|
+
tripleBuilder = false;
|
|
102
|
+
/**
|
|
103
|
+
* defines the internal functions of the woql query object - the
|
|
104
|
+
* language API is defined in WOQLQuery
|
|
105
|
+
* @module WOQLQuery
|
|
106
|
+
* @constructor
|
|
107
|
+
* @param {object} [query] json-ld query for initialisation
|
|
108
|
+
* @returns {WOQLQuery}
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
constructor(query) {
|
|
112
|
+
this.query = query || {};
|
|
113
|
+
// this.errors = [];
|
|
114
|
+
this.cursor = this.query;
|
|
115
|
+
|
|
116
|
+
// eslint-disable-next-line no-constructor-return
|
|
117
|
+
return this;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Basic Error handling
|
|
123
|
+
*/
|
|
124
|
+
WOQLQuery.prototype.parameterError = function (msg) {
|
|
125
|
+
this.errors.push({ type: this.cursor['@type'], message: msg });
|
|
126
|
+
return this;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
WOQLQuery.prototype.hasErrors = function () {
|
|
130
|
+
return this.errors.length > 0;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Internal library function which adds a subquery and sets the cursor
|
|
135
|
+
*/
|
|
136
|
+
WOQLQuery.prototype.addSubQuery = function (Subq) {
|
|
137
|
+
if (Subq) {
|
|
138
|
+
this.cursor.query = this.jobj(Subq);
|
|
139
|
+
} else {
|
|
140
|
+
const nv = {};
|
|
141
|
+
this.cursor.query = nv;
|
|
142
|
+
this.cursor = nv;
|
|
143
|
+
}
|
|
144
|
+
return this;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Does this query contain an update
|
|
149
|
+
*/
|
|
150
|
+
WOQLQuery.prototype.containsUpdate = function (json) {
|
|
151
|
+
json = json || this.query;
|
|
152
|
+
if (this.update_operators.indexOf(json['@type']) !== -1) return true;
|
|
153
|
+
if (json.consequent && this.containsUpdate(json.consequent)) return true;
|
|
154
|
+
if (json.query) return this.containsUpdate(json.query);
|
|
155
|
+
if (json.and) {
|
|
156
|
+
for (var i = 0; i < json.and.length; i++) {
|
|
157
|
+
if (this.containsUpdate(json.and[i])) return true;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (json.or) {
|
|
161
|
+
for (var i = 0; i < json.or.length; i++) {
|
|
162
|
+
if (this.containsUpdate(json.or[i])) return true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return false;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Called to inidicate that this query will cause an update to the DB
|
|
171
|
+
*/
|
|
172
|
+
WOQLQuery.prototype.updated = function () {
|
|
173
|
+
this.contains_update = true;
|
|
174
|
+
return this;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* A bunch of internal functions for formatting values for JSON-LD translation
|
|
179
|
+
*/
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Wraps the passed value in a json-ld literal carriage
|
|
183
|
+
*/
|
|
184
|
+
WOQLQuery.prototype.jlt = function (val, type) {
|
|
185
|
+
if (!type) type = 'xsd:string';
|
|
186
|
+
else type = type.indexOf(':') === -1 ? `xsd:${type}` : type;
|
|
187
|
+
return { '@type': type, '@value': val };
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
WOQLQuery.prototype.varj = function (varb) {
|
|
191
|
+
if (varb instanceof Var) varb = varb.name;
|
|
192
|
+
if (varb.substring(0, 2) === 'v:') varb = varb.substring(2);
|
|
193
|
+
if (typeof varb === 'string') {
|
|
194
|
+
return {
|
|
195
|
+
'@type': 'Value',
|
|
196
|
+
variable: varb,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
return varb;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
WOQLQuery.prototype.rawVar = function (varb) {
|
|
203
|
+
if (varb instanceof Var) return varb.name;
|
|
204
|
+
if (varb.substring(0, 2) === 'v:') varb = varb.substring(2);
|
|
205
|
+
return varb;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
WOQLQuery.prototype.rawVarList = function (vl) {
|
|
209
|
+
const ret = [];
|
|
210
|
+
for (let i = 0; i < vl.length; i++) {
|
|
211
|
+
const co = this.rawVar(vl[i]);
|
|
212
|
+
ret.push(co);
|
|
213
|
+
}
|
|
214
|
+
return ret;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Transforms a javascript representation of a query into a json object if needs be
|
|
219
|
+
*/
|
|
220
|
+
WOQLQuery.prototype.jobj = function (qobj) {
|
|
221
|
+
if (qobj.json) {
|
|
222
|
+
return qobj.json();
|
|
223
|
+
}
|
|
224
|
+
if (qobj === true) return { '@type': 'True' };
|
|
225
|
+
return qobj;
|
|
226
|
+
// return new WOQLQuery.json(qobj);
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Wraps the elements of an AS variable in the appropriate json-ld
|
|
231
|
+
*/
|
|
232
|
+
WOQLQuery.prototype.asv = function (colname_or_index, variable, type) {
|
|
233
|
+
const asvar = {};
|
|
234
|
+
if (typeof colname_or_index === 'number') {
|
|
235
|
+
asvar['@type'] = 'Column';
|
|
236
|
+
asvar.indicator = { '@type': 'Indicator', index: colname_or_index };
|
|
237
|
+
} else if (typeof colname_or_index === 'string') {
|
|
238
|
+
asvar['@type'] = 'Column';
|
|
239
|
+
asvar.indicator = { '@type': 'Indicator', name: colname_or_index };
|
|
240
|
+
}
|
|
241
|
+
if (variable instanceof Var) {
|
|
242
|
+
asvar.variable = variable.name;
|
|
243
|
+
} else if (variable.substring(0, 2) === 'v:') {
|
|
244
|
+
asvar.variable = variable.substring(2);
|
|
245
|
+
} else {
|
|
246
|
+
asvar.variable = variable;
|
|
247
|
+
}
|
|
248
|
+
if (type) asvar.type = type;
|
|
249
|
+
return asvar;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* JSON LD Format Descriptor
|
|
254
|
+
* @param {object} opts
|
|
255
|
+
*/
|
|
256
|
+
WOQLQuery.prototype.wform = function (opts) {
|
|
257
|
+
if (opts && opts.type) {
|
|
258
|
+
this.cursor.format = {
|
|
259
|
+
'@type': 'Format',
|
|
260
|
+
format_type: { '@value': opts.type, '@type': 'xsd:string' },
|
|
261
|
+
};
|
|
262
|
+
if (typeof opts.format_header !== 'undefined') {
|
|
263
|
+
const h = !!opts.format_header;
|
|
264
|
+
this.cursor.format.format_header = {
|
|
265
|
+
'@value': h,
|
|
266
|
+
'@type': 'xsd:boolean',
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return this;
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Wraps arithmetic operators in the appropriate json-ld
|
|
275
|
+
*/
|
|
276
|
+
WOQLQuery.prototype.arop = function (arg) {
|
|
277
|
+
if (typeof arg === 'object') {
|
|
278
|
+
return this.jobj(this.cleanArithmeticValue(arg));
|
|
279
|
+
}
|
|
280
|
+
return this.cleanArithmeticValue(arg, 'xsd:decimal');
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* takes input that can be either a string (variable name)
|
|
285
|
+
* or an array - each element of the array is a member of the list
|
|
286
|
+
*/
|
|
287
|
+
WOQLQuery.prototype.dataList = function (wvar, string_only) {
|
|
288
|
+
if (typeof wvar === 'string') return this.expandDataVariable(wvar, true);
|
|
289
|
+
if (Array.isArray(wvar)) {
|
|
290
|
+
const ret = [];
|
|
291
|
+
for (let i = 0; i < wvar.length; i++) {
|
|
292
|
+
const co = this.cleanDataValue(wvar[i]);
|
|
293
|
+
ret.push(co);
|
|
294
|
+
}
|
|
295
|
+
return ret;
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* takes a list of input that can be any value
|
|
301
|
+
*/
|
|
302
|
+
WOQLQuery.prototype.valueList = function (wvar, string_only) {
|
|
303
|
+
if (typeof wvar === 'string') return this.expandValueVariable(wvar, true);
|
|
304
|
+
if (Array.isArray(wvar)) {
|
|
305
|
+
const ret = [];
|
|
306
|
+
for (let i = 0; i < wvar.length; i++) {
|
|
307
|
+
let co = this.cleanObject(wvar[i]);
|
|
308
|
+
if (typeof co === 'string') co = { node: co };
|
|
309
|
+
ret.push(co);
|
|
310
|
+
}
|
|
311
|
+
return ret;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* creates an unadorned variable name list
|
|
317
|
+
*/
|
|
318
|
+
WOQLQuery.prototype.vlist = function (list) {
|
|
319
|
+
const vl = [];
|
|
320
|
+
for (let i = 0; i < list.length; i++) {
|
|
321
|
+
const v = this.expandValueVariable(list[i]);
|
|
322
|
+
vl.push(v.variable);
|
|
323
|
+
}
|
|
324
|
+
return vl;
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Wraps data values
|
|
329
|
+
*/
|
|
330
|
+
WOQLQuery.prototype.dataValueList = function (list) {
|
|
331
|
+
const dvl = [];
|
|
332
|
+
for (let i = 0; i < list.length; i++) {
|
|
333
|
+
const o = this.cleanDataValue(list[i]);
|
|
334
|
+
dvl.push(o);
|
|
335
|
+
}
|
|
336
|
+
return dvl;
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Transforms whatever is passed in as the subject into the appropriate json-ld for variable or id
|
|
341
|
+
*/
|
|
342
|
+
WOQLQuery.prototype.cleanSubject = function (s) {
|
|
343
|
+
/**
|
|
344
|
+
* @type {any}
|
|
345
|
+
*/
|
|
346
|
+
let subj = false;
|
|
347
|
+
if (s instanceof Var) {
|
|
348
|
+
return this.expandNodeVariable(s);
|
|
349
|
+
} if (typeof s === 'object') {
|
|
350
|
+
return s;
|
|
351
|
+
} if (typeof s === 'string') {
|
|
352
|
+
if (s.indexOf('v:') !== -1) subj = s;
|
|
353
|
+
else subj = s;
|
|
354
|
+
return this.expandNodeVariable(subj);
|
|
355
|
+
}
|
|
356
|
+
this.parameterError('Subject must be a URI string');
|
|
357
|
+
return `${s}`;
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Transforms whatever is passed in as the predicate (id or variable) into the
|
|
362
|
+
* appropriate json-ld form
|
|
363
|
+
*/
|
|
364
|
+
WOQLQuery.prototype.cleanPredicate = function (p) {
|
|
365
|
+
/**
|
|
366
|
+
* @type {any}
|
|
367
|
+
*/
|
|
368
|
+
let pred = false;
|
|
369
|
+
if (p instanceof Var) return this.expandNodeVariable(p);
|
|
370
|
+
if (typeof p === 'object') return p;
|
|
371
|
+
if (typeof p !== 'string') {
|
|
372
|
+
this.parameterError('Predicate must be a URI string');
|
|
373
|
+
return `${p}`;
|
|
374
|
+
}
|
|
375
|
+
if (p.indexOf(':') !== -1) pred = p;
|
|
376
|
+
else if (this.wellKnownPredicate(p)) pred = p;// this.vocab[p]
|
|
377
|
+
else pred = p;// 'scm'
|
|
378
|
+
// else pred = 'scm:' + p
|
|
379
|
+
return this.expandNodeVariable(pred);
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
WOQLQuery.prototype.wellKnownPredicate = function (p, noxsd) {
|
|
383
|
+
if (this.vocab && this.vocab[p]) {
|
|
384
|
+
const full = this.vocab[p];
|
|
385
|
+
const start = full.substring(0, 3);
|
|
386
|
+
if (full === 'system:abstract' || start === 'xdd' || start === 'xsd') return false;
|
|
387
|
+
return true;
|
|
388
|
+
}
|
|
389
|
+
return false;
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
WOQLQuery.prototype.cleanPathPredicate = function (p) {
|
|
393
|
+
let pred = false;
|
|
394
|
+
if (p.indexOf(':') !== -1) pred = p;
|
|
395
|
+
else if (this.wellKnownPredicate(p)) pred = this.vocab[p];
|
|
396
|
+
else pred = p; // 'scm:' + p
|
|
397
|
+
return pred;
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Transforms whatever is passed in as the object of
|
|
402
|
+
* a triple into the appropriate json-ld form (variable, literal or id)
|
|
403
|
+
*/
|
|
404
|
+
WOQLQuery.prototype.cleanObject = function (o, t) {
|
|
405
|
+
const obj = { '@type': 'Value' };
|
|
406
|
+
if (o instanceof Var) {
|
|
407
|
+
return this.expandValueVariable(o);
|
|
408
|
+
} if (o instanceof Doc) {
|
|
409
|
+
return o.encoded;
|
|
410
|
+
} if (typeof o === 'string') {
|
|
411
|
+
if (o.indexOf('v:') !== -1) {
|
|
412
|
+
return this.expandValueVariable(o);
|
|
413
|
+
}
|
|
414
|
+
obj.node = o;
|
|
415
|
+
} else if (typeof o === 'number') {
|
|
416
|
+
t = t || 'xsd:decimal';
|
|
417
|
+
obj.data = this.jlt(o, t);
|
|
418
|
+
} else if (typeof o === 'boolean') {
|
|
419
|
+
t = t || 'xsd:boolean';
|
|
420
|
+
obj.data = this.jlt(o, t);
|
|
421
|
+
} else if (Array.isArray(o)) {
|
|
422
|
+
const res = [];
|
|
423
|
+
for (let i = 0; i < o.length; i++) {
|
|
424
|
+
res.push(this.cleanObject(o[i]));
|
|
425
|
+
}
|
|
426
|
+
obj.list = res;
|
|
427
|
+
} else if (typeof o === 'object' && o) {
|
|
428
|
+
if (typeof o['@value'] !== 'undefined') {
|
|
429
|
+
obj.data = o;
|
|
430
|
+
} else {
|
|
431
|
+
return o;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return obj;
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
WOQLQuery.prototype.cleanDataValue = function (o, t) {
|
|
438
|
+
const obj = { '@type': 'DataValue' };
|
|
439
|
+
if (o instanceof Var) {
|
|
440
|
+
return this.expandDataVariable(o);
|
|
441
|
+
}
|
|
442
|
+
if (o instanceof Doc) {
|
|
443
|
+
return o.encoded;
|
|
444
|
+
}
|
|
445
|
+
if (typeof o === 'string') {
|
|
446
|
+
if (o.indexOf('v:') !== -1) {
|
|
447
|
+
return this.expandDataVariable(o);
|
|
448
|
+
}
|
|
449
|
+
obj.data = this.jlt(o, t);
|
|
450
|
+
} else if (typeof o === 'number') {
|
|
451
|
+
t = t || 'xsd:decimal';
|
|
452
|
+
obj.data = this.jlt(o, t);
|
|
453
|
+
} else if (typeof o === 'boolean') {
|
|
454
|
+
t = t || 'xsd:boolean';
|
|
455
|
+
obj.data = this.jlt(o, t);
|
|
456
|
+
} else if (Array.isArray(o)) {
|
|
457
|
+
const res = [];
|
|
458
|
+
for (let i = 0; i < o.length; i++) {
|
|
459
|
+
res.push(this.cleanDataValue(o[i]));
|
|
460
|
+
}
|
|
461
|
+
obj.list = res;
|
|
462
|
+
} else if (typeof o === 'object' && o) {
|
|
463
|
+
if (o['@value']) obj.data = o;
|
|
464
|
+
else return o;
|
|
465
|
+
}
|
|
466
|
+
return obj;
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
WOQLQuery.prototype.cleanArithmeticValue = function (o, t) {
|
|
470
|
+
const obj = { '@type': 'ArithmeticValue' };
|
|
471
|
+
if (o instanceof Var) {
|
|
472
|
+
return this.expandArithmeticVariable(o);
|
|
473
|
+
} if (typeof o === 'string') {
|
|
474
|
+
if (o.indexOf('v:') !== -1) {
|
|
475
|
+
return this.expandArithmeticVariable(o);
|
|
476
|
+
}
|
|
477
|
+
obj.data = this.jlt(o, t);
|
|
478
|
+
} else if (typeof o === 'number') {
|
|
479
|
+
t = t || 'xsd:decimal';
|
|
480
|
+
obj.data = this.jlt(o, t);
|
|
481
|
+
} else if (typeof o === 'object' && o) {
|
|
482
|
+
if (o['@value']) obj.data = o;
|
|
483
|
+
else return o;
|
|
484
|
+
}
|
|
485
|
+
return obj;
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
WOQLQuery.prototype.cleanNodeValue = function (o, t) {
|
|
489
|
+
const obj = { '@type': 'NodeValue' };
|
|
490
|
+
if (o instanceof Var) {
|
|
491
|
+
return this.expandNodeVariable(o);
|
|
492
|
+
} if (typeof o === 'string') {
|
|
493
|
+
if (o.indexOf('v:') !== -1) {
|
|
494
|
+
return this.expandNodeVariable(o);
|
|
495
|
+
}
|
|
496
|
+
obj.node = o;
|
|
497
|
+
} else if (typeof o === 'object' && o) {
|
|
498
|
+
return o;
|
|
499
|
+
}
|
|
500
|
+
return obj;
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Transforms a graph filter or graph id into the proper json-ld form
|
|
505
|
+
*/
|
|
506
|
+
WOQLQuery.prototype.cleanGraph = function (g) {
|
|
507
|
+
return g;
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Transforms strings that start with v: into variable json-ld structures
|
|
512
|
+
* @param varname - will be transformed if it starts with v:
|
|
513
|
+
*/
|
|
514
|
+
WOQLQuery.prototype.expandVariable = function (varname, type, always) {
|
|
515
|
+
if (varname instanceof Var) {
|
|
516
|
+
return {
|
|
517
|
+
'@type': type,
|
|
518
|
+
variable: varname.name,
|
|
519
|
+
};
|
|
520
|
+
} if (varname.substring(0, 2) === 'v:' || always) {
|
|
521
|
+
if (varname.substring(0, 2) === 'v:') varname = varname.substring(2);
|
|
522
|
+
return {
|
|
523
|
+
'@type': type,
|
|
524
|
+
variable: varname,
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
return {
|
|
528
|
+
'@type': type,
|
|
529
|
+
node: varname,
|
|
530
|
+
};
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
WOQLQuery.prototype.expandValueVariable = function (varname, always) {
|
|
534
|
+
return this.expandVariable(varname, 'Value', always);
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
WOQLQuery.prototype.expandNodeVariable = function (varname, always) {
|
|
538
|
+
return this.expandVariable(varname, 'NodeValue', always);
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
WOQLQuery.prototype.expandDataVariable = function (varname, always) {
|
|
542
|
+
return this.expandVariable(varname, 'DataValue', always);
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
WOQLQuery.prototype.expandArithmeticVariable = function (varname, always) {
|
|
546
|
+
return this.expandVariable(varname, 'ArithmeticValue', always);
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
WOQLQuery.prototype.defaultContext = function (DB_IRI) {
|
|
550
|
+
const def = {};
|
|
551
|
+
for (const pref in UTILS.standard_urls) {
|
|
552
|
+
def[pref] = UTILS.standard_urls[pref];
|
|
553
|
+
}
|
|
554
|
+
def.scm = `${DB_IRI}/schema#`;
|
|
555
|
+
def.doc = `${DB_IRI}/data/`;
|
|
556
|
+
return def;
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Retrieves the value of the current json-ld context
|
|
561
|
+
*/
|
|
562
|
+
WOQLQuery.prototype.getContext = function (q) {
|
|
563
|
+
q = q || this.query;
|
|
564
|
+
for (const prop of Object.keys(q)) {
|
|
565
|
+
if (prop === '@context') return q[prop];
|
|
566
|
+
if (this.paging_transitive_properties.indexOf(prop) !== -1) {
|
|
567
|
+
const nq = q[prop][1];
|
|
568
|
+
const nc = this.getContext(nq);
|
|
569
|
+
if (nc) return nc;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* sets the value of the current json-ld context on a full query scope
|
|
576
|
+
*/
|
|
577
|
+
WOQLQuery.prototype.context = function (c) {
|
|
578
|
+
this.query['@context'] = c;
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* vocabulary elements that can be used without prefixes in woql.js queries
|
|
583
|
+
*/
|
|
584
|
+
WOQLQuery.prototype.loadDefaultVocabulary = function () {
|
|
585
|
+
const vocab = {};
|
|
586
|
+
// vocab.type = 'rdf:type'
|
|
587
|
+
// vocab.label = 'rdfs:label'
|
|
588
|
+
vocab.Class = 'owl:Class';
|
|
589
|
+
vocab.DatatypeProperty = 'owl:DatatypeProperty';
|
|
590
|
+
vocab.ObjectProperty = 'owl:ObjectProperty';
|
|
591
|
+
vocab.Document = 'system:Document';
|
|
592
|
+
vocab.abstract = 'system:abstract';
|
|
593
|
+
vocab.comment = 'rdfs:comment';
|
|
594
|
+
vocab.range = 'rdfs:range';
|
|
595
|
+
vocab.domain = 'rdfs:domain';
|
|
596
|
+
vocab.subClassOf = 'rdfs:subClassOf';
|
|
597
|
+
vocab.string = 'xsd:string';
|
|
598
|
+
vocab.integer = 'xsd:integer';
|
|
599
|
+
vocab.decimal = 'xsd:decimal';
|
|
600
|
+
vocab.boolean = 'xdd:boolean';
|
|
601
|
+
vocab.email = 'xdd:email';
|
|
602
|
+
vocab.json = 'xdd:json';
|
|
603
|
+
vocab.dateTime = 'xsd:dateTime';
|
|
604
|
+
vocab.date = 'xsd:date';
|
|
605
|
+
vocab.coordinate = 'xdd:coordinate';
|
|
606
|
+
vocab.line = 'xdd:coordinatePolyline';
|
|
607
|
+
vocab.polygon = 'xdd:coordinatePolygon';
|
|
608
|
+
return vocab;
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Provides the query with a 'vocabulary' a list of well known predicates that can be used without
|
|
613
|
+
* prefixes mapping: id: prefix:id ...
|
|
614
|
+
*/
|
|
615
|
+
WOQLQuery.prototype.setVocabulary = function (vocab) {
|
|
616
|
+
this.vocab = vocab;
|
|
617
|
+
};
|
|
618
|
+
|
|
619
|
+
WOQLQuery.prototype.getVocabulary = function (vocab) {
|
|
620
|
+
return this.vocab;
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Use instead woqlclient.query('myWOQLQuery')
|
|
625
|
+
* @deprecated
|
|
626
|
+
* Executes the query using the passed client to connect to a server
|
|
627
|
+
*
|
|
628
|
+
*/
|
|
629
|
+
WOQLQuery.prototype.execute = function (client, commit_msg) {
|
|
630
|
+
return client.query(this, commit_msg);
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* converts back and forward from json
|
|
635
|
+
* if the argument is present, the current query is set to it,
|
|
636
|
+
* if the argument is not present, the current json version of this query is returned
|
|
637
|
+
* @param {WOQLJson} [json] - a query in json format
|
|
638
|
+
* @returns {WOQLQuery | WOQLJson} Returns WOQLQuery when setting (for chaining),
|
|
639
|
+
* or WOQLJson when getting
|
|
640
|
+
*/
|
|
641
|
+
WOQLQuery.prototype.json = function (json) {
|
|
642
|
+
if (json) {
|
|
643
|
+
this.query = copyJSON(json);
|
|
644
|
+
return this;
|
|
645
|
+
}
|
|
646
|
+
return copyJSON(this.query, true);
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Returns a script version of the query
|
|
651
|
+
*
|
|
652
|
+
* @param {string} [clang] - either "js" or "python"
|
|
653
|
+
*/
|
|
654
|
+
WOQLQuery.prototype.prettyPrint = function (clang = 'js') {
|
|
655
|
+
const printer = new WOQLPrinter(this.vocab, clang);
|
|
656
|
+
return printer.printJSON(this.query);
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Finds the last woql element that has a subject in it and returns the json for that
|
|
661
|
+
* used for triplebuilder to chain further calls - when they may be inside ands or ors or subqueries
|
|
662
|
+
* @param {object} json
|
|
663
|
+
*/
|
|
664
|
+
WOQLQuery.prototype.findLastSubject = function (json) {
|
|
665
|
+
if (json && json.and) {
|
|
666
|
+
for (var i = json.and.length - 1; i >= 0; i--) {
|
|
667
|
+
const lqs = this.findLastSubject(json.and[i]);
|
|
668
|
+
if (lqs) return lqs;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
if (json && json.or) {
|
|
672
|
+
for (var i = json.or.length - 1; i >= 0; i--) {
|
|
673
|
+
const lqs = this.findLastSubject(json.or[i]);
|
|
674
|
+
if (lqs) return lqs;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (json && json.query) {
|
|
678
|
+
const ls = this.findLastSubject(json.query);
|
|
679
|
+
if (ls) return ls;
|
|
680
|
+
}
|
|
681
|
+
// check for cardinality here
|
|
682
|
+
if (json && json.subject) {
|
|
683
|
+
return json;
|
|
684
|
+
}
|
|
685
|
+
return false;
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Finds the last woql element that has a subject in that is a property id
|
|
690
|
+
* used for triplebuilder to chain further calls - when they may be inside ands or ors or subqueries
|
|
691
|
+
* @param {object} json
|
|
692
|
+
*/
|
|
693
|
+
WOQLQuery.prototype.findLastProperty = function (json) {
|
|
694
|
+
if (json && json.and) {
|
|
695
|
+
for (var i = json.and.length - 1; i >= 0; i--) {
|
|
696
|
+
const lqs = this.findLastProperty(json.and[i]);
|
|
697
|
+
if (lqs) return lqs;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
if (json && json.or) {
|
|
701
|
+
for (var i = json.or.length - 1; i >= 0; i--) {
|
|
702
|
+
const lqs = this.findLastProperty(json.or[i]);
|
|
703
|
+
if (lqs) return lqs;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
if (json && json.query) {
|
|
707
|
+
const ls = this.findLastProperty(json.query);
|
|
708
|
+
if (ls) return ls;
|
|
709
|
+
}
|
|
710
|
+
if (
|
|
711
|
+
json
|
|
712
|
+
&& json.subject
|
|
713
|
+
&& this._is_property_triple(json.predicate, json.object)
|
|
714
|
+
) {
|
|
715
|
+
return json;
|
|
716
|
+
}
|
|
717
|
+
return false;
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
WOQLQuery.prototype._is_property_triple = function (pred, obj) {
|
|
721
|
+
const pred_str = pred.node ? pred.node : pred;
|
|
722
|
+
const obj_str = obj.node ? obj.node : obj;
|
|
723
|
+
if (obj_str === 'owl:ObjectProperty' || obj_str === 'owl:DatatypeProperty') return true;
|
|
724
|
+
if (pred_str === 'rdfs:domain' || pred_str === 'rdfs:range') return true;
|
|
725
|
+
return false;
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* Turns a textual path pattern into a JSON-LD description
|
|
730
|
+
*/
|
|
731
|
+
WOQLQuery.prototype.compilePathPattern = function (pat) {
|
|
732
|
+
const toks = tokenize(pat);
|
|
733
|
+
if (toks && toks.length) return tokensToJSON(toks, this);
|
|
734
|
+
this.parameterError(`Pattern error - could not be parsed ${pat}`);
|
|
735
|
+
};
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Tokenizes the pattern into a sequence of tokens which may be clauses or operators
|
|
739
|
+
* @param {string} pat
|
|
740
|
+
*/
|
|
741
|
+
function tokenize(pat) {
|
|
742
|
+
let parts = getClauseAndRemainder(pat);
|
|
743
|
+
const seq = [];
|
|
744
|
+
while (parts.length === 2) {
|
|
745
|
+
seq.push(parts[0]);
|
|
746
|
+
parts = getClauseAndRemainder(parts[1]);
|
|
747
|
+
}
|
|
748
|
+
seq.push(parts[0]);
|
|
749
|
+
return seq;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/**
|
|
753
|
+
* Breaks a graph pattern up into two parts - the next clause, and the remainder of the string
|
|
754
|
+
* @param {string} pat - graph pattern fragment
|
|
755
|
+
*/
|
|
756
|
+
function getClauseAndRemainder(pat) {
|
|
757
|
+
pat = pat.trim();
|
|
758
|
+
let open = 1;
|
|
759
|
+
// if there is a parentheses, we treat it as a clause and go to the end
|
|
760
|
+
if (pat.charAt(0) === '(') {
|
|
761
|
+
for (var i = 1; i < pat.length; i++) {
|
|
762
|
+
if (pat.charAt(i) === '(') open++;
|
|
763
|
+
else if (pat.charAt(i) === ')') open--;
|
|
764
|
+
if (open === 0) {
|
|
765
|
+
const rem = pat.substring(i + 1).trim();
|
|
766
|
+
if (rem) return [pat.substring(1, i), rem];
|
|
767
|
+
// eslint-disable-next-line max-len
|
|
768
|
+
return getClauseAndRemainder(pat.substring(1, i)); // whole thing surrounded by parentheses, strip them out and reparse
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
return [];
|
|
772
|
+
}
|
|
773
|
+
if (pat[0] === '+' || pat[0] === ',' || pat[0] === '|' || pat[0] === '*') {
|
|
774
|
+
const ret = [pat[0]];
|
|
775
|
+
if (pat.substring(1)) ret.push(pat.substring(1));
|
|
776
|
+
return ret;
|
|
777
|
+
}
|
|
778
|
+
if (pat.charAt(0) === '{') {
|
|
779
|
+
const ret = [pat.substring(0, pat.indexOf('}') + 1)];
|
|
780
|
+
if (pat.substring(pat.indexOf('}') + 1)) ret.push(pat.substring(pat.indexOf('}') + 1));
|
|
781
|
+
return ret;
|
|
782
|
+
}
|
|
783
|
+
for (var i = 1; i < pat.length; i++) {
|
|
784
|
+
if (pat[i] === ',' || pat[i] === '|' || pat[i] === '+' || pat[i] === '{' || pat[i] === '*') return [pat.substring(0, i), pat.substring(i)];
|
|
785
|
+
}
|
|
786
|
+
return [pat];
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
function compilePredicate(pp, q) {
|
|
790
|
+
if (pp.indexOf('<') !== -1 && pp.indexOf('>') !== -1) {
|
|
791
|
+
const pred = pp.slice(1, pp.length - 1);
|
|
792
|
+
// eslint-disable-next-line no-multi-assign,no-constant-condition
|
|
793
|
+
const cleaned = pred === '.' ? null : q.cleanPathPredicate(pred);
|
|
794
|
+
return {
|
|
795
|
+
'@type': 'PathOr',
|
|
796
|
+
or: [{
|
|
797
|
+
'@type': 'InversePathPredicate',
|
|
798
|
+
predicate: cleaned,
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
'@type': 'PathPredicate',
|
|
802
|
+
predicate: cleaned,
|
|
803
|
+
}],
|
|
804
|
+
};
|
|
805
|
+
} if (pp.indexOf('<') !== -1) {
|
|
806
|
+
const pred = pp.slice(1, pp.length);
|
|
807
|
+
const cleaned = pred === '.' ? null : q.cleanPathPredicate(pred);
|
|
808
|
+
return { '@type': 'InversePathPredicate', predicate: cleaned };
|
|
809
|
+
} if (pp.indexOf('>') !== -1) {
|
|
810
|
+
const pred = pp.slice(0, pp.length - 1);
|
|
811
|
+
const cleaned = pred === '.' ? null : q.cleanPathPredicate(pred);
|
|
812
|
+
return { '@type': 'PathPredicate', predicate: cleaned };
|
|
813
|
+
}
|
|
814
|
+
const cleaned = pp === '.' ? null : q.cleanPathPredicate(pp);
|
|
815
|
+
return { '@type': 'PathPredicate', predicate: cleaned };
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* Turns a sequence of tokens into the appropriate JSON-LD
|
|
820
|
+
* @param {Array} seq
|
|
821
|
+
* @param {*} q
|
|
822
|
+
*/
|
|
823
|
+
function tokensToJSON(seq, q) {
|
|
824
|
+
if (seq.length === 1) {
|
|
825
|
+
// may need to be further tokenized
|
|
826
|
+
const ntoks = tokenize(seq[0]);
|
|
827
|
+
if (ntoks.length === 1) {
|
|
828
|
+
// only a single element in clause - cannot be further tokenised
|
|
829
|
+
const tok = ntoks[0].trim();
|
|
830
|
+
return compilePredicate(tok, q);
|
|
831
|
+
}
|
|
832
|
+
return tokensToJSON(ntoks, q);
|
|
833
|
+
} if (seq.indexOf('|') !== -1) {
|
|
834
|
+
// binds most loosely
|
|
835
|
+
const left = seq.slice(0, seq.indexOf('|'));
|
|
836
|
+
const right = seq.slice(seq.indexOf('|') + 1);
|
|
837
|
+
return {
|
|
838
|
+
'@type': 'PathOr',
|
|
839
|
+
or: [tokensToJSON(left, q), tokensToJSON(right, q)],
|
|
840
|
+
};
|
|
841
|
+
} if (seq.indexOf(',') !== -1) {
|
|
842
|
+
// binds tighter
|
|
843
|
+
const first = seq.slice(0, seq.indexOf(','));
|
|
844
|
+
const second = seq.slice(seq.indexOf(',') + 1);
|
|
845
|
+
return {
|
|
846
|
+
'@type': 'PathSequence',
|
|
847
|
+
sequence: [tokensToJSON(first, q), tokensToJSON(second, q)],
|
|
848
|
+
};
|
|
849
|
+
} if (seq[1] === '+') {
|
|
850
|
+
// binds tightest of all
|
|
851
|
+
return {
|
|
852
|
+
'@type': 'PathPlus',
|
|
853
|
+
plus: tokensToJSON([seq[0]], q),
|
|
854
|
+
};
|
|
855
|
+
} if (seq[1] === '*') {
|
|
856
|
+
// binds tightest of all
|
|
857
|
+
return {
|
|
858
|
+
'@type': 'PathStar',
|
|
859
|
+
star: tokensToJSON([seq[0]], q),
|
|
860
|
+
};
|
|
861
|
+
} if (seq[1].charAt(0) === '{') {
|
|
862
|
+
// binds tightest of all
|
|
863
|
+
// we need a test here
|
|
864
|
+
const meat = seq[1].substring(1, seq[1].length - 1).split(',');
|
|
865
|
+
return {
|
|
866
|
+
'@type': 'PathTimes',
|
|
867
|
+
from: meat[0],
|
|
868
|
+
to: meat[1],
|
|
869
|
+
times: tokensToJSON([seq[0]], q),
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
// shouldn't get here - error
|
|
873
|
+
q.parameterError(`Pattern error - could not be parsed ${seq[0]}`);
|
|
874
|
+
return {
|
|
875
|
+
'@type': 'PathPredicate',
|
|
876
|
+
'rdfs:label': `failed to parse query ${seq[0]}`,
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Creates a copy of the passed json representation of a woql query
|
|
882
|
+
* Performing tidying up in doing so - strips out empty queries, rolls up
|
|
883
|
+
* ands and ors with single entries
|
|
884
|
+
*
|
|
885
|
+
* @param {object} orig
|
|
886
|
+
* @returns {object} copy of the passed json object
|
|
887
|
+
*/
|
|
888
|
+
function copyJSON(orig, rollup) {
|
|
889
|
+
if (Array.isArray(orig)) return orig;
|
|
890
|
+
if (rollup) {
|
|
891
|
+
if (orig['@type'] === 'And') {
|
|
892
|
+
if (!orig.and || !orig.and.length) return {};
|
|
893
|
+
if (orig.and.length === 1) return copyJSON(orig.and[0], rollup);
|
|
894
|
+
} else if (orig['@type'] === 'Or') {
|
|
895
|
+
if (!orig.or || !orig.or.length) return {};
|
|
896
|
+
if (orig.or.length === 1) return copyJSON(orig.or[0], rollup);
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
if (typeof orig.query !== 'undefined' && orig['@type'] !== 'Comment') {
|
|
900
|
+
if (!orig.query['@type']) return {};
|
|
901
|
+
} else if (orig['@type'] === 'Comment' && orig.comment) {
|
|
902
|
+
if (!orig.query || !orig.query['@type']) return { '@type': 'Comment', comment: orig.comment };
|
|
903
|
+
}
|
|
904
|
+
if (typeof orig.consequent !== 'undefined') {
|
|
905
|
+
if (!orig.consequent['@type']) return {};
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
const nuj = {};
|
|
909
|
+
for (const k in orig) {
|
|
910
|
+
const part = orig[k];
|
|
911
|
+
if (Array.isArray(part)) {
|
|
912
|
+
const nupart = [];
|
|
913
|
+
for (let j = 0; j < part.length; j++) {
|
|
914
|
+
if (typeof part[j] === 'object') {
|
|
915
|
+
const sub = copyJSON(part[j], rollup);
|
|
916
|
+
if (!sub || !UTILS.empty(sub)) nupart.push(sub);
|
|
917
|
+
} else {
|
|
918
|
+
nupart.push(part[j]);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
nuj[k] = nupart;
|
|
922
|
+
} else if (part === null) {
|
|
923
|
+
// do nothing
|
|
924
|
+
} else if (typeof part === 'object') {
|
|
925
|
+
const q = copyJSON(part, rollup);
|
|
926
|
+
if (!q || !UTILS.empty(q)) nuj[k] = q;
|
|
927
|
+
} else {
|
|
928
|
+
nuj[k] = part;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
return nuj;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
module.exports = WOQLQuery;
|