Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
2088 ghuddy 1
using System;
2
using System.Collections;
2104 ghuddy 3
using System.Text;
2088 ghuddy 4
using System.ComponentModel;
5
using System.Windows.Forms;
6
 
7
namespace EA_DocGen
8
{
9
	/// <summary>
10
	/// Summary description for EA_RelationshipMatrix.
11
	/// </summary>
12
	public class EA_RelationshipMatrix
13
	{
14
 
2122 ghuddy 15
      public struct RM_ColumnType
16
      {
17
         public string columnTitle;
2088 ghuddy 18
 
2122 ghuddy 19
         public string packageGUID;
20
         public string packageName;
21
 
22
         public ArrayList elementTypes;
23
 
24
         public bool packageRecursion;
25
         public bool packageTrimming;
26
         public bool elementNotes;
27
      };
28
 
29
      public struct RM_TableType
30
      {
31
         public string introText;
32
         public string title;
33
      };
34
 
35
      public struct RM_MatrixType
36
      {
37
         public int style;
38
         public RM_TableType fromToTable;
39
         public RM_TableType toFromTable;
40
         public RM_ColumnType from;
41
         public RM_ColumnType to;
42
      };
43
 
44
      // DATA
45
      private static RM_MatrixType RM_Matrix;
46
 
47
      private static EA.Element RM_Element = null;
48
 
2106 ghuddy 49
      private static EA.Package fromPackage = null;
50
      private static EA.Package toPackage = null;
2104 ghuddy 51
 
2122 ghuddy 52
      private static ArrayList processedElements = null;
2094 ghuddy 53
 
2106 ghuddy 54
      private static string [] options_string = null;
2088 ghuddy 55
 
2118 ghuddy 56
      private enum DictionaryValueType
57
      {
58
         DVT_EA_ELEMENT,
59
         DVT_STRING
60
      };
2088 ghuddy 61
 
2106 ghuddy 62
		public static void initialise(ArrayList processedElementsRef)
2088 ghuddy 63
		{
2104 ghuddy 64
         processedElements = processedElementsRef;
65
 
2122 ghuddy 66
         RM_Matrix.from.elementTypes = new ArrayList();
67
         RM_Matrix.to.elementTypes = new ArrayList();
2088 ghuddy 68
		}
69
 
2106 ghuddy 70
      private static void reset()
2088 ghuddy 71
      {
2122 ghuddy 72
         RM_Matrix.style = 1;
2104 ghuddy 73
 
2122 ghuddy 74
         RM_Matrix.fromToTable.introText = null;
75
         RM_Matrix.fromToTable.title = null;
76
 
77
         RM_Matrix.from.columnTitle = null;
78
         RM_Matrix.from.packageGUID = null;
79
         RM_Matrix.from.elementTypes.Clear();
80
         RM_Matrix.from.packageRecursion = true;
81
         RM_Matrix.from.packageTrimming = false;
82
         RM_Matrix.from.elementNotes = false;
83
         RM_Matrix.from.packageName = null;
84
 
2088 ghuddy 85
         fromPackage = null;
2122 ghuddy 86
 
87
         RM_Matrix.toFromTable.introText = null;
88
         RM_Matrix.toFromTable.title = null;
89
 
90
         RM_Matrix.to.columnTitle = null;
91
         RM_Matrix.to.packageGUID = null;
92
         RM_Matrix.to.elementTypes.Clear();
93
         RM_Matrix.to.packageRecursion = true;
94
         RM_Matrix.to.packageTrimming = false;
95
         RM_Matrix.to.elementNotes = false;
96
         RM_Matrix.to.packageName = null;
97
 
2088 ghuddy 98
         toPackage = null;
99
      }
100
 
101
 
2106 ghuddy 102
      public static bool processRelationshipMatrixOptions(EA.Element theElement)
2088 ghuddy 103
      {
2122 ghuddy 104
         RM_Element = theElement;
105
 
2088 ghuddy 106
         reset();
107
 
108
         // Extract the control options from the notes of the element
109
 
110
         string delimStr = "\n";
111
         char [] delim = delimStr.ToCharArray();
112
         options_string = theElement.Notes.ToString().Split(delim,100);
113
         int i = 0;
114
         foreach(string s in options_string)
115
         {
116
            options_string[i] = s.Trim();
117
            i++;
118
         }
119
 
120
         // scan the options string and assign values into the options variables as required
121
         foreach(string s in options_string)
122
         {
123
            if (s.Length > 0 && s != "\n" && s != "\r" && s[0] != '\\')
124
            {
2104 ghuddy 125
               if (s.StartsWith("style="))
126
               {
2122 ghuddy 127
                  RM_Matrix.style = EA_DocGenOptions.getOptionValue(s, RM_Matrix.style);
2104 ghuddy 128
               }
2118 ghuddy 129
                  // FROM items
2104 ghuddy 130
               else if (s.StartsWith("fromIntroText="))
2088 ghuddy 131
               {
2122 ghuddy 132
                  RM_Matrix.fromToTable.introText = EA_DocGenOptions.getOptionValue(s, null);
2088 ghuddy 133
               }
2104 ghuddy 134
               else if (s.StartsWith("fromToTableTitle=")) 
2088 ghuddy 135
               {
2122 ghuddy 136
                  RM_Matrix.fromToTable.title = EA_DocGenOptions.getOptionValue(s, null);
2088 ghuddy 137
               }
2104 ghuddy 138
               else if (s.StartsWith("fromColumnTitle=")) 
2088 ghuddy 139
               {
2122 ghuddy 140
                  RM_Matrix.from.columnTitle = EA_DocGenOptions.getOptionValue(s, RM_Matrix.from.columnTitle);
2088 ghuddy 141
               }
2104 ghuddy 142
               else if (s.StartsWith("fromPackageRecursion=")) 
2088 ghuddy 143
               {
2122 ghuddy 144
                  RM_Matrix.from.packageRecursion = EA_DocGenOptions.getOptionValue(s, RM_Matrix.from.packageRecursion);
2088 ghuddy 145
               }
2104 ghuddy 146
               else if (s.StartsWith("fromPackageTrimming="))
2094 ghuddy 147
               {
2122 ghuddy 148
                  RM_Matrix.from.packageTrimming = EA_DocGenOptions.getOptionValue(s, RM_Matrix.from.packageTrimming);
2094 ghuddy 149
               }
2104 ghuddy 150
               else if (s.StartsWith("fromPackage=")) 
2088 ghuddy 151
               {
2122 ghuddy 152
                  RM_Matrix.from.packageGUID = EA_DocGenOptions.getOptionValue(s, RM_Matrix.from.packageGUID);
2088 ghuddy 153
               }
2118 ghuddy 154
               else if (s.StartsWith("fromElementNotes="))
155
               {
2122 ghuddy 156
                  RM_Matrix.from.elementNotes = EA_DocGenOptions.getOptionValue(s, RM_Matrix.from.elementNotes);
2118 ghuddy 157
               }
2122 ghuddy 158
               else if (s.StartsWith("fromPackageName="))
159
               {
160
                  RM_Matrix.from.packageName = EA_DocGenOptions.getOptionValue(s, RM_Matrix.from.packageName);
161
               }
2104 ghuddy 162
               else if (s.StartsWith("fromElementType=")) 
2088 ghuddy 163
               {
2106 ghuddy 164
                  string et = EA_DocGenOptions.getOptionValue(s,null);
2088 ghuddy 165
                  if (et != null) 
166
                  {
2122 ghuddy 167
                     RM_Matrix.from.elementTypes.Add( et );
2088 ghuddy 168
                  }
169
               }
170
 
171
                  // TO items
2104 ghuddy 172
               else if (s.StartsWith("toIntroText="))
2088 ghuddy 173
               {
2122 ghuddy 174
                  RM_Matrix.toFromTable.introText = EA_DocGenOptions.getOptionValue(s, null);
2088 ghuddy 175
               }
2104 ghuddy 176
               else if (s.StartsWith("toFromTableTitle=")) 
2088 ghuddy 177
               {
2122 ghuddy 178
                  RM_Matrix.toFromTable.title = EA_DocGenOptions.getOptionValue(s, null);
2088 ghuddy 179
               }
2104 ghuddy 180
               else if (s.StartsWith("toColumnTitle=")) 
2088 ghuddy 181
               {
2122 ghuddy 182
                  RM_Matrix.to.columnTitle = EA_DocGenOptions.getOptionValue(s, RM_Matrix.to.columnTitle);
2088 ghuddy 183
               }
2104 ghuddy 184
               else if (s.StartsWith("toPackageRecursion=")) 
2088 ghuddy 185
               {
2122 ghuddy 186
                  RM_Matrix.to.packageRecursion = EA_DocGenOptions.getOptionValue(s, RM_Matrix.to.packageRecursion);
2088 ghuddy 187
               }
2104 ghuddy 188
               else if (s.StartsWith("toPackageTrimming=")) 
2094 ghuddy 189
               {
2122 ghuddy 190
                  RM_Matrix.to.packageTrimming = EA_DocGenOptions.getOptionValue(s, RM_Matrix.to.packageTrimming);
2094 ghuddy 191
               }               
2104 ghuddy 192
               else if (s.StartsWith("toPackage=")) 
2088 ghuddy 193
               {
2122 ghuddy 194
                  RM_Matrix.to.packageGUID = EA_DocGenOptions.getOptionValue(s, RM_Matrix.to.packageGUID);
2088 ghuddy 195
               }
2118 ghuddy 196
               else if (s.StartsWith("toElementNotes="))
197
               {
2122 ghuddy 198
                  RM_Matrix.to.elementNotes = EA_DocGenOptions.getOptionValue(s, RM_Matrix.to.elementNotes);
2118 ghuddy 199
               }
2122 ghuddy 200
               else if (s.StartsWith("toPackageName="))
201
               {
202
                  RM_Matrix.to.packageName = EA_DocGenOptions.getOptionValue(s, RM_Matrix.to.packageName);
203
               }               
2104 ghuddy 204
               else if (s.StartsWith("toElementType=")) 
2088 ghuddy 205
               {
2106 ghuddy 206
                  string et = EA_DocGenOptions.getOptionValue(s,null);
2088 ghuddy 207
                  if (et != null) 
208
                  {
2122 ghuddy 209
                     RM_Matrix.to.elementTypes.Add( et );
2088 ghuddy 210
                  }
211
               }
212
            }
213
         }
214
 
215
         // Verify that we have all the necessary compulsory options
2122 ghuddy 216
         if (RM_Matrix.fromToTable.title == null && RM_Matrix.toFromTable.title == null)
2088 ghuddy 217
         {
218
            MessageBox.Show("Error in EA_DocGenRelationshipMatrix options list\n\n" +
219
               "Missing option: Must specify at least one table title");
220
            return false;
221
         }
222
 
223
         // FROM items
2122 ghuddy 224
         if (RM_Matrix.from.columnTitle == null)
2088 ghuddy 225
         {
226
            MessageBox.Show("Error in EA_DocGenRelationshipMatrix options list\n\n" +
227
               "Missing option: fromColumnTitle");
228
            return false;
229
         }
2122 ghuddy 230
         if (RM_Matrix.from.packageGUID == null)
2088 ghuddy 231
         {
232
            MessageBox.Show("Error in EA_DocGenRelationshipMatrix options list\n\n" +
233
               "Missing option: fromPackageGUID");
234
            return false;
235
         }
2122 ghuddy 236
         if (RM_Matrix.from.elementTypes.Count == 0)
2088 ghuddy 237
         {
238
            MessageBox.Show("Error in EA_DocGenRelationshipMatrix options list\n\n" +
239
               "Missing option(s): fromElementTypes");
240
            return false;
241
         }      
242
 
243
         // TO items
2122 ghuddy 244
         if (RM_Matrix.to.columnTitle == null)
2088 ghuddy 245
         {
246
            MessageBox.Show("Error in EA_DocGenRelationshipMatrix options list\n\n" +
247
               "Missing option: toColumnTitle");
248
            return false;
249
         }
2122 ghuddy 250
         if (RM_Matrix.to.packageGUID == null)
2088 ghuddy 251
         {
252
            MessageBox.Show("Error in EA_DocGenRelationshipMatrix options list\n\n" +
253
               "Missing option: toPackageGUID");
254
            return false;
255
         }
2122 ghuddy 256
         if (RM_Matrix.to.elementTypes.Count == 0)
2088 ghuddy 257
         {
258
            MessageBox.Show("Error in EA_DocGenRelationshipMatrix options list\n\n" +
259
               "Missing option(s): toElementTypes");
260
            return false;
261
         }   
262
 
263
         // Find GUID linked packages in the repository
2122 ghuddy 264
         fromPackage = Main.EA_Repository.GetPackageByGuid( RM_Matrix.from.packageGUID );
2088 ghuddy 265
         if (fromPackage == null)
266
         {
267
            MessageBox.Show("Error processing EA_DocGenRelationshipMatrix\n\n" +
268
               "could not locate fromPackage in Repository");
269
            return false;
270
         }
271
 
2122 ghuddy 272
         toPackage = Main.EA_Repository.GetPackageByGuid( RM_Matrix.to.packageGUID );
2088 ghuddy 273
         if (toPackage == null)
274
         {
275
            MessageBox.Show("Error processing EA_DocGenRelationshipMatrix\n\n" +
276
               "could not locate toPackage in Repository");
277
            return false;
278
         }
279
 
280
         return true;
281
      }
282
 
283
 
2104 ghuddy 284
      public static string optionTemplateForRelationshipMatrix(int style)
2088 ghuddy 285
      {
2104 ghuddy 286
         switch (style)
287
         {
288
            case 1:
289
               return
290
               "style=1\r\n"
291
               + "fromToTableTitle=\r\n"
292
               + "fromIntroText=\r\n"
293
               + "fromColumnTitle=\r\n"
294
               + "fromPackage=\r\n"
295
               + "fromElementType=\r\n"
296
               + "fromElementType=\r\n"
297
               + "fromPackageRecursion=true\r\n"
298
               + "fromPackageTrimming=false\r\n"
2120 ghuddy 299
               + "fromElementNotes=false\r\n"   
2104 ghuddy 300
 
301
               + "toFromTableTitle=\r\n"
302
               + "toIntroText=\r\n"
303
               + "toColumnTitle=\r\n"
304
               + "toPackage=\r\n"
305
               + "toElementType=\r\n"
306
               + "toPackageRecursion=true\r\n"
2118 ghuddy 307
               + "toPackageTrimming=false\r\n"
308
               + "toElementNotes=false\r\n";
2104 ghuddy 309
            case 2:
310
               return
311
               "style=2\r\n"
312
               + "fromToTableTitle=Requirement Dependencies\r\n"
313
               + "fromIntroText=The following table identifies the source requirements (if any) for each requirement stated in this document.\r\n"
314
               + "fromColumnTitle=Requirement\r\n"
315
               + "fromPackage=\r\n"
316
               + "fromElementType=Requirement\r\n"
317
               + "fromPackageRecursion=true\r\n"
318
               + "fromPackageTrimming=false\r\n"
2118 ghuddy 319
               + "fromElementNotes=false\r\n"
2104 ghuddy 320
 
321
               + "toPackageRecursion=true\r\n"
322
               + "toPackage=\r\n"
323
               + "toColumnTitle=Source Requirements\r\n"
324
               + "toElementType=Requirement\r\n";
325
            default:
326
               return "";
327
         }
2088 ghuddy 328
      }
329
 
2122 ghuddy 330
 
2104 ghuddy 331
      /// <summary>
332
      /// This function will insert one or more relationship matrix tables into the document, 
333
      /// built from content specified in options that are provided in the notes section of 
334
      /// the special element that has led to this function being called.
335
      /// </summary>
336
      /// <param name="theElement"></param>
337
      /// <param name="recurse_level"></param>
2106 ghuddy 338
      public static void processRelationshipMatrixElement( EA.Element theElement, int recurse_level )
2104 ghuddy 339
      {
2122 ghuddy 340
         RM_Element = theElement;
341
 
342
         if (RM_Matrix.from.packageName != null && fromPackage != null)
2104 ghuddy 343
         {
2122 ghuddy 344
            EA.Package newFromPackage = EA_Utilities.findNamedPackage(fromPackage, RM_Matrix.from.packageName);
345
            if (newFromPackage != null)
346
            {
347
               fromPackage = newFromPackage;
348
            }
349
            else
350
            {
351
               MessageBox.Show("Error processing EA_DocGenRelationshipMatrix\n\n" +
352
                  "could not locate fromPackageName in Repository");
353
               return;
354
            }
355
         }
356
 
357
         if (RM_Matrix.to.packageName != null && toPackage != null)
358
         {
359
            EA.Package newToPackage = EA_Utilities.findNamedPackage(toPackage, RM_Matrix.to.packageName);
360
            if (newToPackage != null)
361
            {
362
               toPackage = newToPackage;
363
            }
364
            else
365
            {
366
               MessageBox.Show("Error processing EA_DocGenRelationshipMatrix\n\n" +
367
                  "could not locate toPackageName in Repository");
368
               return;
369
            }
370
         }
371
 
372
         switch (RM_Matrix.style)
373
         {
2104 ghuddy 374
            case 1:
375
               processRelationshipMatrixElementStyle1();
376
               break;
2088 ghuddy 377
 
2104 ghuddy 378
            case 2:
379
               processRelationshipMatrixElementStyle2();
380
               break;
381
         }
382
      }
383
 
2122 ghuddy 384
 
2104 ghuddy 385
      /// <summary>
386
      /// This function will insert a relationship matrix table into the document, built from content
387
      /// specified in options that are provided in the notes section of the special element that
388
      /// has led to this function being called.
389
      /// 
390
      /// The style of these tables is that required for requirement to design traceability.
391
      /// </summary>
392
      /// <param name="EA_RelMatrix"></param>
2106 ghuddy 393
      private static void processRelationshipMatrixElementStyle1()
2104 ghuddy 394
      {
395
         int tableNum = 0;
396
         Word.Table table = null;
397
 
398
         // Scan the fromPackage to find all the "from elements".
2122 ghuddy 399
         ElementAccumulator fromLister = new ElementAccumulator(RM_Matrix.from.elementTypes);
400
         EA_Utilities.findAndProcessPackageElements( fromPackage, fromLister, RM_Matrix.from.packageRecursion );
2104 ghuddy 401
 
2106 ghuddy 402
         if (createWordDoc.abortCreationThread)
403
            return;
404
 
2120 ghuddy 405
         // Scan the toPackage to find all the "to elements".
2122 ghuddy 406
         ElementAccumulator toLister = new ElementAccumulator(RM_Matrix.to.elementTypes);
407
         EA_Utilities.findAndProcessPackageElements( toPackage, toLister, RM_Matrix.to.packageRecursion );
2120 ghuddy 408
 
409
         if (createWordDoc.abortCreationThread)
410
            return;
411
 
2104 ghuddy 412
         // Sort the "from elements"
413
         elementSortByName sorter = new elementSortByName();
414
         fromLister.Elements.Sort( sorter );
415
 
2120 ghuddy 416
         // Sort the "to" elements
417
         toLister.Elements.Sort( sorter );
418
 
2106 ghuddy 419
         if (createWordDoc.abortCreationThread)
420
            return;
421
 
2104 ghuddy 422
         // dictionary to support from-to table construction.
423
         ArrayList fromToDictionary = new ArrayList();
424
 
425
         // dictionary to support to-from table construction.
426
         ArrayList toFromDictionary = new ArrayList();
427
 
428
         bool needFromToTable = false;
2122 ghuddy 429
         if (RM_Matrix.fromToTable.title != null && RM_Matrix.fromToTable.title.Length > 0)
2104 ghuddy 430
            needFromToTable = true;
431
 
432
         bool needToFromTable = false;
2122 ghuddy 433
         if (RM_Matrix.toFromTable.title != null && RM_Matrix.toFromTable.title.Length > 0)
2104 ghuddy 434
            needToFromTable = true;
435
 
436
         // NOTE: this code has to execute even if no from-to table is needed, in order to support the
437
         // generation of a to-from table, assuming the user has requested one.
438
         int numberOfFromToRows = 0;
439
 
440
         foreach(EA.Element fromElement in fromLister.Elements)
441
         {
2106 ghuddy 442
            if (createWordDoc.abortCreationThread)
443
               return;
444
 
2104 ghuddy 445
            // look at the elements connection collection to find references to the
446
            // destination elements
447
            bool foundToElement = false;
448
 
449
            EA.Collection conCollection = fromElement.Connectors;
450
 
451
            foreach (EA.Connector thisCon in conCollection)
452
            {
2106 ghuddy 453
               if (createWordDoc.abortCreationThread)
454
                  return;
455
 
456
               EA.Element destE = Main.EA_Repository.GetElementByID( thisCon.SupplierID );
2104 ghuddy 457
               if (destE == null)
458
                  continue;
459
 
460
               // ignore self-referential connections
461
               if (fromElement.ElementID == thisCon.SupplierID)
462
                  continue;
463
 
464
               // if the destination element is of a type that the user has requested to include...
2122 ghuddy 465
               if (!RM_Matrix.to.elementTypes.Contains( destE.Type ))
2104 ghuddy 466
                  continue;
467
 
2120 ghuddy 468
               // if the destination element is in the "to list"...
469
               if ( !toLister.ElementIds.Contains(destE.ElementID) )
470
                  continue;
471
 
2104 ghuddy 472
               // Capture the from-to relationship in a dictionary where the key is the
473
               // "from element", and the value is the "to element".
474
               DictionaryEntry newFromToEntry = new DictionaryEntry(fromElement, destE);
475
               fromToDictionary.Add( newFromToEntry );
476
               foundToElement = true;
477
 
478
               // Capture the from-to relationship in a dictionary where the key is the
479
               // ID of the destination element, and the value is the from element name.
480
               // This dictionary will enable rapid construction of the to-from table if
481
               // the user has requested it, from the exact same relationship info used
482
               // to construct the from-to table.
483
               if (needToFromTable)
484
               {
485
                  DictionaryEntry newToFromEntry = new DictionaryEntry(destE.ElementID, fromElement.Name);
486
                  toFromDictionary.Add( newToFromEntry );
487
               }
488
            }
489
 
490
            // If we found a from-to relationship that table needs a new row.
491
            if (foundToElement)
492
            {
493
               numberOfFromToRows++;
494
            }
495
               // If we did not find a from-to relationship that table still needs a new row 
496
               // if the user wants all "from elements", even if some have no "to elements".
2122 ghuddy 497
            else if (RM_Matrix.from.packageTrimming == false)
2104 ghuddy 498
            {
499
               DictionaryEntry newFromToEntry = new DictionaryEntry(fromElement, null);
500
               fromToDictionary.Add( newFromToEntry );
501
               numberOfFromToRows++;
502
            }
503
         }
504
 
2106 ghuddy 505
         if (createWordDoc.abortCreationThread)
506
            return;
507
 
2104 ghuddy 508
         if (needFromToTable)
509
         {
510
            // Now we can actually serialise the table
511
 
2122 ghuddy 512
            if (RM_Matrix.fromToTable.introText != null && RM_Matrix.fromToTable.introText.Length > 0)
2104 ghuddy 513
            {
2122 ghuddy 514
               Word.Range wr = TextualContent.appendAndSelectText( RM_Matrix.fromToTable.introText, EA_Constants.styleName_Body1 );
515
               object obj = string.Format("EA_DocGen Informational Comment - This table has been produced using the following options:\n\n{0}", RM_Element.Notes);
516
               createWordDoc.WordDocument.Comments.Add(wr, ref obj);
2104 ghuddy 517
            }
518
 
519
            // create the from-to table in the word doc
2122 ghuddy 520
            tableNum = TabularContent.Table_Create( RM_Matrix.fromToTable.title, true, numberOfFromToRows + 1, 2 );
2106 ghuddy 521
            table = createWordDoc.WordDocument.Tables[tableNum];
2104 ghuddy 522
 
2122 ghuddy 523
            TabularContent.Table_SetTableColumnTitle(table, RM_Matrix.from.columnTitle, 1);
524
            TabularContent.Table_SetTableColumnTitle(table, RM_Matrix.to.columnTitle, 2);
2104 ghuddy 525
 
2118 ghuddy 526
            fillInTable(fromToDictionary, table, DictionaryValueType.DVT_EA_ELEMENT);
2104 ghuddy 527
         }
528
 
2106 ghuddy 529
         if (createWordDoc.abortCreationThread)
530
            return;
531
 
2104 ghuddy 532
         // Does user want a to-from table ?
533
         if (needToFromTable)
534
         {
2118 ghuddy 535
            // update fromElementNotes with toElementNotes setting
2122 ghuddy 536
            RM_Matrix.from.elementNotes = RM_Matrix.to.elementNotes;
2118 ghuddy 537
 
2104 ghuddy 538
            // re-use the fromToDictionary to prepare the to-from table content 
539
            fromToDictionary.Clear();
540
 
2120 ghuddy 541
            // We've already found all elements for the left hand column of the to-from table.
542
            // They are stored in the toLister
2104 ghuddy 543
 
2106 ghuddy 544
            if (createWordDoc.abortCreationThread)
545
               return;
546
 
2104 ghuddy 547
            // To make the to-from table, we use the dictionary that was built when making the from-to
548
            // table. The dictionary will allow rapid determination of what "from" items belong to each
549
            // "to" item, without us having to go back to EA and enquire on the database.
550
            // We build a new fromToDictionary from the toFromDictionary, in advance of actually making 
551
            // the table so that we can figure out how many rows the table needs to have.
552
            numberOfFromToRows = 0;
553
 
554
            foreach(EA.Element toElement in toLister.Elements)
555
            {
2106 ghuddy 556
               if (createWordDoc.abortCreationThread)
557
                  return;
558
 
2104 ghuddy 559
               bool foundToElement = false;
560
 
561
               // right-column cell content
562
               foreach (DictionaryEntry de in toFromDictionary)
563
               {
564
                  if ((int)de.Key == toElement.ElementID)
565
                  {
566
                     DictionaryEntry newFromToEntry = new DictionaryEntry(toElement, (string)de.Value);
567
                     fromToDictionary.Add( newFromToEntry );
568
                     foundToElement = true;
569
                  }
570
               }
571
 
2106 ghuddy 572
               if (createWordDoc.abortCreationThread)
573
                  return;
574
 
2104 ghuddy 575
               // If we found a from-to relationship that table needs a new row.
576
               if (foundToElement)
577
               {
578
                  numberOfFromToRows++;
579
               }
580
                  // if user wants all "from elements", even if some have no "to elements", then add a dictionary
581
                  // entry and bump row count.
2122 ghuddy 582
               else if (RM_Matrix.to.packageTrimming == false)
2104 ghuddy 583
               {
584
                  DictionaryEntry newFromToEntry = new DictionaryEntry(toElement, "");
585
                  fromToDictionary.Add( newFromToEntry );
586
                  numberOfFromToRows++;
587
               }
588
            }
589
 
2106 ghuddy 590
            if (createWordDoc.abortCreationThread)
591
               return;
592
 
2104 ghuddy 593
            // Now begin to add the to-from table to the word document
2122 ghuddy 594
            if (RM_Matrix.toFromTable.introText != null && RM_Matrix.toFromTable.introText.Length > 0)
2104 ghuddy 595
            {
2122 ghuddy 596
               Word.Range wr = TextualContent.appendAndSelectText( RM_Matrix.toFromTable.introText, EA_Constants.styleName_Body1 );
597
 
598
               // add options comment only if user did not generate a from-to table, since there is no point in repeating
599
               // the options comment which applies to both from-to and to-from table pair.
600
               if (!needFromToTable)
601
               {
602
                  object obj = string.Format("EA_DocGen Informational Comment - This table has been produced using the following options:\n\n{0}", RM_Element.Notes);
603
                  createWordDoc.WordDocument.Comments.Add(wr, ref obj);
604
               }
2104 ghuddy 605
            }
606
 
607
            // create the table in the word doc
2122 ghuddy 608
            tableNum = TabularContent.Table_Create( RM_Matrix.toFromTable.title, true, numberOfFromToRows + 1, 2 );
2106 ghuddy 609
            table = createWordDoc.WordDocument.Tables[tableNum];
2104 ghuddy 610
 
2122 ghuddy 611
            TabularContent.Table_SetTableColumnTitle(table, RM_Matrix.to.columnTitle, 1);
612
            TabularContent.Table_SetTableColumnTitle(table, RM_Matrix.from.columnTitle, 2);
2104 ghuddy 613
 
2118 ghuddy 614
            fillInTable(fromToDictionary, table, DictionaryValueType.DVT_STRING);
2104 ghuddy 615
         }
616
      }
617
 
2122 ghuddy 618
 
2118 ghuddy 619
      private static void fillInTable(ArrayList fromToDictionary, Word.Table table, DictionaryValueType valueType )
2104 ghuddy 620
      {
621
         int lastFromElementId = -1;
2118 ghuddy 622
         bool firstCellContent = true;
2104 ghuddy 623
         int row = 1;
624
         foreach (DictionaryEntry de in fromToDictionary)
625
         {
2106 ghuddy 626
            if (createWordDoc.abortCreationThread)
627
               return;
628
 
2104 ghuddy 629
            if ( ((EA.Element)de.Key).ElementID != lastFromElementId )
630
            {
631
               lastFromElementId = ((EA.Element)de.Key).ElementID;
632
               row++;
633
               table.Cell(row,1).Range.Text = ((EA.Element)de.Key).Name;
2118 ghuddy 634
               firstCellContent = true;
635
 
2122 ghuddy 636
               if (RM_Matrix.from.elementNotes)
2118 ghuddy 637
               {
2122 ghuddy 638
                  if (((EA.Element)de.Key).Notes != null && ((EA.Element)de.Key).Notes.Length > 0)
639
                  {
640
                     table.Cell(row,1).Range.Text += ((EA.Element)de.Key).Notes;
641
                  }
642
                  // Because we are including both the short description and the notes of the requirement
643
                  // in the cell, we need to discriminate them. We do this by bolding the short description,
644
                  // and reducing the font size of the notes to 8.
645
                  Word.Range wr = table.Cell(row,1).Range;
646
                  wr.Sentences[1].Font.Bold = 1;
647
                  for(int i=2; i<=wr.Sentences.Count; i++)
648
                     wr.Sentences[i].Font.Size = 8;
2118 ghuddy 649
               }
2104 ghuddy 650
            }
2122 ghuddy 651
 
2118 ghuddy 652
            if ((valueType == DictionaryValueType.DVT_EA_ELEMENT) && (((EA.Element)de.Value) != null))
2104 ghuddy 653
            {
2118 ghuddy 654
               if (firstCellContent)
2104 ghuddy 655
               {
2118 ghuddy 656
                  firstCellContent = false;
657
                  table.Cell(row,2).Range.Text = ((EA.Element)de.Value).Name;
658
               }
659
               else
660
               {
661
                  table.Cell(row,2).Range.Text += ((EA.Element)de.Value).Name;
662
               }
663
            }
664
            else if ((valueType == DictionaryValueType.DVT_STRING) && (((string)de.Value).Length > 0))
665
            {
666
               if (firstCellContent)
667
               {
668
                  firstCellContent = false;
2104 ghuddy 669
                  table.Cell(row,2).Range.Text = (string)de.Value;
670
               }
671
               else
672
               {
673
                  table.Cell(row,2).Range.Text += (string)de.Value;
674
               }
675
            }
676
            else
677
            {
2116 ghuddy 678
               if (EA_DocGenOptions.optionValue(EA_DocGenOptions.boolean_options_e.SUPPRESS_UN_ALLOCATED_RELATIONSHIP_WARNINGS) == false)
2104 ghuddy 679
               {
680
                  table.Cell(row,2).Range.Text = "Un-allocated relationship!";
681
                  table.Cell(row,2).Range.Font.Color = Word.WdColor.wdColorRed;
682
               }
683
            }
684
         }
685
      }
686
 
2122 ghuddy 687
 
2104 ghuddy 688
      /// <summary>
689
      /// This function will insert a relationship matrix table into the document, built from content
690
      /// specified in options that are provided in the notes section of the special element that
691
      /// has led to this function being called.
692
      /// 
693
      /// The style of this single table is that required for requirement to requirement traceability.
694
      /// Here, only a single table is generated, and the only elements in the left hand column will
695
      /// be those serialised to the document earlier on, and the content of the right hand column
696
      /// will be the parental requirements (all the way up to root requirements).
697
      /// </summary>
698
      /// <param name="EA_RelMatrix"></param>
2106 ghuddy 699
      private static void processRelationshipMatrixElementStyle2()
2104 ghuddy 700
      {
701
         int i;
702
         int tableNum = 0;
703
         Word.Table table = null;
704
 
705
         // Scan the fromPackage to find all the "from elements".
2122 ghuddy 706
         ElementAccumulator fromLister = new ElementAccumulator(RM_Matrix.from.elementTypes);
707
         EA_Utilities.findAndProcessPackageElements( fromPackage, fromLister, RM_Matrix.from.packageRecursion );
2104 ghuddy 708
 
2106 ghuddy 709
         if (createWordDoc.abortCreationThread)
710
            return;
711
 
2104 ghuddy 712
         // Remove all elements from the list that did not go to form content in the document
713
         // prior to this point in the document generation process.
714
         for (i=0; i<fromLister.Elements.Count; )
715
         {
2106 ghuddy 716
            if (createWordDoc.abortCreationThread)
717
               return;
718
 
2104 ghuddy 719
            if ( !processedElements.Contains( ((EA.Element)fromLister.Elements[i]).ElementID ) )
720
            {
721
               fromLister.Elements.RemoveAt(i);
722
               continue;
723
            }
724
            i++;
725
         }
726
 
2106 ghuddy 727
         if (createWordDoc.abortCreationThread)
728
            return;
729
 
2104 ghuddy 730
         // Sort the remaining "from elements"
731
         elementSortByName sorter = new elementSortByName();
732
         fromLister.Elements.Sort( sorter );
2106 ghuddy 733
 
734
         if (createWordDoc.abortCreationThread)
735
            return;
736
 
2104 ghuddy 737
         // Scan the toPackage to find all the "to elements".
738
         // Extract their element IDs into a new list.
2122 ghuddy 739
         ElementAccumulator toLister = new ElementAccumulator(RM_Matrix.to.elementTypes);
740
         EA_Utilities.findAndProcessPackageElements( toPackage, toLister, RM_Matrix.to.packageRecursion );
2104 ghuddy 741
         ArrayList acceptableParents = new ArrayList();
742
         foreach(EA.Element ele in toLister.Elements)
743
         {
2106 ghuddy 744
            if (createWordDoc.abortCreationThread)
745
               return;
746
 
2104 ghuddy 747
            acceptableParents.Add( ele.ElementID);
748
         }
749
 
2106 ghuddy 750
         if (createWordDoc.abortCreationThread)
751
            return;
752
 
2104 ghuddy 753
         // The list of from elements dictates the number of rows in our table.
754
         int numberOfFromToRows = fromLister.Elements.Count;
755
 
2122 ghuddy 756
         if (RM_Matrix.fromToTable.introText != null && RM_Matrix.fromToTable.introText.Length > 0)
2104 ghuddy 757
         {
2122 ghuddy 758
            Word.Range wr = TextualContent.appendAndSelectText( RM_Matrix.fromToTable.introText, EA_Constants.styleName_Body1 );
759
            object obj = string.Format("EA_DocGen Informational Comment - This table has been produced using the following options:\n\n{0}", RM_Element.Notes);
760
            createWordDoc.WordDocument.Comments.Add(wr, ref obj);
2104 ghuddy 761
         }
762
 
763
         // create the from-to table in the word doc
2122 ghuddy 764
         tableNum = TabularContent.Table_Create( RM_Matrix.fromToTable.title, true, numberOfFromToRows + 1, 2 );
2106 ghuddy 765
         table = createWordDoc.WordDocument.Tables[tableNum];
2104 ghuddy 766
 
2122 ghuddy 767
         TabularContent.Table_SetTableColumnTitle(table, RM_Matrix.from.columnTitle, 1);
768
         TabularContent.Table_SetTableColumnTitle(table, RM_Matrix.to.columnTitle, 2);
2104 ghuddy 769
 
770
         int row = 2;
771
         foreach(EA.Element ele in fromLister.Elements)
772
         {
2106 ghuddy 773
            if (createWordDoc.abortCreationThread)
774
               return;
775
 
2104 ghuddy 776
            table.Cell(row,1).Range.Text = ele.Name;
777
 
2122 ghuddy 778
            if (RM_Matrix.from.elementNotes && ele.Notes != null && ele.Notes.Length > 0)
2118 ghuddy 779
            {
780
               table.Cell(row,1).Range.Text += ele.Notes;
781
            }
782
 
2104 ghuddy 783
            StringBuilder sb = new StringBuilder();
784
 
785
            ArrayList parentsDiscovered = new ArrayList();
786
 
787
            // Find this requirement's parent (source) requirements
788
            elementParenthood(ele, ref acceptableParents, ref parentsDiscovered, ref sb);
789
 
790
            // if no source requirements found and user has opted for trimming, delete the table row
2122 ghuddy 791
            if (RM_Matrix.from.packageTrimming == true && sb.Length == 0)
2104 ghuddy 792
            {
2106 ghuddy 793
               TabularContent.Table_DeleteThisRow(table, row);
2104 ghuddy 794
               continue;
795
            }
796
 
797
            // fill in the right hand cell on this row of the table with the source requirement list
798
            table.Cell(row,2).Range.Text = sb.ToString();
799
            row++;
800
         }
801
 
802
      }
803
 
2122 ghuddy 804
 
2106 ghuddy 805
      private static void elementParenthood(EA.Element ele, ref ArrayList acceptableParents, ref ArrayList parentsDiscovered, ref StringBuilder sb)
2104 ghuddy 806
      {
807
         foreach(EA.Connector con in ele.Connectors)
808
         {
2106 ghuddy 809
            if (createWordDoc.abortCreationThread)
810
               return;
811
 
2104 ghuddy 812
            // ignore downwards direction, indicated by the client ID being equal to the element ID
813
            if (con.ClientID != ele.ElementID)
814
            {
815
               // if we have not already come across this upward path before...
816
               if (!parentsDiscovered.Contains(con.ClientID))
817
               {
818
                  parentsDiscovered.Add(con.ClientID);
819
 
2120 ghuddy 820
                  // if this parent is in the list of acceptable parents...
2104 ghuddy 821
                  if (acceptableParents.Contains(con.ClientID))
822
                  {
823
                     // get the parent element, add its name to our list, and ascend through the element
824
                     // using recursion.
2106 ghuddy 825
                     EA.Element client = Main.EA_Repository.GetElementByID(con.ClientID);
2104 ghuddy 826
                     if (client != null)
827
                     {
828
                        if (sb.Length > 0)
829
                           sb.Append("\n");
830
                        sb.Append(client.Name);
831
 
832
                        elementParenthood(client, ref acceptableParents, ref parentsDiscovered, ref sb);
833
                     }
834
                  }
835
               }
836
            }
837
         }
838
      }
839
 
2088 ghuddy 840
	}
841
}