Subversion Repositories DevTools

Rev

Rev 2163 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2155 ghuddy 1
using System;
2
using System.Text;
3
using System.Globalization;
4
using System.Collections;
5
using System.Windows.Forms;
6
using ReqPro40;
7
 
8
namespace EA_ReqPro
9
{
10
	/// <summary>
11
   /// ExportToReqProDatabase is a specialisation of CopyReqProDatabaseToMemory, designed to copy the 
12
   /// ReqPro database content into memory, and allow a user to select certain aspects to control a
13
   /// subsequent export operation.
14
	/// </summary>
15
	public class ExportToReqProDatabase : CopyReqProDatabaseToMemory
16
	{
17
      private ReqPro_object m_SelectedObject;
18
      private bool m_CreateFolder;
19
      private string m_FolderName;
20
      private string m_ReqType;
21
      private ExportForm.ExportExtent m_ExportExtent;
22
 
23
      private static char [] numbers = "0123456789".ToCharArray();
24
      private static char [] letters = "abcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXY".ToCharArray();
25
 
26
		public ExportToReqProDatabase()
27
		{
28
		}
29
 
30
 
31
      /// <summary>
32
      /// Method to parse a ReqPro database using the information in a ReqProDB artifact,
33
      /// assumed to be selected in EA's project browser prior to the method call.
34
      /// </summary>
35
      /// <param name="ea_repository"></param>
36
      /// <returns></returns>
37
      public override bool prompt_and_parse(ReqProDB_Artifact.MODE mode, out bool cancelled)
38
      {
39
         cancelled = false;
40
 
41
         try
42
         {
43
            base.structure_only = true;
44
 
45
            string exportDateTime = System.DateTime.Now.ToString();
46
 
47
            Main.WriteOutput("EA Requirement export at " + exportDateTime, -1 );
48
            Main.WriteOutput("", -1);
49
 
50
            if (true == base.prompt_and_parse(mode, out cancelled))
51
            {
52
               if (Main.mustAbort)
53
                  return false;
54
 
55
               Main.EA_Repository.EnsureOutputVisible(Main.GUI_OUTPUT_TAB_NAME);
56
 
57
               // Configure the ReqProDB artifact as a traceability artifact, but only if it appeared
58
               // as though it were created for the first time during the export, otherwise leave
59
               // it alone with its existing setting.
60
               if (RQ_Artifact.get_mode(RQ_Element) == ReqProDB_Artifact.MODE.UNDEFINED)
61
                  RQ_Artifact.set_traceability_mode(RQ_Element);
62
 
63
               ExportToReqPro(exportDateTime, out cancelled);
64
 
65
               return true;
66
            }
67
         }
68
         catch (Exception ex)
69
         {
70
            Main.MessageBoxException(ex, "Exception (parse)");
71
         }      
72
 
73
         return false;
74
      }
75
 
76
 
77
      /// <summary>
78
      /// Method called by the base class to convey the user selections made controlling the export
79
      /// operation.
80
      /// </summary>
81
      /// <param name="selectedObject"></param>
82
      /// <param name="createFolder"></param>
83
      /// <param name="folderName"></param>
84
      /// <param name="requirementType"></param>
85
      /// <param name="requirementStatus"></param>
86
      protected override void provideExportDecisionsToClient(ReqPro_object selectedObject,
87
         bool createFolder,
88
         string folderName,
89
         string requirementType,
90
         ExportForm.ExportExtent exportExtent)
91
      {
92
         m_SelectedObject = selectedObject;
93
         m_CreateFolder = createFolder;
94
         m_FolderName = folderName;
95
 
96
         // The requirement type display string in the export form is like "some requirement type(abbrev)"
97
         // We want just the abbrev so use string splitting to extract it.
98
         char [] delim = {'('};
99
         string [] tokens = requirementType.Split(delim, 2);
100
         delim[0] = ')';
101
         m_ReqType = tokens[1].Split(delim,2)[0];
102
 
103
         m_ExportExtent = exportExtent;
104
      }
105
 
106
 
2169 ghuddy 107
      /// <summary>
108
      /// Function to schedule and control the export sequence. Here is where the real work
109
      /// begins of exporting requirements and traceability from EA to RequisitePro.
110
      /// </summary>
111
      /// <param name="exportDateTime"></param>
112
      /// <param name="cancelled"></param>
2155 ghuddy 113
      private void ExportToReqPro(string exportDateTime, out bool cancelled)
114
      {
115
         cancelled = false;
116
 
117
         try
118
         {
119
            ArrayList ea_reqs;   // list of new requirements for export - assigned later from element accumulator
120
            ArrayList ea_mastered_reqs = new ArrayList();
121
            ArrayList ea_mastered_reqs_rp_guids = new ArrayList();
122
 
123
            // Read tag from ReqProDB element that enables/disables the capability to use EA as a master
124
            // repository for requirements originally created in EA. If the tag does not exist, EA mastering
125
            // will be allowed by default.
126
            bool EA_MasteringAllowed = EA_TaggedValues.Read(base.RQ_Element, Constants.TAG_EA_MASTERING_ALLOWED, Constants.DEFAULT_EA_MASTERING_ALLOWED);
127
 
128
            #region DETERMINE PARENT PACKAGE
129
            // Obtain the EA parent package so that we can scan it for existing requirement elements.
130
            EA.Package parentPackage;
131
            if (m_ExportExtent == ExportForm.ExportExtent.PACKAGE_REQS)
132
            {
2169 ghuddy 133
               parentPackage = EA_ProjectBrowser.get_selected_package();
2155 ghuddy 134
            }
135
            else 
136
            {
137
               // default to the ReqProDB container package. This is probably what most exports
138
               // will use.
139
               parentPackage = Main.EA_Repository.GetPackageByID( base.RQ_Element.PackageID );
140
            }
141
            #endregion
142
 
143
            #region GET_EXPORT_LIST
2157 ghuddy 144
            Main.WriteOutput("Acquiring list of requirement elements in EA", -1);
2155 ghuddy 145
 
146
            // setup the element types list to control the element accumulation
147
            ArrayList allowedElementTypes = new ArrayList();
148
            allowedElementTypes.Add("Requirement");
149
            //allowedElementTypes.Add("UseCase");
150
 
151
            if (m_ExportExtent != ExportForm.ExportExtent.SINGLE_REQ)
152
            {
153
               // create the element accumulator, and use it to find all the requirement
154
               // elements in the container package
2169 ghuddy 155
               EA_ElementAccumulator reqLister = new EA_ElementAccumulator(allowedElementTypes);
156
               EA_Parsing.findAndProcessPackageElementsInBrowserOrder( parentPackage, reqLister, true );
2155 ghuddy 157
 
158
               if (Main.mustAbort)
159
                  return;
160
 
2169 ghuddy 161
               // Sanity check the EA requirements
162
               Main.WriteOutput("Sanity checking requirement elements in EA", -1);
163
               if (false == sanity_check_requirements(reqLister.Elements))
164
               {
165
                  cancelled = true;
166
                  return;
167
               }
168
 
2155 ghuddy 169
               // Remove requirements from the accumulated list if they have already been linked
170
               // to ReqPro requirement elements, by virtue of them seeming to have a valid GUID
171
               // We dont actually validate the GUID, just check that one is present or not.
172
               ea_reqs = reqLister.Elements; 
173
               int i_ea_reqs;
174
               for (i_ea_reqs = 0; i_ea_reqs < ea_reqs.Count; ) // No index increment here
175
               {
176
                  EA.Element ea_req = (EA.Element)ea_reqs[i_ea_reqs];
177
 
178
                  string GUID = EA_TaggedValues.Read(ea_req, Constants.TAG_GUID);
179
                  if (GUID != null && GUID.Length > 0 && GUID.StartsWith("{"))
180
                  {
181
                     // found an EA requirement element that seems to already be linked to a 
182
                     // ReqPro requirement element
183
 
184
                     // if the element seems to be one that was mastered (created) in EA and exported
185
                     // to ReqPro on a previous export cycle, then collect it in a seperate list in case
186
                     // we need to do an update on ReqPro later on.
187
                     if (true == EA_TaggedValues.Read(ea_req, Constants.TAG_CREATED_IN_EA, Constants.DEFAULT_CREATED_IN_EA))
188
                     {
189
                        ea_mastered_reqs.Add(ea_req);
190
                        ea_mastered_reqs_rp_guids.Add(GUID);
191
                     }
192
 
193
                     // discard from the export list.
194
                     ea_reqs.RemoveAt(i_ea_reqs);
195
                     continue;
196
                  }
197
                  i_ea_reqs++;   // index increment here
198
               }
199
 
200
               if (Main.mustAbort)
201
                  return;
202
            }
203
            else // user wants to export a single selected requirement
204
            {
2169 ghuddy 205
               EA.Element ea_ele = EA_ProjectBrowser.get_selected_element(allowedElementTypes);
2155 ghuddy 206
               if (ea_ele == null)
207
               {
208
                  MessageBoxEx.Show(
209
                     "The export extent chosen (single requirement export)\n" +
210
                     "is not compatible with the item selected in the EA\n" +
211
                     "project browser. You must select a requirement object\n" +
212
                     "to use this export extent.",
213
                     "Error");
214
                  cancelled = true;
215
                  return;
216
               }
217
 
218
               string GUID = EA_TaggedValues.Read(ea_ele, Constants.TAG_GUID);
219
               if (GUID != null && GUID.Length > 0 && GUID.StartsWith("{"))
220
               {
221
                  MessageBoxEx.Show(
222
                     "The requirement object selected in the EA project browser,\n" +
223
                     "already appears to be associated with a ReqPro object.",
224
                     "Error");
225
                  cancelled = true;
226
                  return;
227
               }
228
 
229
               ea_reqs = new ArrayList();
230
               ea_reqs.Add(ea_ele);
2169 ghuddy 231
 
232
               // Sanity check the EA requirement
233
               Main.WriteOutput("Sanity checking requirement element in EA", -1);
234
               if (false == sanity_check_requirements(ea_reqs))
235
               {
236
                  cancelled = true;
237
                  return;
238
               }
2155 ghuddy 239
            }
240
            #endregion
241
 
242
            // Export newly mastered EA requirements to ReqPro
243
            if (false == export_new_EA_mastered_requirements(ref ea_reqs, ref ea_mastered_reqs, ref ea_mastered_reqs_rp_guids, out cancelled))
244
               return;
245
 
246
            // If the ReqProDB element informs us that EA mastering of requirements is allowed,
247
            // then we can process the update of any requirements in ReqPro that are linked to
248
            // requirements in EA, that seem to have originally been created in EA.
249
            if (EA_MasteringAllowed)
250
            {
251
               if (false == update_old_EA_mastered_requirements(ref ea_mastered_reqs, out cancelled))
252
                  return;
253
            }
254
 
255
            // Export/Update Requirement relationships
256
            export_new_EA_mastered_requirement_relationships(ref ea_reqs);
257
 
258
            if (EA_MasteringAllowed)
259
            {
260
               update_old_EA_mastered_requirement_relationships(ref ea_mastered_reqs);
261
            }
262
 
263
            Main.EA_Repository.RefreshModelView(parentPackage.PackageID);
264
 
265
            // Use historical data stored in the ReqProDB element to determine if any EA mastered requirements
266
            // have been deleted, leaving orphans in the ReqPro database that might need to be cleaned up
267
            report_orphaned_ReqPro_requirements(ref ea_mastered_reqs_rp_guids);
268
 
269
            Main.WriteOutput("Export Completed",-1);
270
            MessageBoxEx.Show("Export Completed");
271
         }
272
         catch (Exception ex)
273
         {
274
            Main.MessageBoxException(ex, "Exception (ExportToReqPro)");
275
         }
276
      }
277
 
2169 ghuddy 278
      /// <summary>
279
      /// sanity check a list of requirements to make sure they all meet ReqPro's constraints
280
      /// </summary>
281
      /// <param name="al"></param>
282
      /// <returns></returns>
283
      private bool sanity_check_requirements(ArrayList al)
284
      {
285
         int numBadRequirements = 0;
286
         foreach (EA.Element ele in al)
287
         {
288
            if (false == requirement_meets_reqpro_constraints(ele))
289
            {
290
               numBadRequirements++;
291
            }
2155 ghuddy 292
 
2169 ghuddy 293
            if (Main.mustAbort)
294
               return false;
295
         }
296
         if (numBadRequirements > 0)
297
         {
298
            MessageBoxEx.Show(
299
               "One or more EA requirement objects for export do not meet the constraints\n" +
300
               "imposed by RequisitePro - see EA_ReqPro output tab for the list of bad objects.",
301
               "Error");
302
            return false;
303
         }
304
         return true;
305
      }
306
 
307
 
2155 ghuddy 308
      /// <summary>
2169 ghuddy 309
      /// sanity check a requirement in EA to make sure it meets ReqPro's constraints
310
      /// and issue and message to the output tab if it does not.
311
      /// </summary>
312
      /// <param name="ele"></param>
313
      /// <returns></returns>
314
      private bool requirement_meets_reqpro_constraints(EA.Element ele)
315
      {
316
         string tag = null;
317
 
318
         if (ele.Name == null)
319
         {
320
            Main.WriteOutput("???", ele.ElementID);
321
            Main.WriteOutput("   Element has no name", ele.ElementID);
322
            return false;
323
         }
324
 
325
         string untagged_name = untaggedReqName(ele.Name, ref tag, false);
326
 
327
         if (untagged_name.Length > 128)
328
         {
329
            Main.WriteOutput(untagged_name, ele.ElementID);
330
            Main.WriteOutput(string.Format("   Element name exceeds 128 char limit - actual length is {0}", untagged_name.Length), ele.ElementID);
331
            return false;
332
         }
333
 
334
         if (untagged_name.IndexOfAny("\r\n".ToCharArray(), 0) >= 0)
335
         {
336
            Main.WriteOutput(untagged_name, ele.ElementID);
337
            Main.WriteOutput("   Element name contains carriage return or line feed", ele.ElementID);
338
            return false;
339
         }
340
 
341
         if (ele.Notes != null && ele.Notes.Length > 16000)
342
         {
343
            Main.WriteOutput(untagged_name, ele.ElementID);
344
            Main.WriteOutput(string.Format("   Element notes exceeds 16000 char limit - actual length is {0}", ele.Notes.Length), ele.ElementID);
345
            return false;
346
         }
347
 
348
         return true;   // requirement is good
349
      }
350
 
351
 
352
 
353
      /// <summary>
2155 ghuddy 354
      /// Exports newly EA mastered requirements to ReqPro
355
      /// </summary>
356
      /// <param name="ea_reqs"></param>
357
      /// <param name="ea_mastered_reqs"></param>
358
      /// <param name="ea_mastered_reqs_rp_guids"></param>
359
      /// <param name="cancelled"></param>
360
      /// <returns></returns>
361
      private bool export_new_EA_mastered_requirements(ref ArrayList ea_reqs, 
362
         ref ArrayList ea_mastered_reqs, 
363
         ref ArrayList ea_mastered_reqs_rp_guids, 
364
         out bool cancelled)
365
      {
366
         cancelled = false;
367
 
368
         // if there are any new requirements to export
369
         if (ea_reqs.Count > 0)
370
         {
371
            Main.WriteOutput(string.Format("Found {0} Requirements for export.", ea_reqs.Count), -1);
372
 
373
            ReqPro40.Requirements req_collection = ReqProDatabase.get_requirements();
374
            if (req_collection == null)
375
            {
376
               MessageBoxEx.Show("Could not acquire Requirement Collection\n" +
377
                  "from ReqPro database.\n", "Error");
378
               cancelled = true;
379
               return false;
380
            }
381
 
382
            ReqPro40.Package rp_pkg = null;
383
 
384
            // Obtain the ReqPro package selected by the user (if any)
385
            if (this.m_SelectedObject != null)
386
            {
387
               rp_pkg = ReqProDatabase.get_package(this.m_SelectedObject.iKey);
388
 
389
               if (this.m_CreateFolder)
390
               {
391
                  ReqPro40.Package rp_sub_pkg = ReqProDatabase.create_sub_package(rp_pkg, this.m_FolderName, "");
392
                  if (rp_sub_pkg != null)
393
                  {
394
                     rp_pkg = rp_sub_pkg;
395
                  }
396
               }
397
            }
398
 
399
            // process each requirement found in EA that needs exporting
400
            foreach(EA.Element ea_req in ea_reqs)
401
            {
402
               // get EA requirement without any temporary tag that the modeller may have given it
2157 ghuddy 403
               string tag = null;
404
               string ea_req_untagged_name = untaggedReqName(ea_req.Name, ref tag, false);
2155 ghuddy 405
 
406
               Main.WriteOutput("Exporting : " + ea_req.Name, ea_req.ElementID);
407
 
2169 ghuddy 408
               // If the EA requirement has a parent requirement, then in ReqPro we must organise it such 
409
               // that it has a parent-child hierarchical relationship
410
               ReqPro40.Requirement parent_rp_req = null;
411
               EA.Element parent_ea_req = null;
412
               if (ea_req.ParentID != 0)
413
               {
414
                  parent_ea_req = Main.EA_Repository.GetElementByID(ea_req.ParentID);
415
                  if (parent_ea_req != null)
416
                  {
417
                     // get GUID of ReqPro parent requirement
418
                     string parent_guid = EA_TaggedValues.Read(parent_ea_req, Constants.TAG_GUID);
419
                     if (parent_guid != null && parent_guid.Length > 0 && parent_guid.StartsWith("{"))
420
                     {
421
                        // Get the parent ReqPro requirement
422
                        parent_rp_req = ReqProDatabase.get_requirement_by_guid(parent_guid);
423
                     }
424
 
425
                     // Even though in EA, a parent-child relationship exists, we want to re-enforce that
426
                     // with a connection relationship too, so that when the parent and child exists on
427
                     // a diagram, they are shown linked together.
428
                     EA_Connectors.add(parent_ea_req, ea_req);
429
                  }
430
               }
431
 
432
 
2155 ghuddy 433
               // Add the requirement to ReqPro requirement collection
2169 ghuddy 434
               ReqPro40.Requirement rp_req = null;
435
 
436
               if (parent_rp_req != null)
437
                  rp_req = ReqProDatabase.add_requirement(req_collection, ea_req_untagged_name, ea_req.Notes, this.m_ReqType, parent_rp_req);
438
               else
439
                  rp_req = ReqProDatabase.add_requirement(req_collection, ea_req_untagged_name, ea_req.Notes, this.m_ReqType);
440
 
2155 ghuddy 441
               if (rp_req != null)
442
               {
443
                  // Get the tag for the new requirement from ReqPro and use it to form a new name for 
444
                  // the EA requirement. Note that at this point in time the tag has a pending form. It
445
                  // only becomes correct once we do a rq_req.Save() later on, so this update has to be
446
                  // repeated later. This first update is just to confirm that we can actually do an 
447
                  // update in EA, before we commit the changes to the ReqPro database.
448
                  string rp_req_tag = rp_req.get_Tag(ReqPro40.enumTagFormat.eTagFormat_FullTag);
449
 
450
                  ea_req.Name = rp_req_tag + " " + ea_req_untagged_name;
451
 
452
                  // Test that the EA requirement can be updated.
453
                  if (false == ea_req.Update())
454
                  {
455
                     MessageBoxEx.Show(
456
                        "Failed to update EA requirement element.\n" +
457
                        "Check that the EA model is writeable.\n" +
458
                        "Check that the EA model is not locked by another user.\n" +
459
                        "Check that the EA requirement element is not currently being edited.\n\n" +
460
                        "Cancelling export - please retry once checks have been performed.", "Error");
461
 
462
                     cancelled = true;
463
                     return false;
464
                  }
465
 
466
 
467
                  // Commit changes to ReqPro database
468
                  rp_req.Save();
469
 
2169 ghuddy 470
                  // Now locate the new requirement under the selected package in ReqPro, but we only need to do this if the
471
                  // requirement is a root level requirement that has no parent requirement.
472
                  if ((rp_pkg != null) && (parent_rp_req == null))
2155 ghuddy 473
                  {
474
                     rp_pkg.AddElement(rp_req, ReqPro40.enumPackageLookups.ePackageLookup_Object, ReqPro40.enumElementTypes.eElemType_Requirement);
475
                  }
476
 
477
 
478
 
479
                  // Now re-acquire the tag, which should no longer be in a pending form but have a real number
480
                  // assigned to it as a result of the commit we just did above.
481
                  rp_req_tag = rp_req.get_Tag(ReqPro40.enumTagFormat.eTagFormat_FullTag);
482
 
2157 ghuddy 483
                  // Attempt to set any attributes in the new ReqPro requirement. 
484
                  exportAttributes(rp_req, ea_req, rp_req_tag);
485
                  rp_req.Save();
486
 
2155 ghuddy 487
                  // Update the EA requirement for the second time, now with the correct and final tag
488
                  ea_req.Name = rp_req_tag + " " + ea_req_untagged_name;
489
                  ea_req.Update();
490
                  Main.WriteOutput("   (Re)Assigned Tag : " + ea_req.Name, ea_req.ElementID);
491
 
492
                  // Record the GUID and tag in EA tagged values. This will effectively bind the EA requirement
493
                  // to its new ReqPro requirement counterpart.
494
                  EA_TaggedValues.Write(ea_req, Constants.TAG_GUID, rp_req.GUID);
495
                  EA_TaggedValues.Write(ea_req, Constants.TAG_TAG, rp_req_tag);
496
 
497
                  // Save in the list of ReqPro GUIDs to support ReqPro orphaned requirement detection later on
498
                  ea_mastered_reqs_rp_guids.Add(rp_req.GUID);
499
 
500
                  // mark the requirement as having been created in EA.
501
                  EA_TaggedValues.Write(ea_req, Constants.TAG_CREATED_IN_EA, true);
502
 
503
                  // Update the ReqPro collection.
504
                  req_collection.Save();
505
               }
506
            }
507
 
508
            // Save details of the ReqPro package where the requirements were exported to. This info can be
509
            // used on the next export to auto-select the ReqPro destination package for the export, etc.
510
            if (rp_pkg != null)
511
            {
512
               EA_TaggedValues.Write(base.RQ_Element, Constants.TAG_LAST_EXPORT_GUID, rp_pkg.GUID);
513
               EA_TaggedValues.Write(base.RQ_Element, Constants.TAG_LAST_EXPORT_NAME, rp_pkg.Name);
514
            }
515
            else
516
            {
517
               // export occurred to the root package.
518
               EA_TaggedValues.Delete(base.RQ_Element, Constants.TAG_LAST_EXPORT_GUID);
519
               EA_TaggedValues.Delete(base.RQ_Element, Constants.TAG_LAST_EXPORT_NAME);
520
            }
521
         }
522
         else
523
         {
524
            Main.WriteOutput("Found no new requirements to add to ReqPro",-1);
525
         }
526
 
527
         Main.WriteSeperator();
528
         return true;
529
      }
530
 
531
 
532
      /// <summary>
533
      /// Updates ReqPro requirements that have masters in EA
534
      /// </summary>
535
      /// <param name="ea_mastered_reqs"></param>
536
      /// <param name="cancelled"></param>
537
      /// <returns></returns>
538
      private bool update_old_EA_mastered_requirements(ref ArrayList ea_mastered_reqs, 
539
         out bool cancelled)
540
      {
541
         cancelled = false;
542
 
543
         // if there are any EA mastered requirements...
544
         if (ea_mastered_reqs.Count > 0)
545
         {
546
            bool possibleOrphans = false;
547
 
548
            Main.WriteOutput(string.Format("Found {0} Requirements to update.", ea_mastered_reqs.Count), -1);
549
 
550
            ReqPro40.Requirements req_collection = ReqProDatabase.get_requirements();
551
 
552
            // process each EA mastered requirement
553
            int i_ea_mastered_reqs = 0;
554
            for (i_ea_mastered_reqs = 0; i_ea_mastered_reqs < ea_mastered_reqs.Count; ) // NOTE: no count increment done here
555
            {
556
               EA.Element ea_req = (EA.Element)ea_mastered_reqs[i_ea_mastered_reqs];
557
 
558
               // make sure there is a GUID
559
               string GUID = EA_TaggedValues.Read(ea_req, Constants.TAG_GUID);
560
               if (GUID != null && GUID.Length > 0 && GUID.StartsWith("{"))
561
               {
562
                  ReqPro40.Requirement rp_req;
563
 
564
                  // Try and find the requirement in ReqPro
565
                  rp_req = ReqProDatabase.get_requirement_by_guid(GUID);
566
                  if (rp_req != null)
567
                  {
568
                     // copy name and notes from EA to ReqPro
2157 ghuddy 569
                     string tag = null;
570
                     string ea_req_untagged_name = untaggedReqName(ea_req.Name, ref tag, true);
2155 ghuddy 571
 
572
                     // Test that the EA requirement can be updated.
573
                     ea_req.Name = ea_req_untagged_name;
574
                     ea_req.Update();
575
                     if (false == ea_req.Update())
576
                     {
577
                        MessageBoxEx.Show(
578
                           "Failed to update EA requirement element.\n" +
579
                           "Check that the EA model is writeable.\n" +
580
                           "Check that the EA model is not locked by another user.\n" +
581
                           "Check that the EA requirement element is not currently being edited.\n\n" +
582
                           "Cancelling export - please retry once checks have been performed.", "Error");
583
 
584
                        cancelled = true;
585
                        return false;
586
                     }
587
 
588
                     // copy content to the existing ReqPro requirement
589
                     rp_req.Name = ea_req_untagged_name;
590
                     rp_req.Text = ea_req.Notes;
591
 
2157 ghuddy 592
                     string rp_req_tag = rp_req.get_Tag(ReqPro40.enumTagFormat.eTagFormat_FullTag);
593
 
2155 ghuddy 594
                     // Attempt to set any attributes in the existing ReqPro requirement. 
2157 ghuddy 595
                     exportAttributes(rp_req, ea_req, rp_req_tag);
2155 ghuddy 596
 
597
                     // Commit changes to ReqPro database
598
                     rp_req.Save();
599
 
600
                     // Although we are allowing EA to be the master repository of requirements
601
                     // if they were originally created in EA, we still want to use ReqPro as the
602
                     // master for any numbering scheme (ie. tags), so update the EA requirements
603
                     // Tag as necessary.
604
                     ea_req.Name = rp_req_tag + " " + ea_req_untagged_name;
605
                     ea_req.Update();
606
                     EA_TaggedValues.Write(ea_req, Constants.TAG_TAG, rp_req_tag);
607
                     Main.WriteOutput("Updated : " + ea_req.Name, ea_req.ElementID);
608
                  }
609
                  else
610
                  {
611
                     possibleOrphans = true;
612
                     Main.WriteOutput("Warning, failed to find ReqPro requirement counterpart (possible orphan?)", ea_req.ElementID);
613
                  }
614
                  i_ea_mastered_reqs++;
615
               }
616
               else
617
               {
618
                  ea_mastered_reqs.RemoveAt(i_ea_mastered_reqs);
619
                  // do not increment i_ea_mastered_reqs after here
620
               }
621
            }
622
 
623
            Main.WriteSeperator();
624
 
625
            if (possibleOrphans == true)
626
            {
627
               Main.WriteOutput("", -1);
628
               Main.WriteOutput("One or more possible orphans have been found", -1);
629
               Main.WriteOutput("This could be the result of someone accidentally deleting the requirement", -1);
630
               Main.WriteOutput("in the ReqPro database. Or, it could be that someone modified the GUID tagged", -1);
631
               Main.WriteOutput("value in EA or ReqPro (very naughty).",-1);
632
               Main.WriteOutput("", -1);
633
               Main.WriteOutput("Going forward, if the requirement must be retained, delete all of its tagged values,", -1);
634
               Main.WriteOutput("in EA, remove the tag from its name, and attempt another export. The EA requirement will", -1);
635
               Main.WriteOutput("be given a new tag number, but at least it will re-appear in the ReqPro database.", -1);
636
               Main.WriteOutput("", -1);
637
               Main.WriteOutput("If the requirement is no longer needed, it can be deleted from EA once any design", -1);
638
               Main.WriteOutput("impacts are understood.", -1);
639
               Main.WriteSeperator();
640
            }
641
         }
642
         else
643
         {
644
            Main.WriteOutput("No ReqPro requirements need updating from their EA masters.",-1);
645
            Main.WriteSeperator();
646
         }
647
         return true;
648
      }
649
 
650
 
651
      /// <summary>
652
      /// Export relationships for the new requirements exported from EA
653
      /// </summary>
654
      /// <param name="ea_reqs"></param>
655
      private void export_new_EA_mastered_requirement_relationships(ref ArrayList ea_reqs)
656
      {
657
         // Algorithm design:
658
         //
659
         // for each new EA requirement (EA.Req) exported
660
         //   Get the ReqPro equivalent requirement (RP.Req)
661
         //   for each connector (EA.C) in EA.Req
662
         //      get referenced requirement (EA.RefReq) from EA.C
663
         //      find EA.RefReq's equivalent requirement (RP.RefReq) in ReqPro
664
         //      Establish a traces to relationship from RP.RefReq to RP.Req
665
 
666
         Main.WriteOutput("Creating Trace Relationships",-1);
667
 
668
         // for each new EA requirement (EA.Req) exported
669
         foreach (EA.Element ea_req in ea_reqs)
670
         {
671
            Main.WriteOutput("   " + ea_req.Name, ea_req.ElementID);
672
 
673
            string GUID = EA_TaggedValues.Read(ea_req, Constants.TAG_GUID, "");
674
            if (GUID != null && GUID.Length > 0 && GUID.StartsWith("{"))
675
            {
676
               // Get the ReqPro equivalent requirement (RP.Req)
677
               ReqPro40.Requirement rp_req = ReqProDatabase.get_requirement_by_guid(GUID);
678
               if (rp_req != null)
679
               {
680
                  // for each connector (EA.C) in EA.Req
681
                  foreach(EA.Connector ea_c in ea_req.Connectors)
682
                  {
683
                     int destId = -1;
684
 
685
                     // we dont care about direction of relationship, so test for both
686
                     if (ea_c.ClientID == ea_req.ElementID)
687
                        destId = ea_c.SupplierID;
688
                     else if (ea_c.SupplierID == ea_req.ElementID)
689
                        destId = ea_c.ClientID;
690
 
691
                     // and make sure we filter out self-referential connectors
692
                     if (destId != ea_req.ElementID)
693
                     {
694
                        // get referenced requirement (EA.RefReq) from EA.C
695
                        EA.Element ea_ref_req = Main.EA_Repository.GetElementByID(destId);
696
                        if (ea_ref_req != null && ea_ref_req.Type.Equals("Requirement"))
697
                        {
698
                           // Get the GUID from the referenced element
699
                           GUID = EA_TaggedValues.Read(ea_ref_req, Constants.TAG_GUID, "");
700
                           if (GUID != null && GUID.Length > 0 && GUID.StartsWith("{"))
701
                           {
702
                              // find EA.RefReq's equivalent requirement (RP.RefReq) in ReqPro
703
                              ReqPro40.Requirement rp_ref_req = ReqProDatabase.get_requirement_by_guid(GUID);
704
                              if (rp_ref_req != null)
705
                              {
706
                                 // Establish a traces to relationship from RP.RefReq to RP.Req
707
                                 ReqPro40.Relationships rp_ref_req_c = (ReqPro40.Relationships)rp_ref_req.TracesTo;
708
                                 if (rp_ref_req_c != null)
709
                                 {
710
                                    // wrap the relationship add in exception handling - In EA, a parent child relationship
711
                                    // can exist by virtue of the elements parentID values, and such does not prevent the
712
                                    // existence of a connection relationship either. But in ReqPro, it does. Once a requirement
713
                                    // has a "hierarchical" relationship, you cannot establish the same relationship in a 2nd
714
                                    // way, using for example a TracesTo relationship. Using exception handling here is probably
715
                                    // quicker than trying to examine what relationships already exist and act accordingly.
716
                                    try
717
                                    {
718
                                       ReqPro40.Relationship rp_ref_req_rel = 
719
                                          rp_ref_req_c.Add(rp_req,
720
                                          ReqPro40.enumRequirementLookups.eReqLookup_Object,
721
                                          null, ReqPro40.enumRelatedProjectLookups.eRelProjLookup_Empty,
722
                                          false);
723
                                       if (rp_ref_req_rel != null)
724
                                       {
725
                                          // commit
726
                                          rp_ref_req.Save();
727
                                       }
728
                                    }
729
                                    catch
730
                                    {
731
                                    }
732
                                 }
733
                              }
734
                           }
735
                        }
736
                     }
737
                  }
738
               }
739
            }
740
         }
741
         Main.WriteSeperator();
742
      }
743
 
744
 
745
      /// <summary>
746
      /// Update ReqPro relationships for requirements mastered in EA
747
      /// </summary>
748
      /// <param name="ea_mastered_reqs"></param>
749
      private void update_old_EA_mastered_requirement_relationships(ref ArrayList ea_mastered_reqs)
750
      {
751
         // Algorithm design:
752
         //
753
         //   for each EA requirement (EA.Req) updated
754
         //     Get the ReqPro equivalent requirement (RP.Req)
755
         //     for each connector (EA.C) in EA.Req
756
         //       get referenced requirement (EA.RefReq) from EA.C
757
         //       find EA.RefReq's equivalent requirement (RP.RefReq) in ReqPro
758
         //       Establish a traces to relationship from RP.RefReq to RP.Req (if it does not already exist)
759
         //       
760
         //     for each trace-to relationship (RP.C) in RP.Req
761
         //       if relationship does not exist in EA.Req
762
         //         delete RP.C
763
         //
764
         //     for each trace-from relationship (RP.C) in RP.Req
765
         //       if relationship does not exist in EA.Req
766
         //         delete RP.C
767
         //
768
 
769
         Main.WriteOutput("Updating Trace Relationships",-1);
770
 
771
         // for each EA requirement (EA.Req) updated
772
         foreach(EA.Element ea_req in ea_mastered_reqs)
773
         {
774
            Main.WriteOutput("   " + ea_req.Name, ea_req.ElementID);
775
 
776
            string GUID = EA_TaggedValues.Read(ea_req, Constants.TAG_GUID, "");
777
            if (GUID != null && GUID.Length > 0 && GUID.StartsWith("{"))
778
            {
779
               // Get the ReqPro equivalent requirement (RP.Req)
780
               ReqPro40.Requirement rp_req = ReqProDatabase.get_requirement_by_guid(GUID);
781
               if (rp_req != null)
782
               {
783
                  // for each connector (EA.C) in EA.Req
784
                  foreach(EA.Connector ea_c in ea_req.Connectors)
785
                  {
786
                     int destId = -1;
787
 
788
                     // we dont care about direction of relationship, so test for both
789
                     if (ea_c.ClientID == ea_req.ElementID)
790
                        destId = ea_c.SupplierID;
791
                     else if (ea_c.SupplierID == ea_req.ElementID)
792
                        destId = ea_c.ClientID;
793
 
794
                     // and make sure we filter out self-referential connectors
795
                     if (destId != ea_req.ElementID)
796
                     {
797
                        // get referenced requirement (EA.RefReq) from EA.C
798
                        EA.Element ea_ref_req = Main.EA_Repository.GetElementByID(destId);
799
                        if (ea_ref_req != null && ea_ref_req.Type.Equals("Requirement"))
800
                        {
801
                           // Get the GUID from the referenced element
802
                           GUID = EA_TaggedValues.Read(ea_ref_req, Constants.TAG_GUID, "");
803
                           if (GUID != null && GUID.Length > 0 && GUID.StartsWith("{"))
804
                           {
805
                              // find EA.RefReq's equivalent requirement (RP.RefReq) in ReqPro
806
                              ReqPro40.Requirement rp_ref_req = ReqProDatabase.get_requirement_by_guid(GUID);
807
                              if (rp_ref_req != null)
808
                              {
809
                                 // Establish a traces to relationship from RP.RefReq to RP.Req (if it does not already exist)
810
                                 ReqPro40.Relationships rp_ref_req_c = (ReqPro40.Relationships)rp_ref_req.TracesTo;
811
                                 if (rp_ref_req_c != null)
812
                                 {
813
                                    // ReqPro throws an exception if you try to create a relationship that already exists.
814
                                    // ReqPro doesn't seem to give any easy way to ask the question, "does a relationship
815
                                    // exist between A and B". It is debatable whether running a hand written function to 
816
                                    // answer the question is going to be any quicker than just catching the exceptions 
817
                                    // and ignoring them. For now though, use exception handling in this very bad way.
818
                                    try
819
                                    {
820
                                       ReqPro40.Relationship rp_ref_req_rel = 
821
                                          rp_ref_req_c.Add(rp_req,
822
                                          ReqPro40.enumRequirementLookups.eReqLookup_Object,
823
                                          null, ReqPro40.enumRelatedProjectLookups.eRelProjLookup_Empty,
824
                                          false);
825
                                       if (rp_ref_req_rel != null)
826
                                       {
827
 
828
                                          // commit
829
                                          rp_ref_req.Save();
830
 
831
                                          Main.WriteOutput("      Created Trace Relationship to " + rp_ref_req.get_Tag(ReqPro40.enumTagFormat.eTagFormat_FullTag), -1);
832
                                       }
833
                                    }
834
                                    catch
835
                                    {
836
                                       // do nothing
837
                                    }
838
                                 }
839
                              }
840
                           }
841
                        }
842
                     }
843
                  }
844
 
845
                  // Examine the Traces-To relationships in ReqPro
846
                  int limit_numberOfTraceTo = 0;
847
                  if (true == rp_req.get_HasTracesTo(ref limit_numberOfTraceTo))
848
                  {
849
                     ReqPro40.Relationships rp_req_c = (ReqPro40.Relationships)rp_req.TracesTo;
850
                     if (rp_req_c != null)
851
                     {
852
                        // for each relationship (RP.C) in RP.Req
853
                        rp_req_c.MoveFirst();
854
                        int i_numberOfTraceTo;
855
                        for (i_numberOfTraceTo = 0; i_numberOfTraceTo < limit_numberOfTraceTo; i_numberOfTraceTo++)
856
                        {
857
                           // Obtain the sub-requirement from the relationship, and parse it
858
                           ReqPro40.Relationship rp_req_rel = rp_req_c.GetCurrentRelationship();
859
 
860
                           ReqPro40.Requirement rp_ref_req = 
861
                              rp_req_rel.get_DestinationRequirement(ReqPro40.enumRequirementsWeights.eReqWeight_Heavy);
862
 
863
                           if (rp_ref_req != null)
864
                           {
865
                              // if relationship does not exist in EA.Req
866
                              if (!ea_element_traces_to_or_from(ea_req, rp_ref_req.GUID))
867
                              {
868
                                 // delete RP.C
869
                                 rp_req_rel.Delete();
870
                                 Main.WriteOutput("      Deleted Trace-To Relationship to " + rp_ref_req.get_Tag(ReqPro40.enumTagFormat.eTagFormat_FullTag), -1);
871
                              }
872
                           }
873
 
874
                           rp_req_c.MoveNext();
875
                        }
876
                        // commit
877
                        rp_req.Save();
878
                     }
879
                  }
880
 
881
                  // Examine the Traces-From relationships in ReqPro
882
                  int limit_numberOfTraceFrom = 0;
883
                  if (true == rp_req.get_HasTracesFrom(ref limit_numberOfTraceFrom))
884
                  {
885
                     ReqPro40.Relationships rp_req_c = (ReqPro40.Relationships)rp_req.TracesFrom;
886
                     if (rp_req_c != null)
887
                     {
888
                        // for each relationship (RP.C) in RP.Req
889
                        rp_req_c.MoveFirst();
890
                        int i_numberOfTraceFrom;
891
                        for (i_numberOfTraceFrom = 0; i_numberOfTraceFrom < limit_numberOfTraceFrom; i_numberOfTraceFrom++)
892
                        {
893
                           // Obtain the sub-requirement from the relationship, and parse it
894
                           ReqPro40.Relationship rp_req_rel = rp_req_c.GetCurrentRelationship();
895
 
896
                           ReqPro40.Requirement rp_ref_req = 
897
                              rp_req_rel.get_SourceRequirement(ReqPro40.enumRequirementsWeights.eReqWeight_Heavy);
898
 
899
                           if (rp_ref_req != null)
900
                           {
901
                              // if relationship does not exist in EA.Req
902
                              if (!ea_element_traces_to_or_from(ea_req, rp_ref_req.GUID))
903
                              {
904
                                 // delete RP.C
905
                                 rp_req_rel.Delete();
906
                                 Main.WriteOutput("      Deleted Trace-From Relationship to " + rp_ref_req.get_Tag(ReqPro40.enumTagFormat.eTagFormat_FullTag), -1);
907
                              }
908
                           }
909
 
910
                           rp_req_c.MoveNext();
911
                        }
912
                        // commit
913
                        rp_req.Save();
914
                     }
915
                  }
916
               }
917
            }
918
         }
919
         Main.WriteSeperator();
920
      }
921
 
922
 
923
      /// <summary>
924
      /// Use historical data stored in the ReqProDB element to 
925
      /// </summary>
926
      /// <param name="ea_mastered_reqs_rp_guids"></param>
927
      private void report_orphaned_ReqPro_requirements(ref ArrayList ea_mastered_reqs_rp_guids)
928
      {
929
         // we can only report on EA mastered requirements that have been deleted, if the extent of
930
         // the export is total, not partial
931
         if (m_ExportExtent == ExportForm.ExportExtent.REQPRODB_REQS)
932
         {
933
            // Get the last list of EA mastered requirements from the ReqProDB element
934
            if (base.RQ_Element.Notes != null && base.RQ_Element.Notes.Length > 0)
935
            {
936
               // split it into a string array
937
               char [] seperators = {'\r','\n'};
938
               string [] options = base.RQ_Element.Notes.Split(seperators);
939
 
940
               ArrayList rp_orphaned_reqs = new ArrayList();
941
               ArrayList rp_non_orphaned_reqs = new ArrayList();
942
 
943
               // process the string array to accumulate list of orphaned and non-orphaned requirements
944
               foreach (string s in options)
945
               {
946
                  string trimmed_s = s.Trim();
947
                  if (trimmed_s.Length > 0)
948
                  {
949
                     if (trimmed_s.StartsWith(Constants.KEY_EXPORTED_GUID))
950
                     {
951
                        string value = trimmed_s.Substring(Constants.KEY_EXPORTED_GUID.Length);
952
                        if (false == ea_mastered_reqs_rp_guids.Contains(value))
953
                        {
954
                           rp_orphaned_reqs.Add(value);
955
                        }
956
                        else
957
                        {
958
                           rp_non_orphaned_reqs.Add(value);
959
                        }
960
                     }
961
                  }
962
               }
963
 
964
               // default decision to use when constructing export options for ReqProDB element later on
965
               DialogResult dlgRes = DialogResult.No;
966
 
967
               // report on orphaned requirements
968
               if (rp_orphaned_reqs.Count > 0)
969
               {
970
                  ArrayList rp_orphaned_req_strings = new ArrayList();
971
 
972
                  foreach(string s in rp_orphaned_reqs)
973
                  {
974
                     ReqPro40.Requirement rp_req = ReqProDatabase.get_requirement_by_guid(s);
975
                     if (rp_req != null)
976
                     {
977
                        string rp_req_tag = rp_req.get_Tag(ReqPro40.enumTagFormat.eTagFormat_FullTag);
978
                        if (rp_req_tag != null)
979
                        {
980
                           rp_orphaned_req_strings.Add("   " + rp_req_tag + " " + rp_req.Name);
981
                        }
982
                     }
983
                  }
984
 
985
                  if (rp_orphaned_req_strings.Count > 0)
986
                  {
987
                     Main.WriteOutput("The following EA Mastered requirements in ReqPro, may no longer be needed.", -1);
988
                     Main.WriteOutput("i.e. they are orphaned requirements in ReqPro, because they have been deleted", -1);
989
                     Main.WriteOutput("in EA since the last export.", -1);
990
                     Main.WriteOutput("Please verify and if necessary, mark them as obsolete in ReqPro.", -1);
991
 
992
                     foreach(string s in rp_orphaned_req_strings)
993
                     {
994
                        Main.WriteOutput(s, -1);
995
                     }
996
 
997
                     Main.WriteSeperator();
998
 
999
                     // allow user to specifiy whether we should forget about the orphaned requirements
1000
                     // the next time we do an export.
1001
                     dlgRes = MessageBoxEx.Show(
1002
                        "Some ReqPro requirements have been orphaned (see output\n" +
1003
                        "tab display for more information).\n" + 
1004
                        "Ignore these problems in future exports?", "Confirm", MessageBoxButtons.YesNo);
1005
                  }
1006
               }
1007
 
1008
               StringBuilder sb = new StringBuilder();
1009
 
1010
               // reconstruct non-export related options using the appropriate ReqProFilterForm static method
1011
               // That method keeps knowledge of the import filter options localised in the right place.
1012
               ReqProFilterForm.saveFilterSettings(options, ref sb);
1013
 
1014
               // If this export had nothing to work with from the ReqProDB options....
1015
               if (rp_orphaned_reqs.Count == 0 && rp_non_orphaned_reqs.Count == 0)
1016
               {
1017
                  // The options did not contain any key values. That probably means that up till now,
1018
                  // any export that has been performed previously, did not actually export anything.
1019
                  // So, just add whatever we exported this time (if anything)
1020
                  if (ea_mastered_reqs_rp_guids.Count > 0)
1021
                  {
1022
                     sb.Append(Constants.EXPORT_HEADING);
1023
                     foreach (string s in ea_mastered_reqs_rp_guids)
1024
                     {
1025
                        sb.Append(Constants.KEY_EXPORTED_GUID);
1026
                        sb.Append(s);
1027
                        sb.Append("\r\n");
1028
                     }
1029
                  }
1030
               }
1031
               else
1032
               {
1033
                  sb.Append(Constants.EXPORT_HEADING);
1034
 
1035
                  // construct export-related options
1036
                  if (dlgRes == DialogResult.No)
1037
                  {
1038
                     foreach (string s in rp_orphaned_reqs)
1039
                     {
1040
                        sb.Append(Constants.KEY_EXPORTED_GUID);
1041
                        sb.Append(s);
1042
                        sb.Append("\r\n");
1043
                     }
1044
                  }
1045
                  foreach (string s in rp_non_orphaned_reqs)
1046
                  {
1047
                     sb.Append(Constants.KEY_EXPORTED_GUID);
1048
                     sb.Append(s);
1049
                     sb.Append("\r\n");
1050
 
1051
                     // if this item is in ea_mastered_reqs_rp_guids, then remove it from there so that we do not
1052
                     // duplicate it in the options string when we process ea_mastered_reqs_rp_guids after this loop
1053
                     // completes
1054
                     if (ea_mastered_reqs_rp_guids.Contains(s))
1055
                     {
1056
                        ea_mastered_reqs_rp_guids.Remove(s);
1057
                     }
1058
                  }
1059
 
1060
                  // If there are any items left in ea_mastered_reqs_rp_guids, add them too
1061
                  foreach (string s in ea_mastered_reqs_rp_guids)
1062
                  {
1063
                     sb.Append(Constants.KEY_EXPORTED_GUID);
1064
                     sb.Append(s);
1065
                     sb.Append("\r\n");
1066
                  }
1067
               }
1068
 
1069
               base.RQ_Element.Notes = sb.ToString();
1070
               base.RQ_Element.Update();
1071
            }
1072
         }
1073
      }
1074
 
1075
 
1076
      private bool ea_element_traces_to_or_from(EA.Element ea_req, string rp_GUID)
1077
      {
1078
         foreach(EA.Connector ea_c in ea_req.Connectors)
1079
         {
1080
            int destId = -1;
1081
 
1082
            // we dont care about direction of relationship, so test for both
1083
            if (ea_c.ClientID == ea_req.ElementID)
1084
               destId = ea_c.SupplierID;
1085
            else if (ea_c.SupplierID == ea_req.ElementID)
1086
               destId = ea_c.ClientID;
1087
 
1088
            // and make sure we filter out self-referential connectors
1089
            if (destId != ea_req.ElementID)
1090
            {
1091
               EA.Element ea_ref_req = Main.EA_Repository.GetElementByID(destId);
1092
               if (ea_ref_req != null)
1093
               {
1094
                  string GUID = EA_TaggedValues.Read(ea_ref_req, Constants.TAG_GUID, "");
1095
                  if (GUID != null && GUID.Length > 0 && GUID.StartsWith("{"))
1096
                  {
1097
                     if (rp_GUID.Equals(GUID))
1098
                        return true;
1099
                  }
1100
               }
1101
            }
1102
         }
1103
 
1104
         return false;
1105
      }
1106
 
1107
 
1108
      /// <summary>
1109
      /// Look for and strip any temporary tag from the requirement name, returning a new
1110
      /// string to be used as the requirement name
1111
      /// </summary>
1112
      /// <param name="taggedReqName"></param>
1113
      /// <returns></returns>
2157 ghuddy 1114
      private string untaggedReqName(string taggedReqName, ref string tag, bool force)
2155 ghuddy 1115
      {
1116
         if (taggedReqName != null)
1117
         {
1118
            // Try and split the string into two tokens at the first space character
1119
            char [] delim = {' '};
1120
            string [] tokens = taggedReqName.Split(delim, 2);
1121
 
1122
            // if there are two tokens resulting from the split
1123
            if (tokens.GetLength(0) == 2)
1124
            {
2157 ghuddy 1125
               // return tag
1126
               tag = tokens[0];
1127
 
2155 ghuddy 1128
               // if the first token appears to be a tag
1129
               if (force == true
1130
                  || tokens[0].StartsWith("REQ")
1131
                  || tokens[0].StartsWith("TAG")
1132
                  || tokens[0].StartsWith("SPR")
2163 ghuddy 1133
                  || tokens[0].StartsWith("<")
2155 ghuddy 1134
                  || (tokens[0].IndexOfAny(numbers) > 0 && tokens[0].IndexOfAny(letters) == 0))
1135
               {
1136
                  // return the token after the tag.
1137
                  return tokens[1];
1138
               }
1139
            }
1140
         }
1141
         // default to the input string
1142
         return taggedReqName;
1143
      }
1144
 
2157 ghuddy 1145
      private string tagPrefix(string tag)
1146
      {
1147
         if (tag != null && tag.Length > 0)
1148
         {
1149
            string[] prefixes = tag.Split("0123456789.".ToCharArray());
1150
            if (prefixes.GetLength(0) > 0)
1151
            {
1152
               return prefixes[0];
1153
            }
1154
         }
1155
         return tag;
1156
      }
2155 ghuddy 1157
 
2157 ghuddy 1158
      private void exportAttributes(ReqPro40.Requirement rp_req, EA.Element ea_req, string rp_req_tag)
2155 ghuddy 1159
      {
1160
         // Update the attributes of a ReqPro requirement. We have to be very careful here.
1161
         // ReqPro does not like us trying to set the value of attributes that do not exist for the
1162
         // specified requirement type, and it also does not like us trying to set an attribute that is
1163
         // a list type, to a value that is not in the predefined set of values for the list type.
1164
         bool hasStatus = false;
1165
         bool hasDifficulty = false;
1166
         bool hasPriority = false;
1167
         bool hasSource = false;
1168
         bool hasSourceVersion = false;
1169
         bool hasSourceSection = false;
1170
         bool hasSubsystem = false;
1171
         bool hasStability = false;
1172
         bool hasType = false;
1173
 
2157 ghuddy 1174
         string reqType = tagPrefix(rp_req_tag);
1175
 
2155 ghuddy 1176
         // Use the ReqProParser's knowledge of requirement types and attribute type associations to tell
1177
         // us what attributes we can set, and then use the setListItemValue() function to do the setting.
1178
         // That function knows how to set List items correctly and safely so as to not cause exceptions
1179
         // to be raised in the ReqPro automation onject.
2157 ghuddy 1180
         if (reqTypeHasOneOrMoreAttrs(reqType,
2155 ghuddy 1181
            ref hasStatus, ref hasDifficulty, ref hasPriority,
1182
            ref hasSource, ref hasSourceVersion, ref hasSourceSection,
1183
            ref hasSubsystem, ref hasStability, ref hasType))
1184
         {
1185
            if (hasStatus)
1186
            {
2161 ghuddy 1187
               setListItemAttrValue(rp_req, ea_req, Constants.RP_ATTR_STATUS, ea_req.Status, rp_req_tag);
2155 ghuddy 1188
            }
1189
            if (hasDifficulty)
1190
            {
2161 ghuddy 1191
               setListItemAttrValue(rp_req, ea_req, Constants.RP_ATTR_DIFFICULTY, ea_req.Difficulty, rp_req_tag);
2155 ghuddy 1192
            }
1193
            if (hasPriority)
1194
            {
2161 ghuddy 1195
               setListItemAttrValue(rp_req, ea_req, Constants.RP_ATTR_PRIORITY, ea_req.Priority, rp_req_tag);
2155 ghuddy 1196
            }
2157 ghuddy 1197
            if (hasSource)
1198
            {
1199
               string s = EA_TaggedValues.Read(ea_req, Constants.TAG_SOURCE);
1200
               if (s != null && s.Length > 0)
1201
               {
2161 ghuddy 1202
                  setListItemAttrValue(rp_req, ea_req, Constants.RP_ATTR_SOURCE, s, rp_req_tag);
2157 ghuddy 1203
               }
1204
            }
1205
            if (hasSourceVersion)
1206
            {
1207
               string s = EA_TaggedValues.Read(ea_req, Constants.TAG_SOURCE_VERSION);
1208
               if (s != null && s.Length > 0)
1209
               {
2161 ghuddy 1210
                  setTextAttrValue(rp_req, ea_req, Constants.RP_ATTR_SOURCE_VERSION, s, rp_req_tag);
2157 ghuddy 1211
               }
1212
            }
1213
            if (hasSourceSection)
1214
            {
1215
               string s = EA_TaggedValues.Read(ea_req, Constants.TAG_SOURCE_SECTION);
1216
               if (s != null && s.Length > 0)
1217
               {
2161 ghuddy 1218
                  setTextAttrValue(rp_req, ea_req, Constants.RP_ATTR_SOURCE_SECTION, s, rp_req_tag);
2157 ghuddy 1219
               }
1220
            }
1221
            if (hasSubsystem)
1222
            {
1223
               string s = EA_TaggedValues.Read(ea_req, Constants.TAG_SUBSYSTEM);
1224
               if (s != null && s.Length > 0)
1225
               {
2159 ghuddy 1226
                  // The tagged value may be a comma seperated list of subsystem names so break it up
1227
                  // and process each one found
1228
                  string[] sa = s.Split(",".ToCharArray());
1229
                  foreach (string sas in sa)
1230
                  {
1231
                     string trimmed_sas = sas.Trim();
1232
                     if (trimmed_sas.Length > 0)
1233
                     {
2161 ghuddy 1234
                        setListItemAttrValue(rp_req, ea_req, Constants.RP_ATTR_SUBSYSTEM_TYPE, trimmed_sas, rp_req_tag);
2159 ghuddy 1235
                     }
1236
                  }
2157 ghuddy 1237
               }
1238
            }
1239
            if (hasStability)
1240
            {
1241
               string s = EA_TaggedValues.Read(ea_req, Constants.TAG_STABILITY);
1242
               if (s != null && s.Length > 0)
1243
               {
2161 ghuddy 1244
                  setListItemAttrValue(rp_req, ea_req, Constants.RP_ATTR_STABILITY, s, rp_req_tag);
2157 ghuddy 1245
               }
1246
            }
1247
            if (hasType)
1248
            {
2159 ghuddy 1249
               // The StereoTypeEx is a comma seperated list, and the first in the list is usually (always?)
1250
               // the one displayed in EA's project browser, so try and export the first item in the list
1251
               bool done = false;
1252
               if (ea_req.StereotypeEx != null && ea_req.StereotypeEx.Length > 0)
2157 ghuddy 1253
               {
1254
                  string[] s_arr = ea_req.StereotypeEx.Split(",".ToCharArray());
1255
                  if (s_arr[0] != null && s_arr[0].Length > 0)
1256
                  {
2161 ghuddy 1257
                     setListItemAttrValue(rp_req, ea_req, Constants.RP_ATTR_REQ_TYPE, s_arr[0], rp_req_tag);
2159 ghuddy 1258
                     done = true;
2157 ghuddy 1259
                  }
1260
               }
2159 ghuddy 1261
               // if we didnt get anything from StereoTypeEx, then try Stereotype
1262
               if (!done && ea_req.Stereotype != null && ea_req.Stereotype.Length > 0)
1263
               {
2161 ghuddy 1264
                  setListItemAttrValue(rp_req, ea_req, Constants.RP_ATTR_REQ_TYPE, ea_req.Stereotype, rp_req_tag);
2159 ghuddy 1265
               }
2157 ghuddy 1266
            }
2155 ghuddy 1267
         }
1268
      }
1269
 
1270
 
1271
      /// <summary>
1272
      /// Set a ReqPro requirement attribute value, for an attribute that is a list type.
1273
      /// This function only allows the setting of the value, if it is one of the values
1274
      /// allowed for the list item. This ensures we do not get an exception raised in the
1275
      /// ReqPro automation object.
1276
      /// </summary>
1277
      /// <param name="rp_req"></param>
1278
      /// <param name="label"></param>
1279
      /// <param name="value"></param>
2157 ghuddy 1280
      private void setListItemAttrValue(ReqPro40.Requirement rp_req, EA.Element ea_req, string label, string value, string rp_req_tag)
2155 ghuddy 1281
      {
2157 ghuddy 1282
         bool attribute_type_found = false;
1283
         bool attribute_value_found = false;
1284
 
2155 ghuddy 1285
         // look through each attribute value, for the one whose label matches the one specified
1286
         ReqPro40.AttrValues rp_attr_values = rp_req.AttrValues;
1287
 
1288
         foreach (ReqPro40.AttrValue rp_attr_value in rp_attr_values)
1289
         {
1290
            if (rp_attr_value != null && rp_attr_value.Label.Equals(label))
1291
            {
2157 ghuddy 1292
               attribute_type_found = true;
1293
 
2155 ghuddy 1294
               // Look through each list item value to make sure that one exists that matches
1295
               // the value specified
1296
               ReqPro40.ListItemValues rp_list_item_values = rp_attr_value.ListItemValues;
1297
               if (rp_list_item_values != null)
1298
               {
1299
                  foreach (ReqPro40.ListItemValue rp_list_item_value in rp_list_item_values)
1300
                  {
1301
                     if (rp_list_item_value.Text.Equals(value))
1302
                     {
1303
                        // We found that the list contains the value specified, so set the value of the attribute
1304
                        rp_list_item_value.Selected = true;
1305
 
2157 ghuddy 1306
                        attribute_value_found = true;
2155 ghuddy 1307
                        // exit inner loop
1308
                        break;
1309
                     }
1310
                  }
1311
               }
1312
               // exit outer loop
1313
               break;
1314
            }
1315
         }
2157 ghuddy 1316
 
1317
         if (!attribute_type_found)
1318
         {
1319
            Main.WriteOutput(string.Format("WARNING, Failed to export attribute type ({0}) for ({1})",
1320
               label, rp_req_tag), ea_req.ElementID);
1321
         }
1322
         if (!attribute_value_found)
1323
         {
1324
            Main.WriteOutput(string.Format("WARNING, Failed to export attribute type/value ({0}/{1}) for ({2})",
1325
               label, value, rp_req_tag), ea_req.ElementID);
1326
         }
2155 ghuddy 1327
      }
1328
 
1329
 
2157 ghuddy 1330
 
1331
      /// <summary>
1332
      /// Set a ReqPro requirement attribute value, for an attribute that is a text type.
1333
      /// </summary>
1334
      /// <param name="rp_req"></param>
1335
      /// <param name="label"></param>
1336
      /// <param name="value"></param>
1337
      private void setTextAttrValue(ReqPro40.Requirement rp_req, EA.Element ea_req, string label, string value, string rp_req_tag)
1338
      {
1339
         bool attribute_type_found = false;
1340
 
1341
         // look through each attribute value, for the one whose label matches the one specified
1342
         ReqPro40.AttrValues rp_attr_values = rp_req.AttrValues;
1343
 
1344
         foreach (ReqPro40.AttrValue rp_attr_value in rp_attr_values)
1345
         {
1346
            if (rp_attr_value != null && rp_attr_value.Label.Equals(label))
1347
            {
1348
               attribute_type_found = true;
1349
 
1350
               rp_attr_value.Text = value;
1351
 
1352
               // exit outer loop
1353
               break;
1354
            }
1355
         }
1356
 
1357
         if (!attribute_type_found)
1358
         {
1359
            Main.WriteOutput(string.Format("WARNING, Failed to export attribute type ({0}) for ({1})",
1360
               label, rp_req_tag), ea_req.ElementID);
1361
         }
1362
      }
1363
 
1364
 
2155 ghuddy 1365
	}
1366
}