Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "VIATRA2/API Example"

Line 33: Line 33:
  
 
==== Import model ====
 
==== Import model ====
 +
 +
Model importers correspond to file extensions but they also have a unique identifier as well. In the first case the extension based solution is shown, where importers for the "bpmn" extension are queried from the framework and the first of those is used for importing. In the second case, the unique identifier (given in it's extension point properties) of the importer is used. Further details on creating importers can be found on the [[VIATRA2/UseCases/ModelExportImport]] page.
  
 
<pre>
 
<pre>
Line 43: Line 45:
 
==== Load machine ====
 
==== Load machine ====
  
Simple
+
The simple way of loading a machine from a VTCL file is using the loadMachine function, where loaders are handled similarly to importers. The return value of the function is the Machine itself, although a class cast is required. Instead of casting, the machine can be queried from the framework using it's fully qualified name.
  
 
<pre>
 
<pre>
Line 51: Line 53:
 
</pre>
 
</pre>
  
Parser
+
However, the simple version can not be used when we would like to get information about the parsing, for examples errors existing in the transformation code, or missing metamodels from the modelspace. In order to access such information, the VTCLParserManager of the framework is used. You can create a ParseController using a VTCL file path string and then use the parseAndBuild method to parse it. After that, the existence of errors can be checked and the error information accessed. The reference to the parsed machine itself is also accessible from the ParseController.
  
 
<pre>
 
<pre>

Revision as of 11:25, 25 October 2010

VIATRA2 Java API example

The VIATRA2 model transformation framework provides an extensive API for performing the most frequently used tasks using Java method invocations instead of through the user interface. The basic steps are opening a model space, importing model instances, parsing and executing transformations and saving the results.

We've compiled an introductory example where all these steps are covered, the example can be downloaded from the VIATRA extras SVN repository here.

1. Set up the example

Check-out the api_example plugin from the SVN repository, along with the bpmn importer plugin (and of course the rest of the VIATRA framework either from SVN or the update site).

Apart from selecting the required plugins for the runtime Eclipse application configuration, you should add the "-console" argument to the arguments (in order to be able to start the execution).

Finally, the example uses files from the runtime workspace instead of the plugin bundle, so import the project into the runtime workspace as well (it should have the same name and contain at least the vpml, vtcl and input folders).

2. Execute example

After starting the Eclipse application, type "ss" into the osgi console (in the original Eclipse), find the "id" of the plugin (org.eclipse.viatra2.api_example) and type "start ID" (replace ID with the actual number, ie. 545). As a result, the example should run, putting some VIATRA2 specific output on the console, with a final line "This is a test output" generated by the transformation execution.

3. API example detailed

The whole API example can be found in the "Viatra2ApiExample.java" in the default package of the plugin, specifically in the "executeExample" method.

Open model space

In our example, we first create a new framework using the singleton framework manager. Then we use the mergeFile method of the IFramework to open a given model space stored in a file. Note that you can use the alternative createFramework(String fileName) method to perform the two operetions in one step.

// create framework
framework = FrameworkManager.getInstance().createFramework();
// parse vpml
framework.mergeFile(root + "/vpml/example.vpml");

Import model

Model importers correspond to file extensions but they also have a unique identifier as well. In the first case the extension based solution is shown, where importers for the "bpmn" extension are queried from the framework and the first of those is used for importing. In the second case, the unique identifier (given in it's extension point properties) of the importer is used. Further details on creating importers can be found on the VIATRA2/UseCases/ModelExportImport page.

// import model, root is the project location
framework.nativeImport(root + "/input/example.bpmn", framework.getNativeImportersForExtension("bpmn").iterator().next());
// alternative solution
framework.nativeImport(root + "/input/example.bpmn","org.eclipse.viatra2.imports.bpmn2");			

Load machine

The simple way of loading a machine from a VTCL file is using the loadMachine function, where loaders are handled similarly to importers. The return value of the function is the Machine itself, although a class cast is required. Instead of casting, the machine can be queried from the framework using it's fully qualified name.

// parse vtcl
Machine machine = (Machine) framework.loadMachine(root + "/vtcl/example.vtcl", framework.getLoadersForExtension("vtcl").iterator().next());
//Machine machine = (Machine) framework.getMachineByFQN("example");

However, the simple version can not be used when we would like to get information about the parsing, for examples errors existing in the transformation code, or missing metamodels from the modelspace. In order to access such information, the VTCLParserManager of the framework is used. You can create a ParseController using a VTCL file path string and then use the parseAndBuild method to parse it. After that, the existence of errors can be checked and the error information accessed. The reference to the parsed machine itself is also accessible from the ParseController.

VTCLParserManager pm  = (VTCLParserManager)framework.getVTCLParserManager();
String vtclFileName = root + "/vtcl/example.vtcl";
VTCLParseController pc = pm.lookupAndCreateParseController(vtclFileName);
pc.parseAndBuild();

if(pc.hasErrors()){
  List<ErrorInformation> errors = pc.getErrors();
  for (ErrorInformation errorInformation : errors) {
    System.err.println(errorInformation.getMessageWithLocation());
  }
}
else{
  machine = pc.getMachine();
}	

Running transformation and transaction management

//parameters
Map<String, Object> params = new HashMap<String, Object>();
params.put("TestParam", "example.model.testModel");
// run transformation
framework.runEntrypoint(machine, params, new IProgressReport() {
  @Override
  public void progress(int indicator) {}
});
// start transaction
String transID = framework.getTopmodel().getTransactionManager().beginTransaction();
// abort transaction (during execution, not recommended)
// closes transaction and tries compensation
framework.getTopmodel().getTransactionManager().abortTransaction();
// commit transaction if OK
framework.getTopmodel().getTransactionManager().commitTransaction();
// undo otherwise (used later)
// reverts all the modifications _after_ the beginning of the transaction
framework.getTopmodel().getTransactionManager().undoTransaction(transID);
					

Accessing the transformation output

// prepare output reading
CodeOutputPlugin cop = new CodeOutputPlugin() {
  @Override
  public void init(IFramework fw) {
    // recives FW reference for optional usage
  }
  @Override
  public void beginWork() {
    // call-back called at the beginning of the transformation execution
  }
  @Override
    public void codeOut(String s) throws VPMRuntimeException {
      // called for every print() and println() rule invocation from VTCL
      // does not support buffers
  }
  @Override
  public void endWork() {
    // call-back called at the end of the transformation execution
  }
};
// event-driven approach (even during transformation execution)
framework.addCodeOutListener(cop);

// buffer access after transformation execution
// use core:// mainly
StringWriter bufsw = (StringWriter) BufferStore.getBuffer(framework.getTopmodel(), "core://example");
// access actual content of the buffer
System.out.println(bufsw.getBuffer().toString());

Saving the modelspace and cleanup

// save workspace
framework.saveFile(root + "/vpml/example_save.vpml");
// cleanup
framework.removeCodeOutListener(cop);
FrameworkManager.getInstance().disposeFramework(framework.getId());

Back to the top