Rev 2145 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
using System;using System.Text;using System.Globalization;using System.Collections;using System.Windows.Forms;using ReqPro40;namespace EA_ReqPro{/// <summary>/// The ReqProParser class encapsulates a parsing algorithm for a ReqPro database/// designed to pick out packages and requirement elements and to provide that information/// to a client with sufficient information to allow it to build a model of that ReqPro/// database content in memory, maintaining the hierarchy and ordering of objects found./// </summary>public class ReqProParser{public ReqProParser(){}/// <summary>/// The parser will call this virtual method when it has opened a ReqPro project/// </summary>/// <param name="rq_project"></param>protected virtual void provideReqProDatabaseInfo(ReqPro40.Project rq_project){}/// <summary>/// The parser will call this virtual method for every package it finds/// in the ReqPro database./// </summary>/// <param name="level"></param>/// <param name="ea_repository"></param>/// <param name="rq_project"></param>/// <param name="rq_Package"></param>protected virtual void processPackage(int level,EA.Repository ea_repository,ReqPro40.Project rq_project,ReqPro40.Package rq_package){}/// <summary>/// The parser will call this virtual method for every requirement it/// finds in the ReqPro database./// </summary>/// <param name="level"></param>/// <param name="ea_repository"></param>/// <param name="rq_project"></param>/// <param name="rq_Package"></param>/// <param name="rq_Requirement"></param>protected virtual void processRequirement(int level,EA.Repository ea_repository,ReqPro40.Project rq_project,ReqPro40.Package rq_package,ReqPro40.Requirement rq_requirement){}/// <summary>/// The parser will call this virtual method for every package or requirement it/// finds in the ReqPro database./// </summary>/// <param name="level"></param>/// <param name="ea_repository"></param>/// <param name="rq_project"></param>/// <param name="rq_Package"></param>/// <param name="rq_Requirement"></param>protected virtual void processObject(int level,EA.Repository ea_repository,ReqPro40.Project rq_project,ReqPro40.Package rq_package,ReqPro40.Requirement rq_requirement){}/// <summary>/// Initiates a ReqPro database parsing operation using a ReqProDB artifact in EA./// This method assumes user has selected the artifact in EA's project browser./// </summary>/// <param name="ea_repository"></param>public virtual bool parse(EA.Repository ea_repository){ReqPro40.Project rq_project = null;try{ReqProDB_Artifact RQ_Artifact = new ReqProDB_Artifact();EA.Element rq_artifact = RQ_Artifact.get_rq_artifact(ea_repository);if (rq_artifact != null){// open the ReqPro data baserq_project = RQ_Artifact.OpenReqProProject(ea_repository, rq_artifact);if (rq_project != null){// give req pro project object to user of this classprovideReqProDatabaseInfo(rq_project);// Get the ReqPro root package and parse itReqPro40.RootPackage rq_rootPackage = rq_project.GetRootPackage(true);parseRootPackage(0, ea_repository, rq_project, rq_rootPackage);}else{return false;}}}catch (Exception ex){MessageBox.Show(ex.Message, "Error (ReqProParser::parse)", MessageBoxButtons.OK);if (rq_project != null)rq_project.CloseProject();return false;}return true;}/// <summary>/// Initiates a ReqPro database parsing operation using a prompted reqpro database open operation/// </summary>/// <param name="ea_repository"></param>/// <returns></returns>public virtual bool prompt_and_parse(EA.Repository ea_repository){ReqPro40.Project rq_project = null;try{// let user select the ReqPro database file nameOpenFileDialog ofd = new OpenFileDialog();ofd.Title = "Select Requisite Pro project file";ofd.Filter = "ReqPro files (*.rqs)|*.rqs|All files (*.*)|*.*";DialogResult dlgRes = ofd.ShowDialog();if (dlgRes == DialogResult.OK){// let user specifiy username/passwordLogon logon = new Logon("");dlgRes = logon.ShowDialog();if (dlgRes == DialogResult.OK){string username = logon.ebUserName.Text;string password = logon.ebPassword.Text;// Connect to the ReqPro database using the ReqPro extensibility mechanismReqPro40.Application reqPro = new ReqPro40.ApplicationClass();rq_project =reqPro.OpenProject(ofd.FileName,ReqPro40.enumOpenProjectOptions.eOpenProjOpt_RQSFile,username,password,enumProjectFlags.eProjFlag_Normal,enumRelatedProjectOptions.eRelatedProjOption_ConnectAsSpecified);if (rq_project != null){// give req pro project object to user of this classprovideReqProDatabaseInfo(rq_project);// Get the ReqPro root package and parse itReqPro40.RootPackage rq_rootPackage = rq_project.GetRootPackage(true);parseRootPackage(0, ea_repository, rq_project, rq_rootPackage);return true;}}}}catch (Exception ex){MessageBox.Show(ex.Message, "Error (ReqProParser::prompt_and_parse)", MessageBoxButtons.OK);if (rq_project != null)rq_project.CloseProject();}return false;}/// <summary>/// This method handles the parsing of the root package in the ReqPro database./// The method is almost identical to the parsePackage method, except that this/// deals with a ReqPro40.RootPackage object, whereas the latter deals with a/// ReqPro40.Package object. Perhaps the two functions could be combined into/// one if we move to .NET 2 where c# has some support for generic (template)/// programming./// </summary>/// <param name="repository"></param>/// <param name="rq_project"></param>/// <param name="thisPackage"></param>private void parseRootPackage(int level,EA.Repository ea_repository,ReqPro40.Project rq_project,ReqPro40.RootPackage thisPackage){// Scan through the sub-packages of the root packageint limit_packageCount = thisPackage.get_Count(ReqPro40.enumElementTypes.eElemType_Package);if (limit_packageCount > 0){int i_packageCount;thisPackage.MoveFirst();for (i_packageCount = 0; i_packageCount < limit_packageCount; i_packageCount++){// Read the sub-package and parse itReqPro40.Package subPackage = (ReqPro40.Package)thisPackage.GetCurrentElement();parsePackage(level+1, ea_repository, rq_project, subPackage);thisPackage.MoveNext();}}// Scan through the requirements directly beneath the root packageint limit_reqCount = thisPackage.get_Count(ReqPro40.enumElementTypes.eElemType_Requirement);if (limit_reqCount > 0){// Obtain the requirement element key list from the root package and scan through each entryint i_reqCount;System.Object[,] keyList = (System.Object[,])thisPackage.KeyList(ReqPro40.enumElementTypes.eElemType_Requirement);for (i_reqCount = 0; i_reqCount < limit_reqCount; i_reqCount++){// Obtain the ReqPro requirement from its key, and parse itReqPro40.Requirement thisRequirement =rq_project.GetRequirement(keyList[0,i_reqCount],ReqPro40.enumRequirementLookups.eReqLookup_Key,ReqPro40.enumRequirementsWeights.eReqWeight_Heavy,ReqPro40.enumRequirementFlags.eReqFlag_RetainHierarchy);if (thisRequirement != null){parseRequirement(level+1, ea_repository, rq_project, null, thisRequirement);}}}}/// <summary>/// This method handles the parsing of each package beneath the root package/// in the ReqPro database./// The method is almost identical to the parseRootPackage method, except that/// this deals with a ReqPro40.Package object, whereas the latter deals with a/// ReqPro40.RootPackage object. Perhaps the two functions could be combined into/// one if we move to .NET 2 where c# has some support for generic (template)/// programming./// </summary>/// <param name="repository"></param>/// <param name="rq_project"></param>/// <param name="thisPackage"></param>private void parsePackage(int level,EA.Repository ea_repository,ReqPro40.Project rq_project,ReqPro40.Package thisPackage){// call user defined functionsprocessPackage(level, ea_repository, rq_project, thisPackage);processObject(level, ea_repository, rq_project, thisPackage, null);// Scan through the sub-packages of this packageint limit_packageCount = thisPackage.get_Count(ReqPro40.enumElementTypes.eElemType_Package);if (limit_packageCount > 0){int i_packageCount;thisPackage.MoveFirst();for (i_packageCount = 0; i_packageCount < limit_packageCount; i_packageCount++){// Read the sub-package and parse itReqPro40.Package subPackage = (ReqPro40.Package)thisPackage.GetCurrentElement();parsePackage(level+1, ea_repository, rq_project, subPackage);thisPackage.MoveNext();}}// Scan through the requirements directly beneath this packageint limit_reqCount = thisPackage.get_Count(ReqPro40.enumElementTypes.eElemType_Requirement);if (limit_reqCount > 0){// Obtain the requirement element key list from this package and scan through each entryint i_reqCount;System.Object[,] keyList = (System.Object[,])thisPackage.KeyList(ReqPro40.enumElementTypes.eElemType_Requirement);for (i_reqCount = 0; i_reqCount < limit_reqCount; i_reqCount++){// Obtain the ReqPro requirement from its key, and parse itReqPro40.Requirement thisRequirement =rq_project.GetRequirement(keyList[0,i_reqCount],ReqPro40.enumRequirementLookups.eReqLookup_Key,ReqPro40.enumRequirementsWeights.eReqWeight_Heavy,ReqPro40.enumRequirementFlags.eReqFlag_RetainHierarchy);if (thisRequirement != null){parseRequirement(level+1, ea_repository, rq_project, thisPackage, thisRequirement);}}}}/// <summary>/// This method parses a requirement and any sub-requirements found in the/// ReqPro database by the package/root package parsers./// NOTE that when called from the parseRootPackage method, the thisPackage/// parameter will be null./// </summary>/// <param name="repository"></param>/// <param name="rq_project"></param>/// <param name="thisPackage"></param>/// <param name="thisRequirement"></param>private void parseRequirement(int level,EA.Repository ea_repository,ReqPro40.Project rq_project,ReqPro40.Package thisPackage,ReqPro40.Requirement thisRequirement){// call user defined functionsprocessRequirement(level, ea_repository, rq_project, thisPackage, thisRequirement);processObject(level, ea_repository, rq_project, thisPackage, thisRequirement);// requirements can have children that are requirements, so we have to find thoseint limit_numberOfChildren = 0;if (true == thisRequirement.get_HasChildren(ref limit_numberOfChildren)){// scan through the child relationshipsReqPro40.Relationships theseRelationships = (ReqPro40.Relationships)thisRequirement.Children;int i_numberOfChildren;theseRelationships.MoveFirst();for (i_numberOfChildren = 0; i_numberOfChildren < limit_numberOfChildren; i_numberOfChildren++){// Obtain the sub-requirement from the relationship, and parse itReqPro40.Relationship thisRelationship = theseRelationships.GetCurrentRelationship();ReqPro40.Requirement subRequirement =thisRelationship.get_DestinationRequirement(ReqPro40.enumRequirementsWeights.eReqWeight_Heavy);if (subRequirement != null){parseRequirement(level+1, ea_repository, rq_project, thisPackage, subRequirement);}theseRelationships.MoveNext();}}}}}