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


XMI: Using C# to Capture UML Models : Page 3

UML models of the future will use XMI as a method of interchanging model data. And because XMI uses XML, suddenly the world is our oyster: In particular, you can extract model data and save it to a data store. Find out how to dissect data from your models using C#.

Example 3: Adding Hardware Information
Capturing the server names and their stereotypes is not all that useful from an asset management point of view. On the other hand, if your diagrams include information describing the hardware being used this could be very useful: for example, having all of your hardware saved in a database based on UML deployment diagrams would let you track servers, clients, and how they relate to each other .

In UML the hardware node has "tags" that identify the hardware's properties. Each tag is created within the modeling tool (Enterprise Architect in this case) and is defined by the modeler (or in some cases saved as a UML profile). In the example I have tags for CPU, disk size, memory size, purposes, notes, and Vendor (see Figure 5). Each tag has a value that is assigned either as a basic type (string, integer ...) or picked from a list of available values. It is very important to be consistent with the values used. If you use "G HT" in CPU to represent "gigahertz hyper-threaded" then you must use the same convention for every CPU tag.

Figure 5. Adding Hardware To the server/stereotype diagram from Example 2, I've added tags that describe each of the node's hardware. I added a client to the example "Mary Machine" to show that there is also a "pc client" stereotype.

The new, refactored code is the same as before but with some additions for reading tags. The XMI doesn't encapsulate the tags within the nodes as one would expect. Instead, each attribute is a "TaggedValue" element that references the attribute's node identifier (XML.id) using the "modelElement" attribute. The difficulty in doing this is that the node elements have to be read before the tag elements (I'll explain why in a minute) and each node element has to be saved for the tag elements to be attached to them.

In XML there are two ways of reading documents. The first way is to read the entire document and save it in memory as a tree where each element is part of a hierarchy built from the root element. This is the DOM model and is the preferred method for smaller documents. The second method is where the document is read and parsed one element at a time. SAX is an example of this method and is referred to as the push model because it parses the document and sends it back (pushes it) without being prompted.

The other way is using Microsoft's XMLReaders (XMLTextReader is derived from it), which is the pull model because the program controls when the next element is parsed. The XML document that I use here is small but some of the files that I have parsed are over 500,000 lines of text, which leads me to the XMLReader method. One of the disadvantages of this method is the requirement that the nodes occur before the tags elements.

To save the nodes I need to use a key/value container. The easiest one to use is the Hashtable. In refactoring the main program (see below) I used the enumerations capability that I get from the Hashtable and the IDictionary enumerator to print out the server nodes.

public static void Main(string[] args)
Hashtable mainHash;
IDictionaryEnumerator ienum;
Node tNode;

string name = ReadString("Please enter the XMI filename : ");
NodeParse np = new NodeParse(name);
mainHash = np.getNodes();
ienum = mainHash.GetEnumerator();
while (ienum.MoveNext())
                    tNode = (Node)ienum.Value;
               System.Console.WriteLine("Node = " + tNode.name + " CPU = " + tNode.CPU);
I refactored the nodeParse object to check for the element "TaggedValue" and call AddAttributeNode which finds the correct Node in the hashtable and adds the tag through a case statement to the Node. The NodeParse class is shown in Listing 3a.

The Node class is nothing more than an object for holding state. Each tag that I am interested in has its own property. Note that the constructor for Node requires that the object is initialized with the server name.

using System;
using System.Text;

namespace XMI_1
          class Node 
                    string _name,  _id = "",  _CPU, _MemorySize, _DiskSize,  _Note,
                              _Purpose,  _Stereotype,Vendor;

                    public Node(string p_id)          {this._name = p_id;}
                    public string id
                    {get  {          return _id;}

                    public string name
                    {get   {          return _name;}
                      set  {_name = value;}}

                    public string CPU
                    {get   { return _CPU;}
                      set   {_CPU = value;}}

                    public string MemorySize
                    {get  {return _MemorySize;}
                      set  {_MemorySize = value;}}

                    public string DiskSize
                    {get  {return _DiskSize;}
                           set {_DiskSize = value;}          }

                    public string Notes
                    {get {return _Notes;}
                               set {_Notes = value;}}

                    public string Purpose
                    {get {return _Purpose;}
                          set  {_Purpose = value;}}

                    public string Stereotype
                    {get {return _Stereotype;}
                               set  {_Stereotype = value;}}

                    public string Vendor
                    {get  {return _Vendor;}
                        set  {_Vendor = value;}}
I did not provide the output for Example 3, as it is nearly identical to Example 4. (Listing 3b has the complete source code for Example 3.)

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