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,148 @@
|
|
|
1
|
+
/* eslint-disable consistent-return */
|
|
2
|
+
/* eslint-disable no-param-reassign */
|
|
3
|
+
/* eslint-disable no-restricted-syntax */
|
|
4
|
+
/* eslint-disable no-unused-vars */
|
|
5
|
+
const WOQLQuery = require('../query/woqlCore');
|
|
6
|
+
const UTILS = require('../utils');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Functions to manipulate and check the paging related properties of a query
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
WOQLQuery.prototype.getLimit = function () {
|
|
13
|
+
return this.getPagingProperty('limit');
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
WOQLQuery.prototype.setLimit = function (l) {
|
|
17
|
+
return this.setPagingProperty('limit', l);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
WOQLQuery.prototype.isPaged = function (q) {
|
|
21
|
+
q = (q || this.query);
|
|
22
|
+
for (const prop of Object.keys(q)) {
|
|
23
|
+
if (prop === 'limit') return true;
|
|
24
|
+
if (this.paging_transitive_properties.indexOf(prop) !== -1) {
|
|
25
|
+
return this.isPaged(q[prop][q[prop].length - 1]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
WOQLQuery.prototype.getPage = function () {
|
|
32
|
+
if (this.isPaged()) {
|
|
33
|
+
const psize = this.getLimit();
|
|
34
|
+
if (this.hasStart()) {
|
|
35
|
+
const s = this.getStart();
|
|
36
|
+
// eslint-disable-next-line radix
|
|
37
|
+
return (parseInt(s / psize) + 1);
|
|
38
|
+
}
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
WOQLQuery.prototype.setPage = function (pagenum) {
|
|
45
|
+
const pstart = (this.getLimit() * (pagenum - 1));
|
|
46
|
+
if (this.hasStart()) {
|
|
47
|
+
this.setStart(pstart);
|
|
48
|
+
} else {
|
|
49
|
+
this.addStart(pstart);
|
|
50
|
+
}
|
|
51
|
+
return this;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
WOQLQuery.prototype.nextPage = function () {
|
|
55
|
+
return this.setPage(this.getPage() + 1);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
WOQLQuery.prototype.firstPage = function () {
|
|
59
|
+
return this.setPage(1);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
WOQLQuery.prototype.previousPage = function () {
|
|
63
|
+
const npage = this.getPage() - 1;
|
|
64
|
+
if (npage > 0) this.setPage(npage);
|
|
65
|
+
return this;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
WOQLQuery.prototype.setPageSize = function (size) {
|
|
69
|
+
this.setPagingProperty('limit', size);
|
|
70
|
+
if (this.hasStart()) {
|
|
71
|
+
this.setStart(0);
|
|
72
|
+
} else {
|
|
73
|
+
this.addStart(0);
|
|
74
|
+
}
|
|
75
|
+
return this;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
WOQLQuery.prototype.hasSelect = function () {
|
|
79
|
+
return (!!this.getPagingProperty('select'));
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
WOQLQuery.prototype.getSelectVariables = function (q) {
|
|
83
|
+
q = (q || this.query);
|
|
84
|
+
for (const prop of Object.keys(q)) {
|
|
85
|
+
if (prop === 'select') {
|
|
86
|
+
const vars = q[prop].slice(0, q[prop].length - 1);
|
|
87
|
+
return vars;
|
|
88
|
+
}
|
|
89
|
+
if (this.paging_transitive_properties.indexOf(prop) !== -1) {
|
|
90
|
+
const val = this.getSelectVariables(q[prop][q[prop].length - 1]);
|
|
91
|
+
if (typeof val !== 'undefined') {
|
|
92
|
+
return val;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
WOQLQuery.prototype.hasStart = function () {
|
|
99
|
+
return (typeof this.getPagingProperty('start') !== 'undefined');
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
WOQLQuery.prototype.getStart = function () {
|
|
103
|
+
return this.getPagingProperty('start');
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
WOQLQuery.prototype.setStart = function (start) {
|
|
107
|
+
return this.setPagingProperty('start', start);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
WOQLQuery.prototype.addStart = function (s) {
|
|
111
|
+
if (this.hasStart()) this.setStart(s);
|
|
112
|
+
else {
|
|
113
|
+
const nq = { start: [s, this.query] };
|
|
114
|
+
this.query = nq;
|
|
115
|
+
}
|
|
116
|
+
return this;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Returns the value of one of the 'paging' related properties (limit, start,...)
|
|
121
|
+
*/
|
|
122
|
+
WOQLQuery.prototype.getPagingProperty = function (pageprop, q) {
|
|
123
|
+
q = (q || this.query);
|
|
124
|
+
for (const prop of Object.keys(q)) {
|
|
125
|
+
if (prop === pageprop) return q[prop][0];
|
|
126
|
+
if (this.paging_transitive_properties.indexOf(prop) !== -1) {
|
|
127
|
+
const val = this.getPagingProperty(pageprop, q[prop][q[prop].length - 1]);
|
|
128
|
+
if (typeof val !== 'undefined') {
|
|
129
|
+
return val;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Sets the value of one of the paging_transitive_properties properties
|
|
137
|
+
*/
|
|
138
|
+
WOQLQuery.prototype.setPagingProperty = function (pageprop, val, q) {
|
|
139
|
+
q = (q || this.query);
|
|
140
|
+
for (const prop of Object.keys(q)) {
|
|
141
|
+
if (prop === pageprop) {
|
|
142
|
+
q[prop][0] = val;
|
|
143
|
+
} else if (this.paging_transitive_properties.indexOf(prop) !== -1) {
|
|
144
|
+
this.setPagingProperty(pageprop, val, q[prop][q[prop].length - 1]);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return this;
|
|
148
|
+
};
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/* eslint-disable camelcase */
|
|
2
|
+
/* eslint-disable consistent-return */
|
|
3
|
+
/* eslint-disable no-restricted-syntax */
|
|
4
|
+
/* eslint-disable no-plusplus */
|
|
5
|
+
/* eslint-disable no-param-reassign */
|
|
6
|
+
/* eslint-disable no-unused-vars */
|
|
7
|
+
/// /@ts-check
|
|
8
|
+
const UTILS = require('../utils');
|
|
9
|
+
const WOQL = require('../woql');
|
|
10
|
+
const WOQLQ = require('./woqlPaging');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {Object} WOQLQuery
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @module WOQLResult
|
|
18
|
+
* @license Apache Version 2
|
|
19
|
+
* Object representing the result of a WOQL Query
|
|
20
|
+
* @param {object} results result JSON object as returned by WOQL query
|
|
21
|
+
* @param {WOQLQuery} query the query object that generated the result
|
|
22
|
+
* @param {object} [config] optional result configuration options object
|
|
23
|
+
* [config.no_compress] by default all URLs are compressed where possible (v:X rather than http://.../variable/x) set to true to return non-compressed values
|
|
24
|
+
* [config.context] specify the JSON-LD context to use for compressing results - by default
|
|
25
|
+
* the query context will be used
|
|
26
|
+
*/
|
|
27
|
+
function WOQLResult(results, query, config) {
|
|
28
|
+
this.bindings = results ? results.bindings : [];
|
|
29
|
+
this.insert_count = results ? results.inserts : 0;
|
|
30
|
+
this.delete_count = results ? results.deletes : 0;
|
|
31
|
+
this.transaction_retry_count = results ? results.transaction_retry_count : 0;
|
|
32
|
+
/**
|
|
33
|
+
* @type {array | boolean}
|
|
34
|
+
*/
|
|
35
|
+
this.variable_names = results ? results['api:variable_names'] : false;
|
|
36
|
+
// console.log(results, this.variable_names)
|
|
37
|
+
this.query = query || WOQL.query();
|
|
38
|
+
this.cursor = 0;
|
|
39
|
+
// if (!(config && config.no_compress)) {
|
|
40
|
+
// const context = results && results.prefixes ? results.prefixes : false
|
|
41
|
+
// this.compress(context)
|
|
42
|
+
// }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
WOQLResult.prototype.formatter = function (context) {
|
|
46
|
+
context = context || this.query.getContext();
|
|
47
|
+
const formatted = [];
|
|
48
|
+
if (this.bindings && this.bindings.length > 0) {
|
|
49
|
+
this.bindings.forEach((row) => {
|
|
50
|
+
const rowObj = {};
|
|
51
|
+
Object.keys(row).forEach((propName) => {
|
|
52
|
+
const propValue = row[propName];
|
|
53
|
+
|
|
54
|
+
if (typeof propValue === 'string') {
|
|
55
|
+
if (propValue !== 'system:unknown') {
|
|
56
|
+
rowObj[propName] = UTILS.shorten(propValue, context);
|
|
57
|
+
} else {
|
|
58
|
+
rowObj[propName] = '';
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
rowObj[propName] = propValue['@value'];
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
formatted.push(rowObj);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return formatted;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {object} [context] optional context to use for compression -
|
|
72
|
+
* if ommitted query context is used
|
|
73
|
+
* @returns {WOQLResult}
|
|
74
|
+
*/
|
|
75
|
+
WOQLResult.prototype.compress = function (context) {
|
|
76
|
+
context = context || this.query.getContext();
|
|
77
|
+
if (context) {
|
|
78
|
+
for (let i = 0; i < this.bindings.length; i++) {
|
|
79
|
+
for (const prop of Object.keys(this.bindings[i])) {
|
|
80
|
+
const nprop = UTILS.shorten(prop, context);
|
|
81
|
+
let nval = this.bindings[i][prop];
|
|
82
|
+
if (typeof this.bindings[i][prop] === 'string') {
|
|
83
|
+
nval = UTILS.shorten(this.bindings[i][prop], context);
|
|
84
|
+
} else if (Array.isArray(this.bindings[i][prop])) {
|
|
85
|
+
nval = [];
|
|
86
|
+
for (let j = 0; j < this.bindings[i][prop].length; j++) {
|
|
87
|
+
let oval = this.bindings[i][prop][j];
|
|
88
|
+
if (typeof oval === 'string') oval = UTILS.shorten(oval, context);
|
|
89
|
+
else if (Array.isArray(oval)) {
|
|
90
|
+
const noval = [];
|
|
91
|
+
for (let k = 0; k < oval.length; k++) {
|
|
92
|
+
let kval = oval[k];
|
|
93
|
+
if (typeof kval === 'string') kval = UTILS.shorten(kval, context);
|
|
94
|
+
noval.push(kval);
|
|
95
|
+
}
|
|
96
|
+
oval = noval;
|
|
97
|
+
}
|
|
98
|
+
nval.push(oval);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
delete this.bindings[i][prop];
|
|
102
|
+
this.bindings[i][nprop] = nval;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// console.log(this.bindings)
|
|
107
|
+
return this;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Returns true if there are any results
|
|
112
|
+
* @returns {boolean}
|
|
113
|
+
*/
|
|
114
|
+
WOQLResult.prototype.hasBindings = function () {
|
|
115
|
+
if (this.bindings && this.count()) return true;
|
|
116
|
+
return false;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Returns true if there are any results
|
|
121
|
+
* @returns {boolean}
|
|
122
|
+
*/
|
|
123
|
+
WOQLResult.prototype.hasUpdates = function () {
|
|
124
|
+
if (this.inserts() > 0 || this.deletes() > 0) return true;
|
|
125
|
+
return false;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Returns original array of bindings returned by API
|
|
130
|
+
* @returns {array} the data result
|
|
131
|
+
*/
|
|
132
|
+
WOQLResult.prototype.getBindings = function () {
|
|
133
|
+
return this.bindings;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Returns original array of bindings returned by API
|
|
137
|
+
* @returns {array} the data result
|
|
138
|
+
*/
|
|
139
|
+
WOQLResult.prototype.rows = function () {
|
|
140
|
+
return this.bindings;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Returns list of variables returned in bindings from API
|
|
145
|
+
* @returns {array|boolean}
|
|
146
|
+
*/
|
|
147
|
+
WOQLResult.prototype.getVariableList = function () {
|
|
148
|
+
if (this.variable_names) {
|
|
149
|
+
return this.variable_names;
|
|
150
|
+
}
|
|
151
|
+
if (this.bindings && this.bindings[0]) {
|
|
152
|
+
return Object.keys(this.bindings[0]);
|
|
153
|
+
}
|
|
154
|
+
return [];
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Number of rows in bound results
|
|
159
|
+
* @returns {number}
|
|
160
|
+
*/
|
|
161
|
+
WOQLResult.prototype.count = function () {
|
|
162
|
+
return this.bindings.length;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Number of reported inserts
|
|
167
|
+
* @returns {number}
|
|
168
|
+
*/
|
|
169
|
+
WOQLResult.prototype.inserts = function () {
|
|
170
|
+
return this.insert_count;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Number of reported inserts
|
|
175
|
+
* @returns {number}
|
|
176
|
+
*/
|
|
177
|
+
WOQLResult.prototype.deletes = function () {
|
|
178
|
+
return this.delete_count;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Get the first object record from the result set
|
|
183
|
+
* @returns {object}
|
|
184
|
+
*/
|
|
185
|
+
WOQLResult.prototype.first = function () {
|
|
186
|
+
this.cursor = 0;
|
|
187
|
+
return this.bindings[0];
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Get the last object record from the result set
|
|
192
|
+
* @returns {object}
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
WOQLResult.prototype.last = function () {
|
|
196
|
+
this.cursor = this.bindings.length - 1;
|
|
197
|
+
return this.bindings[this.bindings.length - 1];
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @returns {object}
|
|
202
|
+
*/
|
|
203
|
+
|
|
204
|
+
WOQLResult.prototype.next = function () {
|
|
205
|
+
if (this.cursor >= this.bindings.length) return false;
|
|
206
|
+
const res = this.bindings[this.cursor];
|
|
207
|
+
this.cursor++;
|
|
208
|
+
return res;
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @returns {object}
|
|
213
|
+
*/
|
|
214
|
+
|
|
215
|
+
// eslint-disable-next-line consistent-return
|
|
216
|
+
WOQLResult.prototype.prev = function () {
|
|
217
|
+
if (this.cursor > 0) {
|
|
218
|
+
this.cursor--;
|
|
219
|
+
return this.bindings[this.cursor];
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Normally sorting of results is the job of the query - this is just in case you
|
|
225
|
+
* want to resort results according to some key (variable)
|
|
226
|
+
* @param {string} key
|
|
227
|
+
* @param {string} asc_or_desc
|
|
228
|
+
* @returns {WOQLResult}
|
|
229
|
+
*/
|
|
230
|
+
// eslint-disable-next-line camelcase
|
|
231
|
+
WOQLResult.prototype.sort = function (key, asc_or_desc) {
|
|
232
|
+
this.bindings.sort((a, b) => this.compareValues(a[key], b[key], asc_or_desc));
|
|
233
|
+
// eslint-disable-next-line no-unused-expressions
|
|
234
|
+
this;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Compares results a, b according to "asc" or "desc" order
|
|
239
|
+
* @param {object} a
|
|
240
|
+
* @param {object} b
|
|
241
|
+
* @param {string} [asc_or_desc]
|
|
242
|
+
* @returns {number}
|
|
243
|
+
*/
|
|
244
|
+
WOQLResult.prototype.compareValues = function (a, b, asc_or_desc = 'asc') {
|
|
245
|
+
if (!a || !b) return 0;
|
|
246
|
+
if (typeof a['@value'] !== 'undefined' && typeof b['@value'] !== 'undefined') {
|
|
247
|
+
a = a['@value'];
|
|
248
|
+
b = b['@value'];
|
|
249
|
+
}
|
|
250
|
+
if (a > b) {
|
|
251
|
+
return asc_or_desc && asc_or_desc === 'asc' ? 1 : -1;
|
|
252
|
+
}
|
|
253
|
+
if (b > a) {
|
|
254
|
+
return asc_or_desc && asc_or_desc === 'asc' ? -1 : 1;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
module.exports = WOQLResult;
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/* eslint-disable guard-for-in */
|
|
2
|
+
/* eslint-disable no-restricted-syntax */
|
|
3
|
+
/* eslint-disable valid-typeof */
|
|
4
|
+
/* eslint-disable no-continue */
|
|
5
|
+
/* eslint-disable no-plusplus */
|
|
6
|
+
/* eslint-disable no-use-before-define */
|
|
7
|
+
const TerminusRule = require('./terminusRule');
|
|
8
|
+
const UTILS = require('../utils');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @file WOQL Rules
|
|
12
|
+
* @license Apache Version 2
|
|
13
|
+
* WOQL Rules support pattern matching on results of WOQL Queries
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
function WOQLRule() {
|
|
17
|
+
TerminusRule.TerminusRule.call(this);
|
|
18
|
+
this.pattern = new WOQLPattern();
|
|
19
|
+
}
|
|
20
|
+
Object.setPrototypeOf(WOQLRule.prototype, TerminusRule.TerminusRule.prototype);
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Specifies that the rule only applies to specific variables returned by the WOQL query
|
|
24
|
+
* @param {Array<string>} vars - array of strings, each a variable name, variable prefixes
|
|
25
|
+
* ("v:") are added automatically if absent
|
|
26
|
+
*/
|
|
27
|
+
WOQLRule.prototype.setVariables = function (vars) {
|
|
28
|
+
if (vars && vars.length) {
|
|
29
|
+
this.pattern.variables = UTILS.removeNamespacesFromVariables(vars);
|
|
30
|
+
this.current_variable = this.pattern.variables[this.pattern.variables.length - 1];
|
|
31
|
+
}
|
|
32
|
+
return this;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Shorthand to the above using spread operator
|
|
37
|
+
*/
|
|
38
|
+
WOQLRule.prototype.vars = function (...varlist) {
|
|
39
|
+
return this.setVariables(varlist);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Specifies that the rule applies to a specific variable, variable prefix ("v:")
|
|
44
|
+
* is added automatically if absent
|
|
45
|
+
*/
|
|
46
|
+
WOQLRule.prototype.v = function (v) {
|
|
47
|
+
if (v) {
|
|
48
|
+
this.current_variable = UTILS.removeNamespaceFromVariable(v);
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
return this.current_variable;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Specifies that the rule applies to a specific edge, a source -> target pair of variables
|
|
56
|
+
*/
|
|
57
|
+
WOQLRule.prototype.edge = function (source, target) {
|
|
58
|
+
this.scope('edge');
|
|
59
|
+
if (source) {
|
|
60
|
+
const vs = UTILS.removeNamespaceFromVariable(source);
|
|
61
|
+
this.setVariables([vs]);
|
|
62
|
+
this.pattern.source = vs;
|
|
63
|
+
}
|
|
64
|
+
if (target) {
|
|
65
|
+
const vs = UTILS.removeNamespaceFromVariable(target);
|
|
66
|
+
if (!source) this.setVariables([vs]);
|
|
67
|
+
this.pattern.target = vs;
|
|
68
|
+
}
|
|
69
|
+
return this;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Specifies that the rule applies to a specific edge, a source -> target pair of variables
|
|
74
|
+
*/
|
|
75
|
+
WOQLRule.prototype.rownum = function (rownum) {
|
|
76
|
+
if (typeof rownum === 'undefined') return this.pattern.rownum;
|
|
77
|
+
this.pattern.rownum = rownum;
|
|
78
|
+
return this;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Specifies that the value of a variable must be one of the values contained in the list
|
|
83
|
+
* @param {...(string|number)} list - parameters are any atomic value (string | number) -
|
|
84
|
+
* the rule will match only cells that have one of these values
|
|
85
|
+
*/
|
|
86
|
+
WOQLRule.prototype.in = function (...list) {
|
|
87
|
+
if (this.current_variable) {
|
|
88
|
+
if (!this.pattern.constraints) this.pattern.constraints = {};
|
|
89
|
+
if (!this.pattern.constraints[this.current_variable]) {
|
|
90
|
+
this.pattern.constraints[this.current_variable] = [];
|
|
91
|
+
}
|
|
92
|
+
this.pattern.constraints[this.current_variable].push(list);
|
|
93
|
+
}
|
|
94
|
+
return this;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Specifies a filter function to apply to each element - only those values that
|
|
99
|
+
* return true when this filter is invoked will be matched
|
|
100
|
+
* @param {function} tester - test function that will be used to filter values
|
|
101
|
+
*/
|
|
102
|
+
WOQLRule.prototype.filter = function (tester) {
|
|
103
|
+
if (this.current_variable) {
|
|
104
|
+
if (!this.pattern.constraints) this.pattern.constraints = {};
|
|
105
|
+
if (!this.pattern.constraints[this.current_variable]) {
|
|
106
|
+
this.pattern.constraints[this.current_variable] = [];
|
|
107
|
+
}
|
|
108
|
+
this.pattern.constraints[this.current_variable].push(tester);
|
|
109
|
+
}
|
|
110
|
+
return this;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
WOQLRule.prototype.matchRow = function (rules, row, rownum, action) {
|
|
114
|
+
const matches = [];
|
|
115
|
+
for (let i = 0; i < rules.length; i++) {
|
|
116
|
+
if (action && this.rule && typeof this.rule[action] === 'undefined') continue;
|
|
117
|
+
if (rules[i].pattern.matchRow(row, rownum)) {
|
|
118
|
+
matches.push(rules[i]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return matches;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
WOQLRule.prototype.matchCell = function (rules, row, key, rownum, action) {
|
|
125
|
+
const matches = [];
|
|
126
|
+
for (let i = 0; i < rules.length; i++) {
|
|
127
|
+
if (action && this.rule && typeof this.rule[action] === 'undefined') continue;
|
|
128
|
+
if (rules[i].pattern.matchCell(row, key, rownum)) {
|
|
129
|
+
matches.push(rules[i]);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return matches;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
*
|
|
137
|
+
* @param {array} rules
|
|
138
|
+
* @param {string} key - column name
|
|
139
|
+
* @param {string} ruleName - the rule name like header, width etc...
|
|
140
|
+
* @returns {array}
|
|
141
|
+
*/
|
|
142
|
+
WOQLRule.prototype.matchColumn = function (rules, key, ruleName) {
|
|
143
|
+
const matches = [];
|
|
144
|
+
for (let i = 0; i < rules.length; i++) {
|
|
145
|
+
if (ruleName && this.rule && typeof this.rule[ruleName] === undefined) continue;
|
|
146
|
+
const ruleRow = rules[i];
|
|
147
|
+
/*
|
|
148
|
+
* if it is not the rule that I'm looking for
|
|
149
|
+
*/
|
|
150
|
+
if (ruleName && ruleRow.rule[ruleName] === undefined) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (ruleRow.pattern.matchColumn(key)) {
|
|
154
|
+
matches.push(ruleRow);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return matches;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
WOQLRule.prototype.matchNode = function (rules, row, key, nid, action) {
|
|
161
|
+
const matches = [];
|
|
162
|
+
for (let i = 0; i < rules.length; i++) {
|
|
163
|
+
if (action && this.rule && typeof this.rule[action] === 'undefined') continue;
|
|
164
|
+
if (rules[i].pattern.matchNode(row, key, nid)) {
|
|
165
|
+
matches.push(rules[i]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return matches;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
WOQLRule.prototype.matchPair = function (rules, row, keya, keyb, action) {
|
|
172
|
+
const matches = [];
|
|
173
|
+
for (let i = 0; i < rules.length; i++) {
|
|
174
|
+
if (action && this.rule && typeof this.rule[action] === 'undefined') continue;
|
|
175
|
+
if (rules[i].pattern.matchPair(row, keya, keyb)) {
|
|
176
|
+
matches.push(rules[i]);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return matches;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// alias
|
|
183
|
+
WOQLRule.prototype.matchEdge = WOQLRule.prototype.matchPair;
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Object to encapsulate the matching of woql result patterns - inherits from TerminusRule
|
|
187
|
+
* @param {Object} pattern
|
|
188
|
+
*/
|
|
189
|
+
function WOQLPattern(pattern) {
|
|
190
|
+
TerminusRule.TerminusPattern.call(this, pattern);
|
|
191
|
+
}
|
|
192
|
+
Object.setPrototypeOf(WOQLPattern.prototype, TerminusRule.TerminusPattern.prototype);
|
|
193
|
+
|
|
194
|
+
WOQLPattern.prototype.prettyPrint = function () {
|
|
195
|
+
// starts with obj. ...
|
|
196
|
+
let str = `${this.scope}('`;
|
|
197
|
+
if (this.variables) {
|
|
198
|
+
str += this.variables.join("', '");
|
|
199
|
+
}
|
|
200
|
+
str += "')";
|
|
201
|
+
if (typeof this.literal !== 'undefined') {
|
|
202
|
+
str += `.literal(${this.literal})`;
|
|
203
|
+
}
|
|
204
|
+
if (typeof this.type !== 'undefined') {
|
|
205
|
+
str += `.type(${this.unpack(this.type)})`;
|
|
206
|
+
}
|
|
207
|
+
if (typeof this.value !== 'undefined') {
|
|
208
|
+
str += `.value(${this.unpack(this.value, true)})`;
|
|
209
|
+
}
|
|
210
|
+
for (const v in this.constraints) {
|
|
211
|
+
str += `.v('${v}')`;
|
|
212
|
+
for (let i = 0; i < this.constraints[v].length; i++) {
|
|
213
|
+
if (typeof this.constraints[v][i] === 'function') {
|
|
214
|
+
str += `.filter(${this.constraints[v][i]})`;
|
|
215
|
+
} else {
|
|
216
|
+
// eslint-disable-next-line no-undef
|
|
217
|
+
str += `.in(${json.unpack(this.constraints[v][i])})`;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return str;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* @param {String|Object} data
|
|
226
|
+
* @param {string|Array<string>} [key] - a variable or an array of two variables
|
|
227
|
+
* (in the case of edge scope) which constitutes the key being tested
|
|
228
|
+
* @param {String} [scope] - the scope in which the test is being carried out (row, column, cell)
|
|
229
|
+
*/
|
|
230
|
+
|
|
231
|
+
WOQLPattern.prototype.matchRow = function (row, rownum) {
|
|
232
|
+
if (typeof this.rownum !== 'undefined' && typeof rownum !== 'undefined') {
|
|
233
|
+
if (!this.numberMatch(this.rownum, rownum)) return false;
|
|
234
|
+
}
|
|
235
|
+
if (this.scope && this.scope !== 'row') return false;
|
|
236
|
+
if (!this.testVariableConstraints(row)) return false;
|
|
237
|
+
return true;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
WOQLPattern.prototype.matchCell = function (row, key, rownum) {
|
|
241
|
+
if (typeof this.rownum !== 'undefined' && typeof rownum !== 'undefined') {
|
|
242
|
+
if (!this.numberMatch(this.rownum, rownum)) return false;
|
|
243
|
+
}
|
|
244
|
+
if (!this.testBasics('column', row[key])) return false;
|
|
245
|
+
if (this.variables && this.variables.length && this.variables.indexOf(key) === -1) return false;
|
|
246
|
+
if (!this.testVariableConstraints(row)) return false;
|
|
247
|
+
return true;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
WOQLPattern.prototype.matchNode = function (row, key) {
|
|
251
|
+
if (!this.testBasics('node', row[key])) return false;
|
|
252
|
+
if (this.variables && this.variables.length && this.variables.indexOf(key) === -1) return false;
|
|
253
|
+
if (!this.testVariableConstraints(row)) return false;
|
|
254
|
+
return true;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
WOQLPattern.prototype.matchColumn = function (key) {
|
|
258
|
+
if (this.scope && this.scope !== 'column') return false;
|
|
259
|
+
if (this.variables && this.variables.length && this.variables.indexOf(key) === -1) return false;
|
|
260
|
+
return true;
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
WOQLPattern.prototype.matchPair = function (row, keya, keyb) {
|
|
264
|
+
if (this.scope && this.scope !== 'edge') return false;
|
|
265
|
+
if (this.source && this.source !== keya) return false;
|
|
266
|
+
if (this.target && this.target !== keyb) return false;
|
|
267
|
+
if (!this.testVariableConstraints(row)) return false;
|
|
268
|
+
return true;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
WOQLPattern.prototype.testVariableConstraints = function (row) {
|
|
272
|
+
for (const k in this.constraints) {
|
|
273
|
+
if (!this.testVariableConstraint(k, row[k])) return false;
|
|
274
|
+
}
|
|
275
|
+
return true;
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
WOQLPattern.prototype.testVariableConstraint = function (name, val) {
|
|
279
|
+
if (!this.constraints[name]) return true;
|
|
280
|
+
for (let i = 0; i < this.constraints[name].length; i++) {
|
|
281
|
+
if (!this.testValue(val, this.constraints[name][i])) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return true;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
WOQLPattern.prototype.setPattern = function (pattern) {
|
|
289
|
+
for (const key in pattern) {
|
|
290
|
+
this[key] = pattern[key];
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
WOQLPattern.prototype.json = function () {
|
|
295
|
+
const json = {};
|
|
296
|
+
if (this.scope) {
|
|
297
|
+
json.scope = this.scope;
|
|
298
|
+
}
|
|
299
|
+
if (this.value) {
|
|
300
|
+
json.value = this.value;
|
|
301
|
+
}
|
|
302
|
+
if (this.rownum) json.rownum = this.rownum;
|
|
303
|
+
if (this.variables) json.variables = this.variables;
|
|
304
|
+
if (this.literal) json.literal = this.literal;
|
|
305
|
+
if (this.type) json.type = this.type;
|
|
306
|
+
if (this.constraints) json.constraints = this.constraints;
|
|
307
|
+
if (this.source) json.source = this.source;
|
|
308
|
+
if (this.target) json.target = this.target;
|
|
309
|
+
return json;
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
module.exports = { WOQLRule, WOQLPattern };
|