Subversion Repositories DevTools

Rev

Rev 2102 | Rev 2106 | 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.Drawing;
3
using System.Collections;
2094 ghuddy 4
using System.Text;
2088 ghuddy 5
using System.ComponentModel;
6
using System.Windows.Forms;
7
using Word;
2092 ghuddy 8
using Microsoft.Office.Core;
2088 ghuddy 9
 
2092 ghuddy 10
 
2088 ghuddy 11
namespace EA_DocGen
12
{
13
 
14
 
15
   /// <summary>
16
   /// Summary description for createWordDoc.
17
   /// </summary>
18
   public class createWordDoc : System.Windows.Forms.Form
19
   {
20
      // Enterprise Architect Model related data
21
      private EA.Repository EA_Repository = null;
22
      private EA.Package EA_ParentPackage = null;
23
      private EA.Project EA_Project;
2094 ghuddy 24
 
2088 ghuddy 25
      private EA_Utilities EA_Utils = null;
26
 
2094 ghuddy 27
      private TabularContent TableUtils = null;
28
      private TextualContent TextUtils = null;
29
      private StyleContent   StyleUtils = null;
2104 ghuddy 30
      private DocSectionTracking DocSectionTracker = null;
2094 ghuddy 31
 
2088 ghuddy 32
      private bool oneShot_skipRootPackage = false;
2094 ghuddy 33
      private bool oneShot_skipRootElementHeading = false;
2088 ghuddy 34
 
2104 ghuddy 35
      private int processingLink = 0;
36
 
37
      private ArrayList processedElements = null;
38
 
2094 ghuddy 39
      // This data is designed to support unit test traceability. As such, it is only of real use
40
      // when making s/w design documents. It allows all non-private classes to be collected into
41
      // a list in order to generate a design-to-unit-test traceability table.
2104 ghuddy 42
      private ArrayList classesNeedingUnitTests = null;
2094 ghuddy 43
      private ArrayList classesWithUnitTests = null;
44
      private Word.Table utTraceabilityTable = null;
45
 
2088 ghuddy 46
      // MS-Office Word related data
47
      private Word.Application WordApp = null;
48
      private Word.Document WordDocument = null;
2094 ghuddy 49
 
2088 ghuddy 50
      private System.Windows.Forms.TextBox textBox_template;
51
      private System.Windows.Forms.Button button_browse_template;
52
      private System.Windows.Forms.TextBox textBox_output_file;
53
      private System.Windows.Forms.Button button_browse_output_file;
54
      private System.Windows.Forms.Button button_cancel;
55
      private System.Windows.Forms.Button button_generate;
56
      private System.Windows.Forms.Button button_view_output;
57
      private System.Windows.Forms.Label label1;
58
      private System.Windows.Forms.Label label2;
59
      private System.Windows.Forms.TextBox textBox_progress;
60
      private System.Windows.Forms.Label label3;
61
      private System.Windows.Forms.CheckBox checkBox_WordVisibility;
62
      /// <summary>
63
      /// Required designer variable.
64
      /// </summary>
65
      private System.ComponentModel.Container components = null;
66
 
67
      public createWordDoc(EA.Repository theRepository, EA.Package theParentPackage, EA_Utilities theEA_Utils)
68
      {
69
         //
70
         // Required for Windows Form Designer support
71
         //
72
         InitializeComponent();
73
 
74
         EA_Repository    = theRepository;
75
         EA_ParentPackage = theParentPackage;
76
         EA_Project       = EA_Repository.GetProjectInterface();
77
 
78
         EA_Utils         = theEA_Utils;
79
 
2104 ghuddy 80
         DocSectionTracker = new DocSectionTracking();
2094 ghuddy 81
 
2104 ghuddy 82
         TableUtils        = new TabularContent(WordApp, WordDocument, EA_Utils);
83
         TextUtils         = new TextualContent(WordApp, WordDocument, DocSectionTracker);
84
         StyleUtils        = new StyleContent(WordApp, WordDocument);
2094 ghuddy 85
 
2104 ghuddy 86
 
2088 ghuddy 87
 
88
         WordApp = new Word.Application();
89
      }
90
 
2094 ghuddy 91
 
2088 ghuddy 92
      /// <summary>
93
      /// Clean up any resources being used.
94
      /// </summary>
95
      protected override void Dispose( bool disposing )
96
      {
97
         if( disposing )
98
         {
99
            if(components != null)
100
            {
101
               components.Dispose();
102
            }
103
         }
104
         base.Dispose( disposing );
105
      }
106
 
107
 
108
 
109
 
110
      #region Windows Form Designer generated code
111
      /// <summary>
112
      /// Required method for Designer support - do not modify
113
      /// the contents of this method with the code editor.
114
      /// </summary>
115
      private void InitializeComponent()
116
      {
117
         this.textBox_template = new System.Windows.Forms.TextBox();
118
         this.button_browse_template = new System.Windows.Forms.Button();
119
         this.textBox_output_file = new System.Windows.Forms.TextBox();
120
         this.button_browse_output_file = new System.Windows.Forms.Button();
121
         this.button_cancel = new System.Windows.Forms.Button();
122
         this.button_generate = new System.Windows.Forms.Button();
123
         this.button_view_output = new System.Windows.Forms.Button();
124
         this.label1 = new System.Windows.Forms.Label();
125
         this.label2 = new System.Windows.Forms.Label();
126
         this.textBox_progress = new System.Windows.Forms.TextBox();
127
         this.label3 = new System.Windows.Forms.Label();
128
         this.checkBox_WordVisibility = new System.Windows.Forms.CheckBox();
129
         this.SuspendLayout();
130
         // 
131
         // textBox_template
132
         // 
133
         this.textBox_template.Location = new System.Drawing.Point(16, 40);
134
         this.textBox_template.Name = "textBox_template";
135
         this.textBox_template.Size = new System.Drawing.Size(592, 22);
136
         this.textBox_template.TabIndex = 0;
137
         this.textBox_template.Text = "";
138
         this.textBox_template.TextChanged += new System.EventHandler(this.textBox_template_TextChanged);
139
         // 
140
         // button_browse_template
141
         // 
142
         this.button_browse_template.Location = new System.Drawing.Point(616, 40);
143
         this.button_browse_template.Name = "button_browse_template";
144
         this.button_browse_template.Size = new System.Drawing.Size(80, 23);
145
         this.button_browse_template.TabIndex = 1;
146
         this.button_browse_template.Text = "Browse";
147
         this.button_browse_template.Click += new System.EventHandler(this.button_browse_template_Click);
148
         // 
149
         // textBox_output_file
150
         // 
151
         this.textBox_output_file.Location = new System.Drawing.Point(16, 112);
152
         this.textBox_output_file.Name = "textBox_output_file";
153
         this.textBox_output_file.Size = new System.Drawing.Size(592, 22);
154
         this.textBox_output_file.TabIndex = 2;
155
         this.textBox_output_file.Text = "";
156
         this.textBox_output_file.TextChanged += new System.EventHandler(this.textBox_output_file_TextChanged);
157
         // 
158
         // button_browse_output_file
159
         // 
160
         this.button_browse_output_file.Location = new System.Drawing.Point(616, 112);
161
         this.button_browse_output_file.Name = "button_browse_output_file";
162
         this.button_browse_output_file.Size = new System.Drawing.Size(80, 24);
163
         this.button_browse_output_file.TabIndex = 3;
164
         this.button_browse_output_file.Text = "Browse";
165
         this.button_browse_output_file.Click += new System.EventHandler(this.button_browse_output_file_Click);
166
         // 
167
         // button_cancel
168
         // 
169
         this.button_cancel.Location = new System.Drawing.Point(616, 384);
170
         this.button_cancel.Name = "button_cancel";
171
         this.button_cancel.Size = new System.Drawing.Size(80, 23);
172
         this.button_cancel.TabIndex = 4;
173
         this.button_cancel.Text = "Close";
174
         this.button_cancel.Click += new System.EventHandler(this.button_cancel_Click);
175
         // 
176
         // button_generate
177
         // 
178
         this.button_generate.Location = new System.Drawing.Point(496, 384);
179
         this.button_generate.Name = "button_generate";
180
         this.button_generate.Size = new System.Drawing.Size(96, 24);
181
         this.button_generate.TabIndex = 5;
182
         this.button_generate.Text = "Generate";
183
         this.button_generate.Click += new System.EventHandler(this.button_generate_Click);
184
         // 
185
         // button_view_output
186
         // 
2098 ghuddy 187
         this.button_view_output.Enabled = false;
2088 ghuddy 188
         this.button_view_output.Location = new System.Drawing.Point(376, 384);
189
         this.button_view_output.Name = "button_view_output";
190
         this.button_view_output.Size = new System.Drawing.Size(96, 23);
191
         this.button_view_output.TabIndex = 6;
192
         this.button_view_output.Text = "View Output";
193
         this.button_view_output.Click += new System.EventHandler(this.button_view_output_Click);
194
         // 
195
         // label1
196
         // 
197
         this.label1.Location = new System.Drawing.Point(16, 16);
198
         this.label1.Name = "label1";
199
         this.label1.Size = new System.Drawing.Size(224, 23);
200
         this.label1.TabIndex = 7;
201
         this.label1.Text = "Input Template or Document Name";
202
         // 
203
         // label2
204
         // 
205
         this.label2.Location = new System.Drawing.Point(16, 88);
206
         this.label2.Name = "label2";
207
         this.label2.Size = new System.Drawing.Size(280, 23);
208
         this.label2.TabIndex = 8;
209
         this.label2.Text = "Output Document Name";
210
         // 
211
         // textBox_progress
212
         // 
213
         this.textBox_progress.Location = new System.Drawing.Point(16, 184);
214
         this.textBox_progress.Multiline = true;
215
         this.textBox_progress.Name = "textBox_progress";
216
         this.textBox_progress.ReadOnly = true;
217
         this.textBox_progress.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
218
         this.textBox_progress.Size = new System.Drawing.Size(680, 168);
219
         this.textBox_progress.TabIndex = 9;
220
         this.textBox_progress.Text = "";
221
         // 
222
         // label3
223
         // 
224
         this.label3.Location = new System.Drawing.Point(16, 152);
225
         this.label3.Name = "label3";
226
         this.label3.TabIndex = 10;
227
         this.label3.Text = "Progress";
228
         // 
229
         // checkBox_WordVisibility
230
         // 
231
         this.checkBox_WordVisibility.Location = new System.Drawing.Point(16, 384);
232
         this.checkBox_WordVisibility.Name = "checkBox_WordVisibility";
233
         this.checkBox_WordVisibility.Size = new System.Drawing.Size(256, 24);
234
         this.checkBox_WordVisibility.TabIndex = 17;
235
         this.checkBox_WordVisibility.Text = "Show MS-WORD During Construction";
236
         // 
237
         // createWordDoc
238
         // 
239
         this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);
240
         this.ClientSize = new System.Drawing.Size(712, 432);
241
         this.Controls.Add(this.checkBox_WordVisibility);
242
         this.Controls.Add(this.label3);
243
         this.Controls.Add(this.textBox_progress);
244
         this.Controls.Add(this.textBox_output_file);
245
         this.Controls.Add(this.textBox_template);
246
         this.Controls.Add(this.label2);
247
         this.Controls.Add(this.label1);
248
         this.Controls.Add(this.button_view_output);
249
         this.Controls.Add(this.button_generate);
250
         this.Controls.Add(this.button_cancel);
251
         this.Controls.Add(this.button_browse_output_file);
252
         this.Controls.Add(this.button_browse_template);
253
         this.Name = "createWordDoc";
254
         this.Text = "createWordDoc";
255
         this.Closing += new System.ComponentModel.CancelEventHandler(this.createWordDoc_Closing);
256
         this.ResumeLayout(false);
257
 
258
      }
259
      #endregion
260
 
261
 
262
      #region Message handlers
263
      private void button_view_output_Click(object sender, System.EventArgs e)
264
      {
265
         if (WordApp != null)
266
         {
267
            WordApp.Visible = true;
268
         }
2094 ghuddy 269
         button_view_output.Enabled = false;
2088 ghuddy 270
      }
271
 
272
 
273
 
274
 
275
      private void button_generate_Click(object sender, System.EventArgs e)
276
      {
277
         if (this.textBox_template.Text.Length > 0)
278
         {
279
            if (this.textBox_output_file.Text.Length > 0)
280
            {
2094 ghuddy 281
               button_generate.Enabled = false;
2088 ghuddy 282
               createTheWordDoc();
283
            }
284
            else
285
            {
286
               MessageBox.Show("Error - must specify an output file");
287
            }
288
         }
289
         else
290
         {
291
            MessageBox.Show("Error - must specify an input template file");
292
         }
293
      }
294
 
295
      private void button_cancel_Click(object sender, System.EventArgs e)
296
      {
297
         this.Close();   
298
      }
299
 
300
      private void button_browse_template_Click(object sender, System.EventArgs e)
301
      {
302
         OpenFileDialog dialog = new OpenFileDialog();
303
         dialog.Filter = "Word Files (*.doc;*.dot)|*.doc;*.dot|All files(*.*)|*.*";
304
         dialog.FilterIndex = 1;
305
         dialog.ShowDialog();
306
         this.textBox_template.Text = dialog.FileName;
307
 
308
      }
309
 
310
      private void button_browse_output_file_Click(object sender, System.EventArgs e)
311
      {
312
         OpenFileDialog dialog = new OpenFileDialog();
313
         dialog.Filter = "Word Files (*.doc;*.dot)|*.doc;*.dot|All files(*.*)|*.*";
314
         dialog.FilterIndex = 1;
315
         dialog.CheckFileExists = false;
316
         dialog.ShowDialog();
317
         this.textBox_output_file.Text = dialog.FileName;
318
      }
319
 
320
      private void textBox_template_TextChanged(object sender, System.EventArgs e)
321
      {
322
 
323
      }
324
 
325
      private void textBox_output_file_TextChanged(object sender, System.EventArgs e)
326
      {
327
 
328
      }
329
 
330
      private void createWordDoc_Closing(object sender, System.ComponentModel.CancelEventArgs e)
331
      {
332
         if (WordApp != null)
333
         {
334
            // try-catch just in case user closed the application themselves whilst viewing the
335
            // generated output document
336
            try 
337
            {
338
               object nothing = Type.Missing;
339
               object notTrue = false;
340
 
341
               WordApp.Application.Quit( ref notTrue, ref nothing, ref nothing);
342
            }
343
            catch (Exception createWordDoc_Closing_exception)
344
            {
345
               // dummy statement
346
               String s = createWordDoc_Closing_exception.Message;
347
            }
348
         }
349
      }
350
 
351
      #endregion
352
 
353
 
354
      #region word document generation code
355
 
356
 
357
 
2094 ghuddy 358
 
2088 ghuddy 359
      /// <summary>
360
      /// Displays progress of the document generation in the createWordDocument dialog
361
      /// </summary>
362
      /// <param name="prefix"></param>
363
      /// <param name="EA_string"></param>
364
      private void displayProgress(string prefix, string EA_string)
365
      {
366
         textBox_progress.AppendText( prefix + EA_string + "\r\n" );
367
 
368
         // Display to the output tab as well - as a longer term record of what happened
2094 ghuddy 369
         StringBuilder sb = new StringBuilder("");
2104 ghuddy 370
 
371
         DocSectionTracker.appendHeadingNumber(ref sb);
372
 
2094 ghuddy 373
         while (sb.Length < 30)
374
            sb.Append(" ");
2088 ghuddy 375
 
2094 ghuddy 376
         sb.Append(prefix);
377
         sb.Append(EA_string);
378
 
379
         EA_Repository.WriteOutput( Main.GUI_OUTPUT_TAB_NAME, sb.ToString(), 0);
2088 ghuddy 380
      }
381
 
382
 
383
      /// <summary>
384
      /// This method takes the specified EA diagram element and puts the diagram image
385
      /// into the clipboard from where it can be pasted into the word document. After
386
      /// pasting it into the document, it sets the style and other aspects of the image.
387
      /// </summary>
388
      /// <param name="theDiagram"></param>
389
      private void appendAndSelectDiagramViaClipboard(EA.Diagram theDiagram)
390
      {
2104 ghuddy 391
         // NOTE: diagrams only use one stereotype, not a list of them, so dont use StereotypeEx field
392
         if (  EA_Utils.options.opt_ConsiderAPIDiagramsOnly 
393
            && !theDiagram.Stereotype.Equals("API") )
394
         {
395
            displayProgress( "SKIPPED DIAGRAM: ", theDiagram.Name.ToString() );
396
         }
2088 ghuddy 397
         // open the diagram in EA and copy it's image to the clipboard
2104 ghuddy 398
         else if (EA_Project.PutDiagramImageOnClipboard(theDiagram.DiagramGUID,0))
2088 ghuddy 399
         {
2094 ghuddy 400
            object startLocation;
401
            object endLocation;
402
 
2098 ghuddy 403
            TextUtils.appendDescription( theDiagram.Notes, EA_Utils );
404
 
2088 ghuddy 405
            // create a range at the end of the document
406
            startLocation = WordDocument.Content.End;
407
            WordDocument.Content.InsertParagraphAfter();
408
            endLocation = WordDocument.Content.End;
2094 ghuddy 409
            Word.Range WordRange = WordDocument.Range(ref startLocation, ref endLocation);
2088 ghuddy 410
            object direction = Word.WdCollapseDirection.wdCollapseEnd;
411
            WordRange.Collapse(ref direction);  // collapse prevents existing content being replaced
412
 
413
            // Get ready for the diagram paste and the formatting we want to do on it with the
414
            // selection object.
2094 ghuddy 415
            TextUtils.SelectInsertionPointAtEndOfDocument();
2088 ghuddy 416
 
417
            // Paste the diagram into the document
418
            WordRange.Paste();           
419
 
420
            // Set style of the diagram to "Normal" so that it can occupy space all the way to the left margin
2094 ghuddy 421
            object l_style = EA_Constants.styleName_Normal;
2088 ghuddy 422
            endLocation = WordDocument.Content.End;
423
            WordRange = WordDocument.Range(ref startLocation, ref endLocation);
424
            WordRange.set_Style(ref l_style);
425
 
426
            // Center the diagram on the page
427
            object unit = Word.WdUnits.wdLine;
428
            object missing = Type.Missing;
429
            object count = 1;
430
            WordApp.Selection.MoveDown( ref unit, ref count, ref missing);
431
            WordApp.Selection.ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter;
432
 
433
            // Add a caption
434
            WordDocument.Content.InsertParagraphAfter();
2094 ghuddy 435
            TextUtils.SelectInsertionPointAtEndOfDocument();         
2088 ghuddy 436
            object Label = "Figure";
437
            object Title = Type.Missing;
438
            object TitleAutoText = Type.Missing;
439
            object Position = Word.WdCaptionPosition.wdCaptionPositionAbove;
440
            object ExcludeLabel = 0;
441
            WordApp.Selection.InsertCaption( ref Label, ref Title, ref TitleAutoText, ref Position, ref ExcludeLabel);
442
            WordApp.Selection.TypeText( ": " + theDiagram.Name.ToString());
443
            WordApp.Selection.ParagraphFormat.Alignment = Word.WdParagraphAlignment.wdAlignParagraphCenter;
444
 
445
            // experimental code to create a bookmark for the figure caption
446
            //WordDocument.Paragraphs[ WordDocument.Paragraphs.Count ].Range.Select();
447
            //object lastParaRange = WordDocument.Paragraphs[ WordDocument.Paragraphs.Count ].Range;
448
            //string bookmarkName = theDiagram.Name;
449
            //bookmarkName = bookmarkName.Replace(' ', '_');
450
            //WordDocument.Bookmarks.Add( bookmarkName, ref lastParaRange );
451
 
452
            // Close the diagram in EA
453
            EA_Repository.CloseDiagram(theDiagram.DiagramID);
2104 ghuddy 454
 
455
            displayProgress( "DIAGRAM: ", theDiagram.Name.ToString() );
2088 ghuddy 456
         }
457
      }
458
 
459
 
2094 ghuddy 460
      #region special element processing functions (link elements, table and text elements, etc)
2088 ghuddy 461
      /// <summary>
462
      /// This is an attempt to create a table similar in style to those made by the ERG doc template macros.
463
      /// It is not exaclty that same though, and further work could be done to align it more precisely.
464
      /// </summary>
465
      /// <param name="tableTitle"></param>
466
      /// <param name="numRows"></param>
467
      /// <param name="numCols"></param>
468
      /// <returns></returns>
2094 ghuddy 469
 
2088 ghuddy 470
      /// <summary>
471
      /// This function process a package link element, parsing each linked package by the
472
      /// parse_package() recursive function.
473
      /// </summary>
474
      /// <param name="theElement"></param>
475
      /// <param name="recurse_level"></param>
476
      private void processPackageLink(EA.Element theElement, int recurse_level)
477
      {
478
         string [] EA_DocGenPkgLnk = null;
479
         string delimStr = "\r\n";
480
         char [] delim = delimStr.ToCharArray();
481
         EA_DocGenPkgLnk = theElement.Notes.ToString().Split(delim,100);
482
         string linkedName = "";
483
 
484
         foreach(string s in EA_DocGenPkgLnk)
485
         {
486
            if (s.Length > 0 && s != "\n" && s != "\r")
487
            {
488
               if (s == "skiproot")
489
               {
490
                  oneShot_skipRootPackage = true;
491
               }
492
               else if (s[0] == '{')
493
               {
494
                  EA.Package theFoundPackage = EA_Utils.EA_Finder.findPackageInRepositoryByGUID(s);
495
                  if (theFoundPackage != null)
496
                  {
497
                     parse_package(theFoundPackage, recurse_level);
498
                  }
499
                  else
500
                  {
501
                     MessageBox.Show("WARNING - Could not find linked package : " + linkedName );
502
                  }
503
               }
504
               else
505
               {
506
                  linkedName = s;
507
               }            
508
            }
509
         }
510
      }
511
 
512
 
513
      /// <summary>
514
      /// This function process a diagram link element, using the appendAndSelectDiagramViaClipboard()
515
      /// for each linked diagram.
516
      /// </summary>
517
      /// <param name="theElement"></param>
518
      private void processDiagramLink(EA.Element theElement)
519
      {
520
         string [] EA_DocGenDiagLnk = null;
521
         string delimStr = "\r\n";
522
         char [] delim = delimStr.ToCharArray();
523
         EA_DocGenDiagLnk = theElement.Notes.ToString().Split(delim,100);
524
         string linkedName = "";
525
 
526
         foreach(string s in EA_DocGenDiagLnk)
527
         {
528
            if (s.Length > 0 && s != "\n" && s != "\r" )
529
            {
530
               if (s[0] == '{')
531
               {
532
                  EA.Diagram theFoundDiagram = EA_Utils.EA_Finder.findDiagramInRepositoryByGUID(s);
533
                  if (theFoundDiagram != null)
534
                  {
535
                     appendAndSelectDiagramViaClipboard( theFoundDiagram );
536
                  }
537
                  else 
538
                  {
539
                     MessageBox.Show("WARNING - Could not find linked diagram : " + linkedName );
540
                  }
541
               }
542
               else
543
               {
544
                  linkedName = s;
545
               }            
546
            }
547
         }         
548
      }
549
 
550
 
551
      /// <summary>
552
      /// This function process an element link element, parsing each linked element by the
553
      /// parse_element() recursive function.
554
      /// </summary>
555
      /// <param name="theElement"></param>
556
      /// <param name="recurse_level"></param>
557
      private void processElementLink(EA.Element theElement, int recurse_level )
558
      {
559
         string [] EA_DocGenEleLnk = null;
560
         string delimStr = "\r\n";
561
         char [] delim = delimStr.ToCharArray();
562
         EA_DocGenEleLnk = theElement.Notes.ToString().Split(delim,100);
563
         string linkedName = "";
564
 
565
         foreach(string s in EA_DocGenEleLnk)
566
         {
567
            if (s.Length > 0 && s != "\n" && s != "\r")
568
            {
2094 ghuddy 569
               if (s == "skiproot")
2088 ghuddy 570
               {
2094 ghuddy 571
                  oneShot_skipRootElementHeading = true;
572
               }
573
               else if ( s[0] == '{')
574
               {
2088 ghuddy 575
                  EA.Element theFoundElement = EA_Utils.EA_Finder.findElementInRepositoryByGUID(s);
576
                  if (theFoundElement != null)
577
                  {
578
                     parse_element( theFoundElement, recurse_level );
579
                  }
580
                  else 
581
                  {
582
                     MessageBox.Show("WARNING - Could not find linked element : " + linkedName );
583
                  }
584
               }
585
               else
586
               {
587
                  linkedName = s;
588
               }            
589
            }
590
         }         
591
      }
592
 
593
 
594
      /// <summary>
2104 ghuddy 595
      /// This method is recursive and searches a model structure to find a match to any 
596
      /// of the names given in a list. Matched package structure is then parsed for
597
      /// document content generation.
2088 ghuddy 598
      /// </summary>
2104 ghuddy 599
      /// <param name="parentPackage"></param>
600
      /// <param name="thePackage"></param>
2088 ghuddy 601
      /// <param name="recurse_level"></param>
2104 ghuddy 602
      /// <param name="skipRoots"></param>
603
      /// <param name="names"></param>
604
      private void processNameLinkPackage(EA.Package parentPackage, EA.Package thePackage, int recurse_level, bool skipRoots, ref ArrayList names)
2088 ghuddy 605
      {
2104 ghuddy 606
         // search for the package name in the names[] list
607
         int i = 0;
608
         bool found = false;
609
         foreach (string name in names)
2088 ghuddy 610
         {
2104 ghuddy 611
            // users can specify parent\child in a name to help narrow down exactly what package they 
612
            // are looking for so deal with that, but the parent\ part is optional.
613
            int splitpos = name.IndexOf('\\',0);
614
            if (splitpos >= 0)
2088 ghuddy 615
            {
2104 ghuddy 616
               if (parentPackage != null)
2088 ghuddy 617
               {
2104 ghuddy 618
                  if (name.Substring(0,splitpos).Equals(parentPackage.Name))
2088 ghuddy 619
                  {
2104 ghuddy 620
                     if (name.Substring(splitpos+1).Equals(thePackage.Name))
621
                     {
622
                        found = true;
623
                        break;
624
                     }
2088 ghuddy 625
                  }
626
               }
2104 ghuddy 627
               else
2088 ghuddy 628
               {
2104 ghuddy 629
                  if (name.Substring(splitpos+1).Equals(thePackage.Name))
2088 ghuddy 630
                  {
2104 ghuddy 631
                     found = true;
2088 ghuddy 632
                     break;
633
                  }
634
               }
2104 ghuddy 635
            }
636
            else
637
            {
638
               if (name.Equals(thePackage.Name))
2088 ghuddy 639
               {
2104 ghuddy 640
                  found = true;
641
                  break;
2088 ghuddy 642
               }
2104 ghuddy 643
            }
644
            i++;
645
         }
2100 ghuddy 646
 
2104 ghuddy 647
         if (found)
648
         {
649
            // remove the found name, arm the skiproot mechanism if needed, and parse the package
650
            names.RemoveAt(i);
651
            if (skipRoots == true)
652
               oneShot_skipRootPackage = true;
2100 ghuddy 653
 
2104 ghuddy 654
            parse_package(thePackage, recurse_level);
655
         }
656
         else if (names.Count > 0)  // any names left to process?
657
         {
658
            // recurse for each of this packages sub-packages
659
            foreach(EA.Package subPackage in thePackage.Packages)
660
            {
661
               processNameLinkPackage(thePackage, subPackage, recurse_level, skipRoots, ref names);                        
662
            }         
663
         }
664
      }
2100 ghuddy 665
 
2104 ghuddy 666
      private void processNameLink(EA.Element theElement, int recurse_level )
667
      {
668
         string delimStr = "\r\n";
669
         char [] delim = delimStr.ToCharArray();
670
         string [] EA_DocGenNameLnk = theElement.Notes.ToString().Split(delim,100);
2100 ghuddy 671
 
2104 ghuddy 672
         string linkedName = "";
673
         bool gotLinkedName = false;
674
 
675
         ArrayList names = new ArrayList();
676
 
677
         EA.Package theFoundPackage = null;
678
 
679
         bool skipRoots = false;
680
 
681
         // search through the option strings
682
         foreach(string s in EA_DocGenNameLnk)
683
         {
684
            if (s.Length > 0 && s != "\n" && s != "\r")
685
            {
686
               if (s == "skiproot")
687
               {
688
                  skipRoots = true;
2100 ghuddy 689
               }
2104 ghuddy 690
               else if (s[0] == '{')  // is it a GUID?
2100 ghuddy 691
               {
2104 ghuddy 692
                  // find the package by its GUID
693
                  theFoundPackage = EA_Utils.EA_Finder.findPackageInRepositoryByGUID(s);
2100 ghuddy 694
               }
2104 ghuddy 695
               else if (s.StartsWith("package="))
2088 ghuddy 696
               {
2104 ghuddy 697
                  // add the users named package to our list of names
698
                  names.Add( s.Substring(8, s.Length - 8) );
2088 ghuddy 699
               }
2104 ghuddy 700
               else if (gotLinkedName == false)
701
               {
702
                  // capture name of package refered to by the GUID - this is only for diagnostic purposes
703
                  gotLinkedName = true;
704
                  linkedName = s;
705
               }            
2088 ghuddy 706
            }
2104 ghuddy 707
         }  
708
 
709
         // If the GUID was resolved...
710
         if (theFoundPackage != null)
711
         {
712
            processNameLinkPackage(null, theFoundPackage, recurse_level, skipRoots, ref names);
2088 ghuddy 713
 
2104 ghuddy 714
            if (names.Count > 0)
2088 ghuddy 715
            {
2104 ghuddy 716
               StringBuilder sb = new StringBuilder();
717
               sb.Append("WARNING - Could not find named package(s)\n");
718
               sb.Append("within name link: ");
719
               sb.Append(linkedName);
720
               sb.Append("\n\nProblem package= directives are:\n");
721
               foreach(String s in names)
2100 ghuddy 722
               {
2104 ghuddy 723
                  sb.Append("\n");
724
                  sb.Append(s);
2100 ghuddy 725
               }
2104 ghuddy 726
               MessageBox.Show(sb.ToString());
2088 ghuddy 727
            }
728
         }
729
         else
730
         {
2104 ghuddy 731
            MessageBox.Show("WARNING - Could not find linked package : " + linkedName );
2088 ghuddy 732
         }
733
      }
734
 
735
      /// <summary>
2104 ghuddy 736
      /// This function processes a name link element. These are elements that point
737
      /// (using a GUID) to a package, and the user has specified text names of sub-packages
738
      /// within the package that they wish to have processed for document generation.
739
      /// This is a useful way of getting content when you cannot be sure that the GUIDs
740
      /// of the packages you want will remain constant (eg. when re-using content from
741
      /// a reqpro import (for doc gen purposes)).
2094 ghuddy 742
      /// </summary>
743
      /// <param name="theElement"></param>
744
      /// <param name="recurse_level"></param>
745
      private void processTestLink(EA.Element theElement, int recurse_level )
746
      {
747
         string [] EA_DocGenEleLnk = null;
748
         string delimStr = "\r\n";
749
         char [] delim = delimStr.ToCharArray();
750
         EA_DocGenEleLnk = theElement.Notes.ToString().Split(delim,100);
751
         string linkedName = "";
752
 
753
         foreach(string s in EA_DocGenEleLnk)
754
         {
755
            if (s.Length > 0 && s != "\n" && s != "\r")
756
            {
757
               if ( s[0] == '{')
758
               {
759
                  try
760
                  {
761
                     // try to find the GUID as a package
762
                     EA.Package theFoundPackage = EA_Utils.EA_Finder.findPackageInRepositoryByGUID(s);
763
                     if (theFoundPackage != null)
2104 ghuddy 764
                        TextUtils.appendUnitTestSuite(theFoundPackage, recurse_level, ref classesWithUnitTests, ref EA_Utils);
2094 ghuddy 765
                     else 
766
                     {
767
                        // try to find the GUID as an element
768
                        EA.Element theFoundElement = EA_Utils.EA_Finder.findElementInRepositoryByGUID(s);
769
                        if (theFoundElement != null)
2104 ghuddy 770
                           TextUtils.appendUnitTestSuite(theFoundElement, recurse_level, ref classesWithUnitTests, ref EA_Utils);
2094 ghuddy 771
                        else 
772
                           MessageBox.Show("WARNING - Could not find linked element : " + linkedName );
773
                     }
774
                  }
775
                  catch 
776
                  {
777
                     // try to find the GUID as an element
778
                     EA.Element theFoundElement = EA_Utils.EA_Finder.findElementInRepositoryByGUID(s);
779
                     if (theFoundElement != null)
2104 ghuddy 780
                        TextUtils.appendUnitTestSuite(theFoundElement, recurse_level, ref classesWithUnitTests, ref EA_Utils);
2094 ghuddy 781
                     else 
782
                        MessageBox.Show("WARNING - Could not find linked element : " + linkedName );
783
                  }
784
               }
785
               else
786
               {
787
                  linkedName = s;
788
               }            
789
            }
790
         }         
791
      }
792
 
793
 
794
      private void processTestTraceability( EA.Element theElement, int recurse_level )
795
      {
2104 ghuddy 796
         if (classesNeedingUnitTests.Count > 0)
2094 ghuddy 797
         {
798
            if (theElement.Notes.Length > 0)
799
            {
800
               TextUtils.appendAndSelectText( theElement.Notes, EA_Constants.styleName_Body1);
801
            }
802
            int tableNum = TableUtils.Table_Create("Design Element to Unit Test Suite Traceability", 2, 2);
803
            utTraceabilityTable = WordDocument.Tables[tableNum];
804
 
805
            TableUtils.Table_SetTableColumnTitle(utTraceabilityTable, "Design Element (class)", 1);
806
            TableUtils.Table_SetTableColumnTitle(utTraceabilityTable, "Test Suite", 2);
807
         }
808
      }
809
 
810
 
811
      private void completeTestTraceability()
812
      {
813
         if (utTraceabilityTable != null)
814
         {
2104 ghuddy 815
            int numClassesRemaining = classesNeedingUnitTests.Count;
2094 ghuddy 816
            int row = 2;
2104 ghuddy 817
            foreach(int elementId in classesNeedingUnitTests)
2094 ghuddy 818
            {
819
               EA.Element theElement = EA_Repository.GetElementByID( elementId );
820
               if (theElement != null)
821
               {
822
                  utTraceabilityTable.Cell(row,1).Range.Text = theElement.Name;
823
 
824
                  if (classesWithUnitTests.Contains( elementId ))
825
                  {
826
                     utTraceabilityTable.Cell(row,2).Range.Text = TextUtils.testSuiteName(theElement);
827
                  }
828
                  else
829
                  {
830
                     utTraceabilityTable.Cell(row,2).Range.Text = "Missing tests!";
831
                     utTraceabilityTable.Cell(row,2).Range.Font.Color = Word.WdColor.wdColorRed;
832
                  }
833
               }
834
 
835
               numClassesRemaining--;
836
               if (numClassesRemaining > 0)
837
               {
838
                  TableUtils.Table_InsertNewRowAfterThisRow(utTraceabilityTable, row);
839
                  row++;
840
               }
841
            }
842
         }
843
      }
844
 
845
      #endregion
846
 
847
      #region special section processing functions (references, terminology, etc)
2088 ghuddy 848
      /// <summary>
849
      /// This function processes elements as if they represented document references for
850
      /// the References section of a document.
851
      /// </summary>
852
      /// <param name="thePackage"></param>
853
      private void createReferencesSection(EA.Package thePackage)
854
      {
855
         foreach(EA.Element theElement in thePackage.Elements)
856
         {
857
            // Here we want to apply the special ERG template styles for each reference
858
            // item.
2094 ghuddy 859
            TextUtils.appendAndSelectText( theElement.Name.ToString(), EA_Constants.styleName_RefListNum );
860
            TextUtils.appendAndSelectText( theElement.Notes.ToString(), EA_Constants.styleName_RefListText );
2088 ghuddy 861
         }
862
      }
863
 
864
 
2104 ghuddy 865
      private void createTerminologySection(EA.Package thePackage, int recurse_level)
2088 ghuddy 866
      {
867
         // Use local package elements as source of glossary, but if none are present, resort to using
868
         // the project glossary in the repository 
869
         int numItems = thePackage.Elements.Count;
870
         if (numItems == 0)
871
         {
872
            numItems = EA_Repository.Terms.Count;
873
            // Create a table
2094 ghuddy 874
            int tableNum = TableUtils.Table_Create("Terminology", numItems+1, 2);
2088 ghuddy 875
            Word.Table table = WordDocument.Tables[tableNum];
876
            object center = Word.WdParagraphAlignment.wdAlignParagraphCenter;
2094 ghuddy 877
 
878
            TableUtils.Table_SetTableColumnTitle(table, "Term", 1);
879
            TableUtils.Table_SetTableColumnTitle(table, "Definition", 2);
2088 ghuddy 880
            table.Columns[1].SetWidth(100, Word.WdRulerStyle.wdAdjustSameWidth );
881
            int row = 2;
2104 ghuddy 882
            // inject the glossary into the table
883
            foreach(EA.Term theTerm in EA_Repository.Terms)
2088 ghuddy 884
            {
2104 ghuddy 885
               table.Cell(row,1).Range.Text = theTerm.Term;
886
               table.Cell(row,2).Range.Text = theTerm.Meaning;
887
               row++;
888
            }
889
         }
890
         else
891
         {
892
            // scan content of terminology package - allow user to specify tables, text, package links,
893
            // and diagram links.
894
            ArrayList infoItems = new ArrayList();
895
            foreach(EA.Element theElement in thePackage.Elements)
896
            {
897
               if (theElement.Name.StartsWith(EA_Constants.EA_DocGenTable))
2088 ghuddy 898
               {
2104 ghuddy 899
                  TableUtils.processTableElement( theElement, recurse_level);
2088 ghuddy 900
               }
2104 ghuddy 901
               else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenPackageLink))
902
               {
903
                  processingLink++;
904
                  processPackageLink( theElement, recurse_level );
905
                  processingLink--;
906
               }
907
               else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenText))
908
               {
909
                  TextUtils.appendAndSelectText( theElement.Notes.ToString(), EA_Constants.styleName_Body1 );
910
               }
911
               else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenDiagramLink))
912
               {
913
                  processingLink++;
914
                  processDiagramLink( theElement );
915
                  processingLink--;
916
               }
917
               else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenElementLink))
918
               {
919
                  processingLink++;
920
                  processElementLink( theElement, recurse_level );
921
                  processingLink--;
922
               }
923
               else if (!theElement.Name.StartsWith(EA_Constants.EA_DocGenBaseName)   // ignore all other special EA_DocGen elements
924
                  || theElement.Name.Length == EA_Constants.EA_DocGenBaseName.Length) // allow EA_DocGen to be used as a term/acronym
925
               {
926
                  infoItems.Add( theElement );
927
               }
2088 ghuddy 928
            }
2104 ghuddy 929
 
930
            if (infoItems.Count > 0)
2088 ghuddy 931
            {
2104 ghuddy 932
               // Create a table
933
               int tableNum = TableUtils.Table_Create("Terminology", infoItems.Count+1, 2);
934
               Word.Table table = WordDocument.Tables[tableNum];
935
               object center = Word.WdParagraphAlignment.wdAlignParagraphCenter;
2088 ghuddy 936
 
2104 ghuddy 937
               TableUtils.Table_SetTableColumnTitle(table, "Term", 1);
938
               TableUtils.Table_SetTableColumnTitle(table, "Definition", 2);
939
               table.Columns[1].SetWidth(100, Word.WdRulerStyle.wdAdjustSameWidth );
940
               int row = 2;
941
 
942
               foreach(EA.Element theElement in infoItems)
2088 ghuddy 943
               {
2104 ghuddy 944
                  table.Cell(row,1).Range.Text = theElement.Name.ToString();
945
                  table.Cell(row,2).Range.Text = theElement.Notes.ToString();
2088 ghuddy 946
                  row++;
947
               }
948
            }
949
         }
950
      }
951
 
2094 ghuddy 952
      #endregion
2088 ghuddy 953
 
954
      private bool generatePackageHeadingAndDescription( EA.Package thePackage, int recurse_level )
955
      {
2104 ghuddy 956
         bool processLowerLevelContent = true;  // return value for this function
2088 ghuddy 957
 
958
         // The package name is a heading, and the package notes are paragraphs 
959
         // directly under that heading
960
 
2094 ghuddy 961
         TextUtils.appendAndSelectHeadingText( thePackage.Name.ToString(), recurse_level );
2104 ghuddy 962
         displayProgress( "PACKAGE: ", thePackage.Name.ToString() );
2088 ghuddy 963
 
964
         // Special handling for package called "Terminology" 
965
         if (thePackage.Name == "Terminology")
966
         {
2094 ghuddy 967
            TextUtils.appendAndSelectText( thePackage.Notes.ToString(), EA_Constants.styleName_Body1 );
2104 ghuddy 968
            createTerminologySection(thePackage, recurse_level);
969
            processLowerLevelContent = false;
2088 ghuddy 970
         }
971
 
2104 ghuddy 972
         else if (thePackage.Name == "References")
2088 ghuddy 973
         {
2094 ghuddy 974
            TextUtils.appendAndSelectText( thePackage.Notes.ToString(), EA_Constants.styleName_Body1 );
2088 ghuddy 975
            createReferencesSection(thePackage);
2104 ghuddy 976
            processLowerLevelContent = false;
2088 ghuddy 977
         }
2104 ghuddy 978
         else
979
         {
980
            // use the package notes as body text and indicate to caller that package elements 
981
            // have not been consumed
982
            TextUtils.appendAndSelectText( thePackage.Notes.ToString(), EA_Constants.styleName_Body1 );      
983
         }
984
 
985
         return processLowerLevelContent;
2088 ghuddy 986
      }
987
 
988
 
989
      private void generatePackageDiagrams( EA.Package thePackage )
990
      {
991
         // default handling of diagrams
992
         foreach(EA.Diagram theDiagram in thePackage.Diagrams)
993
         {
2102 ghuddy 994
            if (theDiagram.ParentID == 0 || thePackage.PackageID == theDiagram.ParentID)
995
            {
996
               appendAndSelectDiagramViaClipboard( theDiagram );
997
            }
2088 ghuddy 998
         }
999
      }
1000
 
2104 ghuddy 1001
 
2102 ghuddy 1002
      private void generateElementDiagrams( EA.Element theElement )
1003
      {
1004
         // default handling of diagrams
1005
         foreach(EA.Diagram theDiagram in theElement.Diagrams)
1006
         {
1007
            if (theDiagram.ParentID == 0 || theElement.ElementID == theDiagram.ParentID)
1008
            {
1009
               appendAndSelectDiagramViaClipboard( theDiagram );
1010
            }
1011
         }
1012
      }
1013
 
2104 ghuddy 1014
 
2094 ghuddy 1015
      private void generateMethodContent( EA.Element theElement, int recurse_level )
2088 ghuddy 1016
      {
1017
         recurse_level++;
2094 ghuddy 1018
 
1019
         // Get all the methods into an array list and sort them by their position in the class's
1020
         // method list (ie. sort order is determined by the Pos value in each method).
1021
         ArrayList theMethods = new ArrayList();
1022
         foreach(EA.Method theMethod in theElement.Methods)
1023
            theMethods.Add( theMethod );
1024
         methodSortByPos sorter = new methodSortByPos();
1025
         theMethods.Sort( sorter );
1026
 
1027
         // filter out methods with certain characteristics?
1028
         // eg. Users may only want to document public and protected methods.
1029
         int numMethodsRemaining = 0;
1030
         foreach(EA.Method theMethod in theMethods)
1031
         {
1032
            if (EA_Utils.options.opt_SuppressPrivateMethods == false
1033
               || !theMethod.Visibility.StartsWith("Private"))
1034
               numMethodsRemaining++;
1035
         }
1036
 
1037
         Word.Range wr;
1038
         StringBuilder sb;
1039
 
1040
         if (numMethodsRemaining > 0)
1041
         {
1042
            // Print the "<Class Name> Operations" headings
1043
            sb = new StringBuilder();
1044
            sb.Append( theElement.Name );
1045
            sb.Append( " Operations" );
1046
            TextUtils.appendAndSelectHeadingText(sb.ToString(), recurse_level);
1047
 
1048
            // Iterate through the class's methods
1049
            foreach(EA.Method theMethod in theMethods)
1050
            {
1051
               sb = new StringBuilder();
1052
 
1053
               if (EA_Utils.options.opt_SuppressPrivateMethods == false
1054
                  || !theMethod.Visibility.StartsWith("Private"))
1055
               {
1056
                  // Print the Method name as a sub heading, and its description
1057
                  TextUtils.appendAndSelectHeadingText(theMethod.Name , recurse_level + 1);
1058
                  TextUtils.appendDescription(theMethod.Notes, EA_Utils);
1059
 
1060
                  // Get a list of the method's parameters and sort them by the position field setup 
1061
                  // in EA by the designer
1062
                  ArrayList theParams = new ArrayList();
1063
                  foreach(EA.Parameter theParam in theMethod.Parameters)
1064
                     theParams.Add( theParam );
1065
                  parameterSortByPos paramSorter = new parameterSortByPos();
1066
                  theParams.Sort( paramSorter );
1067
 
1068
                  // Print the prototype heading
2098 ghuddy 1069
                  wr = TextUtils.appendAndSelectText("\nPrototype:", EA_Constants.styleName_Body1_Left_2_5cm_Italic);
2094 ghuddy 1070
 
1071
                  // begin to build the prototype string
1072
                  sb = new StringBuilder();
1073
                  sb.Append( theMethod.ReturnType );
1074
                  sb.Append( " " );
1075
                  sb.Append( theMethod.Name );
1076
                  sb.Append( "(" );
1077
 
1078
                  if (theParams.Count > 0)
1079
                  {
1080
                     int numParamsRemaining = theParams.Count;
1081
 
1082
                     // print what we have so far constructed for the prototype
2098 ghuddy 1083
                     wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_3_5cm);
2094 ghuddy 1084
 
1085
                     // Now form a new string for the params
1086
                     sb = new StringBuilder();
1087
                     foreach(EA.Parameter theParam in theParams)
1088
                     {
1089
                        // each parameter is   "[in|out|inout] type name [= default-value]"
1090
                        // where the default value is optional
1091
                        sb.Append( "[" );
1092
                        sb.Append( theParam.Kind );
1093
                        sb.Append( "] " );
1094
                        sb.Append( theParam.Type );
1095
                        sb.Append( " " );
1096
                        sb.Append( theParam.Name );
1097
                        if (theParam.Default.Length > 0)
1098
                        {
1099
                           sb.Append( " = " );
1100
                           sb.Append( theParam.Default );
1101
                        }
1102
 
1103
                        // if there are more parameters after this one, add a comma and newline
1104
                        if (numParamsRemaining > 1)
1105
                           sb.Append( ",\n" );
1106
 
1107
                        numParamsRemaining--;
1108
                     }
1109
 
1110
                     // complete the prototype and print it.
1111
                     sb.Append( ")" );
2098 ghuddy 1112
                     wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_4_5cm);
2094 ghuddy 1113
                  }
1114
                  else
1115
                  {
1116
                     // complete the prototype and print it.
1117
                     sb.Append( ")" );
2098 ghuddy 1118
                     wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_3_5cm);
2094 ghuddy 1119
                  }
1120
 
1121
 
1122
                  // Prototype Attributes/Characteristics
1123
                  sb = new StringBuilder();
1124
                  sb.Append( theMethod.Visibility );
1125
 
1126
                  if (theMethod.IsStatic)
1127
                     sb.Append("\nStatic");
1128
 
1129
                  if (theMethod.Abstract)
1130
                     sb.Append("\nAbstract");
1131
 
1132
                  if (theMethod.IsPure)
1133
                     sb.Append("\nPure (c++)");
1134
 
1135
                  if (theMethod.IsSynchronized)
1136
                     sb.Append("\nSynchronised");
1137
 
1138
                  if (theMethod.Concurrency != null && theMethod.Concurrency.Length > 0 && !theMethod.Concurrency.StartsWith("Sequential") )
1139
                  {
1140
                     sb.Append("\n");
1141
                     sb.Append(theMethod.Concurrency);
1142
                  }
1143
 
1144
                  if (theMethod.IsConst)
1145
                     sb.Append("\nConst");
1146
 
1147
                  if (theMethod.IsQuery)
1148
                     sb.Append("\nIs Querry (does not alter class variables)");
1149
 
1150
                  if (theMethod.IsLeaf)
1151
                     sb.Append("\nIs Leaf (cannot be overriden)");
1152
 
1153
                  if (theMethod.ReturnIsArray)
1154
                     sb.Append( "\nReturn value is an array" );
1155
 
1156
                  if (theMethod.Throws != null && theMethod.Throws.Length > 0)
1157
                  {
1158
                     sb.Append("\n");
1159
                     sb.Append( theMethod.Throws );
1160
                  }
1161
 
1162
                  if (sb.Length > 0)
1163
                  {
2098 ghuddy 1164
                     wr = TextUtils.appendAndSelectText("Characteristics:", EA_Constants.styleName_Body1_Left_2_5cm_Italic);
2094 ghuddy 1165
 
2098 ghuddy 1166
                     wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_3_5cm);
2094 ghuddy 1167
                  }
1168
 
1169
                  // Parameter Descriptions
1170
                  if (theParams.Count > 0)
1171
                  {
2098 ghuddy 1172
                     wr = TextUtils.appendAndSelectText("Parameters:", EA_Constants.styleName_Body1_Left_2_5cm_Italic);
2094 ghuddy 1173
 
1174
                     foreach(EA.Parameter theParam in theParams)
1175
                     {
2098 ghuddy 1176
                        wr = TextUtils.appendAndSelectText( theParam.Name + "\t", EA_Constants.stylename_Parameter_Description);
1177
                        // do notes in seperate step since we want to call the appendDescription() method which 
1178
                        // automatically alerts us to missing descriptions in the generated document.
1179
                        wr = TextUtils.appendDescription( theParam.Notes, EA_Constants.stylename_Parameter_Description, EA_Utils, true);
2094 ghuddy 1180
                     }
1181
                  }
1182
               }
1183
            }
1184
         }
1185
      }
1186
 
1187
 
1188
      /// <summary>
1189
      /// This method serialises a class's attributes to the document. 
1190
      /// </summary>
1191
      /// <param name="theElement"></param>
1192
      /// <param name="recurse_level"></param>
1193
      private void generateAttributeContent( EA.Element theElement, int recurse_level )
1194
      {
1195
         recurse_level++;
1196
 
1197
         // Get all the attributes into an array list and sort them by their position in the class's
1198
         // attribute list (ie. sort order is determined by the Pos value in each attribute).
1199
         ArrayList theAttrs = new ArrayList();
1200
         foreach(EA.Attribute theAttr in theElement.Attributes)
1201
            theAttrs.Add( theAttr );
1202
         attributeSortByPos sorter = new attributeSortByPos();
1203
         theAttrs.Sort( sorter );
1204
 
1205
         // TODO
1206
         // filter out attributes with certain characteristics?
1207
         // eg. Users may only want to document public and protected attributes.
1208
 
1209
         int numAttrsRemaining = 0;
1210
         foreach(EA.Attribute theAttr in theAttrs)
1211
         {
1212
            if (EA_Utils.options.opt_SuppressPrivateAttributes == false
1213
               || !theAttr.Visibility.StartsWith("Private"))
1214
               numAttrsRemaining++;
1215
         }
1216
 
1217
         if (numAttrsRemaining > 0)
1218
         {
1219
            StringBuilder sb = new StringBuilder();
1220
 
1221
            sb.Append( theElement.Name );
1222
            sb.Append( " Attributes" );
1223
            TextUtils.appendAndSelectHeadingText(sb.ToString(), recurse_level);
1224
 
1225
            // serialise the attributes to the document.
1226
            foreach(EA.Attribute theAttr in theAttrs)
1227
            {
1228
               if (EA_Utils.options.opt_SuppressPrivateAttributes == false
1229
                  || !theAttr.Visibility.StartsWith("Private"))
1230
               {
1231
                  // Begin to build content string for the "Attribute" table column 
1232
                  sb = new StringBuilder();
1233
 
1234
                  // <type> <name>
1235
                  sb.Append("\n");
1236
                  sb.Append(theAttr.Type);
1237
                  sb.Append(" ");
1238
                  sb.Append(theAttr.Name);
1239
                  Word.Range wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1);
1240
                  wr.Font.Bold = 1;
1241
 
1242
                  wr = TextUtils.appendDescription(theAttr.Notes, EA_Utils);
1243
                  wr.ParagraphFormat.LeftIndent = WordApp.CentimetersToPoints((float)3.5);
1244
 
1245
                  // The approach here is to display as much of the attribute as we can but try to keep the output
1246
                  // uncluttered by omitting items the user has not set via the EA GUI.
1247
 
1248
                  // Begin to build content string for the "Other Information" table cell
1249
                  sb = new StringBuilder();
1250
 
1251
                  sb.Append(theAttr.Visibility);
1252
                  sb.Append("\n");
1253
 
1254
                  if (theAttr.IsConst)
1255
                     sb.Append("Constant\n");
1256
 
1257
                  if (theAttr.IsStatic)
1258
                     sb.Append("Static\n");
1259
 
1260
                  if (theAttr.IsDerived)
1261
                     sb.Append("Derived\n");
1262
 
1263
                  if (theAttr.IsOrdered)
1264
                  {
1265
                     sb.Append("Is Ordered\n");
1266
                  }
1267
 
1268
                  if (theAttr.IsCollection)
1269
                  {
1270
                     sb.Append("Is A Collection\n");
1271
                  }
1272
 
1273
                  if (theAttr.Length.Length > 0 && System.Convert.ToInt32(theAttr.Length) > 0)
1274
                  {
1275
                     sb.Append("Length = ");
1276
                     sb.Append(theAttr.Length);
1277
                     sb.Append("\n");
1278
                  }
1279
 
1280
                  if (!theAttr.Containment.StartsWith("Not Specified"))
1281
                  {
1282
                     sb.Append("Containment =");
1283
                     sb.Append(theAttr.Containment);
1284
                     sb.Append("\n");
1285
                  }
1286
 
1287
                  if (theAttr.Container.Length > 0)
1288
                  {
1289
                     sb.Append("Container Type = ");
1290
                     sb.Append(theAttr.Container);
1291
                     sb.Append("\n");
1292
                  }
1293
 
1294
                  if (theAttr.Style.Length > 0)
1295
                  {
1296
                     sb.Append("Style = ");
1297
                     sb.Append(theAttr.Style);
1298
                     sb.Append("\n");
1299
                  }
1300
 
1301
                  if (  System.Convert.ToInt32(theAttr.LowerBound) > 1
1302
                     || System.Convert.ToInt32(theAttr.UpperBound) > 1)
1303
                  {
1304
                     sb.Append("Multiplicity [");
1305
                     sb.Append(theAttr.LowerBound);
1306
                     sb.Append("..");
1307
                     sb.Append(theAttr.UpperBound);
1308
                     sb.Append("]\n");
1309
                  }
1310
 
1311
                  if (theAttr.Scale.Length > 0 && System.Convert.ToInt32(theAttr.Scale) > 0)
1312
                  {
1313
                     sb.Append("Scale = ");
1314
                     sb.Append(theAttr.Scale);
1315
                     sb.Append( "\n" );
1316
                  }
1317
                  if (theAttr.Precision.Length > 0 && System.Convert.ToInt32(theAttr.Precision) > 0)
1318
                  {
1319
                     sb.Append("Precision = ");
1320
                     sb.Append(theAttr.Precision);
1321
                     sb.Append( "\n" );
1322
                  }
1323
 
1324
                  if (theAttr.Default.Length > 0)
1325
                  {
1326
                     sb.Append("Default Value = ");
1327
                     sb.Append(theAttr.Default);
1328
                     sb.Append( "\n" );
1329
                  }
1330
 
1331
                  // Now look at the constraint and tagged value collections and add any found info to the
1332
                  // right hand column
1333
                  short i;
1334
                  for(i=0; i<theAttr.Constraints.Count; i++)
1335
                  {
1336
                     EA.AttributeConstraint theCons = (EA.AttributeConstraint)theAttr.Constraints.GetAt(i);
1337
                     sb.Append( theCons.Type );
1338
                     sb.Append( ": {" );
1339
                     sb.Append( theCons.Name );
1340
                     sb.Append( "}\n" );
1341
                     //sb.Append( theCons.Notes  );
1342
                     //sb.Append( "\n" );
1343
                  }
1344
 
1345
                  for(i=0; i<theAttr.TaggedValues.Count; i++)
1346
                  {
1347
                     EA.AttributeTag theTag = (EA.AttributeTag)theAttr.TaggedValues.GetAt(i);
1348
                     sb.Append( "[" );
1349
                     sb.Append( theTag.Name );
1350
                     sb.Append( "="  );
1351
                     sb.Append( theTag.Value );
1352
                     sb.Append( "]\n" );
1353
                     //sb.Append( theTag.Notes );
1354
                     //sb.Append( "\n" );
1355
                  }
1356
 
1357
                  if (sb.Length > 0)
1358
                  {
1359
                     // remove the trailing "\n"
1360
                     sb.Remove( sb.ToString().Length - 1, 1);
1361
 
2098 ghuddy 1362
                     wr = TextUtils.appendAndSelectText("Characteristics:", EA_Constants.styleName_Body1_Left_3_5cm_Italic);
2094 ghuddy 1363
 
2098 ghuddy 1364
                     wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_4_5cm);
2094 ghuddy 1365
                  }
1366
 
1367
                  numAttrsRemaining--;
1368
               }
1369
            }
1370
         }
1371
      }
1372
 
1373
 
1374
      private void generateClassCharacteristics( EA.Element theElement, int recurse_level )
1375
      {
1376
         StringBuilder sb = new StringBuilder();
1377
 
2104 ghuddy 1378
         ////////////////////////////////////////////////////////////////////////////////////////////////
2094 ghuddy 1379
         sb.Append( "Characteristics:" );
2098 ghuddy 1380
         Word.Range wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_2_5cm_Italic);
2088 ghuddy 1381
 
2094 ghuddy 1382
         sb = new StringBuilder();
2104 ghuddy 1383
         // VISIBILITY
2094 ghuddy 1384
         sb.Append( theElement.Visibility );
2104 ghuddy 1385
         // ABSTRACT
2094 ghuddy 1386
         if (System.Convert.ToInt32(theElement.Abstract) == 1)
1387
            sb.Append( "\nAbstract" );
2104 ghuddy 1388
         // STEREOTYPES
1389
         if (theElement.StereotypeEx.Length > 0)
1390
         {
1391
            sb.Append("\nStereotypes: ");
1392
            sb.Append(theElement.StereotypeEx);
1393
         }
1394
         // MULTIPLICITY
1395
         if (theElement.Multiplicity.Length > 0)
1396
         {
1397
            sb.Append("\nMultiplicity: ");
1398
            sb.Append(theElement.Multiplicity);
1399
         }
1400
         // IS ACTIVE
1401
         if (theElement.IsActive)
1402
            sb.Append("\nClass is active (has its own thread of control)\n");
1403
         // IS SPEC
1404
         if (theElement.IsSpec)
1405
            sb.Append("\nClass is a specification\n");
2094 ghuddy 1406
 
2098 ghuddy 1407
         wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_3_5cm);
2104 ghuddy 1408
 
1409
         ////////////////////////////////////////////////////////////////////////////////////////////////
2094 ghuddy 1410
         sb = new StringBuilder();
1411
         foreach(EA.Element baseClass in theElement.BaseClasses)
2088 ghuddy 1412
         {
2094 ghuddy 1413
            sb.Append( baseClass.Name);
1414
         }
1415
         if (sb.Length > 0)
1416
         {
2098 ghuddy 1417
            wr = TextUtils.appendAndSelectText("Base Class(es):", EA_Constants.styleName_Body1_Left_2_5cm_Italic);
2088 ghuddy 1418
 
2098 ghuddy 1419
            wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_3_5cm);
2094 ghuddy 1420
         }
1421
 
2104 ghuddy 1422
         ////////////////////////////////////////////////////////////////////////////////////////////////
2094 ghuddy 1423
         sb = new StringBuilder();
1424
         foreach(EA.Element intf in theElement.Realizes)
1425
         {
1426
            sb.Append( intf.Name);
1427
         }
1428
         if (sb.Length > 0)
1429
         {
2098 ghuddy 1430
            wr = TextUtils.appendAndSelectText("Realises:", EA_Constants.styleName_Body1_Left_2_5cm_Italic);
2094 ghuddy 1431
 
2098 ghuddy 1432
            wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_3_5cm);
2094 ghuddy 1433
         }
1434
      }
1435
 
1436
 
1437
      private void generateClassRequirements( EA.Element theElement, int recurse_level )
1438
      {
1439
         StringBuilder sb = new StringBuilder();
1440
 
1441
         sb.Append( "Requirements:" );
2098 ghuddy 1442
         Word.Range wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_2_5cm_Italic);
2094 ghuddy 1443
 
1444
         foreach(EA.Requirement theReq in theElement.Requirements)
1445
         {
1446
            sb = new StringBuilder();
1447
            sb.Append( theReq.Name );
2098 ghuddy 1448
            wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_3_5cm);
2094 ghuddy 1449
            sb = new StringBuilder();
1450
            sb.Append( theReq.Notes );
1451
            if (sb.Length > 0)
2088 ghuddy 1452
            {
2098 ghuddy 1453
               wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_4_5cm);
2088 ghuddy 1454
            }
2094 ghuddy 1455
         }
1456
      }
1457
 
1458
 
1459
      private void generateClassConstraints( EA.Element theElement, int recurse_level )
1460
      {
1461
         StringBuilder sb = new StringBuilder();
1462
 
1463
         sb.Append( "Constraints:" );
2098 ghuddy 1464
         Word.Range wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_2_5cm_Italic);
2094 ghuddy 1465
 
1466
         foreach(EA.Constraint theCons in theElement.Constraints)
1467
         {
1468
            sb = new StringBuilder();
1469
            sb.Append( theCons.Type );
1470
            sb.Append( ": {" );
1471
            sb.Append( theCons.Name );
1472
            sb.Append( "}" );
1473
 
2098 ghuddy 1474
            wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_3_5cm);
2094 ghuddy 1475
 
1476
            if (theCons.Notes.Length > 0)
2088 ghuddy 1477
            {
2094 ghuddy 1478
               sb = new StringBuilder();
1479
               sb.Append( theCons.Notes );
2098 ghuddy 1480
               wr = TextUtils.appendAndSelectText(sb.ToString(), EA_Constants.styleName_Body1_Left_4_5cm);
2094 ghuddy 1481
            }
1482
         }
1483
      }
1484
 
1485
 
2104 ghuddy 1486
      private bool generateElementContent( EA.Element theElement, int recurse_level )
2094 ghuddy 1487
      {
2104 ghuddy 1488
         bool allowSubElementParsing = true;  // return value for the function
1489
 
2094 ghuddy 1490
         // track recursion level to control heading style formatting requirements
1491
         if (oneShot_skipRootElementHeading == false)
1492
            recurse_level++;
1493
 
1494
         if (EA_Utils.options.elementTypeFoundInEA_DocGen( theElement.Type ))
1495
         {
1496
            // pass the element to the requirement element serialisation function. It
1497
            // will tell us if it did anything with it. If not, then carry out the default
1498
            // element serialisation.
1499
            if (false == TextUtils.generateRequirementText(theElement, EA_Utils))
1500
            {
1501
               bool isClass = theElement.Type.StartsWith("Class");
1502
 
2104 ghuddy 1503
               if (   (   true == isClass
1504
                       && true == EA_Utils.options.opt_SuppressPrivateClasses 
1505
                       && true == theElement.Visibility.StartsWith("Private"))
1506
                   || (   true == EA_Utils.options.opt_ConsiderAPIElementsOnly 
1507
                       && 0 > theElement.StereotypeEx.IndexOf("API"))
1508
                  )
2088 ghuddy 1509
               {
2094 ghuddy 1510
                  // do nothing
2104 ghuddy 1511
                  DocSectionTracker.trackDocSection(recurse_level);
1512
                  displayProgress( "SKIPPED: ", theElement.Name );
1513
                  allowSubElementParsing = false;
2088 ghuddy 1514
               }
1515
               else
2094 ghuddy 1516
               {
1517
                  // disarm the one-shot element (heading) skipping feature if it was armed, and 
1518
                  // by-pass the code to generate a new heading level for the element
1519
                  if (oneShot_skipRootElementHeading == false)
1520
                  {
1521
                     // Default element serialisation
2104 ghuddy 1522
                     TextUtils.appendAndSelectHeadingText( theElement.Name, recurse_level );
2094 ghuddy 1523
                  }
1524
                  else
1525
                  {
1526
                     oneShot_skipRootElementHeading = false;
1527
                  }
1528
 
2104 ghuddy 1529
                  processedElements.Add(theElement.ElementID);
1530
                  displayProgress( "ELEMENT: ", theElement.Name );
1531
 
2094 ghuddy 1532
                  TextUtils.appendDescription( theElement.Notes, EA_Utils );
1533
 
2102 ghuddy 1534
                  generateElementDiagrams(theElement);
1535
 
2094 ghuddy 1536
                  if (true == isClass)
1537
                  {
2104 ghuddy 1538
                     // accumulate unit testable classes.
1539
                     if (   theElement.StereotypeEx.IndexOf("API") >= 0
1540
                         && !theElement.Visibility.StartsWith("Private"))
2094 ghuddy 1541
                     {
2104 ghuddy 1542
                        classesNeedingUnitTests.Add( theElement.ElementID );
2094 ghuddy 1543
                     }
1544
 
1545
                     generateClassCharacteristics(theElement, recurse_level);
1546
                  }
1547
 
1548
                  // Requirement collection
1549
                  if (theElement.Requirements.Count > 0)
1550
                  {
1551
                     generateClassRequirements(theElement, recurse_level);
1552
                  }
1553
 
1554
                  // Constraint collection
1555
                  if (theElement.Constraints.Count > 0)
1556
                  {
1557
                     generateClassConstraints(theElement, recurse_level);
1558
                  }
1559
 
1560
                  if (theElement.Issues.Count > 0)
1561
                  {
1562
                  }
1563
 
1564
                  // Attribute collection
1565
                  if (theElement.Attributes.Count > 0)
1566
                  {
1567
                     generateAttributeContent(theElement, recurse_level);
1568
                  }
1569
 
1570
                  // Method collection
1571
                  if (theElement.Methods.Count > 0)
1572
                  {
1573
                     generateMethodContent(theElement, recurse_level);
1574
                  }
1575
               }
2088 ghuddy 1576
            }
2094 ghuddy 1577
            else
1578
            {
2104 ghuddy 1579
               processedElements.Add(theElement.ElementID);
1580
               DocSectionTracker.trackDocSection(recurse_level);
2094 ghuddy 1581
               displayProgress( "ELEMENT: ", theElement.Name );
1582
            }
2088 ghuddy 1583
         }
1584
         else
1585
         {
2104 ghuddy 1586
            DocSectionTracker.trackDocSection(recurse_level);
2088 ghuddy 1587
            displayProgress( "FILTERED: ", theElement.Type );
1588
         }
1589
         // TODO
1590
         // We will probably have to put special code in here at some point for attributes
1591
         // of, and collections of things within elements. This will become apparent once
1592
         // someone tries to produce a design document where such things need to be included
1593
         // in the generated document. Lots of work needed here eventually.
1594
 
2094 ghuddy 1595
         // disarm element heading skip control
1596
         oneShot_skipRootElementHeading = false;
2104 ghuddy 1597
 
1598
         return allowSubElementParsing;
2088 ghuddy 1599
      }
1600
 
2094 ghuddy 1601
 
2088 ghuddy 1602
      /// <summary>
1603
      /// This function searches for the old content in the document in order to remove it
1604
      /// prior to adding in the new content from the latest EA model data.
1605
      /// </summary>
1606
      private void removeExistingDocumentContent()
1607
      {
1608
         //WordApp.Visible = true;  // enable this when debugging this horrible function
1609
         Word.Selection aSelection;
2094 ghuddy 1610
         object findStyle = StyleUtils.getStyle( EA_Constants.styleName_Heading1 );
2088 ghuddy 1611
 
1612
         WordApp.Selection.WholeStory();
1613
         aSelection = WordApp.Selection;
1614
 
1615
         aSelection.Find.ClearFormatting();
1616
         aSelection.Find.set_Style( ref findStyle );
1617
         aSelection.Find.Text = "Introduction";
1618
         aSelection.Find.Replacement.Text = "";
1619
         aSelection.Find.Forward = true;
1620
         aSelection.Find.MatchCase = false;
1621
         aSelection.Find.MatchWholeWord = false;
1622
         aSelection.Find.MatchWildcards = false;
1623
         aSelection.Find.MatchSoundsLike = false;
1624
         aSelection.Find.MatchAllWordForms = false;
1625
 
1626
         object missingValue = Type.Missing;
1627
         if (aSelection.Find.Execute(ref missingValue, ref missingValue, 
1628
            ref missingValue, ref missingValue, ref missingValue, 
1629
            ref missingValue, ref missingValue, ref missingValue, 
1630
            ref missingValue, ref missingValue, ref missingValue, 
1631
            ref missingValue, ref missingValue, ref missingValue, 
1632
            ref missingValue)) 
1633
         { 
1634
            // found Introduction with Heading 1 style so we are now at the point in the 
1635
            // document where everything here on must be deleted in readiness for the newly
1636
            // generated content. Extend the range to the end of the document and cut out the
1637
            // old content.
1638
            Word.Range range = aSelection.Range;
1639
            range.End = WordDocument.Content.End;
1640
            range.Cut();
2092 ghuddy 1641
            // try and ensure that no heading style is left in place following the removal
2094 ghuddy 1642
            object style = EA_Constants.styleName_Body1;
2092 ghuddy 1643
            range.set_Style(ref style);
2088 ghuddy 1644
         }
1645
      }
1646
 
1647
 
1648
      /// <summary>
1649
      /// Parses an element (because elements can contain sub-elements).
1650
      /// This is also the function that identifies the occurrences of the special
1651
      /// EA_DocGenXXX elements.
1652
      /// </summary>
1653
      /// <param name="theElement"></param>
1654
      /// <param name="recurse_level"></param>
1655
      private void parse_element(EA.Element theElement, int recurse_level)
1656
      {
1657
         // First look for and handle special elements that control the doc-gen process
1658
 
1659
         // The EA_DocGenPackageLink can contain a list of GUIDs in its notes section
1660
         // that point to model structure outside of the localised structure forming the
1661
         // document. This enables a document to grab content from other external models
1662
         // as long as they are loaded into the repository.
2094 ghuddy 1663
         if (theElement.Name.StartsWith(EA_Constants.EA_DocGenPackageLink))
2088 ghuddy 1664
         {
2104 ghuddy 1665
            processingLink++;
2088 ghuddy 1666
            processPackageLink( theElement, recurse_level );
2104 ghuddy 1667
            processingLink--;
2088 ghuddy 1668
         }
1669
 
1670
            // The EA_DocGenDiagramLink can contain a list of GUIDs in its notes section
1671
            // that point to diagram elements anywhere in the repository.
2094 ghuddy 1672
         else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenDiagramLink))
2088 ghuddy 1673
         {
2104 ghuddy 1674
            processingLink++;
2088 ghuddy 1675
            processDiagramLink( theElement );
2104 ghuddy 1676
            processingLink--;
2088 ghuddy 1677
         }
1678
 
1679
            // The EA_DocGenDiagramLink can contain a list of GUIDs in its notes section
1680
            // that point to diagram elements anywhere in the repository.
2094 ghuddy 1681
         else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenElementLink))
2088 ghuddy 1682
         {
2104 ghuddy 1683
            processingLink++;
2088 ghuddy 1684
            processElementLink( theElement, recurse_level );
2104 ghuddy 1685
            processingLink--;
2088 ghuddy 1686
         }
1687
 
1688
            // The EA_DocGenTable element can contain table content in its notes section
1689
            // and must be dealt with in a special way.
2094 ghuddy 1690
         else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenTable))
2088 ghuddy 1691
         {
2104 ghuddy 1692
            TableUtils.processTableElement(theElement, recurse_level);
2088 ghuddy 1693
         }
1694
 
1695
            // The EA_DocGenText element can contain text content in its notes section
1696
            // that must be appended to the doc in Body 1 style within the current
1697
            // section.
2094 ghuddy 1698
         else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenText))
2088 ghuddy 1699
         {
2104 ghuddy 1700
            TextUtils.appendAndSelectText( theElement.Notes.ToString(), EA_Constants.styleName_Body1 );
2088 ghuddy 1701
         }
1702
 
2094 ghuddy 1703
         else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenRelationshipMatrix))
2088 ghuddy 1704
         {
2104 ghuddy 1705
            EA_RelationshipMatrix EA_RelMatrix = new EA_RelationshipMatrix(EA_Repository, TableUtils, TextUtils, EA_Utils, WordDocument, processedElements);
1706
            if (EA_RelMatrix.processRelationshipMatrixOptions( theElement ))
1707
            {
1708
               EA_RelMatrix.processRelationshipMatrixElement( theElement, recurse_level );
1709
            }
2088 ghuddy 1710
         }
1711
 
2094 ghuddy 1712
         else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenTestLink))
2088 ghuddy 1713
         {
2104 ghuddy 1714
            processingLink++;
2094 ghuddy 1715
            processTestLink( theElement, recurse_level );
2104 ghuddy 1716
            processingLink--;
2094 ghuddy 1717
         }
1718
 
1719
         else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenTestTraceability))
1720
         {
1721
            processTestTraceability( theElement, recurse_level );
1722
         }
1723
 
2104 ghuddy 1724
         else if (theElement.Name.StartsWith(EA_Constants.EA_DocGenNameLink))
1725
         {
1726
            processingLink++;
1727
            processNameLink( theElement, recurse_level );
1728
            processingLink--;
1729
         }
2094 ghuddy 1730
 
2104 ghuddy 1731
            // we are aware of the other ERG EA add-in, EA_ReqPro! That add-in creates 
2094 ghuddy 1732
            // ReqProDB stereotyped elements. Never consume them in the document generation process.
2104 ghuddy 1733
         else if (0 > theElement.StereotypeEx.IndexOf(EA_Constants.stereotype_ReqProDB))
2094 ghuddy 1734
         {
2104 ghuddy 1735
            bool allowSubElementParsing = generateElementContent( theElement, recurse_level );
1736
            if (allowSubElementParsing)
1737
            {
1738
               // Look at this elements sub-elements
1739
               foreach(EA.Element subElement in theElement.Elements)
1740
               {
1741
                  parse_element(subElement, recurse_level+1);
1742
               }
1743
            }
2102 ghuddy 1744
         }   
2088 ghuddy 1745
      }
1746
 
1747
 
1748
      /// <summary>
1749
      /// Parses the package and all of its content, extracting information as needed, and
1750
      /// adding it to the word document. This method is recursive, since recursion is the
1751
      /// easiest way to walk thru' the package levels in the model.
1752
      /// </summary>
1753
      /// <param name="parentPackage"></param>
1754
      /// <param name="recurse_level"></param>
1755
      private void parse_package(EA.Package thePackage, int recurse_level)
1756
      {
1757
         // track recursion level to control heading style formatting requirements
1758
         // The one-shot skiproot feature of the EA_DocGenPackageLink element handling has an effect
1759
         // here, as you can see. 
1760
         bool rootPackageWasSkipped = !oneShot_skipRootPackage;
1761
         if (oneShot_skipRootPackage == false)
1762
         {
1763
            recurse_level++;
1764
         }
1765
 
2104 ghuddy 1766
         // determine if the package has an API stereotype
1767
         bool packageHasAPIStereotype = false;
1768
         if (0 <= thePackage.StereotypeEx.IndexOf("API") )
1769
            packageHasAPIStereotype = true;
2088 ghuddy 1770
 
2104 ghuddy 1771
         // only process the package if it the stereotype allows, or sensitivity to the stereotype is disabled
1772
         if (  !EA_Utils.options.opt_ConsiderAPIPackagesOnly
1773
            || (EA_Utils.options.opt_ConsiderAPIPackagesOnly && EA_Utils.options.opt_RestrictForLinkedPackagesOnly && processingLink == 0)
1774
            || (EA_Utils.options.opt_ConsiderAPIPackagesOnly && packageHasAPIStereotype) 
1775
            )
2094 ghuddy 1776
         {
2104 ghuddy 1777
 
1778
            bool processLowerLevelContent = true;
2094 ghuddy 1779
 
2104 ghuddy 1780
            // disarm the one-shot package skipping feature if it was armed
1781
            if (oneShot_skipRootPackage == true)
2102 ghuddy 1782
            {
2104 ghuddy 1783
               oneShot_skipRootPackage = false;
2102 ghuddy 1784
            }
2104 ghuddy 1785
            else
1786
            {
1787
               // Generate heading and description for the package. This function also takes care of some
1788
               // specially handled packages (terminology, references).
1789
               processLowerLevelContent = generatePackageHeadingAndDescription( thePackage, recurse_level );
1790
            }
2102 ghuddy 1791
 
2104 ghuddy 1792
            // generate package heading and description. This may, depending on the package name,
1793
            // consume the elements in the package. If it does not, then consume them (and any diagrams)
1794
            // locally here.
1795
            if (true == processLowerLevelContent)
1796
            {
1797
               // consume diagrams
1798
               generatePackageDiagrams( thePackage );
2088 ghuddy 1799
 
2104 ghuddy 1800
               foreach(EA.Element subElement in thePackage.Elements)
1801
               {
1802
                  if (subElement.ParentID == 0 || thePackage.PackageID == subElement.ParentID)
1803
                     parse_element(subElement, recurse_level);
1804
               }
2088 ghuddy 1805
 
2104 ghuddy 1806
               // Scan through the sub-packages within this package.
1807
               foreach(EA.Package subPackage in thePackage.Packages)
1808
               {
1809
                  // recurse
1810
                  parse_package(subPackage, recurse_level);
1811
               }
1812
            }
2088 ghuddy 1813
         }
2104 ghuddy 1814
         else
2088 ghuddy 1815
         {
2104 ghuddy 1816
            // disarm the one-shot package skipping feature if it was armed
1817
            if (oneShot_skipRootPackage == true)
1818
            {
1819
               oneShot_skipRootPackage = false;
1820
            }         
2088 ghuddy 1821
         }
1822
      }
1823
 
1824
 
1825
      /// <summary>
1826
      /// This is the overall generate document method. It creates a word document from 
1827
      /// an input template, sets various characteristics of the document, schedules the
1828
      /// EA parsing function, before finally saving the document to the output file name.
1829
      /// </summary>
1830
      private void createTheWordDoc()
1831
      {
2092 ghuddy 1832
         // caputre initial security settings
1833
         MsoAutomationSecurity  securityBefore = WordApp.AutomationSecurity;
1834
 
2088 ghuddy 1835
         try 
1836
         {
1837
            object template       = this.textBox_template.Text;
1838
            object newTemplate    = Type.Missing;
1839
            object outputFilename = this.textBox_output_file.Text;
1840
 
1841
            object docType = Type.Missing;
1842
            object visible = Type.Missing;
1843
            object nothing = Type.Missing;
1844
            object notTrue = false;
1845
 
1846
            EA_Repository.WriteOutput( Main.GUI_OUTPUT_TAB_NAME, "", 0);
1847
            EA_Repository.WriteOutput( Main.GUI_OUTPUT_TAB_NAME, 
1848
                                       String.Format( "Generating Document {0}", this.textBox_output_file.Text), 0 );
1849
 
2092 ghuddy 1850
            // tell word not to show itself unless user has checked the option to say otherwise
2088 ghuddy 1851
            WordApp.Visible = this.checkBox_WordVisibility.Checked;
2092 ghuddy 1852
 
1853
            // disable VB macros from running in the document
1854
            WordApp.AutomationSecurity = MsoAutomationSecurity.msoAutomationSecurityForceDisable;
1855
            WordApp.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
1856
 
2088 ghuddy 1857
            // Create a document from the input template
1858
            WordDocument = WordApp.Documents.Add(ref template, ref newTemplate, ref docType, ref visible);
1859
 
2094 ghuddy 1860
            TableUtils.AcceptWordAppAndDoc(WordApp, WordDocument);
1861
            TextUtils.AcceptWordAppAndDoc(WordApp, WordDocument);
1862
            StyleUtils.AcceptWordAppAndDoc(WordApp, WordDocument);
1863
 
2088 ghuddy 1864
            // Remove all old content from the input document/template. Note that this assumes
1865
            // that content will begin at section 1 with the title "Introduction" and it will have
1866
            // "Heading 1" style.
1867
            removeExistingDocumentContent();
1868
 
1869
            // turn off grammar and spell checking
1870
            WordDocument.GrammarChecked = false;
1871
            WordDocument.SpellingChecked = false;
1872
 
2094 ghuddy 1873
            // arm the public class list accumulator.
2104 ghuddy 1874
            classesNeedingUnitTests = new ArrayList();
2094 ghuddy 1875
            classesWithUnitTests = new ArrayList();
1876
 
2104 ghuddy 1877
            processingLink = 0;
1878
 
1879
            processedElements = new ArrayList();
1880
 
2092 ghuddy 1881
            // If the input template does not contain the styles needed for requirement documents, 
1882
            // programmatically create them just in case.
2104 ghuddy 1883
            StyleUtils.createRequirementStyles();
1884
            StyleUtils.createAdditionalHeadingLevelStyles();
2098 ghuddy 1885
            StyleUtils.createElementDetailsStyles();
2104 ghuddy 1886
            StyleUtils.correctErrorsInTemplateStyles();
2098 ghuddy 1887
 
2088 ghuddy 1888
            // Parse EA_DocGen Document Model. The parent package is the document model itself
1889
            // and the packages within it are the top level packages only.
1890
            // Question: do we have to parse diagrams and elements at this top level? So far,
1891
            // this has been found to be unecessary, but you never know. For now, dont do it.
1892
            foreach(EA.Package thePackage in EA_ParentPackage.Packages)
1893
            {
1894
               parse_package(thePackage, 0);
1895
            }
1896
 
2094 ghuddy 1897
            // for design docs, a user may have used the test traceability element in their document model,
1898
            // which means that now we are finished with parse 1 of the document, we can complete the traceability
1899
            // table (if any) that was begun when that special element was first encountered.
1900
            completeTestTraceability();
2088 ghuddy 1901
 
2094 ghuddy 1902
            // Save the document to the output file before we try and update the fields. This is because
1903
            // I have seen Fields.Update() fail on a few occasions and it is very annoying
1904
            // to lose what has thus far been generated.
1905
            WordDocument.SaveAs( ref outputFilename, 
1906
               ref nothing, ref nothing, ref nothing, ref nothing, 
1907
               ref nothing, ref nothing, ref nothing, ref nothing,
1908
               ref nothing, ref nothing, ref nothing, ref nothing,
1909
               ref nothing, ref nothing, ref nothing);
2088 ghuddy 1910
 
2094 ghuddy 1911
            object noSave = Word.WdSaveOptions.wdDoNotSaveChanges;
1912
            object format = Word.WdOriginalFormat.wdWordDocument;
1913
            WordDocument.Close(ref noSave, ref format, ref nothing);
1914
 
1915
            // Re-load the document to update the fields. For some as yet unknown reason, doing this 
1916
            // sometimes fails, but by doing it in a re-loaded instance of the word document
1917
            // the failures seem to be reduced.
1918
            WordDocument = WordApp.Documents.Add(ref outputFilename, ref newTemplate, ref docType, ref visible);
1919
            WordDocument.Fields.Update();
2088 ghuddy 1920
            WordDocument.SaveAs( ref outputFilename, 
1921
               ref nothing, ref nothing, ref nothing, ref nothing, 
1922
               ref nothing, ref nothing, ref nothing, ref nothing,
1923
               ref nothing, ref nothing, ref nothing, ref nothing,
1924
               ref nothing, ref nothing, ref nothing);
1925
 
1926
            // Tell user the process completed ok
1927
            textBox_progress.AppendText( "---Completed---" );
1928
            MessageBox.Show("Document Generation Complete");
2098 ghuddy 1929
 
1930
            button_view_output.Enabled = true;
2088 ghuddy 1931
         }
1932
         catch (Exception createTheWordDoc_exception)
1933
         {
1934
            MessageBox.Show("Document Generation Failed\n\n" + createTheWordDoc_exception.Message);
1935
         }
2092 ghuddy 1936
 
1937
         // restore security settings
1938
         WordApp.AutomationSecurity = securityBefore;
2088 ghuddy 1939
      }
1940
 
2092 ghuddy 1941
 
1942
 
1943
 
2088 ghuddy 1944
      #endregion
1945
   }
1946
}