I may have mentioned it before on this blog, but XMI interchange of UML models is notoriously difficult in practice. A major problem of model interchange concerns diagram information: what diagrams are there, which elements appear on the diagrams, and where are they located on the diagram? While the UML model itself often can be exchanged more or less intact between tools, the diagram information usually is lost in the process.
The UML defines a diagram interchange standard (UML DI), but it is not widely used. The standard mandates a very detailed description of UML diagrams. For instance, to show some class ‘Foo’ on a class diagram, it does not only specify to draw its class symbol at certain coordinates, but also whether to draw the operation or attribute compartments, and which operations and attributes should be visible in the compartments. After all, designers can choose to only show selected operations or attributes on a given diagram. Even every single operation parameter on a class diagram is linked to its parameter and type objects in the model.
Instead of UML DI, tool vendors often use proprietary XMI extensions to store the diagram information. Of course, these extensions are not understood by other tools, which explains why the diagrams are lost during model exchange. As a typical example of such an XMI extension, the following excerpt from an XMI file shows how Altova UModel saves its diagrams (I have replaced the XMI IDs for readability):
<xmi:XMI ... xmi:version="2.1"> <xmi:Documentation ... exporter="Altova UModel2012r2" exporterVersion="10"/> <xmi:Extension extender="UModel"> <Diagrams> <uml:RootElement xmi:id="E59RK7MUY3Y4"> <guiRootGuiDiagram xmi:type="uml:ClassDiagram" xmi:id="diag1" name="ClassDiagram" ...> <guiDiagramGuiLink xmi:type="uml:NodeLink" xmi:id="node1" guiLink_Element="cls1"> <nodeRect Left="210" Top="150" Right="271" Bottom="192"/> </guiDiagramGuiLink> <guiDiagramGuiLink xmi:type="uml:LineLink" xmi:id="line1" guiLink_Element="gen1" guiLineLink_LineBegin="node1" guiLineLink_LineEnd="node2"> <guiLineLink_LineMiddleWaypoint xmi:type="uml:MiddleWaypoint" xmi:id="mwp1> <pos X="216" Y="119"/> </guiLineLink_LineMiddleWaypoint> ... </guiDiagramGuiLink> ... </guiRootGuiDiagram> </uml:RootElement> </Diagrams> </xmi:Extension> <uml:Model xmi:id="mdl1" name="Root"> <packagedElement xmi:type="uml:Class" xmi:id="cls1" name="Subclass"> <generalization xmi:type="uml:Generalization" xmi:id="gen1" general="cls2"/> </packagedElement> ... </uml:Model> </xmi:XMI>
As we can see, the entire diagram information is contained within an <xmi:Extension>
element. Altova UModel defines a new meta class “RootElement” in the UML namespace, with a composition association “guiRootGuiDiagram” that contains the diagrams of the model. A diagram in turn has a composition association “guiDiagramGuiLink” that contains all elements on the diagram. These are instances of meta classes “NodeLink” or “LineLink”. Each diagram element has a reference “guiLink_Element” to the model element it represents.
Out of the box, SDMetrics does not parse Altova UModel’s diagram information. But with the above information, we can extend SDMetrics’ XMI import facility. Simply add the following lines to the XMI transformation file:
<xmitransformation modelelement="diagram" xmipattern="guiRootGuiDiagram" recurse="true"> <trigger name="name" type="attrval" attr="name" /> <trigger name="type" type="attrval" attr="xmi:type" /> </xmitransformation> <xmitransformation modelelement="diagramelement" xmipattern="guiDiagramGuiLink"> <trigger name="element" type="attrval" attr="guiLink_Element" /> </xmitransformation>
This maps SDMetrics’ “diagram” and “diagramelement” metaclasses for diagram information to UModel’s “guiRootGuiDiagram” and “guiDiagramGuiLink” elements, respectively.
So far, so good. Now let’s assume we want to define design rules that pertain to diagram guidelines such as “place subclasses below their superclass”. For that we need to check the coordinates of the diagram elements in the diagram. For connectors between elements such as associations or generalizations, it is also useful to know which diagram elements are attached to the connector.
In the XMI file above, the XML element <nodeRect Left="210" Top="150" Right="271" Bottom="192"/>
provides the coordinates of a diagram node link. For line links, the XML attributes “guiLineLink_LineBegin” and “guiLineLink_LineEnd” reference the attached diagram node links. To extract this data from the XMI file, we extend SDMetrics’ meta model for diagram information by adding several attributes to the “diagramelement” type in the meta model definition file:
<modelelement name="diagramelement" > <attribute name="element" type="ref">The element that is shown on the diagram.</attribute> <attribute name="top" type="data">Top coordinate of a node link.</attribute> <attribute name="left" type="data">Left coordinate of a node link.</attribute> <attribute name="right" type="data">Right coordinate of a node link.</attribute> <attribute name="bottom" type="data">Bottom coordinate of a node link.</attribute> <attribute name="connstart" type="ref">Node link at the start of a line link.</attribute> <attribute name="connend" type="ref">Node link at the end of a line link.</attribute> </modelelement>
The complete XMI transformations for the extended diagram elements look like this:
<xmitransformation modelelement="diagramelement" xmipattern="guiDiagramGuiLink"> <trigger name="element" type="attrval" attr="guiLink_Element" /> <trigger name="top" type="cattrval" src="nodeRect" attr="Top" /> <trigger name="left" type="cattrval" src="nodeRect" attr="Left" /> <trigger name="right" type="cattrval" src="nodeRect" attr="Right" /> <trigger name="bottom" type="cattrval" src="nodeRect" attr="Bottom" /> <trigger name="connstart" type="attrval" attr="guiLineLink_LineBegin" /> <trigger name="connend" type="attrval" attr="guiLineLink_LineEnd" /> </xmitransformation>
Note that our simplified meta model for diagrams does not define separate diagram element types for node and line links as Altova UModel does. Instead, we lump the information together in one element. The top/left/right/bottom information only applies to node links, and the connstart/connend attributes only apply to line links. Such simplifications are OK for our purpose of checking some simple layout guidelines.
Also note that these extensions are completely specific to Altova UModel. Other tools store diagram layouts differently. For instance, diagram coordinates are often summarized in a single string such as position=”Top:123, Left:122, Bottom:234, Right: 546″, or geometry=”123, 122; 546, 234″. SDMetrics’ XMI parser cannot dissect such strings “on the fly”. In this situation we would define a single attribute “geometry” for our diagram elements, and then create custom metrics that extract the top, left, right, and bottom coordinates from the geometry string.
In a subsequent post, I will build upon the work shown here to define a design rule that automatically checks that subclasses are located below their superclasses on the diagrams.