n3 2.13.3 → 2.13.5
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/browser/n3.esm.min.js +10 -9
- package/browser/n3.min.js +10 -9
- package/lib/N3Lexer.js +127 -28
- package/lib/N3Reasoner.js +5 -4
- package/lib/N3Store.js +58 -27
- package/package.json +1 -1
- package/src/N3Lexer.js +150 -32
- package/src/N3Reasoner.js +6 -4
- package/src/N3Store.js +55 -29
package/src/N3Reasoner.js
CHANGED
|
@@ -34,6 +34,7 @@ export default class N3Reasoner {
|
|
|
34
34
|
if (!store._addToIndex(graphItem.subjects, subject, predicate, object)) return;
|
|
35
35
|
store._addToIndex(graphItem.predicates, predicate, object, subject);
|
|
36
36
|
store._addToIndex(graphItem.objects, object, subject, predicate);
|
|
37
|
+
this._indexed++;
|
|
37
38
|
}
|
|
38
39
|
// Count genuinely new derivations and fail past the budget. The check comes
|
|
39
40
|
// after all three indexes are updated, so a caught error leaves the store
|
|
@@ -175,7 +176,7 @@ export default class N3Reasoner {
|
|
|
175
176
|
}
|
|
176
177
|
|
|
177
178
|
reason(rules) {
|
|
178
|
-
this._derivations = 0;
|
|
179
|
+
this._derivations = this._indexed = 0;
|
|
179
180
|
if (!Array.isArray(rules)) {
|
|
180
181
|
rules = getRulesFromDataset(rules);
|
|
181
182
|
}
|
|
@@ -242,9 +243,10 @@ export default class N3Reasoner {
|
|
|
242
243
|
}
|
|
243
244
|
}
|
|
244
245
|
finally {
|
|
245
|
-
//
|
|
246
|
-
// so a caught budget error leaves the store
|
|
247
|
-
this._store._size
|
|
246
|
+
// Count the quads added directly to the indexes, even if a derivation
|
|
247
|
+
// budget was exceeded, so a caught budget error leaves the store consistent
|
|
248
|
+
if (this._store._size !== null)
|
|
249
|
+
this._store._size += this._indexed;
|
|
248
250
|
}
|
|
249
251
|
}
|
|
250
252
|
}
|
package/src/N3Store.js
CHANGED
|
@@ -23,11 +23,15 @@ function hasInIndex(index0, key0, key1, key2) {
|
|
|
23
23
|
return !!index2 && key2 in index2;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
// The number of index leaves that the last `merge` call added
|
|
27
|
+
let mergedLeaves = 0;
|
|
28
|
+
|
|
26
29
|
function merge(target, source, depth = 4) {
|
|
27
30
|
let size = target[SIZE] || 0;
|
|
28
31
|
for (const key in source) {
|
|
29
32
|
if (!(key in target)) {
|
|
30
33
|
size++;
|
|
34
|
+
if (depth === 0) mergedLeaves++;
|
|
31
35
|
target[key] = depth === 0 ? null : merge(Object.create(null), source[key], depth - 1);
|
|
32
36
|
}
|
|
33
37
|
// Merge into the existing object in place,
|
|
@@ -242,6 +246,12 @@ export class N3EntityIndex {
|
|
|
242
246
|
}
|
|
243
247
|
}
|
|
244
248
|
|
|
249
|
+
// Returns the size of a store from this copy of N3 if it is known without counting,
|
|
250
|
+
// or null otherwise
|
|
251
|
+
function knownSize(dataset) {
|
|
252
|
+
return dataset instanceof N3Store ? dataset._size : null;
|
|
253
|
+
}
|
|
254
|
+
|
|
245
255
|
// ## Constructor
|
|
246
256
|
export default class N3Store {
|
|
247
257
|
constructor(quads, options) {
|
|
@@ -273,20 +283,11 @@ export default class N3Store {
|
|
|
273
283
|
|
|
274
284
|
// ### `size` returns the number of quads in the store
|
|
275
285
|
get size() {
|
|
276
|
-
//
|
|
277
|
-
|
|
278
|
-
if (
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
// Calculate the number of quads by counting to the deepest level
|
|
282
|
-
size = 0;
|
|
283
|
-
const graphs = this._graphs;
|
|
284
|
-
let subjects, subject;
|
|
285
|
-
for (const graphKey in graphs)
|
|
286
|
-
for (const subjectKey in (subjects = graphs[graphKey].subjects))
|
|
287
|
-
for (const predicateKey in (subject = subjects[subjectKey]))
|
|
288
|
-
size += subject[predicateKey][SIZE];
|
|
289
|
-
return this._size = size;
|
|
286
|
+
// The quad count is kept up to date by every change,
|
|
287
|
+
// except by reasoners from earlier versions of N3, which set it to null
|
|
288
|
+
if (this._size === null)
|
|
289
|
+
this._size = this.countQuads();
|
|
290
|
+
return this._size;
|
|
290
291
|
}
|
|
291
292
|
|
|
292
293
|
// ## Private methods
|
|
@@ -568,8 +569,7 @@ export default class N3Store {
|
|
|
568
569
|
this._addToIndex(graphItem.predicates, predicate, object, subject);
|
|
569
570
|
this._addToIndex(graphItem.objects, object, subject, predicate);
|
|
570
571
|
|
|
571
|
-
|
|
572
|
-
this._size = null;
|
|
572
|
+
if (this._size !== null) this._size++;
|
|
573
573
|
return true;
|
|
574
574
|
}
|
|
575
575
|
|
|
@@ -779,10 +779,14 @@ export default class N3Store {
|
|
|
779
779
|
// If only predicate and possibly object are given, the predicate index will be the fastest
|
|
780
780
|
count += this._countInIndex(content.predicates, predicateId, objectId, subjectId);
|
|
781
781
|
}
|
|
782
|
-
else {
|
|
783
|
-
// If only object is
|
|
782
|
+
else if (object) {
|
|
783
|
+
// If only object is given, the object index will be the fastest
|
|
784
784
|
count += this._countInIndex(content.objects, objectId, subjectId, predicateId);
|
|
785
785
|
}
|
|
786
|
+
else {
|
|
787
|
+
// Without a pattern, the subject index sums the fewest leaf counts
|
|
788
|
+
count += this._countInIndex(content.subjects);
|
|
789
|
+
}
|
|
786
790
|
}
|
|
787
791
|
}
|
|
788
792
|
return count;
|
|
@@ -1102,9 +1106,11 @@ export default class N3Store {
|
|
|
1102
1106
|
this.addQuads(quads);
|
|
1103
1107
|
// Index merging bypasses observer notifications
|
|
1104
1108
|
else if (this._observers === null && quads instanceof N3Store && quads._entityIndex === this._entityIndex) {
|
|
1105
|
-
if (quads.
|
|
1109
|
+
if (quads.size !== 0) {
|
|
1110
|
+
// Each new quad adds one leaf to each of the three indexes
|
|
1111
|
+
mergedLeaves = 0;
|
|
1106
1112
|
this._graphs = merge(this._graphs, quads._graphs);
|
|
1107
|
-
this._size
|
|
1113
|
+
if (this._size !== null) this._size += mergedLeaves / 3;
|
|
1108
1114
|
}
|
|
1109
1115
|
}
|
|
1110
1116
|
else {
|
|
@@ -1127,19 +1133,26 @@ export default class N3Store {
|
|
|
1127
1133
|
if (other === this)
|
|
1128
1134
|
return true;
|
|
1129
1135
|
|
|
1130
|
-
if (!(other instanceof N3Store) || this._entityIndex !== other._entityIndex)
|
|
1136
|
+
if (!(other instanceof N3Store) || this._entityIndex !== other._entityIndex) {
|
|
1137
|
+
// A larger set cannot be a subset, but only compare sizes that are known without counting
|
|
1138
|
+
const otherSize = knownSize(other), thisSize = this._size;
|
|
1139
|
+
if (otherSize !== null && thisSize !== null && otherSize > thisSize)
|
|
1140
|
+
return false;
|
|
1131
1141
|
return other.every(quad => this.has(quad));
|
|
1142
|
+
}
|
|
1132
1143
|
|
|
1144
|
+
// At every level, the index of the subset cannot have more entries
|
|
1133
1145
|
const g1 = this._graphs, g2 = other._graphs;
|
|
1134
|
-
let s1, s2, p1, p2, o1;
|
|
1146
|
+
let s1, s2, p1, p2, o1, o2;
|
|
1135
1147
|
for (const graph in g2) {
|
|
1136
1148
|
if (!(s1 = g1[graph])) return false;
|
|
1137
1149
|
s1 = s1.subjects;
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1150
|
+
if ((s2 = g2[graph].subjects)[SIZE] > s1[SIZE]) return false;
|
|
1151
|
+
for (const subject in s2) {
|
|
1152
|
+
if (!(p1 = s1[subject]) || (p2 = s2[subject])[SIZE] > p1[SIZE]) return false;
|
|
1153
|
+
for (const predicate in p2) {
|
|
1154
|
+
if (!(o1 = p1[predicate]) || (o2 = p2[predicate])[SIZE] > o1[SIZE]) return false;
|
|
1155
|
+
for (const object in o2)
|
|
1143
1156
|
if (!(object in o1)) return false;
|
|
1144
1157
|
}
|
|
1145
1158
|
}
|
|
@@ -1222,7 +1235,7 @@ export default class N3Store {
|
|
|
1222
1235
|
if (other === this) {
|
|
1223
1236
|
const store = new N3Store({ entityIndex: this._entityIndex });
|
|
1224
1237
|
store._graphs = merge(Object.create(null), this._graphs);
|
|
1225
|
-
store._size = this.
|
|
1238
|
+
store._size = this.size;
|
|
1226
1239
|
return store;
|
|
1227
1240
|
}
|
|
1228
1241
|
else if ((other instanceof N3Store) && this._entityIndex === other._entityIndex) {
|
|
@@ -1235,6 +1248,19 @@ export default class N3Store {
|
|
|
1235
1248
|
return store;
|
|
1236
1249
|
}
|
|
1237
1250
|
|
|
1251
|
+
// Test the quads of the smaller dataset against the larger one
|
|
1252
|
+
// when both sizes are known without counting
|
|
1253
|
+
const otherSize = knownSize(other), thisSize = this._size;
|
|
1254
|
+
if (otherSize !== null && thisSize !== null && otherSize < thisSize && typeof other[Symbol.iterator] === 'function' &&
|
|
1255
|
+
// unless it is a store whose custom factories may not create RDF/JS quads,
|
|
1256
|
+
// either for its quads or, through its entity index, for their terms
|
|
1257
|
+
other._factory === N3DataFactory && other._entityIndex._factory === N3DataFactory) {
|
|
1258
|
+
const store = new N3Store({ entityIndex: this._entityIndex });
|
|
1259
|
+
for (const quad of other)
|
|
1260
|
+
if (this.has(quad))
|
|
1261
|
+
store.add(quad);
|
|
1262
|
+
return store;
|
|
1263
|
+
}
|
|
1238
1264
|
return this.filter(quad => other.has(quad));
|
|
1239
1265
|
}
|
|
1240
1266
|
|
|
@@ -1306,7 +1332,7 @@ export default class N3Store {
|
|
|
1306
1332
|
union(quads) {
|
|
1307
1333
|
const store = new N3Store({ entityIndex: this._entityIndex });
|
|
1308
1334
|
store._graphs = merge(Object.create(null), this._graphs);
|
|
1309
|
-
store._size = this.
|
|
1335
|
+
store._size = this.size;
|
|
1310
1336
|
|
|
1311
1337
|
store.addAll(quads);
|
|
1312
1338
|
return store;
|