n3 1.17.0 → 1.17.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/README.md +10 -6
- package/browser/n3.min.js +1 -1
- package/lib/IRIs.js +4 -5
- package/lib/N3DataFactory.js +121 -137
- package/lib/N3Lexer.js +106 -139
- package/lib/N3Parser.js +275 -403
- package/lib/N3Store.js +294 -317
- package/lib/N3StreamParser.js +11 -14
- package/lib/N3StreamWriter.js +7 -11
- package/lib/N3Util.js +19 -25
- package/lib/N3Writer.js +124 -154
- package/lib/index.js +4 -18
- package/package.json +41 -18
- package/src/N3DataFactory.js +31 -24
- package/src/N3Store.js +68 -49
- package/src/N3Writer.js +2 -2
package/lib/N3Store.js
CHANGED
|
@@ -4,280 +4,287 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
|
-
|
|
8
7
|
var _N3DataFactory = _interopRequireWildcard(require("./N3DataFactory"));
|
|
9
|
-
|
|
10
8
|
var _readableStream = require("readable-stream");
|
|
11
|
-
|
|
12
9
|
var _IRIs = _interopRequireDefault(require("./IRIs"));
|
|
13
|
-
|
|
10
|
+
var _N3Util = require("./N3Util");
|
|
14
11
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
-
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
19
|
-
|
|
12
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
13
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
20
14
|
// **N3Store** objects store N3 quads by graph in memory.
|
|
15
|
+
|
|
21
16
|
// ## Constructor
|
|
22
17
|
class N3Store {
|
|
23
18
|
constructor(quads, options) {
|
|
24
19
|
// The number of quads is initially zero
|
|
25
|
-
this._size = 0;
|
|
26
|
-
|
|
27
|
-
this._graphs = Object.create(null);
|
|
20
|
+
this._size = 0;
|
|
21
|
+
// `_graphs` contains subject, predicate, and object indexes per graph
|
|
22
|
+
this._graphs = Object.create(null);
|
|
23
|
+
// `_ids` maps entities such as `http://xmlns.com/foaf/0.1/name` to numbers,
|
|
28
24
|
// saving memory by using only numbers as keys in `_graphs`
|
|
29
|
-
|
|
30
25
|
this._id = 0;
|
|
31
26
|
this._ids = Object.create(null);
|
|
32
|
-
this._ids['><'] = 0; // dummy entry, so the first actual key is non-zero
|
|
33
|
-
|
|
34
27
|
this._entities = Object.create(null); // inverse of `_ids`
|
|
35
28
|
// `_blankNodeIndex` is the index of the last automatically named blank node
|
|
29
|
+
this._blankNodeIndex = 0;
|
|
36
30
|
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
// Shift parameters if `quads` is not given
|
|
39
32
|
if (!options && quads && !quads[0]) options = quads, quads = null;
|
|
40
33
|
options = options || {};
|
|
41
|
-
this._factory = options.factory || _N3DataFactory.default;
|
|
34
|
+
this._factory = options.factory || _N3DataFactory.default;
|
|
42
35
|
|
|
36
|
+
// Add quads if passed
|
|
43
37
|
if (quads) this.addQuads(quads);
|
|
44
|
-
}
|
|
45
|
-
|
|
38
|
+
}
|
|
39
|
+
_termFromId(id, factory) {
|
|
40
|
+
if (id[0] === '.') {
|
|
41
|
+
const entities = this._entities;
|
|
42
|
+
const terms = id.split('.');
|
|
43
|
+
const q = this._factory.quad(this._termFromId(entities[terms[1]]), this._termFromId(entities[terms[2]]), this._termFromId(entities[terms[3]]), terms[4] && this._termFromId(entities[terms[4]]));
|
|
44
|
+
return q;
|
|
45
|
+
}
|
|
46
|
+
return (0, _N3DataFactory.termFromId)(id, factory);
|
|
47
|
+
}
|
|
48
|
+
_termToNumericId(term) {
|
|
49
|
+
if (term.termType === 'Quad') {
|
|
50
|
+
const s = this._termToNumericId(term.subject),
|
|
51
|
+
p = this._termToNumericId(term.predicate),
|
|
52
|
+
o = this._termToNumericId(term.object);
|
|
53
|
+
let g;
|
|
54
|
+
return s && p && o && ((0, _N3Util.isDefaultGraph)(term.graph) || (g = this._termToNumericId(term.graph))) && this._ids[g ? `.${s}.${p}.${o}.${g}` : `.${s}.${p}.${o}`];
|
|
55
|
+
}
|
|
56
|
+
return this._ids[(0, _N3DataFactory.termToId)(term)];
|
|
57
|
+
}
|
|
58
|
+
_termToNewNumericId(term) {
|
|
59
|
+
// This assumes that no graph term is present - we may wish to error if there is one
|
|
60
|
+
const str = term && term.termType === 'Quad' ? `.${this._termToNewNumericId(term.subject)}.${this._termToNewNumericId(term.predicate)}.${this._termToNewNumericId(term.object)}${(0, _N3Util.isDefaultGraph)(term.graph) ? '' : `.${this._termToNewNumericId(term.graph)}`}` : (0, _N3DataFactory.termToId)(term);
|
|
61
|
+
return this._ids[str] || (this._ids[this._entities[++this._id] = str] = this._id);
|
|
62
|
+
}
|
|
46
63
|
|
|
64
|
+
// ## Public properties
|
|
47
65
|
|
|
66
|
+
// ### `size` returns the number of quads in the store
|
|
48
67
|
get size() {
|
|
49
68
|
// Return the quad count if if was cached
|
|
50
69
|
let size = this._size;
|
|
51
|
-
if (size !== null) return size;
|
|
70
|
+
if (size !== null) return size;
|
|
52
71
|
|
|
72
|
+
// Calculate the number of quads by counting to the deepest level
|
|
53
73
|
size = 0;
|
|
54
74
|
const graphs = this._graphs;
|
|
55
75
|
let subjects, subject;
|
|
56
|
-
|
|
57
76
|
for (const graphKey in graphs) for (const subjectKey in subjects = graphs[graphKey].subjects) for (const predicateKey in subject = subjects[subjectKey]) size += Object.keys(subject[predicateKey]).length;
|
|
58
|
-
|
|
59
77
|
return this._size = size;
|
|
60
|
-
}
|
|
61
|
-
// ### `_addToIndex` adds a quad to a three-layered index.
|
|
62
|
-
// Returns if the index has changed, if the entry did not already exist.
|
|
78
|
+
}
|
|
63
79
|
|
|
80
|
+
// ## Private methods
|
|
64
81
|
|
|
82
|
+
// ### `_addToIndex` adds a quad to a three-layered index.
|
|
83
|
+
// Returns if the index has changed, if the entry did not already exist.
|
|
65
84
|
_addToIndex(index0, key0, key1, key2) {
|
|
66
85
|
// Create layers as necessary
|
|
67
86
|
const index1 = index0[key0] || (index0[key0] = {});
|
|
68
|
-
const index2 = index1[key1] || (index1[key1] = {});
|
|
69
|
-
|
|
87
|
+
const index2 = index1[key1] || (index1[key1] = {});
|
|
88
|
+
// Setting the key to _any_ value signals the presence of the quad
|
|
70
89
|
const existed = (key2 in index2);
|
|
71
90
|
if (!existed) index2[key2] = null;
|
|
72
91
|
return !existed;
|
|
73
|
-
}
|
|
74
|
-
|
|
92
|
+
}
|
|
75
93
|
|
|
94
|
+
// ### `_removeFromIndex` removes a quad from a three-layered index
|
|
76
95
|
_removeFromIndex(index0, key0, key1, key2) {
|
|
77
96
|
// Remove the quad from the index
|
|
78
97
|
const index1 = index0[key0],
|
|
79
|
-
|
|
80
|
-
delete index2[key2];
|
|
98
|
+
index2 = index1[key1];
|
|
99
|
+
delete index2[key2];
|
|
81
100
|
|
|
101
|
+
// Remove intermediary index layers if they are empty
|
|
82
102
|
for (const key in index2) return;
|
|
83
|
-
|
|
84
103
|
delete index1[key1];
|
|
85
|
-
|
|
86
104
|
for (const key in index1) return;
|
|
87
|
-
|
|
88
105
|
delete index0[key0];
|
|
89
|
-
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ### `_findInIndex` finds a set of quads in a three-layered index.
|
|
90
109
|
// The index base is `index0` and the keys at each level are `key0`, `key1`, and `key2`.
|
|
91
110
|
// Any of these keys can be undefined, which is interpreted as a wildcard.
|
|
92
111
|
// `name0`, `name1`, and `name2` are the names of the keys at each level,
|
|
93
112
|
// used when reconstructing the resulting quad
|
|
94
113
|
// (for instance: _subject_, _predicate_, and _object_).
|
|
95
114
|
// Finally, `graphId` will be the graph of the created quads.
|
|
96
|
-
|
|
97
|
-
|
|
98
115
|
*_findInIndex(index0, key0, key1, key2, name0, name1, name2, graphId) {
|
|
99
116
|
let tmp, index1, index2;
|
|
100
117
|
const entityKeys = this._entities;
|
|
101
|
-
const graph =
|
|
118
|
+
const graph = this._termFromId(graphId, this._factory);
|
|
102
119
|
const parts = {
|
|
103
120
|
subject: null,
|
|
104
121
|
predicate: null,
|
|
105
122
|
object: null
|
|
106
|
-
};
|
|
123
|
+
};
|
|
107
124
|
|
|
125
|
+
// If a key is specified, use only that part of index 0.
|
|
108
126
|
if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0];
|
|
109
|
-
|
|
110
127
|
for (const value0 in index0) {
|
|
111
128
|
if (index1 = index0[value0]) {
|
|
112
|
-
parts[name0] =
|
|
113
|
-
|
|
129
|
+
parts[name0] = this._termFromId(entityKeys[value0], this._factory);
|
|
130
|
+
// If a key is specified, use only that part of index 1.
|
|
114
131
|
if (key1) (tmp = index1, index1 = {})[key1] = tmp[key1];
|
|
115
|
-
|
|
116
132
|
for (const value1 in index1) {
|
|
117
133
|
if (index2 = index1[value1]) {
|
|
118
|
-
parts[name1] =
|
|
119
|
-
|
|
120
|
-
const values = key2 ? key2 in index2 ? [key2] : [] : Object.keys(index2);
|
|
121
|
-
|
|
134
|
+
parts[name1] = this._termFromId(entityKeys[value1], this._factory);
|
|
135
|
+
// If a key is specified, use only that part of index 2, if it exists.
|
|
136
|
+
const values = key2 ? key2 in index2 ? [key2] : [] : Object.keys(index2);
|
|
137
|
+
// Create quads for all items found in index 2.
|
|
122
138
|
for (let l = 0; l < values.length; l++) {
|
|
123
|
-
parts[name2] =
|
|
139
|
+
parts[name2] = this._termFromId(entityKeys[values[l]], this._factory);
|
|
124
140
|
yield this._factory.quad(parts.subject, parts.predicate, parts.object, graph);
|
|
125
141
|
}
|
|
126
142
|
}
|
|
127
143
|
}
|
|
128
144
|
}
|
|
129
145
|
}
|
|
130
|
-
}
|
|
131
|
-
|
|
146
|
+
}
|
|
132
147
|
|
|
148
|
+
// ### `_loop` executes the callback on all keys of index 0
|
|
133
149
|
_loop(index0, callback) {
|
|
134
150
|
for (const key0 in index0) callback(key0);
|
|
135
|
-
}
|
|
136
|
-
|
|
151
|
+
}
|
|
137
152
|
|
|
153
|
+
// ### `_loopByKey0` executes the callback on all keys of a certain entry in index 0
|
|
138
154
|
_loopByKey0(index0, key0, callback) {
|
|
139
155
|
let index1, key1;
|
|
140
|
-
|
|
141
156
|
if (index1 = index0[key0]) {
|
|
142
157
|
for (key1 in index1) callback(key1);
|
|
143
158
|
}
|
|
144
|
-
}
|
|
145
|
-
|
|
159
|
+
}
|
|
146
160
|
|
|
161
|
+
// ### `_loopByKey1` executes the callback on given keys of all entries in index 0
|
|
147
162
|
_loopByKey1(index0, key1, callback) {
|
|
148
163
|
let key0, index1;
|
|
149
|
-
|
|
150
164
|
for (key0 in index0) {
|
|
151
165
|
index1 = index0[key0];
|
|
152
166
|
if (index1[key1]) callback(key0);
|
|
153
167
|
}
|
|
154
|
-
}
|
|
155
|
-
|
|
168
|
+
}
|
|
156
169
|
|
|
170
|
+
// ### `_loopBy2Keys` executes the callback on given keys of certain entries in index 2
|
|
157
171
|
_loopBy2Keys(index0, key0, key1, callback) {
|
|
158
172
|
let index1, index2, key2;
|
|
159
|
-
|
|
160
173
|
if ((index1 = index0[key0]) && (index2 = index1[key1])) {
|
|
161
174
|
for (key2 in index2) callback(key2);
|
|
162
175
|
}
|
|
163
|
-
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ### `_countInIndex` counts matching quads in a three-layered index.
|
|
164
179
|
// The index base is `index0` and the keys at each level are `key0`, `key1`, and `key2`.
|
|
165
180
|
// Any of these keys can be undefined, which is interpreted as a wildcard.
|
|
166
|
-
|
|
167
|
-
|
|
168
181
|
_countInIndex(index0, key0, key1, key2) {
|
|
169
182
|
let count = 0,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
183
|
+
tmp,
|
|
184
|
+
index1,
|
|
185
|
+
index2;
|
|
173
186
|
|
|
187
|
+
// If a key is specified, count only that part of index 0
|
|
174
188
|
if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0];
|
|
175
|
-
|
|
176
189
|
for (const value0 in index0) {
|
|
177
190
|
if (index1 = index0[value0]) {
|
|
178
191
|
// If a key is specified, count only that part of index 1
|
|
179
192
|
if (key1) (tmp = index1, index1 = {})[key1] = tmp[key1];
|
|
180
|
-
|
|
181
193
|
for (const value1 in index1) {
|
|
182
194
|
if (index2 = index1[value1]) {
|
|
183
195
|
// If a key is specified, count the quad if it exists
|
|
184
|
-
if (key2) key2 in index2 && count++;
|
|
196
|
+
if (key2) key2 in index2 && count++;
|
|
197
|
+
// Otherwise, count all quads
|
|
185
198
|
else count += Object.keys(index2).length;
|
|
186
199
|
}
|
|
187
200
|
}
|
|
188
201
|
}
|
|
189
202
|
}
|
|
190
|
-
|
|
191
203
|
return count;
|
|
192
|
-
}
|
|
193
|
-
// or all graphs if the argument is null or undefined.
|
|
194
|
-
|
|
204
|
+
}
|
|
195
205
|
|
|
206
|
+
// ### `_getGraphs` returns an array with the given graph,
|
|
207
|
+
// or all graphs if the argument is null or undefined.
|
|
196
208
|
_getGraphs(graph) {
|
|
197
209
|
if (!isString(graph)) return this._graphs;
|
|
198
210
|
const graphs = {};
|
|
199
211
|
graphs[graph] = this._graphs[graph];
|
|
200
212
|
return graphs;
|
|
201
|
-
}
|
|
202
|
-
// and passes the corresponding entity to callback if it hasn't occurred before.
|
|
203
|
-
|
|
213
|
+
}
|
|
204
214
|
|
|
215
|
+
// ### `_uniqueEntities` returns a function that accepts an entity ID
|
|
216
|
+
// and passes the corresponding entity to callback if it hasn't occurred before.
|
|
205
217
|
_uniqueEntities(callback) {
|
|
206
218
|
const uniqueIds = Object.create(null);
|
|
207
219
|
return id => {
|
|
208
220
|
if (!(id in uniqueIds)) {
|
|
209
221
|
uniqueIds[id] = true;
|
|
210
|
-
callback(
|
|
222
|
+
callback(this._termFromId(this._entities[id], this._factory));
|
|
211
223
|
}
|
|
212
224
|
};
|
|
213
|
-
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// ## Public methods
|
|
228
|
+
|
|
214
229
|
// ### `add` adds the specified quad to the dataset.
|
|
215
230
|
// Returns the dataset instance it was called on.
|
|
216
231
|
// Existing quads, as defined in Quad.equals, will be ignored.
|
|
217
|
-
|
|
218
|
-
|
|
219
232
|
add(quad) {
|
|
220
233
|
this.addQuad(quad);
|
|
221
234
|
return this;
|
|
222
|
-
}
|
|
223
|
-
// Returns if the quad index has changed, if the quad did not already exist.
|
|
224
|
-
|
|
235
|
+
}
|
|
225
236
|
|
|
237
|
+
// ### `addQuad` adds a new quad to the store.
|
|
238
|
+
// Returns if the quad index has changed, if the quad did not already exist.
|
|
226
239
|
addQuad(subject, predicate, object, graph) {
|
|
227
240
|
// Shift arguments if a quad object is given instead of components
|
|
228
|
-
if (!predicate) graph = subject.graph, object = subject.object, predicate = subject.predicate, subject = subject.subject;
|
|
241
|
+
if (!predicate) graph = subject.graph, object = subject.object, predicate = subject.predicate, subject = subject.subject;
|
|
229
242
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
object = (0, _N3DataFactory.termToId)(object);
|
|
233
|
-
graph = (0, _N3DataFactory.termToId)(graph); // Find the graph that will contain the triple
|
|
234
|
-
|
|
235
|
-
let graphItem = this._graphs[graph]; // Create the graph if it doesn't exist yet
|
|
243
|
+
// Convert terms to internal string representation
|
|
244
|
+
graph = (0, _N3DataFactory.termToId)(graph);
|
|
236
245
|
|
|
246
|
+
// Find the graph that will contain the triple
|
|
247
|
+
let graphItem = this._graphs[graph];
|
|
248
|
+
// Create the graph if it doesn't exist yet
|
|
237
249
|
if (!graphItem) {
|
|
238
250
|
graphItem = this._graphs[graph] = {
|
|
239
251
|
subjects: {},
|
|
240
252
|
predicates: {},
|
|
241
253
|
objects: {}
|
|
242
|
-
};
|
|
254
|
+
};
|
|
255
|
+
// Freezing a graph helps subsequent `add` performance,
|
|
243
256
|
// and properties will never be modified anyway
|
|
244
|
-
|
|
245
257
|
Object.freeze(graphItem);
|
|
246
|
-
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Since entities can often be long IRIs, we avoid storing them in every index.
|
|
247
261
|
// Instead, we have a separate index that maps entities to numbers,
|
|
248
262
|
// which are then used as keys in the other indexes.
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const entities = this._entities;
|
|
253
|
-
subject = ids[subject] || (ids[entities[++this._id] = subject] = this._id);
|
|
254
|
-
predicate = ids[predicate] || (ids[entities[++this._id] = predicate] = this._id);
|
|
255
|
-
object = ids[object] || (ids[entities[++this._id] = object] = this._id);
|
|
256
|
-
|
|
263
|
+
subject = this._termToNewNumericId(subject);
|
|
264
|
+
predicate = this._termToNewNumericId(predicate);
|
|
265
|
+
object = this._termToNewNumericId(object);
|
|
257
266
|
const changed = this._addToIndex(graphItem.subjects, subject, predicate, object);
|
|
258
|
-
|
|
259
267
|
this._addToIndex(graphItem.predicates, predicate, object, subject);
|
|
268
|
+
this._addToIndex(graphItem.objects, object, subject, predicate);
|
|
260
269
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
270
|
+
// The cached quad count is now invalid
|
|
264
271
|
this._size = null;
|
|
265
272
|
return changed;
|
|
266
|
-
}
|
|
267
|
-
|
|
273
|
+
}
|
|
268
274
|
|
|
275
|
+
// ### `addQuads` adds multiple quads to the store
|
|
269
276
|
addQuads(quads) {
|
|
270
277
|
for (let i = 0; i < quads.length; i++) this.addQuad(quads[i]);
|
|
271
|
-
}
|
|
272
|
-
// Returns the dataset instance it was called on.
|
|
273
|
-
|
|
278
|
+
}
|
|
274
279
|
|
|
280
|
+
// ### `delete` removes the specified quad from the dataset.
|
|
281
|
+
// Returns the dataset instance it was called on.
|
|
275
282
|
delete(quad) {
|
|
276
283
|
this.removeQuad(quad);
|
|
277
284
|
return this;
|
|
278
|
-
}
|
|
279
|
-
|
|
285
|
+
}
|
|
280
286
|
|
|
287
|
+
// ### `has` determines whether a dataset includes a certain quad or quad pattern.
|
|
281
288
|
has(subjectOrQuad, predicate, object, graph) {
|
|
282
289
|
if (subjectOrQuad && subjectOrQuad.subject) ({
|
|
283
290
|
subject: subjectOrQuad,
|
|
@@ -286,155 +293,143 @@ class N3Store {
|
|
|
286
293
|
graph
|
|
287
294
|
} = subjectOrQuad);
|
|
288
295
|
return !this.readQuads(subjectOrQuad, predicate, object, graph).next().done;
|
|
289
|
-
}
|
|
290
|
-
|
|
296
|
+
}
|
|
291
297
|
|
|
298
|
+
// ### `import` adds a stream of quads to the store
|
|
292
299
|
import(stream) {
|
|
293
300
|
stream.on('data', quad => {
|
|
294
301
|
this.addQuad(quad);
|
|
295
302
|
});
|
|
296
303
|
return stream;
|
|
297
|
-
}
|
|
298
|
-
|
|
304
|
+
}
|
|
299
305
|
|
|
306
|
+
// ### `removeQuad` removes a quad from the store if it exists
|
|
300
307
|
removeQuad(subject, predicate, object, graph) {
|
|
301
308
|
// Shift arguments if a quad object is given instead of components
|
|
302
|
-
if (!predicate) graph = subject.graph, object = subject.object, predicate = subject.predicate, subject = subject.subject;
|
|
309
|
+
if (!predicate) graph = subject.graph, object = subject.object, predicate = subject.predicate, subject = subject.subject;
|
|
303
310
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
object = (0, _N3DataFactory.termToId)(object);
|
|
307
|
-
graph = (0, _N3DataFactory.termToId)(graph); // Find internal identifiers for all components
|
|
308
|
-
// and verify the quad exists.
|
|
311
|
+
// Convert terms to internal string representation
|
|
312
|
+
graph = (0, _N3DataFactory.termToId)(graph);
|
|
309
313
|
|
|
310
|
-
|
|
311
|
-
|
|
314
|
+
// Find internal identifiers for all components
|
|
315
|
+
// and verify the quad exists.
|
|
316
|
+
const graphs = this._graphs;
|
|
312
317
|
let graphItem, subjects, predicates;
|
|
313
|
-
if (!(subject =
|
|
318
|
+
if (!(subject = subject && this._termToNumericId(subject)) || !(predicate = predicate && this._termToNumericId(predicate)) || !(object = object && this._termToNumericId(object)) || !(graphItem = graphs[graph]) || !(subjects = graphItem.subjects[subject]) || !(predicates = subjects[predicate]) || !(object in predicates)) return false;
|
|
314
319
|
|
|
320
|
+
// Remove it from all indexes
|
|
315
321
|
this._removeFromIndex(graphItem.subjects, subject, predicate, object);
|
|
316
|
-
|
|
317
322
|
this._removeFromIndex(graphItem.predicates, predicate, object, subject);
|
|
318
|
-
|
|
319
323
|
this._removeFromIndex(graphItem.objects, object, subject, predicate);
|
|
324
|
+
if (this._size !== null) this._size--;
|
|
320
325
|
|
|
321
|
-
|
|
322
|
-
|
|
326
|
+
// Remove the graph if it is empty
|
|
323
327
|
for (subject in graphItem.subjects) return true;
|
|
324
|
-
|
|
325
328
|
delete graphs[graph];
|
|
326
329
|
return true;
|
|
327
|
-
}
|
|
328
|
-
|
|
330
|
+
}
|
|
329
331
|
|
|
332
|
+
// ### `removeQuads` removes multiple quads from the store
|
|
330
333
|
removeQuads(quads) {
|
|
331
334
|
for (let i = 0; i < quads.length; i++) this.removeQuad(quads[i]);
|
|
332
|
-
}
|
|
333
|
-
|
|
335
|
+
}
|
|
334
336
|
|
|
337
|
+
// ### `remove` removes a stream of quads from the store
|
|
335
338
|
remove(stream) {
|
|
336
339
|
stream.on('data', quad => {
|
|
337
340
|
this.removeQuad(quad);
|
|
338
341
|
});
|
|
339
342
|
return stream;
|
|
340
|
-
}
|
|
341
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
342
|
-
|
|
343
|
+
}
|
|
343
344
|
|
|
345
|
+
// ### `removeMatches` removes all matching quads from the store
|
|
346
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
344
347
|
removeMatches(subject, predicate, object, graph) {
|
|
345
348
|
const stream = new _readableStream.Readable({
|
|
346
349
|
objectMode: true
|
|
347
350
|
});
|
|
348
|
-
|
|
349
351
|
stream._read = () => {
|
|
350
352
|
for (const quad of this.readQuads(subject, predicate, object, graph)) stream.push(quad);
|
|
351
|
-
|
|
352
353
|
stream.push(null);
|
|
353
354
|
};
|
|
354
|
-
|
|
355
355
|
return this.remove(stream);
|
|
356
|
-
}
|
|
357
|
-
|
|
356
|
+
}
|
|
358
357
|
|
|
358
|
+
// ### `deleteGraph` removes all triples with the given graph from the store
|
|
359
359
|
deleteGraph(graph) {
|
|
360
360
|
return this.removeMatches(null, null, null, graph);
|
|
361
|
-
}
|
|
362
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
363
|
-
|
|
361
|
+
}
|
|
364
362
|
|
|
363
|
+
// ### `getQuads` returns an array of quads matching a pattern.
|
|
364
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
365
365
|
getQuads(subject, predicate, object, graph) {
|
|
366
366
|
return [...this.readQuads(subject, predicate, object, graph)];
|
|
367
|
-
}
|
|
368
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
369
|
-
|
|
367
|
+
}
|
|
370
368
|
|
|
369
|
+
// ### `readQuads` returns an generator of quads matching a pattern.
|
|
370
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
371
371
|
*readQuads(subject, predicate, object, graph) {
|
|
372
372
|
// Convert terms to internal string representation
|
|
373
|
-
subject = subject && (0, _N3DataFactory.termToId)(subject);
|
|
374
|
-
predicate = predicate && (0, _N3DataFactory.termToId)(predicate);
|
|
375
|
-
object = object && (0, _N3DataFactory.termToId)(object);
|
|
376
373
|
graph = graph && (0, _N3DataFactory.termToId)(graph);
|
|
374
|
+
const graphs = this._getGraphs(graph);
|
|
375
|
+
let content, subjectId, predicateId, objectId;
|
|
377
376
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
let content, subjectId, predicateId, objectId; // Translate IRIs to internal index keys.
|
|
382
|
-
|
|
383
|
-
if (isString(subject) && !(subjectId = ids[subject]) || isString(predicate) && !(predicateId = ids[predicate]) || isString(object) && !(objectId = ids[object])) return;
|
|
384
|
-
|
|
377
|
+
// Translate IRIs to internal index keys.
|
|
378
|
+
if (subject && !(subjectId = this._termToNumericId(subject)) || predicate && !(predicateId = this._termToNumericId(predicate)) || object && !(objectId = this._termToNumericId(object))) return;
|
|
385
379
|
for (const graphId in graphs) {
|
|
386
380
|
// Only if the specified graph contains triples, there can be results
|
|
387
381
|
if (content = graphs[graphId]) {
|
|
388
382
|
// Choose the optimal index, based on what fields are present
|
|
389
383
|
if (subjectId) {
|
|
390
|
-
if (objectId)
|
|
391
|
-
|
|
384
|
+
if (objectId)
|
|
385
|
+
// If subject and object are given, the object index will be the fastest
|
|
386
|
+
yield* this._findInIndex(content.objects, objectId, subjectId, predicateId, 'object', 'subject', 'predicate', graphId);else
|
|
387
|
+
// If only subject and possibly predicate are given, the subject index will be the fastest
|
|
392
388
|
yield* this._findInIndex(content.subjects, subjectId, predicateId, null, 'subject', 'predicate', 'object', graphId);
|
|
393
|
-
} else if (predicateId)
|
|
394
|
-
|
|
395
|
-
yield* this._findInIndex(content.
|
|
389
|
+
} else if (predicateId)
|
|
390
|
+
// If only predicate and possibly object are given, the predicate index will be the fastest
|
|
391
|
+
yield* this._findInIndex(content.predicates, predicateId, objectId, null, 'predicate', 'object', 'subject', graphId);else if (objectId)
|
|
392
|
+
// If only object is given, the object index will be the fastest
|
|
393
|
+
yield* this._findInIndex(content.objects, objectId, null, null, 'object', 'subject', 'predicate', graphId);else
|
|
394
|
+
// If nothing is given, iterate subjects and predicates first
|
|
396
395
|
yield* this._findInIndex(content.subjects, null, null, null, 'subject', 'predicate', 'object', graphId);
|
|
397
396
|
}
|
|
398
397
|
}
|
|
399
|
-
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// ### `match` returns a new dataset that is comprised of all quads in the current instance matching the given arguments.
|
|
400
401
|
// The logic described in Quad Matching is applied for each quad in this dataset to check if it should be included in the output dataset.
|
|
401
402
|
// Note: This method always returns a new DatasetCore, even if that dataset contains no quads.
|
|
402
403
|
// Note: Since a DatasetCore is an unordered set, the order of the quads within the returned sequence is arbitrary.
|
|
403
404
|
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
404
405
|
// For backwards compatibility, the object return also implements the Readable stream interface.
|
|
405
|
-
|
|
406
|
-
|
|
407
406
|
match(subject, predicate, object, graph) {
|
|
408
407
|
return new DatasetCoreAndReadableStream(this, subject, predicate, object, graph);
|
|
409
|
-
}
|
|
410
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
411
|
-
|
|
408
|
+
}
|
|
412
409
|
|
|
410
|
+
// ### `countQuads` returns the number of quads matching a pattern.
|
|
411
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
413
412
|
countQuads(subject, predicate, object, graph) {
|
|
414
413
|
// Convert terms to internal string representation
|
|
415
|
-
subject = subject && (0, _N3DataFactory.termToId)(subject);
|
|
416
|
-
predicate = predicate && (0, _N3DataFactory.termToId)(predicate);
|
|
417
|
-
object = object && (0, _N3DataFactory.termToId)(object);
|
|
418
414
|
graph = graph && (0, _N3DataFactory.termToId)(graph);
|
|
419
|
-
|
|
420
|
-
const graphs = this._getGraphs(graph),
|
|
421
|
-
ids = this._ids;
|
|
422
|
-
|
|
415
|
+
const graphs = this._getGraphs(graph);
|
|
423
416
|
let count = 0,
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
if (isString(subject) && !(subjectId = ids[subject]) || isString(predicate) && !(predicateId = ids[predicate]) || isString(object) && !(objectId = ids[object])) return 0;
|
|
417
|
+
content,
|
|
418
|
+
subjectId,
|
|
419
|
+
predicateId,
|
|
420
|
+
objectId;
|
|
430
421
|
|
|
422
|
+
// Translate IRIs to internal index keys.
|
|
423
|
+
if (subject && !(subjectId = this._termToNumericId(subject)) || predicate && !(predicateId = this._termToNumericId(predicate)) || object && !(objectId = this._termToNumericId(object))) return 0;
|
|
431
424
|
for (const graphId in graphs) {
|
|
432
425
|
// Only if the specified graph contains triples, there can be results
|
|
433
426
|
if (content = graphs[graphId]) {
|
|
434
427
|
// Choose the optimal index, based on what fields are present
|
|
435
428
|
if (subject) {
|
|
436
|
-
if (object)
|
|
437
|
-
|
|
429
|
+
if (object)
|
|
430
|
+
// If subject and object are given, the object index will be the fastest
|
|
431
|
+
count += this._countInIndex(content.objects, objectId, subjectId, predicateId);else
|
|
432
|
+
// If only subject and possibly predicate are given, the subject index will be the fastest
|
|
438
433
|
count += this._countInIndex(content.subjects, subjectId, predicateId, objectId);
|
|
439
434
|
} else if (predicate) {
|
|
440
435
|
// If only predicate and possibly object are given, the predicate index will be the fastest
|
|
@@ -445,22 +440,21 @@ class N3Store {
|
|
|
445
440
|
}
|
|
446
441
|
}
|
|
447
442
|
}
|
|
448
|
-
|
|
449
443
|
return count;
|
|
450
|
-
}
|
|
451
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
452
|
-
|
|
444
|
+
}
|
|
453
445
|
|
|
446
|
+
// ### `forEach` executes the callback on all quads.
|
|
447
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
454
448
|
forEach(callback, subject, predicate, object, graph) {
|
|
455
449
|
this.some(quad => {
|
|
456
450
|
callback(quad);
|
|
457
451
|
return false;
|
|
458
452
|
}, subject, predicate, object, graph);
|
|
459
|
-
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// ### `every` executes the callback on all quads,
|
|
460
456
|
// and returns `true` if it returns truthy for all them.
|
|
461
457
|
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
462
|
-
|
|
463
|
-
|
|
464
458
|
every(callback, subject, predicate, object, graph) {
|
|
465
459
|
let some = false;
|
|
466
460
|
const every = !this.some(quad => {
|
|
@@ -468,152 +462,148 @@ class N3Store {
|
|
|
468
462
|
return !callback(quad);
|
|
469
463
|
}, subject, predicate, object, graph);
|
|
470
464
|
return some && every;
|
|
471
|
-
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// ### `some` executes the callback on all quads,
|
|
472
468
|
// and returns `true` if it returns truthy for any of them.
|
|
473
469
|
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
474
|
-
|
|
475
|
-
|
|
476
470
|
some(callback, subject, predicate, object, graph) {
|
|
477
471
|
for (const quad of this.readQuads(subject, predicate, object, graph)) if (callback(quad)) return true;
|
|
478
|
-
|
|
479
472
|
return false;
|
|
480
|
-
}
|
|
481
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
482
|
-
|
|
473
|
+
}
|
|
483
474
|
|
|
475
|
+
// ### `getSubjects` returns all subjects that match the pattern.
|
|
476
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
484
477
|
getSubjects(predicate, object, graph) {
|
|
485
478
|
const results = [];
|
|
486
479
|
this.forSubjects(s => {
|
|
487
480
|
results.push(s);
|
|
488
481
|
}, predicate, object, graph);
|
|
489
482
|
return results;
|
|
490
|
-
}
|
|
491
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
492
|
-
|
|
483
|
+
}
|
|
493
484
|
|
|
485
|
+
// ### `forSubjects` executes the callback on all subjects that match the pattern.
|
|
486
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
494
487
|
forSubjects(callback, predicate, object, graph) {
|
|
495
488
|
// Convert terms to internal string representation
|
|
496
|
-
predicate = predicate && (0, _N3DataFactory.termToId)(predicate);
|
|
497
|
-
object = object && (0, _N3DataFactory.termToId)(object);
|
|
498
489
|
graph = graph && (0, _N3DataFactory.termToId)(graph);
|
|
499
|
-
|
|
500
|
-
const ids = this._ids,
|
|
501
|
-
graphs = this._getGraphs(graph);
|
|
502
|
-
|
|
490
|
+
const graphs = this._getGraphs(graph);
|
|
503
491
|
let content, predicateId, objectId;
|
|
504
|
-
callback = this._uniqueEntities(callback);
|
|
505
|
-
|
|
506
|
-
if (isString(predicate) && !(predicateId = ids[predicate]) || isString(object) && !(objectId = ids[object])) return;
|
|
492
|
+
callback = this._uniqueEntities(callback);
|
|
507
493
|
|
|
494
|
+
// Translate IRIs to internal index keys.
|
|
495
|
+
if (predicate && !(predicateId = this._termToNumericId(predicate)) || object && !(objectId = this._termToNumericId(object))) return;
|
|
508
496
|
for (graph in graphs) {
|
|
509
497
|
// Only if the specified graph contains triples, there can be results
|
|
510
498
|
if (content = graphs[graph]) {
|
|
511
499
|
// Choose optimal index based on which fields are wildcards
|
|
512
500
|
if (predicateId) {
|
|
513
|
-
if (objectId)
|
|
514
|
-
|
|
501
|
+
if (objectId)
|
|
502
|
+
// If predicate and object are given, the POS index is best.
|
|
503
|
+
this._loopBy2Keys(content.predicates, predicateId, objectId, callback);else
|
|
504
|
+
// If only predicate is given, the SPO index is best.
|
|
515
505
|
this._loopByKey1(content.subjects, predicateId, callback);
|
|
516
|
-
} else if (objectId)
|
|
517
|
-
|
|
506
|
+
} else if (objectId)
|
|
507
|
+
// If only object is given, the OSP index is best.
|
|
508
|
+
this._loopByKey0(content.objects, objectId, callback);else
|
|
509
|
+
// If no params given, iterate all the subjects
|
|
518
510
|
this._loop(content.subjects, callback);
|
|
519
511
|
}
|
|
520
512
|
}
|
|
521
|
-
}
|
|
522
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
523
|
-
|
|
513
|
+
}
|
|
524
514
|
|
|
515
|
+
// ### `getPredicates` returns all predicates that match the pattern.
|
|
516
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
525
517
|
getPredicates(subject, object, graph) {
|
|
526
518
|
const results = [];
|
|
527
519
|
this.forPredicates(p => {
|
|
528
520
|
results.push(p);
|
|
529
521
|
}, subject, object, graph);
|
|
530
522
|
return results;
|
|
531
|
-
}
|
|
532
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
533
|
-
|
|
523
|
+
}
|
|
534
524
|
|
|
525
|
+
// ### `forPredicates` executes the callback on all predicates that match the pattern.
|
|
526
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
535
527
|
forPredicates(callback, subject, object, graph) {
|
|
536
528
|
// Convert terms to internal string representation
|
|
537
|
-
subject = subject && (0, _N3DataFactory.termToId)(subject);
|
|
538
|
-
object = object && (0, _N3DataFactory.termToId)(object);
|
|
539
529
|
graph = graph && (0, _N3DataFactory.termToId)(graph);
|
|
540
|
-
|
|
541
|
-
const ids = this._ids,
|
|
542
|
-
graphs = this._getGraphs(graph);
|
|
543
|
-
|
|
530
|
+
const graphs = this._getGraphs(graph);
|
|
544
531
|
let content, subjectId, objectId;
|
|
545
|
-
callback = this._uniqueEntities(callback);
|
|
546
|
-
|
|
547
|
-
if (isString(subject) && !(subjectId = ids[subject]) || isString(object) && !(objectId = ids[object])) return;
|
|
532
|
+
callback = this._uniqueEntities(callback);
|
|
548
533
|
|
|
534
|
+
// Translate IRIs to internal index keys.
|
|
535
|
+
if (subject && !(subjectId = this._termToNumericId(subject)) || object && !(objectId = this._termToNumericId(object))) return;
|
|
549
536
|
for (graph in graphs) {
|
|
550
537
|
// Only if the specified graph contains triples, there can be results
|
|
551
538
|
if (content = graphs[graph]) {
|
|
552
539
|
// Choose optimal index based on which fields are wildcards
|
|
553
540
|
if (subjectId) {
|
|
554
|
-
if (objectId)
|
|
555
|
-
|
|
541
|
+
if (objectId)
|
|
542
|
+
// If subject and object are given, the OSP index is best.
|
|
543
|
+
this._loopBy2Keys(content.objects, objectId, subjectId, callback);else
|
|
544
|
+
// If only subject is given, the SPO index is best.
|
|
556
545
|
this._loopByKey0(content.subjects, subjectId, callback);
|
|
557
|
-
} else if (objectId)
|
|
558
|
-
|
|
546
|
+
} else if (objectId)
|
|
547
|
+
// If only object is given, the POS index is best.
|
|
548
|
+
this._loopByKey1(content.predicates, objectId, callback);else
|
|
549
|
+
// If no params given, iterate all the predicates.
|
|
559
550
|
this._loop(content.predicates, callback);
|
|
560
551
|
}
|
|
561
552
|
}
|
|
562
|
-
}
|
|
563
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
564
|
-
|
|
553
|
+
}
|
|
565
554
|
|
|
555
|
+
// ### `getObjects` returns all objects that match the pattern.
|
|
556
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
566
557
|
getObjects(subject, predicate, graph) {
|
|
567
558
|
const results = [];
|
|
568
559
|
this.forObjects(o => {
|
|
569
560
|
results.push(o);
|
|
570
561
|
}, subject, predicate, graph);
|
|
571
562
|
return results;
|
|
572
|
-
}
|
|
573
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
574
|
-
|
|
563
|
+
}
|
|
575
564
|
|
|
565
|
+
// ### `forObjects` executes the callback on all objects that match the pattern.
|
|
566
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
576
567
|
forObjects(callback, subject, predicate, graph) {
|
|
577
568
|
// Convert terms to internal string representation
|
|
578
|
-
subject = subject && (0, _N3DataFactory.termToId)(subject);
|
|
579
|
-
predicate = predicate && (0, _N3DataFactory.termToId)(predicate);
|
|
580
569
|
graph = graph && (0, _N3DataFactory.termToId)(graph);
|
|
581
|
-
|
|
582
|
-
const ids = this._ids,
|
|
583
|
-
graphs = this._getGraphs(graph);
|
|
584
|
-
|
|
570
|
+
const graphs = this._getGraphs(graph);
|
|
585
571
|
let content, subjectId, predicateId;
|
|
586
|
-
callback = this._uniqueEntities(callback);
|
|
587
|
-
|
|
588
|
-
if (isString(subject) && !(subjectId = ids[subject]) || isString(predicate) && !(predicateId = ids[predicate])) return;
|
|
572
|
+
callback = this._uniqueEntities(callback);
|
|
589
573
|
|
|
574
|
+
// Translate IRIs to internal index keys.
|
|
575
|
+
if (subject && !(subjectId = this._termToNumericId(subject)) || predicate && !(predicateId = this._termToNumericId(predicate))) return;
|
|
590
576
|
for (graph in graphs) {
|
|
591
577
|
// Only if the specified graph contains triples, there can be results
|
|
592
578
|
if (content = graphs[graph]) {
|
|
593
579
|
// Choose optimal index based on which fields are wildcards
|
|
594
580
|
if (subjectId) {
|
|
595
|
-
if (predicateId)
|
|
596
|
-
|
|
581
|
+
if (predicateId)
|
|
582
|
+
// If subject and predicate are given, the SPO index is best.
|
|
583
|
+
this._loopBy2Keys(content.subjects, subjectId, predicateId, callback);else
|
|
584
|
+
// If only subject is given, the OSP index is best.
|
|
597
585
|
this._loopByKey1(content.objects, subjectId, callback);
|
|
598
|
-
} else if (predicateId)
|
|
599
|
-
|
|
586
|
+
} else if (predicateId)
|
|
587
|
+
// If only predicate is given, the POS index is best.
|
|
588
|
+
this._loopByKey0(content.predicates, predicateId, callback);else
|
|
589
|
+
// If no params given, iterate all the objects.
|
|
600
590
|
this._loop(content.objects, callback);
|
|
601
591
|
}
|
|
602
592
|
}
|
|
603
|
-
}
|
|
604
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
605
|
-
|
|
593
|
+
}
|
|
606
594
|
|
|
595
|
+
// ### `getGraphs` returns all graphs that match the pattern.
|
|
596
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
607
597
|
getGraphs(subject, predicate, object) {
|
|
608
598
|
const results = [];
|
|
609
599
|
this.forGraphs(g => {
|
|
610
600
|
results.push(g);
|
|
611
601
|
}, subject, predicate, object);
|
|
612
602
|
return results;
|
|
613
|
-
}
|
|
614
|
-
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
615
|
-
|
|
603
|
+
}
|
|
616
604
|
|
|
605
|
+
// ### `forGraphs` executes the callback on all graphs that match the pattern.
|
|
606
|
+
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
617
607
|
forGraphs(callback, subject, predicate, object) {
|
|
618
608
|
for (const graph in this._graphs) {
|
|
619
609
|
this.some(quad => {
|
|
@@ -621,129 +611,128 @@ class N3Store {
|
|
|
621
611
|
return true; // Halt iteration of some()
|
|
622
612
|
}, subject, predicate, object, graph);
|
|
623
613
|
}
|
|
624
|
-
}
|
|
625
|
-
|
|
614
|
+
}
|
|
626
615
|
|
|
616
|
+
// ### `createBlankNode` creates a new blank node, returning its name
|
|
627
617
|
createBlankNode(suggestedName) {
|
|
628
|
-
let name, index;
|
|
629
|
-
|
|
618
|
+
let name, index;
|
|
619
|
+
// Generate a name based on the suggested name
|
|
630
620
|
if (suggestedName) {
|
|
631
621
|
name = suggestedName = `_:${suggestedName}`, index = 1;
|
|
632
|
-
|
|
633
622
|
while (this._ids[name]) name = suggestedName + index++;
|
|
634
|
-
}
|
|
623
|
+
}
|
|
624
|
+
// Generate a generic blank node name
|
|
635
625
|
else {
|
|
636
626
|
do {
|
|
637
627
|
name = `_:b${this._blankNodeIndex++}`;
|
|
638
628
|
} while (this._ids[name]);
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
|
|
629
|
+
}
|
|
630
|
+
// Add the blank node to the entities, avoiding the generation of duplicates
|
|
642
631
|
this._ids[name] = ++this._id;
|
|
643
632
|
this._entities[this._id] = name;
|
|
644
633
|
return this._factory.blankNode(name.substr(2));
|
|
645
|
-
}
|
|
646
|
-
// and returns the items per list.
|
|
647
|
-
|
|
634
|
+
}
|
|
648
635
|
|
|
636
|
+
// ### `extractLists` finds and removes all list triples
|
|
637
|
+
// and returns the items per list.
|
|
649
638
|
extractLists({
|
|
650
639
|
remove = false,
|
|
651
640
|
ignoreErrors = false
|
|
652
641
|
} = {}) {
|
|
653
642
|
const lists = {}; // has scalar keys so could be a simple Object
|
|
654
|
-
|
|
655
643
|
const onError = ignoreErrors ? () => true : (node, message) => {
|
|
656
644
|
throw new Error(`${node.value} ${message}`);
|
|
657
|
-
};
|
|
645
|
+
};
|
|
658
646
|
|
|
647
|
+
// Traverse each list from its tail
|
|
659
648
|
const tails = this.getQuads(null, _IRIs.default.rdf.rest, _IRIs.default.rdf.nil, null);
|
|
660
649
|
const toRemove = remove ? [...tails] : [];
|
|
661
650
|
tails.forEach(tailQuad => {
|
|
662
651
|
const items = []; // the members found as objects of rdf:first quads
|
|
663
|
-
|
|
664
652
|
let malformed = false; // signals whether the current list is malformed
|
|
665
|
-
|
|
666
653
|
let head; // the head of the list (_:b1 in above example)
|
|
667
|
-
|
|
668
654
|
let headPos; // set to subject or object when head is set
|
|
669
|
-
|
|
670
655
|
const graph = tailQuad.graph; // make sure list is in exactly one graph
|
|
671
|
-
// Traverse the list from tail to end
|
|
672
656
|
|
|
657
|
+
// Traverse the list from tail to end
|
|
673
658
|
let current = tailQuad.subject;
|
|
674
|
-
|
|
675
659
|
while (current && !malformed) {
|
|
676
660
|
const objectQuads = this.getQuads(null, null, current, null);
|
|
677
661
|
const subjectQuads = this.getQuads(current, null, null, null);
|
|
678
662
|
let quad,
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
663
|
+
first = null,
|
|
664
|
+
rest = null,
|
|
665
|
+
parent = null;
|
|
682
666
|
|
|
667
|
+
// Find the first and rest of this list node
|
|
683
668
|
for (let i = 0; i < subjectQuads.length && !malformed; i++) {
|
|
684
669
|
quad = subjectQuads[i];
|
|
685
|
-
if (!quad.graph.equals(graph)) malformed = onError(current, 'not confined to single graph');else if (head) malformed = onError(current, 'has non-list arcs out');
|
|
670
|
+
if (!quad.graph.equals(graph)) malformed = onError(current, 'not confined to single graph');else if (head) malformed = onError(current, 'has non-list arcs out');
|
|
671
|
+
|
|
672
|
+
// one rdf:first
|
|
686
673
|
else if (quad.predicate.value === _IRIs.default.rdf.first) {
|
|
687
674
|
if (first) malformed = onError(current, 'has multiple rdf:first arcs');else toRemove.push(first = quad);
|
|
688
|
-
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// one rdf:rest
|
|
689
678
|
else if (quad.predicate.value === _IRIs.default.rdf.rest) {
|
|
690
679
|
if (rest) malformed = onError(current, 'has multiple rdf:rest arcs');else toRemove.push(rest = quad);
|
|
691
|
-
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// alien triple
|
|
692
683
|
else if (objectQuads.length) malformed = onError(current, 'can\'t be subject and object');else {
|
|
693
684
|
head = quad; // e.g. { (1 2 3) :p :o }
|
|
694
|
-
|
|
695
685
|
headPos = 'subject';
|
|
696
686
|
}
|
|
697
|
-
}
|
|
698
|
-
// { (1 2) :p :o } arrives here with head set to the list.
|
|
699
|
-
|
|
687
|
+
}
|
|
700
688
|
|
|
689
|
+
// { :s :p (1 2) } arrives here with no head
|
|
690
|
+
// { (1 2) :p :o } arrives here with head set to the list.
|
|
701
691
|
for (let i = 0; i < objectQuads.length && !malformed; ++i) {
|
|
702
692
|
quad = objectQuads[i];
|
|
703
|
-
if (head) malformed = onError(current, 'can\'t have coreferences');
|
|
693
|
+
if (head) malformed = onError(current, 'can\'t have coreferences');
|
|
694
|
+
// one rdf:rest
|
|
704
695
|
else if (quad.predicate.value === _IRIs.default.rdf.rest) {
|
|
705
696
|
if (parent) malformed = onError(current, 'has incoming rdf:rest arcs');else parent = quad;
|
|
706
697
|
} else {
|
|
707
698
|
head = quad; // e.g. { :s :p (1 2) }
|
|
708
|
-
|
|
709
699
|
headPos = 'object';
|
|
710
700
|
}
|
|
711
|
-
}
|
|
712
|
-
|
|
701
|
+
}
|
|
713
702
|
|
|
703
|
+
// Store the list item and continue with parent
|
|
714
704
|
if (!first) malformed = onError(current, 'has no list head');else items.unshift(first.object);
|
|
715
705
|
current = parent && parent.subject;
|
|
716
|
-
}
|
|
717
|
-
|
|
706
|
+
}
|
|
718
707
|
|
|
719
|
-
|
|
708
|
+
// Don't remove any quads if the list is malformed
|
|
709
|
+
if (malformed) remove = false;
|
|
710
|
+
// Store the list under the value of its head
|
|
720
711
|
else if (head) lists[head[headPos].value] = items;
|
|
721
|
-
});
|
|
712
|
+
});
|
|
722
713
|
|
|
714
|
+
// Remove list quads if requested
|
|
723
715
|
if (remove) this.removeQuads(toRemove);
|
|
724
716
|
return lists;
|
|
725
|
-
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// ### Store is an iterable.
|
|
726
720
|
// Can be used where iterables are expected: for...of loops, array spread operator,
|
|
727
721
|
// `yield*`, and destructuring assignment (order is not guaranteed).
|
|
728
|
-
|
|
729
|
-
|
|
730
722
|
*[Symbol.iterator]() {
|
|
731
723
|
yield* this.readQuads();
|
|
732
724
|
}
|
|
725
|
+
}
|
|
733
726
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
727
|
+
// Determines whether the argument is a string
|
|
737
728
|
exports.default = N3Store;
|
|
738
|
-
|
|
739
729
|
function isString(s) {
|
|
740
730
|
return typeof s === 'string' || s instanceof String;
|
|
741
731
|
}
|
|
732
|
+
|
|
742
733
|
/**
|
|
743
734
|
* A class that implements both DatasetCore and Readable.
|
|
744
735
|
*/
|
|
745
|
-
|
|
746
|
-
|
|
747
736
|
class DatasetCoreAndReadableStream extends _readableStream.Readable {
|
|
748
737
|
constructor(n3Store, subject, predicate, object, graph) {
|
|
749
738
|
super({
|
|
@@ -757,7 +746,6 @@ class DatasetCoreAndReadableStream extends _readableStream.Readable {
|
|
|
757
746
|
graph
|
|
758
747
|
});
|
|
759
748
|
}
|
|
760
|
-
|
|
761
749
|
get filtered() {
|
|
762
750
|
if (!this._filtered) {
|
|
763
751
|
const {
|
|
@@ -770,41 +758,30 @@ class DatasetCoreAndReadableStream extends _readableStream.Readable {
|
|
|
770
758
|
const newStore = this._filtered = new N3Store({
|
|
771
759
|
factory: n3Store._factory
|
|
772
760
|
});
|
|
773
|
-
|
|
774
761
|
for (const quad of n3Store.readQuads(subject, predicate, object, graph)) newStore.addQuad(quad);
|
|
775
762
|
}
|
|
776
|
-
|
|
777
763
|
return this._filtered;
|
|
778
764
|
}
|
|
779
|
-
|
|
780
765
|
get size() {
|
|
781
766
|
return this.filtered.size;
|
|
782
767
|
}
|
|
783
|
-
|
|
784
768
|
_read() {
|
|
785
769
|
for (const quad of this) this.push(quad);
|
|
786
|
-
|
|
787
770
|
this.push(null);
|
|
788
771
|
}
|
|
789
|
-
|
|
790
772
|
add(quad) {
|
|
791
773
|
return this.filtered.add(quad);
|
|
792
774
|
}
|
|
793
|
-
|
|
794
775
|
delete(quad) {
|
|
795
776
|
return this.filtered.delete(quad);
|
|
796
777
|
}
|
|
797
|
-
|
|
798
778
|
has(quad) {
|
|
799
779
|
return this.filtered.has(quad);
|
|
800
780
|
}
|
|
801
|
-
|
|
802
781
|
match(subject, predicate, object, graph) {
|
|
803
782
|
return new DatasetCoreAndReadableStream(this.filtered, subject, predicate, object, graph);
|
|
804
783
|
}
|
|
805
|
-
|
|
806
784
|
*[Symbol.iterator]() {
|
|
807
785
|
yield* this._filtered || this.n3Store.readQuads(this.subject, this.predicate, this.object, this.graph);
|
|
808
786
|
}
|
|
809
|
-
|
|
810
787
|
}
|