Meshing ACCELEO and Xtext [message #901948] |
Wed, 15 August 2012 09:08  |
|
I am in the middle of an ACCELEO Transformation aimed at producing code (i.e. Java) from an input UML model.
Some elements of this UML model (i.e. Activities Opaque actions) contain some text which is conform to an Xtext grammar and I'd like to get the equivalent AST Ecore representation in the ACCELEO transformation.
To this end I have developed a Java class with a method which takes as input a string, containing the DSL excerpt, and produces an ECORE model conform to it (see http://www.eclipse.org/forums/index.php/m/901947/#msg_901947 for further details). I have tested it in a separate Java application and it seems it works properly.
I have therefore written a simple ACCELEO module (i.e. getDSLModel) wrapping that java class and enabling me to get the Ecore model from the DSL textual representation.
Suppose my DSL (and the equivalent ECORE) consist of a root element named DSLModel containing a (0..*) number of DSLStatements (this is a simplification).
When in ACCELEO I invoke the wrapper from a string, containing a correct dsl script, i have noticed it correctly returns a ModelImpl
['statement1;statement2'.getDSLModel()/]
so the Java service and the XText parse is working.
However if I try to get the model statements, i.e.:
['statement1;statement2'.getDSLModel().statements/]
it returns an **"invalid"** string. So I can't use it in a for loop
I have therefore tried to call the eAllContents() ocl service from the model instance i.e.:
['statement1;statement2'.getDSLModel().eAllContents()/]
and it actually returns the list of statements. I do not understand why the features of the Ecore entities returned from the Xtext parser are not working properly.
Any help would be very appreciated! Thank you
here is the Java service which turns a string into a instance of my DSL model (ECORE AST). I have tested it with an independent Java application and it works fine!
public class GetDSLModel {
public DSLModel getDSLModel(String expression){
DSLStandaloneSetupGenerated dslsas = new DSLStandaloneSetupGenerated();
Injector injector = dslsas.createInjectorAndDoEMFRegistration();
XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
Resource resource = resourceSet.createResource(URI.createURI("dummy:/example.dsl"));
InputStream in = new ByteArrayInputStream(expression.getBytes());
try {
resource.load(in, resourceSet.getLoadOptions());
DSLModel model = (DSLModel) resource.getContents().get(0);
return model;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
Now I need the AST in the main ACCELEO (UML2Text) transformation thus here is the Acceleo wrapper
[query public getDSLModel(str:String): DSLModel = (invoke('sfg.baleno.src.mloaders.GetDSLModel','getDSLModel(java.lang.String)',Sequence{str})).oclAsType(DSLModel)/]
here is what I get if run it
input: ['statement1;statement2'.getDSLModel()/]
output: mypackage.dsl.impl.DSLModelImpl@a1c7a
input: ['statement1;statement2'.getDSLModel().statements/] (Syntactically VALID)
output: invalid
input: ['statement1;statement2'.getDSLModel().eAllContents()/]
output: mypackage.dsl.impl.DSLStatement@e53202 (......
Follow me on Twitter @andreasindico
[Updated on: Wed, 15 August 2012 16:15] Report message to a moderator
|
|
|
|
|
|
|
Re: Meshing ACCELEO and Xtext [message #902084 is a reply to message #902072] |
Wed, 15 August 2012 19:01   |
|
Ok I have changed the Java service this way:
public class GetDSLModel {
public DSLModel getDSLModel(String expression){
DSLStandaloneSetupGenerated dslsas = new DSLStandaloneSetupGenerated();
Injector injector = dslsas.createInjectorAndDoEMFRegistration();
XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
EcoreUtil.resolveAll(resourceSet);
Resource resource = resourceSet.createResource(URI.createURI("dummy:/example.dsl"));
InputStream in = new ByteArrayInputStream(expression.getBytes());
try {
resource.load(in, resourceSet.getLoadOptions());
DSLModel model = (DSLModel) resource.getContents().get(0);
EcoreUtil.resolveAll(model);
return model;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
It still works when invoked from another Java class but it still outputs invalid in Acceleo
Follow me on Twitter @andreasindico
|
|
|
|
Re: Meshing ACCELEO and Xtext [message #902111 is a reply to message #902092] |
Wed, 15 August 2012 22:02   |
|
Ok now the Java code looks like this
public class GetDSLModel {
public DSLModel getDSLModel(String expression){
DSLStandaloneSetup.doSetup();
DSLStandaloneSetupGenerated dslsas = new DSLStandaloneSetupGenerated();
Injector injector = dslsas.createInjectorAndDoEMFRegistration();
XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
EcoreUtil.resolveAll(resourceSet);
Resource resource = resourceSet.createResource(URI.createURI("dummy:/example.dsl"));
InputStream in = new ByteArrayInputStream(expression.getBytes());
try {
resource.load(in, resourceSet.getLoadOptions());
DSLModel model = (DSLModel) resource.getContents().get(0);
EcoreUtil.resolveAll(model);
return model;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
unfortunally it behaves the same. It works when executed from another java class but "it doesn't" when invoked from Acceleo
Follow me on Twitter @andreasindico
|
|
|
|
Re: Meshing ACCELEO and Xtext [message #902130 is a reply to message #902122] |
Thu, 16 August 2012 05:47   |
|
Hi Ed, where are those comments in Acceleo? And how should I invoke the StandaloneSetup.doSetup() in Acceleo, by means of a different wrapper?
Anyway I have also tried to rearrange the code this way:
public class GetDSLModel {
public DSLModel getDSLModel(String expression){
DSLStandaloneSetup.doSetup();
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
EcoreUtil.resolveAll(resourceSet);
Resource resource = resourceSet.createResource(URI.createURI("dummy:/example.dsl"));
InputStream in = new ByteArrayInputStream(expression.getBytes());
try {
resource.load(in, resourceSet.getLoadOptions());
DSLModel model = (DSLModel) resource.getContents().get(0);
EcoreUtil.resolveAll(model);
return model;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
different code same behavior. It works fine when invoked from a different java class but when invoked from Acceleo, though I see it returns correct ClassImpl instances they are apparently not properly turned into the equivalent ECORE entities.
thank you for your kind help
Follow me on Twitter @andreasindico
[Updated on: Thu, 16 August 2012 05:49] Report message to a moderator
|
|
|
Re: Meshing ACCELEO and Xtext [message #902139 is a reply to message #902130] |
Thu, 16 August 2012 06:16   |
Ed Willink Messages: 7594 Registered: July 2009 |
Senior Member |
|
|
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">Hi<br>
<br>
You provide one erroneous class and expect help.<br>
<br>
I've no idea what it does, but it seems all wrong so just delete
it. Why would you expect your ResourceSet to coexist with
Acceleo's and Xtext's?<br>
<br>
Acceleo generates a Java file for your main template. That file is
full of comments about how to make it work standalone. Try reading
them.<br>
<br>
From the Acceleo documentation:<br>
<br>
<h3>Package registration</h3>
<p> You need to register the package that contains your
classifiers, in order to use it inside of your generator. To do
this, have a look at the method named "registerPackages" in the
Java launcher generated next to your main module. You need to
add the following piece of code: </p>
<pre> /**
* @generated NOT
*/
public void registerPackages(ResourceSet resourceSet) {
super.registerPackages(resourceSet);
if (!isInWorkspace(MyPackage.class)) {
resourceSet.getPackageRegistry().put(MyPackage.eINSTANCE.getNsURI(), MyPackage.eINSTANCE);
}
}
</pre>
<p> The "@generated NOT" tag in the Javadoc is necessary to
prevent the removal of your modification. Once the package is
registered, Acceleo can use EMF to load your input model. If
this does not work, you will see an error message stating that
EMF cannot find the package with the uri "<metamodel_uri>". </metamodel_uri></p>
This is where you can put DSLStandaloneSetup.doSetup();<br>
<br>
If you're paranoid about double initialization you can do:<br>
<br>
@Override<br>
public void initialize(EObject element, File folder, List<?
extends Object> arguments) throws IOException {<br>
preInitialize();<br>
super.initialize(element, folder, arguments);<br>
}<br>
<br>
@Override<br>
public void initialize(URI modelURI, File folder,
List<?> arguments) throws IOException {<br>
preInitialize();<br>
super.initialize(modelURI, folder, arguments);<br>
}<br>
<br>
protected void preInitialize() {<br>
DSLStandaloneSetup.doSetup();<br>
}<br>
<br>
or<br>
<br>
static {<br>
if (!EMFPlugin.IS_ECLIPSE_RUNNING) {<br>
DSLStandaloneSetup.doSetup();<br>
}<br>
}<br>
<br>
Regards<br>
<br>
Ed Willink<br>
<br>
On 16/08/2012 06:47, Andrea Sindico wrote:<br>
</div>
<blockquote cite="mid:k0i1i2$iv5$1@xxxxxxxxe.org" type="cite">Hi
Ed, where are those comments in Acceleo? And how should I invoke
the StandaloneSetup.doSetup() in Acceleo, by means of a different
wrapper?
<br>
Anyway I have also tried to rearrange the code this way:
<br>
<br>
<br>
public class GetDSLModel {
<br>
public DSLModel getDSLModel(String expression){
<br>
DSLStandaloneSetup.doSetup(); <br>
ResourceSet resourceSet = new ResourceSetImpl();
<br>
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL,
Boolean.TRUE);
<br>
EcoreUtil.resolveAll(resourceSet);
<br>
Resource resource =
resourceSet.createResource(URI.createURI("dummy:/example.dsl"));
<br>
InputStream in = new
ByteArrayInputStream(expression.getBytes());
<br>
try {
<br>
resource.load(in, resourceSet.getLoadOptions());
<br>
DSLModel model = (DSLModel)
resource.getContents().get(0);
<br>
EcoreUtil.resolveAll(model);
<br>
return model;
<br>
} catch (IOException e) {
<br>
// TODO Auto-generated catch block
<br>
e.printStackTrace();
<br>
}
<br>
return null;
<br>
<br>
}
<br>
<br>
}
<br>
<br>
<br>
<br>
different code same behavior. It works fine when invoked from a
different java class but when invoked from Acceleo, though I see
it returns correct ClassImpl instances they are apparently not
properly turned into the equivalent ECORE entities.
<br>
</blockquote>
<br>
</body>
</html>
|
|
|
Re: Meshing ACCELEO and Xtext [message #902173 is a reply to message #902139] |
Thu, 16 August 2012 08:43   |
|
Ed I have added these lines to the Acceleo main module Java class:
@Override
public void initialize(EObject element, File folder, java.util.List<? extends Object> arguments) throws IOException { preInitialize();
super.initialize(element, folder, arguments);
}
@Override
public void initialize(URI modelURI, File folder, java.util.List<?> arguments) throws IOException {
preInitialize();
super.initialize(modelURI, folder, arguments);
}
protected void preInitialize() {
DSLStandaloneSetup.doSetup();
}
and
@Override
public void registerPackages(ResourceSet resourceSet) {
super.registerPackages(resourceSet);
if (!isInWorkspace(org.eclipse.uml2.uml.UMLPackage.class)) {
resourceSet.getPackageRegistry().put(org.eclipse.uml2.uml.UMLPackage.eINSTANCE.getNsURI(), org.eclipse.uml2.uml.UMLPackage.eINSTANCE);
}
if (!isInWorkspace(mypackages.DSLPackage.class)) {
resourceSet.getPackageRegistry().put(mypackages.DSLPackage.eINSTANCE.getNsURI(), mypackages.DSLPackage.eINSTANCE);
}
but I still experience the same problem.
I have however noticed something new that I guess may help to understand the problem.
If I try this let:
[let dm:DSLModel = 'statement1;statement2;'.getDSLModel().oclAsType(DSLModel)]
I get this warning:
Undefined "Let" expression at line xx in Module ww for block let dm : DSLModel = getDSLModel('statement1;statement2').oclAsType(dsl::DSLModel). Last recorded value of self was org.eclipse.uml2.uml.internal.impl.ClassImpl@96f20a
Follow me on Twitter @andreasindico
|
|
|
Re: Meshing ACCELEO and Xtext [message #902176 is a reply to message #902173] |
Thu, 16 August 2012 08:48   |
Ed Willink Messages: 7594 Registered: July 2009 |
Senior Member |
|
|
Hi
The error means that
'statement1;statement2;'.getDSLModel().oclAsType(DSLModel)
evaluated to invalid so you can debug that with a breakpoint in
getDSLModel().
Regards
Ed Willink
On 16/08/2012 09:43, Andrea Sindico wrote:
> Ed I have added these lines to the Acceleo main module Java class:
>
>
> @Override
> public void initialize(EObject element, File folder,
> java.util.List<? extends Object> arguments) throws IOException {
> preInitialize();
> super.initialize(element, folder, arguments);
> }
> @Override
> public void initialize(URI modelURI, File folder, java.util.List<?>
> arguments) throws IOException {
> preInitialize();
> super.initialize(modelURI, folder, arguments);
> }
> protected void preInitialize() {
> DSLStandaloneSetup.doSetup();
> }
>
>
> and
>
>
> @Override
> public void registerPackages(ResourceSet resourceSet) {
> super.registerPackages(resourceSet);
> if (!isInWorkspace(org.eclipse.uml2.uml.UMLPackage.class)) {
> resourceSet.getPackageRegistry().put(org.eclipse.uml2.uml.UMLPackage.eINSTANCE.getNsURI(),
> org.eclipse.uml2.uml.UMLPackage.eINSTANCE);
> }
> if (!isInWorkspace(mypackages.DSLPackage.class)) {
> resourceSet.getPackageRegistry().put(mypackages.DSLPackage.eINSTANCE.getNsURI(),
> mypackages.DSLPackage.eINSTANCE);
> }
>
>
> but I still experience the same problem.
>
> I have however noticed something new that I guess may help to
> understand the problem. If I try this let:
>
>
> [let dm:DSLModel =
> 'statement1;statement2;'.getDSLModel().oclAsType(DSLModel)]
>
>
> I get this warning:
>
> Undefined "Let" expression at line xx in Module ww for block let dm :
> DSLModel =
> getDSLModel('statement1;statement2').oclAsType(dsl::DSLModel). Last
> recorded value of self was
> mailto:org.eclipse.uml2.uml.internal.impl.ClassImpl@96f20a
>
>
>
|
|
|
|
|
|
Re: Meshing ACCELEO and Xtext [message #902400 is a reply to message #901948] |
Fri, 17 August 2012 13:16   |
|
May the problem be I am actually using two different resource sets (one in the Acceleo module Java class and one in the XText Java service)? If so what is the right way to make the Java service retrieve the Acceleo resource set?
Follow me on Twitter @andreasindico
|
|
|
|
Re: Meshing ACCELEO and Xtext [message #902452 is a reply to message #902403] |
Fri, 17 August 2012 16:13   |
|
Hi Ed,
In the Acceleo terminlogy a service is a Java class implementing some "complex" operation wrapped by an acceleo module. In this case I meant the java class transforming a string with a DSL into an Ecore AST by means of XText.
To quickly if the problem was due to the resource set just to check I have added a static ReousceSet variable to the main acceleo module java class. I have therefore retrieved that from the XText java service and used that instead of instantiating a new one. Unfortunately it still behaves the same Acceleo does not seem to associate the implementation to the related ECORE.
while trying I have however noticed a weird thing I don't know if it could clarify or create more confusion. It happens that sometimes when I launch the Eclipse environment (but not every time I do that!) and run the acceleo transformation it properly manages the model elements retrieved from the Java XText service. It thus works. However as soon as I slightly change the code (i.e. add another tag) it stops working again.
Again thanks for your help
Regards
Follow me on Twitter @andreasindico
|
|
|
|
Powered by
FUDForum. Page generated in 0.02966 seconds