Skip to content

Commit

Permalink
Add filtering based on property value when iterating all entities
Browse files Browse the repository at this point in the history
  • Loading branch information
alvinsw committed Apr 13, 2023
1 parent e9a2f36 commit ddb8979
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 12 deletions.
36 changes: 29 additions & 7 deletions lib/rocrate.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,16 @@ class ROCrate {
/**
* Lookup table to get a reference to existing and non-existing nodes.
* This is needed to avoid searching for the whole graph for every "@reverse" lookup
* and because an entity referenced by other entities may not exist yet in the graph.
* as an entity referenced by other entities may not exist yet in the graph.
* @type {Map<string, Node>}
*/
#nodeById = new Map();
/** Lookup table to index nodes by their properties */
#nodeByX = {};

#handler;
#handlerReverse;

/** Lookup table to get list of entities by their type */
#entityByType = {};

/** Internal representation of the context */
#context = {};

Expand Down Expand Up @@ -586,10 +585,31 @@ class ROCrate {

/**
* Returns a new iterator object that contains the entities in the graph.
* @param {Object} [p]
* @param {boolean} [p.flat] - If true, return the copy of entity as a plain object.
* @param {Object|function} [p.filter] - Filter the result based on the values of the properties defined in this object.
*/
entities(flat) {
entities({flat, filter}={}) {
var iter = this.#nodeById.values();
var crate = this;
var filterFunc = filter;
var t = typeof filterFunc;
if (filter && t !== 'function') {
if (t !== 'object') throw new Error('filter must be a function or object');
filterFunc = function(entity) {
var filtered = true;
for (const key in filter) {
let r = false;
for (const v of Utils.asArrayRef(entity[key])) {
if (!v['@id']) {
r = r || filter[key].test(v.toString());
}
}
filtered = filtered && r;
}
return filtered;
}
}
return {
[Symbol.iterator]() { return this; },
next() {
Expand All @@ -598,7 +618,9 @@ class ROCrate {
value = r.value;
if (value[$size]) {
value = flat ? value.toJSON() : crate.#getNodeProxy(value);
return { done: false, value };
if (!filterFunc || filterFunc(value)) {
return { done: false, value };
}
}
}
return { done: true, value: null };
Expand Down Expand Up @@ -643,7 +665,7 @@ class ROCrate {
* @return {Array}
*/
getGraph(flat = false) {
return Array.from(this.entities(flat));
return Array.from(this.entities({flat}));
}

/**
Expand Down
18 changes: 13 additions & 5 deletions test/node.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,26 +162,34 @@ describe("Entity wrapper", function () {
});

describe("Array wrapper", function () {
g.config.alwaysAsArray = true;
it("can set array value", function () {
g.config.alwaysAsArray = true;
let e1 = g.getEntity('#1');
let test = new Proxy(e1.name, { get: function(t, k, r) { console.log('p', k); return t[k]; }});
console.log('aaaaaaaaa');
test.push('a');
console.log('bbbbbbbbb');
e1.name[0] = 'test value';
assert.strictEqual(e1.name[0], 'test value');
e1.name[1] = 'name';
assert.strictEqual(e1.name[1], 'name');
});
it("can add to array", function () {
g.config.alwaysAsArray = true;
let e1 = g.getEntity('#1');
e1.name = ['d1'];
e1.name.push('name1');
assert.strictEqual(e1.name[1], 'name1');
e1.name.unshift('name0');
assert.strictEqual(e1.name[0], 'name0');
});
it("can remove array element", function () {
g.config.alwaysAsArray = true;
let e1 = g.getEntity('#1');
e1.name = ['n1','n2','n3','n4', 'n5'];
assert.strictEqual(e1.name.pop(), 'n5');
assert.strictEqual(e1.name.shift(), 'n1');
assert.strictEqual(e1.name.length, 3);
e1.name.splice(1, 2);
assert.strictEqual(e1.name[0], 'n2');
assert.strictEqual(e1.name.length, 1);
});

});

Expand Down
15 changes: 15 additions & 0 deletions test/rocrate.new.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ describe("entities", function () {
e = iter.next().value;
assert.equal(e, crate.getEntity(e['@id']));
});
it("can iterate filtered entities", function () {
let crate = new ROCrate();
let result = Array.from(crate.entities({filter: {'@type': /^Dataset$/}}));
assert.equal(result.length, 1);
assert.equal(result[0], crate.rootDataset);
});
});

describe("getGraph", function () {
Expand Down Expand Up @@ -465,6 +471,15 @@ describe("setProperty", function () {
assert.strictEqual(r.hasMember[0]['@id'], 'one');
assert(crate.getEntity('one'));
});
it("can modify array of values", function () {
let crate = new ROCrate(testData, { array: true });
var r = crate.rootDataset;
r.license[1] = 'test licence';
r.license.push('test licence 2');
assert.strictEqual(r.license[1], 'test licence');
assert.strictEqual(r.license[2], 'test licence 2');

});
});

describe("deleteProperty", function () {
Expand Down

0 comments on commit ddb8979

Please sign in to comment.