Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » OCL » Finding all decendants of a Classifier
Finding all decendants of a Classifier [message #40406] Wed, 10 October 2007 14:51 Go to next message
Tor Neple is currently offline Tor NepleFriend
Messages: 57
Registered: July 2009
Member
Hello

I am trying to implement a OCL based UML Model metric "suite" based on a
paper I found .

As part of this I am trying to find all descendants of a UML Classifier.
I have experimented a bit and came up with

self.owner.allOwnedElements()->excluding(self)->select(e:Element |
e.oclIsKindOf(Classifier))->select(i:Classifier|i.parents()- >includes(self))

However, parsing this I get told:
Iterator variable must have same type as source element type
(self.owner.allOwnedElements()->excluding(self)->select(e : Element |
e.oclIsKindOf(uml::Classifier))->select(i : Classifier |
i.parents()->includes(self)))

I thought that all the things that were remaining in the set from the
first select now were Classifiers...

So; anyone got any solutions?
I am afraid I will probably have even more questions over the next
couple of weeks.

Regards

Tor
Re: Finding all decendants of a Classifier [message #40437 is a reply to message #40406] Wed, 10 October 2007 15:19 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: cdamus.ca.ibm.com

Hi, Tor,

Is there a particular need to examine only a subset of the model (using
allOwnedElements) instead of all classifiers in the model? Also, what
about transitive specialization? (parents only includes direct generals)
How about this:

Classifier.allInstances()->select(allParents()->includes(self))

This will result in all of the specializations of the "self" classifier that
exist in the model.

To answer specifically the parse error that you are getting: the problem
is, that the type of the "select" iterator expression is the same as the
type of the collection that it is applied to. In your case, this is
Set(Element) which is the type of Element::allOwnedElements(). The body
expression in an iterator has no power to change the result type of the
iterator expression.

So, you could do the following to resolve the error:

self.owner.allOwnedElements()->excluding(self)->select(e : Element |
e.oclIsKindOf(uml::Classifier)
and
e.oclAsType(uml::Classifier).parents()->includes(self))

However, your result will still be a Set(Element). So, this probably is
more desirable:

self.owner.allOwnedElements()->excluding(self)->iterate(
e : Element; specials : Set(Classifier) = Set{} |
if e.oclIsKindOf(Classifier)
and
e.oclAsType(Classifier).parents()->includes(self)
then
specials->including(e.oclAsType(Classifier))
else
specials
endif)

which results in Set(Classifier).

Or, sprinkling in a little "let"ness for readability:

self.owner.allOwnedElements()->excluding(self)->iterate(
e : Element; specials : Set(Classifier) = Set{} |
let c : Classifier = e.oclAsType(Classifier) in
if c.oclIsUndefined() or c.parents()->excludes(self) then
specials
else
specials->including(c)
endif)

HTH,

Christian


Tor Neple wrote:

> Hello
>
> I am trying to implement a OCL based UML Model metric "suite" based on a
> paper I found .
>
> As part of this I am trying to find all descendants of a UML Classifier.
> I have experimented a bit and came up with
>
> self.owner.allOwnedElements()->excluding(self)->select(e:Element |
>
e.oclIsKindOf(Classifier))->select(i:Classifier|i.parents()- >includes(self))
>
> However, parsing this I get told:
> Iterator variable must have same type as source element type
> (self.owner.allOwnedElements()->excluding(self)->select(e : Element |
> e.oclIsKindOf(uml::Classifier))->select(i : Classifier |
> i.parents()->includes(self)))
>
> I thought that all the things that were remaining in the set from the
> first select now were Classifiers...
>
> So; anyone got any solutions?
> I am afraid I will probably have even more questions over the next
> couple of weeks.
>
> Regards
>
> Tor
Re: Finding all decendants of a Classifier [message #40468 is a reply to message #40437] Wed, 10 October 2007 16:17 Go to previous messageGo to next message
Tor Neple is currently offline Tor NepleFriend
Messages: 57
Registered: July 2009
Member
Thanks for an excellent and swift answer!

The first solution you gave totally slipped my mind (it happens when one
just tries to translate something someone else has written).

So, while we are at it: Is there a smart way of calling the defined OCL
statement/query from Java using mdt.ocl? I have tried using the OCL
helper, but I do not seem to have grasped what context to set (or how)
for the helper, and how to actually feed the Helper a model. I guess it
should be quite straight forward; getting hold of the Classifier from a
Model (either through loading in a resource set, or by finding it in a
tree-viewer somewhere) and then applying the statement/query. I have
looked through the documentation, but I cannot really find what I am
looking for.

Thanks again and regards


Tor

Christian W. Damus wrote:
> Hi, Tor,
>
> Is there a particular need to examine only a subset of the model (using
> allOwnedElements) instead of all classifiers in the model? Also, what
> about transitive specialization? (parents only includes direct generals)
> How about this:
>
> Classifier.allInstances()->select(allParents()->includes(self))
>
> This will result in all of the specializations of the "self" classifier that
> exist in the model.
>
> To answer specifically the parse error that you are getting: the problem
> is, that the type of the "select" iterator expression is the same as the
> type of the collection that it is applied to. In your case, this is
> Set(Element) which is the type of Element::allOwnedElements(). The body
> expression in an iterator has no power to change the result type of the
> iterator expression.
>
> So, you could do the following to resolve the error:
>
> self.owner.allOwnedElements()->excluding(self)->select(e : Element |
> e.oclIsKindOf(uml::Classifier)
> and
> e.oclAsType(uml::Classifier).parents()->includes(self))
>
> However, your result will still be a Set(Element). So, this probably is
> more desirable:
>
> self.owner.allOwnedElements()->excluding(self)->iterate(
> e : Element; specials : Set(Classifier) = Set{} |
> if e.oclIsKindOf(Classifier)
> and
> e.oclAsType(Classifier).parents()->includes(self)
> then
> specials->including(e.oclAsType(Classifier))
> else
> specials
> endif)
>
> which results in Set(Classifier).
>
> Or, sprinkling in a little "let"ness for readability:
>
> self.owner.allOwnedElements()->excluding(self)->iterate(
> e : Element; specials : Set(Classifier) = Set{} |
> let c : Classifier = e.oclAsType(Classifier) in
> if c.oclIsUndefined() or c.parents()->excludes(self) then
> specials
> else
> specials->including(c)
> endif)
>
> HTH,
>
> Christian
>
>
> Tor Neple wrote:
>
>> Hello
>>
>> I am trying to implement a OCL based UML Model metric "suite" based on a
>> paper I found .
>>
>> As part of this I am trying to find all descendants of a UML Classifier.
>> I have experimented a bit and came up with
>>
>> self.owner.allOwnedElements()->excluding(self)->select(e:Element |
>>
> e.oclIsKindOf(Classifier))->select(i:Classifier|i.parents()- >includes(self))
>> However, parsing this I get told:
>> Iterator variable must have same type as source element type
>> (self.owner.allOwnedElements()->excluding(self)->select(e : Element |
>> e.oclIsKindOf(uml::Classifier))->select(i : Classifier |
>> i.parents()->includes(self)))
>>
>> I thought that all the things that were remaining in the set from the
>> first select now were Classifiers...
>>
>> So; anyone got any solutions?
>> I am afraid I will probably have even more questions over the next
>> couple of weeks.
>>
>> Regards
>>
>> Tor
>
Re: Finding all decendants of a Classifier [message #40499 is a reply to message #40468] Wed, 10 October 2007 16:41 Go to previous message
Eclipse UserFriend
Originally posted by: cdamus.ca.ibm.com

Hi, Tor,

Since you have the SDK documentation, you also have the Interactive OCL
Console example: install it in your workspace using the "New ->
Example..." wizard. You will then find an
org.eclipse.emf.ocl.examples.interpreter project in which you can find an
example of how to use the OCLHelper to parse and evaluate queries. Don't
worry about the complexity in the code that deals with Ecore and UML
metamodels ...

Once you have an OCLHelper, you need to decide whether your OCL expression
is a metamodel- or model-level query. Since you plan to evaluate it, I
suppose it is the former: you want to find specializations of a Classifier
in the model. So, you would do:

helper.setContext(UMLPackage.Literals.CLASSIFIER)

to tell the helper that the context of your query is the Classifier
metaclass (not some classifier in your model) and then

helper.createQuery("...")

to parse the query as an OCLExpression.

Evaluation of the OCL expression isn't a responsibility of the helper. The
OCL instance that created the helper is what you use for this. The OCL
infers the model from the context ("self") element supplied to the
evaluate(...) method. The default "model" is the forest of objects in
which the context element exists at evaluation time. This is the root
container and all of its contents (if not in a resource), or the root
containing resource and all of its contents (this handles cross-resource
containment). It is in this scope that the default implementation of
allInstances() searches for instances of a metaclass; you can customize
that by supplying your own "extent-map" via the OCL::setExtentMap method
(possibly using a specialization of the LazyExtentMap to provide a
different scope).

For a query that is repeatedly evaluated with the same extent-map but
different "self" objects, consider using the OCL::createQuery(...) method
to create a reusable query object.

HTH,

Christian

Tor Neple wrote:

> Thanks for an excellent and swift answer!
>
> The first solution you gave totally slipped my mind (it happens when one
> just tries to translate something someone else has written).
>
> So, while we are at it: Is there a smart way of calling the defined OCL
> statement/query from Java using mdt.ocl? I have tried using the OCL
> helper, but I do not seem to have grasped what context to set (or how)
> for the helper, and how to actually feed the Helper a model. I guess it
> should be quite straight forward; getting hold of the Classifier from a
> Model (either through loading in a resource set, or by finding it in a
> tree-viewer somewhere) and then applying the statement/query. I have
> looked through the documentation, but I cannot really find what I am
> looking for.
>
> Thanks again and regards
>
>
> Tor

-----8<-----
Previous Topic:Ease of Use of OCL in EMF
Next Topic:Problem with variables
Goto Forum:
  


Current Time: Thu Apr 25 07:28:49 GMT 2024

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

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

Back to the top