RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


XMI: Capture UML Associations Using C#

XMI is a great technology for anyone who builds applications from models, allowing you to use information contained in those models for big upside. Learn to extract dependency information from a UML deployment diagram using C# and how to use the Pipes and Filters pattern to simplify the whole process.

n this article you'll see an exciting use for XMI—reading the connections between two server nodes in a UML diagram using C#. While my last XMI article collected information about the hardware in a system from XMI, capturing the connections can help answer questions about how servers depend on each other, letting you see how one server breaking down might affect other servers.

Most complex systems contain client, standalone, and server machines. The client machines are modeled as inventory. They have no impact on the system as a whole if they suddenly stop working. Standalone machines are treated in the same fashion; they might have business value, but as far as the overall system is concerned they are isolated. Server machines are different. A server machine is only as useful its connections. In an n-tier environment servers will either be application servers, databases servers, middleware servers, or Web servers.

Modeling such servers requires capturing not only their names and functions but also the links that occur between them. The following examples show how two servers are linked directly through an association or through another server.

A Direct Link Between Two Servers
The example in Figure 1 shows two servers that are linked together. In physical terms a link is the wire connection between two "boxes." A wire connection is the physical media that transports information from one server to another through protocols including TCP/IP for PC-based servers and SNA for mainframe servers. Logically, a link represents a two-way dependency between servers. If a link is broken in a distributed environment then there are consequences for the whole system.

Dependencies at the link level are the same as each server being able to send data to the other server. If one server cannot send data then that server is no longer being used by the network. Any server that uses the data from that server cannot function either (at least for that instant).

Figure 1. Two Directly Linked Servers: The figure shows two servers for HR (human resources) and CRM (customer relationship management) connected through a link.
Although Figure 1 doesn't specify a protocol, in PC environments the default protocol is TCP/IP. From a logical perspective, if the HR server breaks down then the CRM server will not operate correctly. In this case, for example, employees in the HR system could not be assigned to customers in the CRM system. If the CRM server fails then employees' productivity cannot be measured against the client relationship.

Using C# you can read this relationship and store it in a database (as described in the previous article) or use it to query dependencies. That article also developed some code for reading nodes. This article takes the same code and tweaks it to output the links and the nodes.

In XMI links are represented as UML associations (at least in the Enterprise Architect tool) through the Association element. Here's some code that recognizes the association.

switch (_readXMI.LocalName)
     case "Node":
     case "TaggedValue":
     case "Association":
Notice that the association is at the same level as a Node. The code reading this data treats the association like any other XML node; each has its own unique identifier. To add associations you need a hash table to persist them in the same fashion as the nodes from the previous article. Listing 1 shows the code to read the association and add it to a hash table.

The code in Listing 1 reads XML nodes and elements using the same pattern as the last article. As I mentioned then, the problem with using this pattern is that it doesn't work in cases where the XML contains elements you don't want to read. One solution is to check for the ending tags of elements using XMLNodetype.Endelement. While this will work, it is tedious to write. Another solution is to use the pattern for reading XML at every level of the XML even when the data isn't pertinent. This acts as a placeholder to fix the problem.

Figure 2. Reading an XMI Association: Each association endpoint (end1 and end2) contains the ID of the nodes, CRM and HR, as shown in the last two lines.
The example in Listing 1 reads the tags unique to Enterprise Architect in the XMI file, including the style, direction, line color, etc. tags that describe a mixture of display characteristics and other UML properties. The direction tag is of particular note. In this case it contains the value "Unspecified," which by default is the same as bi-directional (although as you'll see later, links specified as bidirectional include arrows on both ends of the link).

As shown below, each association contains a tag for the association connection that encapsulates the two association ends. Each end has an isNavigable attribute corresponding to the direction tag mentioned before. In this case both ends are navigable indicating that the link is bidirectional. Each end also contains a type attribute whose value refers to the node to which the end is connected.

<UML:Association xmi.id=
   visibility="public" isRoot="false" isLeaf="false" 
     <UML:TaggedValue tag="style" value="3" /> 
     <UML:TaggedValue tag="ea_type" 
        value="Association" /> 
     <UML:TaggedValue tag="direction" 
        value="Unspecified" /> 
     <UML:TaggedValue tag="linemode" value="3" /> 
     <UML:TaggedValue tag="linecolor" value="-1" /> 
     <UML:TaggedValue tag="linewidth" value="0" /> 
     <UML:TaggedValue tag="seqno" value="0" /> 
     <UML:TaggedValue tag="headStyle" value="0" /> 
     <UML:TaggedValue tag="lineStyle" value="0" /> 
     <UML:TaggedValue tag="virtualInheritance" 
        value="0" /> 

     <UML:AssociationEnd visibility="public" 
        aggregation="none" isOrdered="false" 
        isNavigable="true" type=
           <UML:TaggedValue tag="containment" 
             value="Unspecified" /> 

     <UML:AssociationEnd visibility="public" 
        aggregation="none" isOrdered="false"    
        isNavigable="true" type=
          <UML:TaggedValue tag="containment" 
            value="Unspecified" /> 
Figure 2 shows the output of an example that demonstrates reading an association from XMI. It prints out the association with its endpoints, then prints out the node names and their IDs to show that they match the association's endpoints.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date