Construct models programmatically but manipulate them with Epsilon [message #1857254] |
Thu, 26 January 2023 18:18 |
Théo Giraudet Messages: 9 Registered: January 2021 |
Junior Member |
|
|
Hello,
Firstly, thanks for the great documentation available, it is really helpful!
I've looked through it a bit and I think Eclipse Epsilon is perfect for my own project but I'm having a little trouble getting started.
Firstly:
- I want to use Eclipse Epsilon outside from Eclipse IDE
- I use EMF (but I'm not very good with it yet)
- I use Maven
- I want to do transformations and model to text later but I will not detail that here because I think these parts are sufficiently documented
I have created a tiny metamodel with EMFatic and I see thanks to the documentation how to use it with Eclipse Epsilon, through Maven.
But in my case, my models have do be built during runtime because the information to create them comes from several external sources.
In the website, I found that I can load metamodel and model in a programmatically way (here) but if I understand well I have to load them at the same time and from files in the filesystem.
As I have to build my model with Java code, it is better for me to have my metamodel as java classes. My first question is:
- Is it possible to generate from EMFatic the classes for the metamodel in the same way I can with EMF and ecore/genmodel files? If yes, is it possible to trigger the generation in a Maven phase?
That done, I will have my metamodel and models loaded with EMF. Can I use them with Eclipse Epsilon without have to load a file as I found on the website?
Thank you in advance for your help!
|
|
|
Re: Construct models programmatically but manipulate them with Epsilon [message #1857257 is a reply to message #1857254] |
Thu, 26 January 2023 20:15 |
|
Hi,
I am a bit confused of what you actually want to achieve. So some questions and answers.
Are your metamodels generated programmatically (i.e. at runtime?).
- If not (that is, you have the metamodels at build time - as I understand) I would suggest creating the Genmodels for them, generate your code and add it to version control.
- If yes, the genmodel (afaik) is not designed to be run outside eclipse, so you would probably need to run it inside a headless eclipse, from an Ant script and call that ant from maven. See some ideas here.
When you pass the metamodel and model file to an EmfModel and then call what Epsilon does is what you are doing, i.e. load the metamodel and model via EMF. If you look at the EmfModel API, there is a setResoruce method. You can use that method to assign the resource you loaded via EMF. With this approach, you should also skip the load call.
Resoruce r = yourEmfLoadMethod();
EmfModel model = new EmfModel();
model.setName("M");
model.setStoredOnDisposal(true);
model.setResource(r);
// Parses and executes the EOL program
EolModule module = new EolModule();
module.parse(new File("program.eol"));
// Makes the model accessible from the program
module.getContext().getModelRepository().addModel(model);
module.execute();
Horacio Hoyos Rodriguez
Kinori Tech
Need professional support for Epsilon, EMF?
Go to: https://kinori.tech
[Updated on: Thu, 26 January 2023 20:22] Report message to a moderator
|
|
|
|
|
|
Re: Construct models programmatically but manipulate them with Epsilon [message #1857419 is a reply to message #1857297] |
Mon, 06 February 2023 19:12 |
Théo Giraudet Messages: 9 Registered: January 2021 |
Junior Member |
|
|
Hello,
Finally, I chose to use XCore to create my metamodels because I can generate my Java classes by using Maven.
Now I try to do my transformation. I have two metamodels A and B and one instance of A named a. I want to get an instance of B b resulting of the transformation of a using model_transformation.etl.
I search on Internet to see if there are examples to do that but I didn't find any solution working for me...
All the code can be find here.
My Metamodels:
(A.xcore)
@GenModel(
bundleManifest="false",
modelDirectory="src/main/java-gen",
complianceLevel="17"
)
package fr.theogiraudet.test.a
class A {
String name
}
(B.xcore)
@GenModel(
bundleManifest="false",
modelDirectory="src/main/java-gen",
complianceLevel="17"
)
package fr.theogiraudet.test.a
class A {
String name
}
(model_transformation.etl)
rule A2B
transform a : A!A
to b : B!B {
a.name = b.name;
}
And finally, the code to apply programmatically the transformation:
public class Main {
private static Logger logger = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) throws Exception {
final A model = AFactory.eINSTANCE.createA();
ResourceSet rs = new ResourceSetImpl();
rs.getPackageRegistry().put(APackage.eNS_URI, APackage.eINSTANCE);
rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("a", new EcoreResourceFactoryImpl());
rs.getPackageRegistry().put(BPackage.eNS_URI, BPackage.eINSTANCE);
rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("b", new EcoreResourceFactoryImpl());
final Resource fooResource = createResource(model, "foo.a", rs);
final EmfModel fooModel = createModel(fooResource, "foo.a");
final EmfModel aMetaModel = createModel(APackage.eINSTANCE.eResource(), "A");
final EmfModel bMetaModel = createModel(BPackage.eINSTANCE.eResource(), "B");
EtlModule module = new EtlModule();
module.getContext().setModule(module);
module.parse(Main.class.getClassLoader().getResource("transformation/model_transformation.etl"));
module.getContext().getModelRepository().addModel(aMetaModel);
module.getContext().getModelRepository().addModel(bMetaModel);
module.getContext().getModelRepository().addModel(fooModel);
module.getContext().setTransformationStrategy(new DefaultTransformationStrategy());
var result = module.execute();
System.out.println();
}
public static Resource createResource(EObject model, String name, ResourceSet set) throws IOException {
var uri = URI.createURI("https:///www.theogiraudet.fr/test/schemas/" + name);
var resource = set.createResource(uri);
resource.getContents().add(model);
resource.load(Map.of());
return resource;
}
public static EmfModel createModel(Resource resource, String name) {
final InMemoryEmfModel model = new InMemoryEmfModel(resource);
model.setName(name);
return model;
}
I guess result must be is (or wraps) my instance of B but the result is of type TransformationTrace and these attributes (cache and transformations) are totally empty...
Thank you in advance for your help!
[Updated on: Mon, 06 February 2023 19:26] Report message to a moderator
|
|
|
|
Re: Construct models programmatically but manipulate them with Epsilon [message #1857440 is a reply to message #1857420] |
Tue, 07 February 2023 19:55 |
Théo Giraudet Messages: 9 Registered: January 2021 |
Junior Member |
|
|
Thank you really much for your pull request. Last question I have (I hope) about that is that I need to inject my model `a`. In your commit, you create instance directly from the EmfModel. I see I can use the `setResource` as I have done in the first version of my minimal project but when I am trying, I have or an empty array for result (if I put the instruction before the load) or even an exception "Exception in thread "main" Type 'A!A' not found" (if after the load).
How can I do that?
[Updated on: Tue, 07 February 2023 19:58] Report message to a moderator
|
|
|
Re: Construct models programmatically but manipulate them with Epsilon [message #1857441 is a reply to message #1857440] |
Tue, 07 February 2023 22:41 |
|
Hi Theo,
Replacing the following lines
// The source model of the transformation
EmfModel sourceModel = new EmfModel();
sourceModel.setName("A");
sourceModel.setReadOnLoad(false); // As the model doesn't exist
sourceModel.setStoredOnDisposal(false); // We don't want to store the source model
sourceModel.setModelFileUri(URI.createFileURI("foo.a"));
sourceModel.setMetamodelUri(APackage.eNS_URI);
sourceModel.load();
with
// The source model of the transformation
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getPackageRegistry().put(APackage.eNS_URI, APackage.eINSTANCE);
Resource resource = resourceSet.createResource(URI.createFileURI("foo.a"));
InMemoryEmfModel sourceModel = new InMemoryEmfModel("A", resource);
should do the trick.
Thanks,
Dimitris
[Updated on: Tue, 07 February 2023 22:42] Report message to a moderator
|
|
|
|
Powered by
FUDForum. Page generated in 0.03661 seconds