Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » OCL » OCL in UML Profile
OCL in UML Profile [message #1747164] Thu, 10 November 2016 11:40 Go to next message
Vetle Volden-Freberg is currently offline Vetle Volden-FrebergFriend
Messages: 39
Registered: February 2016
Member
Hello! I am working on a project where I need to define a relatively simple Constraint on a <<Stereotype>> of the <<Metaclass>> Message using OCL. I want to check if the Lifeline on the receiving end of the message is of a certain stereotype.

I am a newbie with OCL and I've been going through a steep learning curve lately.

So let's say you have a profile "MyProfile" that defines a stereotype: <<MyMessage>> that extends <<Metaclass>> Message and a stereotype: <<MyLifeline>> that extends <<Metaclass>> Lifeline.

How could you write an OCL invariant in an OpaqueExpression that ensures that the lifeline on the receiveEvent of the <<myMessage>> stereotype is of type <<MyLifeline>>?

So far I have experimented with some OpaqueExpressions that sadly do not work as I intended. There is most likely something I've misunderstood when it comes to using OCL.

A result of my experiments is the OpaqueExpression:
self.base_Message.receiveEvent.oclAsType(MessageOccurrenceSpecification).covered.oclIsKindOf(MyProfile::MyLifeline)
It is syntactically correct according to the OCL editor, but when I try it out it always yields the result that the invariant has been violated. I also tried to replace the MyProfile::MyLifeline with extension_MyLifeline but that is not accepted by the parser.

I tried to study the constraint used in the UML 2.5.0 Metamodel EPackage that checks if the ordering of the sendEvent & receiveEvent is correct for Messages that has receiveEvent & sendEvent pointing to the same Lifeline.

That (OCL) constraint looks like this:
receiveEvent.oclIsKindOf(MessageOccurrenceSpecification)
implies
let f : Lifeline = sendEvent->select(oclIsKindOf(MessageOccurrenceSpecification)).oclAsType(MessageOccurrenceSpecification)->asOrderedSet()->first().covered in

f = receiveEvent->select(oclIsKindOf(MessageOccurrenceSpecification)).oclAsType(MessageOccurrenceSpecification)->asOrderedSet()->first().covered implies

f.events->indexOf(sendEvent.oclAsType(MessageOccurrenceSpecification)->asOrderedSet()->first() ) <
f.events->indexOf(receiveEvent.oclAsType(MessageOccurrenceSpecification)->asOrderedSet()->first() )

I tried to see if there was anything in that constraint I could use to my advantage in my case, but nothing has worked so far..

Any ideas on how I can solve this issue?

(I am using Papyrus Neon to make the UML profile)


Cheers, Vetle VF.

[Updated on: Fri, 11 November 2016 13:05]

Report message to a moderator

Re: OCL in UML Profile [message #1747165 is a reply to message #1747164] Thu, 10 November 2016 12:13 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 5586
Registered: July 2009
Senior Member
Hi

I'm not sure what you mean by " OCL invariant in an OpaqueExpression". An OCL invariant is a Constraint. OpaqueExpressions are the base of ExpressionInOCL for queries.

[Your UML 2.5 snippet demonstrates the motivation for introducing selectByKind(). Unfortunately the tooling relies on RSA that has no modern facilities.]

Try self.base_Message.receiveEvent.oclAsType(MessageOccurrenceSpecification).covered.extension_MyLifeline <> null

You can use the Xtext OCL console to practice expressions and so see intermediate results.

You can even use the OCL debugger to single step.

Regards

Ed Willink
Re: OCL in UML Profile [message #1747168 is a reply to message #1747165] Thu, 10 November 2016 12:44 Go to previous messageGo to next message
Vetle Volden-Freberg is currently offline Vetle Volden-FrebergFriend
Messages: 39
Registered: February 2016
Member
"I'm not sure what you mean by " OCL invariant in an OpaqueExpression". An OCL invariant is a Constraint. OpaqueExpressions are the base of ExpressionInOCL for queries." --> Okay, I see.

I tried your suggestion Ed using the Xtext OCL Console, and the result was:
Null source for $uml$::Message::receiveEvent

I also tried just: self.base_Message which gave the result:
null.

So for some reason the OCL treats the base_Message property in my stereotype as null.

I suppose it is because in the console there hasn't been created any objects yet..

When I try your suggestion in a model it gives this error message:
The 'MyMessage::ReceiverIsMyLifeline' constraint is invalid for '<<MyMessage>>RootElement::Interaction1Message' - Failed to evaluate 'UML::Lifeline::extension_MyLifeline' for 'Sequence{org....}' and 'self.base_Message.receiveEvent.oclAsType(UML::MessageOccurrenceSpecification).covered.extension_MyLifeline')

This error message doesn't say much though .. (to me)

Regards, Vetle VF.

[Updated on: Fri, 11 November 2016 11:09]

Report message to a moderator

Re: OCL in UML Profile [message #1747173 is a reply to message #1747168] Thu, 10 November 2016 13:53 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 5586
Registered: July 2009
Senior Member
Hi

Using the console, you must start at a selectable EObject. The UML editor does not reify stereotypes, so you have to select the stereotyped element as "self" and omit the ".base_Message" from the test expression.

See https://bugs.eclipse.org/bugs/show_bug.cgi?id=495255

Regards

Ed Willink
Re: OCL in UML Profile [message #1747189 is a reply to message #1747173] Thu, 10 November 2016 15:33 Go to previous messageGo to next message
Vetle Volden-Freberg is currently offline Vetle Volden-FrebergFriend
Messages: 39
Registered: February 2016
Member
Thanks Ed. This made it a lot easier to check what the result of each statement would be.

Now, for the;
self.receiveEvent.oclAsType(MessageOccurrenceSpecification).covered.extension_MyLifeline <> null

I get:
Results:
Failed to evaluate 'UML::Lifeline::extension_MyLifeline' for 'Sequence{or...}' and 'self.receiveEvent.oclAsType(UML::MessageOccurrenceSpecification).covered.extension_MyLifeline'
java.lang.ClassCastException: org.eclipse.ocl.pivot.internal.values.SparseSequenceValueImpl cannot be cast to org.eclipse.emf.ecore.EObject


If I change context to <<MyLifeline>> and do:
self.getAppliedStereotypes() I get:
MyProfile::MyLifeline.

If I then change the context back to <<MyMessage>> and do:
self.receiveEvent.oclAsType(MessageOccurrenceSpecification).covered.getAppliedStereotypes() I get:
Results:
'Object' rather than 'Sequence($0)<$0:$uml$::Lifeline>' value required.

So I think when I do self.receiveEvent.oclAsType(MessageOccurrenceSpecification).covered I get the object in question, but as a "org.eclipse.ocl.pivot.internal.values.SparseSequenceValueImp". So I assume there is nothing I can do with the query to make this cast possible. And I don't think there is any way I can go around this problem ..

Regards, Vetle VF.

[Updated on: Thu, 10 November 2016 17:47]

Report message to a moderator

Re: OCL in UML Profile [message #1747214 is a reply to message #1747189] Thu, 10 November 2016 19:15 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 5586
Registered: July 2009
Senior Member
Hi

Support for the Java API as in self.getAppliedStereotypes() is an Eclipse OCL extension.

It looks as if it conflicts with the implicit collect. Try an explicit collect

self.receiveEvent.oclAsType(MessageOccurrenceSpecification).covered->collect(getAppliedStereotypes())

Regards

Ed Willink
Re: OCL in UML Profile [message #1747257 is a reply to message #1747214] Fri, 11 November 2016 11:08 Go to previous messageGo to next message
Vetle Volden-Freberg is currently offline Vetle Volden-FrebergFriend
Messages: 39
Registered: February 2016
Member
Hey, Ed.

Still the same outcome unfortunately.

Evaluating:
self.receiveEvent.oclAsType(MessageOccurrenceSpecification).covered->collect(getAppliedStereotypes()).

Results:
'Object' rather than 'Sequence($0)<$0:$uml$::Lifeline>' value required.


Regards, Vetle VF.
Re: OCL in UML Profile [message #1747260 is a reply to message #1747257] Fri, 11 November 2016 12:22 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 5586
Registered: July 2009
Senior Member
Hi

I cannot comment further without a repro: https://wiki.eclipse.org/OCL/ForumNetiquette

Regards

Ed Willink
Re: OCL in UML Profile [message #1747267 is a reply to message #1747260] Fri, 11 November 2016 12:53 Go to previous messageGo to next message
Vetle Volden-Freberg is currently offline Vetle Volden-FrebergFriend
Messages: 39
Registered: February 2016
Member
Ok. So I have reproduced the same issue. This is not my project, however this example illustrates the same problem and is a reproduction of the same effects.

See the attached compressed folder for example files.
The compressed folder includes one Papyrus Project folder with the following contents; Papyrus Model (UML Profile) named myprofile.profile and a Papyrus Model (UML) named myprofileTest.

The UML Profile contains three stereotypes. Two of them are stereotypes of <<Metaclass>> Lifeline <<Stereotype>> MyLifeline1 and <<Stereotype>> MyLifeline2 respectively. The last stereotype is a stereotype of <<Metaclass>> Message called <<Stereotype>> MyMessage.

What I want to accomplish is to create a constraint such that the recepient of <<MyMessage>> can only be a lifeline of stereotype <<MyLifeline2>>.

To reproduce, import the project in Papyrus (I used Neon), open myprofileTest, open the interactive xtext console, click the Message of the <<MyMessage>> stereotype (to set the context of self in the console).

Try the following (using the interactive xtext console):
(1) self.receiveEvent.oclAsType(MessageOccurrenceSpecification).covered.extension_MyLifeline2 <> null

(2) self.receiveEvent.oclAsType(MessageOccurrenceSpecification).covered->collect(getAppliedStereotypes())

Regards, Vetle VF.

[Updated on: Fri, 11 November 2016 16:55]

Report message to a moderator

Re: OCL in UML Profile [message #1747274 is a reply to message #1747267] Fri, 11 November 2016 14:25 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 5586
Registered: July 2009
Senior Member
Hi

Thanks. I see similarly wierd things to you. It looks as if ".covered" is inconsistently a collection and not-a-collection.

See https://bugs.eclipse.org/bugs/show_bug.cgi?id=507406

Regards

Ed Willink
Re: OCL in UML Profile [message #1747275 is a reply to message #1747274] Fri, 11 November 2016 14:29 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 5586
Registered: July 2009
Senior Member
Hi

Workaround. Use a gratuitous "->collect(l | l)".

self.receiveEvent.oclAsType(MessageOccurrenceSpecification).covered->collect(l | l)->collect(l | l.extension_MyLifeline2)

Regards

Ed Willink
Re: OCL in UML Profile [message #1747287 is a reply to message #1747275] Fri, 11 November 2016 16:50 Go to previous messageGo to next message
Vetle Volden-Freberg is currently offline Vetle Volden-FrebergFriend
Messages: 39
Registered: February 2016
Member
Thank you for investing your time and effort into solving my issue Ed. Your workaround worked like a charm!

When the recepient of the message is <<MyLifeline2>> it would evaluate to the object itself. When the recepient wasn't <<MyLifeline2>> it would evaluate to null. So I basically did an .oclIsUndefined() on the evaluation which for some reason returns a Bag(Boolean). So I ended up with creating the following constraint:

self.receiveEvent.oclAsType(MessageOccurrenceSpecification).covered->collect(l | l)->collect(l | l.extension_MyLifeline2).oclIsUndefined() = Bag{false}

Which obviously will return true if the recepient is e.g <<MyLifeline2>> and false otherwise. It's not pretty, but it works Very Happy

Thanks again,

Regards, Vetle VF.
Re: OCL in UML Profile [message #1747296 is a reply to message #1747287] Fri, 11 November 2016 17:50 Go to previous message
Ed Willink is currently offline Ed WillinkFriend
Messages: 5586
Registered: July 2009
Senior Member
Hi

Thank you for the excellent repro. It really saves me a lot of time misguessing at problems.

The underlying problem is that the UML2 evaluation returns an EList for InteractionFragment::covered totally ignoring the UML redefinition as a non-list. This is a necessary limitation of the EMF Java model, which OCL evaluation must remedy. Bug fix pushed to branch ewillink/master. Promotion to master in due course. Seems safe enough to backport to Neon for SR2.

The workaround relies on introducing a polymorphic object/collection step so that the 'wrong' object/collection is accommodated. "->collect(l | l)" is a shortform of ".oclAsSet()->collect(l | l)". It is the oclAsSet() that provides the polymorphism. The collect is gratuitous.

"... <> null" does not work for you because you are dealing with a collection. Try "... ->notEmpty()".

Regards

Ed Willink
Previous Topic:OCL JARs
Next Topic:Validation of property access in post-conditions of UML static operations
Goto Forum:
  


Current Time: Wed Jan 24 06:05:49 GMT 2018

Powered by FUDForum. Page generated in 0.01958 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software