Ghent University – imec – IDLab, Belgium
The easiest way to add components is by manually adding instances.
const myCar = new Car(); myCar.add(new EngineV8()); myCar.add(new TireMichelin()); myCar.add(new TireMichelin()); myCar.add(new TireMichelin()); myCar.add(new TireMichelin());
Downside: swapping components requires code changes.
Dependency Injection: Components are supplied by something external.
Components can be defined declaratively via a configuration file.
const myCar = CarFactory.instantiateCar('car-config.json');
car-config.json:
[ "EngineV8", "TireMichelin", "TireMichelin", "TireMichelin", "TireMichelin" ]
Components.js: A dependency injection framework for JavaScript
Components are described in a semantic configuration file
→ A semantic layer on top of your source code
→ Configuration files could also be used for other programming languages
Comunica uses Components.js to wire actors, buses and mediators
Module: Collection of components (e.g., a software package)
↓
Component: Something that can be instantiated (e.g., a class)
↓
Instance: An instantiated Component
Each module is published as a separate NPM package.
@comunica/actor-query-operation-distinct-hash
:ActorQueryOperationDistinctHash
@comunica/actor-query-operation-construct
:ActorQueryOperationConstruct
We use import
statements to refer to components in different files.
{ "@context": …, "@id": "npmd:@comunica/actor-query-operation-distinct-hash", "@type": "Module", "requireName": "@comunica/actor-query-operation-distinct-hash", "import": [ "files:components/Actor/QueryOperation/DistinctHash.jsonld", … ] }
{ … "components": [ { "@id": "Actor/QueryOperation/DistinctHash", "requireElement": "ActorQueryOperationDistinctHash", "parameters": [ { "@id": "hashAlgorithm", "default": "sha1" }, { "@id": "digestAlgorithm", "default": "base64" } } ] }
Components.js supports any kind of RDF serialization: Turtle, N-Triples, ...
For developers that are familiar with JSON
To achieve semantic RDF-based configurations:
Modules, components and instances have a unique URL.
Others can reuse them by simply linking to them → distributed config files
Fetch them from anywhere (browser, query engine, ...)
npmd:@comunica/actor-query-operation-distinct-hash
expands to https://linkedsoftwaredependencies.org/bundles/npm/%40comunica%2Factor-query-operation-distinct-hash/1.4.4/components/Actor/QueryOperation/DistinctHash.jsonld
@type
of an instance is a Component (IRI){ "@context": …, "@id": "urn:comunica:my", "actors": [ { "@id": "#myDistinctQueryOperator", "@type": "ActorQueryOperationDistinctHash", "hashAlgorithm": "RSA-SHA256" }, { "@id": "#myConstructQueryOperator", "@type": "ActorQueryOperationConstruct" }, … ] }
Goal: Implementing, configuring, and using a custom REDUCED
actor.
REDUCED
: A best-effort variant of SPARQL's DISTINCT
.
Example:
?var: 'B' ?var: 'A' ?var: 'A' ?var: 'B' ?var: 'B'
REDUCED
→?var: 'B' ?var: 'A' ?var: 'B'
REDUCED
implementation: Actual JavaScript implementation.
Each step can be skipped by checking out a different git tag
.
For example, show the solution of step 2: git checkout tutorial-step/2
$ git clone https://github.com/comunica/Tutorial-Comunica-Reduced-Actor $ cd Tutorial-Comunica-Reduced-Actor $ git checkout tutorial-step/1
Each step is explained in detail on GitHub wiki:
https://github.com/comunica/Tutorial-Comunica-Reduced-Actor