Model transformations are an essential element of Model-Driven Engineering (MDE) since they allow developers to automate the manipulation of models. The reliability of any MDE process depends on the correctness of its transformations, since a bug in a single transformation may permeate to many projects.

In the last years, the engines of many transformation tools like ATL and Epsilon have matured enough to be used for real projects. However, these tools do not include methods to help in detecting errors and verifying the correctness of the transformations.

Moreover, IDEs for model transformation languages are still rudimentary compared to IDEs of languages like Java o C, since they lack facilities to detect problems as the transformation is developed, quick fixes, navigation shortcuts, etc.

AnATLyzer fills this gap for ATL by providing a static analyzer able to detect a wide range of non-trivial errors in ATL transformations as well as an advanced IDE which extends the basic ATL editor.

An update site to install the Eclipse plug-ins and instructions to install and use AnATLyzer are available at https://anatlyzer.github.io/.

IDEs for model transformation languages are still rudimentary compared to IDEs of languages like Java o C. AnATLyzer is here to fix this! Click To Tweet

Identifying errors in model transformations

Developing any moderately complex model transformation can be a difficult task, because it is not straightforward to grasp the accepted input model configurations, the relations between its rules, and the connections between the objects produced and consumed by the rules. This issue is exacerbated in ATL due to its implicit rule resolution mechanism. In this setting, AnATLyzer is intended to help in the early detection of problems and to help users to understand and fix them.

As a simple example, let’s consider the simple transformation rule shown in the image. A developer typically sees the transformation text and the meta-models used by the transformation as shown in the tree editor. With this information, could you say if is this transformation correct? (i.e., assuming getSuperClass correctly returns the super class of a Java class).

a correct model transformation

In fact, there is a problem in rule class2class because superClass is a derived feature in UML, and therefore cannot be assigned. Transformation languages like ATL and ETL do not check anything statically, not even simple problems like this one. However, this is a common error that developers make in transformations generating UML models, but could easily be detected with proper tooling.

AnATLyzer features

AnATLyzer extends the ATL editor available as part of the ATL Eclipse plug-in with new features, namely:

  • A powerful static analyzer, integrated into the ATL editor to report problems in the editor each time the ATL file is saved.
  • Support for OCL pre-conditions and post-conditions.
  • A large catalog of quick fixes (more than 100).
  • Facilities to understand the transformation, like visualizations and automatically generated example models.
  • Navigation shortcuts to easily jump to elements of the transformation.
  • An API to use AnATLyzer programmatically to write programs which handle ATL transformations (e.g., in experiments) and to create extension points to add new capabilities to the plug-in.

Static analysis of model transformations

The main feature of AnATLyzer is its static analyzer. It is able to detect more than 50 kinds of problems in ATL transformations. These problems are of various kinds, including typing problems, rule problems, target conformance violations, and style issues. The static analyzer is based on three components:

  1. A type inference engine for OCL, which is able to deal with many of the peculiarities of the version of OCL implemented by ATL,
  2. A rule analysis component to detect problems with the transformation rules. For instance, AnATLyzer can detect if a binding is fully resolved (i.e., for any source object appearing on the right-hand side of the binding there is a rule covering it).
  3. An interface to the USE Validator constraint solver to improve the precision of the analysis. This is needed in situations in which type checking the transformation is not enough to determine if an expression is erroneous or not. Instead, AnATLyzer asks the constraint solver to produce a counter-example confirming the problem.

The following image shows the process followed by AnATLyzer to check errors.

Analysis model transformations

Given an ATL transformation, the first step is type checking. The type inference engine annotates each node of the abstract syntax tree with its inferred type. From this, a transformation dependence graph (TDG) is constructed, which is similar to a program dependence graph but also including links between bindings and their resolving rules. Then, the transformation analysis phase outputs two kinds of problems: 1) actual errors and warnings, which can be readily reported to the user and 2) “potential problems”. These are smells which cannot be statically confirmed to be problems (e.g., there are OCL expressions like rule filters or if conditions which cannot be checked with a plain static analysis). AnATLyzer is able to verify them by relying on a constraint solver. For each potential problem, we compute its OCL path condition (i.e., an OCL constraint stating the requirements for an input model to make the transformation fail at the problems’ location). Then, this OCL constraint is used as input of the constraint solver. If a model satisfying the OCL constraint is found, the problem is confirmed and reported to the user since there exists at least one model that would cause the problem at runtime. Otherwise, the problem is discarded.

For example, the following is a piece of transformation between UML Activity Diagrams and Intalio BPMN diagrams. It contains some errors which will be detected by AnATLyzer.

-- @nsURI UML=http://www.eclipse.org/uml2/3.0.0/UML
-- @path Intalio=/uml2intalio/metamodels/bpmn.ecore
module UML2Intalio;
create OUT: Intalio from IN: UML;

-- Error #1: the return type is incorrect
-- Error #2: name is an optional property so call .toLower() 
--           may yield a "null pointer exception". 
helper context UML!Action def: toIntalioName: Intalio!Activity =
	self.name.toLower();

rule activitypartition2pool {
  from a: UML!ActivityPartition
  to	   p: Intalio!Pool,
	    l: Intalio!Lane (
       -- Error #3: Invalid assignment of Artifact due to rule objectnode
       activities <- a.node
   )
}

rule opaqueaction {
   from n: UML!OpaqueAction
   to   a: Intalio!Activity (
      name <- n.toIntalio ) } rule initialnode { from n: UML!InitialNode ( n.incoming -> isEmpty()
  )
  to a: Intalio!Activity (
     -- Error #4: .toIntalioName() is only defined on Action
     name <- n.toIntalioName,
     activityType <- #EventStartEmpty
  )
}

rule edges {
   from f: UML!ControlFlow
   to e: Intalio!SequenceEdge (
	source <- f.source,
	target <- f.target 
   ) 
} 
rule objectnode {
   from n : UML!ObjectNode
   to a : Intalio!Artifact
}

 

  • Error #1. Invalid return type. The type inferred by AnATLyzer is diferent from the one declared in the transformation. ATL does not check type declarations at runtime, but it is important to have accurate type information to avoid confusion.
  • Error #2. Access to undefined receptor. In the UML meta-model name is an optional property. This will cause a runtime error when name is Undefined. It is possible to fix this problem by adding a precondition indicating that the transformation assumes that the name is always defined. AnATLyzer will feed the pre-condition into a constraint solver to rule out the problem.
-- @precondition
helper def: compulsoryName: Boolean =
  UML!NamedElement.allInstances()->forAll(e | not e.name.oclIsUndefined());
  • Error #3. Binding resolved with invalid target. There is an invalid assignment to the binding because a.node may contain ObjectNode elements, which are mapped to Artifact by rule objectnode. The problem is that Artifact is compatible with Activity (the type of the activities reference). This could be resolved filtering the binding “a.node->reject(e | e.oclIsKindOf(UML!ObjectNode))”.
  • Error #4. Helper toIntalioName not defined for Activity. The helper is only defined for type Action, so the call is not valid in this case.

IDE facilities

On top of the type information gathered during the static analsis, AnATLyzer provides a number of facilities to improve the productivity of transformation developers. The image below is a screenshot of AnATLyzer showing the aspect of the IDE and some of its features. Let’s describe some of them.

screenshot of the model transformation analyzer

Live analysis

The static analyzer is automatically executed each time the file is saved. The regular type checking phase is normally fast enough to avoid interrupting the developer workflow. For those problems which need the constraint solver, a separate thread is launched in the background. It is possible to configure which errors should be checked in the live analysis and which kind of errors should be delayed to be checked on demand.

Batch analysis

Some kinds of analysis may take more than a few milliseconds to complete as they heavily rely on the solver. These analysis include checking rule conflicts (i.e., no two rules match the same source element), target invariant analysis (i.e., checks whether any possible output model of a transformation will fulfil a set of provided post-conditions or target meta-model invariants) and child stealing analysis (i.e., checks that no object changes its container at runtime).

Quick fixes

AnATLyzer provides a large catalog of more than 100 quick fixes to help developers easily correct the problems detected by AnATLyzer. A quick fix may modify the transformation text, modify the source or target meta-models or generate a pre-condition. In addition, the quick fix menu provides access to other features of the IDE, such as visualizations to investigate a problem. Given a problem, the user can access the available quick fixes with CTRL+1.

Explanations and witness model

For every detected error it is possible to ask for an explanation. The explanation consists of a text and a witness model which, if used as source model to execute the transformation, would make the transformation fail at the error’s location. The following image shows the explanation dialog for “Error #3: Binding resolved with invalid target”.

witness model for the transformation

Visualizations

AnATLyzer provides a visualization facility to improve the understanding of the relationships between bindings and rules.

The visualization renders the transformation as a graph where rules are nodes and bindings are edges. This visualization is also used to help the user understand binding-related errors. The following image shows the visualization for “Error #3: Binding resolved with invalid target”, indicating that the guilty rule is objectnode, so that it is easy to see that the target element, Artifact, is not compatible with the type expected in the left hand side of the binding, Activity.

Visualization of a binding-related error

Navigation shortcuts

Editors for other languages like Java provide facilities to easily jump between the elements of a program. For ATL, the keyboard shortcut CTRL+O shows a popup dialog to quickly access the elements of the transformation (helpers and rules). The shortcut CTRL+B pressed over a binding allows a developer to jump to the rules which resolve a binding, and if it is pressed over the rule name shows the bindings which are resolved by such rule.

Programmatic API

It is possible to make use of the AnATLyzer infrastructure to profit from the type inference, the transformation dependence graph and the possibility of using the constraint solver to refine the analysis or using algorithms already implemented like computing the meta-model footprint of a transformation. This is useful in a number of scenarios, for example:

  • To implement optimized access to model repository for a specific transformation based on the types accessed by the transformation.
  • Build generators from ATL to other technologies, for example to create a new ATL compiler for another platform or to compile to some verifier backend.
  • Run experiments over transformations in batch mode, for instance, to compare how many errors are made by students of an MDE course.

In addition, AnATLyzer provides several extension points to easily add new functionality to the IDE, including creating new analysis, new quick fixes, new visualizations or implementing interfaces for another constraint solvers.

Summary

AnATLyzer is an IDE to develop ATL transformations based on a powerful static analyser. Its goal is to provide advanced capabilities to improve the quality of the transformations. If you develop ATL transformations, you should give it a try!

AnATLyzer is an IDE to develop ATL transformations based on a powerful static analyser Click To Tweet

Additional information

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