Checking an OCL constraint before actually setting the value [message #1129273] |
Tue, 08 October 2013 13:17 |
Thomas Steinbach Messages: 13 Registered: March 2013 |
Junior Member |
|
|
Hello,
is there a way to check an OCL constraint before you actually set the value?
Example: (or see the exported project as zip)
You have a class Person
- with the attribute age and
- a reference father to another person.
- Of course a father should be older than his child
in pseudo-code:
Person child = new Person(age=60)
Person father = new Person(age=50)
Constraint con = Person.getFatherIsOlderConstraint()
con.testIfWouldBeAccepted(child, father)
As far as I got with code to try checking at all:
(with help of http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.ocl.doc%2Fhelp%2FOCLInterpreterTutorial.html)
private void validateBeforeSet(Person p) throws ParserException {
OCL ocl = OCL.newInstance();
OCLHelper helper = ocl.createOCLHelper();
helper.setContext(SimplemodelPackage.Literals.PERSON);
Constraint invariant = (Constraint) helper.createInvariant("father.age < age");
Query invEval = ocl.createQuery(invariant);
invEval.getEvaluationEnvironment().add("father", p.getFather());
Object result = invEval.evaluate(p);
System.out.println(result);
}
But the result is always "invalid", even if I change the invariant to "father.age > age"
Eclipse:
Version: Kepler Release
Build id: 20130614-0229
OCL End User SDK 4.1.1.v20130916-1423
OCL Examples and Editors 3.3.1.v20130916-1423
Thank you for your time and help,
Tom
[Updated on: Tue, 08 October 2013 13:54] Report message to a moderator
|
|
|
Re: Checking an OCL constraint before actually setting the value [message #1129308 is a reply to message #1129273] |
Tue, 08 October 2013 13:59 |
Ed Willink Messages: 7670 Registered: July 2009 |
Senior Member |
|
|
Hi
If you want to test a hypothetical state, you will need to create that
hypothetical state. Possibly by creating a deep clone and then applying
your mutation.
A deep clone can be very expensive and may have unexpected side effects.
If your hypothesis is limited to a couple of features you could
re-implement getXXXX to conditionally return your hypothetical value.
If you want to have many changes, it may be possible to have your model
extend HypothesizedEObject in which you re-implement some part of the
eGet() flow; this could work withe the OCL interpreter but would fail
with the OCL to JHava Code Generator that generates duirect getXXX
rather that eGet(XXX) accesses.
Much the easiest would be to do the real change live and perhaps
roll-back, possibly with the help of EMFt, but I can see that in many
scenarios this might be unacceptable.
When I finally get round to implementing @pre for accurate postcondition
execution, the difficulties of maintaining a smart system copy for @pre
and maintaining a smart system copy for a hypothesis might not be so
very different, so please raise an enhancement Bugzilla. I'm afraid that
the response may be over a year away.
Regards
Ed Willink
On 08/10/2013 14:17, Thomas Steinbach wrote:
> Hello,
>
> is there a way to check an OCL constraint before you actually set the value?
>
> Example: (or see the exported project as zip)
> You have a class Person
> - with the attribute age and
> - a reference father to another person.
> - Of course a father should be older than his child
>
> in pseudo-code:
> Person child = new Person(age=60)
> Person father = new Person(age=50)
>
> Constraint con = Person.getFatherIsOlderConstraint()
> con.testIfWouldBeAccepted(child, father)
>
> As far as I got with code to try checking at all:
> private void validateBeforeSet(Person p) {
>
> OCL ocl = OCL.newInstance();
> OCLHelper helper = ocl.createOCLHelper();
> helper.setContext(SimplemodelPackage.Literals.PERSON);
>
>
> Constraint x = null;
> try {
> x = (Constraint) helper.createInvariant("father.age > age");
> } catch (ParserException e) {
> e.printStackTrace();
> }
>
> Object r = ocl.check(p, x);
> System.out.println(r);
> }
>
>
> Thank you for your time and help,
> Tom
|
|
|
|
|
how a newbie (mis)interpretes OCL [message #1129463 is a reply to message #1129374] |
Tue, 08 October 2013 16:52 |
Thomas Steinbach Messages: 13 Registered: March 2013 |
Junior Member |
|
|
maybe I misinterprete OCL, because the above solution would mean to have the condition twice, first in the constraint where needed and second in the operation you mentioned before, in order to check if setting the value would be allowed?
What I've expected is the following (in words, see my try with code below and the corresponding markers):
Quote:- The framework creates something out of the pure OCL-String "father.age > self.age",
maybe a generated class which contains the code representing the condition "father.age > self.age" (* Code 1)
- this "element" knows _how_ to determine if the result is true or not,
but just needs the two parameters father and self
- now I can provide several objects for the parameter father and ask this "condition"-element for its result (* Code 2)
Is the code below going in this direction, or did I misunderstand it at all?
OCL ocl = OCL.newInstance(EcoreEnvironmentFactory.INSTANCE);
OCLHelper helper = ocl.createOCLHelper();
helper.setContext(SimplemodelPackage.Literals.PERSON);
Constraint condition = (Constraint) helper.createInvariant("father.age < age"); <--- (* Code 1)
Query invEval = ocl.createQuery(invariant);
invEval.getEvaluationEnvironment().add("father", p.getFather()); <--- (*Code 2), bind the Condition element to the current father-parameter
Object b = invEval.evaluate(p); <--- evaluate if this father-element would match the condition
--> System.out.println(b); results in "invalid"
With best regards,
Tom
[Updated on: Tue, 08 October 2013 17:04] Report message to a moderator
|
|
|
Re: how a newbie (mis)interpretes OCL [message #1129477 is a reply to message #1129463] |
Tue, 08 October 2013 17:14 |
Ed Willink Messages: 7670 Registered: July 2009 |
Senior Member |
|
|
Hi
I cannot really follow your message beyond the complaint about duplication.
Operations are a common approach to support reuse.
You can provide an operation that performs the hypothetical validation
with custom parameters and code the invariant to invoke the same
operation with state values.
Regards
Ed Willink
On 08/10/2013 17:52, Thomas Steinbach wrote:
> maybe I misinterprete OCL, because the above solution would mean to
> have the condition twice, first in the constraint where needed and
> second in the operation you mentioned before, in order to check if
> setting the value would be allowed?
>
> What I expected is the following (in words, see my try with code below
> and the corresponding markers):
>
> Quote:
>> - The framework creates something out of "father.age > self.age",
>> maybe a generated class which contains the code representing the
>> condition "father.age > self.age" (* Code 1)
>> - this "element" knows _how_ to determine if the result is true or not,
>> but just needs the two parameters father and self
>>
>> - now I can provide several objects for the parameter father and ask
>> this "condition"-element for its result (* Code 2)
>
>
>
> Is the code below going in this direction, or did I misunderstand it
> at all?
>
> OCL ocl = OCL.newInstance(EcoreEnvironmentFactory.INSTANCE);
> OCLHelper helper = ocl.createOCLHelper();
> helper.setContext(SimplemodelPackage.Literals.PERSON);
>
>
> Constraint condition = (Constraint)
> helper.createInvariant("father.age < age"); <--- (* Code 1)
>
> Query invEval = ocl.createQuery(invariant);
> invEval.getEvaluationEnvironment().add("father",
> p.getFather()); <--- (*Code 2), bind the Condition element to the
> current father-parameter
>
> Object b = invEval.evaluate(p); <--- evaluate if this
> father-element would match the condition
>
>
> With best regards,
> Tom
|
|
|
Powered by
FUDForum. Page generated in 0.04122 seconds