rdflib 2.2.21 → 2.2.22-04669b23

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.
Files changed (118) hide show
  1. package/dist/rdflib.min.js +1 -1
  2. package/dist/rdflib.min.js.LICENSE.txt +11 -1
  3. package/dist/rdflib.min.js.map +1 -1
  4. package/esm/blank-node.js +61 -114
  5. package/esm/class-order.js +1 -1
  6. package/esm/collection.js +70 -128
  7. package/esm/default-graph.js +14 -48
  8. package/esm/empty.js +8 -39
  9. package/esm/factories/canonical-data-factory.js +33 -65
  10. package/esm/factories/extended-term-factory.js +18 -25
  11. package/esm/factories/factory-types.js +3 -2
  12. package/esm/factories/rdflib-data-factory.js +9 -19
  13. package/esm/fetcher.js +1341 -1854
  14. package/esm/formula.js +639 -846
  15. package/esm/index.js +40 -77
  16. package/esm/jsonldparser.js +34 -50
  17. package/esm/jsonparser.js +1 -8
  18. package/esm/lists.js +47 -110
  19. package/esm/literal.js +120 -189
  20. package/esm/log.js +7 -7
  21. package/esm/n3parser.js +1022 -1412
  22. package/esm/named-node.js +70 -119
  23. package/esm/namespace.js +2 -5
  24. package/esm/node-internal.js +73 -110
  25. package/esm/node.js +2 -7
  26. package/esm/parse.js +12 -19
  27. package/esm/patch-parser.js +10 -30
  28. package/esm/query-to-sparql.js +0 -18
  29. package/esm/query.js +63 -147
  30. package/esm/rdfaparser.js +794 -997
  31. package/esm/rdfxmlparser.js +347 -461
  32. package/esm/serialize.js +9 -34
  33. package/esm/serializer.js +842 -1048
  34. package/esm/sparql-to-query.js +44 -134
  35. package/esm/statement.js +54 -85
  36. package/esm/store.js +830 -1103
  37. package/esm/types.js +22 -21
  38. package/esm/update-manager.js +869 -1106
  39. package/esm/updates-via.js +104 -161
  40. package/esm/uri.js +9 -53
  41. package/esm/utils/default-graph-uri.js +3 -2
  42. package/esm/utils/termValue.js +0 -1
  43. package/esm/utils/terms.js +19 -21
  44. package/esm/utils-js.js +20 -61
  45. package/esm/utils.js +10 -21
  46. package/esm/variable.js +32 -78
  47. package/esm/xsd.js +2 -2
  48. package/lib/blank-node.js +60 -113
  49. package/lib/class-order.js +1 -2
  50. package/lib/collection.js +69 -131
  51. package/lib/default-graph.js +13 -52
  52. package/lib/empty.js +8 -43
  53. package/lib/factories/canonical-data-factory.js +35 -79
  54. package/lib/factories/extended-term-factory.js +18 -32
  55. package/lib/factories/factory-types.d.ts +6 -6
  56. package/lib/factories/factory-types.js +1 -4
  57. package/lib/factories/rdflib-data-factory.js +9 -23
  58. package/lib/fetcher.d.ts +6 -6
  59. package/lib/fetcher.js +1370 -1843
  60. package/lib/formula.d.ts +1 -1
  61. package/lib/formula.js +640 -855
  62. package/lib/index.d.ts +1 -2
  63. package/lib/index.js +67 -156
  64. package/lib/jsonldparser.js +33 -54
  65. package/lib/jsonparser.js +1 -10
  66. package/lib/lists.js +55 -112
  67. package/lib/literal.js +120 -195
  68. package/lib/log.d.ts +0 -6
  69. package/lib/log.js +7 -8
  70. package/lib/n3parser.d.ts +1 -0
  71. package/lib/n3parser.js +1023 -1422
  72. package/lib/named-node.js +69 -126
  73. package/lib/namespace.js +2 -7
  74. package/lib/node-internal.js +74 -107
  75. package/lib/node.js +2 -12
  76. package/lib/parse.d.ts +1 -1
  77. package/lib/parse.js +12 -32
  78. package/lib/patch-parser.js +11 -34
  79. package/lib/query-to-sparql.js +0 -23
  80. package/lib/query.js +62 -167
  81. package/lib/rdfaparser.js +796 -1009
  82. package/lib/rdfxmlparser.js +349 -466
  83. package/lib/serialize.d.ts +1 -1
  84. package/lib/serialize.js +9 -44
  85. package/lib/serializer.d.ts +1 -0
  86. package/lib/serializer.js +846 -1063
  87. package/lib/sparql-to-query.js +42 -167
  88. package/lib/statement.js +55 -91
  89. package/lib/store.d.ts +2 -2
  90. package/lib/store.js +850 -1112
  91. package/lib/tf-types.d.ts +4 -4
  92. package/lib/types.d.ts +8 -8
  93. package/lib/types.js +23 -23
  94. package/lib/update-manager.d.ts +1 -1
  95. package/lib/update-manager.js +865 -1103
  96. package/lib/updates-via.js +105 -164
  97. package/lib/uri.js +8 -61
  98. package/lib/utils/default-graph-uri.js +3 -5
  99. package/lib/utils/termValue.js +0 -2
  100. package/lib/utils/terms.js +19 -40
  101. package/lib/utils-js.js +23 -88
  102. package/lib/utils.js +10 -27
  103. package/lib/variable.js +34 -85
  104. package/lib/xsd-internal.js +0 -3
  105. package/lib/xsd.js +2 -6
  106. package/package.json +40 -39
  107. package/src/fetcher.ts +2 -2
  108. package/src/index.ts +0 -2
  109. package/src/jsonldparser.js +13 -4
  110. package/src/n3parser.js +12 -4
  111. package/src/serialize.ts +4 -11
  112. package/src/serializer.js +24 -0
  113. package/src/update-manager.ts +12 -7
  114. package/changes.txt +0 -59
  115. package/esm/convert.js +0 -61
  116. package/lib/convert.d.ts +0 -2
  117. package/lib/convert.js +0 -77
  118. package/src/convert.js +0 -70
package/esm/serializer.js CHANGED
@@ -1,7 +1,4 @@
1
- import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
- import _createClass from "@babel/runtime/helpers/createClass";
3
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
-
5
2
  /* Serialization of RDF Graphs
6
3
  **
7
4
  ** Tim Berners-Lee 2006
@@ -16,1201 +13,998 @@ import * as Util from './utils-js';
16
13
  import CanonicalDataFactory from './factories/canonical-data-factory';
17
14
  import { createXSD } from './xsd';
18
15
  import solidNs from 'solid-namespace';
16
+ // import * as jsonld from 'jsonld'
17
+ import * as ttl2jsonld from '@frogcat/ttl2jsonld';
19
18
  export default function createSerializer(store) {
20
19
  return new Serializer(store);
21
20
  }
22
21
  ;
23
- export var Serializer = /*#__PURE__*/function () {
24
- function Serializer(store) {
25
- _classCallCheck(this, Serializer);
26
-
22
+ export class Serializer {
23
+ constructor(store) {
27
24
  _defineProperty(this, "_notQNameChars", '\t\r\n !"#$%&\'()*.,+/;<=>?@[\\]^`{|}~');
28
-
29
25
  _defineProperty(this, "_notNameChars", this._notQNameChars + ':');
30
-
31
26
  _defineProperty(this, "validPrefix", new RegExp(/^[a-zA-Z][a-zA-Z0-9]*$/));
32
-
33
27
  _defineProperty(this, "forbidden1", new RegExp(/[\\"\b\f\r\v\t\n\u0080-\uffff]/gm));
34
-
35
28
  _defineProperty(this, "forbidden3", new RegExp(/[\\"\b\f\r\v\u0080-\uffff]/gm));
36
-
37
29
  this.flags = '';
38
30
  this.base = null;
39
31
  this.prefixes = []; // suggested prefixes
40
-
41
32
  this.namespaces = []; // complementary
42
-
43
- var nsKeys = Object.keys(solidNs());
44
-
45
- for (var i in nsKeys) {
46
- var uri = solidNs()[nsKeys[i]]('');
47
- var prefix = nsKeys[i];
33
+ const nsKeys = Object.keys(solidNs());
34
+ for (const i in nsKeys) {
35
+ const uri = solidNs()[nsKeys[i]]('');
36
+ const prefix = nsKeys[i];
48
37
  this.prefixes[uri] = prefix;
49
38
  this.namespaces[prefix] = uri;
50
39
  }
51
-
52
40
  this.suggestPrefix('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'); // XML code assumes this!
53
-
54
41
  this.suggestPrefix('xml', 'reserved:reservedForFutureUse'); // XML reserves xml: in the spec.
55
42
 
56
43
  this.namespacesUsed = []; // Count actually used and so needed in @prefixes
57
-
58
44
  this.keywords = ['a']; // The only one we generate at the moment
59
-
60
45
  this.prefixchars = 'abcdefghijklmnopqustuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
61
46
  this.incoming = null; // Array not calculated yet
62
-
63
47
  this.formulas = []; // remembering original formulae from hashes
64
-
65
48
  this.store = store;
66
49
  this.rdfFactory = store.rdfFactory || CanonicalDataFactory;
67
50
  this.xsd = createXSD(this.rdfFactory);
68
51
  }
69
-
70
- _createClass(Serializer, [{
71
- key: "setBase",
72
- value: function setBase(base) {
73
- this.base = base;
74
- return this;
75
- }
76
- }, {
77
- key: "setFlags",
78
- value: function setFlags(flags) {
79
- this.flags = flags || '';
80
- return this;
52
+ setBase(base) {
53
+ this.base = base;
54
+ return this;
55
+ }
56
+ setFlags(flags) {
57
+ this.flags = flags || '';
58
+ return this;
59
+ }
60
+ toStr(x) {
61
+ var s = x.toNT();
62
+ if (x.termType === 'Graph') {
63
+ this.formulas[s] = x; // remember as reverse does not work
81
64
  }
82
- }, {
83
- key: "toStr",
84
- value: function toStr(x) {
85
- var s = x.toNT();
86
-
87
- if (x.termType === 'Graph') {
88
- this.formulas[s] = x; // remember as reverse does not work
89
- }
90
65
 
91
- return s;
66
+ return s;
67
+ }
68
+ fromStr(s) {
69
+ if (s[0] === '{') {
70
+ var x = this.formulas[s];
71
+ if (!x) console.log('No formula object for ' + s);
72
+ return x;
92
73
  }
93
- }, {
94
- key: "fromStr",
95
- value: function fromStr(s) {
96
- if (s[0] === '{') {
97
- var x = this.formulas[s];
98
- if (!x) console.log('No formula object for ' + s);
99
- return x;
100
- }
74
+ return this.store.fromNT(s);
75
+ }
101
76
 
102
- return this.store.fromNT(s);
77
+ /**
78
+ * Defines a set of [prefix, namespace] pairs to be used by this Serializer instance.
79
+ * Overrides previous prefixes if any
80
+ * @param namespaces
81
+ * @return {Serializer}
82
+ */
83
+ setNamespaces(namespaces) {
84
+ for (var px in namespaces) {
85
+ this.setPrefix(px, namespaces[px]);
103
86
  }
104
- /**
105
- * Defines a set of [prefix, namespace] pairs to be used by this Serializer instance.
106
- * Overrides previous prefixes if any
107
- * @param namespaces
108
- * @return {Serializer}
109
- */
110
-
111
- }, {
112
- key: "setNamespaces",
113
- value: function setNamespaces(namespaces) {
114
- for (var px in namespaces) {
115
- this.setPrefix(px, namespaces[px]);
116
- }
87
+ return this;
88
+ }
117
89
 
118
- return this;
90
+ /**
91
+ * Defines a namespace prefix, overriding any existing prefix for that URI
92
+ * @param prefix
93
+ * @param uri
94
+ */
95
+ setPrefix(prefix, uri) {
96
+ if (prefix.slice(0, 7) === 'default') return; // Try to weed these out
97
+ if (prefix.slice(0, 2) === 'ns') return; // From others inferior algos
98
+ if (!prefix || !uri) return; // empty strings not suitable
99
+
100
+ // remove any existing prefix targeting this uri
101
+ // for (let existingPrefix in this.namespaces) {
102
+ // if (this.namespaces[existingPrefix] == uri)
103
+ // delete this.namespaces[existingPrefix];
104
+ // }
105
+
106
+ // remove any existing mapping for this prefix
107
+ for (let existingNs in this.prefixes) {
108
+ if (this.prefixes[existingNs] == prefix) delete this.prefixes[existingNs];
119
109
  }
120
- /**
121
- * Defines a namespace prefix, overriding any existing prefix for that URI
122
- * @param prefix
123
- * @param uri
124
- */
125
-
126
- }, {
127
- key: "setPrefix",
128
- value: function setPrefix(prefix, uri) {
129
- if (prefix.slice(0, 7) === 'default') return; // Try to weed these out
130
-
131
- if (prefix.slice(0, 2) === 'ns') return; // From others inferior algos
132
-
133
- if (!prefix || !uri) return; // empty strings not suitable
134
- // remove any existing prefix targeting this uri
135
- // for (let existingPrefix in this.namespaces) {
136
- // if (this.namespaces[existingPrefix] == uri)
137
- // delete this.namespaces[existingPrefix];
138
- // }
139
- // remove any existing mapping for this prefix
110
+ this.prefixes[uri] = prefix;
111
+ this.namespaces[prefix] = uri;
112
+ }
140
113
 
141
- for (var existingNs in this.prefixes) {
142
- if (this.prefixes[existingNs] == prefix) delete this.prefixes[existingNs];
143
- }
114
+ /* Accumulate Namespaces
115
+ **
116
+ ** These are only hints. If two overlap, only one gets used
117
+ ** There is therefore no guarantee in general.
118
+ */
119
+ suggestPrefix(prefix, uri) {
120
+ if (prefix.slice(0, 7) === 'default') return; // Try to weed these out
121
+ if (prefix.slice(0, 2) === 'ns') return; // From others inferior algos
122
+ if (!prefix || !uri) return; // empty strings not suitable
123
+ if (prefix in this.namespaces || uri in this.prefixes) return; // already used
124
+ this.prefixes[uri] = prefix;
125
+ this.namespaces[prefix] = uri;
126
+ }
144
127
 
145
- this.prefixes[uri] = prefix;
146
- this.namespaces[prefix] = uri;
128
+ // Takes a namespace -> prefix map
129
+ suggestNamespaces(namespaces) {
130
+ for (var px in namespaces) {
131
+ this.suggestPrefix(px, namespaces[px]);
147
132
  }
148
- /* Accumulate Namespaces
149
- **
150
- ** These are only hints. If two overlap, only one gets used
151
- ** There is therefore no guarantee in general.
152
- */
153
-
154
- }, {
155
- key: "suggestPrefix",
156
- value: function suggestPrefix(prefix, uri) {
157
- if (prefix.slice(0, 7) === 'default') return; // Try to weed these out
158
-
159
- if (prefix.slice(0, 2) === 'ns') return; // From others inferior algos
160
-
161
- if (!prefix || !uri) return; // empty strings not suitable
162
-
163
- if (prefix in this.namespaces || uri in this.prefixes) return; // already used
164
-
165
- this.prefixes[uri] = prefix;
166
- this.namespaces[prefix] = uri;
167
- } // Takes a namespace -> prefix map
168
-
169
- }, {
170
- key: "suggestNamespaces",
171
- value: function suggestNamespaces(namespaces) {
172
- for (var px in namespaces) {
173
- this.suggestPrefix(px, namespaces[px]);
133
+ return this;
134
+ }
135
+ checkIntegrity() {
136
+ var p, ns;
137
+ for (p in this.namespaces) {
138
+ if (this.prefixes[this.namespaces[p]] !== p) {
139
+ throw new Error('Serializer integity error 1: ' + p + ', ' + this.namespaces[p] + ', ' + this.prefixes[this.namespaces[p]] + '!');
174
140
  }
175
-
176
- return this;
177
141
  }
178
- }, {
179
- key: "checkIntegrity",
180
- value: function checkIntegrity() {
181
- var p, ns;
182
-
183
- for (p in this.namespaces) {
184
- if (this.prefixes[this.namespaces[p]] !== p) {
185
- throw new Error('Serializer integity error 1: ' + p + ', ' + this.namespaces[p] + ', ' + this.prefixes[this.namespaces[p]] + '!');
186
- }
187
- }
188
-
189
- for (ns in this.prefixes) {
190
- if (this.namespaces[this.prefixes[ns]] !== ns) {
191
- throw new Error('Serializer integity error 2: ' + ns + ', ' + this.prefixs[ns] + ', ' + this.namespaces[this.prefixes[ns]] + '!');
192
- }
193
- }
194
- } // Make up an unused prefix for a random namespace
195
-
196
- }, {
197
- key: "makeUpPrefix",
198
- value: function makeUpPrefix(uri) {
199
- var p = uri;
200
-
201
- function canUseMethod(pp) {
202
- if (!this.validPrefix.test(pp)) return false; // bad format
203
-
204
- if (pp === 'ns') return false; // boring
205
-
206
- if (pp in this.namespaces) return false; // already used
207
-
208
- this.prefixes[uri] = pp;
209
- this.namespaces[pp] = uri;
210
- return pp;
211
- }
212
-
213
- var canUse = canUseMethod.bind(this);
214
- if ('#/'.indexOf(p[p.length - 1]) >= 0) p = p.slice(0, -1);
215
- var slash = p.lastIndexOf('/');
216
- if (slash >= 0) p = p.slice(slash + 1);
217
- var i = 0;
218
-
219
- while (i < p.length) {
220
- if (this.prefixchars.indexOf(p[i])) {
221
- i++;
222
- } else {
223
- break;
224
- }
225
- }
226
-
227
- p = p.slice(0, i);
228
- if (p.length < 6 && canUse(p)) return p; // exact is best
229
-
230
- if (canUse(p.slice(0, 3))) return p.slice(0, 3);
231
- if (canUse(p.slice(0, 2))) return p.slice(0, 2);
232
- if (canUse(p.slice(0, 4))) return p.slice(0, 4);
233
- if (canUse(p.slice(0, 1))) return p.slice(0, 1);
234
- if (canUse(p.slice(0, 5))) return p.slice(0, 5);
235
-
236
- if (!this.validPrefix.test(p)) {
237
- p = 'n'; // Otherwise the loop below may never termimnate
238
- }
239
-
240
- for (var j = 0;; j++) {
241
- if (canUse(p.slice(0, 3) + j)) return p.slice(0, 3) + j;
142
+ for (ns in this.prefixes) {
143
+ if (this.namespaces[this.prefixes[ns]] !== ns) {
144
+ throw new Error('Serializer integity error 2: ' + ns + ', ' + this.prefixs[ns] + ', ' + this.namespaces[this.prefixes[ns]] + '!');
242
145
  }
243
146
  }
244
- }, {
245
- key: "rootSubjects",
246
- value: function rootSubjects(sts) {
247
- var incoming = {};
248
- var subjects = {};
249
- var allBnodes = {};
250
- /* This scan is to find out which nodes will have to be the roots of trees
251
- ** in the serialized form. This will be any symbols, and any bnodes
252
- ** which hve more or less than one incoming arc, and any bnodes which have
253
- ** one incoming arc but it is an uninterrupted loop of such nodes back to itself.
254
- ** This should be kept linear time with repect to the number of statements.
255
- ** Note it does not use any indexing of the store.
256
- */
257
-
258
- for (var i = 0; i < sts.length; i++) {
259
- var st = sts[i];
260
-
261
- var checkMentions = function checkMentions(x) {
262
- if (!incoming.hasOwnProperty(x)) incoming[x] = [];
263
- incoming[x].push(st.subject); // List of things which will cause this to be printed
264
- };
265
-
266
- var st2 = [st.subject, st.predicate, st.object];
267
- st2.map(function (y) {
268
- if (y.termType === 'BlankNode') {
269
- allBnodes[y.toNT()] = true;
270
- } else if (y.termType === 'Collection') {
271
- y.elements.forEach(function (z) {
272
- checkMentions(z); // bnodes in collections important
273
- });
274
- }
275
- });
276
- checkMentions(sts[i].object);
277
- var ss = subjects[this.toStr(st.subject)]; // Statements with this as subject
278
-
279
- if (!ss) ss = [];
280
- ss.push(st);
281
- subjects[this.toStr(st.subject)] = ss; // Make hash. @@ too slow for formula?
282
- }
283
-
284
- var roots = [];
285
-
286
- for (var xNT in subjects) {
287
- if (!subjects.hasOwnProperty(xNT)) continue;
288
- var y = this.fromStr(xNT);
289
-
290
- if (y.termType !== 'BlankNode' || !incoming[y] || incoming[y].length !== 1) {
291
- roots.push(y);
292
- continue;
293
- }
294
- }
295
-
296
- this.incoming = incoming; // Keep for serializing @@ Bug for nested formulas
297
- // Now do the scan using existing roots
298
-
299
- var rootsHash = {};
300
-
301
- for (var k = 0; k < roots.length; k++) {
302
- rootsHash[roots[k].toNT()] = true;
303
- }
304
-
305
- return {
306
- 'roots': roots,
307
- 'subjects': subjects,
308
- 'rootsHash': rootsHash,
309
- 'incoming': incoming
310
- };
311
- } // //////////////////////////////////////////////////////
147
+ }
312
148
 
313
- }, {
314
- key: "toN3",
315
- value: function toN3(f) {
316
- return this.statementsToN3(f.statements);
149
+ // Make up an unused prefix for a random namespace
150
+ makeUpPrefix(uri) {
151
+ var p = uri;
152
+ function canUseMethod(pp) {
153
+ if (!this.validPrefix.test(pp)) return false; // bad format
154
+ if (pp === 'ns') return false; // boring
155
+ if (pp in this.namespaces) return false; // already used
156
+ this.prefixes[uri] = pp;
157
+ this.namespaces[pp] = uri;
158
+ return pp;
317
159
  }
318
- }, {
319
- key: "explicitURI",
320
- value: function explicitURI(uri) {
321
- if (this.flags.indexOf('r') < 0 && this.base) {
322
- uri = Uri.refTo(this.base, uri);
323
- } else if (this.flags.indexOf('u') >= 0) {
324
- // Unicode encoding NTriples style
325
- uri = backslashUify(uri);
160
+ var canUse = canUseMethod.bind(this);
161
+ if ('#/'.indexOf(p[p.length - 1]) >= 0) p = p.slice(0, -1);
162
+ var slash = p.lastIndexOf('/');
163
+ if (slash >= 0) p = p.slice(slash + 1);
164
+ var i = 0;
165
+ while (i < p.length) {
166
+ if (this.prefixchars.indexOf(p[i])) {
167
+ i++;
326
168
  } else {
327
- uri = hexify(uri);
169
+ break;
328
170
  }
329
-
330
- return '<' + uri + '>';
331
171
  }
332
- }, {
333
- key: "statementsToNTriples",
334
- value: function statementsToNTriples(sts) {
335
- var sorted = sts.slice();
336
- sorted.sort();
337
- var str = '';
338
- var rdfns = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
339
- var self = this;
340
- var kb = this.store;
341
- var factory = this.rdfFactory;
342
-
343
- var termToNT = function termToNT(x) {
344
- if (x.termType !== 'Collection') {
345
- return self.atomicTermToN3(x);
346
- }
347
-
348
- var list = x.elements;
349
- var rest = kb.sym(rdfns + 'nill');
350
-
351
- for (var i = list.length - 1; i >= 0; i--) {
352
- var bnode = factory.blankNode();
353
- str += termToNT(bnode) + ' ' + termToNT(kb.sym(rdfns + 'first')) + ' ' + termToNT(list[i]) + '.\n';
354
- str += termToNT(bnode) + ' ' + termToNT(kb.sym(rdfns + 'rest')) + ' ' + termToNT(rest) + '.\n';
355
- rest = bnode;
356
- }
172
+ p = p.slice(0, i);
173
+ if (p.length < 6 && canUse(p)) return p; // exact is best
174
+ if (canUse(p.slice(0, 3))) return p.slice(0, 3);
175
+ if (canUse(p.slice(0, 2))) return p.slice(0, 2);
176
+ if (canUse(p.slice(0, 4))) return p.slice(0, 4);
177
+ if (canUse(p.slice(0, 1))) return p.slice(0, 1);
178
+ if (canUse(p.slice(0, 5))) return p.slice(0, 5);
179
+ if (!this.validPrefix.test(p)) {
180
+ p = 'n'; // Otherwise the loop below may never termimnate
181
+ }
357
182
 
358
- return self.atomicTermToN3(rest);
183
+ for (var j = 0;; j++) if (canUse(p.slice(0, 3) + j)) return p.slice(0, 3) + j;
184
+ }
185
+ rootSubjects(sts) {
186
+ var incoming = {};
187
+ var subjects = {};
188
+ var allBnodes = {};
189
+
190
+ /* This scan is to find out which nodes will have to be the roots of trees
191
+ ** in the serialized form. This will be any symbols, and any bnodes
192
+ ** which hve more or less than one incoming arc, and any bnodes which have
193
+ ** one incoming arc but it is an uninterrupted loop of such nodes back to itself.
194
+ ** This should be kept linear time with repect to the number of statements.
195
+ ** Note it does not use any indexing of the store.
196
+ */
197
+ for (var i = 0; i < sts.length; i++) {
198
+ var st = sts[i];
199
+ var checkMentions = function (x) {
200
+ if (!incoming.hasOwnProperty(x)) incoming[x] = [];
201
+ incoming[x].push(st.subject); // List of things which will cause this to be printed
359
202
  };
360
203
 
361
- for (var i = 0; i < sorted.length; i++) {
362
- var st = sorted[i];
363
- var s = '';
364
- s += termToNT(st.subject) + ' ';
365
- s += termToNT(st.predicate) + ' ';
366
- s += termToNT(st.object) + ' ';
367
-
368
- if (this.flags.indexOf('q') >= 0) {
369
- // Do quads not nrtiples
370
- s += termToNT(st.why) + ' ';
204
+ var st2 = [st.subject, st.predicate, st.object];
205
+ st2.map(function (y) {
206
+ if (y.termType === 'BlankNode') {
207
+ allBnodes[y.toNT()] = true;
208
+ } else if (y.termType === 'Collection') {
209
+ y.elements.forEach(function (z) {
210
+ checkMentions(z); // bnodes in collections important
211
+ });
371
212
  }
213
+ });
372
214
 
373
- s += '.\n';
374
- str += s;
375
- }
376
-
377
- return str;
215
+ checkMentions(sts[i].object);
216
+ var ss = subjects[this.toStr(st.subject)]; // Statements with this as subject
217
+ if (!ss) ss = [];
218
+ ss.push(st);
219
+ subjects[this.toStr(st.subject)] = ss; // Make hash. @@ too slow for formula?
378
220
  }
379
- }, {
380
- key: "statementsToN3",
381
- value: function statementsToN3(sts) {
382
- var indent = 4;
383
- var width = 80;
384
- var kb = this.store; // A URI Map alows us to put the type statemnts at the top.
385
-
386
- var uriMap = {
387
- 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': 'aaa:00'
388
- };
389
-
390
- var SPO = function SPO(x, y) {
391
- // Do limited canonicalization of bnodes
392
- return Util.heavyCompareSPO(x, y, kb, uriMap);
393
- };
394
-
395
- sts.sort(SPO);
396
-
397
- if (this.base && !this.defaultNamespace) {
398
- this.defaultNamespace = this.base + '#';
399
- }
400
-
401
- var predMap = {};
402
221
 
403
- if (this.flags.indexOf('s') < 0) {
404
- predMap['http://www.w3.org/2002/07/owl#sameAs'] = '=';
222
+ var roots = [];
223
+ for (var xNT in subjects) {
224
+ if (!subjects.hasOwnProperty(xNT)) continue;
225
+ var y = this.fromStr(xNT);
226
+ if (y.termType !== 'BlankNode' || !incoming[y] || incoming[y].length !== 1) {
227
+ roots.push(y);
228
+ continue;
405
229
  }
230
+ }
231
+ this.incoming = incoming; // Keep for serializing @@ Bug for nested formulas
406
232
 
407
- if (this.flags.indexOf('t') < 0) {
408
- predMap['http://www.w3.org/1999/02/22-rdf-syntax-ns#type'] = 'a';
409
- }
410
-
411
- if (this.flags.indexOf('i') < 0) {
412
- predMap['http://www.w3.org/2000/10/swap/log#implies'] = '=>';
413
- } // //////////////////////// Arrange the bits of text
414
-
415
-
416
- var spaces = function spaces(n) {
417
- var s = '';
418
-
419
- for (var i = 0; i < n; i++) {
420
- s += ' ';
421
- }
422
-
423
- return s;
424
- };
425
-
426
- var treeToLine = function treeToLine(tree) {
427
- var str = '';
233
+ // Now do the scan using existing roots
234
+ var rootsHash = {};
235
+ for (var k = 0; k < roots.length; k++) {
236
+ rootsHash[roots[k].toNT()] = true;
237
+ }
238
+ return {
239
+ 'roots': roots,
240
+ 'subjects': subjects,
241
+ 'rootsHash': rootsHash,
242
+ 'incoming': incoming
243
+ };
244
+ }
428
245
 
429
- for (var i = 0; i < tree.length; i++) {
430
- var branch = tree[i];
431
- var s2 = typeof branch === 'string' ? branch : treeToLine(branch); // Note the space before the dot in case statement ends with 123 or colon. which is in fact allowed but be conservative.
246
+ // //////////////////////////////////////////////////////
432
247
 
433
- if (i !== 0) {
434
- var ch = str.slice(-1) || ' ';
248
+ toN3(f) {
249
+ return this.statementsToN3(f.statements);
250
+ }
251
+ explicitURI(uri) {
252
+ if (this.flags.indexOf('r') < 0 && this.base) {
253
+ uri = Uri.refTo(this.base, uri);
254
+ } else if (this.flags.indexOf('u') >= 0) {
255
+ // Unicode encoding NTriples style
256
+ uri = backslashUify(uri);
257
+ } else {
258
+ uri = hexify(uri);
259
+ }
260
+ return '<' + uri + '>';
261
+ }
262
+ statementsToNTriples(sts) {
263
+ var sorted = sts.slice();
264
+ sorted.sort();
265
+ var str = '';
266
+ var rdfns = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
267
+ var self = this;
268
+ var kb = this.store;
269
+ var factory = this.rdfFactory;
270
+ var termToNT = function (x) {
271
+ if (x.termType !== 'Collection') {
272
+ return self.atomicTermToN3(x);
273
+ }
274
+ var list = x.elements;
275
+ var rest = kb.sym(rdfns + 'nill');
276
+ for (var i = list.length - 1; i >= 0; i--) {
277
+ var bnode = factory.blankNode();
278
+ str += termToNT(bnode) + ' ' + termToNT(kb.sym(rdfns + 'first')) + ' ' + termToNT(list[i]) + '.\n';
279
+ str += termToNT(bnode) + ' ' + termToNT(kb.sym(rdfns + 'rest')) + ' ' + termToNT(rest) + '.\n';
280
+ rest = bnode;
281
+ }
282
+ return self.atomicTermToN3(rest);
283
+ };
284
+ for (var i = 0; i < sorted.length; i++) {
285
+ var st = sorted[i];
286
+ var s = '';
287
+ s += termToNT(st.subject) + ' ';
288
+ s += termToNT(st.predicate) + ' ';
289
+ s += termToNT(st.object) + ' ';
290
+ if (this.flags.indexOf('q') >= 0) {
291
+ // Do quads not nrtiples
292
+ s += termToNT(st.why) + ' ';
293
+ }
294
+ s += '.\n';
295
+ str += s;
296
+ }
297
+ return str;
298
+ }
299
+ statementsToN3(sts) {
300
+ var indent = 4;
301
+ var width = 80;
302
+ var kb = this.store;
303
+ // A URI Map alows us to put the type statemnts at the top.
304
+ var uriMap = {
305
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type': 'aaa:00'
306
+ };
307
+ var SPO = function (x, y) {
308
+ // Do limited canonicalization of bnodes
309
+ return Util.heavyCompareSPO(x, y, kb, uriMap);
310
+ };
311
+ sts.sort(SPO);
312
+ if (this.base && !this.defaultNamespace) {
313
+ this.defaultNamespace = this.base + '#';
314
+ }
315
+ var predMap = {};
316
+ if (this.flags.indexOf('s') < 0) {
317
+ predMap['http://www.w3.org/2002/07/owl#sameAs'] = '=';
318
+ }
319
+ if (this.flags.indexOf('t') < 0) {
320
+ predMap['http://www.w3.org/1999/02/22-rdf-syntax-ns#type'] = 'a';
321
+ }
322
+ if (this.flags.indexOf('i') < 0) {
323
+ predMap['http://www.w3.org/2000/10/swap/log#implies'] = '=>';
324
+ }
325
+ // //////////////////////// Arrange the bits of text
435
326
 
436
- if (s2 === ',' || s2 === ';') {// no gap
437
- } else if (s2 === '.' && !'0123456789.:'.includes(ch)) {// no gap except after number and colon
438
- // no gap
439
- } else {
440
- str += ' '; // separate from previous token
441
- }
327
+ var spaces = function (n) {
328
+ var s = '';
329
+ for (var i = 0; i < n; i++) s += ' ';
330
+ return s;
331
+ };
332
+ var treeToLine = function (tree) {
333
+ var str = '';
334
+ for (var i = 0; i < tree.length; i++) {
335
+ var branch = tree[i];
336
+ var s2 = typeof branch === 'string' ? branch : treeToLine(branch);
337
+ // Note the space before the dot in case statement ends with 123 or colon. which is in fact allowed but be conservative.
338
+ if (i !== 0) {
339
+ var ch = str.slice(-1) || ' ';
340
+ if (s2 === ',' || s2 === ';') {
341
+ // no gap
342
+ } else if (s2 === '.' && !'0123456789.:'.includes(ch)) {// no gap except after number and colon
343
+ // no gap
344
+ } else {
345
+ str += ' '; // separate from previous token
442
346
  }
443
-
444
- str += s2;
445
347
  }
446
348
 
447
- return str;
448
- }; // Convert a nested tree of lists and strings to a string
449
-
450
-
451
- var treeToString = function treeToString(tree, level) {
452
- var str = '';
453
- var lastLength = 100000;
454
- if (level === undefined) level = -1;
455
-
456
- for (var i = 0; i < tree.length; i++) {
457
- var branch = tree[i];
458
-
459
- if (typeof branch !== 'string') {
460
- var substr = treeToString(branch, level + 1);
461
-
462
- if (substr.length < 10 * (width - indent * level) && substr.indexOf('"""') < 0) {
463
- // Don't mess up multiline strings
464
- var line = treeToLine(branch);
465
-
466
- if (line.length < width - indent * level) {
467
- branch = line; // Note! treat as string below
349
+ str += s2;
350
+ }
351
+ return str;
352
+ };
468
353
 
469
- substr = '';
470
- }
354
+ // Convert a nested tree of lists and strings to a string
355
+ var treeToString = function (tree, level) {
356
+ var str = '';
357
+ var lastLength = 100000;
358
+ if (level === undefined) level = -1;
359
+ for (var i = 0; i < tree.length; i++) {
360
+ var branch = tree[i];
361
+ if (typeof branch !== 'string') {
362
+ var substr = treeToString(branch, level + 1);
363
+ if (substr.length < 10 * (width - indent * level) && substr.indexOf('"""') < 0) {
364
+ // Don't mess up multiline strings
365
+ var line = treeToLine(branch);
366
+ if (line.length < width - indent * level) {
367
+ branch = line; // Note! treat as string below
368
+ substr = '';
471
369
  }
472
-
473
- if (substr) lastLength = 10000;
474
- str += substr;
475
370
  }
476
-
477
- if (typeof branch === 'string') {
478
- if (branch.length === 1 && str.slice(-1) === '\n') {
479
- if (',.;'.indexOf(branch) >= 0) {
480
- str = str.slice(0, -1); // be conservative and ensure a whitespace between some chars and a final dot, as in treeToLine above
481
-
482
- if (branch == '.' && '0123456789.:'.includes(str.charAt(str.length - 1))) {
483
- str += ' ';
484
- lastLength += 1;
485
- }
486
-
487
- str += branch + '\n'; // slip punct'n on end
488
-
371
+ if (substr) lastLength = 10000;
372
+ str += substr;
373
+ }
374
+ if (typeof branch === 'string') {
375
+ if (branch.length === 1 && str.slice(-1) === '\n') {
376
+ if (',.;'.indexOf(branch) >= 0) {
377
+ str = str.slice(0, -1);
378
+ // be conservative and ensure a whitespace between some chars and a final dot, as in treeToLine above
379
+ if (branch == '.' && '0123456789.:'.includes(str.charAt(str.length - 1))) {
380
+ str += ' ';
489
381
  lastLength += 1;
490
- continue;
491
- }
492
- }
493
-
494
- if (lastLength < indent * level + 4 || // if new line not necessary
495
- lastLength + branch.length + 1 < width && ';.'.indexOf(str[str.length - 2]) < 0) {
496
- // or the string fits on last line
497
- str = str.slice(0, -1) + ' ' + branch + '\n'; // then continue on this line
498
-
499
- lastLength += branch.length + 1;
500
- } else {
501
- var _line = spaces(indent * level) + branch;
502
-
503
- str += _line + '\n';
504
- lastLength = _line.length;
505
-
506
- if (level < 0) {
507
- str += '\n'; // extra blank line
508
-
509
- lastLength = 100000; // don't touch
510
382
  }
383
+ str += branch + '\n'; // slip punct'n on end
384
+ lastLength += 1;
385
+ continue;
511
386
  }
512
387
  }
513
- }
514
-
515
- return str;
516
- }; // //////////////////////////////////////////// Structure for N3
517
- // Convert a set of statements into a nested tree of lists and strings
518
-
519
-
520
- function statementListToTreeMethod(statements) {
521
- var stats = this.rootSubjects(statements);
522
- var roots = stats.roots;
523
- var results = [];
524
-
525
- for (var i = 0; i < roots.length; i++) {
526
- var root = roots[i];
527
- results.push(subjectTree(root, stats));
528
- }
529
-
530
- return results;
531
- }
532
-
533
- var statementListToTree = statementListToTreeMethod.bind(this); // The tree for a subject
534
-
535
- function subjectTree(subject, stats) {
536
- if (subject.termType === 'BlankNode' && !stats.incoming[subject]) {
537
- return objectTree(subject, stats, true).concat(['.']); // Anonymous bnode subject
538
- }
539
-
540
- return [termToN3(subject, stats)].concat([propertyTree(subject, stats)]).concat(['.']);
541
- } // The property tree for a single subject or anonymous node
542
-
543
-
544
- function propertyTreeMethod(subject, stats) {
545
- var results = [];
546
- var lastPred = null;
547
- var sts = stats.subjects[this.toStr(subject)] || []; // relevant statements
548
-
549
- if (typeof sts === 'undefined') {
550
- throw new Error('Cant find statements for ' + subject);
551
- }
552
-
553
- var objects = [];
554
-
555
- for (var i = 0; i < sts.length; i++) {
556
- var st = sts[i];
557
-
558
- if (st.predicate.uri === lastPred) {
559
- objects.push(',');
388
+ if (lastLength < indent * level + 4 ||
389
+ // if new line not necessary
390
+ lastLength + branch.length + 1 < width && ';.'.indexOf(str[str.length - 2]) < 0) {
391
+ // or the string fits on last line
392
+ str = str.slice(0, -1) + ' ' + branch + '\n'; // then continue on this line
393
+ lastLength += branch.length + 1;
560
394
  } else {
561
- if (lastPred) {
562
- results = results.concat([objects]).concat([';']);
563
- objects = [];
395
+ let line = spaces(indent * level) + branch;
396
+ str += line + '\n';
397
+ lastLength = line.length;
398
+ if (level < 0) {
399
+ str += '\n'; // extra blank line
400
+ lastLength = 100000; // don't touch
564
401
  }
565
-
566
- results.push(predMap[st.predicate.uri] ? predMap[st.predicate.uri] : termToN3(st.predicate, stats));
567
402
  }
568
-
569
- lastPred = st.predicate.uri;
570
- objects.push(objectTree(st.object, stats));
571
403
  }
572
-
573
- results = results.concat([objects]);
574
- return results;
575
404
  }
576
405
 
577
- var propertyTree = propertyTreeMethod.bind(this);
578
-
579
- function objectTreeMethod(obj, stats, force) {
580
- if (obj.termType === 'BlankNode' && (force || stats.rootsHash[obj.toNT()] === undefined)) {
581
- // if not a root
582
- if (stats.subjects[this.toStr(obj)]) {
583
- return ['[', propertyTree(obj, stats), ']'];
584
- } else {
585
- return '[]';
586
- }
587
- }
406
+ return str;
407
+ };
408
+
409
+ // //////////////////////////////////////////// Structure for N3
410
+ // Convert a set of statements into a nested tree of lists and strings
411
+ function statementListToTreeMethod(statements) {
412
+ var stats = this.rootSubjects(statements);
413
+ var roots = stats.roots;
414
+ var results = [];
415
+ for (var i = 0; i < roots.length; i++) {
416
+ var root = roots[i];
417
+ results.push(subjectTree(root, stats));
418
+ }
419
+ return results;
420
+ }
421
+ var statementListToTree = statementListToTreeMethod.bind(this);
588
422
 
589
- return termToN3(obj, stats);
423
+ // The tree for a subject
424
+ function subjectTree(subject, stats) {
425
+ if (subject.termType === 'BlankNode' && !stats.incoming[subject]) {
426
+ return objectTree(subject, stats, true).concat(['.']); // Anonymous bnode subject
590
427
  }
591
428
 
592
- var objectTree = objectTreeMethod.bind(this);
593
-
594
- function termToN3Method(expr, stats) {
595
- //
596
- var i, res;
597
-
598
- switch (expr.termType) {
599
- case 'Graph':
600
- res = ['{'];
601
- res = res.concat(statementListToTree(expr.statements));
602
- return res.concat(['}']);
603
-
604
- case 'Collection':
605
- res = ['('];
606
-
607
- for (i = 0; i < expr.elements.length; i++) {
608
- res.push([objectTree(expr.elements[i], stats)]);
609
- }
610
-
611
- res.push(')');
612
- return res;
613
-
614
- default:
615
- return this.atomicTermToN3(expr);
429
+ return [termToN3(subject, stats)].concat([propertyTree(subject, stats)]).concat(['.']);
430
+ }
431
+ // The property tree for a single subject or anonymous node
432
+ function propertyTreeMethod(subject, stats) {
433
+ var results = [];
434
+ var lastPred = null;
435
+ var sts = stats.subjects[this.toStr(subject)] || []; // relevant statements
436
+ if (typeof sts === 'undefined') {
437
+ throw new Error('Cant find statements for ' + subject);
438
+ }
439
+ var objects = [];
440
+ for (var i = 0; i < sts.length; i++) {
441
+ var st = sts[i];
442
+ if (st.predicate.uri === lastPred) {
443
+ objects.push(',');
444
+ } else {
445
+ if (lastPred) {
446
+ results = results.concat([objects]).concat([';']);
447
+ objects = [];
448
+ }
449
+ results.push(predMap[st.predicate.uri] ? predMap[st.predicate.uri] : termToN3(st.predicate, stats));
616
450
  }
451
+ lastPred = st.predicate.uri;
452
+ objects.push(objectTree(st.object, stats));
617
453
  }
618
-
619
- Serializer.prototype.termToN3 = termToN3;
620
- var termToN3 = termToN3Method.bind(this);
621
-
622
- function prefixDirectivesMethod() {
623
- var str = '';
624
-
625
- if (this.defaultNamespace) {
626
- str += '@prefix : ' + this.explicitURI(this.defaultNamespace) + '.\n';
627
- }
628
-
629
- for (var ns in this.prefixes) {
630
- if (!this.prefixes.hasOwnProperty(ns)) continue;
631
- if (!this.namespacesUsed[ns]) continue;
632
- str += '@prefix ' + this.prefixes[ns] + ': ' + this.explicitURI(ns) + '.\n';
454
+ results = results.concat([objects]);
455
+ return results;
456
+ }
457
+ var propertyTree = propertyTreeMethod.bind(this);
458
+ function objectTreeMethod(obj, stats, force) {
459
+ if (obj.termType === 'BlankNode' && (force || stats.rootsHash[obj.toNT()] === undefined)) {
460
+ // if not a root
461
+ if (stats.subjects[this.toStr(obj)]) {
462
+ return ['[', propertyTree(obj, stats), ']'];
463
+ } else {
464
+ return '[]';
633
465
  }
634
-
635
- return str + '\n';
636
466
  }
637
-
638
- var prefixDirectives = prefixDirectivesMethod.bind(this); // Body of statementsToN3:
639
-
640
- var tree = statementListToTree(sts);
641
- return prefixDirectives() + treeToString(tree);
642
- } // //////////////////////////////////////////// Atomic Terms
643
- // Deal with term level things and nesting with no bnode structure
644
-
645
- }, {
646
- key: "atomicTermToN3",
647
- value: function atomicTermToN3(expr, stats) {
467
+ return termToN3(obj, stats);
468
+ }
469
+ var objectTree = objectTreeMethod.bind(this);
470
+ function termToN3Method(expr, stats) {
471
+ //
472
+ var i, res;
648
473
  switch (expr.termType) {
649
- case 'BlankNode':
650
- case 'Variable':
651
- return expr.toNT();
652
-
653
- case 'Literal':
654
- var val = expr.value;
655
-
656
- if (typeof val !== 'string') {
657
- throw new TypeError('Value of RDF literal node must be a string');
658
- } // var val = expr.value.toString() // should be a string already
659
-
660
-
661
- if (expr.datatype && this.flags.indexOf('x') < 0) {
662
- // Supress native numbers
663
- switch (expr.datatype.uri) {
664
- case 'http://www.w3.org/2001/XMLSchema#integer':
665
- return val;
666
-
667
- case 'http://www.w3.org/2001/XMLSchema#decimal':
668
- // In Turtle, must have dot
669
- if (val.indexOf('.') < 0) val += '.0';
670
- return val;
671
-
672
- case 'http://www.w3.org/2001/XMLSchema#double':
673
- {
674
- // Must force use of 'e'
675
- var eNotation = val.toLowerCase().indexOf('e') > 0;
676
- if (val.indexOf('.') < 0 && !eNotation) val += '.0';
677
- if (!eNotation) val += 'e0';
678
- return val;
679
- }
680
-
681
- case 'http://www.w3.org/2001/XMLSchema#boolean':
682
- return expr.value === '1' ? 'true' : 'false';
683
- }
684
- }
685
-
686
- var str = this.stringToN3(expr.value);
687
-
688
- if (expr.language) {
689
- str += '@' + expr.language;
690
- } else if (!expr.datatype.equals(this.xsd.string)) {
691
- str += '^^' + this.atomicTermToN3(expr.datatype, stats);
474
+ case 'Graph':
475
+ res = ['{'];
476
+ res = res.concat(statementListToTree(expr.statements));
477
+ return res.concat(['}']);
478
+ case 'Collection':
479
+ res = ['('];
480
+ for (i = 0; i < expr.elements.length; i++) {
481
+ res.push([objectTree(expr.elements[i], stats)]);
692
482
  }
693
-
694
- return str;
695
-
696
- case 'NamedNode':
697
- return this.symbolToN3(expr);
698
-
699
- case 'DefaultGraph':
700
- return '';
701
-
483
+ res.push(')');
484
+ return res;
702
485
  default:
703
- throw new Error('Internal: atomicTermToN3 cannot handle ' + expr + ' of termType: ' + expr.termType);
486
+ return this.atomicTermToN3(expr);
704
487
  }
705
- } // stringToN3: String escaping for N3
706
-
707
- }, {
708
- key: "stringToN3",
709
- value: function stringToN3(str, flags) {
710
- if (!flags) flags = 'e';
711
- var res = '';
712
- var i, j, k;
713
- var delim;
714
- var forbidden;
715
-
716
- if (str.length > 20 && // Long enough to make sense
717
- str.slice(-1) !== '"' && // corner case'
718
- flags.indexOf('n') < 0 && ( // Force single line
719
- str.indexOf('\n') > 0 || str.indexOf('"') > 0)) {
720
- delim = '"""';
721
- forbidden = this.forbidden3;
722
- } else {
723
- delim = '"';
724
- forbidden = this.forbidden1;
488
+ }
489
+ Serializer.prototype.termToN3 = termToN3;
490
+ var termToN3 = termToN3Method.bind(this);
491
+ function prefixDirectivesMethod() {
492
+ var str = '';
493
+ if (this.defaultNamespace) {
494
+ str += '@prefix : ' + this.explicitURI(this.defaultNamespace) + '.\n';
725
495
  }
496
+ for (var ns in this.prefixes) {
497
+ if (!this.prefixes.hasOwnProperty(ns)) continue;
498
+ if (!this.namespacesUsed[ns]) continue;
499
+ str += '@prefix ' + this.prefixes[ns] + ': ' + this.explicitURI(ns) + '.\n';
500
+ }
501
+ return str + '\n';
502
+ }
503
+ var prefixDirectives = prefixDirectivesMethod.bind(this);
504
+ // Body of statementsToN3:
505
+ var tree = statementListToTree(sts);
506
+ return prefixDirectives() + treeToString(tree);
507
+ }
508
+ // //////////////////////////////////////////// Atomic Terms
509
+
510
+ // Deal with term level things and nesting with no bnode structure
511
+ atomicTermToN3(expr, stats) {
512
+ switch (expr.termType) {
513
+ case 'BlankNode':
514
+ case 'Variable':
515
+ return expr.toNT();
516
+ case 'Literal':
517
+ var val = expr.value;
518
+ if (typeof val !== 'string') {
519
+ throw new TypeError('Value of RDF literal node must be a string');
520
+ }
521
+ // var val = expr.value.toString() // should be a string already
522
+ if (expr.datatype && this.flags.indexOf('x') < 0) {
523
+ // Supress native numbers
524
+ switch (expr.datatype.uri) {
525
+ case 'http://www.w3.org/2001/XMLSchema#integer':
526
+ return val;
527
+ case 'http://www.w3.org/2001/XMLSchema#decimal':
528
+ // In Turtle, must have dot
529
+ if (val.indexOf('.') < 0) val += '.0';
530
+ return val;
531
+ case 'http://www.w3.org/2001/XMLSchema#double':
532
+ {
533
+ // Must force use of 'e'
534
+ const eNotation = val.toLowerCase().indexOf('e') > 0;
535
+ if (val.indexOf('.') < 0 && !eNotation) val += '.0';
536
+ if (!eNotation) val += 'e0';
537
+ return val;
538
+ }
539
+ case 'http://www.w3.org/2001/XMLSchema#boolean':
540
+ return expr.value === '1' ? 'true' : 'false';
541
+ }
542
+ }
543
+ var str = this.stringToN3(expr.value);
544
+ if (expr.language) {
545
+ str += '@' + expr.language;
546
+ } else if (!expr.datatype.equals(this.xsd.string)) {
547
+ str += '^^' + this.atomicTermToN3(expr.datatype, stats);
548
+ }
549
+ return str;
550
+ case 'NamedNode':
551
+ return this.symbolToN3(expr);
552
+ case 'DefaultGraph':
553
+ return '';
554
+ default:
555
+ throw new Error('Internal: atomicTermToN3 cannot handle ' + expr + ' of termType: ' + expr.termType);
556
+ }
557
+ }
726
558
 
727
- for (i = 0; i < str.length;) {
728
- forbidden.lastIndex = 0;
729
- var m = forbidden.exec(str.slice(i));
730
- if (m == null) break;
731
- j = i + forbidden.lastIndex - 1;
732
- res += str.slice(i, j);
733
- var ch = str[j];
734
-
735
- if (ch === '"' && delim === '"""' && str.slice(j, j + 3) !== '"""') {
736
- res += ch;
559
+ // stringToN3: String escaping for N3
560
+
561
+ stringToN3(str, flags) {
562
+ if (!flags) flags = 'e';
563
+ var res = '';
564
+ var i, j, k;
565
+ var delim;
566
+ var forbidden;
567
+ if (str.length > 20 &&
568
+ // Long enough to make sense
569
+ str.slice(-1) !== '"' &&
570
+ // corner case'
571
+ flags.indexOf('n') < 0 && (
572
+ // Force single line
573
+ str.indexOf('\n') > 0 || str.indexOf('"') > 0)) {
574
+ delim = '"""';
575
+ forbidden = this.forbidden3;
576
+ } else {
577
+ delim = '"';
578
+ forbidden = this.forbidden1;
579
+ }
580
+ for (i = 0; i < str.length;) {
581
+ forbidden.lastIndex = 0;
582
+ var m = forbidden.exec(str.slice(i));
583
+ if (m == null) break;
584
+ j = i + forbidden.lastIndex - 1;
585
+ res += str.slice(i, j);
586
+ var ch = str[j];
587
+ if (ch === '"' && delim === '"""' && str.slice(j, j + 3) !== '"""') {
588
+ res += ch;
589
+ } else {
590
+ k = '\b\f\r\t\v\n\\"'.indexOf(ch); // No escaping of bell (7)?
591
+ if (k >= 0) {
592
+ res += '\\' + 'bfrtvn\\"'[k];
737
593
  } else {
738
- k = '\b\f\r\t\v\n\\"'.indexOf(ch); // No escaping of bell (7)?
739
-
740
- if (k >= 0) {
741
- res += '\\' + 'bfrtvn\\"'[k];
594
+ if (flags.indexOf('e') >= 0) {
595
+ // Unicode escaping in strings not unix style
596
+ res += '\\u' + ('000' + ch.charCodeAt(0).toString(16).toLowerCase()).slice(-4);
742
597
  } else {
743
- if (flags.indexOf('e') >= 0) {
744
- // Unicode escaping in strings not unix style
745
- res += "\\u" + ('000' + ch.charCodeAt(0).toString(16).toLowerCase()).slice(-4);
746
- } else {
747
- // no 'e' flag
748
- res += ch;
749
- }
598
+ // no 'e' flag
599
+ res += ch;
750
600
  }
751
601
  }
752
-
753
- i = j + 1;
754
602
  }
755
-
756
- return delim + res + str.slice(i) + delim;
757
- } // A single symbol, either in <> or namespace notation
758
-
759
- }, {
760
- key: "symbolToN3",
761
- value: function symbolToN3(x) {
762
- // c.f. symbolString() in notation3.py
763
- var uri = x.uri;
764
- var j = uri.indexOf('#');
765
-
766
- if (j < 0 && this.flags.indexOf('/') < 0) {
767
- j = uri.lastIndexOf('/');
768
- }
769
-
770
- if (j >= 0 && this.flags.indexOf('p') < 0 && ( // Can split at namespace but only if http[s]: URI or file: or ws[s] (why not others?)
771
- uri.indexOf('http') === 0 || uri.indexOf('ws') === 0 || uri.indexOf('file') === 0)) {
772
- var canSplit = true;
773
-
774
- for (var k = j + 1; k < uri.length; k++) {
775
- if (this._notNameChars.indexOf(uri[k]) >= 0) {
776
- canSplit = false;
777
- break;
778
- }
779
- }
780
- /*
781
- if (uri.slice(0, j + 1) === this.base + '#') { // base-relative
782
- if (canSplit) {
783
- return ':' + uri.slice(j + 1) // assume deafult ns is local
784
- } else {
785
- return '<#' + uri.slice(j + 1) + '>'
786
- }
787
- }
788
- */
789
-
790
-
791
- if (canSplit) {
792
- var localid = uri.slice(j + 1);
793
- var namesp = uri.slice(0, j + 1);
794
-
795
- if (this.defaultNamespace && this.defaultNamespace === namesp && this.flags.indexOf('d') < 0) {
796
- // d -> suppress default
797
- if (this.flags.indexOf('k') >= 0 && this.keyords.indexOf(localid) < 0) {
798
- return localid;
799
- }
800
-
801
- return ':' + localid;
802
- } // this.checkIntegrity() // @@@ Remove when not testing
803
-
804
-
805
- var prefix = this.prefixes[namesp];
806
- if (!prefix) prefix = this.makeUpPrefix(namesp);
807
-
808
- if (prefix) {
809
- this.namespacesUsed[namesp] = true;
810
- return prefix + ':' + localid;
811
- } // Fall though if can't do qname
812
-
603
+ i = j + 1;
604
+ }
605
+ return delim + res + str.slice(i) + delim;
606
+ }
607
+ // A single symbol, either in <> or namespace notation
608
+
609
+ symbolToN3(x) {
610
+ // c.f. symbolString() in notation3.py
611
+ var uri = x.uri;
612
+ var j = uri.indexOf('#');
613
+ if (j < 0 && this.flags.indexOf('/') < 0) {
614
+ j = uri.lastIndexOf('/');
615
+ }
616
+ if (j >= 0 && this.flags.indexOf('p') < 0 && (
617
+ // Can split at namespace but only if http[s]: URI or file: or ws[s] (why not others?)
618
+ uri.indexOf('http') === 0 || uri.indexOf('ws') === 0 || uri.indexOf('file') === 0)) {
619
+ var canSplit = true;
620
+ for (var k = j + 1; k < uri.length; k++) {
621
+ if (this._notNameChars.indexOf(uri[k]) >= 0) {
622
+ canSplit = false;
623
+ break;
813
624
  }
814
625
  }
815
-
816
- return this.explicitURI(uri);
817
- } // /////////////////////////// Quad store serialization
818
- // @para. write - a function taking a single string to be output
819
- //
820
-
821
- }, {
822
- key: "writeStore",
823
- value: function writeStore(write) {
824
- var kb = this.store;
825
- var fetcher = kb.fetcher;
826
- var session = fetcher && fetcher.appNode; // The core data
827
-
828
- var sources = this.store.index[3];
829
-
830
- for (var s in sources) {
831
- // -> assume we can use -> as short for log:semantics
832
- var source = kb.fromNT(s);
833
- if (session && source.equals(session)) continue;
834
- write('\n' + this.atomicTermToN3(source) + ' ' + this.atomicTermToN3(kb.sym('http://www.w3.org/2000/10/swap/log#semantics')) + ' { ' + this.statementsToN3(kb.statementsMatching(undefined, undefined, undefined, source)) + ' }.\n');
835
- } // The metadata from HTTP interactions:
836
-
837
-
838
- kb.statementsMatching(undefined, kb.sym('http://www.w3.org/2007/ont/link#requestedURI')).map(function (st) {
839
- write('\n<' + st.object.value + '> log:metadata {\n');
840
- var sts = kb.statementsMatching(undefined, undefined, undefined, st.subject);
841
- write(this.statementsToN3(this.statementsToN3(sts)));
842
- write('}.\n');
843
- }); // Inferences we have made ourselves not attributable to anyone else
844
-
845
- var metaSources = [];
846
- if (session) metaSources.push(session);
847
- var metadata = [];
848
- metaSources.map(function (source) {
849
- metadata = metadata.concat(kb.statementsMatching(undefined, undefined, undefined, source));
850
- });
851
- write(this.statementsToN3(metadata));
852
- } // ////////////////////////////////////////////// XML serialization
853
-
854
- }, {
855
- key: "statementsToXML",
856
- value: function statementsToXML(sts) {
857
- var indent = 4;
858
- var width = 80;
859
- var namespaceCounts = []; // which have been used
860
-
861
- namespaceCounts['http://www.w3.org/1999/02/22-rdf-syntax-ns#'] = true;
862
- var liPrefix = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#_'; // prefix for ordered list items
863
- // //////////////////////// Arrange the bits of XML text
864
-
865
- var spaces = function spaces(n) {
866
- var s = '';
867
-
868
- for (var i = 0; i < n; i++) {
869
- s += ' ';
870
- }
871
-
872
- return s;
873
- };
874
-
875
- var XMLtreeToLine = function XMLtreeToLine(tree) {
876
- var str = '';
877
-
878
- for (var i = 0; i < tree.length; i++) {
879
- var branch = tree[i];
880
- var s2 = typeof branch === 'string' ? branch : XMLtreeToLine(branch);
881
- str += s2;
882
- }
883
-
884
- return str;
885
- }; // Convert a nested tree of lists and strings to a string
886
-
887
-
888
- var XMLtreeToString = function XMLtreeToString(tree, level) {
889
- var str = '';
890
- var line;
891
- var lastLength = 100000;
892
- if (!level) level = 0;
893
-
894
- for (var i = 0; i < tree.length; i++) {
895
- var branch = tree[i];
896
-
897
- if (typeof branch !== 'string') {
898
- var substr = XMLtreeToString(branch, level + 1);
899
-
900
- if (substr.length < 10 * (width - indent * level) && substr.indexOf('"""') < 0) {
901
- // Don't mess up multiline strings
902
- line = XMLtreeToLine(branch);
903
-
904
- if (line.length < width - indent * level) {
905
- branch = ' ' + line; // @@ Hack: treat as string below
906
-
907
- substr = '';
626
+ /*
627
+ if (uri.slice(0, j + 1) === this.base + '#') { // base-relative
628
+ if (canSplit) {
629
+ return ':' + uri.slice(j + 1) // assume deafult ns is local
630
+ } else {
631
+ return '<#' + uri.slice(j + 1) + '>'
908
632
  }
909
633
  }
910
-
911
- if (substr) lastLength = 10000;
912
- str += substr;
913
- }
914
-
915
- if (typeof branch === 'string') {
916
- if (lastLength < indent * level + 4) {
917
- // continue
918
- str = str.slice(0, -1) + ' ' + branch + '\n';
919
- lastLength += branch.length + 1;
920
- } else {
921
- line = spaces(indent * level) + branch;
922
- str += line + '\n';
923
- lastLength = line.length;
924
- }
925
- } else {// not string
634
+ */
635
+ if (canSplit) {
636
+ var localid = uri.slice(j + 1);
637
+ var namesp = uri.slice(0, j + 1);
638
+ if (this.defaultNamespace && this.defaultNamespace === namesp && this.flags.indexOf('d') < 0) {
639
+ // d -> suppress default
640
+ if (this.flags.indexOf('k') >= 0 && this.keyords.indexOf(localid) < 0) {
641
+ return localid;
926
642
  }
643
+ return ':' + localid;
927
644
  }
928
-
929
- return str;
930
- };
931
-
932
- function statementListToXMLTreeMethod(statements) {
933
- this.suggestPrefix('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
934
- var stats = this.rootSubjects(statements);
935
- var roots = stats.roots;
936
- var results = [];
937
-
938
- for (var i = 0; i < roots.length; i++) {
939
- var root = roots[i];
940
- results.push(subjectXMLTree(root, stats));
645
+ // this.checkIntegrity() // @@@ Remove when not testing
646
+ var prefix = this.prefixes[namesp];
647
+ if (!prefix) prefix = this.makeUpPrefix(namesp);
648
+ if (prefix) {
649
+ this.namespacesUsed[namesp] = true;
650
+ return prefix + ':' + localid;
941
651
  }
942
-
943
- return results;
944
- }
945
-
946
- var statementListToXMLTree = statementListToXMLTreeMethod.bind(this);
947
-
948
- function escapeForXML(str) {
949
- if (typeof str === 'undefined') return '@@@undefined@@@@';
950
- return str.replace(/[&<"]/g, function (m) {
951
- switch (m[0]) {
952
- case '&':
953
- return '&amp;';
954
-
955
- case '<':
956
- return '&lt;';
957
-
958
- case '"':
959
- return '&quot;';
960
- // '
961
- }
962
- });
652
+ // Fall though if can't do qname
963
653
  }
654
+ }
964
655
 
965
- function relURIMethod(term) {
966
- return escapeForXML(this.base ? Util.uri.refTo(this.base, term.uri) : term.uri);
967
- }
968
-
969
- var relURI = relURIMethod.bind(this); // The tree for a subject
970
-
971
- function subjectXMLTreeMethod(subject, stats) {
972
- var results = [];
973
- var type, t, st, pred;
974
- var sts = stats.subjects[this.toStr(subject)]; // relevant statements
975
-
976
- if (typeof sts === 'undefined') {
977
- // empty bnode
978
- return propertyXMLTree(subject, stats);
979
- } // Sort only on the predicate, leave the order at object
980
- // level undisturbed. This leaves multilingual content in
981
- // the order of entry (for partner literals), which helps
982
- // readability.
983
- //
984
- // For the predicate sort, we attempt to split the uri
985
- // as a hint to the sequence
656
+ return this.explicitURI(uri);
657
+ }
986
658
 
659
+ // /////////////////////////// Quad store serialization
987
660
 
988
- sts.sort(function (a, b) {
989
- var ap = a.predicate.uri;
990
- var bp = b.predicate.uri;
661
+ // @para. write - a function taking a single string to be output
662
+ //
663
+ writeStore(write) {
664
+ var kb = this.store;
665
+ var fetcher = kb.fetcher;
666
+ var session = fetcher && fetcher.appNode;
991
667
 
992
- if (ap.substring(0, liPrefix.length) === liPrefix || bp.substring(0, liPrefix.length) === liPrefix) {
993
- // we're only interested in sorting list items
994
- return ap.localeCompare(bp);
995
- }
668
+ // The core data
996
669
 
997
- var as = ap.substring(liPrefix.length);
998
- var bs = bp.substring(liPrefix.length);
999
- var an = parseInt(as, 10);
1000
- var bn = parseInt(bs, 10);
670
+ var sources = this.store.index[3];
671
+ for (var s in sources) {
672
+ // -> assume we can use -> as short for log:semantics
673
+ var source = kb.fromNT(s);
674
+ if (session && source.equals(session)) continue;
675
+ write('\n' + this.atomicTermToN3(source) + ' ' + this.atomicTermToN3(kb.sym('http://www.w3.org/2000/10/swap/log#semantics')) + ' { ' + this.statementsToN3(kb.statementsMatching(undefined, undefined, undefined, source)) + ' }.\n');
676
+ }
1001
677
 
1002
- if (isNaN(an) || isNaN(bn) || an !== as || bn !== bs) {
1003
- // we only care about integers
1004
- return ap.localeCompare(bp);
1005
- }
678
+ // The metadata from HTTP interactions:
1006
679
 
1007
- return an - bn;
1008
- });
680
+ kb.statementsMatching(undefined, kb.sym('http://www.w3.org/2007/ont/link#requestedURI')).map(function (st) {
681
+ write('\n<' + st.object.value + '> log:metadata {\n');
682
+ var sts = kb.statementsMatching(undefined, undefined, undefined, st.subject);
683
+ write(this.statementsToN3(this.statementsToN3(sts)));
684
+ write('}.\n');
685
+ });
1009
686
 
1010
- for (var i = 0; i < sts.length; i++) {
1011
- st = sts[i]; // look for a type
687
+ // Inferences we have made ourselves not attributable to anyone else
1012
688
 
1013
- if (st.predicate.uri === 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' && !type && st.object.termType === 'NamedNode') {
1014
- type = st.object;
1015
- continue; // don't include it as a child element
1016
- } // see whether predicate can be replaced with "li"
689
+ var metaSources = [];
690
+ if (session) metaSources.push(session);
691
+ var metadata = [];
692
+ metaSources.map(function (source) {
693
+ metadata = metadata.concat(kb.statementsMatching(undefined, undefined, undefined, source));
694
+ });
695
+ write(this.statementsToN3(metadata));
696
+ }
1017
697
 
698
+ // ////////////////////////////////////////////// XML serialization
1018
699
 
1019
- pred = st.predicate;
700
+ statementsToXML(sts) {
701
+ var indent = 4;
702
+ var width = 80;
703
+ var namespaceCounts = []; // which have been used
704
+ namespaceCounts['http://www.w3.org/1999/02/22-rdf-syntax-ns#'] = true;
705
+ var liPrefix = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#_'; // prefix for ordered list items
1020
706
 
1021
- if (pred.uri.substr(0, liPrefix.length) === liPrefix) {
1022
- var number = pred.uri.substr(liPrefix.length); // make sure these are actually numeric list items
707
+ // //////////////////////// Arrange the bits of XML text
1023
708
 
1024
- var intNumber = parseInt(number, 10);
709
+ var spaces = function (n) {
710
+ var s = '';
711
+ for (var i = 0; i < n; i++) s += ' ';
712
+ return s;
713
+ };
714
+ var XMLtreeToLine = function (tree) {
715
+ var str = '';
716
+ for (var i = 0; i < tree.length; i++) {
717
+ var branch = tree[i];
718
+ var s2 = typeof branch === 'string' ? branch : XMLtreeToLine(branch);
719
+ str += s2;
720
+ }
721
+ return str;
722
+ };
1025
723
 
1026
- if (number === intNumber.toString()) {
1027
- // was numeric; don't need to worry about ordering since we've already
1028
- // sorted the statements
1029
- pred = this.rdfFactory.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#li');
724
+ // Convert a nested tree of lists and strings to a string
725
+ var XMLtreeToString = function (tree, level) {
726
+ var str = '';
727
+ var line;
728
+ var lastLength = 100000;
729
+ if (!level) level = 0;
730
+ for (var i = 0; i < tree.length; i++) {
731
+ var branch = tree[i];
732
+ if (typeof branch !== 'string') {
733
+ var substr = XMLtreeToString(branch, level + 1);
734
+ if (substr.length < 10 * (width - indent * level) && substr.indexOf('"""') < 0) {
735
+ // Don't mess up multiline strings
736
+ line = XMLtreeToLine(branch);
737
+ if (line.length < width - indent * level) {
738
+ branch = ' ' + line; // @@ Hack: treat as string below
739
+ substr = '';
1030
740
  }
1031
741
  }
1032
-
1033
- t = qname(pred);
1034
-
1035
- switch (st.object.termType) {
1036
- case 'BlankNode':
1037
- if (stats.incoming[st.object].length === 1) {
1038
- // there should always be something in the incoming array for a bnode
1039
- results = results.concat(['<' + t + ' rdf:parseType="Resource">', subjectXMLTree(st.object, stats), '</' + t + '>']);
1040
- } else {
1041
- results = results.concat(['<' + t + ' rdf:nodeID="' + st.object.toNT().slice(2) + '"/>']);
1042
- }
1043
-
1044
- break;
1045
-
1046
- case 'NamedNode':
1047
- results = results.concat(['<' + t + ' rdf:resource="' + relURI(st.object) + '"/>']);
1048
- break;
1049
-
1050
- case 'Literal':
1051
- results = results.concat(['<' + t + (st.object.datatype.equals(this.xsd.string) ? '' : ' rdf:datatype="' + escapeForXML(st.object.datatype.uri) + '"') + (st.object.language ? ' xml:lang="' + st.object.language + '"' : '') + '>' + escapeForXML(st.object.value) + '</' + t + '>']);
1052
- break;
1053
-
1054
- case 'Collection':
1055
- results = results.concat(['<' + t + ' rdf:parseType="Collection">', collectionXMLTree(st.object, stats), '</' + t + '>']);
1056
- break;
1057
-
1058
- default:
1059
- throw new Error("Can't serialize object of type " + st.object.termType + ' into XML');
1060
- } // switch
1061
-
1062
- }
1063
-
1064
- var tag = type ? qname(type) : 'rdf:Description';
1065
- var attrs = '';
1066
-
1067
- if (subject.termType === 'BlankNode') {
1068
- if (!stats.incoming[subject] || stats.incoming[subject].length !== 1) {
1069
- // not an anonymous bnode
1070
- attrs = ' rdf:nodeID="' + subject.toNT().slice(2) + '"';
742
+ if (substr) lastLength = 10000;
743
+ str += substr;
744
+ }
745
+ if (typeof branch === 'string') {
746
+ if (lastLength < indent * level + 4) {
747
+ // continue
748
+ str = str.slice(0, -1) + ' ' + branch + '\n';
749
+ lastLength += branch.length + 1;
750
+ } else {
751
+ line = spaces(indent * level) + branch;
752
+ str += line + '\n';
753
+ lastLength = line.length;
1071
754
  }
1072
- } else {
1073
- attrs = ' rdf:about="' + relURI(subject) + '"';
755
+ } else {// not string
1074
756
  }
1075
-
1076
- return ['<' + tag + attrs + '>'].concat([results]).concat(['</' + tag + '>']);
1077
757
  }
1078
-
1079
- var subjectXMLTree = subjectXMLTreeMethod.bind(this);
1080
-
1081
- function collectionXMLTree(subject, stats) {
1082
- var res = [];
1083
-
1084
- for (var i = 0; i < subject.elements.length; i++) {
1085
- res.push(subjectXMLTree(subject.elements[i], stats));
758
+ return str;
759
+ };
760
+ function statementListToXMLTreeMethod(statements) {
761
+ this.suggestPrefix('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
762
+ var stats = this.rootSubjects(statements);
763
+ var roots = stats.roots;
764
+ var results = [];
765
+ for (var i = 0; i < roots.length; i++) {
766
+ var root = roots[i];
767
+ results.push(subjectXMLTree(root, stats));
768
+ }
769
+ return results;
770
+ }
771
+ var statementListToXMLTree = statementListToXMLTreeMethod.bind(this);
772
+ function escapeForXML(str) {
773
+ if (typeof str === 'undefined') return '@@@undefined@@@@';
774
+ return str.replace(/[&<"]/g, function (m) {
775
+ switch (m[0]) {
776
+ case '&':
777
+ return '&amp;';
778
+ case '<':
779
+ return '&lt;';
780
+ case '"':
781
+ return '&quot;';
782
+ // '
1086
783
  }
784
+ });
785
+ }
1087
786
 
1088
- return res;
1089
- } // The property tree for a single subject or anonymos node
1090
-
1091
-
1092
- function propertyXMLTreeMethod(subject, stats) {
1093
- var results = [];
1094
- var sts = stats.subjects[this.toStr(subject)]; // relevant statements
1095
-
1096
- if (!sts) return results; // No relevant statements
1097
-
1098
- sts.sort();
1099
-
1100
- for (var i = 0; i < sts.length; i++) {
1101
- var st = sts[i];
1102
-
1103
- switch (st.object.termType) {
1104
- case 'BlankNode':
1105
- if (stats.rootsHash[st.object.toNT()]) {
1106
- // This bnode has been done as a root -- no content here @@ what bout first time
1107
- results = results.concat(['<' + qname(st.predicate) + ' rdf:nodeID="' + st.object.toNT().slice(2) + '">', '</' + qname(st.predicate) + '>']);
1108
- } else {
1109
- results = results.concat(['<' + qname(st.predicate) + ' rdf:parseType="Resource">', propertyXMLTree(st.object, stats), '</' + qname(st.predicate) + '>']);
1110
- }
1111
-
1112
- break;
1113
-
1114
- case 'NamedNode':
1115
- results = results.concat(['<' + qname(st.predicate) + ' rdf:resource="' + relURI(st.object) + '"/>']);
1116
- break;
1117
-
1118
- case 'Literal':
1119
- results = results.concat(['<' + qname(st.predicate) + (st.object.datatype.equals(this.xsd.string) ? '' : ' rdf:datatype="' + escapeForXML(st.object.datatype.value) + '"') + (st.object.language ? ' xml:lang="' + st.object.language + '"' : '') + '>' + escapeForXML(st.object.value) + '</' + qname(st.predicate) + '>']);
1120
- break;
1121
-
1122
- case 'Collection':
1123
- results = results.concat(['<' + qname(st.predicate) + ' rdf:parseType="Collection">', collectionXMLTree(st.object, stats), '</' + qname(st.predicate) + '>']);
1124
- break;
1125
-
1126
- default:
1127
- throw new Error("Can't serialize object of type " + st.object.termType + ' into XML');
1128
- } // switch
1129
-
787
+ function relURIMethod(term) {
788
+ return escapeForXML(this.base ? Util.uri.refTo(this.base, term.uri) : term.uri);
789
+ }
790
+ var relURI = relURIMethod.bind(this);
791
+
792
+ // The tree for a subject
793
+ function subjectXMLTreeMethod(subject, stats) {
794
+ var results = [];
795
+ var type, t, st, pred;
796
+ var sts = stats.subjects[this.toStr(subject)]; // relevant statements
797
+ if (typeof sts === 'undefined') {
798
+ // empty bnode
799
+ return propertyXMLTree(subject, stats);
800
+ }
801
+
802
+ // Sort only on the predicate, leave the order at object
803
+ // level undisturbed. This leaves multilingual content in
804
+ // the order of entry (for partner literals), which helps
805
+ // readability.
806
+ //
807
+ // For the predicate sort, we attempt to split the uri
808
+ // as a hint to the sequence
809
+ sts.sort(function (a, b) {
810
+ var ap = a.predicate.uri;
811
+ var bp = b.predicate.uri;
812
+ if (ap.substring(0, liPrefix.length) === liPrefix || bp.substring(0, liPrefix.length) === liPrefix) {
813
+ // we're only interested in sorting list items
814
+ return ap.localeCompare(bp);
815
+ }
816
+ var as = ap.substring(liPrefix.length);
817
+ var bs = bp.substring(liPrefix.length);
818
+ var an = parseInt(as, 10);
819
+ var bn = parseInt(bs, 10);
820
+ if (isNaN(an) || isNaN(bn) || an !== as || bn !== bs) {
821
+ // we only care about integers
822
+ return ap.localeCompare(bp);
823
+ }
824
+ return an - bn;
825
+ });
826
+ for (var i = 0; i < sts.length; i++) {
827
+ st = sts[i];
828
+ // look for a type
829
+ if (st.predicate.uri === 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' && !type && st.object.termType === 'NamedNode') {
830
+ type = st.object;
831
+ continue; // don't include it as a child element
832
+ }
833
+
834
+ // see whether predicate can be replaced with "li"
835
+ pred = st.predicate;
836
+ if (pred.uri.substr(0, liPrefix.length) === liPrefix) {
837
+ var number = pred.uri.substr(liPrefix.length);
838
+ // make sure these are actually numeric list items
839
+ var intNumber = parseInt(number, 10);
840
+ if (number === intNumber.toString()) {
841
+ // was numeric; don't need to worry about ordering since we've already
842
+ // sorted the statements
843
+ pred = this.rdfFactory.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#li');
844
+ }
1130
845
  }
1131
-
1132
- return results;
846
+ t = qname(pred);
847
+ switch (st.object.termType) {
848
+ case 'BlankNode':
849
+ if (stats.incoming[st.object].length === 1) {
850
+ // there should always be something in the incoming array for a bnode
851
+ results = results.concat(['<' + t + ' rdf:parseType="Resource">', subjectXMLTree(st.object, stats), '</' + t + '>']);
852
+ } else {
853
+ results = results.concat(['<' + t + ' rdf:nodeID="' + st.object.toNT().slice(2) + '"/>']);
854
+ }
855
+ break;
856
+ case 'NamedNode':
857
+ results = results.concat(['<' + t + ' rdf:resource="' + relURI(st.object) + '"/>']);
858
+ break;
859
+ case 'Literal':
860
+ results = results.concat(['<' + t + (st.object.datatype.equals(this.xsd.string) ? '' : ' rdf:datatype="' + escapeForXML(st.object.datatype.uri) + '"') + (st.object.language ? ' xml:lang="' + st.object.language + '"' : '') + '>' + escapeForXML(st.object.value) + '</' + t + '>']);
861
+ break;
862
+ case 'Collection':
863
+ results = results.concat(['<' + t + ' rdf:parseType="Collection">', collectionXMLTree(st.object, stats), '</' + t + '>']);
864
+ break;
865
+ default:
866
+ throw new Error("Can't serialize object of type " + st.object.termType + ' into XML');
867
+ } // switch
1133
868
  }
1134
869
 
1135
- var propertyXMLTree = propertyXMLTreeMethod.bind(this);
1136
-
1137
- function qnameMethod(term) {
1138
- var uri = term.uri;
1139
- var j = uri.indexOf('#');
1140
-
1141
- if (j < 0 && this.flags.indexOf('/') < 0) {
1142
- j = uri.lastIndexOf('/');
1143
- }
1144
-
1145
- if (j < 0) throw new Error('Cannot make qname out of <' + uri + '>');
1146
-
1147
- for (var k = j + 1; k < uri.length; k++) {
1148
- if (this._notNameChars.indexOf(uri[k]) >= 0) {
1149
- throw new Error('Invalid character "' + uri[k] + '" cannot be in XML qname for URI: ' + uri);
1150
- }
870
+ var tag = type ? qname(type) : 'rdf:Description';
871
+ var attrs = '';
872
+ if (subject.termType === 'BlankNode') {
873
+ if (!stats.incoming[subject] || stats.incoming[subject].length !== 1) {
874
+ // not an anonymous bnode
875
+ attrs = ' rdf:nodeID="' + subject.toNT().slice(2) + '"';
1151
876
  }
877
+ } else {
878
+ attrs = ' rdf:about="' + relURI(subject) + '"';
879
+ }
880
+ return ['<' + tag + attrs + '>'].concat([results]).concat(['</' + tag + '>']);
881
+ }
882
+ var subjectXMLTree = subjectXMLTreeMethod.bind(this);
883
+ function collectionXMLTree(subject, stats) {
884
+ var res = [];
885
+ for (var i = 0; i < subject.elements.length; i++) {
886
+ res.push(subjectXMLTree(subject.elements[i], stats));
887
+ }
888
+ return res;
889
+ }
1152
890
 
1153
- var localid = uri.slice(j + 1);
1154
- var namesp = uri.slice(0, j + 1);
891
+ // The property tree for a single subject or anonymos node
892
+ function propertyXMLTreeMethod(subject, stats) {
893
+ var results = [];
894
+ var sts = stats.subjects[this.toStr(subject)]; // relevant statements
895
+ if (!sts) return results; // No relevant statements
896
+ sts.sort();
897
+ for (var i = 0; i < sts.length; i++) {
898
+ var st = sts[i];
899
+ switch (st.object.termType) {
900
+ case 'BlankNode':
901
+ if (stats.rootsHash[st.object.toNT()]) {
902
+ // This bnode has been done as a root -- no content here @@ what bout first time
903
+ results = results.concat(['<' + qname(st.predicate) + ' rdf:nodeID="' + st.object.toNT().slice(2) + '">', '</' + qname(st.predicate) + '>']);
904
+ } else {
905
+ results = results.concat(['<' + qname(st.predicate) + ' rdf:parseType="Resource">', propertyXMLTree(st.object, stats), '</' + qname(st.predicate) + '>']);
906
+ }
907
+ break;
908
+ case 'NamedNode':
909
+ results = results.concat(['<' + qname(st.predicate) + ' rdf:resource="' + relURI(st.object) + '"/>']);
910
+ break;
911
+ case 'Literal':
912
+ results = results.concat(['<' + qname(st.predicate) + (st.object.datatype.equals(this.xsd.string) ? '' : ' rdf:datatype="' + escapeForXML(st.object.datatype.value) + '"') + (st.object.language ? ' xml:lang="' + st.object.language + '"' : '') + '>' + escapeForXML(st.object.value) + '</' + qname(st.predicate) + '>']);
913
+ break;
914
+ case 'Collection':
915
+ results = results.concat(['<' + qname(st.predicate) + ' rdf:parseType="Collection">', collectionXMLTree(st.object, stats), '</' + qname(st.predicate) + '>']);
916
+ break;
917
+ default:
918
+ throw new Error("Can't serialize object of type " + st.object.termType + ' into XML');
919
+ } // switch
920
+ }
1155
921
 
1156
- if (this.defaultNamespace && this.defaultNamespace === namesp && this.flags.indexOf('d') < 0) {
1157
- // d -> suppress default
1158
- return localid;
922
+ return results;
923
+ }
924
+ var propertyXMLTree = propertyXMLTreeMethod.bind(this);
925
+ function qnameMethod(term) {
926
+ var uri = term.uri;
927
+ var j = uri.indexOf('#');
928
+ if (j < 0 && this.flags.indexOf('/') < 0) {
929
+ j = uri.lastIndexOf('/');
930
+ }
931
+ if (j < 0) throw new Error('Cannot make qname out of <' + uri + '>');
932
+ for (var k = j + 1; k < uri.length; k++) {
933
+ if (this._notNameChars.indexOf(uri[k]) >= 0) {
934
+ throw new Error('Invalid character "' + uri[k] + '" cannot be in XML qname for URI: ' + uri);
1159
935
  }
1160
-
1161
- var prefix = this.prefixes[namesp];
1162
- if (!prefix) prefix = this.makeUpPrefix(namesp);
1163
- namespaceCounts[namesp] = true;
1164
- return prefix + ':' + localid;
1165
936
  }
1166
-
1167
- var qname = qnameMethod.bind(this); // Body of toXML:
1168
-
1169
- var tree = statementListToXMLTree(sts);
1170
- var str = '<rdf:RDF';
1171
-
1172
- if (this.defaultNamespace) {
1173
- str += ' xmlns="' + escapeForXML(this.defaultNamespace) + '"';
937
+ var localid = uri.slice(j + 1);
938
+ var namesp = uri.slice(0, j + 1);
939
+ if (this.defaultNamespace && this.defaultNamespace === namesp && this.flags.indexOf('d') < 0) {
940
+ // d -> suppress default
941
+ return localid;
1174
942
  }
943
+ var prefix = this.prefixes[namesp];
944
+ if (!prefix) prefix = this.makeUpPrefix(namesp);
945
+ namespaceCounts[namesp] = true;
946
+ return prefix + ':' + localid;
947
+ }
948
+ var qname = qnameMethod.bind(this);
1175
949
 
1176
- for (var ns in namespaceCounts) {
1177
- if (!namespaceCounts.hasOwnProperty(ns)) continue; // Rel uris in xml ns is not strictly allowed in the XMLNS spec but needed in practice often
950
+ // Body of toXML:
1178
951
 
1179
- var ns2 = this.base && this.flags.includes('z') ? Util.uri.refTo(this.base, ns) : ns;
1180
- str += '\n xmlns:' + this.prefixes[ns] + '="' + escapeForXML(ns2) + '"';
952
+ var tree = statementListToXMLTree(sts);
953
+ var str = '<rdf:RDF';
954
+ if (this.defaultNamespace) {
955
+ str += ' xmlns="' + escapeForXML(this.defaultNamespace) + '"';
956
+ }
957
+ for (var ns in namespaceCounts) {
958
+ if (!namespaceCounts.hasOwnProperty(ns)) continue;
959
+ // Rel uris in xml ns is not strictly allowed in the XMLNS spec but needed in practice often
960
+ var ns2 = this.base && this.flags.includes('z') ? Util.uri.refTo(this.base, ns) : ns;
961
+ str += '\n xmlns:' + this.prefixes[ns] + '="' + escapeForXML(ns2) + '"';
962
+ }
963
+ str += '>';
964
+ var tree2 = [str, tree, '</rdf:RDF>']; // @@ namespace declrations
965
+ return XMLtreeToString(tree2, -1);
966
+ } // End @@ body
967
+
968
+ statementsToJsonld(sts) {
969
+ // ttl2jsonld creates context keys for all ttl prefix
970
+ // context keys must be full IRI
971
+ function findId(itemObj) {
972
+ if (itemObj['@id']) {
973
+ const item = itemObj['@id'].split(':');
974
+ if (keys[item[0]]) itemObj['@id'] = jsonldObj['@context'][item[0]] + item[1];
975
+ }
976
+ const itemValues = Object.values(itemObj);
977
+ for (const i in itemValues) {
978
+ if (typeof itemValues[i] !== 'string') {
979
+ // @list contains array
980
+ findId(itemValues[i]);
981
+ }
1181
982
  }
983
+ }
984
+ const turtleDoc = this.statementsToN3(sts);
985
+ const jsonldObj = ttl2jsonld.parse(turtleDoc);
986
+ return JSON.stringify(jsonldObj, null, 2);
987
+ }
988
+ }
1182
989
 
1183
- str += '>';
1184
- var tree2 = [str, tree, '</rdf:RDF>']; // @@ namespace declrations
1185
-
1186
- return XMLtreeToString(tree2, -1);
1187
- } // End @@ body
1188
-
1189
- }]);
1190
-
1191
- return Serializer;
1192
- }(); // String escaping utilities
990
+ // String escaping utilities
1193
991
 
1194
992
  function hexify(str) {
1195
993
  // also used in parser
1196
994
  return encodeURI(str);
1197
995
  }
1198
-
1199
996
  function backslashUify(str) {
1200
997
  var res = '';
1201
998
  var k;
1202
-
1203
999
  for (var i = 0; i < str.length; i++) {
1204
1000
  k = str.charCodeAt(i);
1205
-
1206
1001
  if (k > 65535) {
1207
- res += "\\U" + ('00000000' + k.toString(16)).slice(-8); // convert to upper?
1002
+ res += '\\U' + ('00000000' + k.toString(16)).slice(-8); // convert to upper?
1208
1003
  } else if (k > 126) {
1209
- res += "\\u" + ('0000' + k.toString(16)).slice(-4);
1004
+ res += '\\u' + ('0000' + k.toString(16)).slice(-4);
1210
1005
  } else {
1211
1006
  res += str[i];
1212
1007
  }
1213
1008
  }
1214
-
1215
1009
  return res;
1216
1010
  }