Drill-Down Sequence Diagrams with Picto¶
This article demonstrates using Picto and its PlantUML integration to generate drill-down sequence diagrams from models conforming to a minimal EMF-based sequence diagram language.
Metamodel¶
Below is the metamodel of our mini sequence-diagram (minisd
) DSL (in Emfatic). In our language, a scenario consists of a number of interactions between participants, and alternative execution paths (Alt
).
@namespace(uri="minisd", prefix="")
package minisd;
class Scenario extends Block {}
class Participant {
attr String name;
}
abstract class Step {}
class Block extends Step {
attr String title;
val Step[*] steps;
}
class Alt extends Step {
attr String title;
val Block[*] blocks;
}
class Interaction extends Step {
ref Participant from;
ref Participant to;
attr String message;
}
Customer-ATM Model¶
Below is a Flexmi model that conforms to the minisd DSL and captures the interaction between a customer and an ATM.
<?nsuri minisd?>
<?render-egx minisd2plantuml.egx?>
<_>
<participant name="Customer"/>
<participant name="ATM"/>
<scenario title="Customer-ATM">
<int from="Customer" to="ATM" msg="Insert card"/>
<int from="ATM" to="Customer" msg="Request PIN"/>
<int from="Customer" to="ATM" msg="Enter PIN"/>
<alt title="Check PIN">
<block title="PIN valid">
<int from="ATM" to="Customer" msg="Display options"/>
<alt title="Options">
<block title="Cash withdrawal">
<int from="Customer" to="ATM" msg="Select cash withdrawal"/>
<int from="ATM" to="Customer" msg="Ask for amount"/>
<int from="Customer" to="ATM" msg="Enter amount"/>
<alt title="Check funds">
<block title="Sufficient funds">
<int from="ATM" to="Customer" msg="Produce cash"/>
</block>
<block title="Insufficient funds">
<int from="ATM" to="Customer" msg="Produce error message"/>
</block>
</alt>
</block>
<block title="Balance display">
<int from="Customer" to="ATM" msg="Select balance display"/>
<int from="ATM" to="Customer" msg="Display balance"/>
<int from="ATM" to="Customer" msg="Return card"/>
</block>
</alt>
</block>
<block title="PIN invalid">
<int from="ATM" to="Customer" msg="Try again"/>
</block>
</alt>
</scenario>
</_>
Visualisation Transformation¶
To visualise models that conform to the minisd DSL (such as the Customer-ATM model above) in Picto, we have written a model-to-text transformation in EGL, that transforms such models into a series of PlantUML sequence diagrams.
In particular, the transformation produces one sequence diagram for the entire model, and one sequence diagram for each execution path in it. The EGX orchestration program and the EGL template are shown below.
rule Scenario2PlantUml
transform s : Scenario {
template : "minisd2plantuml.egl"
parameters : Map {
"mainBlock" = null,
"format" = "plantuml",
"path" = List{s.title},
"icon" = "sequence"
}
}
rule Block2PlantUml
transform b : Block {
guard : b.eContainer.isTypeOf(Alt)
template : "minisd2plantuml.egl"
parameters : Map {
"mainBlock" = b,
"format" = "plantuml",
"path" = b.closure(p|p.eContainer).invert().including(b).title,
"icon" = "block"
}
}
rule Alt2PlantUml
transform a : Alt {
parameters : Map {
"format" = "text",
"path" = a.closure(p|p.eContainer).invert().including(a).title,
"icon" = "alt"
}
}
@startuml
[%
var excludedBlocks = Sequence{};
if (mainBlock.isDefined()) {
var ancestors = mainBlock.closure(b|b.eContainer()).select(b|b.isTypeOf(Block)).including(mainBlock);
for (a in ancestors) {
if (a.eContainer().isDefined() and a.eContainer().isTypeOf(Alt)) {
excludedBlocks.addAll(a.eContainer().blocks.excluding(a));
}
}
}
%]
[%=Scenario.all.first().toPlantUml()%]
@enduml
[%
operation Scenario toPlantUml() {
return self.steps.collect(s|s.toPlantUml()).concat("\n");
}
operation Interaction toPlantUml() {
return self.from.name + "->" + self.to.name + ": " + self.message + "\n";
}
operation Alt toPlantUml() {
var plantUml = "";
var visibleBlocks = self.blocks.excludingAll(excludedBlocks);
for (b in visibleBlocks) {
if (loopCount == 1) {
plantUml += "alt";
if (mainBlock.isDefined() and mainBlock.eContainer == self) {
plantUml += " #azure";
}
}
else plantUml += "else ";
plantUml += " " + b.title;
plantUml += "\n" + b.toPlantUml();
}
if (visibleBlocks.notEmpty()) plantUml += "\nend\n";
return plantUml;
}
operation Block toPlantUml() {
if (excludedBlocks.contains(self)) return "";
return self.steps.collect(s|s.toPlantUml()).concat("");
}
%]
Drill-Down Sequence Diagrams¶
The result is a set of sequence diagrams that we can navigate to drill down the alternative interaction paths. Notice how selecting an alternative (e.g. Sufficient funds
) hides all irrelevant information from the sequence diagram (e.g. Balance display
, PIN invalid
).
Source code
The complete source code for this example is in Epsilon's Git repository.