Subversion Repositories DevTools

Rev

Rev 2173 | 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.Windows.Forms;
2141 ghuddy 6
using ReqPro40;
7
 
8
 
9
namespace EA_ReqPro
10
{
11
 
12
	/// <summary>
2173 ghuddy 13
   /// ImportReqProDatabase is a specialisation of CopyReqProDatabaseToMemory, designed to copy the
14
   /// ReqPro database content into an EA database, discarding the structure of and hierarchy of
2155 ghuddy 15
   /// packages, selecting just the requirements found in the ReqPro database for storage into EA,
16
   /// where they will be used for design traceability purposes.
2141 ghuddy 17
	/// </summary>
2155 ghuddy 18
   public class ImportReqProDatabase : CopyReqProDatabaseToMemory
19
   {
2167 ghuddy 20
      private struct req_lists_t
21
      {
22
         public ArrayList ea_reqs;
23
         public ArrayList ea_GUIDs;
24
         public ArrayList new_ea_reqs;
25
         public ArrayList new_ea_GUIDs;
2173 ghuddy 26
         public ArrayList orphaned_ea_reqs;
2167 ghuddy 27
      };
28
 
2173 ghuddy 29
      private req_lists_t gReq_lists = new req_lists_t();
2167 ghuddy 30
 
2151 ghuddy 31
      private int totalRequirements = 0;
32
 
2167 ghuddy 33
      private EA.Package gCurrentPackage = null;
34
      private EA.Package gNewReqProDBPackage = null;
35
      private EA.Package gChangeHistoryPackage = null;
36
      private EA.Package gOrphansPackage = null;
37
 
2173 ghuddy 38
      private int gNewRequirementCount = 0;
39
      private int gModifiedRequirementCount = 0;
40
      private int gStatusUpdatedRequirementCount = 0;
41
      private int gOrphanedCount = 0;
2167 ghuddy 42
 
2173 ghuddy 43
      private EA.Element gChangeLog = null;
44
 
2141 ghuddy 45
      /// <summary>
46
      /// Constructor logic
47
      /// </summary>
48
      /// <param name="ea_repository"></param>
2151 ghuddy 49
      public ImportReqProDatabase(): base()
2155 ghuddy 50
      {
2151 ghuddy 51
         totalRequirements = 0;
2155 ghuddy 52
      }
2141 ghuddy 53
 
54
 
55
      /// <summary>
56
      /// Method to parse a ReqPro database using the information in a ReqProDB artifact,
57
      /// assumed to be selected in EA's project browser prior to the method call.
58
      /// </summary>
59
      /// <param name="ea_repository"></param>
60
      /// <returns></returns>
2155 ghuddy 61
      public override bool prompt_and_parse(ReqProDB_Artifact.MODE mode, out bool cancelled)
2151 ghuddy 62
      {
2155 ghuddy 63
         cancelled = false;
64
 
2151 ghuddy 65
         try
66
         {
2155 ghuddy 67
            base.structure_only = false;
68
 
69
            string importDateTime = System.DateTime.Now.ToString();
70
 
71
            Main.WriteOutput("EA Requirement import at " + importDateTime, -1 );
72
            Main.WriteOutput("",-1);
73
 
74
            if (true == base.prompt_and_parse(mode, out cancelled))
2151 ghuddy 75
            {
76
               if (Main.mustAbort)
77
                  return false;
78
 
79
               Main.EA_Repository.EnsureOutputVisible(Main.GUI_OUTPUT_TAB_NAME);
80
 
81
               // Configure the ReqProDB artifact as a traceability artifact
82
               RQ_Artifact.set_traceability_mode(RQ_Element);
83
 
2155 ghuddy 84
               ImportFromReqPro(importDateTime);
2151 ghuddy 85
 
86
               return true;
87
            }
88
         }
89
         catch (Exception ex)
90
         {
2153 ghuddy 91
            Main.MessageBoxException(ex, "Exception (parse)");
2173 ghuddy 92
         }
2155 ghuddy 93
 
2151 ghuddy 94
         return false;
95
      }
96
 
2167 ghuddy 97
 
2141 ghuddy 98
      /// <summary>
99
      /// Displays the content of the change log element to the output trace display. This method must
100
      /// be kept in sync with the ImportFromReqPro method, obviously.
101
      /// </summary>
102
      /// <param name="ea_repository"></param>
2151 ghuddy 103
      /// <param name="changeLog"></param>
104
      public void displayChangeLog(EA.Element changeLog)
2141 ghuddy 105
      {
2175 ghuddy 106
         int numberOfChangesForDeletedElements = 0;
107
 
2167 ghuddy 108
         Main.WriteOutput("Displaying Import Change Log", -1);
2141 ghuddy 109
 
2167 ghuddy 110
         if (changeLog.Notes == null || changeLog.Notes.Length == 0 || changeLog.Notes.Trim().Length == 0)
111
         {
112
            Main.WriteOutput("  No changes", -1);
113
         }
114
         else
115
         {
116
            // The change log element contains all the log in its notes section. Break it up into
117
            // lines, because each line is a single log entry, so that we can process them one at
118
            // a time.
119
            string delimStr = "\n";
120
            char [] delim = delimStr.ToCharArray();
121
            string[] log_strings = changeLog.Notes.Split(delim,2000);
2141 ghuddy 122
 
123
 
2167 ghuddy 124
            // modify delimiters to : character so that we can extract the parameters for each log entry
125
            delimStr = ":";
126
            delim = delimStr.ToCharArray();
2141 ghuddy 127
 
2167 ghuddy 128
            foreach(string s in log_strings)
129
            {
130
               if (Main.mustAbort)
131
                  break;
2151 ghuddy 132
 
2167 ghuddy 133
               // over time, users may delete the orphaned requirements from the EA database, but their
2173 ghuddy 134
               // GUIDs will still exist in the change log. Use of such a GUID will cause
2167 ghuddy 135
               // an exception in the GetElementByGuid() function. What should we do? We can attempt
136
               // to remove those GUIDs from the list. We can do this by accumulating a new list of GUIDs
2173 ghuddy 137
               // that is formed from the old list, where only good items from the old list find their
2167 ghuddy 138
               // way into the new list. Gradually, the list is wittled away as EA users delete orphaned
139
               // requirements having first dealt with the design change impacts that resulted from their
140
               // orphanage.
141
               try
2141 ghuddy 142
               {
2167 ghuddy 143
                  if (s.StartsWith("{"))
144
                  {
145
                     string trimmed_s = s.Trim();
2141 ghuddy 146
 
2167 ghuddy 147
                     // Get log entry;s parameters.
148
                     string[] parameters = trimmed_s.Split(delim, 10);
2141 ghuddy 149
 
2167 ghuddy 150
                     // The first parameter is the GUID so use it to get the requirement element
151
                     EA.Element ea_req = Main.EA_Repository.GetElementByGuid(parameters[0]);
2141 ghuddy 152
 
2167 ghuddy 153
                     // Now discriminate actions based on the second parameter
2141 ghuddy 154
 
2167 ghuddy 155
                     if (parameters[1].StartsWith("Created"))
2141 ghuddy 156
                     {
2175 ghuddy 157
                        // user may have deleted old orphaned requirements so we would not be able to get the EA
158
                        // element so we cannot use it for display purposes at all.
159
                        if (ea_req == null)
160
                        {
161
                           Main.WriteOutput("  Created : " + parameters[2], -1 );
162
                        }
163
                        else
164
                        {
165
                           Main.WriteOutput("  Created : " + ea_req.Name, ea_req.ElementID );
166
                        }
2167 ghuddy 167
                     }
168
                        /////////////////////////////////////////////////////////////////////////////////////////////////////////////
169
                     else if (parameters[1].StartsWith("Orphaned"))
170
                     {
2175 ghuddy 171
                        // user may have deleted old orphaned requirements so we would not be able to get the EA
172
                        // element so we cannot use it for display purposes at all.
173
                        if (ea_req == null)
2167 ghuddy 174
                        {
2175 ghuddy 175
                           Main.WriteOutput("  Orphaned : " + parameters[2], -1 );
176
                        }
177
                        else
178
                        {
179
                           // We have the EA element so do a full display of the orphaned item
180
                           Main.WriteOutput("  Orphaned : " + ea_req.Name, ea_req.ElementID );
2159 ghuddy 181
 
2175 ghuddy 182
                           foreach (EA.Connector theConnector in ea_req.Connectors)
183
                           {
184
                              int destId = -1;
2167 ghuddy 185
 
2175 ghuddy 186
                              // we dont care about direction of relationship, so test for both
187
                              if (theConnector.ClientID == ea_req.ElementID)
188
                                 destId = theConnector.SupplierID;
189
                              else if (theConnector.SupplierID == ea_req.ElementID)
190
                                 destId = theConnector.ClientID;
2167 ghuddy 191
                              else
2175 ghuddy 192
                                 destId = theConnector.SupplierID;
193
 
194
                              // and make sure we filter out self-referential connectors
195
                              if (destId != ea_req.ElementID)
2167 ghuddy 196
                              {
2175 ghuddy 197
                                 EA.Package tgt_pkg = (EA.Package)Main.EA_Repository.GetPackageByID( destId );
198
                                 if (tgt_pkg != null)
2167 ghuddy 199
                                 {
2175 ghuddy 200
                                    Main.WriteOutput("     --> " + tgt_pkg.Name, tgt_pkg.PackageID);
2167 ghuddy 201
                                 }
2175 ghuddy 202
                                 else
203
                                 {
204
                                    EA.Element tgt_ele = (EA.Element)Main.EA_Repository.GetElementByID( destId );
205
                                    if (tgt_ele != null)
206
                                    {
207
                                       //if (!tgt_ele.Type.StartsWith("Requirement"))
208
                                       Main.WriteOutput("     --> " + tgt_ele.Name, tgt_ele.ElementID);
209
                                    }
210
                                 }
2167 ghuddy 211
                              }
2159 ghuddy 212
                           }
2141 ghuddy 213
                        }
214
                     }
2175 ghuddy 215
                     else
2167 ghuddy 216
                     {
2175 ghuddy 217
                        if (ea_req != null)
218
                        {
219
                           /////////////////////////////////////////////////////////////////////////////////////////////////////////////
220
                           if (parameters[1].StartsWith(Constants.CHG_LOG_NAME))
221
                           {
222
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", Constants.CHG_LOG_NAME, ea_req.Name), ea_req.ElementID );
223
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
224
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
225
                           }
226
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////
227
                           else if (parameters[1].StartsWith(Constants.CHG_LOG_NOTES)) // aka Description of the requirement
228
                           {
229
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", "Description", ea_req.Name), ea_req.ElementID );
230
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
231
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
232
                           }
233
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////
234
                           else if (parameters[1].StartsWith(Constants.CHG_LOG_DIFFICULTY))
235
                           {
236
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", Constants.CHG_LOG_DIFFICULTY, ea_req.Name), ea_req.ElementID );
237
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
238
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
239
                           }
240
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////
241
                           else if (parameters[1].StartsWith(Constants.CHG_LOG_PRIORITY))
242
                           {
243
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", Constants.CHG_LOG_PRIORITY, ea_req.Name), ea_req.ElementID );
244
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
245
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
246
                           }
247
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////
248
                           else if (parameters[1].StartsWith(Constants.CHG_LOG_VERSION))
249
                           {
250
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", Constants.CHG_LOG_VERSION, ea_req.Name), ea_req.ElementID );
251
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
252
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
253
                           }
254
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////
255
                           else if (parameters[1].StartsWith(Constants.CHG_LOG_STATUS))
256
                           {
257
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", Constants.CHG_LOG_STATUS, ea_req.Name), ea_req.ElementID );
258
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
259
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
260
                           }
261
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////
262
                           else if (parameters[1].StartsWith(Constants.CHG_LOG_SUBSYSTEM_TYPE))
263
                           {
264
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", Constants.CHG_LOG_SUBSYSTEM_TYPE, ea_req.Name), ea_req.ElementID );
265
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
266
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
267
                           }
268
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////
269
                           else if (parameters[1].StartsWith(Constants.CHG_LOG_STABILITY))
270
                           {
271
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", Constants.CHG_LOG_STABILITY, ea_req.Name), ea_req.ElementID );
272
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
273
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
274
                           }
275
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////
276
                           else if (parameters[1].StartsWith(Constants.CHG_LOG_REQ_TYPE))
277
                           {
278
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", Constants.CHG_LOG_REQ_TYPE, ea_req.Name), ea_req.ElementID );
279
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
280
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
281
                           }
282
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////
283
                           else if (parameters[1].StartsWith(Constants.CHG_LOG_SOURCE_VERSION))
284
                           {
285
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", Constants.CHG_LOG_SOURCE_VERSION, ea_req.Name), ea_req.ElementID );
286
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
287
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
288
                           }
289
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////
290
                           else if (parameters[1].StartsWith(Constants.CHG_LOG_SOURCE_SECTION))
291
                           {
292
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", Constants.CHG_LOG_SOURCE_SECTION, ea_req.Name), ea_req.ElementID );
293
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
294
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
295
                           }
296
                              /////////////////////////////////////////////////////////////////////////////////////////////////////////////
297
                           else if (parameters[1].StartsWith(Constants.CHG_LOG_SOURCE))
298
                           {
299
                              Main.WriteOutput(string.Format("  Modified {0}: {1}", Constants.CHG_LOG_SOURCE, ea_req.Name), ea_req.ElementID );
300
                              Main.WriteOutput("     <<< " + parameters[2], ea_req.ElementID);
301
                              Main.WriteOutput("     >>> " + parameters[3], ea_req.ElementID);
302
                           }
303
                        }
304
                        else
305
                        {
306
                           numberOfChangesForDeletedElements++;
307
                        }
2167 ghuddy 308
                     }
2141 ghuddy 309
                  }
310
               }
2167 ghuddy 311
               catch
312
               {
313
               }
2141 ghuddy 314
            }
315
         }
2175 ghuddy 316
         if (numberOfChangesForDeletedElements > 0)
317
         {
318
            Main.WriteOutput("NOTE: Some propert changes were not shown because the requirement elements have since been deleted", -1);
319
            Main.WriteOutput("and it is impossible to use the change log recorded GUIDs to determine what they were.", -1);
320
         }
2141 ghuddy 321
      }
322
 
2147 ghuddy 323
 
324
      /// <summary>
2173 ghuddy 325
      /// Rid a string of any : char because we use that as a delimiter in the change log and so we
2147 ghuddy 326
      /// do not want a users use of the character to confuse the change log display mechanism.
327
      /// </summary>
328
      /// <param name="s"></param>
329
      /// <returns></returns>
330
      private string NO_COLONS(string s)
331
      {
332
         string sc =  s.Replace(':', ' ');
333
         sc = sc.Replace('\r' , ' ');
334
         sc = sc.Replace('\n' , ' ');
2173 ghuddy 335
 
2147 ghuddy 336
         return sc;
337
      }
2151 ghuddy 338
 
339
 
2155 ghuddy 340
 
341
 
2151 ghuddy 342
      /// <summary>
343
      /// A method that imports requirements from a ReqPro database into EA for the purpose
344
      /// of supporting requirement-to-design traceability.
345
      /// </summary>
346
      /// <param name="repository"></param>
2155 ghuddy 347
      private void ImportFromReqPro(string importDateTime)
2151 ghuddy 348
      {
349
         try
350
         {
2167 ghuddy 351
            DialogResult dlgres;
352
 
353
            // begin to initialise some of our element lists
2173 ghuddy 354
            gReq_lists.new_ea_reqs = new ArrayList();
355
            gReq_lists.new_ea_GUIDs = new ArrayList();
356
            gReq_lists.ea_GUIDs = new ArrayList();
357
            gReq_lists.orphaned_ea_reqs = new ArrayList();
2167 ghuddy 358
 
2151 ghuddy 359
            ArrayList ea_req_matched = new ArrayList();
360
 
2167 ghuddy 361
            // Obtain the EA parent package so that we can create under it our ReqProDB structure and change history packages
2151 ghuddy 362
            EA.Package parentPackage = Main.EA_Repository.GetPackageByID( base.RQ_Element.PackageID );
363
 
2167 ghuddy 364
            // Find or create the change history package in which to store change logs
365
            gChangeHistoryPackage = find_or_create_change_history_package(parentPackage);
366
 
367
            // create the ReqProDB structure package in the parent container package, and attach it to its counterpart
368
            // in the ReqPro_object tree structure (ie. attach it to the root node therein).
369
            gNewReqProDBPackage = (EA.Package)parentPackage.Packages.AddNew( "ReqProDB " + importDateTime, "Package");
370
            gNewReqProDBPackage.Update();
371
            rq_root_package.ea_element_ID = gNewReqProDBPackage.PackageID;
372
 
373
            // Migrate the older form of import directory and change log, into the newer format
374
            migrate_old_import_packages_to_change_history_package(parentPackage);
375
            Main.EA_Repository.RefreshModelView(parentPackage.PackageID);
376
 
377
            if (Main.mustAbort)
378
               return;
379
 
380
            // Create a package to hold orphans. This will be removed later on if it ends up empty.
381
            gOrphansPackage = find_or_create_orphans_package(parentPackage);
382
 
383
            // Get a list of EA requirements that already exist under the overall ReqProDB container package
2151 ghuddy 384
            ArrayList allowedElementTypes = new ArrayList();
385
            allowedElementTypes.Add("Requirement");
386
            allowedElementTypes.Add("UseCase");
387
 
2155 ghuddy 388
            Main.WriteOutput("Acquiring list of elements already in EA", -1);
2169 ghuddy 389
            EA_ElementAccumulator reqLister = new EA_ElementAccumulator(allowedElementTypes);
390
            EA_Parsing.findAndProcessPackageElements( parentPackage, reqLister, true );
2151 ghuddy 391
 
2173 ghuddy 392
            gReq_lists.ea_reqs = reqLister.Elements;
2167 ghuddy 393
 
2151 ghuddy 394
            if (Main.mustAbort)
395
               return;
396
 
2173 ghuddy 397
            // For the list we just found, get an adjacent list of the associated ReqPro GUIDs.
2167 ghuddy 398
            // The two lists will be indexable by the same index.
2173 ghuddy 399
            foreach (EA.Element ea_req in gReq_lists.ea_reqs)
2151 ghuddy 400
            {
2155 ghuddy 401
               string GUID = EA_TaggedValues.Read(ea_req, Constants.TAG_GUID);
2173 ghuddy 402
               gReq_lists.ea_GUIDs.Add(GUID);
2151 ghuddy 403
               ea_req_matched.Add(false);
404
            }
405
 
406
            if (Main.mustAbort)
407
               return;
408
 
409
 
2167 ghuddy 410
            // Create the change log element in the change history package
2173 ghuddy 411
            gChangeLog = (EA.Element)gChangeHistoryPackage.Elements.AddNew("Change Log" + " - import " + importDateTime, "InformationItem");
412
            gChangeLog.Notes = "";
413
            gChangeLog.TreePos = gChangeHistoryPackage.Elements.Count - 1;
414
            gChangeLog.Update();
2151 ghuddy 415
 
416
            // Get a flattened list of requirements from the hierarchical data the user has filtered
417
            ArrayList rq_req_collection = new ArrayList();
418
            get_rq_req_collection(ref rq_req_collection);
419
 
2167 ghuddy 420
            // initialise some statistical vars
2173 ghuddy 421
            gNewRequirementCount = 0;
422
            gModifiedRequirementCount = 0;
423
            gStatusUpdatedRequirementCount = 0;
424
            gOrphanedCount = 0;
2151 ghuddy 425
 
426
 
2155 ghuddy 427
            Main.WriteOutput("Merging ReqPro content to EA", -1);
2167 ghuddy 428
 
429
            // loop through all of the ReqPro requirements we have captured from the ReqPro database
2151 ghuddy 430
            foreach(ReqPro_object rq_obj in rq_req_collection)
431
            {
432
               if (Main.mustAbort)
433
                  break;
434
 
435
               try
436
               {
437
                  // Find which EA requirement element refers to the current ReqPro GUID
438
                  int i_ea_req;
2173 ghuddy 439
                  i_ea_req = gReq_lists.ea_GUIDs.IndexOf( rq_obj.guid );
2151 ghuddy 440
 
441
                  // If EA element was found
442
                  if (0 <= i_ea_req)
443
                  {
2173 ghuddy 444
                     // update orphanage detection data
2151 ghuddy 445
                     ea_req_matched[i_ea_req] = true;
2173 ghuddy 446
                     rq_obj.matched = true;
2151 ghuddy 447
 
2173 ghuddy 448
                     EA.Element ea_req = ((EA.Element)gReq_lists.ea_reqs[i_ea_req]);
2151 ghuddy 449
 
450
                     rq_obj.ea_element_ID = ea_req.ElementID;
451
 
2155 ghuddy 452
                     // Only update the requirement if it was not mastered in EA, or
453
                     // unrestricted imports have been enabled
454
                     if (  (false == EA_TaggedValues.Read(ea_req, Constants.TAG_CREATED_IN_EA, Constants.DEFAULT_CREATED_IN_EA))
455
                        || (true == EA_TaggedValues.Read(ea_req, Constants.TAG_UNRESTRICTED_IMPORTS, Constants.DEFAULT_UNRESTRICTED_IMPORTS)) )
456
                     {
457
                        // This ReqPro requirement already has a counterpart in EA, so we must simply
458
                        // update the counterpart. But, to aid the designer, we need to try to tell them
2173 ghuddy 459
                        // how the requirement has changed, which could ofcoarse change the meaning
2155 ghuddy 460
                        // of the requirement and require design changes to be done.
2151 ghuddy 461
 
2155 ghuddy 462
                        bool meaningMayHaveChanged = false;
463
                        bool statusMayHaveChanged = false;
2173 ghuddy 464
 
2155 ghuddy 465
                        string ea_req_name = rq_obj.tag + " " + rq_obj.name;
2151 ghuddy 466
 
2155 ghuddy 467
                        Main.WriteOutput("Updating: " + ea_req_name, rq_obj.ea_element_ID);
2151 ghuddy 468
 
2173 ghuddy 469
                        ea_req.Name       = updated_property_value_if_changed(gChangeLog, ea_req, ea_req.Name, Constants.CHG_LOG_NAME, ea_req_name, ref meaningMayHaveChanged);
2151 ghuddy 470
 
2173 ghuddy 471
                        ea_req.Notes      = updated_property_value_if_changed(gChangeLog, ea_req, ea_req.Notes, Constants.CHG_LOG_NOTES, rq_obj.text, ref meaningMayHaveChanged);
2151 ghuddy 472
 
2173 ghuddy 473
                        ea_req.Difficulty = updated_property_value_if_changed(gChangeLog, ea_req, ea_req.Difficulty, Constants.CHG_LOG_DIFFICULTY, rq_obj.difficulty, ref statusMayHaveChanged);
2151 ghuddy 474
 
2173 ghuddy 475
                        ea_req.Priority   = updated_property_value_if_changed(gChangeLog, ea_req, ea_req.Priority, Constants.CHG_LOG_PRIORITY, rq_obj.priority, ref statusMayHaveChanged);
2151 ghuddy 476
 
2173 ghuddy 477
                        ea_req.Status     = updated_property_value_if_changed(gChangeLog, ea_req, ea_req.Status, Constants.CHG_LOG_STATUS, rq_obj.status, ref statusMayHaveChanged);
2155 ghuddy 478
 
2173 ghuddy 479
                        if_tagged_value_changed_update_it(gChangeLog, ea_req, Constants.TAG_SOURCE, Constants.CHG_LOG_SOURCE, rq_obj.source, ref statusMayHaveChanged);
2155 ghuddy 480
 
2173 ghuddy 481
                        if_tagged_value_changed_update_it(gChangeLog, ea_req, Constants.TAG_SOURCE_VERSION, Constants.CHG_LOG_SOURCE_VERSION, rq_obj.sourceVersion, ref statusMayHaveChanged);
2155 ghuddy 482
 
2173 ghuddy 483
                        if_tagged_value_changed_update_it(gChangeLog, ea_req, Constants.TAG_SOURCE_SECTION, Constants.CHG_LOG_SOURCE_SECTION, rq_obj.sourceSection, ref statusMayHaveChanged);
2155 ghuddy 484
 
2173 ghuddy 485
                        if_tagged_value_changed_update_it(gChangeLog, ea_req, Constants.TAG_SUBSYSTEM, Constants.CHG_LOG_SUBSYSTEM_TYPE, rq_obj.subsystem, ref statusMayHaveChanged);
2155 ghuddy 486
 
2173 ghuddy 487
                        if_tagged_value_changed_update_it(gChangeLog, ea_req, Constants.TAG_STABILITY, Constants.CHG_LOG_STABILITY, rq_obj.stability, ref statusMayHaveChanged);
2155 ghuddy 488
 
489
                        // Requirement Types are actually implemented using ordinary EA element stereotypes.
2161 ghuddy 490
                        string[] sar = ea_req.StereotypeEx.Split(",".ToCharArray());
2167 ghuddy 491
 
492
                        // if we didnt get a requirement type from the ReqPro database, set it to an empty string so that it can
493
                        // be compared to the EA stereotype strings.
494
                        if (rq_obj.type == null)
495
                           rq_obj.type = "";
496
 
2161 ghuddy 497
                        if (sar.Length > 0)
2155 ghuddy 498
                        {
2161 ghuddy 499
                           // The first item in the stereotype list is the one on display in the EA element properties and so is the one the user
500
                           // thinks is assigned to the requirement element, so check against that for changes
501
                           string sar0 = sar[0].Trim();
502
 
503
                           if (!sar0.Equals(rq_obj.type))
504
                           {
2173 ghuddy 505
                              gChangeLog.Notes += ea_req.ElementGUID + ":" + Constants.CHG_LOG_REQ_TYPE + ":" + sar0 + ":" + rq_obj.type + "\r\n";
506
                              gChangeLog.Update();
2161 ghuddy 507
                              statusMayHaveChanged = true;
508
                              ea_req.StereotypeEx = rq_obj.type;
509
                              ea_req.Stereotype = rq_obj.type;
510
                           }
511
                        }
512
                        else if (!ea_req.Stereotype.Equals(rq_obj.type))
513
                        {
2173 ghuddy 514
                           gChangeLog.Notes += ea_req.ElementGUID + ":" + Constants.CHG_LOG_REQ_TYPE + ":" + ea_req.Stereotype + ":" + rq_obj.type + "\r\n";
515
                           gChangeLog.Update();
2155 ghuddy 516
                           statusMayHaveChanged = true;
2157 ghuddy 517
                           ea_req.StereotypeEx = rq_obj.type;
518
                           ea_req.Stereotype = rq_obj.type;
2155 ghuddy 519
                        }
520
 
521
                        ea_req.Update();
522
 
523
                        if (meaningMayHaveChanged)
524
                        {
2173 ghuddy 525
                           gModifiedRequirementCount++;
2155 ghuddy 526
                        }
2173 ghuddy 527
 
2155 ghuddy 528
                        if (statusMayHaveChanged)
529
                        {
2173 ghuddy 530
                           gStatusUpdatedRequirementCount++;
2155 ghuddy 531
                        }
532
 
533
                        totalRequirements++;
2151 ghuddy 534
                     }
535
                  }
536
                  else
537
                  {
2173 ghuddy 538
                     // update orphanage detection data
539
                     rq_obj.matched = true;
540
 
2151 ghuddy 541
                     totalRequirements++;
542
 
543
                     // This ReqPro requirement does not have a counterpart in EA, so we must create
544
                     // a new one.
2173 ghuddy 545
                     gNewRequirementCount++;
2151 ghuddy 546
 
547
                     // create the new EA requirement in the import package
2167 ghuddy 548
                     EA.Element ea_req = (EA.Element)gChangeHistoryPackage.Elements.AddNew( rq_obj.tag + " " + rq_obj.name, "Requirement");
2151 ghuddy 549
 
550
                     rq_obj.ea_element_ID = ea_req.ElementID;
551
 
2155 ghuddy 552
                     CopyReqProDatabase.copyReq(ea_req, rq_obj);
2151 ghuddy 553
 
2155 ghuddy 554
                     ea_req.Notes = rq_obj.text;
555
 
2151 ghuddy 556
                     ea_req.Update();
557
 
2167 ghuddy 558
                     // add the new requirement to our list for later processing
2173 ghuddy 559
                     gReq_lists.new_ea_reqs.Add(ea_req);
560
                     gReq_lists.new_ea_GUIDs.Add(rq_obj.guid);
2167 ghuddy 561
 
2173 ghuddy 562
                     gChangeLog.Notes += ea_req.ElementGUID + ":Created:" + ea_req.Name + "\r\n";
563
                     gChangeLog.Update();
2151 ghuddy 564
 
2155 ghuddy 565
                     Main.WriteOutput("Created: " + ea_req.Name, ea_req.ElementID);
2151 ghuddy 566
                  }
2173 ghuddy 567
 
2151 ghuddy 568
               }
569
               catch (Exception ex)
570
               {
2155 ghuddy 571
                  Main.WriteOutput("Exception (ImportFromReqPro), " + ex.Message + ", " + rq_obj.name, -1);
2151 ghuddy 572
               }
573
            }
574
 
575
            if (Main.mustAbort)
576
               return;
577
 
2155 ghuddy 578
            Main.WriteOutput("Checking for orphaned requirements", -1);
2167 ghuddy 579
 
2173 ghuddy 580
            // Now do initial check for orphaned EA requirements
581
            for (int i = 0; i < gReq_lists.ea_GUIDs.Count; i++)
2151 ghuddy 582
            {
583
               if (Main.mustAbort)
584
                  break;
585
 
2173 ghuddy 586
               string rq_GUID = (string)gReq_lists.ea_GUIDs[i];
2151 ghuddy 587
               if (rq_GUID != "")
588
               {
589
                  if ((bool)ea_req_matched[i] == false)
590
                  {
2173 ghuddy 591
                     EA.Element ea_req = (EA.Element)gReq_lists.ea_reqs[i];
2151 ghuddy 592
 
2173 ghuddy 593
                     add_to_orphan_list(ref ea_req);
2151 ghuddy 594
                  }
595
               }
596
            }
597
 
2173 ghuddy 598
            // Now we import the ReqPro database package structure and migrate all of our existing or
2167 ghuddy 599
            // new requirements into it. We only create the structure we need, ie. empty package structure
600
            // will not be created unecessarily.
601
            Main.WriteOutput("Importing latest ReqPro database package structure", -1);
602
            populate_latest_reqprodb_structure_package(rq_root_package);
603
            gNewReqProDBPackage.Packages.Refresh();
604
            gNewReqProDBPackage.Elements.Refresh();
605
            gNewReqProDBPackage.Diagrams.Refresh();
2151 ghuddy 606
            Main.EA_Repository.RefreshModelView(parentPackage.PackageID);
607
 
2167 ghuddy 608
            if (Main.mustAbort)
609
               return;
610
 
2173 ghuddy 611
            // If there is any change to report, ask user if they want to see it now, and if so, display it
612
            if (gChangeLog.Notes != null && gChangeLog.Notes.Length > 0)
613
            {
614
               dlgres = MessageBoxEx.Show("Display Change Log?", "Change Log", MessageBoxButtons.YesNo);
615
               if (dlgres == DialogResult.Yes)
616
                  displayChangeLog(gChangeLog);
617
            }
618
 
619
            if (Main.mustAbort)
620
               return;
621
 
622
 
623
            // Take care of orphaned packages that have been orphaned due to a reduction in the scope of import.
624
            //Main.WriteOutput("Re-locating orphaned requirements (if any)", -1);
625
            //foreach (EA.Element ea_req_orphaned in ea_reqs_orphaned)
626
            //{
627
            //   ea_req_orphaned.PackageID = gOrphansPackage.PackageID;
628
            //   ea_req_orphaned.Update();
629
            //}
630
 
2167 ghuddy 631
            // Remove the old superseded facsimile of the ReqPro database package structure. At this point,
632
            // orphaned requirements left in these will be moved to the Orphaned package, before the old
633
            // structure package is removed.
634
            Main.WriteOutput("Removing old ReqPro database package structures", -1);
635
            remove_old_empty_structures(parentPackage, gNewReqProDBPackage);
636
 
637
            if (Main.mustAbort)
638
               return;
639
 
640
            // Remove other empty packages - this tidies up the ReqPro import area so that at the top level
641
            // all a user should see is the Change History package, ReqProDB package, and possibly an Orphans package.
642
            Main.WriteOutput("Pruning empty packages", -1);
643
 
644
            prune_empty_packages(parentPackage);
645
 
646
            // Refresh the project browser
647
            Main.EA_Repository.RefreshModelView(parentPackage.PackageID);
648
 
2149 ghuddy 649
            // Setup the internal requirement to requirement connectivity. This is seperate from the browser
650
            // organisation of elements in EA, but since in ReqPro, that organisation tells part of the story
651
            // of requirement to requirement connectivity, it is mirrored in the internal connectivity, along
652
            // with explicit trace relationships setup in ReqPro.
653
            // The purpose of this internal connectivity is to support relationship matrix tables in documentation
654
            // generated by EA_DocGen, or to support diagrammatic representations of the requirements in EA,
655
            // where the connectivity will become apparent through links ajoining the requirement elements in the
656
            // diagram.
2151 ghuddy 657
            write_traces(totalRequirements);
2141 ghuddy 658
 
2151 ghuddy 659
            if (Main.mustAbort)
660
               return;
2141 ghuddy 661
 
2167 ghuddy 662
            // Output any messages the underlying parser may have collected as a result of observations it has made
663
            // regarding the data it has read from the ReqPro database.
2155 ghuddy 664
            writeDelayedMessages();
2173 ghuddy 665
 
2151 ghuddy 666
            // display summary stats
2173 ghuddy 667
            Main.WriteOutput(gNewRequirementCount.ToString() + " new requirements", -1);
668
            Main.WriteOutput(gModifiedRequirementCount.ToString() + " requirements modified", -1);
669
            Main.WriteOutput(gStatusUpdatedRequirementCount.ToString() + " requirements had status changes", -1);
670
            Main.WriteOutput(gOrphanedCount.ToString() + " requirements were orphaned", -1);
2151 ghuddy 671
 
2155 ghuddy 672
            Main.WriteOutput("Import Completed", -1);
673
            MessageBoxEx.Show("Import Completed");
2173 ghuddy 674
 
2151 ghuddy 675
         }
676
         catch (Exception ex)
677
         {
2153 ghuddy 678
            Main.MessageBoxException(ex, "Exception (ImportFromReqPro)");
2151 ghuddy 679
         }
680
      }
681
 
2173 ghuddy 682
      private string updated_property_value_if_changed(EA.Element changeLog,
683
         EA.Element ea_req,
684
         string dest_value,
685
         string changeLogName,
2155 ghuddy 686
         string source_value,
687
         ref bool mayHaveChanged)
688
      {
689
         if (dest_value.CompareTo(source_value) != 0 )
690
         {
691
            changeLog.Notes += ea_req.ElementGUID + ":" + changeLogName+ ":" + NO_COLONS(dest_value) + ":" + NO_COLONS(source_value) + "\r\n";
692
            changeLog.Update();
693
            mayHaveChanged = true;
694
            return source_value;
695
         }
696
         return dest_value;
697
      }
2151 ghuddy 698
 
2167 ghuddy 699
 
2173 ghuddy 700
      private void if_tagged_value_changed_update_it(EA.Element changeLog,
701
         EA.Element ea_req,
702
         string tagname,
703
         string changeLogName,
2155 ghuddy 704
         string source_value,
705
         ref bool statusMayHaveChanged)
706
      {
707
         string value = EA_TaggedValues.Read(ea_req, tagname, "");
708
         if ((source_value != null) && (false == source_value.Equals(value)))
709
         {
710
            changeLog.Notes += ea_req.ElementGUID + ":" + changeLogName + ":" + value + ":" + source_value + "\r\n";
711
            changeLog.Update();
712
            EA_TaggedValues.Write(ea_req, tagname, source_value);
713
            statusMayHaveChanged = true;
714
         }
715
      }
2151 ghuddy 716
 
717
 
2155 ghuddy 718
 
2141 ghuddy 719
      /// <summary>
2173 ghuddy 720
      /// This method (along with its sibling overload) obtains a flattened view of the
2141 ghuddy 721
      /// hierarchical requirements obtained from the ReqPro database. This accumulation
722
      /// takes account of the users filtering requests.
723
      /// </summary>
724
      /// <param name="ea_repository"></param>
2151 ghuddy 725
      private void get_rq_req_collection(ref ArrayList rq_req_collection)
2141 ghuddy 726
      {
727
         foreach( ReqPro_object sub_obj in rq_root_package.ReqPro_objects )
728
         {
2151 ghuddy 729
            get_rq_req_collection(ref rq_req_collection, sub_obj);
2141 ghuddy 730
         }
731
      }
732
 
2167 ghuddy 733
 
2151 ghuddy 734
      private void get_rq_req_collection(ref ArrayList rq_req_collection,
2141 ghuddy 735
                                         ReqPro_object rq_obj )
736
      {
737
         if (rq_obj.isPackage)
738
         {
2147 ghuddy 739
            // if the package is not filtered, or if we are allowed to dig beneath filtered
740
            // packages...
741
            if (rq_obj.filtered == false || base.allowPackageStructureFragments)
2141 ghuddy 742
            {
743
               // Using recursion, scan this objects sub-objects
744
               foreach( ReqPro_object sub_obj in rq_obj.ReqPro_objects )
745
               {
2147 ghuddy 746
                  // if the sub-object is a package, always recurse to process it, else
747
                  // if the sub-object is a requirement, only recurse if the containing package
748
                  // is not filtered, so that requirements of filtered packages are themselves
749
                  // filtered out by virtue of their parent packages filtering state.
750
                  if (  sub_obj.isPackage
751
                     || (sub_obj.isRequirement && rq_obj.filtered == false))
752
                  {
2151 ghuddy 753
                     get_rq_req_collection(ref rq_req_collection, sub_obj);
2147 ghuddy 754
                  }
2141 ghuddy 755
               }
756
            }
757
         }
758
         else if (rq_obj.isRequirement)
759
         {
760
            if ( ! (reqTypeIsFiltered(rq_obj) || reqStatusTypeIsFiltered(rq_obj)) )
761
            {
762
               // Add this requirement to the flattened list we are accumulating
763
               rq_req_collection.Add(rq_obj);
764
 
2149 ghuddy 765
               // In ReqPro, a requirement can be related to another requirement in several ways:
2173 ghuddy 766
               // 1. By virtue of its position relative to another in the browser display. That is,
767
               //    if you place a requirement beneath a parent requirement, you are establishing a
2149 ghuddy 768
               //    parent-child relationship.
769
               // 2. By virtue of a specific TraceTo relationship being made via the Traceability menu
2173 ghuddy 770
               //    option.
2149 ghuddy 771
               // Interestingly, ReqPro prevents you creating a relationship of one of the above types,
772
               // if a relationship of the other type already exists. This implies that the relationship
773
               // between a parent and child requirement must be singular and is important regardless
774
               // of the manner in which it was created or represented.
775
               // The CopyReqProDatabaseToMemory base class will already have taken care of recording
776
               // relationships detected from ReqPro made using method 2 above. What we need to do here is
777
               // take care of those apparent from the browser based hierarchical organisation (ie. made
778
               // in ReqPro using method 1).
2173 ghuddy 779
               // All we need to do is grab the parent object (if any) and add the GUID of the child to
2149 ghuddy 780
               // its list of trace-to's. Later on, the write_traces() class method will turn these into
781
               // EA based connection objects that belong to the parent requirement elements.
782
               if (rq_obj.parent != null)
783
               {
784
                  rq_obj.parent.ReqPro_traces.Add(rq_obj.guid);
785
               }
786
 
2147 ghuddy 787
               // Using recursion, scan this objects sub-objects, which in practise will all
2173 ghuddy 788
               // be requirement objects. At this time requirement objects cannot have packages
2147 ghuddy 789
               // as children.
2141 ghuddy 790
               foreach( ReqPro_object sub_obj in rq_obj.ReqPro_objects )
791
               {
2151 ghuddy 792
                  get_rq_req_collection(ref rq_req_collection, sub_obj);
2141 ghuddy 793
               }
794
            }
795
         }
796
      }
797
 
798
 
2167 ghuddy 799
 
800
 
801
 
802
 
803
      /// <summary>
2173 ghuddy 804
      /// Populates a ReqProDB structure package to be used as a home for the requirements within the
2167 ghuddy 805
      /// overall import container, and re-locate requirements into it from wherever they may be elsewhere
806
      /// within and under the import container.
807
      /// </summary>
808
      /// <param name="rq_obj"></param>
809
      private void populate_latest_reqprodb_structure_package(ReqPro_object rq_obj)
810
      {
811
         foreach( ReqPro_object sub_obj in rq_obj.ReqPro_objects )
812
         {
813
            if (Main.mustAbort)
814
               return;
815
 
816
            if (sub_obj.isPackage)
817
            {
818
               populate_latest_reqprodb_structure_package(sub_obj);   // recurse
819
            }
820
            else if (sub_obj.isRequirement)
821
            {
822
               EA.Element ea_req = null;
823
 
824
               // Examine all of our requirement lists to try and re-locate the requirements from
825
               // the old structure(s) to the new one.
826
 
827
               // re-locate existing requirements updated during this import
828
               int i_ea_req;
2173 ghuddy 829
               i_ea_req = gReq_lists.ea_GUIDs.IndexOf( sub_obj.guid );
2167 ghuddy 830
               if (0 <= i_ea_req)
831
               {
2173 ghuddy 832
                  ea_req = ((EA.Element)gReq_lists.ea_reqs[i_ea_req]);
2167 ghuddy 833
 
834
                  EA.Package pkg = get_or_create_latest_structure(sub_obj);
835
 
2173 ghuddy 836
                  if (sub_obj.matched == false)
837
                  {
838
                     add_to_orphan_list(ref ea_req);
839
 
840
                     ea_req.PackageID = gOrphansPackage.PackageID;   // re-locate
841
                     ea_req.Update();
842
                  }
843
                  else if (sub_obj.filtered == false)
844
                  {
845
                     ea_req.PackageID = pkg.PackageID;   // re-locate
846
                     ea_req.TreePos = sub_obj.treePos;
847
                     ea_req.Update();
848
                  }
849
                  else
850
                  {
851
                     // QUESTION: So what if it is filtered? What happens to it then?
852
                     // Will it stay in the same place or be relocated as an orphan?
853
                     // ANSWER: relocate_elements_to_orphans_package() does this, called later
854
                     // in the import sequence.
855
                  }
2167 ghuddy 856
               }
857
               else
858
               {
859
                  // re-locate new requirements that have come in for the first time on this import.
2173 ghuddy 860
                  i_ea_req = gReq_lists.new_ea_GUIDs.IndexOf( sub_obj.guid );
2167 ghuddy 861
                  if (0 <= i_ea_req)
862
                  {
2173 ghuddy 863
                     ea_req = ((EA.Element)gReq_lists.new_ea_reqs[i_ea_req]);
2167 ghuddy 864
 
865
                     EA.Package pkg = get_or_create_latest_structure(sub_obj);
2173 ghuddy 866
 
2167 ghuddy 867
                     ea_req.PackageID = pkg.PackageID;   // re-locate
868
                     ea_req.TreePos = sub_obj.treePos;
869
                     ea_req.Update();
870
                  }
871
               }
872
 
873
               // Re-locate requirement under its parent requirement, if such a relationship exists.
874
               if (ea_req != null && sub_obj.parent.isRequirement)
875
               {
2173 ghuddy 876
                  // Only do this if the parent requirement has not been orphaned or filtered out of the import
2171 ghuddy 877
                  if (sub_obj.parent.ea_element_ID != -1)
2167 ghuddy 878
                  {
2171 ghuddy 879
                     EA.Element parent_ea_req = Main.EA_Repository.GetElementByID(sub_obj.parent.ea_element_ID);
880
                     if (parent_ea_req != null)
881
                     {
2173 ghuddy 882
                        // make sure we only assign ele-to-ele relationship if both elements are in the same
883
                        // package
884
                        if (ea_req.PackageID == parent_ea_req.PackageID)
885
                        {
886
                           ea_req.ParentID = parent_ea_req.ElementID;   // re-locate
887
                           ea_req.TreePos = sub_obj.treePos;
888
                           ea_req.Update();
889
                        }
2171 ghuddy 890
                     }
2167 ghuddy 891
                  }
2171 ghuddy 892
                  else
893
                  {
894
                     // TODO: what if the parent requirement has been orphaned, but the child as represented by
895
                     // the current value of sub_obj has not been? Will that have already been taken care of by
896
                     // the code earlier in this function that re-locates existing requirements to the correct
897
                     // parent package?
898
                  }
2167 ghuddy 899
               }
900
 
901
               populate_latest_reqprodb_structure_package(sub_obj);   // recurse
902
            }
903
         }
904
      }
905
 
906
 
907
      /// <summary>
908
      /// This is a helper for the populate_latest_reqprodb_structure_package() function. It allows on-the-fly
2173 ghuddy 909
      /// EA package path construction, triggered whenever we find we have a requirement to
2167 ghuddy 910
      /// re-locate into the latest facsimile of the ReqPro database structure.
911
      /// </summary>
912
      /// <param name="rq_obj"></param>
913
      /// <returns></returns>
914
      private EA.Package get_or_create_latest_structure(ReqPro_object rq_obj)
915
      {
916
         // go up the tree to find the immediate enclosing package of the requirement represented
917
         // by the input parameter. We do this because it is certain that this function will be called
918
         // initially passing a ReqPro_object that has "isRequirement" set to true. The requirement object
919
         // may also be nested within another requirement object, as a result of its parent-child hierarchy
920
         // in ReqPro.
921
         while(rq_obj.isRequirement && rq_obj.parent != null)
922
         {
923
            rq_obj = rq_obj.parent;
924
         }
925
 
926
         // Now that we have reached a package, we can figure out if we need to create its facsimile in EA
927
         // or detect if that has already been done on a previous invocation.
928
         if (rq_obj.isPackage)
929
         {
930
            // if this package has already been related to an EA package, then simply return it. The EA package
931
            // must have been created ona  previous invocation of this function.
932
            if (rq_obj.ea_element_ID != -1)
933
            {
934
               return Main.EA_Repository.GetPackageByID(rq_obj.ea_element_ID);
935
            }
936
            else // need to create this package, and if necessary, its parental line right up to the root package
937
            {
938
               // use recursion to work our way up the package ancestral line until we hit a point where
939
               // we find an EA package, then unwind, creating the sub-packages down to where our requirement
940
               // is to be held.
941
               EA.Package pkg = get_or_create_latest_structure(rq_obj.parent);   // recurse
942
               if (pkg != null)
943
               {
944
                  if (rq_obj.filtered)
945
                  {
946
                     return pkg;
947
                  }
948
                  else
949
                  {
2169 ghuddy 950
                     EA.Package sub_pkg = EA_Package.create(pkg, rq_obj.name, rq_obj.treePos);
2167 ghuddy 951
 
952
                     // attach the EA package to the ReqPro_object so that we do not attempt to create this
953
                     // package again on another call into this function.
954
                     rq_obj.ea_element_ID = sub_pkg.PackageID;
955
 
956
                     return sub_pkg;
957
                  }
958
               }
959
            }
960
         }
961
 
962
         // default to returning the root level package in EA where the requirement structure begins.
963
         // This will always be valid and available, but hopefully, the execution path wont drop down
964
         // to here.
965
         return Main.EA_Repository.GetPackageByID(rq_root_package.ea_element_ID);
966
      }
967
 
968
      /// <summary>
2173 ghuddy 969
      /// Remove the old ReqProDB structure packages if they are now empty of requirements. IF some
2167 ghuddy 970
      /// requirements remain in them, they are moved to the orphaned package so that the old ReqProDB
971
      /// packages can be removed.
972
      /// </summary>
973
      /// <param name="parentPackage"></param>
974
      /// <param name="new_structure_pkg"></param>
975
      private void remove_old_empty_structures(EA.Package parentPackage, EA.Package new_structure_pkg)
976
      {
977
         // NOTE: The parentPackage is the container of the ReqProDB element
978
         short i;
979
         for(i=0; i<parentPackage.Packages.Count; i++)
980
         {
981
            gCurrentPackage = (EA.Package)parentPackage.Packages.GetAt(i);
982
 
983
            // dont do anything to the new structure package that has been created on the current import cycle.
984
            if (new_structure_pkg != null && gCurrentPackage.PackageID == new_structure_pkg.PackageID)
985
            {
986
               continue;
987
            }
988
 
989
            // skip any packages that are not ReqProDB structure packages
990
            if (!gCurrentPackage.Name.StartsWith("ReqProDB"))
991
            {
992
               continue;
993
            }
994
 
995
            // re-locate all elements to the orphans package
996
            relocate_elements_to_orphans_package(gCurrentPackage);
997
 
998
            // Now delete the old ReqProDB structure package
999
            parentPackage.Packages.DeleteAt(i, false);
1000
         }
2173 ghuddy 1001
 
2167 ghuddy 1002
         parentPackage.Packages.Refresh();
1003
         Main.EA_Repository.RefreshModelView(parentPackage.PackageID);
1004
      }
1005
 
1006
 
1007
      /// <summary>
2173 ghuddy 1008
      /// Re-locate all requirements that remain under a ReqProDB structure package, to its
2167 ghuddy 1009
      /// top level, so that later on, the package hierarchy within it can be removed.
1010
      /// </summary>
1011
      /// <param name="parentPackage"></param>
1012
      private void relocate_elements_to_orphans_package(EA.Package parentPackage)
1013
      {
1014
         if (parentPackage.PackageID != gOrphansPackage.PackageID)
1015
         {
1016
            // relocate elements and diagrams to the top level of the orphans package
1017
            foreach(EA.Element ele in parentPackage.Elements)
1018
            {
1019
               ele.PackageID = gOrphansPackage.PackageID;
1020
               ele.Update();
1021
            }
1022
            foreach(EA.Diagram diag in parentPackage.Diagrams)
1023
            {
1024
               diag.PackageID = gOrphansPackage.PackageID;
1025
               diag.Update();
1026
            }
1027
 
1028
            // now parse lower level packages in the tree
1029
            foreach(EA.Package sub_pkg in parentPackage.Packages)
1030
            {
1031
               relocate_elements_to_orphans_package(sub_pkg);  // recurse
1032
            }
1033
         }
1034
      }
1035
 
1036
 
1037
      /// <summary>
1038
      /// This function migrates the older form of import package and its change log file into the newer
1039
      /// Change History package, and deletes the old import package. In doing this, it will move any
1040
      /// requirements still remaining in the import package to the top level of the new ReqProDB structure
1041
      /// package.
1042
      /// </summary>
1043
      /// <param name="parentPackage"></param>
1044
      private void migrate_old_import_packages_to_change_history_package(EA.Package parentPackage)
1045
      {
1046
         if (gNewReqProDBPackage != null && gChangeHistoryPackage != null)
1047
         {
1048
            bool found = false;
1049
            short i;
1050
            for(i=0; i<parentPackage.Packages.Count; i++)
1051
            {
1052
               EA.Package sub_pkg = (EA.Package)parentPackage.Packages.GetAt(i);
1053
 
1054
               if (sub_pkg.Name.StartsWith("import"))
1055
               {
1056
                  if (!found)
1057
                  {
1058
                     found = true;
1059
                     Main.WriteOutput("Migrating old import package contents to Change History and ReqProDB packages", -1);
1060
                  }
1061
 
1062
                  // re-locate all elements from the old import package to the new ReqProDB structure package.
1063
                  migrate_old_import_packages_to_change_history_package_recurser(sub_pkg);
1064
 
1065
                  // delete the old import package
1066
                  parentPackage.Packages.DeleteAt(i, false);
1067
               }
1068
            }
1069
            parentPackage.Packages.Refresh();
1070
            Main.EA_Repository.RefreshModelView(parentPackage.PackageID);
1071
         }
1072
      }
1073
 
1074
      /// <summary>
1075
      /// Moves all elements out of an old-style import package, and into the new ReqProDB structure package.
2173 ghuddy 1076
      /// Change Log elements are handled in a special way such that they are renamed from plain "Change Log"
2167 ghuddy 1077
      /// to the new style "Change Log - import <date> <time>" format, and are moved into the new "Change History"
1078
      /// package.
1079
      /// </summary>
1080
      /// <param name="parentPackage"></param>
1081
      private void migrate_old_import_packages_to_change_history_package_recurser(EA.Package parentPackage)
1082
      {
1083
         foreach(EA.Element ele in parentPackage.Elements)
1084
         {
1085
            if (ele.Name.StartsWith("Change Log"))
1086
            {
1087
               ele.Name = ele.Name + " - " + parentPackage.Name;
1088
               ele.PackageID = gChangeHistoryPackage.PackageID;
1089
               ele.Update();
1090
               gChangeHistoryPackage.Elements.Refresh();
1091
            }
1092
            else
1093
            {
1094
               ele.PackageID = gNewReqProDBPackage.PackageID;
1095
               ele.Update();
1096
            }
1097
         }
1098
 
1099
         foreach(EA.Diagram diag in parentPackage.Diagrams)
1100
         {
1101
            diag.PackageID = gNewReqProDBPackage.PackageID;
1102
            diag.Update();
1103
         }
1104
 
1105
         foreach(EA.Package sub_pkg in parentPackage.Packages)
1106
         {
1107
            migrate_old_import_packages_to_change_history_package_recurser(sub_pkg);   // recurse
1108
         }
1109
      }
1110
 
1111
 
1112
      private EA.Package find_or_create_change_history_package(EA.Package parentPackage)
1113
      {
1114
         foreach(EA.Package sub_pkg in parentPackage.Packages)
1115
         {
1116
            if (sub_pkg.Name.StartsWith("Change History"))
1117
            {
1118
               return sub_pkg;
1119
            }
1120
         }
2169 ghuddy 1121
         EA.Package pkg = EA_Package.create(parentPackage, "Change History", 1);
2167 ghuddy 1122
         return pkg;
1123
      }
1124
 
1125
      private EA.Package find_or_create_orphans_package(EA.Package parentPackage)
1126
      {
1127
         foreach(EA.Package sub_pkg in parentPackage.Packages)
1128
         {
1129
            if (sub_pkg.Name.StartsWith("Orphaned Requirements"))
1130
            {
1131
               return sub_pkg;
1132
            }
1133
         }
2169 ghuddy 1134
         EA.Package pkg = EA_Package.create(parentPackage, "Orphaned Requirements", 1);
2167 ghuddy 1135
         return pkg;
1136
      }
1137
 
1138
 
1139
      /// <summary>
2173 ghuddy 1140
      /// This function removes any empty packages it can find in the ReqPro import area. This is
2167 ghuddy 1141
      /// a tidying up operation.
1142
      /// </summary>
1143
      /// <param name="parentPackage"></param>
1144
      /// <returns></returns>
1145
      private bool prune_empty_packages(EA.Package parentPackage)
1146
      {
1147
         bool retVal = false;
1148
         bool needRefresh = false;
1149
         short i;
1150
         for(i=0; i<parentPackage.Packages.Count; i++)
1151
         {
1152
            EA.Package sub_pkg = (EA.Package)parentPackage.Packages.GetAt(i);
1153
 
1154
            if (true == prune_empty_packages(sub_pkg))   // recurse
1155
            {
1156
               parentPackage.Packages.DeleteAt(i, false);
1157
               needRefresh = true;
1158
            }
1159
         }
1160
 
1161
         if (needRefresh)
1162
         {
1163
            parentPackage.Packages.Refresh();
1164
         }
1165
 
2173 ghuddy 1166
         if (parentPackage.Packages.Count == 0
2167 ghuddy 1167
            && parentPackage.Elements.Count == 0
1168
            && parentPackage.Diagrams.Count == 0)
1169
         {
1170
            retVal = true;
1171
         }
1172
 
1173
         return retVal;
1174
      }
2173 ghuddy 1175
 
1176
      private void add_to_orphan_list(ref EA.Element ea_req)
1177
      {
1178
         if (!gReq_lists.orphaned_ea_reqs.Contains(ea_req.ElementID))
1179
         {
1180
            gReq_lists.orphaned_ea_reqs.Add(ea_req.ElementID);
1181
 
1182
            gOrphanedCount++;
1183
            gChangeLog.Notes += ea_req.ElementGUID + ":Orphaned:" + ea_req.Name + "\r\n";
1184
            gChangeLog.Update();
1185
         }
1186
      }
1187
 
2141 ghuddy 1188
	}
2173 ghuddy 1189
 
1190
 
2141 ghuddy 1191
}