Usage

Installation

OCL.js is entirely written in JavaScript and served either via npm or GitHub. It is designed to run either in a node environment or in the browser.

To add OCL.js to your project install it via npm as follows and you are good to go:

$ npm install @stekoe/ocl.js --save

As alternative, you can also download the ocl.min.js file from GitHub and include that to your code.

Import Library

When adding OCL.js via npm, you can start using it via importing the OCLEngine that is provided by “@stekoe/ocl.js”.

import OCLEngine from "@stekoe/ocl.js"
// Or of you prefer require:
// const OCLEngine = require('@stekoe/ocl.js');

const myOclExpression = `
    context Person
        inv: self.parents->forAll(p | p <> self)
`;

// Instantiate the OclEngine here
const oclEngine = new OclEngine()

// Add your first OCL expression here
oclEngine.addOclExpression(myOclExpression)

// Evaluate an object obj against all know OCL expressions
oclEngine.evaluate(obj)

Provide own typeDeterminer

When the discriminator for an object type is part of the given instance (e.g. a field called type) then it is possible to pass in a custom function which determines the actual type.

Let’s say you have a type as follows and you want to use the field _type as discriminator:

class MyCustomType {
    constructor(type) {
        this._type = type;
    }
}

Then you can pass in a callback into the setTypeDeterminer function to override the default behavior:

import OCLEngine from "@stekoe/ocl.js"

const oclEngine = new OclEngine();
oclEngine.setTypeDeterminer(obj => return obj._type);

const person = new MyCustomType('Person');
oclEngine.evaluate(person);

Now the the OCLEngine will apply all implemented constraints having context Person on the given person instance.

Query objects

Instead of just evaluating objects, it is also possible to use the OCL.js to query object properties. Querying object properties works very much like the same way as defining constraints but without having the need to define context and invariant. To illustrate how querying works, let’s assume we have to classes Job and Person defined as follows:

class Job {
    salary: number;
}

class Person {
    age: any;
    jobs: Array<Job> = [];
    parents: Array<Person> = [];

    constructor(age = 21) {
        super();
        this.age = age;
    }
}

If one now wants to have a sum of all jobs’ sallaries, we can define a OCL query to reqlise that:

const person = new Person();
person.jobs.push(new Job(17000));
person.jobs.push(new Job(18000));
person.jobs.push(new Job(4000));

let query = oclEngine.createQuery('self.jobs.salary->sum()');
let result = oclEngine.evaluateQuery(person, query);
console.log(result); // will return 39000