@comunica/actor-abstract-path 2.3.1-alpha.28.0 → 2.3.1-alpha.29.0

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.
@@ -24,17 +24,17 @@ export declare abstract class ActorAbstractPath extends ActorQueryOperationTyped
24
24
  }>;
25
25
  private predicateStarGraphVariable;
26
26
  /**
27
- * Returns an iterator with Bindings of the query subject predicate* ?o
28
- * If graph is a variable, it will also be in those bindings
29
- * @param {Term} subject Term of where we start the predicate* search.
30
- * @param {Variable} object Variable of the zeroOrMore-query.
31
- * @param {Term} objectVal
32
- * @param {Algebra.PropertyPathSymbol} predicate Predicate of the *-path.
33
- * @param {Term} graph The graph in which we search for the pattern. (Possibly a variable)
34
- * @param {ActionContext} context
35
- * @return {Promise<AsyncIterator<Bindings>} Iterator to where all bindings of query should have been pushed.
36
- */
37
- getObjectsPredicateStarEval(subject: RDF.Term, object: RDF.Variable, predicate: Algebra.PropertyPathSymbol, graph: RDF.Term, context: IActionContext): Promise<IPathResultStream>;
27
+ * Returns an iterator with Bindings of the query subject predicate* ?o or subject predicate+ ?o
28
+ * If graph is a variable, it will also be in those bindings
29
+ * @param {Term} subject Term of where we start the predicate* search.
30
+ * @param {Algebra.PropertyPathSymbol} predicate Predicate of the *-path.
31
+ * @param {Variable} object Variable of the zeroOrMore-query.
32
+ * @param {Term} graph The graph in which we search for the pattern. (Possibly a variable)
33
+ * @param {ActionContext} context The context to pass to sub-opertations
34
+ * @param emitFirstSubject If the path operation is predicate*, otherwise it is predicate+.
35
+ * @return {Promise<AsyncIterator<Bindings>} Iterator to where all bindings of query should have been pushed.
36
+ */
37
+ getObjectsPredicateStarEval(subject: RDF.Term, predicate: Algebra.PropertyPathSymbol, object: RDF.Variable, graph: RDF.Term, context: IActionContext, emitFirstSubject: boolean): Promise<IPathResultStream>;
38
38
  /**
39
39
  * Pushes all terms to iterator `it` that are a solution of object predicate* ?o.
40
40
  * @param {Term} object Term of where we start the predicate* search.
@@ -8,6 +8,7 @@ const asynciterator_1 = require("asynciterator");
8
8
  const rdf_data_factory_1 = require("rdf-data-factory");
9
9
  const rdf_string_1 = require("rdf-string");
10
10
  const sparqlalgebrajs_1 = require("sparqlalgebrajs");
11
+ const PathVariableObjectIterator_1 = require("./PathVariableObjectIterator");
11
12
  const DF = new rdf_data_factory_1.DataFactory();
12
13
  const BF = new bindings_factory_1.BindingsFactory();
13
14
  /**
@@ -53,8 +54,10 @@ class ActorAbstractPath extends bus_query_operation_1.ActorQueryOperationTypedMe
53
54
  return { context, operation: undefined };
54
55
  }
55
56
  async predicateStarGraphVariable(subject, object, predicate, graph, context) {
57
+ // TODO: refactor this with an iterator just like PathVariableObjectIterator so we handle backpressure correctly
56
58
  // Construct path to obtain all graphs where subject exists
57
- const predVar = this.generateVariable(ActorAbstractPath.FACTORY.createPath(subject, predicate, object, graph));
59
+ const predVar = this.generateVariable(ActorAbstractPath.FACTORY
60
+ .createPath(subject, predicate, object, graph));
58
61
  const findGraphs = ActorAbstractPath.FACTORY.createUnion([
59
62
  ActorAbstractPath.FACTORY.createPattern(subject, predVar, object, graph),
60
63
  ActorAbstractPath.FACTORY.createPattern(object, predVar, subject, graph),
@@ -91,26 +94,23 @@ class ActorAbstractPath extends bus_query_operation_1.ActorQueryOperationTypedMe
91
94
  };
92
95
  }
93
96
  /**
94
- * Returns an iterator with Bindings of the query subject predicate* ?o
95
- * If graph is a variable, it will also be in those bindings
96
- * @param {Term} subject Term of where we start the predicate* search.
97
- * @param {Variable} object Variable of the zeroOrMore-query.
98
- * @param {Term} objectVal
99
- * @param {Algebra.PropertyPathSymbol} predicate Predicate of the *-path.
100
- * @param {Term} graph The graph in which we search for the pattern. (Possibly a variable)
101
- * @param {ActionContext} context
102
- * @return {Promise<AsyncIterator<Bindings>} Iterator to where all bindings of query should have been pushed.
103
- */
104
- async getObjectsPredicateStarEval(subject, object, predicate, graph, context) {
97
+ * Returns an iterator with Bindings of the query subject predicate* ?o or subject predicate+ ?o
98
+ * If graph is a variable, it will also be in those bindings
99
+ * @param {Term} subject Term of where we start the predicate* search.
100
+ * @param {Algebra.PropertyPathSymbol} predicate Predicate of the *-path.
101
+ * @param {Variable} object Variable of the zeroOrMore-query.
102
+ * @param {Term} graph The graph in which we search for the pattern. (Possibly a variable)
103
+ * @param {ActionContext} context The context to pass to sub-opertations
104
+ * @param emitFirstSubject If the path operation is predicate*, otherwise it is predicate+.
105
+ * @return {Promise<AsyncIterator<Bindings>} Iterator to where all bindings of query should have been pushed.
106
+ */
107
+ async getObjectsPredicateStarEval(subject, predicate, object, graph, context, emitFirstSubject) {
105
108
  if (graph.termType === 'Variable') {
106
109
  return this.predicateStarGraphVariable(subject, object, predicate, graph, context);
107
110
  }
108
- const it = new asynciterator_1.BufferedIterator();
109
- // We can safely ignore undefs because termHashes is empty
110
- // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
111
- const metadata = await this
112
- .getObjectsPredicateStar(subject, predicate, graph, context, {}, it, { count: 0 });
111
+ const it = new PathVariableObjectIterator_1.PathVariableObjectIterator(subject, predicate, graph, context, this.mediatorQueryOperation, emitFirstSubject);
113
112
  const bindingsStream = it.transform({
113
+ autoStart: false,
114
114
  transform(item, next, push) {
115
115
  push(BF.bindings([[object, item]]));
116
116
  next();
@@ -118,7 +118,7 @@ class ActorAbstractPath extends bus_query_operation_1.ActorQueryOperationTypedMe
118
118
  });
119
119
  return {
120
120
  bindingsStream,
121
- metadata,
121
+ metadata: () => new Promise(resolve => it.getProperty('metadata', (metadata) => resolve(metadata()))),
122
122
  };
123
123
  }
124
124
  /**
@@ -0,0 +1,24 @@
1
+ import type { MediatorQueryOperation } from '@comunica/bus-query-operation';
2
+ import type { IActionContext } from '@comunica/types';
3
+ import type * as RDF from '@rdfjs/types';
4
+ import { BufferedIterator } from 'asynciterator';
5
+ import type { Algebra } from 'sparqlalgebrajs';
6
+ /**
7
+ * An iterator that implements the multi-length property path operation (* and +)
8
+ * for a fixed subject and predicate, and a variable object.
9
+ */
10
+ export declare class PathVariableObjectIterator extends BufferedIterator<RDF.Term> {
11
+ private readonly subject;
12
+ private readonly predicate;
13
+ private readonly graph;
14
+ private readonly context;
15
+ private readonly mediatorQueryOperation;
16
+ private readonly maxRunningOperations;
17
+ private readonly termHashes;
18
+ private readonly runningOperations;
19
+ private readonly pendingOperations;
20
+ constructor(subject: RDF.Term, predicate: Algebra.PropertyPathSymbol, graph: RDF.Term, context: IActionContext, mediatorQueryOperation: MediatorQueryOperation, emitFirstSubject: boolean, maxRunningOperations?: number);
21
+ protected _end(destroy?: boolean): void;
22
+ protected _push(item: RDF.Term, pushAsResult?: boolean): void;
23
+ protected _read(count: number, done: () => void): void;
24
+ }
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PathVariableObjectIterator = void 0;
4
+ const bus_query_operation_1 = require("@comunica/bus-query-operation");
5
+ const asynciterator_1 = require("asynciterator");
6
+ const rdf_data_factory_1 = require("rdf-data-factory");
7
+ const rdf_string_1 = require("rdf-string");
8
+ const sparqlalgebrajs_1 = require("sparqlalgebrajs");
9
+ const DF = new rdf_data_factory_1.DataFactory();
10
+ const FACTORY = new sparqlalgebrajs_1.Factory();
11
+ /**
12
+ * An iterator that implements the multi-length property path operation (* and +)
13
+ * for a fixed subject and predicate, and a variable object.
14
+ */
15
+ class PathVariableObjectIterator extends asynciterator_1.BufferedIterator {
16
+ constructor(subject, predicate, graph, context, mediatorQueryOperation, emitFirstSubject, maxRunningOperations = 16) {
17
+ // The autoStart flag must be true to kickstart metadata collection
18
+ super({ autoStart: true });
19
+ this.subject = subject;
20
+ this.predicate = predicate;
21
+ this.graph = graph;
22
+ this.context = context;
23
+ this.mediatorQueryOperation = mediatorQueryOperation;
24
+ this.maxRunningOperations = maxRunningOperations;
25
+ this.termHashes = new Map();
26
+ this.runningOperations = [];
27
+ this.pendingOperations = [];
28
+ // Push the subject as starting point
29
+ this._push(this.subject, emitFirstSubject);
30
+ }
31
+ _end(destroy) {
32
+ // Close all running iterators
33
+ for (const it of this.runningOperations) {
34
+ it.destroy();
35
+ }
36
+ super._end(destroy);
37
+ }
38
+ _push(item, pushAsResult = true) {
39
+ let termString;
40
+ if (pushAsResult) {
41
+ // Don't push if this subject was already found
42
+ termString = (0, rdf_string_1.termToString)(item);
43
+ if (this.termHashes.has(termString)) {
44
+ return;
45
+ }
46
+ }
47
+ // Add a pending path operation for this item
48
+ const variable = DF.variable('b');
49
+ this.pendingOperations.push({
50
+ variable,
51
+ operation: FACTORY.createPath(item, this.predicate, variable, this.graph),
52
+ });
53
+ // Otherwise, push the subject
54
+ if (termString) {
55
+ this.termHashes.set(termString, item);
56
+ super._push(item);
57
+ }
58
+ }
59
+ _read(count, done) {
60
+ // eslint-disable-next-line @typescript-eslint/no-this-alias,consistent-this
61
+ const self = this;
62
+ (async function () {
63
+ // Open as many operations as possible
64
+ while (self.runningOperations.length < self.maxRunningOperations) {
65
+ if (self.pendingOperations.length === 0) {
66
+ break;
67
+ }
68
+ const pendingOperation = self.pendingOperations.pop();
69
+ const results = bus_query_operation_1.ActorQueryOperation.getSafeBindings(await self.mediatorQueryOperation.mediate({ operation: pendingOperation.operation, context: self.context }));
70
+ const runningOperation = results.bindingsStream.transform({
71
+ autoStart: false,
72
+ transform(bindings, next, push) {
73
+ const newTerm = bindings.get(pendingOperation.variable);
74
+ push(newTerm);
75
+ next();
76
+ },
77
+ });
78
+ if (!runningOperation.done) {
79
+ self.runningOperations.push(runningOperation);
80
+ runningOperation.on('error', error => self.destroy(error));
81
+ runningOperation.on('readable', () => {
82
+ self.readable = true;
83
+ self._fillBufferAsync();
84
+ });
85
+ runningOperation.on('end', () => {
86
+ self.runningOperations.splice(self.runningOperations.indexOf(runningOperation), 1);
87
+ self.readable = true;
88
+ self._fillBufferAsync();
89
+ });
90
+ }
91
+ self.setProperty('metadata', results.metadata);
92
+ }
93
+ // Try to read `count` items (based on UnionIterator)
94
+ let lastCount = 0;
95
+ let item;
96
+ // eslint-disable-next-line no-cond-assign
97
+ while (lastCount !== (lastCount = count)) {
98
+ // Prioritize the operations that have been added first
99
+ for (let i = 0; i < self.runningOperations.length && count > 0; i++) {
100
+ // eslint-disable-next-line no-cond-assign
101
+ if ((item = self.runningOperations[i].read()) !== null) {
102
+ count--;
103
+ self._push(item);
104
+ }
105
+ }
106
+ }
107
+ // Close if everything has been read
108
+ if (self.runningOperations.length === 0 && self.pendingOperations.length === 0) {
109
+ self.close();
110
+ }
111
+ })().then(() => {
112
+ done();
113
+ }, error => this.destroy(error));
114
+ }
115
+ }
116
+ exports.PathVariableObjectIterator = PathVariableObjectIterator;
117
+ //# sourceMappingURL=PathVariableObjectIterator.js.map
package/lib/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from './ActorAbstractPath';
2
+ export * from './PathVariableObjectIterator';
package/lib/index.js CHANGED
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./ActorAbstractPath"), exports);
18
+ __exportStar(require("./PathVariableObjectIterator"), exports);
18
19
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comunica/actor-abstract-path",
3
- "version": "2.3.1-alpha.28.0",
3
+ "version": "2.3.1-alpha.29.0",
4
4
  "description": "An abstract actor for handling mediatypes",
5
5
  "lsd:module": true,
6
6
  "main": "lib/index.js",
@@ -31,11 +31,11 @@
31
31
  "lib/**/*.js"
32
32
  ],
33
33
  "dependencies": {
34
- "@comunica/bindings-factory": "2.3.1-alpha.28.0",
35
- "@comunica/bus-query-operation": "2.3.1-alpha.28.0",
36
- "@comunica/context-entries": "2.3.1-alpha.28.0",
37
- "@comunica/core": "2.3.1-alpha.28.0",
38
- "@comunica/types": "2.3.1-alpha.28.0",
34
+ "@comunica/bindings-factory": "2.3.1-alpha.29.0",
35
+ "@comunica/bus-query-operation": "2.3.1-alpha.29.0",
36
+ "@comunica/context-entries": "2.3.1-alpha.29.0",
37
+ "@comunica/core": "2.3.1-alpha.29.0",
38
+ "@comunica/types": "2.3.1-alpha.29.0",
39
39
  "@rdfjs/types": "*",
40
40
  "asynciterator": "^3.4.2",
41
41
  "rdf-data-factory": "^1.0.3",
@@ -47,5 +47,5 @@
47
47
  "build:ts": "node \"../../node_modules/typescript/bin/tsc\"",
48
48
  "build:components": "componentsjs-generator"
49
49
  },
50
- "gitHead": "a6b2907780c1607eceb10e7f12ef6978f79e4aba"
50
+ "gitHead": "0ad833f8f32f7e3c2de1b22a0424da027656bf6a"
51
51
  }