Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » How to add customized method to the xtext generated dsl interface(How to use customized processor to add method declaration in the infered ecore model )
How to add customized method to the xtext generated dsl interface [message #645974] Tue, 21 December 2010 12:32 Go to next message
Pierre-Alain BOURDIL is currently offline Pierre-Alain BOURDILFriend
Messages: 25
Registered: September 2010
Junior Member
Greetings,

The problem :

i defined a dsl, which manage interface, such as :
Interface:
    "interface" name=ID {
         members += InterfaceMembers
     }

InterfaceMembers: 
   Operation|Attribute

Attribute : 
    "attribute" name=ID

Operation
    "operation" name=ID


The Interface generated by xtext has operation to get InterfaceMembers :

 EList<InterfaceMember> getMembers();


I'd like to add two operations to this Interface (along with their implementation in the InterfaceImpl class), getOperations and getAttributes, with the above signature :

 EList<Operation> getOperations();
 EList<Attribute> getAttribute();


One tentative of solution :

I've tried to customize the xtext code generation, namely ecore inference, to add the operation "getOperations", but i failed. I've created a Xtend file, which look likes that :

import ecore;
import webIDL;


process(xtext::GeneratedMetamodel this) :
	ePackage.process()
;

process(EPackage this) :
	eClassifiers.process()
;

process(EClassifier this) :
	null
;

process(EClass this) :
	if this.name == 'Interface' then
		this.addOperation(
			"getOperations",
			List[Operation], // This is my dsl operation type, imported from "import WebIDL", encapsulated in a Xpand2::type list
	'return new org.eclipse.emf.common.util.BasicEList<Operation>();')
;


create ecore::EOperation addOperation(ecore::EClassifier c, 
									  String strName,
									  xpand2::Type type, 
									  String strBody):
									 type-> 
	setName(strName) ->
	setEType(type) -> // type error 
	((ecore::EClass)c).eOperations.add(this);


The code above does not work, because setEType expect an ecore::EClassifier as a parameter, changing the type of the addOperation type argument to ecore::EClassifier does not solve the problem. Moreover, i can't figure out how force the ecore inference to generate an EList of operation for the getOperation method.


My questions are :

1) How can i force the ecore inference to generate an EList of Operation as return type of my getOperation ?
2) Did i misused the postprocessor functionnality ? My idea here was to add those methods directly in my dsl ecore metamodel and let the xtext ecore inference output the source code. In case y idea's wrong, how can i generate those methods ?
Re: How to add customized method to the xtext generated dsl interface [message #646004 is a reply to message #645974] Tue, 21 December 2010 14:26 Go to previous messageGo to next message
Jan Koehnlein is currently offline Jan KoehnleinFriend
Messages: 760
Registered: July 2009
Location: Hamburg
Senior Member
It looks like you're confusing type systems (xpand, ecore, Java) in your
transformation - at least the argument 'type' should rather be an
ecore::Classifier, and its multiplicity should be provided by setting
'upperBound' to -1 on the EOperation instead of passing a list.
Nevertheless, I am not sure if that's the only problem.

You might have noticed that it's kind of tricky writing this
transformation, so I'd suggest to modify the Ecore model by hand (start
with the generated one) to get it clear on the EMF side and use the
modified Ecore as an imported metamodel.

Am 21.12.10 13:32, schrieb Pierre-Alain BOURDIL:
> Greetings,
> The problem :
> i defined a dsl, which manage interface, such as :
> Interface:
> "interface" name=ID {
> members += InterfaceMembers
> }
>
> InterfaceMembers: Operation|Attribute
>
> Attribute : "attribute" name=ID
>
> Operation
> "operation" name=ID
>
>
> The Interface generated by xtext has operation to get InterfaceMembers :
>
> EList<InterfaceMember> getMembers();
>
>
> I'd like to add two operations to this Interface (along with their
> implementation in the InterfaceImpl class), getOperations and
> getAttributes, with the above signature :
>
> EList<Operation> getOperations();
> EList<Attribute> getAttribute();
>
>
> One tentative of solution :
>
> I've tried to customize the xtext code generation, namely ecore
> inference, to add the operation "getOperations", but i failed. I've
> created a Xtend file, which look likes that :
>
> import ecore;
> import webIDL;
>
>
> process(xtext::GeneratedMetamodel this) :
> ePackage.process()
> ;
>
> process(EPackage this) :
> eClassifiers.process()
> ;
>
> process(EClassifier this) :
> null
> ;
>
> process(EClass this) :
> if this.name == 'Interface' then
> this.addOperation(
> "getOperations",
> List[Operation], // This is my dsl operation type, imported from "import
> WebIDL", encapsulated in a Xpand2::type list
> 'return new org.eclipse.emf.common.util.BasicEList<Operation>();')
> ;
>
>
> create ecore::EOperation addOperation(ecore::EClassifier c, String strName,
> xpand2::Type type, String strBody):
> type-> setName(strName) ->
> setEType(type) -> // type error ((ecore::EClass)c).eOperations.add(this);
>
>
> The code above does not work, because setEType expect an
> ecore::EClassifier as a parameter, changing the type of the addOperation
> type argument to ecore::EClassifier does not solve the problem.
> Moreover, i can't figure out how force the ecore inference to generate
> an EList of operation for the getOperation method.
>
> My questions are :
> 1) How can i force the ecore inference to generate an EList of Operation
> as return type of my getOperation ? 2) Did i misused the postprocessor
> functionnality ? My idea here was to add those methods directly in my
> dsl ecore metamodel and let the xtext ecore inference output the source
> code. In case y idea's wrong, how can i generate those methods ?


--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com


---
Get professional support from the Xtext committers at www.typefox.io
Re: How to add customized method to the xtext generated dsl interface [message #646029 is a reply to message #646004] Tue, 21 December 2010 16:26 Go to previous messageGo to next message
Pierre-Alain BOURDIL is currently offline Pierre-Alain BOURDILFriend
Messages: 25
Registered: September 2010
Junior Member
Thanks for your answer,

what i understood is that there's no easy way to add method using ecore inference postprocessing. Manually update the ecore mm, then using it as an imported mm prohibits evolution on this mm, thereby on my grammar, which is not possible for me at this time.

Regarding type confusion, you're right, i was wondering if exists an easy way to reference dsl specific type within xpand context , because of my little knowledge of those tools.

Now, if there' s no way to easily custom the generated interface using xtend, is there a way to generate a posteriori the source code for the method directly in the Interface and InterfaceImpl code, using xpand template or maybe atl transformation plugged using the MWE workflow ?

Regards.
Re: How to add customized method to the xtext generated dsl interface [message #646054 is a reply to message #646029] Tue, 21 December 2010 18:12 Go to previous messageGo to next message
Meinte Boersma is currently offline Meinte BoersmaFriend
Messages: 434
Registered: July 2009
Location: Leiden, Netherlands
Senior Member
Pierre-Alain,

Generation of .genmodel and Java classes is entirely down to the EMF generator. Xtext is only a client (user) of that technology. What you want to do, can be done in EMF alone, using the postprocessing stage. It's just that it's generally easier to separate the meta model (generation) from the grammar (parser generation), as Jan suggests. With a little more knowledge of Xtend, you should be able to do it using the postprocessing as well.


Re: How to add customized method to the xtext generated dsl interface [message #646122 is a reply to message #646029] Wed, 22 December 2010 08:41 Go to previous messageGo to next message
Jan Koehnlein is currently offline Jan KoehnleinFriend
Messages: 760
Registered: July 2009
Location: Hamburg
Senior Member
First of all: What do you need this separation for? If you need that in
an Xpand code generator only, the easiest and most common way is to
write an Xtend function filtering the feature. As you can put the first
parameter of a function call in front of the method name with a dot the
call will look like a method call on the object itself, e.g.

getAttributes(Interface this) : getOperations().typeSelect(Attribute);
// call as myInterface.getAttributes()


If you really need these operations on the Java classes you have to
modify the Ecore model. Manually evolving the ecore model in parallel to
the grammar is not that complicated, as the grammar editor will give you
early feedback on mismatches. We have discovered that the Ecore
derivation can help a lot in the early stages of a project, but it makes
sense to switch to the imported metamodel when the complexity increases.

If you want to do the transformation anyway, here are a couple of hints
1) Use the JavaMetamodel (import Java namespaces rather than Ecore
ones). This will give you a lot more control over the Ecore artifacts -
not only the structural features but also the Java-Bean-Properties
2) If you cannot access the EClass Objects from Xtend directly, write an
Xtend-Function that delegates to Java.
3) AFAIK, there are a couple of ways to get the implementation body into
an EOperation, e.g. by an EAnnotation, using delegates or by just
manually adding them in the Java class and marking the method as not
@generated. The latter will not work with Xtext, as the Java classes are
completely wiped on each generation run. I'd recommend having a loog at
the
/org.eclipse.emf.mwe2.lib/src/org/eclipse/emf/mwe2/ecore/Eco reGenerator.java
from MWE, which is an alternative EcoreGeneratorFragment allowing to put
customizations (Java classes that extend the generated ones) at specific
locations and automatically dealing with adapting the factory.



Am 21.12.10 17:26, schrieb Pierre-Alain BOURDIL:
> Thanks for your answer,
> what i understood is that there's no easy way to add method using ecore
> inference postprocessing. Manually update the ecore mm, then using it as
> an imported mm prohibits evolution on this mm, thereby on my grammar,
> which is not possible for me at this time.
> Regarding type confusion, you're right, i was wondering if exists an
> easy way to reference dsl specific type within xpand context , because
> of my little knowledge of those tools.
> Now, if there' s no way to easily custom the generated interface using
> xtend, is there a way to generate a posteriori the source code for the
> method directly in the Interface and InterfaceImpl code, using xpand
> template or maybe atl transformation plugged using the MWE workflow ?
> Regards.


--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com


---
Get professional support from the Xtext committers at www.typefox.io
Re: How to add customized method to the xtext generated dsl interface [message #646902 is a reply to message #646122] Sun, 02 January 2011 21:06 Go to previous message
Pierre-Alain BOURDIL is currently offline Pierre-Alain BOURDILFriend
Messages: 25
Registered: September 2010
Junior Member
Greetings,

Thanks everyone for your answers, it helped so much. I finally found how to solve my problem, using xtend and postprocessing :

process(EClass this) :
	if this.name == 'Interface' then
	    addOperation(
                             "getOperations",
	        ePackage.getEClassifier("Operation"),
	        -1,
	         ' //JAVA CODE HERE' )->
	if this.name == 'Interface' then	
	     addOperation(
	         "getAttributes",
                               ePackage.getEClassifier("Attribute"),
                              -1,
                              '//JAVA CODE HERE'');
	
create ecore::EOperation addOperation(
    ecore::EClassifier c, String strName,
    ecore::EClassifier type,
    Integer upperBound,
    String strBody):
	setName(strName) ->
	setEType(type) -> 
	setUpperBound(upperBound)->
	addBodyAnnotation(strBody)->
	((ecore::EClass)c).eOperations.add(this);


create ecore::EAnnotation addBodyAnnotation(ecore::EOperation op, String strBody):
	setSource("http://www.eclipse.org/emf/2002/GenModel") ->
	this.createBody(strBody) ->
	op.eAnnotations.add(this);

create ecore::EStringToStringMapEntry createBody(ecore::EAnnotation anno, String strBody):
	setKey("body") ->
	setValue(strBody) ->
	anno.details.add(this);



The code above uses m2m Xtend capabilities, namely "create" operation. The createBody operation create the body of the operation using EAnnotation (key = body).

Two operations, getAttributes and getOperations, are added, using the chain expression. Their types are multi-valued, because of the -1 upper bound.

One problem was to reference dsl specific type within xpand context, and there is a very easy way to do that, provided by the ecore EMFMetaModel from Xtend :
ePackage.getEClassifier("Attribute"),

This expression returns the EClass "Attribute" generated by xtext.


Regards ,
Previous Topic:start mwe from maven?
Next Topic:creation of .chk files
Goto Forum:
  


Current Time: Fri Apr 26 02:55:47 GMT 2024

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

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

Back to the top