Jump to: navigation, search

VIATRA2/Native importer creation

Creating a VIATRA2 Importer for a Simple XML-based Language

Introduction

There is a third party editor given, which can export into an XML file. We need to represent this model in the VIATRA2/Model_Space. Native importers are used to create models in the model space of VIATRA2. This example shows how to build an importer that can instantiate a model in the model space based on a file.

There are two essential components of an importer:

  • A metamodel : The metamodel describes the language, which we want to create an importer for. The metamodel can be regarded as a representation of the language's abstract syntax.
  • An importer plug-in : This is the implementation of the importer. Its basic task is to explore the input file, and instantiate the elements of the metamodel accordingly.


Example: Car workflow

The example we would like to use as the pilot example is a workflow description language. A file describes the activities of drivers of cars in a scenario. So we have the participants (the drivers), and the timeline. This workflow however, does not cope with use decisions along the scenario, only a sequential execution of activities is possible extended with concurrency. Hence, it is basically an interval editor. Each interval represents an activity.


Fig.1 The graphical concrete syntax of the language.


Fig. 1 represents a possible graphical concrete syntax of the language.This example has two participants, John Doe and Jane Doe. They are having a chat conversation from 12:00 till 12:09. Meanwhile Jane listens to a song, and John goes on listening the radio.

Fig.2 The XML notation of the workflow.

The XML representation of the example workflow can be seen on Fig. 2. We have one <carworkflow> . The carworkflow describes the activities of the drivers of two <car>s. The <activity>(ie's) attributes also define the additional attributes.

File:Cwf xsd.png
Fig.3 The XSD Schema definition of the language.


Fig. 3 shows the XSD representation of the language. Based on the XSD definition of the language the metamodel can easily be written (See Fig.4).

Fig.4 The metamodel of the language in the syntax of the VIATRA2 Textualt Metamodeling Language.

The usual way of creating a metamodel based on an XSD schema: First complex types should be identified by entities in VIATRA2. For the representation of containment relations and cross references between XML tags we have multiple options. Here simple relations are only used. However, for the containment a good idea could be to derive them from a containment supertype. So to represent that a car workflow has cars as containmnet simply a relation is used. In this simple example attributes are similarly handled. The line relation(application,activity,String) indicates that an entity the type of whom is activity may have a reference to an application.

Please note the following:

  • In the metamodel attributes and containments are not distinguished. If it is needed however, many solutions exist. One possible is that we define two supertypes, one for the containment, the other for the attributes. In order to do that most probably, XML tags and attributes also need supertypes.
  • The names of entities are recommended to be identical with the names of the complex types in the Schema. The names of the relations should reflect the names of entities the actual complex type may contain. This makes the build of the importer easier, and more maintainable.


The Importer

Once the metamodel is ready, the importer has to be written. In order to write an importer the Eclipse extension point hu.bme.mit.viatra.core2.modelimport has to be extended. The extension point should refer to a class implementing the interface hu.bme.mit.viatra.imports.NativeImporter. The schema of the interface is the following:

 package hu.bme.mit.inf.hidenets.eval.plugin.carwfimporter;
 import java.io.InputStream;  
 import hu.bme.mit.viatra.errors.VPMRuntimeException;
 import hu.bme.mit.viatra.framework.IFramework;
 import hu.bme.mit.viatra.imports.NativeImporter;
  
 public class CarWorkflowImporter implements NativeImporter {
 
 	public void process(InputStream f, IFramework fw)
 			throws VPMRuntimeException {
 	}
 
 	public void processFile(String f, IFramework fw) 
                       throws VPMRuntimeException {
 	}
 }


The framework is going to call the method processFile. It is recommended to create an InputStream of the file and then call the process method. So the relevant part of the importer should be placed into the method process. The outline of an importer (the process method) like this:

Get the IModelManager interface like this: IModelManager mm = fw.getTopmodel().getModelManager();

Get the meta elements (elements of the viatra metamodel) from the modelspace: E.g.:IEntity META_car = mm.getEntityByName(<fully qualified name of the entity as string>) for all the entities. E.g.:IRelation META_car_activity = mm.getRelationByName(<fully qualified name of the relation>) for all the relations.

Explore the input model. E.g. make a DOM tree and do a depth first search. Every time an element is reached it has to be instantiated in the VIATRA2 model space also like this:

 
 IEntity vCar = mm.newEntity("car",value,vCarWorkflow);
 mm.newInstanceOf(META_car,vCar);
 

The first argument is the name of the entity in the modelspace. Most of the time irrelevant. value is a String which is going to be the value of the new entity. Presuming that the car workflow entity has already been instantiated,we give it as container.

VERY IMPORTANT: from the modeling point of view the container of the new entity is also irrelevant. Pattern matching for VIATRA2 containment is not recommended. Containment from the point of view of the model is going to be represented with the appropriate relations. The VIATRA2 containment helps to organize the model space so that it remains comprehensible. Also don't forget the second line: declare that the new entity has the type of car.

Now the relation has to be instantiated that represents the XML containment in our model:

 
 IRelation vCarWorkflow_car = mm.newRelation("carworkflow_car",vCarWorkflow,vCar);
 mm.newInstanceOf(META_CarWorkflow_car,vCarWorkflow_car);
 

Running these steps in a recursive manner is going to create a tree reflecting the XML tree.

However, in the XML there are usually crossreferences between the tags like the target attribute of the tag activity. There is another phase needed for resolving these after the containment tree is ready. The simplest way to do it is to put all entities into a HashMap with the key how they are referenced. When the references are resolved we just instantiate relations like the one above.

The Attached Source Code

The attached source code (click here) imports the above specified car workflow language. The importer code, the metamodel and an example VIATRA2 modelspace is attached. However, there are two differences to the above example:

  • The importer does not implement the NativeImporter interface, but the ASMNativeFunction. This means, that the importer is not going to be accessible from the native imports menu, but can be triggered from VTCL code as a native function.
  • The part of the importer that is responsible for building the container tree in the modelspace is generic. The metamodel elements are not obtained previously to the exploration of the input file. The type of the object to be instantiated is determined based on the name of the tag during exploration. This makes the size of this part independent of the input XML language.


Kovmate.gmail.com 09:54, 9 June 2008 (EDT)