Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » ATL » One to many transformation
One to many transformation [message #911862] Wed, 12 September 2012 13:16 Go to next message
Cristiano De Faveri is currently offline Cristiano De FaveriFriend
Messages: 13
Registered: August 2012
Junior Member
Hi All,

I have a scenario which a target model should create a sequence of classes due to the list of Strings another class holds.

The code snippet below illustrates the problem. I have FindClause which has bindingObjects whichs holds a list of aliases (EStrings).
For each Aliases I have to create a ObjectSource class which alias will be each FindClause.bindingObject.Alias of the list and className will be an String according to the type attribute of BindingObject.

I started a rule Find2From and created a helper to return the className based on FindClause.bindingObject.type, however how to fill alias attribute based on the FindClause.bindingObject.alias list ?

Many thanks in advance.

**** INModel ****

+-FindClause (clause : EString, bindingObject : BindingObject (1..*))
+-BindingObject (type : ObjectType, alias : EString (1..*))
+-ObjectType ( value : EString)

*******OUTModel*******

+-FromClause (clause : EString, objectList : ObjectSource (1.*))
+-ObjectSource(alias : EString, className : EString)

rule Find2From {
	from
		findClause : ajqlModel!FindClause
	to 
		fromClause : hqlModel!FromClause  (
			clause <- 'From',
			ObjectSource <- Sequence {source} 
			)
		source : hqlModel!ObjectSource (
   	            -- className <- thisModule.getObjectName(findClause.bindingObject.type)
		    -- alias <- ?[/color]??
	)
}
Re: One to many transformation [message #911904 is a reply to message #911862] Wed, 12 September 2012 14:59 Go to previous messageGo to next message
Hugo Bruneliere is currently offline Hugo BruneliereFriend
Messages: 612
Registered: July 2009
Senior Member
Hello,

Multi-valued attributes of type X are considered by ATL as being of type Sequence(X).
So you can navigate BindingObject.alias as of type Sequence(String), in order to obtain the single String value you want to put as the value for the Object.alias (single-valued) String attribute.
Cf. http://wiki.eclipse.org/ATL/User_Guide_-_The_ATL_Language#Sequence_data_type_operations

Best regards,

Hugo


------------------------------------------
Hugo Bruneliere - R&D Engineer
AtlanMod research team (Inria, EMN & LINA)
Ecole des Mines de Nantes
Nantes - France
------------------------------------------
Re: One to many transformation [message #913109 is a reply to message #911904] Fri, 14 September 2012 19:52 Go to previous messageGo to next message
Cristiano De Faveri is currently offline Cristiano De FaveriFriend
Messages: 13
Registered: August 2012
Junior Member
Hi Hugo many thanks for your response.

Still stuck with this problem. I've trying different ways to implement using the declarative way of ATL.

I'm using this approach to iterate over the sequences :

...
_fromClause : hqlModel!FromClause( 
    	clause <- 'From',
	ObjectList <- query1Clause.query.find.bindingObject -> collect (bindIt | bindIt.alias -> collect (aliasIt | thisModule.getSourceObject(bindIt.type, aliasIt ))) 
        -- the simple algorithm i'm trying to implement
             -- For each bindingObject (bindIt), for each bindingObject.Alias (aliasIt) , invoke getSourceObject rule passing bindingObject.type and aliasIt (String)
...

rule getSourceObject (type: ajqlModel!ObjectType, findAlias: String) {
	to
		ObjectSource : hqlModel!ObjectSource (
			alias <- findAlias,
			className <- thisModule.getObjectName(type) 
		)
}


However, a not very clear error has been raised during the execution (compilation is 0 errors)

org.eclipse.m2m.atl.engine.emfvm.VMException: Operation not found: AJQL2HQL : ASMModule.including(java.util.ArrayList)

Am I using the chain of -> collect in a wrong way ?




Re: One to many transformation [message #915514 is a reply to message #913109] Mon, 17 September 2012 12:53 Go to previous messageGo to next message
Hugo Bruneliere is currently offline Hugo BruneliereFriend
Messages: 612
Registered: July 2009
Senior Member
Hello,

By using two consecutive "collect" operations, you're obtaining a Sequence(Sequence(ObjectSource)).
To get a Sequence(ObjectSource), you have to explicitly call the "flatten" operation (cf. ATL user guide).
The error may come from this.

Best regards,

Hugo


------------------------------------------
Hugo Bruneliere - R&D Engineer
AtlanMod research team (Inria, EMN & LINA)
Ecole des Mines de Nantes
Nantes - France
------------------------------------------
Re: One to many transformation [message #915761 is a reply to message #915514] Mon, 17 September 2012 23:02 Go to previous messageGo to next message
Cristiano De Faveri is currently offline Cristiano De FaveriFriend
Messages: 13
Registered: August 2012
Junior Member
Hi Hugo,

Thanks for your tips.

I tried to insert flatten() into the statement, but without any success.
In order to understand what is going on, I just break down the structure into imperative statements to collect more information about it. I tried some debug statements and even debug environment, but it does not help me a lot.

This is the code I tried to change with flatten() clause.

ObjectList <- query1Clause.query.find.bindingObject -> collect (bindIt | bindIt.alias -> collect (aliasIt | thisModule.getSourceObject(bindIt.type, aliasIt ))) -> flatten()


The error remains the same : org.eclipse.m2m.atl.engine.emfvm.VMException: Operation not found: AJQL2HQL : ASMModule.including(java.util.ArrayList)

I broke down the structure like this :

1. Remove ObjectList from fromClause :

 _fromClause : hqlModel!FromClause( 
	    	clause <- 'From'
	   ),  
...


2. Then I wrote a simple imperative code to figure out what's going on :

...	
                do {
		       'debuging...'.println();
		
		for (it in query1Clause.query.find.bindingObject) { -- iterates over bindingObject
			'bindingObj...'.println();
			thisModule.getObjectName(it.type).println();	
			
			for (it2 in it.alias) { -- iterates over alias inside bindingObjects
				_fromClause.ObjectList -> including(thisModule.getSourceObject (it.type, it2));
			   -- append ObjectSource to ObjectList (try to at least) - Here the error raises
			}	
		}	
	}


This approach leads to a java.lang.ArrayIndexOutOfBoundsException exception

The iteration is working fine, I could see every information when traversing the model, even getSourceObject helper. The issue has been raised when trying to fill out the list property (

I'm trying different paths in order to solve this problem, unfortunately without success. Do you have any another advise or some debug tip I could use ?


Many thanks Hugo for your assistance.

Re: One to many transformation [message #915933 is a reply to message #915761] Tue, 18 September 2012 08:38 Go to previous messageGo to next message
Hugo Bruneliere is currently offline Hugo BruneliereFriend
Messages: 612
Registered: July 2009
Senior Member
Hello,

The second error comes from the fact that you're using a variable (_fromClause.ObjectList) which has not be initialized yet.
Something like the following may work better:
_fromClause.ObjectList <- Sequence{};
for (it2 in it.alias) {
    _fromClause.ObjectList <- _fromClause.ObjectList->including(thisModule.getSourceObject (it.type, it2));
}
Anyway I would not try to solve your problem by using an imperative "do" section, because it seems that you're introducing another error that is different from the original one.

Considering your real error (cf. your initial post), it seems that you're doing an illegal call to the "including" operation on a given sequence: have you checked that this is not coming from the "getSourceObject" rule or from the "getObjectName" helper?

Best regards,

Hugo



------------------------------------------
Hugo Bruneliere - R&D Engineer
AtlanMod research team (Inria, EMN & LINA)
Ecole des Mines de Nantes
Nantes - France
------------------------------------------
Re: One to many transformation [message #916099 is a reply to message #915933] Tue, 18 September 2012 14:22 Go to previous messageGo to next message
Cristiano De Faveri is currently offline Cristiano De FaveriFriend
Messages: 13
Registered: August 2012
Junior Member
Hi Hugo,

I'll keep the original declarative issue per your recommendation. The imperative code was just to try to break down the problem.

Debugging the expression like this

-> collect (aliasIt | thisModule.getSourceObject(bindIt.type, aliasIt).debug()


I can see this result after the first iteration :

Sequence {Sequence {}}

OK, according to your previous message, since collect over collect will generate a sequence over a sequence.
Debug(), in this case, is running before trying to insert ObjectSource object into the sequence. The problem seems the Sequence expects a Sequence and not a single object returned by getSourceObject(..). Even though, I believe that the message Operation not found ASMModule.including(java.util.ArrayList) would not be appropriate in this situation since it is a Sequence anyway. But I'm not sure if this would be the problem.

I tried to flat the sequence before inserting but without success as well.

I shared a small project focused on this problem containing ecore metamodel, a simple model and atl files. This is the project I'm currently working on to try to solve the issue. If you can take a look Hugo, I'd be very very grateful.

www.defavari.com.br/public/ATLProject/

Thank you again.



Re: One to many transformation [message #916135 is a reply to message #916099] Tue, 18 September 2012 15:44 Go to previous messageGo to next message
Hugo Bruneliere is currently offline Hugo BruneliereFriend
Messages: 612
Registered: July 2009
Senior Member
From what I've seen, you're applying the "flatten" operation onto the nested collection which has no effect (as it is already a simple collection of elements).
The "flatten" operation should be applied onto the nesting collection:
query1Clause.query.find.bindingObject 
       -> collect (bindIt | bindIt.alias 
             -> collect (aliasIt | thisModule.getSourceObject(bindIt.type, aliasIt))
       ) -> flatten()
Does it work with this?

Hugo


------------------------------------------
Hugo Bruneliere - R&D Engineer
AtlanMod research team (Inria, EMN & LINA)
Ecole des Mines de Nantes
Nantes - France
------------------------------------------
Re: One to many transformation [message #916139 is a reply to message #916135] Tue, 18 September 2012 15:53 Go to previous messageGo to next message
Cristiano De Faveri is currently offline Cristiano De FaveriFriend
Messages: 13
Registered: August 2012
Junior Member
Yes, I tried flatten() at the end also. Same issue.

By the way, the stack shows something like

...(name: QueryStatement) (instanceClassName: null) ...

In my perception, this instanceClassName: null does not have any influence on that. I checked my ecore model, validate it (EMF tools) and check it visually as well. It seems OK.

Cristiano

e.m2m.atl.engine.emfvm.VMException: Operation not found: AJQL2HQL : ASMModule.including(java.util.ArrayList)
	at __applyQuery2Query#97(AJQL2HQL.atl[27:29-28:85])
		local variables: self=AJQL2HQL : ASMModule, link=TransientLink {rule = Query2Query, sourceElements = {query1Clause = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@430636bc[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@78993cb9[/email] (name: Query) (instanceClassName: null) (abstract: false, interface: false))}, targetElements = {_queryStatement = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@4cf39304[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@40d3853d[/email] (name: QueryStatement) (instanceClassName: null) (abstract: false, interface: false)), _whereClause = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@b391314[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@7ed0890a[/email] (name: WhereClause) (instanceClassName: null) (abstract: false, interface: false)), _selectClause = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@50138bcd[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@60679695[/email] (name: SelectClause) (instanceClassName: null) (abstract: false, interface: false)), _fromClause = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@333f68cd[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@30cf41a5[/email] (name: FromClause) (instanceClassName: null) (abstract: false, interface: false)), _expression = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@7f98504[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@2cd53091[/email] (name: Expression) (instanceClassName: null) (abstract: false, interface: false)), query2Clause = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@e8bcdb3[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@83fdb62[/email] (name: Query) (instanceClassName: null) (abstract: false, interface: false))}, variables = {}}, query1Clause=IN!<unnamed>, query2Clause=OUT!<unnamed>, _queryStatement=OUT!<unnamed>, _selectClause=OUT!<unnamed>, _fromClause=OUT!<unnamed>, _whereClause=OUT!<unnamed>, _expression=OUT!<unnamed>, bindIt=IN!<unnamed>, aliasIt='b'
	at __exec__#8(AJQL2HQL.atl)
		local variables: self=AJQL2HQL : ASMModule, e=TransientLink {rule = Query2Query, sourceElements = {query1Clause = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@430636bc[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@78993cb9[/email] (name: Query) (instanceClassName: null) (abstract: false, interface: false))}, targetElements = {_queryStatement = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@4cf39304[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@40d3853d[/email] (name: QueryStatement) (instanceClassName: null) (abstract: false, interface: false)), _whereClause = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@b391314[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@7ed0890a[/email] (name: WhereClause) (instanceClassName: null) (abstract: false, interface: false)), _selectClause = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@50138bcd[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@60679695[/email] (name: SelectClause) (instanceClassName: null) (abstract: false, interface: false)), _fromClause = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@333f68cd[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@30cf41a5[/email] (name: FromClause) (instanceClassName: null) (abstract: false, interface: false)), _expression = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@7f98504[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@2cd53091[/email] (name: Expression) (instanceClassName: null) (abstract: false, interface: false)), query2Clause = [email]org.eclipse.emf.ecore.impl.DynamicEObjectImpl@e8bcdb3[/email] (eClass: [email]org.eclipse.emf.ecore.impl.EClassImpl@83fdb62[/email] (name: Query) (instanceClassName: null) (abstract: false, interface: false))}, variables = {}}
	at main#24(AJQL2HQL.atl)
		local variables: self=AJQL2HQL : ASMModule

[Updated on: Tue, 18 September 2012 15:54]

Report message to a moderator

Re: One to many transformation [message #916362 is a reply to message #916139] Tue, 18 September 2012 23:49 Go to previous messageGo to next message
Cristiano De Faveri is currently offline Cristiano De FaveriFriend
Messages: 13
Registered: August 2012
Junior Member
Hi,

Just to register a change I made for testing purposes, I created a helper which returns an oclUndefined instead of call getSourceObject(..). Just to check if the problem is located on "including" to sequence or if the message is a consequence of another problem. The weird part is that using an oclUndefined any error is raised. Using debug() after flatten() it shows {oclUndefined, oclUndefined}. I do not know if the ASMModule just skip any part of the code when the object is of type oclUndefined or if the rule getSourceObject (..) is not working properly. All debug clauses inserted into getSourceObject shows the data properly. It seems the "to" clause is not creating the object properly raising an issue that is not clear on the current exceptional message. Maybe this information is valuable.

query1Clause.query.find.bindingObject 
       -> collect (bindIt | bindIt.alias 
             -> collect (aliasIt | thisModule.getSO(bindIt.type, aliasIt))
       ) -> flatten()

helper def : getSO (type : ajqlModel!ObjectType , findAlias: String) : hqlModel!ObjectSource =
	let x : hqlModel!ObjectSource = OclUndefined
	in x
;
Re: One to many transformation [message #916624 is a reply to message #916362] Wed, 19 September 2012 08:39 Go to previous messageGo to next message
Hugo Bruneliere is currently offline Hugo BruneliereFriend
Messages: 612
Registered: July 2009
Senior Member
Hello,

Thanks for the complementary information.
Right now, I cannot really see where the error is coming from.
Have you already tried to use the ATL Debugger on this transformation?
Maybe this could help to better trace what actually happens during the transformation execution...

Hugo


------------------------------------------
Hugo Bruneliere - R&D Engineer
AtlanMod research team (Inria, EMN & LINA)
Ecole des Mines de Nantes
Nantes - France
------------------------------------------
Re: One to many transformation [message #916757 is a reply to message #916624] Wed, 19 September 2012 12:19 Go to previous messageGo to next message
Cristiano De Faveri is currently offline Cristiano De FaveriFriend
Messages: 13
Registered: August 2012
Junior Member
Thanks Hugo, I tried in the past without any clear results, but I'll check it again, looking for more details. Come back soon with the results.

I'm really under pressure on this point because this is just the tip of the iceberg of the entire transformation. Without solving this issue, I can't move forward, unless I have some alternative for now.

Thank you again.
Re: One to many transformation [message #918212 is a reply to message #916757] Thu, 20 September 2012 21:14 Go to previous messageGo to next message
Cristiano De Faveri is currently offline Cristiano De FaveriFriend
Messages: 13
Registered: August 2012
Junior Member
Hi Hugo,

Help me to understand why it works now ! Smile

I tried to focus my mind on this piece of code
...
-> collect (aliasIt | thisModule.getSourceObject(bindIt.type, aliasIt))
..


which error come from. In my mind, ATL built two sequences from collect over collect Sequence{Sequence{hqlModel!ObjectSource}} which flattened yields in a perfect Sequence{hqlModel!ObjectSource} which is what the property ObjectList expects. However the error we saw about incluing operation missing seems not be about these two sequences (what makes sense since Sequences owns including operation). What I do is to "cast" the return of called rule getSourceObject to Sequence of hqlModel!ObjectSource in the imperative portion of the code. Look :

rule getSourceObject (type : ajqlModel!ObjectType , findAlias: String) { 
	to 
		ObjectSource : hqlModel!ObjectSource 
		(
			alias <- findAlias.debug(),
			className <- thisModule.getObjectName(type).debug() 
		)
	do {
		Sequence {ObjectSource};	
	}	
}


Returning a sequence instead of a single object works, however it does not make sense for me yet. Do you have any idea about it ?

thanks.

Re: One to many transformation [message #918671 is a reply to message #918212] Fri, 21 September 2012 08:25 Go to previous messageGo to next message
Hugo Bruneliere is currently offline Hugo BruneliereFriend
Messages: 612
Registered: July 2009
Senior Member
Hi,

What happens if you just let the original nested "collects" (with the correct call to "flatten") and write your called rule like this:
rule getSourceObject (type : ajqlModel!ObjectType , findAlias: String) { 
	to 
		_objectSource : hqlModel!ObjectSource 
		(
			alias <- findAlias.debug(),
			className <- thisModule.getObjectName(type).debug() 
		)
	do {
		_objectSource;	
	}	
}
Does it works?

Hugo


------------------------------------------
Hugo Bruneliere - R&D Engineer
AtlanMod research team (Inria, EMN & LINA)
Ecole des Mines de Nantes
Nantes - France
------------------------------------------
Re: One to many transformation [message #919026 is a reply to message #918671] Fri, 21 September 2012 16:00 Go to previous messageGo to next message
Cristiano De Faveri is currently offline Cristiano De FaveriFriend
Messages: 13
Registered: August 2012
Junior Member
Uau.... it works as well. So my thought was wrong about the need of returning a Sequence. I need to express return type explicitly on imperative code the have compute object available further on the code.

...
_fromClause : hqlModel!FromClause ( 
	    	clause <- 'From',
			ObjectList <- query1Clause.query.find.bindingObject -> collect (bindIt | bindIt.alias -> collect (aliasIt | thisModule.getSourceObject(bindIt.type, aliasIt ))) -> flatten() -> debug()   
		),  
...

rule getSourceObject (type : ajqlModel!ObjectType , findAlias: String) { 
	to 
		ObjectSource : hqlModel!ObjectSource 
		(
			alias <- findAlias,
			className <- thisModule.getObjectName(type) 
		)
	do {
		ObjectSource;		
	}
}


output debug :


uence {OUT!<unnamed>, OUT!<unnamed>}
AJQL2HQL executed in 0,002s.

I was wrong when thinking "to" section leaves available the object for further computation. I was thinking "to" clause like a return of a function and it seems this is not the case. Guess this part of the manual clarify this point. It was not clear for me when I read this in the past... my apologizes.

Called Rules
...
"The code specified within the imperative block makes a variable (metamodel) defined in the context of the ATL module pointing to this model element. By this mean, the generated Metamodel remains accessible for further computation during the transformation.
... "

Am I right ?
Re: One to many transformation [message #921582 is a reply to message #919026] Mon, 24 September 2012 08:43 Go to previous message
Hugo Bruneliere is currently offline Hugo BruneliereFriend
Messages: 612
Registered: July 2009
Senior Member
(imperative) called rules are not (declarative) matched rules and so don't behave in the ATL standard way.

Hugo


------------------------------------------
Hugo Bruneliere - R&D Engineer
AtlanMod research team (Inria, EMN & LINA)
Ecole des Mines de Nantes
Nantes - France
------------------------------------------
Previous Topic:How to convert ATL-file to EMF-file?
Next Topic:ATL Plugin with 2 source metamodels
Goto Forum:
  


Current Time: Sat Nov 29 01:38:06 GMT 2014

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

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