Subversion Repositories DevTools

Rev

Rev 2151 | Rev 2155 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2141 ghuddy 1
using System;
2151 ghuddy 2
using System.Text;
3
using System.Globalization;
4
using System.Collections;
5
using System.Collections.Specialized;
6
using System.Windows.Forms;
2141 ghuddy 7
using ReqPro40;
8
 
9
 
10
namespace EA_ReqPro
11
{
12
	/// <summary>
13
	/// The ReqProParser class encapsulates a parsing algorithm for a ReqPro database
14
	/// designed to pick out packages and requirement elements and to provide that information
15
	/// to a client with sufficient information to allow it to build a model of that ReqPro
16
	/// database content in memory, maintaining the hierarchy and ordering of objects found.
17
	/// </summary>
18
	public class ReqProParser
19
	{
2151 ghuddy 20
      // lists of meta-data in the ReqPro database
21
      protected ArrayList rq_req_types;
22
      protected ArrayList rq_req_status_types;
23
      protected ArrayList delayedMessages;
24
 
25
      // constructor
2141 ghuddy 26
		public ReqProParser()
27
		{
2151 ghuddy 28
         delayedMessages = new ArrayList();
2141 ghuddy 29
		}
30
 
31
      /// <summary>
32
      /// The parser will call this virtual method when it has opened a ReqPro project
33
      /// </summary>
34
      /// <param name="rq_project"></param>
2145 ghuddy 35
      protected virtual void provideReqProDatabaseInfo(ReqPro40.Application rq_app, 
36
         ReqPro40.Project rq_project, 
37
         ReqProDB_Artifact rq_artifact,
38
         EA.Element rq_element)
2141 ghuddy 39
      {
40
      }
41
 
42
      /// <summary>
43
      /// The parser will call this virtual method for every package it finds
44
      /// in the ReqPro database.
45
      /// </summary>
46
      /// <param name="level"></param>
47
      /// <param name="ea_repository"></param>
48
      /// <param name="rq_project"></param>
49
      /// <param name="rq_Package"></param>
2151 ghuddy 50
      protected virtual void processPackage(int level,
51
                                            ReqPro40.Project rq_project, 
2141 ghuddy 52
                                            ReqPro40.Package rq_package)
53
      {
54
      }
55
 
56
      /// <summary>
57
      /// The parser will call this virtual method for every requirement it
58
      /// finds in the ReqPro database.
59
      /// </summary>
60
      /// <param name="level"></param>
61
      /// <param name="ea_repository"></param>
62
      /// <param name="rq_project"></param>
63
      /// <param name="rq_Package"></param>
64
      /// <param name="rq_Requirement"></param>
2151 ghuddy 65
      protected virtual void processRequirement(int level,
66
                                                ReqPro40.Project rq_project, 
2141 ghuddy 67
                                                ReqPro40.Package rq_package,
68
                                                ReqPro40.Requirement rq_requirement)
69
      {
70
      }
71
 
72
      /// <summary>
73
      /// The parser will call this virtual method for every package or requirement it
74
      /// finds in the ReqPro database.
75
      /// </summary>
76
      /// <param name="level"></param>
77
      /// <param name="ea_repository"></param>
78
      /// <param name="rq_project"></param>
79
      /// <param name="rq_Package"></param>
80
      /// <param name="rq_Requirement"></param>
2151 ghuddy 81
      protected virtual void processObject(int level,
82
                                           ReqPro40.Project rq_project, 
2141 ghuddy 83
                                           ReqPro40.Package rq_package,
84
                                           ReqPro40.Requirement rq_requirement)
85
      {
86
      }
87
 
2151 ghuddy 88
      protected void writeDelayedMessages()
89
      {
90
         foreach(string s in delayedMessages)
91
         {
92
            Main.EA_Repository.WriteOutput( Main.GUI_OUTPUT_TAB_NAME, s, -1);
93
         }
94
      }
2141 ghuddy 95
 
2151 ghuddy 96
      #region Requirement Type methods
2141 ghuddy 97
 
98
      /// <summary>
2151 ghuddy 99
      /// Get the requirement types from the ReqPro database, into a simple list, where each element
100
      /// describes the requirement type and whether it is filtered or not. This list can be given to 
101
      /// the ReqProFilterForm to capture the users requirement type filtering decisions. 
102
      /// </summary>
103
      protected void get_rq_req_types_from_database(ReqPro40.Project RQ_project)
104
      {
105
         rq_req_types = new ArrayList();
106
 
107
         ReqPro40.ReqTypes rqtypes = RQ_project.ReqTypes;
108
         foreach (ReqPro40.ReqType rq_type in rqtypes)
109
         {
110
            ReqPro_ReqType new_req_type = new ReqPro_ReqType(rq_type);
111
            new_req_type.name     = rq_type.Name;
112
            new_req_type.prefix   = rq_type.ReqPrefix;
113
            rq_req_types.Add(new_req_type);
114
         }
115
      }
116
 
117
      /// <summary>
118
      /// Examine the requirement type list to see if the requirement type of the specified object
119
      /// has been filtered or not.
120
      /// </summary>
121
      /// <param name="rq_obj"></param>
122
      /// <returns></returns>
123
      protected bool reqTypeIsFiltered(ReqPro_object rq_obj)
124
      {
125
         return ((ReqPro_ReqType)rq_req_types[rq_obj.tag_enum]).filtered;
126
      }
127
 
2153 ghuddy 128
      protected bool reqTypeHasOneOrMoreAttrs(ReqPro_object rq_obj, 
129
         ref bool hasStatus, 
130
         ref bool hasDiff, 
131
         ref bool hasPrio,
132
         ref bool hasSource,
133
         ref bool hasSourceVersion,
134
         ref bool hasSourceSection)
2151 ghuddy 135
      {
136
         foreach (ReqPro_ReqType rp_rt in rq_req_types)
137
         {
138
            if (rq_obj.tag.StartsWith(rp_rt.prefix))
139
            {
140
               hasStatus = rp_rt.hasStatus;
141
               hasDiff = rp_rt.hasDifficulty;
142
               hasPrio = rp_rt.hasPriority;
2153 ghuddy 143
               hasSource = rp_rt.hasSource;
144
               hasSourceVersion = rp_rt.hasSourceVersion;
145
               hasSourceSection = rp_rt.hasSourceSection;
146
 
147
               return hasStatus | hasDiff | hasPrio | hasSource | hasSourceVersion | hasSourceSection;
2151 ghuddy 148
            }
149
         }
150
 
151
         return false;
152
      }
153
 
154
      #endregion
155
 
156
      #region Requirement Status Type methods
157
 
158
      /// <summary>
159
      /// Get the requirement status types from the ReqPro database, into a simple list, where each element
160
      /// describes the requirement status type and whether it is filtered or not. This list can be given to 
161
      /// the ReqProFilterForm to capture the users requirement status type filtering decisions. 
162
      /// </summary>
163
      protected void get_rq_req_status_types_from_database(ReqPro40.Project RQ_project)
164
      {
165
         StringCollection status_values = new StringCollection();
166
 
167
         // Each requirement type can have its own unique list of status attribute values
168
         // so we have to go through each requirement type and find the set of status values
169
         // that each one has and add them to out string collection, if the collection does
170
         // not already have the strings ofcoarse. So, we are merging together all the status
171
         // values in the ReqPro database, into one set.
172
         foreach (ReqPro_ReqType rp_rt in rq_req_types)
173
         {
174
            try 
175
            {
176
               ReqPro40.Attr attr = rp_rt.rq_type.get_Attr("Status", ReqPro40.enumAttrLookups.eAttrLookups_Label);
177
               rp_rt.hasStatus = true;
178
 
179
               foreach (ReqPro40.ListItem listItem in attr.ListItems)
180
               {
181
                  if (!status_values.Contains(listItem.Text))
182
                  {
183
                     status_values.Add(listItem.Text);
184
                  }
185
               }
186
            }
187
            catch 
188
            {
189
               delayedMessages.Add( string.Format("WARNING, ReqPro requirement type ({0}) has no Status attribute", rp_rt.prefix) );
190
            }
191
            // Also check if this requirement type has any of the other attributes we might import. This is
192
            // a little off topic for this function but this is a convenient place to do this until another
193
            // function is written.
194
            try 
195
            {
196
               ReqPro40.Attr attr = rp_rt.rq_type.get_Attr("Difficulty", ReqPro40.enumAttrLookups.eAttrLookups_Label);
197
               rp_rt.hasDifficulty = true;
198
            }
199
            catch 
200
            {
201
               delayedMessages.Add( string.Format("WARNING, ReqPro requirement type ({0}) has no Difficulty attribute", rp_rt.prefix) );
202
            };
203
 
204
            try 
205
            {
206
               ReqPro40.Attr attr = rp_rt.rq_type.get_Attr("Priority", ReqPro40.enumAttrLookups.eAttrLookups_Label);
207
               rp_rt.hasPriority = true;
208
            }
209
            catch 
210
            {
211
               delayedMessages.Add( string.Format("WARNING, ReqPro requirement type ({0}) has no Priority attribute", rp_rt.prefix) );
212
            };
2153 ghuddy 213
 
214
            try 
215
            {
216
               ReqPro40.Attr attr = rp_rt.rq_type.get_Attr("Source", ReqPro40.enumAttrLookups.eAttrLookups_Label);
217
               rp_rt.hasSource = true;
218
            }
219
            catch 
220
            {
221
               delayedMessages.Add( string.Format("WARNING, ReqPro requirement type ({0}) has no Source attribute", rp_rt.prefix) );
222
            };
223
 
224
            try 
225
            {
226
               ReqPro40.Attr attr = rp_rt.rq_type.get_Attr("Source Version", ReqPro40.enumAttrLookups.eAttrLookups_Label);
227
               rp_rt.hasSourceVersion = true;
228
            }
229
            catch 
230
            {
231
               delayedMessages.Add( string.Format("WARNING, ReqPro requirement type ({0}) has no Source Version attribute", rp_rt.prefix) );
232
            };
233
 
234
            try 
235
            {
236
               ReqPro40.Attr attr = rp_rt.rq_type.get_Attr("Source Section", ReqPro40.enumAttrLookups.eAttrLookups_Label);
237
               rp_rt.hasSourceSection = true;
238
            }
239
            catch 
240
            {
241
               delayedMessages.Add( string.Format("WARNING, ReqPro requirement type ({0}) has no Source Section attribute", rp_rt.prefix) );
242
            };
2151 ghuddy 243
         }
244
 
245
         // if reqpro had no status values, then add a dummy one
246
         if (status_values.Count == 0)
247
         {
248
            status_values.Add("Approved");
249
         }
250
 
251
         // With our merged set of status values, create a list of ReqPro_ReqStatus objects.
252
         rq_req_status_types = new ArrayList();
253
         foreach (string s in status_values)
254
         {
255
            ReqPro_ReqStatus new_ReqPro_ReqStatus = new ReqPro_ReqStatus();
256
            new_ReqPro_ReqStatus.filtered = false;
257
            new_ReqPro_ReqStatus.status_value = s;
258
            rq_req_status_types.Add(new_ReqPro_ReqStatus);
259
         }
260
      }
261
 
262
      /// <summary>
263
      /// Examine the requirement status type list to see if the requirement status type of 
264
      /// the specified object has been filtered or not.
265
      /// </summary>
266
      /// <param name="rq_obj"></param>
267
      /// <returns></returns>
268
      protected bool reqStatusTypeIsFiltered(ReqPro_object rq_obj)
269
      {
270
         foreach (ReqPro_ReqStatus rqs in rq_req_status_types)
271
         {
272
            if (0 == rqs.status_value.CompareTo(rq_obj.status))
273
            {
274
               return rqs.filtered;
275
            }
276
         }
277
         return false;
278
      }
279
 
280
      #endregion
281
 
282
 
283
      /// <summary>
2141 ghuddy 284
      /// Initiates a ReqPro database parsing operation using a prompted reqpro database open operation
285
      /// </summary>
286
      /// <param name="ea_repository"></param>
2151 ghuddy 287
      /// <returns></returns>
288
      public virtual bool prompt_and_parse(ReqProDB_Artifact.MODE mode)
2141 ghuddy 289
      {
2145 ghuddy 290
         ReqPro40.Application rq_app = null;
2141 ghuddy 291
         ReqPro40.Project rq_project = null;
292
 
2151 ghuddy 293
         try
294
         {
295
            // If we can find a ReqProDB artifact in the package, use it to logon to the ReqPro database
296
            ReqProDB_Artifact RQ_Artifact = new ReqProDB_Artifact();
297
            EA.Element RQ_Element = RQ_Artifact.get_rq_artifact();
298
            if (RQ_Element != null)
299
            {
300
               // check to see if the ReqProDB element has the same mode as that specified by parameter
301
               ReqProDB_Artifact.MODE rq_art_mode = RQ_Artifact.get_mode(RQ_Element);
302
               if (rq_art_mode != ReqProDB_Artifact.MODE.UNDEFINED)
303
               {
304
                  if (rq_art_mode != mode)
305
                  {
306
                     DialogResult dlgRes = MessageBoxEx.Show("You are attempting to use a ReqProDB element " +
307
                        "for a different purpose than that which was " +
308
                        "specified when the element was first created. " +
309
                        "Continue Anyway?", "Confirm", MessageBoxButtons.YesNo);
310
                     if (dlgRes != DialogResult.Yes)
311
                     {
312
                        return false;
313
                     }
314
                  }
315
               }
316
 
317
               if (Main.mustAbort)
318
                  return false;
319
 
320
               rq_project = RQ_Artifact.OpenReqProProject(RQ_Element);
321
               if (rq_project != null)
322
                  rq_app = RQ_Artifact.RQ_app;
323
            }
324
 
325
            if (Main.mustAbort)
326
               return false;
327
 
328
            // If no ReqProDB artifact found, prompt user to logon to the ReqPro database
329
            if (rq_project == null)
330
            {
331
               // let user select the ReqPro database file name
332
               OpenFileDialog ofd = new OpenFileDialog();
333
               ofd.Title = "Select Requisite Pro project file";
334
               ofd.Filter = "ReqPro files (*.rqs)|*.rqs|All files (*.*)|*.*";
335
               DialogResult dlgRes = ofd.ShowDialog();
336
               if (dlgRes != DialogResult.OK)
337
                  return false;
338
 
339
               if (Main.mustAbort)
340
                  return false;
341
 
342
               // let user specifiy username/password
343
               Logon logon = new Logon("");
344
               dlgRes = logon.ShowDialog();
345
               if (dlgRes != DialogResult.OK)
346
                  return false;
347
 
348
               if (Main.mustAbort)
349
                  return false;
350
 
351
               string username = logon.ebUserName.Text;
352
               string password = logon.ebPassword.Text;
353
 
354
               // Connect to the ReqPro database using the ReqPro extensibility mechanism
355
               rq_app = new ReqPro40.ApplicationClass();
356
 
357
               rq_project = 
358
                  rq_app.OpenProject(ofd.FileName,
359
                  ReqPro40.enumOpenProjectOptions.eOpenProjOpt_RQSFile,
360
                  username,
361
                  password, 
362
                  enumProjectFlags.eProjFlag_Normal,
363
                  enumRelatedProjectOptions.eRelatedProjOption_ConnectAsSpecified);
364
 
365
               if (Main.mustAbort)
366
                  return false;
367
 
368
               // if we do not currently have a ReqProDB artifact, create one
369
               if (RQ_Element == null)
370
               {
371
                  RQ_Element = RQ_Artifact.create_rq_artifact(
2153 ghuddy 372
                     EA_Utilities.get_selected_package(), 
2151 ghuddy 373
                     rq_project.Name, 
374
                     rq_project.Description, 
375
                     logon.ebUserName.Text, 
376
                     ofd.FileName, 
377
                     rq_project.GUID);
378
               }
379
               if (Main.mustAbort)
380
                  return false;
381
            }
382
 
383
            if (Main.mustAbort)
384
               return false;
385
 
386
            // Now do the parsing of the ReqPro database
387
            if (rq_project != null)
388
            {
2145 ghuddy 389
               // give req pro project object to user of this class
2151 ghuddy 390
               provideReqProDatabaseInfo(rq_app, rq_project, RQ_Artifact, RQ_Element);
391
 
392
               // get the requirement types from the req pro project
393
               get_rq_req_types_from_database(rq_project);
394
 
395
               get_rq_req_status_types_from_database(rq_project);
396
 
397
               // Get the ReqPro root package and parse it
398
               Main.EA_Repository.WriteOutput(Main.GUI_OUTPUT_TAB_NAME, "Acquiring ReqPro Database", -1);
399
               ReqPro40.RootPackage rq_rootPackage = rq_project.GetRootPackage(true);
400
 
401
               parseRootPackage(0, rq_project, rq_rootPackage);
402
 
403
               if (Main.mustAbort)
404
                  return false;
405
 
406
               return true;
407
            }
408
         }
409
         catch (Exception ex)
410
         {
2153 ghuddy 411
            Main.MessageBoxException(ex, "Exception (prompt_and_parse)");
2151 ghuddy 412
            if (rq_project != null)
413
               rq_project.CloseProject();
2141 ghuddy 414
         }  
415
         return false;
2151 ghuddy 416
      }
417
 
2141 ghuddy 418
      /// <summary>
419
      /// This method handles the parsing of the root package in the ReqPro database.
420
      /// The method is almost identical to the parsePackage method, except that this
421
      /// deals with a ReqPro40.RootPackage object, whereas the latter deals with a
422
      /// ReqPro40.Package object. Perhaps the two functions could be combined into 
423
      /// one if we move to .NET 2 where c# has some support for generic (template)
424
      /// programming.
425
      /// </summary>
426
      /// <param name="repository"></param>
427
      /// <param name="rq_project"></param>
2151 ghuddy 428
      /// <param name="thisPackage"></param>
429
      private void parseRootPackage(int level,
430
                                    ReqPro40.Project rq_project, 
431
                                    ReqPro40.RootPackage thisPackage)
432
      {
433
         // Scan through the sub-packages of the root package
434
         int limit_packageCount = thisPackage.get_Count(ReqPro40.enumElementTypes.eElemType_Package);
435
         if (limit_packageCount > 0)
436
         {
437
            int i_packageCount;
438
            thisPackage.MoveFirst();
439
            for (i_packageCount = 0; i_packageCount < limit_packageCount; i_packageCount++)
440
            {
441
               if (Main.mustAbort)
442
                  break;
443
 
444
               // Read the sub-package and parse it
445
               ReqPro40.Package subPackage = (ReqPro40.Package)thisPackage.GetCurrentElement();
446
               parsePackage(level+1, "", rq_project, subPackage);
447
               thisPackage.MoveNext();
448
            }
449
         }
450
 
451
         if (Main.mustAbort)
452
            return;
453
 
454
         // Scan through the requirements directly beneath the root package
455
         int limit_reqCount = thisPackage.get_Count(ReqPro40.enumElementTypes.eElemType_Requirement);
456
         if (limit_reqCount > 0)
457
         {
458
            // Obtain the requirement element key list from the root package and scan through each entry
459
            int i_reqCount;
460
            System.Object[,] keyList = (System.Object[,])thisPackage.KeyList(ReqPro40.enumElementTypes.eElemType_Requirement);
461
            for (i_reqCount = 0; i_reqCount < limit_reqCount; i_reqCount++)
462
            {
463
               if (Main.mustAbort)
464
                  break;
465
 
466
               // Obtain the ReqPro requirement from its key, and parse it
467
               ReqPro40.Requirement thisRequirement = 
468
                  rq_project.GetRequirement(keyList[0,i_reqCount],
469
                                            ReqPro40.enumRequirementLookups.eReqLookup_Key,
470
                                            ReqPro40.enumRequirementsWeights.eReqWeight_Heavy,
471
                                            ReqPro40.enumRequirementFlags.eReqFlag_RetainHierarchy);
472
 
473
               if (thisRequirement != null)
474
               {
475
                  parseRequirement(level+1, rq_project, null, thisRequirement);                  
476
               }
477
            }
478
         }
479
      }
480
 
2141 ghuddy 481
      /// <summary>
482
      /// This method handles the parsing of each package beneath the root package
483
      /// in the ReqPro database.
484
      /// The method is almost identical to the parseRootPackage method, except that 
485
      /// this deals with a ReqPro40.Package object, whereas the latter deals with a
486
      /// ReqPro40.RootPackage object. Perhaps the two functions could be combined into 
487
      /// one if we move to .NET 2 where c# has some support for generic (template)
488
      /// programming.      
489
      /// </summary>
490
      /// <param name="repository"></param>
491
      /// <param name="rq_project"></param>
2151 ghuddy 492
      /// <param name="thisPackage"></param>
493
      private void parsePackage(int level,
494
                                string prefix,
495
                                ReqPro40.Project rq_project, 
496
                                ReqPro40.Package thisPackage)
497
      {
498
         if (Main.mustAbort)
499
            return;
500
 
501
         Main.EA_Repository.WriteOutput(Main.GUI_OUTPUT_TAB_NAME, prefix + thisPackage.Name, -1);
502
 
503
         // call user defined functions
504
         processPackage(level, rq_project, thisPackage);
505
         processObject(level, rq_project, thisPackage, null);
506
 
507
         // Scan through the sub-packages of this package
508
         int limit_packageCount = thisPackage.get_Count(ReqPro40.enumElementTypes.eElemType_Package);
509
         if (limit_packageCount > 0)
510
         {
511
            int i_packageCount;
512
            thisPackage.MoveFirst();
513
            for (i_packageCount = 0; i_packageCount < limit_packageCount; i_packageCount++)
514
            {
515
               if (Main.mustAbort)
516
                  break;
517
 
518
               // Read the sub-package and parse it
519
               ReqPro40.Package subPackage = (ReqPro40.Package)thisPackage.GetCurrentElement();
520
               parsePackage(level+1, prefix + "    ", rq_project, subPackage);
521
               thisPackage.MoveNext();
522
            }
523
         }
524
 
525
         if (Main.mustAbort)
526
            return;
527
 
528
         // Scan through the requirements directly beneath this package
529
         int limit_reqCount = thisPackage.get_Count(ReqPro40.enumElementTypes.eElemType_Requirement);
530
         if (limit_reqCount > 0)
531
         {
532
            // Obtain the requirement element key list from this package and scan through each entry
533
            int i_reqCount;
534
            System.Object[,] keyList = (System.Object[,])thisPackage.KeyList(ReqPro40.enumElementTypes.eElemType_Requirement);
535
            for (i_reqCount = 0; i_reqCount < limit_reqCount; i_reqCount++)
536
            {
537
               if (Main.mustAbort)
538
                  break;
539
 
540
               // Obtain the ReqPro requirement from its key, and parse it
541
               ReqPro40.Requirement thisRequirement = 
542
                  rq_project.GetRequirement(keyList[0,i_reqCount],
543
                                            ReqPro40.enumRequirementLookups.eReqLookup_Key,
544
                                            ReqPro40.enumRequirementsWeights.eReqWeight_Heavy,
545
                                            ReqPro40.enumRequirementFlags.eReqFlag_RetainHierarchy);
546
               if (thisRequirement != null)
547
               {
548
                  parseRequirement(level+1, rq_project, thisPackage, thisRequirement);                  
549
               }
550
            }
551
         }
552
      }
553
 
554
 
555
 
2141 ghuddy 556
      /// <summary>
557
      /// This method parses a requirement and any sub-requirements found in the 
558
      /// ReqPro database by the package/root package parsers.
559
      /// NOTE that when called from the parseRootPackage method, the thisPackage
560
      /// parameter will be null.
561
      /// </summary>
562
      /// <param name="repository"></param>
563
      /// <param name="rq_project"></param>
564
      /// <param name="thisPackage"></param>
2151 ghuddy 565
      /// <param name="thisRequirement"></param>
566
      private void parseRequirement(int level,
567
                                    ReqPro40.Project rq_project, 
568
                                    ReqPro40.Package thisPackage, 
569
                                    ReqPro40.Requirement thisRequirement)
570
      {
571
         if (Main.mustAbort)
572
            return;
2141 ghuddy 573
 
2151 ghuddy 574
         // call user defined functions
575
         processRequirement(level, rq_project, thisPackage, thisRequirement);
576
         processObject(level, rq_project, thisPackage, thisRequirement);
577
 
578
         // requirements can have children that are requirements, so we have to find those
579
         int limit_numberOfChildren = 0;
580
         if (true == thisRequirement.get_HasChildren(ref limit_numberOfChildren))
581
         {
582
            // scan through the child relationships
583
            ReqPro40.Relationships theseRelationships = (ReqPro40.Relationships)thisRequirement.Children;
584
 
585
            int i_numberOfChildren;
586
            theseRelationships.MoveFirst();
587
            for (i_numberOfChildren = 0; i_numberOfChildren < limit_numberOfChildren; i_numberOfChildren++)
588
            {
589
               if (Main.mustAbort)
590
                  break;
591
 
592
               // Obtain the sub-requirement from the relationship, and parse it
593
               ReqPro40.Relationship thisRelationship = theseRelationships.GetCurrentRelationship();
594
 
595
               ReqPro40.Requirement subRequirement = 
596
                  thisRelationship.get_DestinationRequirement(ReqPro40.enumRequirementsWeights.eReqWeight_Heavy);
597
 
598
               if (subRequirement != null)
599
               {
600
                  parseRequirement(level+1, rq_project, thisPackage, subRequirement);
601
               }
602
 
603
               theseRelationships.MoveNext();
604
            }
605
         }
606
      }
607
 
2141 ghuddy 608
	}
2151 ghuddy 609
 
2141 ghuddy 610
}