Files
GenericTeProgramLibrary/Source/TSRealLib/Common/Raytheon.Common/COE/XmlUtilities/XmlParser.cs
2025-10-24 15:18:11 -07:00

589 lines
28 KiB
C#

// **********************************************************************************************************
// XmlParser.cs
// 6/6/2022
// NGI - Next Generation Interceptor
//
// Contract No. HQ0856-21-C-0003/1022000209
//
// THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S.
// INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON
// COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT.
// DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON
// COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED
// TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF
// RAYTHEON COMPANY.
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M,
// NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006,
// INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3,
// DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3,
// SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4,
// INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//
// CONTROLLED BY: MISSILE DEFENSE AGENCY
// CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
// CUI CATEGORY: CTI
// DISTRIBUTION/DISSEMINATION CONTROL: F
// POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.XPath;
namespace Raytheon.Common.Coe
{
public class XmlParser
{
public class CommonXmlElements
{
public List<string> fileIncludes = new List<string>();
public string projectName = string.Empty;
public string classification = string.Empty;
public string fileHeader = string.Empty;
}
public class XmlConstant
{
public string nameSpace = string.Empty;
public List<string> comments = new List<string>();
public string name = string.Empty;
public string value = string.Empty;
public string description = string.Empty;
}
public class XmlEnumeration
{
public string nameSpace = string.Empty;
public string description = string.Empty;
public List<string> comments = new List<string>();
//public Dictionary<string, string> enumKeyAndValuePairs = new Dictionary<string, string>();
public List<XmlEnumItem> enumItems = new List<XmlEnumItem>();
}
public class XmlEnumItem
{
public List<string> comments = new List<string>();
public string name = string.Empty;
public string value = string.Empty;
}
public class XmlStructure
{
public string nameSpace = string.Empty;
public string name = string.Empty;
public List<string> comments = new List<string>();
public List<XmlStructureItem> structDataItems = new List<XmlStructureItem>();
}
public class XmlStructureItem
{
public string nameSpace = string.Empty;
public List<string> comments = new List<string>();
public string name = string.Empty;
public string description = string.Empty;
public string type = string.Empty;
public string defaultVal = string.Empty;
public string arrayLength = string.Empty;
public string bits = string.Empty;
}
public class XmlMbitMessage
{
public string nameSpace = string.Empty;
public string name = string.Empty;
public string label = string.Empty;
public string instruLabel = string.Empty;
public string description = string.Empty;
public List<string> comments = new List<string>();
public List<XmlParser.XmlStructureItem> dataItems = new List<XmlParser.XmlStructureItem>();
}
///===================================================================================
/// XmlParser.getCommonElementsFromXml
///===================================================================================
/// <summary>
/// Each XML file contains common elements such as header, includes, etc
/// We want to parse it and save the common elements
/// </summary>
/// <param name="nav">navigator object that points to the current XML node we are at</param>
/// <param name="commonElements">data structure that stores all the common elements of each XML file</param>
///===================================================================================
public static bool GetCommonElementsFromXml(XPathNavigator nav, CommonXmlElements commonElements)
{
bool isSuccessful = true;
if (string.Equals(nav.Name, "include", StringComparison.OrdinalIgnoreCase))
{
if (nav.MoveToFirstChild())
{
GetFileIncludes(nav, commonElements);
nav.MoveToParent();
}
}
else if (string.Equals(nav.Name, "project", StringComparison.OrdinalIgnoreCase))
{
commonElements.projectName = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "classification", StringComparison.OrdinalIgnoreCase))
{
commonElements.classification = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "fileheader", StringComparison.OrdinalIgnoreCase))
{
commonElements.fileHeader = nav.Value;
}
else if (string.Equals(nav.Name, "packing", StringComparison.OrdinalIgnoreCase))
{
}
else
isSuccessful = false;
return isSuccessful;
}
///===================================================================================
/// XmlParser.getFileIncludes
///===================================================================================
/// <summary>
/// Get the file includes specify by the XML file
/// </summary>
/// <param name="nav">navigator object that points to the current XML node we are at</param>
/// <param name="commonElements">data structure that stores all the common elements of each XML file</param>
///===================================================================================
public static void GetFileIncludes(XPathNavigator nav, CommonXmlElements commonElements)
{
do
{
commonElements.fileIncludes.Add(nav.Value.Trim());
} while (nav.MoveToNext());
}
///===================================================================================
/// XmlParser.getConstant
///===================================================================================
/// <summary>
/// Parse the symbolic constant defined by the XML
/// </summary>
/// <param name="nav">navigator object that points to the current XML node we are at</param>
/// <param name="nameSpace">the XML file name that defines this constant</param>
/// <param name="xmlConstants">the Dictionary that stores this constant information</param>
/// <param name="duplicateConstants">the Dictioanry that stores duplicate constant definitions</param>
///===================================================================================
public static void GetConstant(XPathNavigator nav, string nameSpace, List<XmlConstant> xmlConstants, Dictionary<string, List<string>> duplicateConstants)
{
XmlConstant tempXmlConstant = new XmlConstant();
if (nav.MoveToFirstChild())
{
do
{
if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase))
{
tempXmlConstant.name = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "description", StringComparison.OrdinalIgnoreCase))
{
tempXmlConstant.description = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "value", StringComparison.OrdinalIgnoreCase))
{
tempXmlConstant.value = nav.Value.Trim();
}
else if (nav.Name.Length > 0)
{
throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString());
}
} while (nav.MoveToNext());
nav.MoveToParent();
}
if (tempXmlConstant.name.Length > 0)
{
tempXmlConstant.nameSpace = nameSpace;
xmlConstants.Add(tempXmlConstant);
}
else
{
throw new XmlParsingException("Child element \"name\" not found for node \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString());
}
}
///===================================================================================
/// XmlParser.getEnumeration
///===================================================================================
/// <summary>
/// Parse the enumeration type defined by the XML
/// </summary>
/// <param name="nav">navigator object that points to the current XML node we are at</param>
/// <param name="nameSpace">the XML file name that defines this enumeration type</param>
/// <param name="xmlEnum">data structure that stores enumeration data</param>
/// <param name="duplicateEnums">the Dictioanry that stores duplicate enumeration type</param>
///===================================================================================
public static void GetEnumeration(XPathNavigator nav, string nameSpace, Dictionary<string, XmlEnumeration> xmlEnums, Dictionary<string, List<string>> duplicateEnums)
{
string enumTypeName = string.Empty;
string tempEnumTypeName = "temp";
Dictionary<string, XmlEnumeration> tempXmlEnums = new Dictionary<string, XmlEnumeration>
{
[tempEnumTypeName] = new XmlEnumeration()
};
tempXmlEnums[tempEnumTypeName].nameSpace = nameSpace;
if (nav.MoveToFirstChild())
{
do
{
if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase))
{
enumTypeName = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "description", StringComparison.OrdinalIgnoreCase))
{
tempXmlEnums[tempEnumTypeName].description = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "comment", StringComparison.OrdinalIgnoreCase))
{
tempXmlEnums[tempEnumTypeName].comments.Add(nav.Value.Trim());
}
else if (string.Equals(nav.Name, "item", StringComparison.OrdinalIgnoreCase) || string.Equals(nav.Name, "enum_item", StringComparison.OrdinalIgnoreCase))
{
if (nav.MoveToFirstChild())
{
GetEnumItem(nav, tempXmlEnums[tempEnumTypeName]);
nav.MoveToParent();
}
}
else if (nav.Name.Length > 0)
{
throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString());
}
} while (nav.MoveToNext());
nav.MoveToParent();
}
if (enumTypeName.Length > 0)
{
if (xmlEnums.ContainsKey(enumTypeName))
{
// save file name the defines this message that is a duplicate
if (!duplicateEnums.ContainsKey(enumTypeName))
{
duplicateEnums[enumTypeName] = new List<string>();
}
int index2 = duplicateEnums[enumTypeName].FindIndex(f => string.Equals(f, nameSpace + ".xml", StringComparison.OrdinalIgnoreCase));
if (index2 < 0)
duplicateEnums[enumTypeName].Add(nameSpace + ".xml");
// see if the official structure is already in the duplicate list
int index3 = duplicateEnums[enumTypeName].FindIndex(f => string.Equals(f, xmlEnums[enumTypeName].nameSpace + ".xml", StringComparison.OrdinalIgnoreCase));
// if the official structure is not in the duplicate list, we want to save it in the duplicate list
if (index3 < 0)
{
duplicateEnums[enumTypeName].Add(xmlEnums[enumTypeName].nameSpace + ".xml");
}
}
else
{
xmlEnums[enumTypeName] = tempXmlEnums[tempEnumTypeName];
}
}
else
{
throw new XmlParsingException("Child element \"name\" not found for node \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString());
}
}
///===================================================================================
/// XmlParser.getEnumItem
///===================================================================================
/// <summary>
/// Parse each enumerated key/value pair
/// </summary>
/// <param name="nav">navigator object that points to the current XML node we are at</param>
/// <param name="xmlEnum">data structure that stores enumeration data</param>
///===================================================================================
public static void GetEnumItem(XPathNavigator nav, XmlEnumeration xmlEnum)
{
XmlEnumItem enumItem = new XmlEnumItem();
do
{
if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase) || string.Equals(nav.Name, "item_name", StringComparison.OrdinalIgnoreCase))
{
enumItem.name = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "value", StringComparison.OrdinalIgnoreCase))
{
enumItem.value = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "comment", StringComparison.OrdinalIgnoreCase))
{
enumItem.comments.Add(nav.Value.Trim());
}
else if (nav.Name.Length > 0)
{
throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString());
}
} while (nav.MoveToNext());
xmlEnum.enumItems.Add(enumItem);
}
public static void GetStructure(XPathNavigator nav, string nameSpace, Dictionary<string, XmlStructure> xmlStructures, List<string> comments, Dictionary<string, List<string>> duplicateStructures)
{
string structureTypeName = string.Empty;
string tempStructureTypeName = "temp";
Dictionary<string, XmlStructure> tempXmlStructures = new Dictionary<string, XmlStructure>();
tempXmlStructures[tempStructureTypeName] = new XmlStructure();
tempXmlStructures[tempStructureTypeName].nameSpace = nameSpace;
if (nav.MoveToFirstChild())
{
do
{
if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase))
{
structureTypeName = nav.Value.Trim();
if (comments != null && comments.Count > 0)
{
tempXmlStructures[tempStructureTypeName].comments = new List<string>(comments);
}
}
else if (string.Equals(nav.Name, "comment", StringComparison.OrdinalIgnoreCase))
{
tempXmlStructures[tempStructureTypeName].comments.Add(nav.Value.Trim());
}
else if (string.Equals(nav.Name, "item", StringComparison.OrdinalIgnoreCase) || string.Equals(nav.Name, "struct_item", StringComparison.OrdinalIgnoreCase))
{
if (nav.MoveToFirstChild())
{
XmlStructureItem structureItem = new XmlStructureItem();
structureItem.nameSpace = nameSpace;
GetStructureItem(nav, structureItem);
tempXmlStructures[tempStructureTypeName].structDataItems.Add(structureItem);
nav.MoveToParent();
}
}
else if (nav.Name.Length > 0)
{
throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString());
}
} while (nav.MoveToNext());
nav.MoveToParent();
}
if (structureTypeName.Length > 0)
{
if (xmlStructures.ContainsKey(structureTypeName))
{
// save file name the defines this message that is a duplicate
if (!duplicateStructures.ContainsKey(structureTypeName))
{
duplicateStructures[structureTypeName] = new List<string>();
}
int index2 = duplicateStructures[structureTypeName].FindIndex(f => string.Equals(f, nameSpace + ".xml", StringComparison.OrdinalIgnoreCase));
if (index2 < 0)
duplicateStructures[structureTypeName].Add(nameSpace + ".xml");
// see if the official structure is already in the duplicate list
int index3 = duplicateStructures[structureTypeName].FindIndex(f => string.Equals(f, xmlStructures[structureTypeName].nameSpace + ".xml", StringComparison.OrdinalIgnoreCase));
// if the official structure is not in the duplicate list, we want to save it in the duplicate list
if (index3 < 0)
{
duplicateStructures[structureTypeName].Add(xmlStructures[structureTypeName].nameSpace + ".xml");
}
}
else
{
xmlStructures[structureTypeName] = tempXmlStructures[tempStructureTypeName];
xmlStructures[structureTypeName].name = structureTypeName;
}
}
else
{
throw new XmlParsingException("Child element \"name\" not found for node \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString());
}
}
///===================================================================================
/// XmlParser.getStructureItem
///===================================================================================
/// <summary>
/// Parse the data structure defined by the XML
/// </summary>
/// <param name="nav">navigator object that points to the current XML node we are at</param>
/// <param name="xmlStructureItem">data structure that stores all data members of the data structure</param>
///===================================================================================
public static void GetStructureItem(XPathNavigator nav, XmlStructureItem xmlStructureItem)
{
do
{
if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase) || string.Equals(nav.Name, "item_name", StringComparison.OrdinalIgnoreCase))
{
xmlStructureItem.name = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "type", StringComparison.OrdinalIgnoreCase))
{
xmlStructureItem.type = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "default", StringComparison.OrdinalIgnoreCase))
{
xmlStructureItem.defaultVal = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "arrayLength", StringComparison.OrdinalIgnoreCase))
{
xmlStructureItem.arrayLength = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "comment", StringComparison.OrdinalIgnoreCase))
{
xmlStructureItem.comments.Add(nav.Value.Trim());
}
else if (string.Equals(nav.Name, "description", StringComparison.OrdinalIgnoreCase))
{
xmlStructureItem.description = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "bits", StringComparison.OrdinalIgnoreCase))
{
xmlStructureItem.bits = nav.Value.Trim();
}
else if (nav.Name.Length > 0)
{
throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString());
}
} while (nav.MoveToNext());
}
///===================================================================================
/// XmlParser.getMbitMessage
///===================================================================================
/// <summary>
/// Parse the message defined by the XML
/// </summary>
/// <param name="nav">navigator object that points to the current XML node we are at</param>
/// <param name="nameSpace">the XML file name that defines this message</param>
/// <param name="mbitMessages">list of messages defined by XML</param>
/// <param name="duplicateMbitMessages">the Dictioanry that stores duplicate messages</param>
///===================================================================================
public static void GetMbitMessage(XPathNavigator nav, string nameSpace, List<XmlMbitMessage> mbitMessages, Dictionary<string, List<string>> duplicateMbitMessages)
{
var mbitMsg = new XmlMbitMessage()
{
nameSpace = nameSpace
};
if (nav.MoveToFirstChild())
{
do
{
if (string.Equals(nav.Name, "name", StringComparison.OrdinalIgnoreCase))
{
mbitMsg.name = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "label", StringComparison.OrdinalIgnoreCase))
{
mbitMsg.label = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "instrulabel", StringComparison.OrdinalIgnoreCase))
{
mbitMsg.instruLabel = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "description", StringComparison.OrdinalIgnoreCase))
{
mbitMsg.description = nav.Value.Trim();
}
else if (string.Equals(nav.Name, "comment", StringComparison.OrdinalIgnoreCase))
{
mbitMsg.comments.Add(nav.Value.Trim());
}
else if (string.Equals(nav.Name, "item", StringComparison.OrdinalIgnoreCase)
|| string.Equals(nav.Name, "struct_item", StringComparison.OrdinalIgnoreCase)
|| string.Equals(nav.Name, "msg_item", StringComparison.OrdinalIgnoreCase))
{
if (nav.MoveToFirstChild())
{
XmlStructureItem structureItem = new XmlStructureItem()
{
nameSpace = nameSpace
};
GetStructureItem(nav, structureItem);
mbitMsg.dataItems.Add(structureItem);
nav.MoveToParent();
}
}
else if (nav.Name.Length > 0)
{
throw new XmlParsingException("Unknown element \"" + nav.OuterXml.Substring(0, nav.OuterXml.IndexOf(">") + 1) + "\" on line " + ((IXmlLineInfo)nav).LineNumber.ToString());
}
} while (nav.MoveToNext());
nav.MoveToParent();
int index = mbitMessages.FindIndex(f => string.Equals(f.name, mbitMsg.name, StringComparison.OrdinalIgnoreCase));
if (index >= 0)
{
// save file name the defines this message that is a duplicate
if (!duplicateMbitMessages.ContainsKey(mbitMsg.name))
{
duplicateMbitMessages[mbitMsg.name] = new List<string>();
}
int index3 = duplicateMbitMessages[mbitMsg.name].FindIndex(f => string.Equals(f, nameSpace + ".xml", StringComparison.OrdinalIgnoreCase));
if (index3 < 0)
duplicateMbitMessages[mbitMsg.name].Add(nameSpace + ".xml");
// see if the official message is already in the duplicate list
int index2 = duplicateMbitMessages[mbitMsg.name].FindIndex(f => string.Equals(f, mbitMessages[index].nameSpace + ".xml", StringComparison.OrdinalIgnoreCase));
// if the official message is not in the duplicate list, we want to save it in the duplicate list
if (index2 < 0)
{
duplicateMbitMessages[mbitMsg.name].Add(mbitMessages[index].nameSpace + ".xml");
}
// the existing message is defined in an xml file other than MsgsMc.xml. At this time, we want the messages in MsgsMc.xml to take precedence over other xml files.
// Why is the same message being defined in multiple xml files?
if (!string.Equals(mbitMessages[index].nameSpace, "msgsmc", StringComparison.OrdinalIgnoreCase) && string.Equals(nameSpace, "msgsmc", StringComparison.OrdinalIgnoreCase))
{
mbitMessages.RemoveAt(index);
mbitMessages.Add(mbitMsg);
}
}
else
mbitMessages.Add(mbitMsg);
}
}
}
}