2

I'd like to load 2 different input models (a .bpel and a .wsdl) in my main template of Acceleo.

I loaded the ecore metamodels for both bpel and wsdl and I'd like to be able to use something like this:

[comment encoding = UTF-8 /]
[module generate('http:///org/eclipse/bpel/model/bpel.ecore','http://www.eclipse.org/wsdl/2003/WSDL')/]

[import org::eclipse::acceleo::module::sample::files::processJavaFile /]

[template public generate(aProcess : Process, aDefinition : Definition)]
[comment @main /]
    Process Name : [aProcess.name/]
    Def Location : [aDefinition.location/]  

[/template]

but when I run the acceleo template I get this error:

An internal error occurred during: "Launching Generate".
Could not find public template generate in module generate.

I think I have to modify the java launcher (generate.java) because right now it can't take 2 models as arguments. Do you know how? Thanks!

** EDIT from Kellindil suggestions:

Just to know if I understood it right, before I get to modify stuff: I'm trying to modify the Generate() constructor. I changed it in:

//MODIFIED CODE
public Generate(URI modelURI, URI modelURI2, File targetFolder, 
                List<? extends Object> arguments) {
initialize(modelURI, targetFolder, arguments);
}

In the generic case, I can see it calls the AbstractAcceleoGenerator.initialize(URI, File, List>?>), shall I call it twice, once per each model? like:

initialize(modelURI, targetFolder, arguments);
initialize(modelURI2, targetFolder, arguments);

Then, to mimic in my Generate() constructor the code that is in the super-implementation:

//NON MODIFIED ACCELEO CODE 
Map<String, String> AbstractAcceleoLauncher.generate(Monitor monitor) {
File target = getTargetFolder();
if (!target.exists() && !target.mkdirs()) {
        throw new IOException("target directory " + target + " couldn't be   created."); //$NON-NLS-1$ //$NON-NLS-2$
    }
    AcceleoService service = createAcceleoService();
    String[] templateNames = getTemplateNames();
    Map<String, String> result = new HashMap<String, String>();
    for (int i = 0; i < templateNames.length; i++) {
        result.putAll(service.doGenerate(getModule(), templateNames[i], getModel(), getArguments(),
                target, monitor));
    }

    postGenerate(getModule().eResource().getResourceSet());
    originalResources.clear();

    return result;
}

what shall I do? Shall I try to mimic what this method is doing in my Generate() constructor after the initialize() calls?

AxA
  • 319
  • 5
  • 18

2 Answers2

3

What you wish to do is indeed possible with Acceleo, but it is not the "default" case that the generated launcher expects.

You'll have to mark the "generate" method of the generated java class as "@generated NOT" (or remove the "@generated" annotation from its javadoc altogether). In this method, what you need to do is mimic the behavior of the super-implementation (in AbstractAcceleoLauncher) does, loading two models instead of one and passing them on to AcceleoService#doGenerate.

In other words, you will need to look at the API Acceleo provides to generate code, and use it in the way that fits your need. Our generated java launcher and the AcceleoService class are there to provide an example that fits the general use case. Changing the behavior can be done by following these samples.

Kellindil
  • 4,523
  • 21
  • 20
  • I'm not sure I'll be able to dig into this as I'm short on time, but I got the idea. I managed to split my transformation in two smaller transformations and avoided this problem. Thanks for the hints Kellindll. – AxA Aug 07 '12 at 06:59
  • Hi Kellindil, I edited the question, as I might try to do what you suggested me, I'm just not sure anymore if I understood it right, could you have a look? Thanks – AxA Aug 08 '12 at 09:56
  • 1
    No, you will have to change everything that takes the input model and re-write the implementations to take the second model into account. In the "initialize" method, you will need to load the second model in the same resource set as the first. Then, in the "generate" method, you need to change the call to "service.doGenerate" into calls to "doGenerateTemplate" with an argument list that takes boths of your models. What you really need to mimic is this "AcceleoService#doGenerate" method. This is no trivial task. – Kellindil Aug 09 '12 at 09:45
  • I see it's not as easy as I thought, and for my purpose I think I need even more than 2 models. I'll get back here if I'll have time to dig in this. – AxA Aug 13 '12 at 09:28
0

You should'nt need to modify the Generate.java class. By default, it should allow you to perform the code generation.

You need to create a launch config and provide the right arguments (process and definition) in this launch config, that's all.

I don't understand the 'client.xmi' URI that is the 1st argument of your module. It looks like it is your model file, if so remove it from the arguments, which must only contain your metamodels URIs.

Laurent
  • 186
  • 2
  • Hi Laurent,
    in the arguments of the launch configuration, 2 arguments are automatically filled by Acceleo (see image link I added): 1) the INPUT model : SimpleProcess.BPEL (from which I get the root element aProcess : Process ) 2) the OUTPUT folder: ...bpel2java/uni What I'd like to add is another input model 3) 2nd INPUT model: SimpleProcessArtifacts.WSDL (from which I'd like to get a different root element, aDefinition : Definition or aMessage : Message) Shall I just add a third argument in the "Program arguments" tab with the path of my 2nd model? PS: I fixed the client.xmi URI
    – AxA Aug 04 '12 at 11:53