Today, Wolfgang Kling talks about MoScript, a new textual DSL to write model manipulation scripts. This work has been done in collaboration with Frédéric Jouault, Dennis Wagelaar, Marco Brambilla and myself and recently presented at the SLE’11 conference (clicke here to get the full paper).

Enter Wolfgang:

In this post we are going to present MoScript, a textual DSL for modelling tasks and workflow automation we just presented at SLE2011. Before entering in details of the DSL lets check the key points of the context and the problematic of this work.

As Model-Driven Engineering (MDE) methods and tools are maturing and becoming more popular, the number of modelling artefacts consumed and produced by software engineering processes (e.g., models, metamodels, and transformations) has been increasing considerably. For instance, in the model driven development of a system, every artefact (e.g. requirements specifications, analysis and design documents, implementation artefacts, etc.,) becomes a model.

Considering big and complex systems, performing common modelling tasks like browsing the models repositories, searching, inspecting and transforming models interactively is not feasible anymore. We need ways to perform these tasks in batch, but more important than that, we need ways to perform them according to how are the models arranged in the models repository. For instance, if we change a requirements model, we will need to re-execute all the transformations that use the model and also the transformations that use the output of the former transformations and so on until the final transformations that generate the code, in order to leave the system consistent again.

In order to do that, we need a global view of the repository, which represents all the artefacts of the repository and how are they related between them and also a scripting language capable of operating on top of this view enabling us to automate common modelling tasks.

The mentioned global view is what has been called a megamodel. A megamodel is a regular model whose elements represent the models stored in a repository and the relations between them. In other words, the megamodel contains the metadata that describe the model repository. The following picture is a graphical representation of a megamodel and the repository it describes.

In the picture, an element reference is a normal reference between model elements and a model reference is a kind of symbolic link between the model element and the physical storage of that same element.

To tame this complexity of modeling artifacts, we have created  MoScript, a megamodel-based scripting DSL for modelling tasks and workflow automation that uses OCL as base query language. With MoScript, users can write scripts containing queries (based on model content, structure, relationships, and behaviour derived through on-the-fly simulation) to retrieve models from model repositories, manipulate them (e.g., by running transformations on sets of models), and store them back in the repository.

MoScript provides a set of operations that allows you to inspect the content of the models by dereferencing the symbolic links the megamodel elements contain, and also operations to execute model-to-model transformations, model-to-text and text-to-model transformations.

Before showing some examples of MoScript scripts, we need to explain the meaning of the most important artefacts a megamodel can contain to represent a MDE project:

  • Terminal Model: A model to which no model can conform.
  • Metamodel: A model to which Terminal Models conform.
  • Metametamodel: A model to which other Metamodels conform.
  • Reference Model: A model to which other models conform. A Metamodel and a Metametamodel are both reference models.
  • Model: Any artefact that conforms to a well-defined grammar. Reference Models and Terminal Models are models.
  • Transformation Model: A model that represents and thus contains the source code of a transformation.
  • Transformation: A relation that associates a Transformation Model and its source and target Reference Models.
  • Transformation Record: A relation that associates a Transformation with its input and output Models

All these elements can be retrieved and manipulated using MoScript. Let’s see some examples (they are very simple but they give us an idea of the power of the language; for more complex ones please refer to the full paper of this work)

Example 1

Suppose you need to find the metamodels with less than 20 class elements in a repository of thousands of models (where clearly a manual examination of each model is not feasible) . Assuming that the repository contains only Ecore metamodels, the simple MoScript query to do it is the following.

 

1

2

Metamodel::allInstances()

−>select(mm | mm.allContentInstancesOf(‘EClass’)->size() < 20)

 

Line 1 retrieves all the instances of metamodel elements from the megamodel, then, in line 2, each metamodel is inspected by retrieving all its elements of type EClass in a collection, and checking the size of the set. How does this work?:  when the metamodel elements are selected, what we get is just metadata representing the physical metamodels of the repository. Instead, when the operation allContentInstancesOf is invoked the physical metamodel described by the metadata is dereferenced and loaded and thus it can now be manipulated in the rest of the script. MoScript also loads the reference model to which the metamodel conforms (in this case the Ecore metametamodel) to be able to inspect the metamodels.

Example 2

Suppose we want to regenerate our Java systems in .NET.  Assuming that we already have a transformation java2dNet, we may want to apply this transformation to all java models in our repository to generate all the corresponding .NET models. The following code shows how MoScript could do that.

 

 

1

2

3

4

5

6

7

 

 

let javaModels : Collection(Model) = Model::allInstances()

−>select(m | m.conformsTo.kind = ‘Java’) in

 

let java2dNet : Transformation = Transformation::allInstances()

−>any(t | t.identifier = ’java2dNet’) in

javaModels->collect(jm | java2dNet.applyTo(Sequence{jm}))

In lines 1 and 2 the set of models conforming to the java metamodel are retrieved from the repository. In lines 4 and 5 the transformation java2Net is also retrieved from the repository. In line 7 the java2Net transformation is applied to each java model by means of the applyTo operation. The result of this example is a collection of TransformationRecord elements, which contain the newly produced .Net models.

Behind the scenes, MoScript makes a type checking between the metamodels of the models to be transformed and the metamodels compatibles with the transformation, by querying the megamodel. In the same way MoScript determines which transformation engine should execute the transformation. Finally MoScript sends the models and metamodels to the transformation engine for execution.

The resulting models may be persisted in the model repository, inspected or even transformed again with MoScript.

Want to build better software faster?

Want to build better software faster?

Read about the latest trends on software modeling and low-code development

You have Successfully Subscribed!

Pin It on Pinterest

Share This