|
// This code is copyright Dustin Metzgar.
// There are no restrictions to what you can do with this code. If you do
// use it for something interesting, let me know (dustin.metzgar@gmail.com).
using System;
using System.CodeDom;
using System.Collections;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Xml;
namespace XmiParser
{
/// <summary>
/// A class that is designed to read XMI documents into the object model format used
/// by the code generation system.
/// </summary>
public class XmiHelper
{
private XmlDocument _OrigDoc;
private Hashtable _XmiObjects;
/// <summary>
/// Whether or not the XML document is an XMI document.
/// </summary>
public bool IsXmiDocument
{
get
{
try
{
return _OrigDoc.DocumentElement.Name == "XMI";
}
catch
{
return false;
}
}
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="doc"></param>
public XmiHelper(XmlDocument doc)
{
_OrigDoc = doc;
_XmiObjects = new Hashtable();
}
/// <summary>
/// Finds a xmi object by its xmi id.
/// </summary>
/// <param name="xmiId"></param>
/// <returns></returns>
public XmiBaseObject FindObjectByXmiId(string xmiId)
{
return _XmiObjects[xmiId] as XmiBaseObject;
}
/// <summary>
/// Parses the XMI document.
/// </summary>
public void ParseXmi()
{
Hashtable htElems = GetElementTable();
foreach (string elemName in htElems.Keys)
{
XmlNodeList nl = _OrigDoc.SelectNodes("XMI/XMI.content//" + elemName);
Type t = htElems[elemName] as Type;
foreach (XmlElement el in nl)
{
XmiBaseObject xbo = Activator.CreateInstance(t, new object[] { el, this }) as XmiBaseObject;
if (!xbo.IsIdRef)
_XmiObjects.Add(xbo.XmiId, xbo);
}
}
}
/// <summary>
/// Gets a list of all the xmi objects collected.
/// </summary>
/// <returns></returns>
public XmiBaseObject[] GetObjects()
{
ArrayList al = new ArrayList(_XmiObjects.Values);
return (XmiBaseObject[])al.ToArray(typeof(XmiBaseObject));
}
/// <summary>
/// The element table reads the current assembly for all the classes that extend <see cref="XmiBaseObject"/>.
/// The resulting Hashtable has the name of the XMI element as the key, and the Type of the class that reads
/// it as the value.
/// </summary>
/// <returns></returns>
private Hashtable GetElementTable()
{
Hashtable ht = new Hashtable();
Assembly asm = this.GetType().Assembly;
Type[] types = asm.GetTypes();
foreach (Type t in types)
{
if (t.IsSubclassOf(typeof(XmiBaseObject)))
{
object[] attr = t.GetCustomAttributes(typeof(XmiElementNameAttribute), true);
if (attr.Length > 0)
{
XmiElementNameAttribute xena = attr[0] as XmiElementNameAttribute;
ht.Add(xena.ElementName, t);
}
}
}
return ht;
}
/// <summary>
/// Returns a CodeCompileUnit that has all the classes read from the XMI in it.
/// </summary>
/// <returns></returns>
public CodeCompileUnit GetCodeDomModel()
{
if (!IsXmiDocument)
throw new ArgumentException("Document is not a valid XMI document!");
ParseXmi();
CodeCompileUnit ccu = new CodeCompileUnit();
foreach (XmiNamespace xn in GetNamespaces())
{
CodeNamespace cn = new CodeNamespace(EnsureNamespaceName(xn.Name));
ccu.Namespaces.Add(cn);
cn.Imports.Add(new CodeNamespaceImport("System"));
foreach (XmiClass xc in GetClassesInNamespace(xn))
{
CodeTypeDeclaration ctd = xc.GetCodeDomClass();
cn.Types.Add(ctd);
}
}
return ccu;
}
private XmiNamespace[] GetNamespaces()
{
ArrayList al = new ArrayList();
XmiBaseObject[] xmiObjects = GetObjects();
foreach (XmiBaseObject xbo in xmiObjects)
{
if (xbo is XmiNamespace)
al.Add(xbo);
}
return (XmiNamespace[])al.ToArray(typeof(XmiNamespace));
}
private XmiClass[] GetClassesInNamespace(XmiNamespace xn)
{
ArrayList al = new ArrayList();
XmiBaseObject[] xmiObjects = GetObjects();
foreach (XmiBaseObject xbo in xmiObjects)
{
if (xbo is XmiClass)
{
XmiClass xc = xbo as XmiClass;
if (xn.XmiId == xc.NamespaceId)
al.Add(xc);
}
}
return (XmiClass[])al.ToArray(typeof(XmiClass));
}
private static string EnsureNamespaceName(string ns)
{
if (ns == null || ns.Length == 0)
return "UnknownNamespace";
Regex re = new Regex("[^a-zA-Z0-9_]");
string s = re.Replace(ns, "");
re = new Regex("^0-9");
while (s.Length > 1 && re.IsMatch(s))
s = s.Substring(1);
if (s.Length == 1 && re.IsMatch(s))
return "UnknownNamespace";
return s;
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.