Click here to Skip to main content
15,894,720 members
Articles / Desktop Programming / Windows Forms

Introduction to NIEM and IEPDs

,
Rate me:
Please Sign up or sign in to vote.
4.74/5 (7 votes)
1 Jan 2009CPOL16 min read 56.4K   499   30  
Developed by the Department of Justice and the Department of Homeland Security, the National Information Exchange Model "Bridges Information Systems".
// (c) 2009 Marc Clifton
// All Rights Reserved.
// You are free to use this code as long as you comply with the
// Code Project Open License (CPOL) 1.02
// http://www.codeproject.com/info/cpol10.aspx

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Schema;

namespace IepdBrowser
{
	public partial class IepdBrowserForm : Form
	{
		protected Iepd iepd;

		public IepdBrowserForm()
		{
			InitializeComponent();
		}

		public void PopulateTree()
		{
			tnTypes.Nodes.Clear();
			tvElements.Nodes.Clear();
			dgvLookupData.DataSource = null;

			Dictionary<QName, List<XmlSchemaType>> h = iepd.TypeHierarchy;

			foreach (KeyValuePair<QName, List<XmlSchemaType>> kvp in h)
			{
				// Find all nodes that are root parents.

				if (!iepd.ParentList.ContainsKey(kvp.Key))
				{
					TreeNode tn;
					tn = new TreeNode(kvp.Key.name);
					tn.Tag = kvp.Key;
					tnTypes.Nodes.Add(tn);
					PopulateChildren(iepd, tn, kvp.Key);
				}
			}

			tnTypes.Sort();
			tnTypes.ExpandAll();					   
		}

		protected void PopulateChildren(Iepd iepd, TreeNode tn, QName qname)
		{
			if (iepd.TypeHierarchy.ContainsKey(qname))
			{
				foreach (XmlSchemaType xst in iepd.TypeHierarchy[qname])
				{
					TreeNode tnChild = new TreeNode(xst.QualifiedName.Name);
					tnChild.Tag = new QName(xst.QualifiedName);
					tn.Nodes.Add(tnChild);
					PopulateChildren(iepd, tnChild, new QName(xst.QualifiedName.Name, xst.QualifiedName.Namespace));
				}
			}
		}

		protected void tnTypes_AfterSelect(object sender, TreeViewEventArgs e)
		{
			QName qname = (QName)e.Node.Tag;
			tbNamespace.Text = qname.ns;

			tvElements.Nodes.Clear();
			Cursor = Cursors.WaitCursor;
			List<ElementInfo> elInfoList = iepd.GetElements(qname);
			TreeNode tnRoot = new TreeNode("Elements");

			foreach (ElementInfo elInfo in elInfoList)
			{
				TreeNode tn = CreateElementRow(elInfo);
				tnRoot.Nodes.Add(tn);
			}

			tvElements.Nodes.Add(tnRoot);

			tnRoot.Expand();
			Cursor = Cursors.Arrow;
		}

		protected TreeNode CreateElementRow(ElementInfo elInfo)
		{
			TreeNode tn = new TreeNode();
			string cardinality = BuildCardinalityString(elInfo);
			tn.Text = elInfo.Name + " " + cardinality + ", Type=" + elInfo.Type + ")";
			tn.Tag = elInfo;

			if (elInfo.ChildElements.Count > 0)
			{
				foreach (ElementInfo ei in elInfo.ChildElements)
				{
					TreeNode tnChild = CreateElementRow(ei);
					tn.Nodes.Add(tnChild);
				}
			}
			else
			{
				// If we haven't filled in the child elements, see if there are any and create a placeholder.
				// This puts a "+" sign on the node, so when the user opens it, we can get the child elements
				// at that point.  The purpose of this is to improve the UI response when selecting a type,
				// because some of the types can take quite a while to generate the complete hierarchy.
				if (iepd.HasChildElements(elInfo))
				{
					TreeNode tnChild = new TreeNode("More...");
					tn.Nodes.Add(tnChild);
				}
			}

			List<SubstElementsInfo> substGroupList = elInfo.SubstGroupElements;

			foreach (SubstElementsInfo substElementInfo in substGroupList)
			{
				TreeNode tnsg = new TreeNode();
				// Set to non-null, so it's not deleted when we collapse and then drill into an element
				// that only has one substitution group.  The tag is not currently used (2/
				tnsg.Tag = elInfo;
				tnsg.Text = "Substitution Group (";
				// tnsg.Text += substElementInfo.xseSubstGroup.Name;
				tnsg.Text += substElementInfo.xseSubstGroup.QualifiedName;
				tnsg.Text += ")";
				tn.Nodes.Add(tnsg);

				foreach (ElementInfo sgElemInfo in substElementInfo.substElements)
				{
					TreeNode sgSubNode = CreateElementRow(sgElemInfo);
					tnsg.Nodes.Add(sgSubNode);
				}
			}

			return tn;
		}

		protected string BuildCardinalityString(ElementInfo elInfo)
		{
			StringBuilder sb = new StringBuilder();
			sb.Append("(");

			if (elInfo.MinOccurs.ToLower() == "unbounded")
			{
				sb.Append("*");
			}
			else
			{
				sb.Append(elInfo.MinOccurs);
			}

			sb.Append("..");

			if (elInfo.MaxOccurs.ToLower() == "unbounded")
			{
				sb.Append("*");
			}
			else
			{
				sb.Append(elInfo.MaxOccurs);
			}

			sb.Append(")");

			return sb.ToString();
		}

		private void mnuOpen_Click(object sender, EventArgs e)
		{
			OpenFileDialog ofd = new OpenFileDialog();
			ofd.Filter = "schema files (*.xsd)|*.xsd";
			ofd.RestoreDirectory = true;
			DialogResult res = ofd.ShowDialog();

			if (res == DialogResult.OK)
			{
				iepd = new Iepd(ofd.FileName);
				iepd.BuildTypeHierarchyFromElements();
				PopulateTree();
			}
		}

		private void mnuExit_Click(object sender, EventArgs e)
		{
			Close();
		}

		private void tvElements_AfterSelect(object sender, TreeViewEventArgs e)
		{
			ElementInfo elInfo = (ElementInfo)e.Node.Tag;
			List<EnumFacet> lookupList = iepd.GetLookupData(elInfo);
			dgvLookupData.DataSource = lookupList;
		}

		private void tvElements_BeforeExpand(object sender, TreeViewCancelEventArgs e)
		{
			ElementInfo elInfo = (ElementInfo)e.Node.Tag;

			// A "More..." child node will have Tag==null
			// There may be more than one child node, 
			// as the node may contain "More..." plus substitution groups.
			if ( (e.Node.Nodes.Count > 0) && (e.Node.Nodes[0].Tag==null) )
			{
				// Remove the "More..." node.
				e.Node.Nodes[0].Remove();
				elInfo.DrillIntoType(iepd);
				int n = 0;

				foreach (ElementInfo ei in elInfo.ChildElements)
				{
					TreeNode tnChild = CreateElementRow(ei);
					e.Node.Nodes.Insert(n, tnChild);
					++n;
				}
			}

			e.Cancel = false;
		}
	}
}

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Interacx
United States United States
Blog: https://marcclifton.wordpress.com/
Home Page: http://www.marcclifton.com
Research: http://www.higherorderprogramming.com/
GitHub: https://github.com/cliftonm

All my life I have been passionate about architecture / software design, as this is the cornerstone to a maintainable and extensible application. As such, I have enjoyed exploring some crazy ideas and discovering that they are not so crazy after all. I also love writing about my ideas and seeing the community response. As a consultant, I've enjoyed working in a wide range of industries such as aerospace, boatyard management, remote sensing, emergency services / data management, and casino operations. I've done a variety of pro-bono work non-profit organizations related to nature conservancy, drug recovery and women's health.

Written By
Database Developer
United States United States
Educated in industrial engineering, optimization techniques, information security, computer science, math, statistics, and business management, I support a public safety software platform.

Keywords:
Information Systems, relational database management systems, information security, ERP, EAI, SAP, PeopleSoft, data warehousing, OFX, e-commerce, speech recognition, CRM, statistical analysis, modeling and simulation, operations research, cognitive engineering.

Comments and Discussions