Skip to content

Commit a6db734

Browse files
author
Miel Vander Sande
committed
Added summary datasource
1 parent b7a55fb commit a6db734

File tree

3 files changed

+139
-0
lines changed

3 files changed

+139
-0
lines changed

lib/datasources/SummaryDatasource.js

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
var Datasource = require('./Datasource'),
2+
N3 = require('n3'),
3+
path = require('path'),
4+
fs = require('fs'),
5+
Bloem = require('bloem').Bloem;
6+
7+
var ACCEPT = 'text/turtle;q=1.0,application/n-triples;q=0.7,text/n3;q=0.6';
8+
9+
var DCT = 'http://purl.org/dc/terms/',
10+
AMF = 'http://semweb.mmlab.be/ns/membership#',
11+
DS = 'http://semweb.mmlab.be/ns/summaries#';
12+
13+
// Creates a new SummaryDatasource
14+
function SummaryDatasource(options) {
15+
if (!(this instanceof SummaryDatasource))
16+
return new SummaryDatasource(options);
17+
Datasource.call(this, options);
18+
19+
// Settings for data summaries
20+
this._summariesFolder = options.dir || '../../summaries';
21+
}
22+
Datasource.extend(SummaryDatasource, ['triplePattern', 'limit', 'offset']);
23+
24+
// Prepares the datasource for querying
25+
SummaryDatasource.prototype._initialize = function (done) {
26+
var tripleStore = this._tripleStore = new N3.Store();
27+
var parser = new N3.Parser();
28+
var filters = this._filters = {};
29+
var self = this;
30+
31+
fs.readdir(this._summariesFolder, function (err, items) {
32+
if (err) {
33+
done(err);
34+
return;
35+
}
36+
37+
// Store every summary in the store
38+
items.forEach(function (summaryFile) {
39+
var document = self._fetch({ url: path.join(self._summariesFolder, summaryFile), headers: { accept: ACCEPT } }, done);
40+
// N3Parser._resetBlankNodeIds();
41+
parser.parse(document, function (error, triple) {
42+
if (error) {
43+
done(error);
44+
return;
45+
}
46+
47+
if (triple)
48+
tripleStore.addTriple(triple.subject, triple.predicate, triple.object, summaryFile);
49+
else {
50+
// Create AMFs
51+
self._storeFilters();
52+
done();
53+
}
54+
});
55+
});
56+
});
57+
};
58+
59+
SummaryDatasource.prototype._storeFilters = function () {
60+
var filterQuads = this._tripleStore.find(null, DS + 'objFilter', null);
61+
62+
filterQuads.forEach(function (quad) {
63+
var bitsString = this._tripleStore.find(quad.object, AMF + 'bits', null)[0].object;
64+
var bits = parseInt(N3.Util.getLiteralValue(bitsString), 10);
65+
66+
var hashesString = this._tripleStore.find(quad.object, AMF + 'hashes', null)[0].object;
67+
var hashes = parseInt(N3.Util.getLiteralValue(hashesString), 10);
68+
69+
// Decode filter
70+
var filterString = this._tripleStore.find(quad.object, AMF + 'filter', null)[0].object;
71+
var filter = Buffer.from(N3.Util.getLiteralValue(filterString), 'base64');
72+
73+
// Find predicate
74+
var predicate = this._tripleStore.find(quad.subject, DS + 'predicate', null, quad.graph)[0].object;
75+
76+
this._filters[predicate] = this._filters[predicate] || {}; // create entry for predicate if not exists
77+
this._filters[predicate][quad.graph] = new Bloem(bits, hashes, filter); // add filter for the summary
78+
});
79+
};
80+
81+
SummaryDatasource.prototype._findSources = function (term, predicate) {
82+
var filters = predicate ? [predicate] : Object.keys(this._filters);
83+
var sources = [];
84+
for (var i = 0; i < filters.length; i++) {
85+
var filter = this._filters[filters[i]];
86+
for (var source in filter) {
87+
if (filter[source].has(Buffer.from(term)) && sources.indexOf(source) < 0)
88+
sources.push(source);
89+
}
90+
}
91+
return sources;
92+
};
93+
94+
// Writes the results of the query to the given triple stream
95+
SummaryDatasource.prototype._executeQuery = function (query, destination) {
96+
var offset = query.offset || 0, limit = query.limit || Infinity,
97+
triples = this._tripleStore.findByIRI(query.subject, query.predicate, query.object);
98+
99+
if (query.subject && query.predicate === DCT + 'isPartOf') {
100+
triples = this._findSources(query.subject).map(function (source) {
101+
return {
102+
subject: query.subject,
103+
predicate: query.predicate,
104+
object: source,
105+
};
106+
});
107+
}
108+
109+
// Send the metadata
110+
destination.setProperty('metadata', { totalCount: triples.length, hasExactCount: true });
111+
// Send the requested subset of triples
112+
for (var i = offset, l = Math.min(offset + limit, triples.length); i < l; i++)
113+
destination._push(triples[i]);
114+
destination.close();
115+
};
116+
117+
118+
119+
module.exports = SummaryDatasource;

package-lock.json

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
},
2424
"dependencies": {
2525
"asynciterator": "^1.1.0",
26+
"bloem": "^0.2.4",
2627
"forwarded-parse": "^2.0.0",
2728
"jsonld": "^0.4.11",
2829
"lodash": "^2.4.2",

0 commit comments

Comments
 (0)