rdflib 2.2.10 → 2.2.12-5f141ca2
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/.babelrc +0 -0
- package/README.md +1 -0
- package/changes.txt +0 -0
- package/dist/rdflib.min.js +62 -0
- package/dist/rdflib.min.js.map +1 -0
- package/esm/blank-node.js +137 -0
- package/esm/class-order.js +12 -0
- package/esm/collection.js +173 -0
- package/esm/convert.js +61 -0
- package/esm/default-graph.js +57 -0
- package/esm/empty.js +46 -0
- package/esm/factories/canonical-data-factory.js +204 -0
- package/esm/factories/extended-term-factory.js +55 -0
- package/esm/factories/factory-types.js +18 -0
- package/esm/factories/rdflib-data-factory.js +55 -0
- package/esm/fetcher.js +2180 -0
- package/esm/formula.js +987 -0
- package/esm/index.js +64 -0
- package/esm/jsonldparser.js +122 -0
- package/esm/jsonparser.js +60 -0
- package/esm/literal.js +236 -0
- package/esm/log.js +13 -0
- package/esm/n3parser.js +1854 -0
- package/esm/named-node.js +154 -0
- package/esm/namespace.js +17 -0
- package/esm/node-internal.js +151 -0
- package/esm/node.js +46 -0
- package/esm/parse.js +138 -0
- package/esm/patch-parser.js +110 -0
- package/esm/query-to-sparql.js +83 -0
- package/esm/query.js +620 -0
- package/esm/rdfaparser.js +1197 -0
- package/esm/rdfxmlparser.js +588 -0
- package/esm/serialize.js +95 -0
- package/esm/serializer.js +1162 -0
- package/esm/sparql-to-query.js +566 -0
- package/esm/statement.js +128 -0
- package/esm/store.js +1306 -0
- package/esm/tf-types.js +1 -0
- package/esm/types.js +25 -0
- package/esm/update-manager.js +1252 -0
- package/esm/updates-via.js +197 -0
- package/esm/uri.js +245 -0
- package/esm/utils/default-graph-uri.js +4 -0
- package/esm/utils/termValue.js +8 -0
- package/esm/utils/terms.js +72 -0
- package/esm/utils-js.js +348 -0
- package/esm/utils.js +103 -0
- package/esm/variable.js +101 -0
- package/esm/xsd-internal.js +10 -0
- package/esm/xsd.js +15 -0
- package/lib/blank-node.d.ts +44 -0
- package/lib/blank-node.js +0 -0
- package/lib/class-order.d.ts +7 -0
- package/lib/class-order.js +0 -0
- package/lib/collection.d.ts +65 -0
- package/lib/collection.js +0 -0
- package/lib/convert.d.ts +2 -0
- package/lib/convert.js +0 -0
- package/lib/default-graph.d.ts +13 -0
- package/lib/default-graph.js +0 -0
- package/lib/empty.d.ts +11 -0
- package/lib/empty.js +0 -0
- package/lib/factories/canonical-data-factory.d.ts +6 -0
- package/lib/factories/canonical-data-factory.js +0 -0
- package/lib/factories/extended-term-factory.d.ts +13 -0
- package/lib/factories/extended-term-factory.js +0 -0
- package/lib/factories/factory-types.d.ts +67 -0
- package/lib/factories/factory-types.js +0 -0
- package/lib/factories/rdflib-data-factory.d.ts +4 -0
- package/lib/factories/rdflib-data-factory.js +0 -0
- package/lib/fetcher.d.ts +443 -0
- package/lib/fetcher.js +3 -2
- package/lib/formula.d.ts +327 -0
- package/lib/formula.js +0 -0
- package/lib/index.d.ts +40 -0
- package/lib/index.js +0 -0
- package/lib/jsonldparser.d.ts +13 -0
- package/lib/jsonldparser.js +0 -0
- package/lib/jsonparser.d.ts +4 -0
- package/lib/jsonparser.js +0 -0
- package/lib/literal.d.ts +67 -0
- package/lib/literal.js +0 -0
- package/lib/log.d.ts +15 -0
- package/lib/log.js +0 -0
- package/lib/n3parser.d.ts +62 -0
- package/lib/n3parser.js +1334 -1289
- package/lib/named-node.d.ts +44 -0
- package/lib/named-node.js +0 -0
- package/lib/namespace.d.ts +7 -0
- package/lib/namespace.js +0 -0
- package/lib/node-internal.d.ts +63 -0
- package/lib/node-internal.js +0 -0
- package/lib/node.d.ts +2 -0
- package/lib/node.js +0 -0
- package/lib/parse.d.ts +16 -0
- package/lib/parse.js +0 -0
- package/lib/patch-parser.d.ts +3 -0
- package/lib/patch-parser.js +0 -0
- package/lib/query-to-sparql.d.ts +1 -0
- package/lib/query-to-sparql.js +0 -0
- package/lib/query.d.ts +27 -0
- package/lib/query.js +0 -0
- package/lib/rdfaparser.d.ts +78 -0
- package/lib/rdfaparser.js +0 -0
- package/lib/rdfxmlparser.d.ts +60 -0
- package/lib/rdfxmlparser.js +430 -413
- package/lib/serialize.d.ts +23 -0
- package/lib/serialize.js +1 -1
- package/lib/serializer.d.ts +54 -0
- package/lib/serializer.js +851 -824
- package/lib/sparql-to-query.d.ts +6 -0
- package/lib/sparql-to-query.js +0 -0
- package/lib/statement.d.ts +55 -0
- package/lib/statement.js +0 -0
- package/lib/store.d.ts +302 -0
- package/lib/store.js +0 -0
- package/lib/tf-types.d.ts +151 -0
- package/lib/tf-types.js +0 -0
- package/lib/types.d.ts +68 -0
- package/lib/types.js +0 -0
- package/lib/update-manager.d.ts +198 -0
- package/lib/update-manager.js +0 -0
- package/lib/updates-via.d.ts +26 -0
- package/lib/updates-via.js +0 -0
- package/lib/uri.d.ts +33 -0
- package/lib/uri.js +0 -0
- package/lib/utils/default-graph-uri.d.ts +3 -0
- package/lib/utils/default-graph-uri.js +0 -0
- package/lib/utils/termValue.d.ts +3 -0
- package/lib/utils/termValue.js +0 -0
- package/lib/utils/terms.d.ts +33 -0
- package/lib/utils/terms.js +0 -0
- package/lib/utils-js.d.ts +50 -0
- package/lib/utils-js.js +0 -0
- package/lib/utils.d.ts +20 -0
- package/lib/utils.js +0 -0
- package/lib/variable.d.ts +29 -0
- package/lib/variable.js +0 -0
- package/lib/xsd-internal.d.ts +11 -0
- package/lib/xsd-internal.js +0 -0
- package/lib/xsd.d.ts +19 -0
- package/lib/xsd.js +8 -14
- package/package.json +3 -3
- package/src/blank-node.ts +0 -0
- package/src/class-order.ts +0 -0
- package/src/collection.ts +0 -0
- package/src/convert.js +0 -0
- package/src/default-graph.ts +0 -0
- package/src/empty.ts +0 -0
- package/src/factories/canonical-data-factory.ts +0 -0
- package/src/factories/extended-term-factory.ts +0 -0
- package/src/factories/factory-types.ts +0 -0
- package/src/factories/rdflib-data-factory.ts +0 -0
- package/src/fetcher.ts +6 -3
- package/src/formula.ts +0 -0
- package/src/index.ts +0 -0
- package/src/jsonldparser.js +0 -0
- package/src/jsonparser.js +0 -0
- package/src/literal.ts +0 -0
- package/src/log.js +0 -0
- package/src/n3parser.js +1114 -1110
- package/src/named-node.ts +0 -0
- package/src/namespace.ts +0 -0
- package/src/node-internal.ts +0 -0
- package/src/node.ts +0 -0
- package/src/parse.ts +0 -0
- package/src/patch-parser.js +0 -0
- package/src/query-to-sparql.js +0 -0
- package/src/query.js +0 -0
- package/src/rdfaparser.js +0 -0
- package/src/rdfxmlparser.js +22 -21
- package/src/serialize.ts +3 -3
- package/src/serializer.js +74 -62
- package/src/sparql-to-query.js +0 -0
- package/src/statement.ts +0 -0
- package/src/store.ts +0 -0
- package/src/tf-types.ts +0 -0
- package/src/types.ts +0 -0
- package/src/update-manager.ts +0 -0
- package/src/updates-via.js +0 -0
- package/src/uri.ts +0 -0
- package/src/utils/default-graph-uri.ts +0 -0
- package/src/utils/termValue.ts +0 -0
- package/src/utils/terms.ts +0 -0
- package/src/utils-js.js +0 -0
- package/src/utils.ts +0 -0
- package/src/variable.ts +0 -0
- package/src/xsd-internal.js +0 -0
- package/src/xsd.js +16 -14
package/esm/query.js
ADDED
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
2
|
+
// Matching a formula against another formula
|
|
3
|
+
// Assync as well as Synchronously
|
|
4
|
+
//
|
|
5
|
+
// W3C open source licence 2005.
|
|
6
|
+
//
|
|
7
|
+
// This builds on term.js, match.js (and identity.js?)
|
|
8
|
+
// to allow a query of a formula.
|
|
9
|
+
//
|
|
10
|
+
// Here we introduce for the first time a subclass of term: variable.
|
|
11
|
+
//
|
|
12
|
+
// SVN ID: $Id: query.js 25116 2008-11-15 16:13:48Z timbl $
|
|
13
|
+
// Variable
|
|
14
|
+
//
|
|
15
|
+
// Compare with BlankNode. They are similar, but a variable
|
|
16
|
+
// stands for something whose value is to be returned.
|
|
17
|
+
// Also, users name variables and want the same name back when stuff is printed
|
|
18
|
+
|
|
19
|
+
/* jsl:option explicit */
|
|
20
|
+
// Turn on JavaScriptLint variable declaration checking
|
|
21
|
+
import IndexedFormula from './store';
|
|
22
|
+
import { defaultGraphURI as defaultDocumentURI } from './utils/default-graph-uri';
|
|
23
|
+
import log from './log';
|
|
24
|
+
import { docpart } from './uri';
|
|
25
|
+
/**
|
|
26
|
+
* Query class, for tracking queries the user has in the UI.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
export var Query = function Query(name, id) {
|
|
30
|
+
_classCallCheck(this, Query);
|
|
31
|
+
|
|
32
|
+
this.pat = new IndexedFormula(); // The pattern to search for
|
|
33
|
+
|
|
34
|
+
this.vars = []; // Used by UI code but not in query.js
|
|
35
|
+
// this.orderBy = [] // Not used yet
|
|
36
|
+
|
|
37
|
+
this.name = name;
|
|
38
|
+
this.id = id;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* This function will match a pattern to the current Store
|
|
42
|
+
*
|
|
43
|
+
* The callback function is called whenever a match is found
|
|
44
|
+
* When fetcher is supplied this will be called to load from the web
|
|
45
|
+
* any new nodes as they are discovered. This will cause the query to traverse the
|
|
46
|
+
* graph of linked data, sometimes called "Link Following Query"
|
|
47
|
+
*
|
|
48
|
+
* @param myQuery - a knowledgebase containing a pattern to use as query
|
|
49
|
+
* @param callback - whenever the pattern in myQuery is met this is called with
|
|
50
|
+
* the new bindings as parameter
|
|
51
|
+
* @param fetcher? - If and only if, you want link following, give a fetcher
|
|
52
|
+
* which has been created for the quadstore being queried.
|
|
53
|
+
* @param onDone - callback when query finished
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
export function indexedFormulaQuery(myQuery, callback, fetcher, onDone) {
|
|
57
|
+
/** Debug strings
|
|
58
|
+
*/
|
|
59
|
+
function bindingDebug(b) {
|
|
60
|
+
var str = '';
|
|
61
|
+
var v;
|
|
62
|
+
|
|
63
|
+
for (v in b) {
|
|
64
|
+
if (b.hasOwnProperty(v)) {
|
|
65
|
+
str += ' ' + v + ' -> ' + b[v];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return str;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function bindingsDebug(nbs) {
|
|
73
|
+
var str = 'Bindings: ';
|
|
74
|
+
var i;
|
|
75
|
+
var n = nbs.length;
|
|
76
|
+
|
|
77
|
+
for (i = 0; i < n; i++) {
|
|
78
|
+
str += bindingDebug(nbs[i][0]) + ';\n\t';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return str;
|
|
82
|
+
} // bindingsDebug
|
|
83
|
+
|
|
84
|
+
/** Unification
|
|
85
|
+
*
|
|
86
|
+
* Unification finds all bindings such that when the binding is applied
|
|
87
|
+
* to one term it is equal to the other.
|
|
88
|
+
* @returns {Arrray}- a list of bindings, where a binding is an associative array
|
|
89
|
+
* mapping variuable to value.
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
function unifyTerm(self, other, bindings, formula) {
|
|
94
|
+
var actual = bindings[self];
|
|
95
|
+
|
|
96
|
+
if (actual === undefined) {
|
|
97
|
+
// Not mapped
|
|
98
|
+
if (self.isVar) {
|
|
99
|
+
var b = [];
|
|
100
|
+
b[self] = other;
|
|
101
|
+
return [[b, null]]; // Match
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
actual = self;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!actual.complexType) {
|
|
108
|
+
if (formula.redirections[actual]) {
|
|
109
|
+
actual = formula.redirections[actual];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (formula.redirections[other]) {
|
|
113
|
+
other = formula.redirections[other];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (actual.equals(other) || actual.uri && actual.uri === defaultDocumentURI) {
|
|
117
|
+
// Used to mean 'any graph' in a query
|
|
118
|
+
return [[[], null]];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (self instanceof Array) {
|
|
125
|
+
if (!(other instanceof Array)) {
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return unifyContents(self, other, bindings);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
throw new Error('query.js: oops - code not written yet'); // return undefined; // for lint - no jslint objects to unreachables
|
|
133
|
+
// return actual.unifyContents(other, bindings)
|
|
134
|
+
} // unifyTerm
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
function unifyContents(self, other, bindings, formula) {
|
|
138
|
+
var nbs2;
|
|
139
|
+
|
|
140
|
+
if (self.length !== other.length) {
|
|
141
|
+
return []; // no way
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (!self.length) {
|
|
145
|
+
return [[[], null]]; // Success
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
var nbs = unifyTerm(self[0], other[0], bindings, formula);
|
|
149
|
+
|
|
150
|
+
if (nbs.length === 0) {
|
|
151
|
+
return nbs;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
var res = [];
|
|
155
|
+
var i;
|
|
156
|
+
var n = nbs.length;
|
|
157
|
+
var nb;
|
|
158
|
+
var j;
|
|
159
|
+
var m;
|
|
160
|
+
var v;
|
|
161
|
+
var nb2;
|
|
162
|
+
var bindings2;
|
|
163
|
+
|
|
164
|
+
for (i = 0; i < n; i++) {
|
|
165
|
+
// for each possibility from the first term
|
|
166
|
+
nb = nbs[i][0]; // new bindings
|
|
167
|
+
|
|
168
|
+
bindings2 = [];
|
|
169
|
+
|
|
170
|
+
for (v in nb) {
|
|
171
|
+
if (nb.hasOwnProperty(v)) {
|
|
172
|
+
bindings2[v] = nb[v]; // copy
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
for (v in bindings) {
|
|
177
|
+
if (bindings.hasOwnProperty(v)) {
|
|
178
|
+
bindings2[v] = bindings[v]; // copy
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
nbs2 = unifyContents(self.slice(1), other.slice(1), bindings2, formula);
|
|
183
|
+
m = nbs2.length;
|
|
184
|
+
|
|
185
|
+
for (j = 0; j < m; j++) {
|
|
186
|
+
nb2 = nbs2[j][0]; // @@@@ no idea whether this is used or right
|
|
187
|
+
|
|
188
|
+
for (v in nb) {
|
|
189
|
+
if (nb.hasOwnProperty(v)) {
|
|
190
|
+
nb2[v] = nb[v];
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
res.push([nb2, null]);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return res;
|
|
199
|
+
} // unifyContents
|
|
200
|
+
// Matching
|
|
201
|
+
//
|
|
202
|
+
// Matching finds all bindings such that when the binding is applied
|
|
203
|
+
// to one term it is equal to the other term. We only match formulae.
|
|
204
|
+
|
|
205
|
+
/** if x is not in the bindings array, return the var; otherwise, return the bindings **/
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
function bind(x, binding) {
|
|
209
|
+
var y = binding[x];
|
|
210
|
+
|
|
211
|
+
if (y === undefined) {
|
|
212
|
+
return x;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return y;
|
|
216
|
+
} // When there are OPTIONAL clauses, we must return bindings without them if none of them
|
|
217
|
+
// succeed. However, if any of them do succeed, we should not. (This is what branchCount()
|
|
218
|
+
// tracked. The problem currently is (2011/7) that when several optionals exist, and they
|
|
219
|
+
// all match, multiple sets of bindings are returned, each with one optional filled in.)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
function union(a, b) {
|
|
223
|
+
var c = {};
|
|
224
|
+
var x;
|
|
225
|
+
|
|
226
|
+
for (x in a) {
|
|
227
|
+
if (a.hasOwnProperty(x)) {
|
|
228
|
+
c[x] = a[x];
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
for (x in b) {
|
|
233
|
+
if (b.hasOwnProperty(x)) {
|
|
234
|
+
c[x] = b[x];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return c;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function OptionalBranchJunction(originalCallback, trunkBindings) {
|
|
242
|
+
this.trunkBindings = trunkBindings;
|
|
243
|
+
this.originalCallback = originalCallback;
|
|
244
|
+
this.branches = []; // this.results = []; // result[i] is an array of bindings for branch i
|
|
245
|
+
// this.done = {}; // done[i] means all/any results are in for branch i
|
|
246
|
+
// this.count = {}
|
|
247
|
+
|
|
248
|
+
return this;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
OptionalBranchJunction.prototype.checkAllDone = function () {
|
|
252
|
+
var i;
|
|
253
|
+
|
|
254
|
+
for (i = 0; i < this.branches.length; i++) {
|
|
255
|
+
if (!this.branches[i].done) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
log.debug('OPTIONAL BIDNINGS ALL DONE:');
|
|
261
|
+
this.doCallBacks(this.branches.length - 1, this.trunkBindings);
|
|
262
|
+
}; // Recrursively generate the cross product of the bindings
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
OptionalBranchJunction.prototype.doCallBacks = function (b, bindings) {
|
|
266
|
+
var j;
|
|
267
|
+
|
|
268
|
+
if (b < 0) {
|
|
269
|
+
return this.originalCallback(bindings);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
for (j = 0; j < this.branches[b].results.length; j++) {
|
|
273
|
+
this.doCallBacks(b - 1, union(bindings, this.branches[b].results[j]));
|
|
274
|
+
}
|
|
275
|
+
}; // A mandatory branch is the normal one, where callbacks
|
|
276
|
+
// are made immediately and no junction is needed.
|
|
277
|
+
// Might be useful for onFinsihed callback for query API.
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
function MandatoryBranch(callback, onDone) {
|
|
281
|
+
this.count = 0;
|
|
282
|
+
this.success = false;
|
|
283
|
+
this.done = false; // this.results = []
|
|
284
|
+
|
|
285
|
+
this.callback = callback;
|
|
286
|
+
this.onDone = onDone; // this.junction = junction
|
|
287
|
+
// junction.branches.push(this)
|
|
288
|
+
|
|
289
|
+
return this;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
MandatoryBranch.prototype.reportMatch = function (bindings) {
|
|
293
|
+
// log.error("@@@@ query.js 1"); // @@
|
|
294
|
+
this.callback(bindings);
|
|
295
|
+
this.success = true;
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
MandatoryBranch.prototype.reportDone = function () {
|
|
299
|
+
this.done = true;
|
|
300
|
+
log.info('Mandatory query branch finished.***');
|
|
301
|
+
|
|
302
|
+
if (this.onDone !== undefined) {
|
|
303
|
+
this.onDone();
|
|
304
|
+
}
|
|
305
|
+
}; // An optional branch hoards its results.
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
var OptionalBranch = function OptionalBranch(junction) {
|
|
309
|
+
this.count = 0;
|
|
310
|
+
this.done = false;
|
|
311
|
+
this.results = [];
|
|
312
|
+
this.junction = junction;
|
|
313
|
+
junction.branches.push(this);
|
|
314
|
+
return this;
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
OptionalBranch.prototype.reportMatch = function (bindings) {
|
|
318
|
+
this.results.push(bindings);
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
OptionalBranch.prototype.reportDone = function () {
|
|
322
|
+
log.debug('Optional branch finished - results.length = ' + this.results.length);
|
|
323
|
+
|
|
324
|
+
if (this.results.length === 0) {
|
|
325
|
+
// This is what optional means: if no hits,
|
|
326
|
+
this.results.push({}); // mimic success, but with no bindings
|
|
327
|
+
|
|
328
|
+
log.debug("Optional branch FAILED - that's OK.");
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
this.done = true;
|
|
332
|
+
this.junction.checkAllDone();
|
|
333
|
+
};
|
|
334
|
+
/** prepare -- sets the index of the item to the possible matches
|
|
335
|
+
* @param f - formula
|
|
336
|
+
* @param item - an Statement, possibly w/ vars in it
|
|
337
|
+
* @param bindings - Bindings so far
|
|
338
|
+
* @returns false if the query fails -- there are no items that match
|
|
339
|
+
*/
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
function prepare(f, item, bindings) {
|
|
343
|
+
var terms, termIndex, i, ind;
|
|
344
|
+
item.nvars = 0;
|
|
345
|
+
item.index = null; // if (!f.statements) log.warn("@@@ prepare: f is "+f)
|
|
346
|
+
// log.debug("Prepare: f has "+ f.statements.length)
|
|
347
|
+
// log.debug("Prepare: Kb size "+f.statements.length+" Preparing "+item)
|
|
348
|
+
|
|
349
|
+
terms = [item.subject, item.predicate, item.object, item.why];
|
|
350
|
+
ind = [f.subjectIndex, f.predicateIndex, f.objectIndex, f.whyIndex];
|
|
351
|
+
|
|
352
|
+
for (i = 0; i < 4; i++) {
|
|
353
|
+
var t = terms[i]; // console.log(" Prepare (" + t + ") "+(t in bindings))
|
|
354
|
+
|
|
355
|
+
if (t.uri && t.uri === defaultDocumentURI) {// chrome:session
|
|
356
|
+
// console.log(' query: Ignoring slot ' + i)
|
|
357
|
+
} else if (t.isVar && !(bindings[t] !== undefined)) {
|
|
358
|
+
item.nvars++;
|
|
359
|
+
} else {
|
|
360
|
+
t = bind(terms[i], bindings); // returns the RDF binding if bound, otherwise itself
|
|
361
|
+
// if (terms[i]!=bind(terms[i],bindings) alert("Term: "+terms[i]+"Binding: "+bind(terms[i], bindings))
|
|
362
|
+
|
|
363
|
+
if (f.redirections[f.id(t)]) {
|
|
364
|
+
t = f.redirections[f.id(t)]; // redirect
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
termIndex = ind[i][f.id(t)];
|
|
368
|
+
|
|
369
|
+
if (!termIndex) {
|
|
370
|
+
item.index = [];
|
|
371
|
+
return false; // Query line cannot match
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (item.index === null || item.index.length > termIndex.length) {
|
|
375
|
+
// Find smallest index
|
|
376
|
+
item.index = termIndex;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (item.index === null) {
|
|
382
|
+
// All 4 are variables?
|
|
383
|
+
item.index = f.statements;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return true;
|
|
387
|
+
} // prepare
|
|
388
|
+
|
|
389
|
+
/** sorting function -- negative if self is easier **/
|
|
390
|
+
// We always prefer to start with a URI to be able to browse a graph
|
|
391
|
+
// this is why we put off items with more variables till later.
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
function easiestQuery(self, other) {
|
|
395
|
+
if (self.nvars !== other.nvars) {
|
|
396
|
+
return self.nvars - other.nvars;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return self.index.length - other.index.length;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
var matchIndex = 0; // index
|
|
403
|
+
|
|
404
|
+
/** matches a pattern formula against the knowledge base, e.g. to find matches for table-view
|
|
405
|
+
*
|
|
406
|
+
* @param f - knowledge base formula
|
|
407
|
+
* @param g - pattern formula (may have vars)
|
|
408
|
+
* @param bindingsSoFar - bindings accumulated in matching to date
|
|
409
|
+
* @param level - spaces to indent stuff also lets you know what level of recursion you're at
|
|
410
|
+
* @param fetcher - function (term, requestedBy) If you want link following
|
|
411
|
+
* @param localCallback - function(bindings, pattern, branch) called on sucess
|
|
412
|
+
* @returns nothing
|
|
413
|
+
*
|
|
414
|
+
* Will fetch linked data from the web iff the knowledge base an associated source fetcher (f.fetcher)
|
|
415
|
+
***/
|
|
416
|
+
|
|
417
|
+
var match = function match(f, g, bindingsSoFar, level, fetcher, localCallback, branch) {
|
|
418
|
+
log.debug('Match begins, Branch count now: ' + branch.count + ' for ' + branch.pattern_debug); // log.debug("match: f has "+f.statements.length+", g has "+g.statements.length)
|
|
419
|
+
|
|
420
|
+
var pattern = g.statements;
|
|
421
|
+
|
|
422
|
+
if (pattern.length === 0) {
|
|
423
|
+
// when it's satisfied all the pattern triples
|
|
424
|
+
log.debug('FOUND MATCH WITH BINDINGS:' + bindingDebug(bindingsSoFar));
|
|
425
|
+
|
|
426
|
+
if (g.optional.length === 0) {
|
|
427
|
+
branch.reportMatch(bindingsSoFar);
|
|
428
|
+
} else {
|
|
429
|
+
log.debug('OPTIONAL: ' + g.optional);
|
|
430
|
+
var junction = new OptionalBranchJunction(callback, bindingsSoFar); // @@ won't work with nested optionals? nest callbacks
|
|
431
|
+
|
|
432
|
+
var br = [];
|
|
433
|
+
var b;
|
|
434
|
+
|
|
435
|
+
for (b = 0; b < g.optional.length; b++) {
|
|
436
|
+
br[b] = new OptionalBranch(junction); // Allocate branches to prevent premature ending
|
|
437
|
+
|
|
438
|
+
br[b].pattern_debug = g.optional[b]; // for diagnotics only
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
for (b = 0; b < g.optional.length; b++) {
|
|
442
|
+
br[b].count = br[b].count + 1; // Count how many matches we have yet to complete
|
|
443
|
+
|
|
444
|
+
match(f, g.optional[b], bindingsSoFar, '', fetcher, callback, br[b]);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
branch.count--;
|
|
449
|
+
log.debug('Match ends -- success , Branch count now: ' + branch.count + ' for ' + branch.pattern_debug);
|
|
450
|
+
return; // Success
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
var item;
|
|
454
|
+
var i;
|
|
455
|
+
var n = pattern.length; // log.debug(level + "Match "+n+" left, bs so far:"+bindingDebug(bindingsSoFar))
|
|
456
|
+
// Follow links from variables in query
|
|
457
|
+
|
|
458
|
+
if (fetcher) {
|
|
459
|
+
// Fetcher is used to fetch URIs, function first term is a URI term, second is the requester
|
|
460
|
+
var id = 'match' + matchIndex++;
|
|
461
|
+
|
|
462
|
+
var fetchResource = function fetchResource(requestedTerm, id) {
|
|
463
|
+
var docuri = requestedTerm.uri.split('#')[0];
|
|
464
|
+
fetcher.nowOrWhenFetched(docuri, undefined, function (ok, body, xhr) {
|
|
465
|
+
if (!ok) {
|
|
466
|
+
console.log('Error following link to <' + requestedTerm.uri + '> in query: ' + body);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
match(f, g, bindingsSoFar, level, fetcher, // match not match2 to look up any others necessary.
|
|
470
|
+
localCallback, branch);
|
|
471
|
+
});
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
for (i = 0; i < n; i++) {
|
|
475
|
+
item = pattern[i]; // for each of the triples in the query
|
|
476
|
+
|
|
477
|
+
if (bindingsSoFar[item.subject] !== undefined && bindingsSoFar[item.subject].uri && fetcher && fetcher.getState(docpart(bindingsSoFar[item.subject].uri)) === 'unrequested') {
|
|
478
|
+
// fetch the subject info and return to id
|
|
479
|
+
fetchResource(bindingsSoFar[item.subject], id);
|
|
480
|
+
return; // only look up one per line this time, but we will come back again though match
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (bindingsSoFar[item.object] !== undefined && bindingsSoFar[item.object].uri && fetcher && fetcher.getState(docpart(bindingsSoFar[item.object].uri)) === 'unrequested') {
|
|
484
|
+
fetchResource(bindingsSoFar[item.object], id);
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
} // if fetcher
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
match2(f, g, bindingsSoFar, level, fetcher, localCallback, branch);
|
|
492
|
+
}; // match
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
var constraintsSatisfied = function constraintsSatisfied(bindings, constraints) {
|
|
496
|
+
var res = true;
|
|
497
|
+
var x;
|
|
498
|
+
var test;
|
|
499
|
+
|
|
500
|
+
for (x in bindings) {
|
|
501
|
+
if (bindings.hasOwnProperty(x)) {
|
|
502
|
+
if (constraints[x]) {
|
|
503
|
+
test = constraints[x].test;
|
|
504
|
+
|
|
505
|
+
if (test && !test(bindings[x])) {
|
|
506
|
+
res = false;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
return res;
|
|
513
|
+
};
|
|
514
|
+
/** match2 -- stuff after the fetch **/
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
var match2 = function match2(f, g, bindingsSoFar, level, fetcher, callback, branch) {
|
|
518
|
+
// post fetch
|
|
519
|
+
var pattern = g.statements;
|
|
520
|
+
var n = pattern.length;
|
|
521
|
+
var i;
|
|
522
|
+
var k;
|
|
523
|
+
var nk;
|
|
524
|
+
var v;
|
|
525
|
+
var bindings2;
|
|
526
|
+
var newBindings1;
|
|
527
|
+
var item;
|
|
528
|
+
|
|
529
|
+
for (i = 0; i < n; i++) {
|
|
530
|
+
// For each statement left in the query, run prepare
|
|
531
|
+
item = pattern[i]; // log.info('match2: item=' + item + ', bindingsSoFar=' + bindingDebug(bindingsSoFar))
|
|
532
|
+
|
|
533
|
+
prepare(f, item, bindingsSoFar); // if (item.index) console.log(' item.index.length ' + item.index.length)
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
pattern.sort(easiestQuery);
|
|
537
|
+
item = pattern[0]; // log.debug("Sorted pattern:\n"+pattern)
|
|
538
|
+
|
|
539
|
+
var rest = f.formula();
|
|
540
|
+
rest.optional = g.optional;
|
|
541
|
+
rest.constraints = g.constraints;
|
|
542
|
+
rest.statements = pattern.slice(1); // No indexes: we will not query g.
|
|
543
|
+
|
|
544
|
+
log.debug(level + 'match2 searching ' + item.index.length + ' for ' + item + '; bindings so far=' + bindingDebug(bindingsSoFar)); // var results = []
|
|
545
|
+
|
|
546
|
+
var c;
|
|
547
|
+
var nc = item.index.length;
|
|
548
|
+
var nbs1;
|
|
549
|
+
var st;
|
|
550
|
+
var onward = 0; // var x
|
|
551
|
+
|
|
552
|
+
for (c = 0; c < nc; c++) {
|
|
553
|
+
// For each candidate statement
|
|
554
|
+
st = item.index[c]; // for each statement in the item's index, spawn a new match with that binding
|
|
555
|
+
|
|
556
|
+
nbs1 = unifyContents([item.subject, item.predicate, item.object, item.why], [st.subject, st.predicate, st.object, st.why], bindingsSoFar, f);
|
|
557
|
+
log.info(level + ' From first: ' + nbs1.length + ': ' + bindingsDebug(nbs1));
|
|
558
|
+
nk = nbs1.length; // branch.count += nk
|
|
559
|
+
// log.debug("Branch count bumped "+nk+" to: "+branch.count)
|
|
560
|
+
|
|
561
|
+
for (k = 0; k < nk; k++) {
|
|
562
|
+
// For each way that statement binds
|
|
563
|
+
bindings2 = [];
|
|
564
|
+
newBindings1 = nbs1[k][0];
|
|
565
|
+
|
|
566
|
+
if (!constraintsSatisfied(newBindings1, g.constraints)) {
|
|
567
|
+
// branch.count--
|
|
568
|
+
log.debug('Branch count CS: ' + branch.count);
|
|
569
|
+
} else {
|
|
570
|
+
for (v in newBindings1) {
|
|
571
|
+
if (newBindings1.hasOwnProperty(v)) {
|
|
572
|
+
bindings2[v] = newBindings1[v]; // copy
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
for (v in bindingsSoFar) {
|
|
577
|
+
if (bindingsSoFar.hasOwnProperty(v)) {
|
|
578
|
+
bindings2[v] = bindingsSoFar[v]; // copy
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
branch.count++; // Count how many matches we have yet to complete
|
|
583
|
+
|
|
584
|
+
onward++;
|
|
585
|
+
match(f, rest, bindings2, level + ' ', fetcher, callback, branch); // call match
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
branch.count--;
|
|
591
|
+
|
|
592
|
+
if (onward === 0) {
|
|
593
|
+
log.debug('Match2 fails completely on ' + item);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
log.debug('Match2 ends, Branch count: ' + branch.count + ' for ' + branch.pattern_debug);
|
|
597
|
+
|
|
598
|
+
if (branch.count === 0) {
|
|
599
|
+
log.debug('Branch finished.');
|
|
600
|
+
branch.reportDone();
|
|
601
|
+
}
|
|
602
|
+
}; // match2
|
|
603
|
+
// ////////////////////////// Body of query() ///////////////////////
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
var f = this;
|
|
607
|
+
log.debug('Query on ' + this.statements.length);
|
|
608
|
+
var trunck = new MandatoryBranch(callback, onDone);
|
|
609
|
+
trunck.count++; // count one branch to complete at the moment
|
|
610
|
+
|
|
611
|
+
if (myQuery.sync) {
|
|
612
|
+
match(f, myQuery.pat, myQuery.pat.initBindings, '', fetcher, callback, trunck);
|
|
613
|
+
} else {
|
|
614
|
+
// Give up thread: Allow other activities to run
|
|
615
|
+
setTimeout(function () {
|
|
616
|
+
match(f, myQuery.pat, myQuery.pat.initBindings, '', fetcher, callback, trunck);
|
|
617
|
+
}, 0);
|
|
618
|
+
} // returns nothing; callback does the work
|
|
619
|
+
|
|
620
|
+
} // query
|