Subversion Repositories DevTools

Rev

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 base
               rq_project = RQ_Artifact.OpenReqProProject(ea_repository, rq_artifact);
               if (rq_project != null)
               {
                  // give req pro project object to user of this class
                  provideReqProDatabaseInfo(rq_project);

                  // Get the ReqPro root package and parse it
                  ReqPro40.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 name
            OpenFileDialog 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/password
               Logon 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 mechanism
                  ReqPro40.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 class
                     provideReqProDatabaseInfo(rq_project);

                     // Get the ReqPro root package and parse it
                     ReqPro40.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 package
         int 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 it
               ReqPro40.Package subPackage = (ReqPro40.Package)thisPackage.GetCurrentElement();
               parsePackage(level+1, ea_repository, rq_project, subPackage);
               thisPackage.MoveNext();
            }
         }

         // Scan through the requirements directly beneath the root package
         int 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 entry
            int 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 it
               ReqPro40.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 functions
         processPackage(level, ea_repository, rq_project, thisPackage);
         processObject(level, ea_repository, rq_project, thisPackage, null);

         // Scan through the sub-packages of this package
         int 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 it
               ReqPro40.Package subPackage = (ReqPro40.Package)thisPackage.GetCurrentElement();
               parsePackage(level+1, ea_repository, rq_project, subPackage);
               thisPackage.MoveNext();
            }
         }

         // Scan through the requirements directly beneath this package
         int 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 entry
            int 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 it
               ReqPro40.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 functions
         processRequirement(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 those
         int limit_numberOfChildren = 0;
         if (true == thisRequirement.get_HasChildren(ref limit_numberOfChildren))
         {
            // scan through the child relationships
            ReqPro40.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 it
               ReqPro40.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();
            }
         }
      }

        }
}