Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » M2T (model-to-text transformation) » a difficult query to solve(find all the routes between one class and another)
a difficult query to solve [message #1804554] Thu, 28 March 2019 17:06 Go to next message
Jonathan Marino is currently offline Jonathan MarinoFriend
Messages: 8
Registered: May 2015
Junior Member
I am doing my engineering thesis on code generation for C language and I'm evaluating acceleo.
I have the next problem:
We are in uml using multiple inheritance. Let's say we have the following class diagram:

A
/ | \
B C D
| | \ |
| | E
\ | /
F

And we want to get all possible paths from A to F
((A, B, F), (A, C, F), (A, C, E, F), (A, D, E, F))
How can I write an OCL query that throws that result for that diagram? is there a way to solve something like this with JAVA instead of OCL?
Re: a difficult query to solve [message #1804609 is a reply to message #1804554] Fri, 29 March 2019 13:18 Go to previous messageGo to next message
Tomasz  Babczynski is currently offline Tomasz BabczynskiFriend
Messages: 11
Registered: May 2015
Junior Member
For the first question I should to think a bit but I suppose that the recursion will fit it.
Something like this (probably a bit more complicated):

[query private superClasses(c: Class) : OrderedSet(Class) = superClasses(c.superClass) /]


The answer for the last question is - yes, java wrapper. Look at tutorial:
https://wiki.eclipse.org/Acceleo/Getting_Started#Java_services_wrappers


Tomasz Babczyński
Re: a difficult query to solve [message #1804620 is a reply to message #1804609] Fri, 29 March 2019 15:28 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 6372
Registered: July 2009
Senior Member
Hi

(Apologies for not responding to your revised message on the OCL newsgroup. Your initial message came in at the same time as many SPAM philosophical queries which you inappropriate reference to diamond reinforced.)

The problem involves a nested iteration of indeterminate depth. This can sometimes be solved by a closure() iteration, but more usually by a recursion.

Given a helper function superPaths() : Set(Sequence(Class)) the problem degenerates to prepending each of the local superClasses on to the superPaths of each superClass.

Body something like: self.superClasses->collectNested(superClass | superPaths(superClass )->prepend(superClass ))->asSet()

In EMF-Java, you can define getSuperPaths() as a derived property with a cache.

In OCLinEcore, you can do much the same, the cache should happen automatically.

In Acceleo, the inherent caching of each operation invocation will automatically build the 'derived-property' cache as a Map from Class to Sequence(Class).

(If you use derived property caches, you should be aware that they will go stale if you change the metamodel.)

Regards

Ed Willink
Re: a difficult query to solve [message #1805335 is a reply to message #1804620] Fri, 12 April 2019 02:01 Go to previous messageGo to next message
Jonathan Marino is currently offline Jonathan MarinoFriend
Messages: 8
Registered: May 2015
Junior Member
Hello,
Thanks for the prompt reply.
I am not able to resolve the issue.
Based on your answer I coded the following query:

[query public superPaths(aClass: Class) : Sequence(Sequence(Class))=
	if (aClass.superClass->isEmpty()) then
		Sequence(Sequence(Class)){Sequence(Class){aClass}}
	else
		aClass.superClass->collectNested(superClass1 | superPaths(superClass1 ).prepend(aClass ))->asSequence()
	endif
/]

And I generated the following template to verify the result
[for (classes:Sequence(Class) | superPaths())]
	Route [i/]:
	[for (class: uml::Class | classes)separator(',')][class.name/][/for]
[/for]


But with a simple model:
Class1    Class6
|       /       |
Class3       Class2
       \     /
        Class4
          |
        Class5

For Class4 I get:
Route 1:
Class4, Class3, Class6, Class4, Class3, Class1
Route 2:
Class4, Class2, Class6

And for Class5:
Route 1:
Class5, Class4, Class3, Class6, Class4, Class3, Class1, Class5, Class4, Class2, Class6

It is close, apparently after a second level of inheritance the sequences become flattened. I do not know if I'm facing a bug or there's something wrong with the query ...

[Updated on: Fri, 12 April 2019 02:04]

Report message to a moderator

Re: a difficult query to solve [message #1805345 is a reply to message #1805335] Fri, 12 April 2019 06:58 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 6372
Registered: July 2009
Senior Member
Hi

In my example I used Set(Sequence(T)). I have no idea why you use Sequence(Sequence(T)) ; it may malfunction.

If your example doesn't work, then you need to debug it. Try simpler cases. If it flattens find out where the flattening occurs.

I'm not sure why you call your answers 'close'. The only closeness in that some input elements appear. How can Class1 possibly be the middle of a path?

I do not have time to look at snippets of your functionality. You need to post an executable repro to get help.

Generally with Acceleo, introduction of let-variables can aid understanding and reduce opportunities for tooling malfunctions. Nested collections offer ample opportunities for both.

Regards

Ed Willink

Re: a difficult query to solve [message #1806026 is a reply to message #1805345] Tue, 30 April 2019 18:04 Go to previous messageGo to next message
Jonathan Marino is currently offline Jonathan MarinoFriend
Messages: 8
Registered: May 2015
Junior Member
Hello,
After many attempts I was not able to create the query with Set instead of Sequence. At least I receive the error: "Invalid type for iteration".

For now in my thesis I say that I was not able to solve it with OCL, but I would like to change it.

The repository executable with the query is at: https://github.com/jonyMarino/oopc_acceleo_issue.git

Thank you very much and I hope you can help me,
Regards,
Jonathan

PD: I said it was close because if you notice even where Class1 appears in the middle is that there are many paths one after another, the fact that Class5 does not appear three times tells me that part of the collection was flattened before the "prepend" and after that it seems that all the collection was flattened...
Re: a difficult query to solve [message #1806040 is a reply to message #1806026] Wed, 01 May 2019 09:23 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 6372
Registered: July 2009
Senior Member
Hi

The problem is that in
Quote:
Body something like: self.superClasses->collectNested(superClass | superPaths(superClass )->prepend(superClass ))->asSet()


collectNested is not a suitable operation for merging multiple Set(Sequence()) to give a larger Set; it gives a wrapped Set. You need to fall back on iterate.

You should find that the following works:

Quote:
[comment encoding = UTF-8 /]
[module generate('http://www.eclipse.org/uml2/5.0.0/UML')]

[query public superPaths(aClass: uml::Class) : OrderedSet(Sequence(uml::Class))=
let superSuperPaths : Set(Sequence(uml::Class)) = if aClass.superClass->isEmpty()
then OrderedSet(Sequence(Class)){Sequence(Class){}}
else aClass.superClass->iterate(superClass1;
result : Set(Sequence(uml::Class)) = Set(Sequence(uml::Class)){}
| result->union(superPaths(superClass1)))
endif in
superSuperPaths->collectNested(superPath : Sequence(uml::Class) | superPath->prepend(aClass))->asOrderedSet()
/]

[template public main(aPackage : uml::Package)]
[comment @main /]
[file (aPackage.name + '.txt', false, 'UTF-8')]
[for (aClass : uml::Class | aPackage.ownedType->filter(uml::Class))]
[genClass(aClass)/]
[/for]
[/file]
[/template]

[template public genClass (aClass : uml::Class) ]
[aClass.name/]
[for (path : Sequence(uml::Class) | superPaths(aClass))]
Route [i/]:[for (class : uml::Class | path) separator(',')] [class.name/][/for]
[/for]
[/template]


At least the following looks like a plausible result:

Quote:
Class4
Route 1: Class4, Class2, Class6
Route 2: Class4, Class3, Class6
Route 3: Class4, Class3, Class1

Class1
Route 1: Class1

Class5
Route 1: Class5, Class4, Class3, Class6
Route 2: Class5, Class4, Class3, Class1
Route 3: Class5, Class4, Class2, Class6

Class2
Route 1: Class2, Class6

Class6
Route 1: Class6

Class3
Route 1: Class3, Class1
Route 2: Class3, Class6


Regards

Ed Willink
Re: a difficult query to solve [message #1806110 is a reply to message #1806040] Thu, 02 May 2019 18:05 Go to previous message
Jonathan Marino is currently offline Jonathan MarinoFriend
Messages: 8
Registered: May 2015
Junior Member
Thank you very much Ed!

To complete the answer I added this query to get all the paths from any class to another:

[query public getPaths(fromClass: uml::Class, toClass: uml::Class) : OrderedSet(Sequence(uml::Class))=
fromClass.superPaths()->select(path: Sequence(uml::Class) | path->includes(toClass))->collectNested(path: Sequence(uml::Class) | path->subSequence(2,path->indexOf(toClass)))->asOrderedSet()
/]


I think that the JAVA way is very necessary since it allows debugging.
If I had known before that it served to solve this type of queries I would have fought much less with them and do it the JAVA form. Any way, the queries in OCL enrich the thesis very much.

Regards!
Previous Topic:Invoke method cannot used for OrderedSet ?
Next Topic:[Acceleo] Disambiguate class reference
Goto Forum:
  


Current Time: Sat May 25 13:04:51 GMT 2019

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

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

Back to the top