Since the FSM (>= 1.3) now uses external schema files, it seems only logical to generate these from a visual editor instead of hand-typing them. And with OOo being the de facto standard for office work, OOo Draw seems a logical choice.
In addition, while I'd gladly have used Dia or Inkscape as a drawing tools, both are significantly less easy to use for this type of diagramming (IMHO), so the first UML to FSM converter rests on OOo Draw.
Now, how can one go about it ? Simply enough, with OpenDocument being an open standard, its layout is rather obvious.
However, in the long run, Dia has dedicated UML formatting, and hence seems a more logical choice, although it is far less easy to use. So the maintained converter, at least for now, uses Dia files.
The data in OpenDocument drawings is held in the office:document-content/office:body/office:drawing/draw:page
element of the content.xml
file in the zipped archive making up an OpenDocument document.
A FSM diagram source only needs two element types (rect
: rectangles, and connector
: transitions), so we can ignore all other elements.
rect
elements are used for the states. We only use their ID and the content of their 'text:p' child as the state nameconnector
element has several attributes and a child element, but only a few are useful for this applicationdraw:start-shape
defines the ID of the transition entry statedraw:end-shape
defines the ID of the transition exit statetext:p
element defines UML description of the transition, the content of which we can parse as an UML descriptionThis following excerpt represents the useful part of a two-state transition diagram:
[..snip..] <draw:page draw:name="page1" draw:style-name="dp1" draw:master-page-name="Standard"> <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> <draw:rect draw:style-name="gr1" draw:text-style-name="P1" draw:id="id1" draw:layer="layout" svg:width="4.5cm" svg:height="3.5cm" svg:x="2.5cm" svg:y="3.5cm"> <text:p/> </draw:rect> <draw:connector draw:style-name="gr2" draw:text-style-name="P1" draw:layer="layout" draw:type="curve" svg:x1="4.75cm" svg:y1="7cm" svg:x2="11.75cm" svg:y2="15.5cm" draw:start-shape="id1" draw:start-glue-point="2" draw:end-shape="id2" draw:end-glue-point="0"> <text:p text:style-name="P2">Square 1 to 2</text:p> </draw:connector> <draw:rect draw:style-name="gr1" draw:text-style-name="P1" draw:id="id2" draw:layer="layout" svg:width="6.5cm" svg:height="4.5cm" svg:x="8.5cm" svg:y="15.5cm"> <text:p/> </draw:rect> </draw:page> [..snip..]
Supposing for now that the OOo document has already been unzipped to directory draw2
, here is a possible piece of code to parse the FSM:
error_reporting(E_ALL|E_STRICT); $doc = new DOMDocument(); $doc->preserveWhiteSpace = false; $doc->load('draw2/content.xml'); $xpath = new DOMXPath($doc); $xpath->registerNamespace('office', "urn:oasis:names:tc:opendocument:xmlns:office:1.0"); $xpath->registerNamespace('draw', "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"); $xpath->registerNamespace('text', "urn:oasis:names:tc:opendocument:xmlns:text:1.0"); $qtext = 'text:p'; $qnodes = '(' . '//office:document-content/office:body/office:drawing/draw:page/draw:rect' . '|' . '//office:document-content/office:body/office:drawing/draw:page/draw:connector' . ')'; $result = $xpath->query($qnodes, $doc); foreach ($result as $node) { $name = $node->tagName; switch ($name) { case 'draw:rect': $id = $node->getAttribute('id'); $restext = $xpath->query($qtext, $node); $textnode = $restext->item(0); $state = $textnode->nodeValue; $states[$id] = $state; break; case 'draw:connector': $start = $node->getAttribute('start-shape'); $end = $node->getAttribute('end-shape'); $restext = $xpath->query($qtext, $node); $textnode = $restext->item(0); $event = $textnode->nodeValue; $events[$start][$end] = $event; break; default: // nothing } }
From there on, it's a simple matter of merging the two trees and generating the resulting FSM XML file.
Like OOo, Dia saves its content in an easy to parse zipped XML format.
Since Dia includes dedicated UML widgets, these can be used to semantically extract them instead of relying on format limitations as was the case in the OOo converter test.
The elements recognized are:
Other UML elements are available but not processed yet. The “UML - Fork” division/reunion bar could be the next addition, but state nesting is not being considered.