blob: 1af629b50e553b69acbc1eca30863d8de5e51501 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-language" content="en">
<meta name="description" content="Scalable Reactive Model Transformations">
<meta name="MobileOptimized" content="width" />
<meta name="HandheldFriendly" content="true" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="/viatra/js/googleAnalytics.js"></script>
<script type="text/javascript" src="/viatra/js/magnific-popup.video.js"></script>
<script type="text/javascript" src="/viatra/js/magnific-popup.min.js"></script>
<script type="text/javascript" src="/viatra/js/functions.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="/viatra/angular/viatra.js"></script>
<script src="/viatra/highlight.js/highlight.min.js"></script>
<link rel="stylesheet" type="text/css" href="//www.eclipse.org/eclipse.org-common/themes/solstice/public/stylesheets/vendor/cookieconsent/cookieconsent.min.css" />
<script src="//www.eclipse.org/eclipse.org-common/themes/solstice/public/javascript/vendor/cookieconsent/default.min.js"></script>
<link rel="shortcut icon" type="image/x-icon" href="/viatra/favicon.ico" />
<title>Viatra - Scalable reactive model transformations</title>
<link type="text/css" rel="stylesheet" href="/viatra/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="/viatra/css/style.css" />
<link type="text/css" rel="stylesheet" href="/viatra/css/media.css" />
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300italic,700,300' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="https://use.fontawesome.com/ef6567f233.css">
<link rel="stylesheet" href="/viatra/highlight.js/styles/foundation.min.css">
<link rel="stylesheet" type="text/css" href="/viatra/css/asciidoctor.css"/>
</head>
<body ng-app="viatra" ng-controller="main" class="cloak">
<ng-include src="'/viatra/angular/blocks/header.html'"></ng-include>
<div class="clear"></div>
<div id="body_wrapper">
<h1 class="page_title">Getting Started with VIATRA</h1>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p><a href="http://www.eclipse.org/viatra/">VIATRA</a> is an open source model transformation framework, focusing on efficient evaluation of model queries and supports various transformation workflows. This document contains a tutorial for getting started with the query and transformation development.</p>
</div>
<div class="paragraph">
<p>The tutorial relies on the <a href="https://github.com/viatra/viatra-docs/blob/master/cps/Home.adoc">CPS Demonstrator application</a>. The CPS Demonstrator is specified to cover a usual workflow in Model-driven Engineering, where a system is (1) first described in a source model, then (2) automated model-to-model transformations are used to derive a target model. Finally, (3) model-to-text transformation is performed to generate code from the target domain. In addition, a model generator that can automatically create source domain models can support the correctness testing and performance evaluation of the components. This tutorial uses only a subset of the transformation problem, as its main goal is to illustrate the basics of the VIATRA environment. Consult the original demonstrator for a more complex transformation example.</p>
</div>
<div class="paragraph">
<p>We expect readers to be familiar with the basics of Eclipse plug-in development, more specifically creating plug-in projects and defining basic UI extensions such as commands. Additionally, we expect a basic understanding of EMF-based modeling. If required, look at the Plug-in development tutorial at <a href="http://www.vogella.com/tutorials/EclipsePlugin/article.html" class="bare">http://www.vogella.com/tutorials/EclipsePlugin/article.html</a> or the EMF tutorial at <a href="http://www.vogella.com/tutorials/EclipseEMF/article.html" class="bare">http://www.vogella.com/tutorials/EclipseEMF/article.html</a> for a short presentation on these subjects.</p>
</div>
<div class="paragraph">
<p>This tutorial includes a <strong>quick setup guide</strong>, then describes both <strong>model query development</strong> and their usage in the <strong>query runtime</strong>. Then, both <strong>batch</strong> and <strong>event-driven transformations</strong> are covered.</p>
</div>
<div id="toc" class="toc">
<div id="toctitle" class="title">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#environment">1. Setting up the tutorial</a></li>
<li><a href="#_domains">2. Domains</a>
<ul class="sectlevel2">
<li><a href="#_cyber_physical_system">2.1. Cyber Physical System</a></li>
<li><a href="#_deployment">2.2. Deployment</a></li>
<li><a href="#_traceability">2.3. Traceability</a></li>
</ul>
</li>
<li><a href="#_query_development">3. Query Development</a>
<ul class="sectlevel2">
<li><a href="#_using_the_query_development_environment">3.1. Using the Query Development Environment</a></li>
<li><a href="#_using_queries_programmatically">3.2. Using Queries Programmatically</a></li>
</ul>
</li>
<li><a href="#_model_transformation_development">4. Model Transformation Development</a>
<ul class="sectlevel2">
<li><a href="#_batch_transformations">4.1. Batch Transformations</a></li>
<li><a href="#_event_driven_transformations">4.2. Event-driven Transformations</a></li>
<li><a href="#_debugging_model_transformations">4.3. Debugging model transformations</a></li>
</ul>
</li>
</ul>
</div>
<div style="page-break-after: always;"></div>
</div>
</div>
<div class="sect1">
<h2 id="environment"><a class="link" href="#environment">1. Setting up the tutorial</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>This tutorial was last updated using VIATRA 2.3.0 (released on 18th December 2019), available from the Simultaneous Release Train p2 repository (<a href="http://download.eclipse.org/releases/2019-12" class="bare">http://download.eclipse.org/releases/2019-12</a>). The latest version can be downloaded from <a href="http://download.eclipse.org/viatra/updates/release/latest" class="bare">http://download.eclipse.org/viatra/updates/release/latest</a> that should be compatible with everything described here. To install VIATRA, select the <code>VIATRA Query and Transformation SDK</code> from the selected repository to install.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/install.png" alt="Install window">
</div>
<div class="title">Figure 1. Install window</div>
</div>
<div class="paragraph">
<p>This document assumes that the CPS metamodels are installed into the Eclipse instance. They are available from the p2 repository <a href="http://download.eclipse.org/viatra/examples/cps" class="bare">http://download.eclipse.org/viatra/examples/cps</a></p>
</div>
<div class="paragraph">
<p>VIATRA defines a custom perspective called <code>Transformation Development</code> that includes a few views and shortcuts that make it easier to develop queries and transformations. The remainder of the tutorial expects that this perspective is selected; in case a different perspective is used, the corresponding views and wizards are still available in their standard respective locations.</p>
</div>
<div style="page-break-after: always;"></div>
</div>
</div>
<div class="sect1">
<h2 id="_domains"><a class="link" href="#_domains">2. Domains</a></h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_cyber_physical_system"><a class="link" href="#_cyber_physical_system">2.1. Cyber Physical System</a></h3>
<div class="paragraph">
<p>The CPS domain specifies application and host types and their instances, requests and requirements on applications and resource requirements of applications towards hosts. Application types have a state machine that describes their behavior through states and transitions. Finally, application instances can be allocated to host instances that can communicate with each other.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/cps/cps_ecore.png" alt="Cyber Physical System model Ecore diagram">
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Host instances have a unique node IP address.</p>
</li>
<li>
<p>Application instances have a unique identifier.</p>
</li>
<li>
<p>State machines can define an initial state.</p>
</li>
<li>
<p>Transitions may specify an action for sending or waiting for a signal. A signal can be sent by providing an application type (with its ID) and a signal identifier, while waiting for a signal is done by specifying its identifier.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_deployment"><a class="link" href="#_deployment">2.2. Deployment</a></h3>
<div class="paragraph">
<p>In the deployment model, host instances contain the applications that are running on them, while each application has a behavior with states and transitions. The behavior has a current state and transitions may trigger other transitions when the triggered transition is waiting for the signal they are sending and the application type is correct.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/cps/deployment_ecore.png" alt="Deployment model Ecore diagram">
</div>
</div>
</div>
<div class="sect2">
<h3 id="_traceability"><a class="link" href="#_traceability">2.3. Traceability</a></h3>
<div class="paragraph">
<p>The traceability model describes the correspondence between a CPS and a deployment model. The traceability is stored in a set of traces that refer to zero, one or multiple CPS and deployment elements.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/cps/traceability_ecore.png" alt="Traceability model Ecore diagram">
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_query_development"><a class="link" href="#_query_development">3. Query Development</a></h2>
<div class="sectionbody">
<div style="page-break-after: always;"></div>
<div class="sect2">
<h3 id="_using_the_query_development_environment"><a class="link" href="#_using_the_query_development_environment">3.1. Using the Query Development Environment</a></h3>
<div class="paragraph">
<p>Constraints and conditions in the VIATRA framework are expressed using a graph pattern-based language. This declarative formalism allows very compact definitions of complex conditions, while it is still possible to provide live query evaluation based on the Rete algorithm.</p>
</div>
<div class="paragraph">
<p>In the following we get an overview of the query development environment, starting with the definition of queries, followed by query evaluation support. Then we gain an understanding of the various language elements by creating more and more complex queries.</p>
</div>
<div class="paragraph">
<p>A graph pattern encodes a <em>named</em> query with some <em>parameters</em> defined as a <em>disjunction</em> of pattern <em>bodies</em>, while each body consists of a <em>set</em> of constraints. The result of a graph pattern, called <em>match set</em>, is a <em>set</em> of (model element) tuples where the elements fulfill all constraints defined in at least one of the pattern bodies.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
The pattern language always works on sets: neither the constraints nor the match set is ordered; and match set never includes multiple tuples with exactly the same model elements.
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="_define_your_first_query"><a class="link" href="#_define_your_first_query">3.1.1. Define your First Query</a></h4>
<div class="paragraph">
<p>To define queries, first a <em>VIATRA Query Project</em> has to be created with the standard <em>New Project Wizard</em> of Eclipse. Such projects are specialized Eclipse plug-in projects with preconfigured VIATRA dependencies and the query generator initialized. Query specifications have to be added to the Java classpath of the projects, more specifically into Java packages. Based on these observations the creation of the first query consists of the following steps:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Create a new VIATRA Query project in the host Eclipse with any name. The tutorial will assume the following name: <code>org.eclipse.viatra.examples.cps.queries</code>.</p>
</li>
<li>
<p>Add <code>org.eclipse.viatra.examples.cps.model</code> to the Plug-in dependencies to make the CPS metamodel available for the project.</p>
</li>
<li>
<p>Create a Java package to store the queries. The tutorial will assume one named <code>org.eclipse.viatra.examples.cps.queries</code>.</p>
</li>
<li>
<p>Create a new query definition in a package named using the <code>New Query Definition</code> wizard from the VIATRA category. The tutorial assumes the query file is named <code>CPSQueries.vql</code>.</p>
</li>
<li>
<p>Fill the first query:</p>
<div id="vql-first" class="listingblock">
<div class="title">queries.vql</div>
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">// Java package declaration, must match the container of the file
package org.eclipse.viatra.examples.cps.queries
// EPackage import
import "http://org.eclipse.viatra/model/cps"
// Pattern declaration
pattern hostIpAddress(host: HostInstance, ip : java String) {
// Type constraint stating that variables 'host' and 'ip' are connected via a 'nodeIp' attribute
HostInstance.nodeIp(host,ip);
}</code></pre>
</div>
</div>
</li>
</ol>
</div>
<div class="paragraph">
<p>Looking at the pattern header, we see that this pattern has two parameters, meaning its results will be a pair of values, the first selecting a <code>HostInstance</code> from the model, while the second one a <code>String</code> literal. The connection between these elements is described by a single constraint ensuring that <code>ip</code> variable stores the <code>nodeIp</code> attribute of a corresponding <code>HostInstance</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="_evaluate_queries_in_the_query_results_view"><a class="link" href="#_evaluate_queries_in_the_query_results_view">3.1.2. Evaluate Queries in the Query Results View</a></h4>
<div class="paragraph">
<p>VIATRA includes a view to evaluate the results of queries over various editors, and reacts on changes in the editor.</p>
</div>
<div class="paragraph">
<p>The <strong>Query Results</strong> view is the primary tool for debugging graph patterns. Open the view by selecting <em>Window/Show View/Query Results</em> or you can simply press the <span class="keyseq"><kbd>CTRL</kbd>+<kbd>3</kbd></span> shortcut and start to type the name of the view. The view allows loading models and queries, and display (and update) the results of queries automatically. Together with the installed metamodels there is also an example instance model included that will be used in this tutorial as an example.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/generate_cps_example.png" alt="Generate CPS example">
</div>
<div class="title">Figure 2. Initialize the example CPS demonstrator project</div>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Open our example instance model (/org.eclipse.viatra.examples.cps.instances/example.cyberphysicalsystem)</p>
</li>
<li>
<p>Make sure "ReteEngine" is selected in the toolbar of the Query Results view</p>
</li>
<li>
<p>then press the 'Load model from active editor' (first button on the toolbar)</p>
</li>
<li>
<p>Open the query specification (vql file)</p>
</li>
<li>
<p>then press the 'Load queries from the active editor' button</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>At this point the <em>Query Results</em> view should contain the matches of the freshly created pattern. Using the example model, you can see that there are 6 matches for the pattern, each consisting of a HostInstance-IP address pair. Note that the <em>Query Results</em> view provides live results: by updating the model in the model editor file, e.g. adding a new host instance or changing its IP address, the results update automatically.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/queryresultview.png" alt="Query Results View in Action">
</div>
<div class="title">Figure 3. Query Results View</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
If the 'Load model from active editor' button is not enabled, it either means, the current editor does not contain a model, or VIATRA does not understand the editor type. By default, EMF tree editors are supported; other editor types, such as graphical editors are supported by additional integration plug-ins, such as the GMF or Graphiti integration available from the VIATRA repository.
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_define_additional_queries"><a class="link" href="#_define_additional_queries">3.1.3. Define Additional Queries</a></h4>
<div class="paragraph">
<p>In the following, we define a set of patterns that illustrate additional capabilities of the query language. Each pattern will come with a short definition, followed by the code itself and some remarks about how the pattern works.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>List all <code>HostInstance</code> elements whose IP address is an empty string</p>
<div class="ulist">
<ul>
<li>
<p>This pattern, similar to the first pattern, still consists of a single constraint. The pattern constraints can refer to Java literals, like empty strings or numbers directly.</p>
</li>
<li>
<p>Notice that if you create a new <code>HostInstance</code> element, it will not appear in the match results. This happens because in EMF unset and empty attributes are different (similar to the difference between empty Strings and null in Java). You can write a pattern that finds missing attribute values using the <code>neg find</code> construct (see later).</p>
<div id="vql-emptyipaddress" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">pattern emptyIpAddress(host: HostInstance) {
HostInstance.nodeIp(host, "");
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>List all <code>HostInstance</code>-<code>HostInstance</code> pairs that share a common IP address</p>
<div class="ulist">
<ul>
<li>
<p>This pattern is more complex, as it has three parameters and three constraints. The first two describe similar type constraints we have seen. The pattern also compares the values of variables <code>host1</code> and <code>host2</code> with each other using the <code>!=</code> (<em>not equal</em>) operator (The <code>==</code> operator is also available).</p>
<div id="vql-sameipaddress" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">pattern sameIpAddress(host1 : HostInstance, host2 : HostInstance, commonIp : java String) {
HostInstance.nodeIp(host1, commonIp);
HostInstance.nodeIp(host2, commonIp);
host1!=host2;
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>List all <code>HostInstance</code> elements that have non well-formed IPv4 addresses (e.g. not four numbers separated with dots)</p>
<div class="ulist">
<ul>
<li>
<p>The well-formedness validation of the IP address strings requires specific validation blocks called <code>check</code> expressions where you can write a wide range of <em>Xbase</em> expressions, behaving similarly to Java and accessing Java classes from the classpath of the project. In this case, the well-formedness of the address values is represented with a regular expression evaluation.</p>
</li>
<li>
<p>It is important to note that check expressions <strong>have to</strong> be side-effect free and can only be called on attribute variables.</p>
<div id="vql-ipformatinvalid" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">pattern ipFormatInvalid(host : HostInstance, ip : java String) {
HostInstance.nodeIp(host,ip);
check (
!ip.matches("^[\\d\\.]+")
);
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>List <code>State</code> elements connected through <code>Transition</code> elements</p>
<div class="ulist">
<ul>
<li>
<p>A pattern body might use variables other than the pattern parameters, such as the variable <code>transition</code> in this example. These variables are called local variables.</p>
</li>
<li>
<p>It is important to note that if there are multiple transitions between two states, the match set will still include only a single pair of the states, because local variables are not included in the match tuples. If all edges are required, the corresponding transition variable should also be declared as a parameter.</p>
<div id="vql-connectedto" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">pattern connectedTo(state: State, other: State){
// There exists a transition from `state` to `other`
State.outgoingTransitions(state, transition);
Transition.targetState(transition, other);
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>List bad host instances that fail either of the previous conditions.</p>
<div class="ulist">
<ul>
<li>
<p>Disjunctions can be expressed by using the <code>or</code> keyword between pattern bodies. A model element tuple is included in the match set of a pattern, if at least one of the bodies have a match. Note that if multiple bodies would match the same tuple, the match set of the pattern will still only include the tuple once (<em>set semantics</em>).</p>
</li>
<li>
<p>Patterns can be reused using <code>find</code> constraints meaning all conditions expressed by the called pattern must be matched from the source.</p>
</li>
<li>
<p>This pattern also includes <em>single-use</em> (or don&#8217;t care) variables, starting with the character '_'. Such a declaration describes a variable where we are only interested in its existence but not its value.</p>
<div id="vql-badhost" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">pattern badHost(host : HostInstance, ip : java String) {
find sameIpAddress(host, _other, ip);
} or {
HostInstance.nodeIp(host, ip);
find emptyIpAddress(host);
} or {
find ipFormatInvalid(host, ip);
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>List all good host instances (that meet neither of the incorrect conditions)</p>
<div class="ulist">
<ul>
<li>
<p>The negative pattern composition, expressed by the <code>neg find</code> keyword is used to define negative conditions. This works similar to the <code>find</code> constraints, with the notable exception that if there are any matches to the badHost with the selected parameters, the host pattern fails to match.</p>
</li>
<li>
<p>Those actual parameters of the negative pattern call that are not used elsewhere in the calling body are <em>universally quantified</em>, meaning that the calling pattern only matches if variables of the calling pattern cannot be bound to matching elements.</p>
<div id="vql-goodhost" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">pattern goodHost(host : HostInstance, ip : java String) {
HostInstance.nodeIp(host, ip);
neg find badHost(host, _);
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>List the number of applications for each HostInstance</p>
<div class="ulist">
<ul>
<li>
<p>Patterns can be marked as private, making the pattern itself only visible inside the source file it is defined. The generated code for these patterns is reduced (e.g. does not include generated Match and Matcher classes for easier access).</p>
</li>
<li>
<p>It is possible to calculate the matches of a pattern using the <code>count find</code> expressions. The value of such an expression is the number of matches found with the selected number of matches.</p>
<div id="vql-countapplications" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">private pattern allocatedApplications(host : HostInstance, app : ApplicationInstance) {
HostInstance.applications(host, app);
}
pattern countApplications(host : HostInstance, m : java Integer) {
m == count find allocatedApplications(host, _);
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>List all states of a state machine that are reachable from its initial state (either directly or indirectly)</p>
<div class="ulist">
<ul>
<li>
<p>The reachable states are calculated using the transitive closure of the previously introduced connectedTo pattern.</p>
<div id="vql-reachablestate" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">pattern reachableState(sm :StateMachine, state: State){
// The initial state of the statemachine is reachable
StateMachine.initial(sm, state);
} or {
StateMachine.initial(sm, initial);
// Ensure the state is indeed included in the state machine; unnecessary in a well-formed model
StateMachine.states(sm, state);
// The + symbol after the pattern name represents transitive closure
find connectedTo+(initial, state);
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
</ol>
</div>
</div>
<div class="sect3">
<h4 id="_validation"><a class="link" href="#_validation">3.1.4. Validation</a></h4>
<div class="paragraph">
<p>VIATRA provides facilities to create validation rules based on the pattern language of the framework. These rules can be evaluated on various EMF instance models and upon violations of constraints, markers are automatically created in the Eclipse Problems View.</p>
</div>
<div class="paragraph">
<p>The <strong>@Constraint</strong> annotation can be used to derive a validation rule from a graph pattern as a validation rule. The pattern of the rule identifies the erroneous model elements, while the annotation parameters provides information about how to present the results in the user interface. The annotation uses the following parameters:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><em>key:</em> The list of paremeters which determine which objects the constraint violation needs to be attached to.</p>
</li>
<li>
<p><em>message:</em> The message to display when the constraint violation is found. The message may refer the parameter variables between $ symbols, or their EMF features, such as in $Param1.name$.</p>
</li>
<li>
<p><em>severity:</em> "warning" or "error"</p>
</li>
<li>
<p><em>targetEditorId:</em> An Eclipse editor ID where the validation framework should register itself to the context menu. Use ` * ` as a wildcard if the constraint should be used always when validation is started.</p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
To find a specific editor id, we can use the <em>Plug-in Selection Spy</em> tool with a <span class="keyseq"><kbd>Shift</kbd>+<kbd>Alt</kbd>+<kbd>F1</kbd></span> shortcut. For a few generic editors, such as the <strong>Sample Reflective Ecore Editor</strong>, the framework by default provides such a registration option, no manual registration is necessary.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>For example:</p>
</div>
<div id="vql-constraint" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">@Constraint(targetEditorId = "org.eclipse.viatra.examples.cps.cyberPhysicalSystem.presentation.CyberPhysicalSystemEditorID",
severity = "error",
message = "The ip address is not unique",
key = {host1})
pattern sameIpAddress(host1: HostInstance, host2: HostInstance, commonIp : java String) {
HostInstance.nodeIp(host1, commonIp);
HostInstance.nodeIp(host2, commonIp);
host1!=host2;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>When adding such a constraint annotation to a graph pattern, the code generator initializes a validation project that includes and registers the rules derived from the patterns for the framework. These rules can be tried out by opening a new runtime Eclipse instance:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Launch a new <code>Eclipse application</code> containing all projects in the workspace.</p>
</li>
<li>
<p>In the newly launched Eclipse instance, open an erroneous instance model in the model editor (make sure the editor is the same one that is added to the <code>targetEditorId</code> parameter).</p>
</li>
<li>
<p>Start the validation from the popup menu items under <strong>VIATRA Validation</strong>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>For more information about look at the <a href="https://www.vogella.com/tutorials/EclipsePlugin/article.html">Eclipse IDE Plug-in Development tutorial at vogella.com</a>.</p>
</div>
</div>
<div class="sect3">
<h4 id="_more_complex_queries"><a class="link" href="#_more_complex_queries">3.1.5. More Complex Queries</a></h4>
<div class="paragraph">
<p>This section introduces a set of more complex queries, useful for both introducing the remaining language features such as aggregators while illustrating the way the query language allows breaking down more complex conditions.</p>
</div>
<div class="sect4">
<h5 id="_calculate_the_maximum_number_of_instances"><a class="link" href="#_calculate_the_maximum_number_of_instances">3.1.5.1. Calculate the Maximum Number of Instances</a></h5>
<div class="paragraph">
<p>It is possible to find the Application Type that has the most instances defined in the model by combining a <em>counting</em> of the values of the related feature and a <em>max</em> function. The <code>sumNumberOfInstances</code> helper pattern uses a <code>count</code> call of the <code>ApplicationType.instances</code> feature (note the omission of the <code>find</code> keyword there). This feature is available starting with VIATRA 2.0, and allows reducing the number of trivial helper patterns, like the pattern <code>hostIpAddress</code> introduced earlier in this tutorial.</p>
</div>
<div class="paragraph">
<p>After the counts are available in the match set of a pattern, it is possible to calculate the maximum value using the <code>max find</code> construct. However, it is important that calculating the maximum does not connect the ApplicationType instances to their maximum, that needs to be done with an additional constraint.</p>
</div>
<div id="vql-maximumNumberOfInstances" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">pattern maximumNumberOfInstances(at : ApplicationType, max : java Integer) {
max == max find sumNumberOfInstances(at, #);
find sumNumberOfInstances(applicationType, max);
}
pattern sumNumberOfInstances(at : ApplicationType, n : java Integer) {
n == count ApplicationType.instances(at, _);
}</code></pre>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_check_memory_requirements_of_a_host"><a class="link" href="#_check_memory_requirements_of_a_host">3.1.5.2. Check Memory Requirements of a Host</a></h5>
<div class="paragraph">
<p>The CPS metamodel explicitly stores requirements of applications, and both free and total resource values in case of host instances. However, checking that application requirements and free and total values are consistent requires checking.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/cps_resources.png" alt="Requirements in the CPS Metamodel">
</div>
<div class="title">Figure 4. Requirement handling in the metamodel</div>
</div>
<div class="paragraph">
<p>In the following example we focus on the memory requirements, but similar queries can be provided for CPU or HDD requirements. The well-formedness constraint we are trying to enforce is as follows: <code>FREE MEMORY + SUM(MEMORY OF DEPLOYED APPLICATIONS) = TOTAL MEMORY</code>.</p>
</div>
<div class="paragraph">
<p>The pattern requires two helper patterns: one of them (<code>applicationTypeRequirementRAM</code>) is responsible for collecting the RAM requirement for a selected <code>Application Type</code>, the other (<code>totalMemoryRequirements</code>) summarizes all memory requirements a selected application instance.</p>
</div>
<div class="paragraph">
<p>Using these helper patterns, the <code>invalidMemoryRequirement</code> pattern executes two additional steps: (1) it <em>summarizes</em> the results of the pattern <code>totalMemoryRequirements</code> with regards to the application instances allocated to a host instance, and (2) <em>checks</em> whether the three requirements are consistent.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
A Host Instance is allocated to at most a single application, so it is not required to summarize the requirements of all applications here as done in the <code>invalidMemoryRequirement</code> pattern. However, adding this element to the query illustrates how to use <code>sum</code> correctly if multiple levels of summarization is necessary.
</td>
</tr>
</table>
</div>
<div id="vql-invalidMemoryRequirement" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">pattern invalidMemoryRequirement(h : HostInstance, available : java Integer, allocated : java Integer, total : java Integer) {
HostInstance.availableRam(h, available);
HostInstance.totalRam(h, total);
allocated == sum find totalMemoryRequirements(h, _, #);
check(total != allocated + available);
}
private pattern totalMemoryRequirements(h : HostInstance, ai : ApplicationInstance, ram : java Integer) {
HostInstance.applications(h, ai);
ApplicationInstance.type(ai, at);
ram == sum find applicationTypeRequirementRAM(at, #);
}
private pattern applicationTypeRequirementRAM(at : ApplicationType, ram : java Integer) {
ApplicationType.requirements(at, req);
ResourceRequirement.requiredRam(req, ram);
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_references"><a class="link" href="#_references">3.1.6. References</a></h4>
<div class="ulist">
<ul>
<li>
<p><a href="query-language.html">Pattern Language</a></p>
</li>
<li>
<p><a href="addons.html#viatra-validation">Validation Framework</a></p>
</li>
<li>
<p><a href="addons.html#viatra-qbf">Query Based Features</a></p>
</li>
</ul>
</div>
<div style="page-break-after: always;"></div>
</div>
</div>
<div class="sect2">
<h3 id="_using_queries_programmatically"><a class="link" href="#_using_queries_programmatically">3.2. Using Queries Programmatically</a></h3>
<div class="paragraph">
<p>VIATRA Query provides an API to execute queries on various models, including support for listening to match set changes. However, as the incremental evaluation relies on indexes, the API also covers lifecycle management for the runtime. The central element of the API is the Query Engine that is responsible for loading query specifications, setting up indexes and providing match results. This approach is supported by code generators that create a runtime representation for graph patterns and provide a type-safe API to access VIATRA code.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/query_runtime.png" alt="query runtime">
</div>
<div class="title">Figure 5. Overview of the runtime components of VIATRA Query</div>
</div>
<div class="paragraph">
<p>To start working with the VIATRA Query API, we have to provide (1) a Scope representing the model and a (2) set of query specifications. The easiest way to initialize a scope, is to simply wrap an EMF ResourceSet inside a new EMFScope instace. For query specifications, the generated matcher classes can be used as an example, see as follows.</p>
</div>
<div class="paragraph">
<p>In general, the generated code in a VIATRA Query project is based on a (1) query specification classes representing the original VQL specifications for the runtime API, sharing a qualified class name with the original pattern specification. Each query specification includes (2) a Match and Matcher nested subclass for each pattern definition (recommended for general usage). Finally, (3) a group class for each file that can be used to initialize all queries together, using the same Java classname as the original vql file.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/query_generated_code.png" alt="query generated code">
</div>
<div class="title">Figure 6. Structure of the query generated code</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
The default generated API structure was changed in VIATRA 2.0. Before VIATRA 2.0 query specifications, matches and matchers were generated into separate classes. The remainder of the tutorial relies on the new generation schema; using the old schema requires a few updates in the code, specifically for match and matcher class references are to be updated accordingly.
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="_initialize_a_headless_application"><a class="link" href="#_initialize_a_headless_application">3.2.1. Initialize a headless Application</a></h4>
<div class="paragraph">
<p>To illustrate the usage of the VIATRA Query API, we will create a headless Eclipse application, and execute it over one of the queries written in the previous part. Such an application is a Java class registered using the extension point <code><code>org.eclipse.core.runtime.applications</code></code> (requiring the <code><code>org.eclipse.core.runtime</code></code> bundle as a dependency).</p>
</div>
<div id="query-runtime-app-extension" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;extension id="queryrunner" point="org.eclipse.core.runtime.applications"&gt;
&lt;application cardinality="singleton-global" thread="main" visible="true"&gt;
&lt;run class="org.eclipse.viatra.examples.cps.queries.runner.QueryRunner"/&gt;
&lt;/application&gt;
&lt;/extension&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code><code>IApplication</code></code> interface requires two methods to be implemented, called <code><code>start</code></code> and <code><code>stop</code></code>. In our case, we will only use start (and returning 0 to mark successful execution), stop is unnecessary.</p>
</div>
<div id="query-runtime-app-code" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public class QueryRunner implements IApplication {
@Override
public Object start(IApplicationContext context) throws Exception {
// Return value 0 is considered as a successful execution on Unix systems
return 0;
}
@Override
public void stop() {
// Headless applications do not require specific stop steps
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The created application can be started as an Eclipse application by specifically selecting the previously created extension.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/run_headless_application.png" alt="run headless application">
</div>
<div class="title">Figure 7. Running the Query Runner application</div>
</div>
</div>
<div class="sect3">
<h4 id="_initializing_a_query_engine"><a class="link" href="#_initializing_a_query_engine">3.2.2. Initializing a Query Engine</a></h4>
<div class="paragraph">
<p>To initialize a query engine, as first step an EMF scope has to be loaded. This can be done using the following code segment (expecting the model file was copied into the root of the queries project):</p>
</div>
<div id="query-runtime-scope" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private EMFScope initializeModelScope() {
ResourceSet rs = new ResourceSetImpl();
rs.getResource(URI.createPlatformPluginURI("org.eclipse.viatra.examples.cps.queries/example.cyberphysicalsystem", true), true);
return new EMFScope(rs);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If we have a model scope, it can be used to initialize a managed query engine. The internal implementation of the <code><code>ViatraQueryEngine.on</code></code> method ensure that only a single query engine will be created for each scope, and the query engine will be disposed together with the backing model, making this the preferred implementation for common cases.</p>
</div>
<div class="paragraph">
<p>Additionally, it is recommended to prepare the engine with all queries that will be used. For this, the generated query groups (one per query file) include a <code><code>prepare</code></code> method that creates all indexes required for the pattern matchers, with only a single round of model traversal required.</p>
</div>
<div id="query-runtime-prepare" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private ViatraQueryEngine prepareQueryEngine(EMFScope scope) {
// Access managed query engine
ViatraQueryEngine engine = ViatraQueryEngine.on(scope);
// Initialize all queries on engine
CPSQueries.instance().prepare(engine);
return engine;
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
If multiple query groups are to be loaded, either create a generic pattern group that holds all the patterns, or create a coalesce traversal block where you can execute multiple prepare statements together using the <code><code>engine.getBaseIndex().coalesceTraversals()</code></code> method.
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_the_pattern_matcher_api"><a class="link" href="#_the_pattern_matcher_api">3.2.3. The pattern matcher API</a></h4>
<div class="paragraph">
<p>The easiest way to use all the query engine is to ask for all matches of a query. The <code><code>getAllMatches</code></code> method of a pattern matcher returns a <strong>set</strong> of match objects that allow named references to its parameters</p>
</div>
<div id="query-runtime-printallmatches" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private void printAllMatches(ViatraQueryEngine engine) {
// Access pattern matcher
HostIpAddress.Matcher matcher = HostIpAddress.Matcher.on(engine);
// Get and iterate over all matches
for (HostIpAddress.Match match : matcher.getAllMatches()) {
// Print all the matches to the standard output
System.out.println(match.getHost());
}
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
It is safe to ask for the same matcher multiple times using the <code><code>on</code></code> method. Although the returned matcher instances may be different, but internally they reuse the same indexes. Given the matchers themselves are stateless, they are safe to use and forget, and at a later point ask for it again.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>It is also possible to use a more functional style processing of matches with a <a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html">Consumer</a>.</p>
</div>
<div id="query-runtime-printAllMatches2" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private void printAllMatches2(ViatraQueryEngine engine) {
HostIpAddress.Matcher matcher = HostIpAddress.Matcher.on(engine);
matcher.forEachMatch(new Consumer&lt;HostIpAddress.Match&gt;() {
@Override
public void accept(HostIpAddress.Match match) {
System.out.println(match.getHost());
}
});
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Before VIATRA 2.0, a separate MatchProcessor class was generated for each class that works similar to the Consumer-based implementation, but also extract all parameters. In version 2.0, this MatchProcessor is not generated by default, but can be enabled in the compiler settings.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>This can be simplified with a lambda expression as follows:</p>
</div>
<div id="query-runtime-printAllMatches3" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private void printAllMatches3(ViatraQueryEngine engine) {
HostIpAddress.Matcher matcher = HostIpAddress.Matcher.on(engine);
matcher.forEachMatch(match -&gt; System.out.println(match.getHost()));
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Often it is beneficial to check for and process only a single match. For this reason it is possible to ask for a single match using the <code><code>getOneArbitraryMatch</code></code> method. In order to handle cases where the given matcher has no matches in the current model, this method returns with an <a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/Optional.html">Optional</a> instance.</p>
</div>
<div id="query-runtime-printonematch" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private void printOneMatch(ViatraQueryEngine engine) {
HostIpAddress.Matcher matcher = HostIpAddress.Matcher.on(engine);
// getOneArbitraryMatch returns an optional
matcher.getOneArbitraryMatch()
//Print out the match only if available
.ifPresent(match -&gt; System.out.println(match.getHost()));
}</code></pre>
</div>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
The match returned by the <code><code>getOneArbitraryMatch</code></code> is neither random nor deterministic, but unspecified. <em>Usually</em> repeatedly calling it on the same model (without any model updates) returns the same match, but this is also not guaranteed. On the other hand, restarting the application on the same model <em>usually</em> changes the match returned.
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Before version 2.0, <code><code>getOneArbitraryMatch</code></code> returned <code><code>null</code></code> if no matches are available. Do not forget to handle this case if necessary.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The generated matchers also include a few methods to access values of the parameters. For example, in case of the <code><code>hostIpAddress</code></code> pattern there is a <code><code>getAllValuesOfip</code></code> method that returns all values the parameter <code><code>ip</code></code> finds.</p>
</div>
<div id="query-runtime-printalladdresses" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private void printAllAddresses(ViatraQueryEngine engine) {
HostIpAddress.Matcher matcher = HostIpAddress.Matcher.on(engine);
for (String ip : matcher.getAllValuesOfip()) {
System.out.println(ip);
}
}</code></pre>
</div>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
If there are multiple hosts that have the same IP address, the <code><code>getAllValuesOfip()</code></code> call will return each IP address only once. This is consistent with all other APIs that always return sets. If duplicates are required, you have to process all matches manually.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>All matcher functionality supports filtering the matches with constants. By setting some filter parameters with a non-null value we state that we are interested in only matches where the selected parameters equal to the given value.</p>
</div>
<div id="query-runtime-printfilteredmatches" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private void printFilteredMatches(ViatraQueryEngine engine) {
HostIpAddress.Matcher matcher = HostIpAddress.Matcher.on(engine);
for (HostIpAddress.Match match : matcher.getAllMatches(null, "152.66.102.1")) {
System.out.println(match);
}
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Regardless of input values receiving null values, the <code><code>getAllmatches</code></code> (and similar operations) will never return matches with <code><code>null</code></code> values. If no matches fulfill all the set parameters, the returned set will be empty.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>If a filter condition has to be reused, it is possible to create mutable matches where the filtered values are set accordingly. This approach is also useful to use named setters (e.g. if multiple String parameters are to be set) or one does not want to write <code><code>null</code></code> literals.</p>
</div>
<div id="query-runtime-printfilteredmatches2" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private void printFilteredMatches2(ViatraQueryEngine engine) {
HostIpAddress.Matcher matcher = HostIpAddress.Matcher.on(engine);
HostIpAddress.Match filter = matcher.newMatch(null, "152.66.102.1");
for (HostIpAddress.Match match : matcher.getAllMatches(filter)) {
System.out.println(match);
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finally, if we are only interested in whether there exist any match fulfilling the query, or we want to know how many matches there are, the matcher has methods that calculate these. Both of these methods can be combined with filter matches.</p>
</div>
<div id="query-runtime-countmatches" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private void printCounts(ViatraQueryEngine engine) {
HostIpAddress.Matcher matcher = HostIpAddress.Matcher.on(engine);
System.out.println(matcher.countMatches());
System.out.println(matcher.hasMatch(null, null));
System.out.printf("Count matches with ip 152.66.102.3: %d %n", matcher.countMatches(null, "152.66.102.3"));
System.out.printf("Has matches with ip 152.66.102.13: %b %n", matcher.hasMatch(null, "152.66.102.13"));
}</code></pre>
</div>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
If asking for the has/count calls is immediately followed by the processing of the said matches, it is usually better to call <code><code>getAllMatches</code></code> or <code><code>getOneArbitraryMatch</code></code> directly, and calculate the count/existence using them.
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="_advanced_query_engine_features"><a class="link" href="#_advanced_query_engine_features">3.2.4. Advanced query engine features</a></h4>
<div class="paragraph">
<p>There are cases where the standard engine lifecycle is inappropriate, e.g. the models will not be unloaded but we want to spare memory by freeing up indexes. Furthermore, there are some functionality, like hint handling or match update listener support that was not added to the base implementation to keep its API clean.</p>
</div>
<div id="query-runtime-prepareadvanced" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private AdvancedViatraQueryEngine prepareAdvancedQueryEngine(EMFScope scope) {
AdvancedViatraQueryEngine engine = AdvancedViatraQueryEngine.createUnmanagedEngine(scope);
// Initialize all queries on engine
CPSQueries.instance().prepare(engine);
return engine;
}</code></pre>
</div>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
Do not forget to dispose unmanaged engine manually using the <code><code>AdvancedQueryEngine.dispose()</code></code> method. If you want to use managed query engines but use the advanced features, you might use the <code><code>AdvancedQueryEngine.from(engine)</code></code> call; however, do <strong>NOT</strong> dispose such engines.
</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="_react_to_match_updates"><a class="link" href="#_react_to_match_updates">3.2.4.1. React to match updates</a></h5>
<div class="paragraph">
<p>One feature of the advanced query engine is to allow listening to changes, e.g. registering a match update listener for a pattern matcher. Such a listener is triggered when the match set for a pattern matcher changes, together with the direction of the changes.</p>
</div>
<div id="query-runtime-changelistener" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">IMatchUpdateListener&lt;HostIpAddress.Match&gt; listener = new IMatchUpdateListener&lt;HostIpAddress.Match&gt;() {
@Override
public void notifyAppearance(HostIpAddress.Match match) {
System.out.printf("[ADD] %s %n", match.prettyPrint());
}
@Override
public void notifyDisappearance(HostIpAddress.Match match) {
System.out.printf("[REM] %s %n", match.prettyPrint());
}
};
private void addChangeListener(AdvancedViatraQueryEngine engine) {
HostIpAddress.Matcher matcher = HostIpAddress.Matcher.on(engine);
try {
// fireNow = true parameter means all current matches are sent to the listener
engine.addMatchUpdateListener(matcher, listener, true);
// execute model manipulations
matcher.getOneArbitraryMatch()
.ifPresent(match -&gt; match.getHost().setNodeIp("123.123.123.123"));
} finally {
// Don't forget to remove listeners if not required anymore
engine.removeMatchUpdateListener(matcher, listener);
}
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
By registering the match update listener with a <code><code>true</code></code> value for the <code><code>fireNow</code></code> parameter, we ensure that all existing matches are sent to the listener. If we only want to consider future updates, set that parameter to false.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>When looking at the output, the setNodeIp call will result in two changes: the first one represents the removal of the old match (host - old IP pair), while the second one represents an addition of a new one (host - new IP pair). In general, a model update can often often result in multiple match changes (even on a single pattern).</p>
</div>
<div class="admonitionblock caution">
<table>
<tr>
<td class="icon">
<i class="fa icon-caution" title="Caution"></i>
</td>
<td class="content">
Be very careful when using match update listeners, as sometimes they are called while the model indexes are in an inconsistent state. For this reason, do not update the underlying model and do not execute further model queries. If such cases are required, delay the execution for a later phase. Better still, you can rely on the transformation API of VIATRA that ensure that rules are only executed when the indexes are in a consistent state.
</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_query_backends_and_hints"><a class="link" href="#_query_backends_and_hints">3.2.4.2. Query backends and hints</a></h5>
<div class="paragraph">
<p>The advanced query engine also allows to initialize patterns with non-default settings called <strong>hints</strong>. The most important feature of these hints allow setting the pattern matcher backend, and other backend-specific settings could be changed.</p>
</div>
<div class="paragraph">
<p>In addition to Rete-based incremental query evaluation VIATRA also includes a local search-based approach. By default, Rete is used, but by adding the <code><code>org.eclipse.viatra.query.runtime.localsearch</code></code> bundle as a dependency of the project, it is possible to generate local-search specific evaluation hints using the <code><code>LocalSearchHints</code></code> class. Similar, Rete-specific hints are available in the <code><code>ReteHintOptions</code></code> class. The backend-specific hints are beyond the scope of this tutorial, for more details see the corresponding VIATRA documentation or Javadoc.</p>
</div>
<div id="query-runtime-localsearch" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private void queryWithLocalSearch(AdvancedViatraQueryEngine engine) {
// Prepares a hint for local search
QueryEvaluationHint hint = LocalSearchHints.getDefault().build();
// Ensures that local search is used for matching
HostIpAddress.Matcher matcher = engine.getMatcher(HostIpAddress.instance(), hint);
// The local search backend features the same API as the Rete backend
for (HostIpAddress.Match match : matcher.getAllMatches()) {
System.out.println(match.prettyPrint());
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>As you can see, after the initialization the local search based backend can be queried with the same backend as the Rete-based one, however, it calculates the results when queried instead of relying on previously cached results. This means, usually it is cheaper (in memory and prepare time) to initialize a local search based matcher, but gathering the results is more expensive.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
As the name suggests, <strong>hints</strong> might be ignored by the query engine, e.g. if an incorrect configuration was set, or the engine knows of a functionally equivalent way that has a better performance. For details about the hints, consult the LocalSearchHints and ReteHintOptions classes.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>There are a few aspects where the current (version 2.0) local search backend behaves differently to the original, Rete-based algorithm:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Recursive queries are not supported. Trying to initialize a query with recursion results in a runtime error.</p>
</li>
<li>
<p>The algorithm cannot provide change notifications, so registering a MatchUpdateListener over local search-based queries is prohibited.</p>
</li>
</ul>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
The local search backend of VIATRA is almost functionally compatible with the Rete-based backend, but has very different performance characterics. If performance is critical, make sure to understand both algorithms to choose the appropriate one for the problem at hand.
</td>
</tr>
</table>
</div>
<div style="page-break-after: always;"></div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_model_transformation_development"><a class="link" href="#_model_transformation_development">4. Model Transformation Development</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>For model transformation development a Java API is available, allowing seamless integration of the transformations into any Java applications. However, to enhance readability, we recommend using a higher-level JVM language, as it allows defining the transformation as an internal DSL of this host language.</p>
</div>
<div class="paragraph">
<p>In this tutorial we rely on the <a href="https://eclipse.org/xtend/">Xtend language</a> to host the VIATRA transformation DSL, and we rely on its extension method and type inference support to reduce unnecessary elements. However, other JVM-based languages can also be used with similar efficiency (for an example in <a href="https://kotlinlang.org/">Kotlin</a> see <a href="https://gist.github.com/doczir/bfe95c470599c5b8e60b400b80f92ea2" class="bare">https://gist.github.com/doczir/bfe95c470599c5b8e60b400b80f92ea2</a>).</p>
</div>
<div class="sect2">
<h3 id="_batch_transformations"><a class="link" href="#_batch_transformations">4.1. Batch Transformations</a></h3>
<div class="paragraph">
<p>This exercise helps the audience to create a simple batch transformation using the VIATRA Transformation API.
The transformation will transform the hosts and applications in a CPS model to a deployment model.
The exercise also covers registering a menu command which initializes the transformation.</p>
</div>
<div class="sect3">
<h4 id="_create_transformation"><a class="link" href="#_create_transformation">4.1.1. Create transformation</a></h4>
<div class="paragraph">
<p>For the transformation, we have to create a <em>VIATRA Query Project</em> (the one from the <a href="#_query_development">query development tutorial</a> could also be reused), and create a new query file called <em>CpsXformM2M.vql</em> to store the patterns we want to use in the transformation with the following contents:</p>
</div>
<div id="bmt-queries" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">import "http://org.eclipse.viatra/model/cps"
import "http://org.eclipse.viatra/model/deployment"
import "http://org.eclipse.viatra/model/cps-traceability"
pattern hostInstance(hostInstance : HostInstance) {
HostInstance(hostInstance);
}
pattern applicationInstance(
appType : ApplicationType,
appInstance : ApplicationInstance
) {
HostInstance.applications(_, appInstance);
ApplicationType.instances(appType, appInstance);
}
/**
* Traceability link access
*/
pattern cps2depTrace(
cps2dep : CPSToDeployment,
trace : CPS2DeploymentTrace,
cpsElement : Identifiable,
depElement : DeploymentElement
) {
CPSToDeployment.traces(cps2dep, trace);
CPS2DeploymentTrace.cpsElements(trace, cpsElement);
CPS2DeploymentTrace.deploymentElements(trace, depElement);
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Create transformation class in Xtend</p>
<div class="ulist">
<ul>
<li>
<p>Create new <em>Model Transformation</em> with the wizard</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/transformation_wizard.png" alt="transformation wizard">
</div>
<div class="title">Figure 8. Model Transformation Wizard - Create new transformation</div>
</div>
</li>
<li>
<p>Setup the name of the transformation and click Next</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/batch_transformation_wizard_name.png" alt="batch transformation wizard name">
</div>
<div class="title">Figure 9. Model Transformation Wizard - Name of the new batch transformation</div>
</div>
</li>
<li>
<p>Setup the type of the transformation to <em>BatchTransformation</em> and click Finish</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/batch_transformation_wizard_type.png" alt="batch transformation wizard type">
</div>
<div class="title">Figure 10. Model Transformation Wizard - Type of the new transformation</div>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>In the created file we have to register a few extension methods, more specifically for our used queries (<code><code>CpsXformM2m</code></code>, the same name the VQL file uses) and the EMF EPackages we want to refer (here the deployment and traceability packages). A few additional extension methods are already registered, e.g. transformation rule builder and model manipulation API.</p>
</div>
<div id="bmt-codeextensions" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">/** VIATRA Query Pattern group **/
val extension CpsXformM2M cpsXformM2M = CpsXformM2M.instance
/** EMF metamodels **/
val extension DeploymentPackage depPackage = DeploymentPackage.eINSTANCE
val extension TraceabilityPackage trPackage = TraceabilityPackage.eINSTANCE</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Constructor will also initialize transformation (replace the generated one)</p>
<div class="ulist">
<ul>
<li>
<p>It assumes that the resource and trace models are already created</p>
</li>
<li>
<p>The IModelManipulations implementation is used to make model access replaceable, this way the same transformation may be used for cases where the resource set is transactional. The initialization of this is generated automatically into the <code>createTransformation</code> method.</p>
<div id="bmt-init" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">val CPSToDeployment cps2dep
new(CPSToDeployment cps2dep, ViatraQueryEngine engine) {
this.cps2dep = cps2dep
resource = cps2dep.deployment.eResource
this.engine = engine
prepare(engine)
createTransformation
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>Transformation will remain active until disposed is called (there is a generated <code>dispose</code> method in the class)</p>
</li>
<li>
<p>Create a rule to generate DeploymentHosts for each HostInstances</p>
<div class="ulist">
<ul>
<li>
<p>The <code>BatchTransformationRuleFactory</code> extension provides a builder API for rule definition</p>
</li>
<li>
<p>A VIATRA query is used as precondition to the rule, which means the rule will be activated each time the given pattern when changes allowing to update the output accordingly.</p>
<div id="bmt-rule-structure" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">val hostRule = createRule.precondition(HostInstance.instance).action[/*Action part*/].build</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>Specify which action to run when the rule fires. It will create the transformed <code>DeploymentHost</code> element in the output model as well as a trace element associating the source <code>HostInstance</code> and the target <code>DeploymentHost</code>:</p>
<div id="bmt-hostrule" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">val hostRule = createRule(HostInstance.instance).action[
val cpsHostInstance = it.hostInstance
val nodeIp = cpsHostInstance.nodeIp
println('''Mapping host with IP: «nodeIp»''')
/** Create &amp; initialize DeploymentHost in output model **/
val depHost = cps2dep.deployment.createChild(deployment_Hosts, deploymentHost) =&gt; [
set(deploymentHost_Ip, nodeIp)
]
/** Create trace element in trace model **/
cps2dep.createChild(CPSToDeployment_Traces, CPS2DeploymentTrace) =&gt; [
addTo(CPS2DeploymentTrace_CpsElements, cpsHostInstance)
addTo(CPS2DeploymentTrace_DeploymentElements, depHost)
]
println('''Mapped with IP: «nodeIp»''')
].build</code></pre>
</div>
</div>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Before version 2.1 the <code>createRule</code> method was parameterless and the query specification had to be provided in the <code>precondition</code> method. This was changed as the old API required some unexpected type casts when writing transformations in plain Java (instead of Xtend or Kotlin). This approach is still available in VIATRA 2.1, but it is marked as deprecated.
</td>
</tr>
</table>
</div>
<div class="ulist">
<ul>
<li>
<p>The rule which creates <code>DeploymentApplication</code> elements for <code>ApplicationInstance</code> objects, looks similar. It has to find the <code>DeploymentHost</code> created from the <code>HostInstance</code> to which the source <code>ApplicationInstance</code> is allocated, so it assumes the <code>hostRule</code> has already fired:</p>
<div id="bmt-apprule" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">val applicationRule = createRule(ApplicationInstance.instance).action[
val cpsApplicationInstance = it.appInstance
val appId = cpsApplicationInstance.identifier
println('''Mapping application with ID: «appId»''')
/* Find the DeploymentHost created from the HostInstance to which the source ApplicationInstance is allocated */
val cpsHostInstance = cpsApplicationInstance.allocatedTo
val depHost = engine.cps2depTrace.getAllValuesOfdepElement(null, null, cpsHostInstance).filter(DeploymentHost).head
/* Create &amp; initialize DeploymentApplication in this DeploymentHost */
val deploymentApplication = depHost.createChild(deploymentHost_Applications, deploymentApplication) =&gt; [
set(deploymentApplication_Id, appId)
]
/* Create trace element in trace model */
cps2dep.createChild(CPSToDeployment_Traces, CPS2DeploymentTrace) =&gt; [
addTo(CPS2DeploymentTrace_CpsElements, cpsApplicationInstance)
addTo(CPS2DeploymentTrace_DeploymentElements, deploymentApplication)
]
println('''Mapped application with ID: «appId»''')
].build</code></pre>
</div>
</div>
</li>
<li>
<p>Implement the method which performs the transformation using the rules defined above:</p>
<div class="ulist">
<ul>
<li>
<p>Since we are using the non-incremental (the whole model is always retransformed on model changes), the output and trace models are to be cleared before the any rule can fire</p>
</li>
<li>
<p>Pay attention to fire the rules in the proper order</p>
<div id="bme-execute" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">def execute() {
println('''Executing transformation on: Cyber-physical system: «cps2dep.cps.identifier»''')
/* Clear output &amp; trace model for batch transformation**/
cps2dep.deployment.hosts.clear
cps2dep.traces.clear
/* Fire transformation rules**/
hostRule.fireAllCurrent
applicationRule.fireAllCurrent
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_create_a_menu_command_to_execute_the_transformation"><a class="link" href="#_create_a_menu_command_to_execute_the_transformation">4.1.2. Create a menu command to execute the transformation</a></h4>
<div class="ulist">
<ul>
<li>
<p>Create a UI plugin with the following additional dependencies:</p>
<div id="bmt-ui-dependencies" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">org.eclipse.ui,
com.incquerylabs.course.cps.viatra.batch;bundle-version="0.1.0",
org.eclipse.viatra.examples.cps.traceability;bundle-version="0.1.0",
org.eclipse.viatra.query.runtime;bundle-version="1.2.0"</code></pre>
</div>
</div>
</li>
<li>
<p>Create handler implementation:</p>
<div id="bmt-handler" class="listingblock">
<div class="title">TransformHandler.java</div>
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public class TransformHandler extends AbstractHandler implements IHandler {
ViatraQueryEngine engine;
CPS2DeploymentTransformationViatra transformation;
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
IStructuredSelection selection =
(IStructuredSelection) HandlerUtil.getCurrentSelection(event);
CPSToDeployment tracemodel =
(CPSToDeployment) selection.getFirstElement();
if (engine == null){
try {
engine = ViatraQueryEngine.on(
new EMFScope(
tracemodel.eResource().getResourceSet()));
transformation = new CPS2DeploymentTransformationViatra(tracemodel,
engine);
} catch (ViatraQueryException e) {
throw new ExecutionException(e.getMessage(), e);
}
}
transformation.execute();
return null;
}
}</code></pre>
</div>
</div>
</li>
<li>
<p>Register handler in the context menu of <code>CPSToDeployment</code> elements in <code>plugin.xml</code>:</p>
<div id="bmt-command" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;extension point="org.eclipse.ui.commands"&gt;
&lt;command
defaultHandler="com.incquerylabs.course.cps.viatra.batch.ui.TransformHandler"
id="com.incquerylabs.course.cps.viatra.batch.ui.command"
name="Transform"&gt;
&lt;/command&gt;
&lt;/extension&gt;
&lt;extension point="org.eclipse.ui.menus"&gt;
&lt;menuContribution allPopups="false"
locationURI="popup:org.eclipse.ui.popup.any?after=additions"&gt;
&lt;command commandId="com.incquerylabs.course.cps.viatra.batch.ui.command"
style="push"&gt;
&lt;visibleWhen checkEnabled="false"&gt;
&lt;with variable="selection"&gt;
&lt;count value="1"&gt;
&lt;/count&gt;
&lt;iterate&gt;
&lt;adapt type="org.eclipse.viatra.examples.cps.traceability.CPSToDeployment"&gt;
&lt;/adapt&gt;
&lt;/iterate&gt;
&lt;/with&gt;
&lt;/visibleWhen&gt;
&lt;/command&gt;
&lt;/menuContribution&gt;
&lt;/extension&gt;</code></pre>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_execute_the_transformation"><a class="link" href="#_execute_the_transformation">4.1.3. Execute the transformation</a></h4>
<div class="ulist">
<ul>
<li>
<p>Launch <em>Eclipse Application</em></p>
</li>
<li>
<p>Create a generic resource project</p>
</li>
<li>
<p>Copy a <code>.cyberphysicalsystem</code> resource in it if you already have one, or create a new <em>CyberPhysicalSystem Model</em></p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatraIncr_example1.png" alt="viatraIncr example1">
</div>
<div class="title">Figure 11. Project with a .cyberphysicalsystem resource</div>
</div>
</li>
<li>
<p>Create a Deployment model</p>
<div class="ulist">
<ul>
<li>
<p>Root element shall be <em>Deployment</em></p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatraIncr_example2.png" alt="viatraIncr example2">
</div>
<div class="title">Figure 12. New Deployment Model</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>Create a Traceability model</p>
<div class="ulist">
<ul>
<li>
<p>Root element shall be <em>CPS To Deployment</em></p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatraIncr_example3.png" alt="viatraIncr example3">
</div>
<div class="title">Figure 13. New Traceability Model</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>In the Traceability editor, load both CPS and Deployment models with <em>Load Resources...</em> in the context menu</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatraIncr_example4.png" alt="viatraIncr example4">
</div>
<div class="title">Figure 14. Load necessary resources into the Tracebility Model</div>
</div>
</li>
<li>
<p>Set CPS and Deployment references of traceability model in the properties view</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatraIncr_example5.png" alt="viatraIncr example5">
</div>
<div class="title">Figure 15. Set the references of the Traceability Model</div>
</div>
</li>
<li>
<p>Create a new <em>HostType</em>, <em>HostInstance</em>, <em>ApplicationType</em> and <em>ApplicationInstance</em> in the Deployment model</p>
</li>
<li>
<p>Execute transformation using the created command (on the context menu of the Traceability model root)</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatrabatch.png" alt="viatrabatch">
</div>
<div class="title">Figure 16. Transformation command in the context menu</div>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_references_2"><a class="link" href="#_references_2">4.1.4. References</a></h4>
<div class="ulist">
<ul>
<li>
<p>VIATRA Transformation API: <a href="transformations.html" class="bare">transformations.html</a></p>
</li>
<li>
<p>Further transformation examples: <a href="https://wiki.eclipse.org/VIATRA/Transformation/Examples" class="bare">https://wiki.eclipse.org/VIATRA/Transformation/Examples</a></p>
</li>
</ul>
</div>
<div style="page-break-after: always;"></div>
</div>
</div>
<div class="sect2">
<h3 id="_event_driven_transformations"><a class="link" href="#_event_driven_transformations">4.2. Event-driven Transformations</a></h3>
<div class="paragraph">
<p>This exercise heps the audience to create a simple event-driven transformation using the VIATRA Transformation API. The transformation will create (and then incrementally update while active) a deployment model based on a CPS model. The exercise also covers registering a menu command which initializes the transformation.</p>
</div>
<div class="paragraph">
<p>Given the batch and event-driven transformations are really similar, this section focuses mainly on the differences; if required, consult the <a href="#_batch_transformations">batch transformation tutorial</a>.</p>
</div>
<div class="sect3">
<h4 id="_create_transformation_2"><a class="link" href="#_create_transformation_2">4.2.1. Create transformation</a></h4>
<div class="paragraph">
<p>Specific patterns have to be defined for event-driven rules; note that there are small differences to the batch definitions, e.g. there is an additional pattern called <em>allocatedDeploymentApplication</em>.</p>
</div>
<div id="emt-queries" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vql" data-lang="vql">import "http://org.eclipse.viatra/model/cps"
import "http://org.eclipse.viatra/model/deployment"
import "http://org.eclipse.viatra/model/cps-traceability"
pattern hostInstance(hostInstance) {
HostInstance(hostInstance);
}
pattern applicationInstance(appType, appInstance){
HostInstance.applications(_, appInstance);
ApplicationType.instances(appType, appInstance);
}
pattern allocatedDeploymentApplication(depHost, depApp) {
DeploymentHost.applications(depHost, depApp);
}
pattern cps2depTrace(cps2dep, trace, cpsElement, depElement) {
CPSToDeployment.traces(cps2dep, trace);
CPS2DeploymentTrace.cpsElements(trace, cpsElement);
CPS2DeploymentTrace.deploymentElements(trace, depElement);
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Create transformation class (preferably Xtend)</p>
<div class="ulist">
<ul>
<li>
<p>Create new <em>Model Transformation</em> with the wizard</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/transformation_wizard.png" alt="transformation wizard">
</div>
<div class="title">Figure 17. Model Transformation Wizard - Create new transformation</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Setup the name of the transformation and click Next</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/eventdriven_transformation_wizard_name.png" alt="eventdriven transformation wizard name">
</div>
<div class="title">Figure 18. Model Transformation Wizard - Name of the new event-driven transformation</div>
</div>
</li>
<li>
<p>Setup the type of the transformation to <em>EventDrivenTransformation</em> and click Finish</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/eventdriven_transformation_wizard_type.png" alt="eventdriven transformation wizard type">
</div>
<div class="title">Figure 19. Model Transformation Wizard - Type of the new transformation</div>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>Register used, domain-specific APIs as extensions, common APIs are already generated</p>
<div id="emt-extensions" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">/*
* VIATRA Query group
*/
val extension CpsXformM2M cpsXformM2M = CpsXformM2M.instance
/*
* EMF metamodels
*/
val extension DeploymentPackage depPackage = DeploymentPackage::eINSTANCE
val extension TraceabilityPackage trPackage = TraceabilityPackage::eINSTANCE</code></pre>
</div>
</div>
</li>
<li>
<p>Constructor will also initialize transformation (replace the generated one)</p>
<div class="ulist">
<ul>
<li>
<p>It assumes that the output and trace models are already created</p>
</li>
<li>
<p>The IModelManipulations implementation is used to make model access replaceable, this way the same transformation may be used for cases where the resource set is transactional</p>
<div id="emt-init" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">val CPSToDeployment cps2dep
new(CPSToDeployment cps2dep, ViatraQueryEngine engine) {
this.cps2dep = cps2dep
this.resource = cps2dep.deployment.eResource
this.engine = engine
prepare(engine)
createTransformation
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>Transformation will remain active until dispose is called (a <code>dispose</code> method is already generated)</p>
</li>
<li>
<p>Create a rule to create DeploymentHosts for each HostInstances</p>
<div class="ulist">
<ul>
<li>
<p>The EventDrivenTransformationRuleFactory extension provides a builder API for rule definition</p>
</li>
<li>
<p>A VIATRA query pattern is used as precondition to the rule, which means the rule will be activated each time the given pattern changes allowing to update the output accordingly.</p>
<div id="emt-rule-structure" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">val hostRule = createRule(HostInstanceMatcher.querySpecification)</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Before version 2.1 the <code>createRule</code> method was parameterless and the query specification had to be provided in the <code>precondition</code> method. This was changed as the old API required some unexpected type casts when writing transformations in plain Java (instead of Xtend or Kotlin). This approach is still available in VIATRA 2.1, but it is marked as deprecated.
</td>
</tr>
</table>
</div>
<div class="ulist">
<ul>
<li>
<p>Add action for each kind of changes in the pattern to update trace and output models:</p>
<div class="ulist">
<ul>
<li>
<p>upon creation of a HostInstance</p>
<div id="emt-hostrule" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">.action(CRUDActivationStateEnum.CREATED) [
val hostinstance = hostInstance
val nodeIp = hostInstance.nodeIp
println('''Mapping host with IP: «nodeIp»''')
/* Create new DeploymentHost element in output model */
val host = cps2dep.deployment.createChild(deployment_Hosts, deploymentHost) =&gt; [
set(deploymentHost_Ip, nodeIp)
]
/* Create trace entry */
cps2dep.createChild(CPSToDeployment_Traces, CPS2DeploymentTrace) =&gt; [
addTo(CPS2DeploymentTrace_CpsElements, hostinstance)
addTo(CPS2DeploymentTrace_DeploymentElements, host)
]
]</code></pre>
</div>
</div>
</li>
<li>
<p>upon the change of a HostInstance</p>
<div id="emt-hostupdated" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">.action(CRUDActivationStateEnum.UPDATED) [
/* find associated DeploymentHost element */
val depHost = engine.cps2depTrace
.getOneArbitraryMatch(cps2dep, null, hostInstance, null)
.depElement as DeploymentHost
val hostIp = depHost.ip
println('''Updating mapped host with IP: «hostIp»''')
/* update IP attribute */
val nodeIp = hostInstance.nodeIp
depHost.set(deploymentHost_Ip, nodeIp)
println('''Updated mapped host with IP: «nodeIp»''')
]</code></pre>
</div>
</div>
</li>
<li>
<p>upon the removal of a HostInstance</p>
<div id="emt-hostdeleted" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">.action(CRUDActivationStateEnum.DELETED) [
/* Find trace element */
val traceMatch = engine.cps2depTrace
.getOneArbitraryMatch(cps2dep, null, hostInstance, null)
val hostIp = hostInstance.nodeIp
println('''Removing host with IP: «hostIp»''')
/* Remove DeploymentHost element */
cps2dep.deployment.remove(deployment_Hosts, traceMatch.depElement)
/* Remove trace */
cps2dep.remove(CPSToDeployment_Traces, traceMatch.trace)
println('''Removed host with IP: «hostIp»''')
]</code></pre>
</div>
</div>
</li>
<li>
<p>Add default activation lifecycle then build the rule:</p>
<div class="ulist">
<ul>
<li>
<p>The lifecycle defines the state machine used to determine the possible states on which transition actions can defined.</p>
<div id="emt-lifecycle" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">.addLifeCycle(Lifecycles.getDefault(true, true)).build</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>The rule which create DeploymentApplication elements for ApplicationInstances, looks similar</p>
<div id="emt-applicationrule" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">val applicationRule = createRule(ApplicationInstanceMatcher.querySpecification)
.action(CRUDActivationStateEnum.CREATED) [
/* Find associated DeploymentHost for the HostInstance this application is allocated to */
val depHost = engine.cps2depTrace.getAllValuesOfdepElement(null, null, appInstance.allocatedTo).filter(
DeploymentHost).head
val appinstance = appInstance
val appId = appInstance.identifier
println('''Mapping application with ID: «appId»''')
/* Create DeploymentApplication application in host */
val app = depHost.createChild(deploymentHost_Applications, deploymentApplication) =&gt; [
set(deploymentApplication_Id, appId)
]
/* create trace entry */
cps2dep.createChild(CPSToDeployment_Traces, CPS2DeploymentTrace) =&gt; [
addTo(CPS2DeploymentTrace_CpsElements, appinstance)
addTo(CPS2DeploymentTrace_DeploymentElements, app)
]
println('''Mapped application with ID: «appId»''')
].action(CRUDActivationStateEnum.UPDATED) [
/* find associated DeploymentApplication */
val depApp = engine.cps2depTrace.getOneArbitraryMatch(cps2dep, null, appInstance, null).
depElement as DeploymentApplication
/* Update ID */
if (depApp.id != appInstance.identifier)
depApp.set(deploymentApplication_Id, appInstance.identifier)
].action(CRUDActivationStateEnum.DELETED) [
/* find associated DeploymentApplication */
val trace = engine.cps2depTrace.getAllValuesOftrace(null, appInstance, null).head as CPS2DeploymentTrace
val depApp = trace.deploymentElements.head as DeploymentApplication
/* Remove application from host */
engine.allocatedDeploymentApplication.getAllValuesOfdepHost(depApp).head.remove(deploymentHost_Applications, depApp)
/* Remove traces */
cps2dep.remove(CPSToDeployment_Traces, trace)
].addLifeCycle(Lifecycles.getDefault(true, true)).build</code></pre>
</div>
</div>
</li>
<li>
<p>Replace the generated <code>createTransformation</code> using the rules defined above</p>
<div class="ulist">
<ul>
<li>
<p>For cases when it is possible to have more than one rules activated (e.g. a new HostInstance is added to the model with already set allocated applications) a conflict resolver is used to provide a fixed ordering of rules to be executed.</p>
</li>
<li>
<p>We use a priority-based resolver (lower priority rules will be executed first), which considers priority of disappearing rules to be inverted (a disappearing application&#8217;s priority will be -2)</p>
<div id="emt-create" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">private def createTransformation() {
//Initialize model manipulation API
this.manipulation = new SimpleModelManipulations(engine)
//Initialize event-driven transformation
val fixedPriorityResolver = new InvertedDisappearancePriorityConflictResolver
fixedPriorityResolver.setPriority(hostRule.ruleSpecification, 1)
fixedPriorityResolver.setPriority(applicationRule.ruleSpecification, 2)
transformation = EventDrivenTransformation.forEngine(engine)
.setConflictResolver(fixedPriorityResolver)
.addRule(hostRule)
.addRule(applicationRule)
.build
}</code></pre>
</div>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_creating_a_menu_command_to_execute_the_transformation"><a class="link" href="#_creating_a_menu_command_to_execute_the_transformation">4.2.2. Creating a menu command to execute the transformation</a></h4>
<div class="ulist">
<ul>
<li>
<p>Create UI plugin</p>
</li>
<li>
<p>Add dependencies:</p>
<div id="emt-dependencies" class="listingblock">
<div class="title">MANIFEST.MF</div>
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">org.eclipse.ui,
com.incquerylabs.course.cps.viatra.incr;bundle-version="0.1.0",
org.eclipse.viatra.examples.cps.traceability;bundle-version="0.1.0",
org.eclipse.viatra.query.runtime;bundle-version="1.2.0"</code></pre>
</div>
</div>
</li>
<li>
<p>Create handler implementations:</p>
<div id="emt-handler" class="listingblock">
<div class="title">ToggleTransformationHandler.java</div>
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">public class ToggleTransformationHandler extends AbstractHandler implements IHandler {
ViatraQueryEngine engine;
CPS2DeploymentTransformationViatra transformation;
/* (non-Javadoc)
* @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
*/
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
IStructuredSelection selection =
(IStructuredSelection) HandlerUtil.getCurrentSelection(event);
CPSToDeployment tracemodel =
(CPSToDeployment) selection.getFirstElement();
if(transformation == null) {
if(engine == null) {
try {
engine = ViatraQueryEngine.on(
new EMFScope(
tracemodel.eResource()
.getResourceSet()));
transformation =
new CPS2DeploymentTransformationViatra(tracemodel,
engine);
} catch (ViatraQueryException e) {
throw new ExecutionException(e.getMessage(), e);
}
}
} else {
transformation.dispose();
}
return null;
}
}</code></pre>
</div>
</div>
</li>
<li>
<p>Register handler in the context menu of "CPSToDeployment" elements</p>
<div id="emt-command" class="listingblock">
<div class="title">plugin.xml</div>
<div class="content">
<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;extension point="org.eclipse.ui.commands"&gt;
&lt;command defaultHandler="com.incquerylabs.course.cps.viatra.incr.ui.ToggleTransformationHandler"
id="com.incquerylabs.course.cps.viatra.incr.ui.command"
name="Toggle Transformation"&gt;
&lt;/command&gt;
&lt;/extension&gt;
&lt;extension point="org.eclipse.ui.menus"&gt;
&lt;menuContribution allPopups="false"
locationURI="popup:org.eclipse.ui.popup.any?after=additions"&gt;
&lt;command commandId="com.incquerylabs.course.cps.viatra.incr.ui.command"
label="Toggle Incremental Transformation"
style="push"&gt;
&lt;visibleWhen checkEnabled="false"&gt;
&lt;with variable="selection"&gt;
&lt;count value="1"&gt;
&lt;/count&gt;
&lt;iterate&gt;
&lt;adapt type="org.eclipse.viatra.examples.cps.traceability.CPSToDeployment"&gt;
&lt;/adapt&gt;
&lt;/iterate&gt;
&lt;/with&gt;
&lt;/visibleWhen&gt;
&lt;/command&gt;
&lt;/menuContribution&gt;
&lt;/extension&gt;</code></pre>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_executing_the_transformation"><a class="link" href="#_executing_the_transformation">4.2.3. Executing the transformation</a></h4>
<div class="ulist">
<ul>
<li>
<p>Launch runtime eclipse</p>
</li>
<li>
<p>Create a generic resource project</p>
</li>
<li>
<p>Copy a <code>.cyberphysicalsystem</code> resource in it</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatraIncr_example1.png" alt="viatraIncr example1">
</div>
<div class="title">Figure 20. Project with a .cyberphysicalsystem resource</div>
</div>
</li>
<li>
<p>Create an empty Deployment model</p>
<div class="ulist">
<ul>
<li>
<p>Root element shall be Deployment</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatraIncr_example2.png" alt="viatraIncr example2">
</div>
<div class="title">Figure 21. New Deployment Model</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>Create a Traceability model</p>
<div class="ulist">
<ul>
<li>
<p>Root element shall be "CPS To Deployment"</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatraIncr_example3.png" alt="viatraIncr example3">
</div>
<div class="title">Figure 22. New Traceability Model</div>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>In the Traceability editor, load both CPS and Deployment models with "Load Resources.." in the context menu</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatraIncr_example4.png" alt="viatraIncr example4">
</div>
<div class="title">Figure 23. Load necessary resources into the Traceability Model</div>
</div>
</li>
<li>
<p>Set CPS and Deployment references of traceability model in the properties view</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatraIncr_example5.png" alt="viatraIncr example5">
</div>
<div class="title">Figure 24. Set the references of the Traceability Model</div>
</div>
</li>
<li>
<p>Toggle transformation using the created command (on the context menu of the Traceability model root)</p>
<div class="imageblock">
<div class="content">
<img src="./images/tutorial/viatraIncr_example6.png" alt="viatraIncr example6">
</div>
<div class="title">Figure 25. Toggle transformation in the context menu</div>
</div>
</li>
<li>
<p>Initial activation done on first modification of the input model, e.g. create a new HostType</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_references_3"><a class="link" href="#_references_3">4.2.4. References</a></h4>
<div class="ulist">
<ul>
<li>
<p>VIATRA Transformation API: <a href="transformations.html" class="bare">transformations.html</a></p>
</li>
<li>
<p>Further transformation examples: <a href="https://wiki.eclipse.org/VIATRA/Transformation/Examples" class="bare">https://wiki.eclipse.org/VIATRA/Transformation/Examples</a></p>
</li>
</ul>
</div>
<div style="page-break-after: always;"></div>
</div>
</div>
<div class="sect2">
<h3 id="_debugging_model_transformations"><a class="link" href="#_debugging_model_transformations">4.3. Debugging model transformations</a></h3>
<div class="paragraph">
<p>The development and debugging of model transformations is not a trivial exercise, the basic concepts of software debugging however can be mapped to this field as well. Debuggers can be used for detecting bugs, as well as better understanding the structure and behavior of programs. Direct control over a program allows the programmer to follow the flow of execution or stop the program at any desired point. Then it is possible to inspect its current state and verify the correctness of the software. These properties are very desirable in the field of model transformations too.
The VIATRA framework incorporates a debugger framework that supports the following features:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Display the state of remote VIATRA transformations.</p>
</li>
<li>
<p>Allow the user to control the execution of VIATRA transformations, via standard debugger commands ("Step over", "Continue") or by selecting the next activation to be executed.</p>
</li>
<li>
<p>Display the model instances associated with the transformation under debugging.</p>
</li>
<li>
<p>Allow the user to define various transformation breakpoints.</p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
The model transformation debugger described in this section requires the <code>VIATRA Query and Transformation SDK Extensions (Incubation)</code> component to be installed from the VIATRA repository. The debugger in its current form is considered experimental, and both the feature set and API setup is subject to change in future releases of VIATRA.
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="_setting_up_the_transformation_under_debugging"><a class="link" href="#_setting_up_the_transformation_under_debugging">4.3.1. Setting Up the Transformation Under Debugging</a></h4>
<div class="paragraph">
<p>In order to support debugging, the model transformation definition needs minor modifications. These can be done in two different ways:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>If the transformation is being newly developed, it is highly advised to use the VIATRA model transformation creation wizard. As shown on the figure below, the user can select the "VIATRA debugger support" checkbox, this way the generated code will incorporate the appropriate setup.</p>
</li>
<li>
<p>In case of an already-existing transformation, the model transformation definition needs to be modified manually. This involves adding the VIATRA debug configuration to the VIATRA transformation builder (requiring an additional dependency to the plugin <code>org.eclipse.viatra.transformation.runtime.debug</code>). The following example snippet shows how this is achieved for the example.</p>
</li>
</ul>
</div>
<div id="Transformation-setup" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-Java" data-lang="Java">// New import declaration
import org.eclipse.viatra.transformation.debug.configuration.TransformationDebuggerConfiguration
public class CPS2DeploymentTransformationViatra {
...
private def createTransformation() {
...
// Initializes a debugger configuration with the name `TestTransformation`
val debugger = new TransformationDebuggerConfiguration("TestTransformation")
transformation = BatchTransformation
.forEngine(engine)
// Adds the debugger configuration to the transformation
.addAdapterConfiguration(debugger)
.build
...
}
...
}</code></pre>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Here we replace the previously created transformation to always start with debugging enabled. If necessary, the addition of the adapters could be made configurable by the transformation developer and separate menu items can be added as necessary.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The transformation debugger configuration registers a runtime agent that blocks transformation execution until a debugger client connects via JMX. For the agent to work, a few command line parameters to be specified:</p>
</div>
<div id="Transformation-vmargs" class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-Java" data-lang="Java">-Dcom.sun.management.jmxremote.port="port to be used, typically 1099"
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_using_the_debugger_ui"><a class="link" href="#_using_the_debugger_ui">4.3.2. Using the Debugger UI</a></h4>
<div class="paragraph">
<p>The following section describes how to use the VIATRA transformation debugger UI elements once the debugging infrastructure is set up. This section of the guide assumes that a target Eclipse instance is running.</p>
</div>
<div class="sect4">
<h5 id="_connecting_to_the_transformation_under_debugging"><a class="link" href="#_connecting_to_the_transformation_under_debugging">4.3.2.1. Connecting to the transformation under debugging</a></h5>
<div class="ulist">
<ul>
<li>
<p>If the VIATRA debugger feature is installed, the Debugger UI Elements are contained by the Eclipse Debug perspective, once this perspective is selected, the related VIATRA debug views are displayed.</p>
</li>
</ul>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/debug_persp_empty.png" alt="Debug perspective">
</div>
<div class="title">Figure 26. Debug perspective with debugger views</div>
</div>
<div class="ulist">
<ul>
<li>
<p>The debugger can be initialized via launching a <em>VIATRA Transformation Remote Debugging</em> debug configuration. The debug configuration can be specified similarly to any other Eclipse launch configuration. As the figure below shows, firstly, the target port needs to be specified. This value needs to be equal to the port value specified in the target Eclipse launch configuration (typically its 1099).</p>
</li>
<li>
<p>Next the port needs to be queried, via using the button located next to the port text field.</p>
</li>
<li>
<p>After the querying is completed, the user can select from a set of transformation instances that are present on that port.</p>
</li>
<li>
<p>Finally, a class file present in the workspace needs to be selected, as the breakpoints associated with the transformation will be bound to the resource of this file.</p>
</li>
</ul>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/debug_newlaunch.png" alt="Class selection">
</div>
<div class="title">Figure 27. Editing launch configuration</div>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/newtransf_classsel.png" alt="Class selection">
</div>
<div class="title">Figure 28. Selecting a class</div>
</div>
<div class="ulist">
<ul>
<li>
<p>These launch configurations are saved, once the user defines a configuration for a target transformation, it can be reused without any required modifications (Assuming that the user did not modify the ID of the transformation session).</p>
</li>
<li>
<p>After launching the debug configuration, the debug session is initialized allowing the user to observe and control the execution of the selected transformation. Here the transformation debugging session is displayed in the Eclipse debug view. There are however additional contemporary views that display the details of the selected debug session.</p>
</li>
</ul>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/debug_persp.png" alt="Debug perspective">
</div>
<div class="title">Figure 29. Debugger in its initialized state</div>
</div>
</div>
<div class="sect4">
<h5 id="_browsing_the_transformation_state"><a class="link" href="#_browsing_the_transformation_state">4.3.2.2. Browsing the transformation state</a></h5>
<div class="paragraph">
<p>One of the main use-cases of the VIATRA transformation debugger, is to enable the transformation developer to observe the state of a VIATRA transformation at certain point in its execution sequence. The debugger allows the transformation developer to observe the following transformation elements:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Active transformation rule activations</p>
</li>
<li>
<p>Input and output model instances</p>
</li>
<li>
<p>The input parameters of the next Activation</p>
</li>
</ul>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
In order to use the debugger UI elements, select the Debug Stack trace representing the transformation:
</td>
</tr>
</table>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/selectthread.png" alt="Select transformation stack frame">
</div>
<div class="title">Figure 30. Selecting the transformation stack frame</div>
</div>
<div class="paragraph">
<p>The <em>Transformation Browser</em> view is responsible for observing the internal state of the transformation. It allows the user to observe the current transformation rule activations, and it supports the definition of various transformation breakpoints.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/transformation_rules.png" alt="TB rules">
</div>
<div class="title">Figure 31. Transformation Browser ordered by transformation rules</div>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/conflict_set.png" alt="TB conflict set">
</div>
<div class="title">Figure 32. Transformation Browser ordered by EVM Conflict Set state</div>
</div>
<div class="paragraph">
<p>The <em>Transformation Model Instance Viewer</em> enables the transformation developer to observe the state of the source and target model instances related to the model transformation selected in the <em>Adaptable Transformation Browser</em> view. This view displays the model instances in a multi-tabbed tree view with properties view support.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/model_browser.png" alt="VTB view">
</div>
<div class="title">Figure 33. VIATRA model instance browser view</div>
</div>
<div class="paragraph">
<p>The parameters of the next activation to be executed can be observed via the <em>Variables</em> Eclipse Debug View. After selecting the given debug stack frame (representing a transformation rule activation), the parameters of the transformation rule precondition are displayed as variables.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/variables_view.png" alt="Variables view">
</div>
<div class="title">Figure 34. VIATRA transformation preconditions as Variables</div>
</div>
</div>
<div class="sect4">
<h5 id="_controlling_the_transformation_execution_sequence"><a class="link" href="#_controlling_the_transformation_execution_sequence">4.3.2.3. Controlling the transformation execution sequence</a></h5>
<div class="paragraph">
<p>The VIATRA transformation debugger enables the transformation developer to control the execution sequence of the transformation under debugging. This can be done in the following ways.</p>
</div>
<div class="sect5">
<h6 id="_using_breakpoints_and_standard_debug_commands"><a class="link" href="#_using_breakpoints_and_standard_debug_commands">Using Breakpoints and standard debug commands</a></h6>
<div class="paragraph">
<p>The Transformation debugger supports the following breakpoints:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><em>Activation breakpoint</em>: Activation breakpoints can be toggled via selecting a rule activation and using the appropriate command on the <em>Transformation Browser</em> view.</p>
</li>
<li>
<p><em>Rule Breakpoint</em>: Rule breakpoints can be created via selecting a model transformation instance and using the appropriate UI element. Once this is done, the following dialog opens, on which the transformation developer can specify the name of the transformation rule. Once an activation is about to be executed, the debugger checks if the activation derives from the rule associated with the specified name. If this condition is true, the execution is halted.</p>
</li>
<li>
<p><em>Conditional breakpoint</em>: These breakpoints allow the user to define VIATRA Query based conditions to halt the execution of the transformation. In order to create a conditional breakpoint, select a model transformation instance in the <em>Transformation Browser</em> view, and use the appropriate command on the view&#8217;s command bar. Afterwards, a dialog window opens which allows the user to define VIATRA query patterns. The execution of the transformation is halted once the match set of the pattern changes.</p>
</li>
</ul>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/rule_breakpoint.png" alt="Rule breakpoint definition">
</div>
<div class="title">Figure 35. Rule breakpoint definition dialog</div>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/conditional_breakpoint.png" alt="Conditional breakpoint definition">
</div>
<div class="title">Figure 36. Conditional breakpoint definition dialog</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
This editor reuses the standard Xtext based VIATRA query editor, however in this case, package definitions should be omitted (as there is no enclosed Eclipse resource to the file). Furthermore, the definition can contain only one public pattern at this point, this restriction, however, does not apply to private patterns.
</td>
</tr>
</table>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
The Debugger runtime component reuses the VIATRA Query language parser infrastructure to parse the patterns contained in <em>conditional breakpoints</em>. The debugger runtime component explicitly does not require classes of the parser infrastructure to be loaded (in order to minimize the dependencies of said runtime component). Make sure however, if <em>conditional breakpoints</em> are used, the target platform on which the transformation under debugging is running should contain the VIATRA Query Tooling UI elements, and they should be initialized as well. If these required steps are omitted, the debugger produces the following error message:
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
The rule and conditional breakpoints are persisted between individual transformation debugging sessions. The breakpoints are contained in a common breakpoint pool managed by the Eclipse Breakpoint Manager.
</td>
</tr>
</table>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
The breakpoints added are displayed in the <em>Breakpoints</em> Eclipse Debug view. Which can be used to disable and remove these breakpoints.
</td>
</tr>
</table>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/conditional_breakpoint_parseerror.png" alt="Conditional breakpoint parsing error">
</div>
<div class="title">Figure 37. Conditional breakpoint error dialog</div>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/breakpoints_view.png" alt="Eclipse Breakpoints view">
</div>
<div class="title">Figure 38. Transformation breakpoints in the Eclipse Breakpoints view</div>
</div>
<div class="paragraph">
<p>The debugger supports the following Eclipse debug commands:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Step Over (F6)</dt>
<dd>
<p>If the transformation execution is halted, use this command the execute the next activation, and stop the execution again.</p>
</dd>
<dt class="hdlist1">Resume (F8)</dt>
<dd>
<p>If the transformation execution is halted, use this command to continue the execution of the transformation until a breakpoint is hit.</p>
</dd>
<dt class="hdlist1">Terminate (Ctrl+F2)</dt>
<dd>
<p>The transformation is resumed and the debugger agent is disconnected from the target transformation. The transformation debugging session is terminated.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>A few debug commands are not supported for now, including <em>Step Return</em>, <em>Step Into</em>, <em>Suspend</em> and <em>Disconnect</em>.</p>
</div>
</div>
<div class="sect5">
<h6 id="_directly_selecting_the_next_transformation_activation_to_be_fired"><a class="link" href="#_directly_selecting_the_next_transformation_activation_to_be_fired">Directly selecting the next transformation activation to be fired</a></h6>
<div class="paragraph">
<p>The transformation debugger allows the user to define which activation should be executed next. In order to do this, select an activation and use the appropriate command to set it as the next activation to be executed.</p>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
The changes made this ways could produce unpredictable behavior in the model transformation (Overriding the defined priority could result in inconsistent model states). Use this feature cautiously.
</td>
</tr>
</table>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/select_next.png" alt="Select next activation">
</div>
<div class="title">Figure 39. Selecting the next activation</div>
</div>
<div class="paragraph">
<p>Once the next activation is selected, notice that the red rectangle representing, the next activation to be fired, is moved to the desired activation. At this point, if the transformation is resumed, it will continue its execution from the selected activation.</p>
</div>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_common_issues"><a class="link" href="#_common_issues">4.3.3. Common issues</a></h4>
<div class="sect4">
<h5 id="_trying_to_connect_to_an_unreachable_viatra_transformation_instance"><a class="link" href="#_trying_to_connect_to_an_unreachable_viatra_transformation_instance">4.3.3.1. Trying to connect to an unreachable VIATRA transformation instance</a></h5>
<div class="paragraph">
<p>If the VIATRA transformation instance specified in the debugger launch configuration does not exist, the debugger tooling will inform the user, that the debugging session could not be initialized and terminate the newly created session as well.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/connection_error.png" alt="Debugger Connection Error">
</div>
<div class="title">Figure 40. Debugger Connection Error</div>
</div>
</div>
<div class="sect4">
<h5 id="_transformation_under_debugging_terminated_abruptly"><a class="link" href="#_transformation_under_debugging_terminated_abruptly">4.3.3.2. Transformation under debugging terminated abruptly.</a></h5>
<div class="paragraph">
<p>If the eclipse instance in which the target transformation is running is terminated, or the connection is severed between the host and target components, the debugger tooling will terminate the respective VIATRA debugger launch automatically.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/automatic_termination.png" alt="Automatic termination">
</div>
<div class="title">Figure 41. Automatic termination</div>
</div>
</div>
<div class="sect4">
<h5 id="_trying_to_add_a_conditional_breakpoint_but_the_xtext_parser_infrastructure_is_not_initialized"><a class="link" href="#_trying_to_add_a_conditional_breakpoint_but_the_xtext_parser_infrastructure_is_not_initialized">4.3.3.3. Trying to add a conditional breakpoint, but the Xtext parser infrastructure is not initialized.</a></h5>
<div class="paragraph">
<p>In order to ensure that the conditional breakpoint patterns are parsed properly in the runtime Eclipse instance, the Xtext parser infrastructure needs to be initialized. If the debugger tooling produces the following exception, open a VIATRA query view (e.g.: VIATRA Query Explorer) to manually initialize the parser tooling. These manual steps are needed, as Xtext-based parser tooling components are loaded lazily.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="./images/transformation/screenshots/conditional_breakpoint_parseerror.png" alt="Conditional breakpoint parsing error">
</div>
<div class="title">Figure 42. Conditional breakpoint error dialog</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>hljs.initHighlighting()</script>
</div>
<div class="clear"></div>
<ng-include src="'/viatra/angular/blocks/footer.html'"></ng-include>
</body>
</html>