Sequence Diagram Implementation Details - Ericsson/papyrus-patches GitHub Wiki

Overview

The nature of the sequence diagram and the interactions in UML, force us to introduce a new mechanism to build the GEF/GMF command chain. Normally a number of edit policies are installed in the edit parts, which contribute with command to the end result of the user action. Edit parts policies normally:

  • It provides commands to the command chain.
  • It modify the request to add additional information or constraint the original request attributes
  • It validate the request, and if invalid, it forbids the execution of the command.
  • Forward the request to the parent, children or to some other services, such as ElementTypes framework.

Normally all that is done in the edit policies getCommand() or any of its extended methods, based on th einformation carried inside the request. Assuming the target of the user action is one edit part and the action does not have any implication or dependency on other edit parts, it is a straight way to do it. And that it is the way it has been doing in all the diagrams in papyrus.

However, when any user action has dependencies or trigger actions in a number of other edit parts, this approach has been proved not optimal, and almost impossible to implement because of the number of things to consider in each of the edit policies, and because each policy it has very contextual information related to the host edit part and nothing else.

We realized that it is basically the root cause of the problem with all the attempts to implement sequence diagrams in papyrus and other GMF based applications. We start to talk and propose an alternative approach, instead of act in each of the edit policies to try to perform the user action, we strip off most of the edit policies that contribute to the command chain and delegate to a logical model, which provide the complete command chain for the user action. This allows us, for example to apply a layout to the whole diagram for some action, like making place for the a new element when that is created in the middle of the diagram, or nudging down all the elements in the diagram when we move a message...

With this approach we get a simpler, consistent implementation that allows us to provide a better user experience.

The Logical Model

The implementation make use of a logical model that represent the interaction and the sequence diagram that it can be seen as a directed graph of nodes, groups and links and its dependencies. Ocurrences and message ends are represented as nodes, messages as links, and fragments and execution specification as groups.

If we take as an example the sequence diagram below:

we build this logical model:

In this picture every circle represent a node in the logical model, the gray square, represent groups or clusters of nodes. Links are represented by thin blue arrows. The big blue arrows represent group dependencies. The dependencies are used to link to find which groups should be handle together as one, when moving or deleting them.

This view of the diagram is build as an hierarchical graph, as shown in the picture below:

In reality some of the groups in the picture above, are not created as clusters, but as nodes, as they are one-node group. Inthe picture, black arrows represent a containment relation, blue arrows represent cluster dependencies to apply in a cascade fashion. The red arrows implies a dependency (as the blue ones) but with some constraints imposed by the source group. This is normally represent horizontal structures, such the ones used to represent interaction uses.

The idea with the logical model is that if we want to move the validate() message originated in lifeline :window after the execution first specification in the same lifeline, it will be enough by removing the 'Send Anchor 1' node from group 2 and inserting it directly in the lifeline after the group 2. Then we re-layout the graph and we have actually move validate() message and all the ones triggered from that point with it. The logical model will provide a command chain to perform all the needed operation on the uml diagram and notation diagrams comparing itself with the actual diagram and uml model.

Using the normal aproach, to do the same operation, it will very difficult if not impossible.

Logical model Implementation

This logical model is implemented using nodes, links and clusters (groups):

  • Node: it is the simplest part of the model. It represents simple fragments, such as occurrence specifications or message ends. Nodes are contained in clusters. A Node may trigger others nodes or cluster through link, for example a send event triggers the receive event which can be thw start of a ExecutionSpecification

  • Mark Node: A mrk node is a node that represent a graphical mark in the diagram and as such it does not represent a uml element neither it has representation in the notation model as such, but it needs to be handle as node in the logical model. Example of mark nodes are interaction use start and end point, or the send event for a found message.

  • Cluster: A cluster represents a set of Nodes that should be handle together. The nodes owned by a cluster are treated as one. When the cluster is moved or deleted, its owned nodes are moved or deleted together with it.
    An example, it could be the set of Nodes that represent an Execution Specification defined as:

    • The start mark, defined with a Occurrence Specification.
    • The Execution Specification itself.
    • The end mark, defined with aOccurrenceSpecification.
  • Link: A link represent a message or edge in the diagram. It keeps references to the source and target nodes, which are used to create a node (source) to node/cluster (target) dependencies in the logical model. The links are owned by the Interaction Graph or a Fragment cluster.

  • Fragment cluster: A Fragment Cluster represent indivisible structures that extends across Lifeline and are composed of other Cluster}. It is used to represent Interaction Uses, Combined Fragments and Interaction Operands.

  • Interaction Graph: The Interaction Graph represent a Interaction and encapsulates the dependencies and the composition of the Interaction Fragments in the Interaction.
    It maintains a ordered list clusters representing the Lifelines, a list of fragment clusters representing Combined Fragments and Interaction Uses, and a list of nodes representing floating elements, like Gates or marks associated to lost or found messages.

A high level view of the model is shown in this diagram.

The elements in the model keep a reference to the notation view, uml element and edit part that represent. In addition to that the Interaction graph also keep a reference to the diagram, diagram edit part and the edit part viewer as shown in the picture below.

The Interaction Graph provides a high level API and a low level API. The high level API provides semantic awareness functions:

addLifeline(),moveLifeline(), removeLifeline(), ...

And the low level API operates on nodes and blocks (list of related nodes):

addNodeBlock(), removeNodeBlock(), moveNodeBlock(), ...

Command chain

Most of the edit policies that contributes commands to the then command chain targeting the uml or notation model are removed, disable or modify to provide a single command that apply the action to the logical model. This single command is built with a number of actions on the logical model that will be applied when the command is executed. The command class provides high level api functions to add this actions:

addLifeline(), moveLifeline, nudgeLifeline, ...

Most of this functions verify the request and create the actions. The actions uses the Interaction graph high level api.

When the command is executed all the actions are applied to the logical model and the command compare the resulting logical model with the uml and notation models and generate a number of EMF commands that it will be executed to update the uml and notation models.

The ElementTypes framework is used to generate those commands, so any extension done through the ElementTypes framework will be used as before. When creating new uml elements, the command actions use the element types framework to create the new elements, but remove then from the model afterwards. The uml elements are added back to the model by the emf generated command. This is done like that in order to be able to compare the logical model with the uml model but keep using the element types framework.

A new semantical edit policy is provided to handle the Destroy request in a proactive manner, instead of letting the ElementType framework trigger deletes on cascade.