contributed by Christian Krause
This tutorial shows some of the basic concepts of the Henshin transformation language and tool environment. The example transformation is endogenous, meaning that it operates on a single metamodel. We explain how to define transformation rules using Henshin's integrated graphical editor, and how to use the interpreter (wizard and programmatically) to execute rules on an example model.
The transformation model, example input models and source code can be found here.
The class Bank serves as a root container for all other classes. Every bank owns a number of accounts, each with a unique ID and the current credit Two types of persons are distinguished: managers and clients. Every client is associated with at most one manager and can own a number of accounts in the bank. Note that the references between Account and Client, and Manager and Client are bidirectional. Therefore, it is for example not only possible to obtain all accounts of a given client, but also to find out to which client a given account belongs to.
We define a couple of transformation rules for the above metamodel. We use the integrated graphical editor of Henshin. To set-up the transformation, go to File → New → Other → Henshin → Henshin transformation Diagram. This wizard will create two files, one for storing the transformation model and one for the diagram information (e.g. bank.henshin and bank.henshin_diagram). When the wizard is finished, an empty diagram file is created and opened in the graphical editor. Now you need to import the metamodel for which you want to define a transformation. This can be done by right-clicking in the empty editor and selecting Import Package... → From Workspace. Then select the file bank.ecore and within this file the package bank. If the import was successfull you will see all classes of the metamodel appearing in the palette of the editor.
To create a new transformation rule, use the Rule tool in the palette. In the top of every rule, its name and parameters are specified (and some optional information which we do not consider here). In the below example, we write createAccount(client, accountId), where the client parameter is the name of the client for whom an account should be created, and accountId is the ID to be used for the new account.
Nodes: Inside of the rule, we now create a number of nodes now, as shown in the screenshot below. For example, to create the bank node in the top, you can use the Bank tool in the palette. After you have created the node, you can change its name and also its type. For changing the name of this object to bank click on the name label of the node and enter bank:Bank. Note that these names can be important when you want to pass an object as a parameter of the rule. In this case you would add bank to the list of the rule.
Edges: To specify a link between two nodes use the tool Edge in the palette and draw a line between two lines. This is possible only if the metamodel contains a reference between the two corresponding classes. If multiple references are possible, you can choose from a pop-up menu.
Attributes: Attributes can be created within nodes and are specified by the name of the attribute and an '=' followed by an expression which is evaluated during the rule application.
Actions: Nodes and edges are annotated with stereotypes which we refer to as actions. A number of actions are supported: «preserve» matches an object and preserves it during the rule application, «create» creates a new object or link between objects, «delete» deletes an existing object or link, «forbid» forbid the existience of an object or link. Note that these are the basic actions, which can be further parameterized (see below).
The rule createAccount(client,accountId)
matches a bank, a client with the name given in the rule parameter client
and the client's manager. The rule creates a new account for the client and sets
its ID to the value given in accountId. The rule is applicable only if now
other account exists already with the same ID.
We now show how to execute single transformation rules using the Henshin interpreter, invoked through a dialog. To run this dialog, open the *.henshin file, right-click on a rule or a transformation and select Apply Transformation in the context menu. Then choose an instance model that should be transformed. Finally, set the parameters of the rule (not all have to be specified) and click on Preview to see the changes.
An application of the rule createAccount(client)
is shown on the right. As parameters we specified client=Alice
with type String, and accountId=5 with type Int.
The preview window on the right shows the
result of applying the rule with these parameters.
An application of the rule transferMoney
is shown on the right. We have specified the parameters client,
fromId, toid and amount. The other parameters
are automatically matched by the transformation engine. Note also
that is important to specify the correct parameter types, because
otherwise the rule cannot be matched.
The preview window on the right shows the
result of applying the rule with these parameters.
An application of the ruleThe rule deleteAllAccounts(client)
is shown on the right. As parameter we specified client=Charles
with type String.
The preview window on the right shows the
result of applying the rule with these parameters.
Of course, you can also invoke the interpreter programmatically. You can find an implementation of the example transformations above using the interpreter in the BankExample class.