Rev 2141 | Rev 2151 | 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.Application rq_app,ReqPro40.Project rq_project,ReqProDB_Artifact rq_artifact,EA.Element rq_element){}/// <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 prompted reqpro database open operation/// </summary>/// <param name="ea_repository"></param>/// <returns></returns>public virtual bool prompt_and_parse(EA.Repository ea_repository, ReqProDB_Artifact.MODE mode){ReqPro40.Application rq_app = null;ReqPro40.Project rq_project = null;try{// If we can find a ReqProDB artifact in the package, use it to logon to the ReqPro databaseReqProDB_Artifact RQ_Artifact = new ReqProDB_Artifact();EA.Element RQ_Element = RQ_Artifact.get_rq_artifact(ea_repository);if (RQ_Element != null){// check to see if the ReqProDB element has the same mode as that specified by parameterReqProDB_Artifact.MODE rq_art_mode = RQ_Artifact.get_mode(ea_repository, RQ_Element);if (rq_art_mode != ReqProDB_Artifact.MODE.UNDEFINED){if (rq_art_mode != mode){DialogResult dlgRes = MessageBox.Show("You are attempting to use a ReqProDB element\n" +"for a different purpose than that which was\n" +"specified when the element was first created.\n" +"Continue Anyway?", "Confirm", MessageBoxButtons.YesNo);if (dlgRes != DialogResult.Yes){return false;}}}rq_project = RQ_Artifact.OpenReqProProject(ea_repository, RQ_Element);if (rq_project != null)rq_app = RQ_Artifact.RQ_app;}// If no ReqProDB artifact found, prompt user to logon to the ReqPro databaseif (rq_project == null){// 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)return false;// let user specifiy username/passwordLogon logon = new Logon("");dlgRes = logon.ShowDialog();if (dlgRes != DialogResult.OK)return false;string username = logon.ebUserName.Text;string password = logon.ebPassword.Text;// Connect to the ReqPro database using the ReqPro extensibility mechanismrq_app = new ReqPro40.ApplicationClass();rq_project =rq_app.OpenProject(ofd.FileName,ReqPro40.enumOpenProjectOptions.eOpenProjOpt_RQSFile,username,password,enumProjectFlags.eProjFlag_Normal,enumRelatedProjectOptions.eRelatedProjOption_ConnectAsSpecified);// if we do not currently have a ReqProDB artifact, create oneif (RQ_Element == null){EA_Utilities EA_Utils = new EA_Utilities(ea_repository);RQ_Element = RQ_Artifact.create_rq_artifact( ea_repository,EA_Utils.get_selected_package(),rq_project.Name,rq_project.Description,logon.ebUserName.Text,ofd.FileName,rq_project.GUID);}}// Now do the parsing of the ReqPro databaseif (rq_project != null){// give req pro project object to user of this classprovideReqProDatabaseInfo(rq_app, rq_project, RQ_Artifact, RQ_Element);// 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();}}}}}