Closed pmeijer closed 6 years ago
It looks like ocl.js
is not matching the context (class named Person
) against any of the objects you evaluated. You should take a look at setTypeDeterminer and make sure that your objects type can be determined.
oclEngine.setTypeDeterminer((obj: any) => {
// name of the class is type name
return obj.constructor.name;
});
Additionally your OCL invariant is structured incorrectly. Given your objects, it should look more like this:
const dadIsMale = `
-- Check that dad is indeed a male
context Person
inv: (not self.pointers.dad.oclIsUndefined()) implies self.pointers.dad.attributes.isMale = true
`;
Hey y'all! Thanks for the question and @JDziurlaj thanks for helping out! I have read your email but have not found the time to answer, yet, but your help is very much appreciated!
@pmeijer As @JDziurlaj already mentioned, you have to define a custom typeDeterminer
function that will take any object as parameter which is passed into the .evaluate
function. I assume that the field type
is the discriminator in your example, hence a corresponding function for your use case should look like and work as follows:
oclEngine.setTypeDeterminer((obj: any) => {
return obj.type; // ob.type will contain 'Person' or 'Family'
});
Hope we were able to help you a little bit and I promise to optimize the API documentation as soon as possible!
I have extended the documentation regarding this feature: http://ocl.stekoe.de/usage.html#provide-own-typedeterminer
Thank you both for your replies. The documentation is thorough in regards to supported OCL expressions - which is great since I'm new to OCL. However it would be really good to generate jsdoc documentation for the OclEngine amd OclResult.
Changing the invariant still leads to issues with dad though. Technically dad.pointers.dad
is null and not undefined.
const dadIsMale = `
-- Check that dad is indeed a male
context Person
inv: (not self.pointers.dad.oclIsUndefined()) implies self.pointers.dad.attributes.isMale = true
`;
oclEngine.addOclExpression(dadIsMale);
let res = oclEngine.evaluate(aFamily);
console.log(res.getResult()); // true, since the Family Context itself is fine
res = oclEngine.evaluate(son);
console.log(res.getResult()); // true
res = oclEngine.evaluate(dad);
console.log(res.getResult()); // true, dad doesn't define a dad (but returns false)
res = oclEngine.evaluate(derp);
console.log(res.getResult()); // false, derps dad is Jen
I'm not sure what self.pointers.dad.bogus()
is, but I'm assuming that the expression is being evaluated as false
or undefined
, and the not
is causing it to become true and evaluate the implication.
Changing to const Person = new OCLObject('Person', {name: 'Person', isMale: true}, {dad: undefined, mom: undefined}, {});
works.
You're right I sloppily forgot the not was added.
@pmeijer I have added two issues which should remind me to add more API documentation. Shame on me for not having done that yet.
@pmeijer I have added two issues which should remind me to add more API documentation. Shame on me for not having done that yet.
Hi @SteKoe ,
I am new to OCL.
evaluatedContexts
Array is always empty in my example.
What is wrong in the code?
https://codesandbox.io/s/rule-engine-ocl-js-z38c2?file=/src/App.js
It's not clear to me how to use the API of this project. Specifically I'm having problems of building up the "instance" models to be checked. I'm very interested in integrating OCL into a metamodeling framework, but after playing around with the ocl.js I can't get it to work. I've included a snippet, any pointers are welcome. (I'm using the structure below since I'm intending to generate the models to be evaluated on the fly based on the models in our framework.)