From 5e6a9b09a9080ad09212608c65c7574777fda329 Mon Sep 17 00:00:00 2001 From: constraintAutomaton Date: Thu, 11 Apr 2024 14:13:01 +0200 Subject: [PATCH] Add reachability criteria annotation to the metadata of links * reachability criteria annotation added * matching subject and checksubject field added to the link annotation --- .../lib/ActorExtractLinksAll.ts | 2 +- ...ActorRdfMetadataExtractTraverseAll-test.ts | 10 ++- .../lib/ActorExtractLinksContentPolicies.ts | 6 +- .../ActorExtractLinksContentPolicies-test.ts | 86 +++++++++++++++---- .../lib/ActorExtractLinksTree.ts | 9 +- .../test/ActorExtractLinksTree-test.ts | 16 ++-- .../lib/ActorExtractLinksPredicates.ts | 14 ++- .../test/ActorExtractLinksPredicates-test.ts | 44 ++++++++-- .../lib/ActorExtractLinksQuadPatternQuery.ts | 12 ++- .../ActorExtractLinksQuadPatternQuery-test.ts | 26 ++++-- .../lib/ActorExtractLinksQuadPattern.ts | 10 ++- .../test/ActorExtractLinksQuadPattern-test.ts | 14 +-- .../lib/ActorExtractLinksSolidTypeIndex.ts | 7 +- .../ActorExtractLinksSolidTypeIndex-test.ts | 84 ++++++++++++------ 14 files changed, 250 insertions(+), 90 deletions(-) diff --git a/packages/actor-extract-links-all/lib/ActorExtractLinksAll.ts b/packages/actor-extract-links-all/lib/ActorExtractLinksAll.ts index 012c392b0..9d30afa5b 100644 --- a/packages/actor-extract-links-all/lib/ActorExtractLinksAll.ts +++ b/packages/actor-extract-links-all/lib/ActorExtractLinksAll.ts @@ -19,7 +19,7 @@ export class ActorExtractLinksAll extends ActorExtractLinks { return { links: await ActorExtractLinks.collectStream(action.metadata, (quad, links) => { for (const link of getNamedNodes(getTerms(quad))) { - links.push({ url: link.value }); + links.push({ url: link.value, metadata: { producedByActor: { name: this.name }}}); } }), }; diff --git a/packages/actor-extract-links-all/test/ActorRdfMetadataExtractTraverseAll-test.ts b/packages/actor-extract-links-all/test/ActorRdfMetadataExtractTraverseAll-test.ts index 0cdadfd83..d9f4de703 100644 --- a/packages/actor-extract-links-all/test/ActorRdfMetadataExtractTraverseAll-test.ts +++ b/packages/actor-extract-links-all/test/ActorRdfMetadataExtractTraverseAll-test.ts @@ -19,15 +19,15 @@ describe('ActorExtractLinksAll', () => { }); it('should be a ActorExtractLinksAll constructor', () => { - expect(new ( ActorExtractLinksAll)({ name: 'actor', bus })) + expect(new (ActorExtractLinksAll)({ name: 'actor', bus })) .toBeInstanceOf(ActorExtractLinksAll); - expect(new ( ActorExtractLinksAll)({ name: 'actor', bus })) + expect(new (ActorExtractLinksAll)({ name: 'actor', bus })) .toBeInstanceOf(ActorExtractLinks); }); it('should not be able to create new ActorExtractLinksAll objects without \'new\'', () => { expect(() => { - ( ActorExtractLinksAll)(); + (ActorExtractLinksAll)(); }).toThrow(`Class constructor ActorExtractLinksAll cannot be invoked without 'new'`); }); }); @@ -75,7 +75,9 @@ describe('ActorExtractLinksAll', () => { { url: 'ex:p' }, { url: 'ex:o5' }, { url: 'ex:gx' }, - ], + ].map((link) => { + return { ...link, metadata: { producedByActor: { name: actor.name }}}; + }), }); }); }); diff --git a/packages/actor-extract-links-content-policies/lib/ActorExtractLinksContentPolicies.ts b/packages/actor-extract-links-content-policies/lib/ActorExtractLinksContentPolicies.ts index 134e3d7b6..824a79903 100644 --- a/packages/actor-extract-links-content-policies/lib/ActorExtractLinksContentPolicies.ts +++ b/packages/actor-extract-links-content-policies/lib/ActorExtractLinksContentPolicies.ts @@ -127,7 +127,11 @@ export class ActorExtractLinksContentPolicies extends ActorExtractLinks for (const variable of contentPolicy.variables) { const term = binding.get(variable.name); if (term && term.termType === 'NamedNode') { - const link: ILink = { url: term.value, transform }; + const link: ILink = { + url: term.value, + transform, + metadata: { producedByActor: { name: this.name, traverseConditional: this.traverseConditional }}, + }; // Mark in the context if the linked document's policies should be considered link.context = new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: variable.withPolicies }); diff --git a/packages/actor-extract-links-content-policies/test/ActorExtractLinksContentPolicies-test.ts b/packages/actor-extract-links-content-policies/test/ActorExtractLinksContentPolicies-test.ts index 6accccf79..aa66e1088 100644 --- a/packages/actor-extract-links-content-policies/test/ActorExtractLinksContentPolicies-test.ts +++ b/packages/actor-extract-links-content-policies/test/ActorExtractLinksContentPolicies-test.ts @@ -111,10 +111,10 @@ describe('ActorExtractLinksContentPolicies', () => { actor = new ActorExtractLinksContentPolicies({ name: 'actor', bus, - actorInitQuery: {}, + actorInitQuery: {}, traverseConditional: false, }); - ( actor).queryEngine = queryEngine; + (actor).queryEngine = queryEngine; input = stream([ quad('ex:s1', 'ex:px', 'ex:o1', 'ex:gx'), quad('ex:s2', 'ex:p', '"o"', 'ex:g'), @@ -190,7 +190,12 @@ describe('ActorExtractLinksContentPolicies', () => { transform: undefined, context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: false }), }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, traverseConditional: actor.traverseConditional }}, + }; + }), }); }); @@ -198,10 +203,10 @@ describe('ActorExtractLinksContentPolicies', () => { actor = new ActorExtractLinksContentPolicies({ name: 'actor', bus, - actorInitQuery: {}, + actorInitQuery: {}, traverseConditional: true, }); - ( actor).queryEngine = queryEngine; + (actor).queryEngine = queryEngine; const context = new ActionContext({ [KEY_CONTEXT_POLICIES.name]: [ new ContentPolicy( @@ -229,7 +234,12 @@ describe('ActorExtractLinksContentPolicies', () => { transform: undefined, context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: false }), }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, traverseConditional: actor.traverseConditional }}, + }; + }), }); }); @@ -263,7 +273,12 @@ describe('ActorExtractLinksContentPolicies', () => { { url: 'ex:match1', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: false }) }, { url: 'ex:match3', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: false }) }, { url: 'ex:match2Bis', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: false }) }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, traverseConditional: actor.traverseConditional }}, + }; + }), }); }); @@ -313,7 +328,12 @@ describe('ActorExtractLinksContentPolicies', () => { transform: expect.anything(), context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: false }), }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, traverseConditional: actor.traverseConditional }}, + }; + }), }); expect(result.links[0].transform).toBeInstanceOf(Function); expect(result.links[1].transform).toBeInstanceOf(Function); @@ -359,7 +379,12 @@ describe('ActorExtractLinksContentPolicies', () => { links: [ { url: 'ex:match1', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: true }) }, { url: 'ex:match3', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: true }) }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, traverseConditional: actor.traverseConditional }}, + }; + }), }); }); @@ -380,7 +405,12 @@ describe('ActorExtractLinksContentPolicies', () => { links: [ { url: 'ex:match1', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: true }) }, { url: 'ex:match3', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: true }) }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, traverseConditional: actor.traverseConditional }}, + }; + }), }); }); @@ -393,7 +423,12 @@ describe('ActorExtractLinksContentPolicies', () => { { url: 'ex:match1', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: true }) }, { url: 'ex:match3', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: true }) }, { url: 'ex:match2Bis', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: false }) }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, traverseConditional: actor.traverseConditional }}, + }; + }), }); }); @@ -418,7 +453,12 @@ describe('ActorExtractLinksContentPolicies', () => { { url: 'ex:match2Bis', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: false }) }, { url: 'ex:match1', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: true }) }, { url: 'ex:match3', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: true }) }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, traverseConditional: actor.traverseConditional }}, + }; + }), }); }); @@ -432,7 +472,12 @@ describe('ActorExtractLinksContentPolicies', () => { { url: 'ex:match1', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: true }) }, { url: 'ex:match3', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: true }) }, { url: 'ex:match2Bis', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: false }) }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, traverseConditional: actor.traverseConditional }}, + }; + }), }); }); @@ -459,7 +504,12 @@ describe('ActorExtractLinksContentPolicies', () => { }, // URL match2Bis will not match the query operation pattern // { url: 'ex:match2Bis', context: new ActionContext({ [KEY_CONTEXT_WITHPOLICIES.name]: false }) }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, traverseConditional: actor.traverseConditional }}, + }; + }), }); }); @@ -483,7 +533,7 @@ describe('ActorExtractLinksContentPolicies', () => { new ContentPolicy( factory.createBgp([]), [{ name: 'varUnknown', withPolicies: false }], - factory.createConstruct( undefined, undefined), + factory.createConstruct(undefined, undefined), ), )).toBeTruthy(); }); @@ -493,7 +543,7 @@ describe('ActorExtractLinksContentPolicies', () => { new ContentPolicy( factory.createBgp([]), [{ name: 'varUnknown', withPolicies: false }], - factory.createConstruct( undefined, [ + factory.createConstruct(undefined, [ factory.createPattern( DF.namedNode('ex:s1'), DF.namedNode('ex:p1'), @@ -519,7 +569,7 @@ describe('ActorExtractLinksContentPolicies', () => { new ContentPolicy( factory.createBgp([]), [{ name: 'varUnknown', withPolicies: false }], - factory.createConstruct( undefined, [ + factory.createConstruct(undefined, [ factory.createPattern( DF.namedNode('ex:s1'), DF.namedNode('ex:p1'), @@ -545,7 +595,7 @@ describe('ActorExtractLinksContentPolicies', () => { new ContentPolicy( factory.createBgp([]), [{ name: 'varUnknown', withPolicies: false }], - factory.createConstruct( undefined, [ + factory.createConstruct(undefined, [ factory.createPattern( DF.variable('varS'), DF.namedNode('ex:p1'), diff --git a/packages/actor-extract-links-extract-tree/lib/ActorExtractLinksTree.ts b/packages/actor-extract-links-extract-tree/lib/ActorExtractLinksTree.ts index 02fa9d648..d41f15bcf 100644 --- a/packages/actor-extract-links-extract-tree/lib/ActorExtractLinksTree.ts +++ b/packages/actor-extract-links-extract-tree/lib/ActorExtractLinksTree.ts @@ -18,7 +18,6 @@ const DF = new DataFactory(); export class ActorExtractLinksTree extends ActorExtractLinks { public static readonly aNodeType = DF.namedNode('https://w3id.org/tree#node'); public static readonly aRelation = DF.namedNode('https://w3id.org/tree#relation'); - private static readonly rdfTypeNode = DF.namedNode('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'); public static readonly aView = DF.namedNode('https://w3id.org/tree#view'); public static readonly aSubset = DF.namedNode('http://rdfs.org/ns/void#subset'); public static readonly isPartOf = DF.namedNode('http://purl.org/dc/terms/isPartOf'); @@ -34,7 +33,7 @@ export class ActorExtractLinksTree extends ActorExtractLinks { public async run(action: IActionExtractLinks): Promise { return new Promise((resolve, reject) => { const strictModeFlag: boolean | undefined = - action.context.get(KeysExtractLinksTree.strictTraversal); + action.context.get(KeysExtractLinksTree.strictTraversal); const strictMode = strictModeFlag ?? true; const metadata = action.metadata; const currentNodeUrl = action.url; @@ -70,7 +69,7 @@ export class ActorExtractLinksTree extends ActorExtractLinks { const subjectOfRelation = relationNodeSubject.get(nodeValue); if (subjectOfRelation && effectiveTreeDocumentSubject.has(subjectOfRelation) ) { - links.push({ url: link }); + links.push({ url: link, metadata: { producedByActor: { name: this.name }}}); } } @@ -100,13 +99,13 @@ export class ActorExtractLinksTree extends ActorExtractLinks { if ( (!strictMode || quad.subject.value === url) && (quad.predicate.equals(ActorExtractLinksTree.aView) || - quad.predicate.equals(ActorExtractLinksTree.aSubset))) { + quad.predicate.equals(ActorExtractLinksTree.aSubset))) { rootNodeEffectiveSubject.add(quad.object.value); } if ( (!strictMode || quad.object.value === url) && - quad.predicate.equals(ActorExtractLinksTree.isPartOf)) { + quad.predicate.equals(ActorExtractLinksTree.isPartOf)) { rootNodeEffectiveSubject.add(quad.subject.value); } diff --git a/packages/actor-extract-links-extract-tree/test/ActorExtractLinksTree-test.ts b/packages/actor-extract-links-extract-tree/test/ActorExtractLinksTree-test.ts index d68b1a4b4..707ddbafb 100644 --- a/packages/actor-extract-links-extract-tree/test/ActorExtractLinksTree-test.ts +++ b/packages/actor-extract-links-extract-tree/test/ActorExtractLinksTree-test.ts @@ -56,7 +56,7 @@ describe('ActorExtractLinksExtractLinksTree', () => { const result = await actor.run(action); - expect(result).toEqual({ links: [{ url: expectedUrl }]}); + expect(result).toEqual({ links: [{ url: expectedUrl, metadata: { producedByActor: { name: actor.name }}}]}); }); it('should return the links of a TREE with multiple relations', async() => { @@ -80,7 +80,7 @@ describe('ActorExtractLinksExtractLinksTree', () => { const result = await actor.run(action); expect(result).toEqual({ links: expectedUrl.map((value) => { - return { url: value }; + return { url: value, metadata: { producedByActor: { name: actor.name }}}; }) }); }); @@ -99,7 +99,7 @@ describe('ActorExtractLinksExtractLinksTree', () => { const result = await actor.run(action); - expect(result).toEqual({ links: [{ url: expectedUrl }]}); + expect(result).toEqual({ links: [{ url: expectedUrl, metadata: { producedByActor: { name: actor.name }}}]}); }); it('should return the links of a TREE with multiple relations combining blank nodes and named nodes', async() => { @@ -122,7 +122,7 @@ describe('ActorExtractLinksExtractLinksTree', () => { const result = await actor.run(action); expect(result).toEqual({ links: expectedUrl.map((value) => { - return { url: value }; + return { url: value, metadata: { producedByActor: { name: actor.name }}}; }) }); }); @@ -152,7 +152,7 @@ describe('ActorExtractLinksExtractLinksTree', () => { const result = await actor.run(action); - expect(result).toEqual({ links: [{ url: expectedUrl }]}); + expect(result).toEqual({ links: [{ url: expectedUrl, metadata: { producedByActor: { name: actor.name }}}]}); } }); @@ -181,7 +181,7 @@ describe('ActorExtractLinksExtractLinksTree', () => { const result = await actor.run(action); - expect(result).toEqual({ links: [{ url: expectedUrl }]}); + expect(result).toEqual({ links: [{ url: expectedUrl, metadata: { producedByActor: { name: actor.name }}}]}); } }); @@ -213,7 +213,7 @@ describe('ActorExtractLinksExtractLinksTree', () => { const result = await actor.run(action); - expect(result).toEqual({ links: [{ url: expectedUrl }]}); + expect(result).toEqual({ links: [{ url: expectedUrl, metadata: { producedByActor: { name: actor.name }}}]}); } }); @@ -241,7 +241,7 @@ describe('ActorExtractLinksExtractLinksTree', () => { const result = await actor.run(action); expect(result).toEqual({ links: expectedUrl.map((value) => { - return { url: value }; + return { url: value, metadata: { producedByActor: { name: actor.name }}}; }) }); }); }); diff --git a/packages/actor-extract-links-predicates/lib/ActorExtractLinksPredicates.ts b/packages/actor-extract-links-predicates/lib/ActorExtractLinksPredicates.ts index 73d347f51..a20f45c63 100644 --- a/packages/actor-extract-links-predicates/lib/ActorExtractLinksPredicates.ts +++ b/packages/actor-extract-links-predicates/lib/ActorExtractLinksPredicates.ts @@ -8,10 +8,12 @@ import type { IActorArgs, IActorTest } from '@comunica/core'; export class ActorExtractLinksPredicates extends ActorExtractLinks { private readonly checkSubject: boolean; private readonly predicates: RegExp[]; + private readonly stringPredicates: string[]; public constructor(args: IActorExtractLinksTraversePredicatesArgs) { super(args); + this.stringPredicates = args.predicateRegexes; this.predicates = args.predicateRegexes.map(stringRegex => new RegExp(stringRegex, 'u')); } @@ -25,7 +27,17 @@ export class ActorExtractLinksPredicates extends ActorExtractLinks { if (!this.checkSubject || this.subjectMatches(quad.subject.value, action.url)) { for (const regex of this.predicates) { if (regex.test(quad.predicate.value)) { - links.push({ url: quad.object.value }); + links.push({ + url: quad.object.value, + metadata: { + producedByActor: { + name: this.name, + predicates: this.stringPredicates, + matchingPredicate: quad.predicate.value, + checkSubject: this.checkSubject, + }, + }, + }); break; } } diff --git a/packages/actor-extract-links-predicates/test/ActorExtractLinksPredicates-test.ts b/packages/actor-extract-links-predicates/test/ActorExtractLinksPredicates-test.ts index 52aa2dd15..ae3527266 100644 --- a/packages/actor-extract-links-predicates/test/ActorExtractLinksPredicates-test.ts +++ b/packages/actor-extract-links-predicates/test/ActorExtractLinksPredicates-test.ts @@ -15,15 +15,17 @@ describe('ActorExtractLinksTraversePredicates', () => { describe('An ActorExtractLinksTraversePredicates instance with check subject', () => { let actor: ActorExtractLinksPredicates; let input: Readable; + let predicateRegexes: string[]; beforeEach(() => { + predicateRegexes = [ + 'http://www.w3.org/ns/ldp#contains', + ]; actor = new ActorExtractLinksPredicates({ name: 'actor', bus, checkSubject: true, - predicateRegexes: [ - 'http://www.w3.org/ns/ldp#contains', - ], + predicateRegexes, }); input = stream([ quad('ex:s', 'http://www.w3.org/ns/ldp#contains', 'ex:r1', 'ex:gx'), @@ -44,7 +46,19 @@ describe('ActorExtractLinksTraversePredicates', () => { links: [ { url: 'ex:r1' }, { url: 'ex:r2' }, - ], + ].map((link) => { + return { + ...link, + metadata: { + producedByActor: { + name: actor.name, + predicates: predicateRegexes, + matchingPredicate: 'http://www.w3.org/ns/ldp#contains', + checkSubject: true, + }, + }, + }; + }), }); }); }); @@ -52,15 +66,17 @@ describe('ActorExtractLinksTraversePredicates', () => { describe('An ActorExtractLinksTraversePredicates instance without check subject', () => { let actor: ActorExtractLinksPredicates; let input: Readable; + let predicateRegexes: string[]; beforeEach(() => { + predicateRegexes = [ + 'http://www.w3.org/ns/ldp#contains', + ]; actor = new ActorExtractLinksPredicates({ name: 'actor', bus, checkSubject: false, - predicateRegexes: [ - 'http://www.w3.org/ns/ldp#contains', - ], + predicateRegexes, }); input = stream([ quad('ex:s', 'http://www.w3.org/ns/ldp#contains', 'ex:r1', 'ex:gx'), @@ -77,7 +93,19 @@ describe('ActorExtractLinksTraversePredicates', () => { { url: 'ex:r1' }, { url: 'ex:r2' }, { url: 'ex:r3' }, - ], + ].map((link) => { + return { + ...link, + metadata: { + producedByActor: { + name: actor.name, + predicates: predicateRegexes, + matchingPredicate: 'http://www.w3.org/ns/ldp#contains', + checkSubject: false, + }, + }, + }; + }), }); }); }); diff --git a/packages/actor-extract-links-quad-pattern-query/lib/ActorExtractLinksQuadPatternQuery.ts b/packages/actor-extract-links-quad-pattern-query/lib/ActorExtractLinksQuadPatternQuery.ts index b94377956..bb2e5c2e0 100644 --- a/packages/actor-extract-links-quad-pattern-query/lib/ActorExtractLinksQuadPatternQuery.ts +++ b/packages/actor-extract-links-quad-pattern-query/lib/ActorExtractLinksQuadPatternQuery.ts @@ -93,15 +93,21 @@ export class ActorExtractLinksQuadPatternQuery extends ActorExtractLinks { } // For the discovered quad term names, check extract the named nodes in the quad - for (const quadTermName of Object.keys(quadTermNames)) { + for (const quadTermName of Object.keys(quadTermNames)) { if (quad[quadTermName].termType === 'NamedNode') { - links.push({ url: quad[quadTermName].value }); + links.push({ + url: quad[quadTermName].value, + metadata: { producedByActor: { name: this.name, onlyVariables: this.onlyVariables }}, + }); } } } else { // --- If we want to follow links, irrespective of matching with a variable component --- for (const link of getNamedNodes(getTerms(quad))) { - links.push({ url: link.value }); + links.push({ + url: link.value, + metadata: { producedByActor: { name: this.name, onlyVariables: this.onlyVariables }}, + }); } } } diff --git a/packages/actor-extract-links-quad-pattern-query/test/ActorExtractLinksQuadPatternQuery-test.ts b/packages/actor-extract-links-quad-pattern-query/test/ActorExtractLinksQuadPatternQuery-test.ts index 1dc635b33..19fd9ef14 100644 --- a/packages/actor-extract-links-quad-pattern-query/test/ActorExtractLinksQuadPatternQuery-test.ts +++ b/packages/actor-extract-links-quad-pattern-query/test/ActorExtractLinksQuadPatternQuery-test.ts @@ -27,9 +27,9 @@ describe('ActorExtractLinksQuadPatternQuery', () => { }); it('should be a ActorExtractLinksQuadPatternQuery constructor', () => { - expect(new ( ActorExtractLinksQuadPatternQuery)({ name: 'actor', bus })) + expect(new (ActorExtractLinksQuadPatternQuery)({ name: 'actor', bus })) .toBeInstanceOf(ActorExtractLinksQuadPatternQuery); - expect(new ( ActorExtractLinksQuadPatternQuery)({ name: 'actor', bus })) + expect(new (ActorExtractLinksQuadPatternQuery)({ name: 'actor', bus })) .toBeInstanceOf(ActorExtractLinks); }); @@ -87,7 +87,9 @@ describe('ActorExtractLinksQuadPatternQuery', () => { { url: 'ex:p' }, { url: 'ex:o4' }, { url: 'ex:g' }, - ], + ].map((link) => { + return { ...link, metadata: { producedByActor: { name: actor.name, onlyVariables: false }}}; + }), }); }); @@ -119,7 +121,9 @@ describe('ActorExtractLinksQuadPatternQuery', () => { { url: 'ex:s2' }, { url: 'ex:p' }, { url: 'ex:g' }, - ], + ].map((link) => { + return { ...link, metadata: { producedByActor: { name: actor.name, onlyVariables: false }}}; + }), }); }); @@ -146,7 +150,9 @@ describe('ActorExtractLinksQuadPatternQuery', () => { { url: 'ex:p' }, { url: 'ex:o4' }, { url: 'ex:g' }, - ], + ].map((link) => { + return { ...link, metadata: { producedByActor: { name: actor.name, onlyVariables: false }}}; + }), }); }); @@ -168,7 +174,9 @@ describe('ActorExtractLinksQuadPatternQuery', () => { { url: 'ex:p' }, { url: 'ex:o4' }, { url: 'ex:g' }, - ], + ].map((link) => { + return { ...link, metadata: { producedByActor: { name: actor.name, onlyVariables: false }}}; + }), }); }); @@ -194,7 +202,9 @@ describe('ActorExtractLinksQuadPatternQuery', () => { { url: 'ex:p' }, { url: 'ex:o4' }, { url: 'ex:g' }, - ], + ].map((link) => { + return { ...link, metadata: { producedByActor: { name: actor.name, onlyVariables: false }}}; + }), }); }); }); @@ -263,7 +273,7 @@ describe('ActorExtractLinksQuadPatternQuery', () => { await expect(actor.run({ url: '', metadata: input, requestTime: 0, context })).resolves .toEqual({ links: [ - { url: 'ex:o6' }, + { url: 'ex:o6', metadata: { producedByActor: { name: actor.name, onlyVariables: true }}}, ], }); }); diff --git a/packages/actor-extract-links-quad-pattern/lib/ActorExtractLinksQuadPattern.ts b/packages/actor-extract-links-quad-pattern/lib/ActorExtractLinksQuadPattern.ts index c8ec06c81..280c656ad 100644 --- a/packages/actor-extract-links-quad-pattern/lib/ActorExtractLinksQuadPattern.ts +++ b/packages/actor-extract-links-quad-pattern/lib/ActorExtractLinksQuadPattern.ts @@ -42,7 +42,10 @@ export class ActorExtractLinksQuadPattern extends ActorExtractLinks { if (matchPatternComplete(quad, quadPattern)) { for (const quadTermName of filterQuadTermNames(quadPattern, value => value.termType === 'Variable')) { if (quad[quadTermName].termType === 'NamedNode') { - links.push({ url: quad[quadTermName].value }); + links.push({ + url: quad[quadTermName].value, + metadata: { producedByActor: { name: this.name, onlyVariables: true }}, + }); } } } @@ -51,7 +54,10 @@ export class ActorExtractLinksQuadPattern extends ActorExtractLinks { // eslint-disable-next-line no-lonely-if if (matchPatternComplete(quad, quadPattern)) { for (const link of getNamedNodes(getTerms(quad))) { - links.push({ url: link.value }); + links.push({ + url: link.value, + metadata: { producedByActor: { name: this.name, onlyVariables: false }}, + }); } } } diff --git a/packages/actor-extract-links-quad-pattern/test/ActorExtractLinksQuadPattern-test.ts b/packages/actor-extract-links-quad-pattern/test/ActorExtractLinksQuadPattern-test.ts index 102d6b275..70491516a 100644 --- a/packages/actor-extract-links-quad-pattern/test/ActorExtractLinksQuadPattern-test.ts +++ b/packages/actor-extract-links-quad-pattern/test/ActorExtractLinksQuadPattern-test.ts @@ -25,15 +25,15 @@ describe('ActorExtractLinksQuadPattern', () => { }); it('should be a ActorExtractLinksQuadPattern constructor', () => { - expect(new ( ActorExtractLinksQuadPattern)({ name: 'actor', bus })) + expect(new (ActorExtractLinksQuadPattern)({ name: 'actor', bus })) .toBeInstanceOf(ActorExtractLinksQuadPattern); - expect(new ( ActorExtractLinksQuadPattern)({ name: 'actor', bus })) + expect(new (ActorExtractLinksQuadPattern)({ name: 'actor', bus })) .toBeInstanceOf(ActorExtractLinks); }); it('should not be able to create new ActorExtractLinksQuadPattern objects without \'new\'', () => { expect(() => { - ( ActorExtractLinksQuadPattern)(); + (ActorExtractLinksQuadPattern)(); }).toThrow(`Class constructor ActorExtractLinksQuadPattern cannot be invoked without 'new'`); }); }); @@ -89,7 +89,9 @@ describe('ActorExtractLinksQuadPattern', () => { { url: 'ex:p' }, { url: 'ex:o4' }, { url: 'ex:g' }, - ], + ].map((link) => { + return { ...link, metadata: { producedByActor: { name: actor.name, onlyVariables: false }}}; + }), }); }); }); @@ -125,7 +127,9 @@ describe('ActorExtractLinksQuadPattern', () => { { url: 'ex:s2' }, { url: 'ex:s4' }, { url: 'ex:o4' }, - ], + ].map((link) => { + return { ...link, metadata: { producedByActor: { name: actor.name, onlyVariables: true }}}; + }), }); }); }); diff --git a/packages/actor-extract-links-solid-type-index/lib/ActorExtractLinksSolidTypeIndex.ts b/packages/actor-extract-links-solid-type-index/lib/ActorExtractLinksSolidTypeIndex.ts index 6d53a1fbc..c9d5504b0 100644 --- a/packages/actor-extract-links-solid-type-index/lib/ActorExtractLinksSolidTypeIndex.ts +++ b/packages/actor-extract-links-solid-type-index/lib/ActorExtractLinksSolidTypeIndex.ts @@ -142,7 +142,12 @@ export class ActorExtractLinksSolidTypeIndex extends ActorExtractLinks { if (!typeLinks[type]) { typeLinks[type] = []; } - typeLinks[type].push({ url: bindings.get('instance')!.value }); + typeLinks[type].push({ + url: bindings.get('instance')!.value, + metadata: { + producedByActor: { name: this.name, onlyMatchingTypes: this.onlyMatchingTypes, inference: this.inference }, + }, + }); } return typeLinks; } diff --git a/packages/actor-extract-links-solid-type-index/test/ActorExtractLinksSolidTypeIndex-test.ts b/packages/actor-extract-links-solid-type-index/test/ActorExtractLinksSolidTypeIndex-test.ts index 56a33dc46..7fb5910ae 100644 --- a/packages/actor-extract-links-solid-type-index/test/ActorExtractLinksSolidTypeIndex-test.ts +++ b/packages/actor-extract-links-solid-type-index/test/ActorExtractLinksSolidTypeIndex-test.ts @@ -25,12 +25,12 @@ describe('ActorExtractLinksSolidTypeIndex', () => { beforeEach(() => { bus = new Bus({ name: 'bus' }); - mediatorDereferenceRdf = { + mediatorDereferenceRdf = { mediate: jest.fn(async() => ({ data: new ArrayIterator([], { autoStart: false }), })), }; - actorInitQuery = {}; + actorInitQuery = {}; input = stream([]); context = new ActionContext({ [KeysInitQuery.query.name]: AF.createBgp([ @@ -65,7 +65,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { actorInitQuery, inference: false, }); - ( actor).queryEngine = { + (actor).queryEngine = { queryBindings: jest.fn(async() => ({ toArray: async() => [ BF.fromRecord({ instance: DF.namedNode('ex:file1'), class: DF.namedNode('ex:class1') }), @@ -77,12 +77,12 @@ describe('ActorExtractLinksSolidTypeIndex', () => { describe('test', () => { it('should reject for an empty context', async() => { - await expect(actor.test( { context: new ActionContext() })).rejects + await expect(actor.test({ context: new ActionContext() })).rejects .toThrow('Actor actor can only work in the context of a query.'); }); it('should reject for a context without query operation', async() => { - await expect(actor.test( { + await expect(actor.test({ context: new ActionContext({ [KeysInitQuery.query.name]: {}, }), @@ -90,7 +90,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { }); it('should reject for a context without query', async() => { - await expect(actor.test( { + await expect(actor.test({ context: new ActionContext({ [KeysQueryOperation.operation.name]: {}, }), @@ -98,7 +98,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { }); it('should be true for a valid context', async() => { - await expect(actor.test( { context })).resolves.toBeTruthy(); + await expect(actor.test({ context })).resolves.toBeTruthy(); }); }); @@ -146,7 +146,12 @@ describe('ActorExtractLinksSolidTypeIndex', () => { { url: 'ex:file2', }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, onlyMatchingTypes: false, inference: false }}, + }; + }), }); expect(mediatorDereferenceRdf.mediate).toHaveBeenCalledTimes(2); @@ -171,7 +176,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { mediatorDereferenceRdf, actorInitQuery, }); - ( actor).queryEngine = { + (actor).queryEngine = { queryBindings: jest.fn(async() => ({ toArray: async() => [ BF.fromRecord({ instance: DF.namedNode('ex:file1'), class: DF.namedNode('ex:class1') }), @@ -202,7 +207,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { quad('ex:s4', 'ex:p', 'ex:o4', 'ex:g'), quad('ex:s5', 'ex:p', 'ex:o5', 'ex:gx'), ]); - ( actor).queryEngine.queryBindings = (query: string) => { + (actor).queryEngine.queryBindings = (query: string) => { if (query.includes('solid:TypeRegistration')) { return { toArray: async() => [ @@ -212,7 +217,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { }; } return { - toArray: async() => [ ], + toArray: async() => [], }; }; await expect(actor.run({ url: '', metadata: input, requestTime: 0, context })).resolves @@ -220,6 +225,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { links: [ { url: 'ex:file1', + metadata: { producedByActor: { name: actor.name, onlyMatchingTypes: true, inference: true }}, }, ], }); @@ -235,7 +241,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { quad('ex:s4', 'ex:p', 'ex:o4', 'ex:g'), quad('ex:s5', 'ex:p', 'ex:o5', 'ex:gx'), ]); - ( actor).queryEngine.queryBindings = (query: string) => { + (actor).queryEngine.queryBindings = (query: string) => { if (query.includes('solid:TypeRegistration')) { return { toArray: async() => [ @@ -245,7 +251,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { }; } return { - toArray: async() => [ ], + toArray: async() => [], }; }; @@ -280,7 +286,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { quad('ex:s4', 'ex:p', 'ex:o4', 'ex:g'), quad('ex:s5', 'ex:p', 'ex:o5', 'ex:gx'), ]); - ( actor).queryEngine.queryBindings = (query: string) => { + (actor).queryEngine.queryBindings = (query: string) => { if (query.includes('solid:TypeRegistration')) { return { toArray: async() => [ @@ -290,7 +296,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { }; } return { - toArray: async() => [ ], + toArray: async() => [], }; }; context = new ActionContext({ @@ -319,7 +325,12 @@ describe('ActorExtractLinksSolidTypeIndex', () => { { url: 'ex:file2', }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, onlyMatchingTypes: true, inference: true }}, + }; + }), }); expect(mediatorDereferenceRdf.mediate).toHaveBeenCalledTimes(1); @@ -350,6 +361,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { links: [ { url: 'ex:file1', + metadata: { producedByActor: { name: actor.name, onlyMatchingTypes: true, inference: true }}, }, ], }); @@ -365,7 +377,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { quad('ex:s4', 'ex:p', 'ex:o4', 'ex:g'), quad('ex:s5', 'ex:p', 'ex:o5', 'ex:gx'), ]); - ( actor).queryEngine.queryBindings = (query: string) => { + (actor).queryEngine.queryBindings = (query: string) => { if (query.includes('solid:TypeRegistration')) { return { toArray: async() => [ @@ -398,6 +410,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { links: [ { url: 'ex:file2', + metadata: { producedByActor: { name: actor.name, onlyMatchingTypes: true, inference: true }}, }, ], }); @@ -412,7 +425,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { quad('ex:s4', 'ex:p', 'ex:o4', 'ex:g'), quad('ex:s5', 'ex:p', 'ex:o5', 'ex:gx'), ]); - ( actor).queryEngine.queryBindings = (query: string) => { + (actor).queryEngine.queryBindings = (query: string) => { if (query.includes('solid:TypeRegistration')) { return { toArray: async() => [ @@ -453,7 +466,12 @@ describe('ActorExtractLinksSolidTypeIndex', () => { { url: 'ex:file2', }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, onlyMatchingTypes: true, inference: true }}, + }; + }), }); expect(mediatorDereferenceRdf.mediate).toHaveBeenCalledTimes(1); expect(mediatorDereferenceRdf.mediate).toHaveBeenCalledWith({ url: 'ex:index1', context }); @@ -466,7 +484,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { quad('ex:s4', 'ex:p', 'ex:o4', 'ex:g'), quad('ex:s5', 'ex:p', 'ex:o5', 'ex:gx'), ]); - ( actor).queryEngine.queryBindings = (query: string) => { + (actor).queryEngine.queryBindings = (query: string) => { if (query.includes('solid:TypeRegistration')) { return { toArray: async() => [ @@ -503,7 +521,12 @@ describe('ActorExtractLinksSolidTypeIndex', () => { { url: 'ex:file1', }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, onlyMatchingTypes: true, inference: true }}, + }; + }), }); expect(mediatorDereferenceRdf.mediate).toHaveBeenCalledTimes(1); expect(mediatorDereferenceRdf.mediate).toHaveBeenCalledWith({ url: 'ex:index1', context }); @@ -516,7 +539,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { quad('ex:s4', 'ex:p', 'ex:o4', 'ex:g'), quad('ex:s5', 'ex:p', 'ex:o5', 'ex:gx'), ]); - ( actor).queryEngine.queryBindings = (query: string) => { + (actor).queryEngine.queryBindings = (query: string) => { if (query.includes('solid:TypeRegistration')) { return { toArray: async() => [ @@ -552,6 +575,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { links: [ { url: 'ex:file1', + metadata: { producedByActor: { name: actor.name, onlyMatchingTypes: true, inference: true }}, }, ], }); @@ -577,7 +601,7 @@ describe('ActorExtractLinksSolidTypeIndex', () => { mediatorDereferenceRdf, actorInitQuery, }); - ( actor).queryEngine = { + (actor).queryEngine = { queryBindings: jest.fn(async() => ({ toArray: async() => [ BF.fromRecord({ instance: DF.namedNode('ex:file1'), class: DF.namedNode('ex:class1') }), @@ -615,7 +639,12 @@ describe('ActorExtractLinksSolidTypeIndex', () => { { url: 'ex:file2', }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, onlyMatchingTypes: true, inference: false }}, + }; + }), }); expect(mediatorDereferenceRdf.mediate).toHaveBeenCalledTimes(1); expect(mediatorDereferenceRdf.mediate).toHaveBeenCalledWith({ url: 'ex:index1', context }); @@ -648,7 +677,12 @@ describe('ActorExtractLinksSolidTypeIndex', () => { { url: 'ex:file2', }, - ], + ].map((link) => { + return { + ...link, + metadata: { producedByActor: { name: actor.name, onlyMatchingTypes: true, inference: false }}, + }; + }), }); expect(mediatorDereferenceRdf.mediate).toHaveBeenCalledTimes(1); expect(mediatorDereferenceRdf.mediate).toHaveBeenCalledWith({ url: 'ex:index1', context });