The Reactions Language

Heiko Klare edited this page Sep 1, 2017 · 7 revisions

Table of Contents

The Reactions Language

The reactions language is a domain-specific language (DSL) for defining consistency relations between two metamodels. Consistency relations are specified unidirectionally and change-driven by defining how changes in an instance of one metamodel have to be transformed into changes of instances of another metamodel to restore consistency. For example, the modification of a name of a UML class is transformed into the change of a Java class that corresponds to the UML class.

Reactions and Routines

The reactions language consists of two main constructs, reactions and routines. A reaction specifies, in reaction to which kind of change some consistency repair logic, defined in a routine, has to be executed. A routine specifies which information has to be extracted from the models and how consistency is repaired. For instance, a reaction may specify that in reaction to the modification of a UML class name a routine shall be executed that retrieves the corresponding Java class and updates its name.

Reactions and routines explicitly separated to allow the reuse of repair logic. A routine can be called by reactions or by other routines. Thus, separating the repair logic (routine) from the decision when to execute it (reaction) increases the reusability.

Reactions

A reaction specifies when some consistency restoration logic shall be executed. It defines the so called trigger, for example, the replacement of an attribute value or the insertion of a reference, and specifies which routine has to be called for restoring consistency.

Several reactions can be specified for the same change without excluding each other. If two reactions are defines for the same change, both will be executed. Currently, the order in which they are executed is undefined and cannot be influenced. Therefore, only a single reactions should be specified for one change delegating to different routines in the correct order to avoid unexpected behavior due to the execution order.

Routines

A routine specifies how some kind of consistency relation between instances of two metamodels can be restored after a change. It consists of a matcher and an action.

The matcher specifies preconditions on the state of the models to execute the action. For instance, if a UML class is created and a corresponding Java class shall be created, the Java package corresponding to the UML package of the UML class has to be retrieved to place the created Java class in. If it does not exist, the action cannot be executed. Most of the matcher statements are based on retrieving elements from the models which can be also used in the action afterwards. For example, the Java package corresponding to the UML package can be accessed for placing the Java class in within the action.

The action specifies which changes have to be performed in another model to restore consistency. Several operations are available, especially creating, updating and deleting elements, adding and removing correspondences and calling other routines. The actions should be executed completely or not at all to avoid resulting in inconsistent intermediate states. To achieve this, all preconditions for executing the action should be specified in the matcher.

Correspondences

Consistency between two models is based on relations between elements of these models. For example, a UML class diagram and Java code can be considered consistent if they contain the same classes, having the same names, attributes, operations, associations and so on. Consequently, a class in the UML diagram has a corresponding class in Java code. Therefore, a correspondence model is used, which contains links between model elements that describe the same concept. A single correspondence consists of two model elements that describe the same concept, for example, a UML class and a Java class.

The correspondence model can be queried and modified by reactions. The matcher of a routine provides constructs for retrieving elements from the correspondence model, for example, the Java class corresponding to a UML class. In the action, correspondences can be added or removed between two objects,

Correspondences can also be defined for metaclasses rather than model elements. This can be useful, if elements are needed once per application (singletons). For example, having a Java project, only one corresponding UML model may has to exist. This can be stored in a correspondence to a metaclass of the Java metamodel, e.g. a Package. Adding such a correspondence within a Reaction can look as follows: `add correspondence between ContainersPackage.Literals.Package and umlModel` whereas `ContainersPackage.Literals.Package` is the Package-EClass of the Java metamodel and `umlModel` is a reference to the uml model element.

Syntax

The syntax of the reactions language is aligned with mainstream programming languages using curly braces for blocks and common syntax for variable declarations. Keywords in the reactinos language do not necessarily consist of a single word but are often sequences of words to increase the readability.

An example showing the creation of a Java class in reaction to the creation of a UML class is shown in the following. Fictive UML and Java metaclasses are used and accessed via uml.* and java.*

reaction CreatedUmlClass {
	after root created and inserted uml.Class
	call {
		val umlClass = change.newValue
		createJavaClass(umlClass);
	}
}

routine createJavaClass(uml.Class umlClass) {
	match {
		val javaPackage = retrieve java.Package corresponding to umlClass.package
	}
	action {
		val javaClass = create java.Class corresponding to umlClass and initialize {
			javaClass.name = umlClass.name
		}
		update javaPackage {
			javaPackage.classes += javaClass
		}
	}
}

Statements

Routines

Match

Matches are used to identify, if a consistency relation exists for the given elements which the routine can repair. Therefore, it is especially necessary to investigate the existing correspondences. Therefore, different statements are available:

  • `retrieve`: Retrieves elements from the correspondence model, with an optional prepended parameter assignment via `val NAME =`
    • `one`: For single element retrievals
      • `asserted`: Asserts that a corresponding element exists and if not throws an exception
      • `matching`: Looks for a corresponding element and aborts the routine execution if none is found
      • `optional`: Retrieves a corresponding element if existing, but also proceeds if there is none
    • `many`: For many element retrievals
  • `require abscence of`: Requires the abscence of a corresponding element for the specified one
  • `check`: A generic check statement that has to evaluate to true to proceed
    • `asserted`: Throws an exception if the check fails
    • `matching`: Only stops proceeding with that routine if the check fails

Usage

Keywords

The reactions language uses keywords defined in the Xtend language and additionally the following:

  • reaction
  • routine
  • and
  • create
  • delete
  • update
  • after
  • with
  • plain
  • retrieve
  • optional
  • action
  • execute
  • call
'Warning: This list is incomplete'

Writing code

The reactions language uses several Xtend code blocks for defining the logic of a consistency specification. In these code blocks, ordinary Xtend code can be written. Nevertheless, the usable identifiers are restricted because keywords of the reactions language cannot be used as identifiers anymore. A list of keywords can be found here and especially comprises words like optional, action create and delete.

Important: Keywords can be escaped using the ^ character, e.g. "EcoreUtil.^create(...)".

Writing an application

To use the Reactions language for writing an application, you have to start an Eclipse in which the Reactions language is installed, for example, an inner Eclipse from the Eclipse with your Vitruvius workspace. Then, you have to create an Eclipse Plug-in project for the application. Within this project, you create a file with the extension .reactions. This file automatically opens with the reactions language editor. If it does not, the reactions language is not correctly installed in your Eclipse. After writing reactions in this document, you have to right-click on the Plug-in project within the Package Explorer (not Model Explorer or something else) and select "Generate MIR". The command generates the necessary code inside the src-gen folder. In the "mir.reactions" subfolder, an AbstractChangePropagationSpecification* class is created. You should extend this class with an empty, concrete class in a package that is exported by your Plug-in and can then be used in a VSUM to keep models consistent.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.