Subversion Repositories DevTools

Rev

Rev 2132 | Blame | Compare with Previous | Last modification | View Log | RSS feed

using System;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using System.Text;
using Microsoft.Office.Interop.Word;

namespace EA_DocGen
{
   /// <summary>
   /// A Base Class designed to work with the findAndProcessPackageElements method.
   /// Users will normally derive their own classes from this and add real functionality
   /// to the over-ridable methods the base class provides.
   /// </summary>
   public class EA_UtilitiesRecursionWorker
   {
      public EA_UtilitiesRecursionWorker()
      {
      }

      public virtual void processElement( EA.Element theElement )
      {
      }
      public virtual void processPackage( EA.Package thePackage )
      {
      }
   }

   

        /// <summary>
        /// Class containing functions that implement the EA_DocGen menu items.
        /// </summary>
        public class EA_Utilities
        {
      // data used by followLink() to roll around multiple GUIDs contained in the link
      static int lastLinkID = -1;
      static int nextGuidIndex = 0;



      // Operations

      public static EA.Package findNamedPackage(EA.Package current_pkg, string package_path)
      {
         string[] package_names = package_path.Split("\\".ToCharArray());

         if (current_pkg.Name.Equals(package_names[0]))
         {
            if (package_names.GetLength(0) > 1)
            {
               // prepare the package path for the possible recursion by removing the token we have just
               // matched (plus any '\' char which is assumed to be present) from the fron of the string.
               package_path = package_path.Remove(0, package_names[0].Length + 1);
            }
            else
            {
               // package_path has no more items in it, and we have matched the first item, so we are done
               // Exit returning the current package
               return current_pkg;
            }
         }

         foreach(EA.Package subPackage in current_pkg.Packages)
         {
            EA.Package returned_package = findNamedPackage(subPackage, package_path);
            if (returned_package != null)
            {
               return returned_package;
            }
         }

         return null;
      }


      public static void identifyClipboardItem()
      {
         object o = null;

         Main.EA_Repository.EnsureOutputVisible(Main.GUI_OUTPUT_TAB_NAME);
         Main.EA_Repository.WriteOutput(Main.GUI_OUTPUT_TAB_NAME, "", -1);
         Main.EA_Repository.WriteOutput(Main.GUI_OUTPUT_TAB_NAME, "Name : " + GUID_Clipboard.name, -1);
         Main.EA_Repository.WriteOutput(Main.GUI_OUTPUT_TAB_NAME, "GUID : " + GUID_Clipboard.guid, -1);
         if (GUID_Clipboard.objType == EA.ObjectType.otPackage)
         {
            Main.EA_Repository.WriteOutput(Main.GUI_OUTPUT_TAB_NAME, "Type : Package", -1);
            o = Main.EA_Repository.GetPackageByGuid(GUID_Clipboard.guid);
         }
         else if (GUID_Clipboard.objType == EA.ObjectType.otElement)
         {
            Main.EA_Repository.WriteOutput(Main.GUI_OUTPUT_TAB_NAME, "Type : Element", -1);
            o = Main.EA_Repository.GetElementByGuid(GUID_Clipboard.guid);
         }
         else if (GUID_Clipboard.objType == EA.ObjectType.otDiagram)
         {
            Main.EA_Repository.WriteOutput(Main.GUI_OUTPUT_TAB_NAME, "Type : Diagram", -1);
            o = Main.EA_Repository.GetDiagramByGuid(GUID_Clipboard.guid);
         }
         if (o != null)
         {
            Main.EA_Repository.ShowInProjectView(o);
         }
      }

      public static void updateLink()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otElement)
         {
            EA.Element ele = (EA.Element)obj;

            if (ele.Name.StartsWith(EA_Constants.EA_DocGenBaseName)
               && ele.Name.IndexOf("Link") > 0)
            {
               char[] sep = new char[] {'\r', '\n'};
               string[] strings = ele.Notes.Split(sep, 50);
               foreach(string s in strings)
               {
                  if (s.Length > 0 && s[0] == '{')
                  {
                     if (ele.Name.StartsWith(EA_Constants.EA_DocGenDiagramLink))
                     {
                        EA.Diagram diag = (EA.Diagram)Main.EA_Repository.GetDiagramByGuid(s);
                        if (diag != null)
                        {
                           ele.Name = EA_Constants.EA_DocGenDiagramLink + " - " + GetPackagePath(diag.PackageID, diag.Name);
                           ele.Update();
                           Main.EA_Repository.RefreshModelView(ele.PackageID);
                           Main.EA_Repository.ShowInProjectView(ele);
                           return;
                        }
                     }
                     else if (ele.Name.StartsWith(EA_Constants.EA_DocGenElementLink))
                     {
                        EA.Element e = (EA.Element)Main.EA_Repository.GetElementByGuid(s);
                        if (e != null)
                        {
                           ele.Name = EA_Constants.EA_DocGenElementLink + " - " + GetPackagePath(e.PackageID, e.Name);
                           ele.Update();
                           Main.EA_Repository.RefreshModelView(ele.PackageID);
                           Main.EA_Repository.ShowInProjectView(ele);
                           return;
                        }
                     }
                     else if (ele.Name.StartsWith(EA_Constants.EA_DocGenPackageLink))
                     {
                        EA.Package p = (EA.Package)Main.EA_Repository.GetPackageByGuid(s);
                        if (p != null)
                        {
                           ele.Name = EA_Constants.EA_DocGenPackageLink + " - " + GetPackagePath(p.PackageID, p.Name);
                           ele.Update();
                           Main.EA_Repository.RefreshModelView(ele.PackageID);
                           Main.EA_Repository.ShowInProjectView(ele);
                           return;
                        }
                     }
                     else if (ele.Name.StartsWith(EA_Constants.EA_DocGenNameLink))
                     {
                        EA.Package p = (EA.Package)Main.EA_Repository.GetPackageByGuid(s);
                        if (p != null)
                        {
                           ele.Name = EA_Constants.EA_DocGenNameLink + " - " + GetPackagePath(p.PackageID, p.Name);
                           ele.Update();
                           Main.EA_Repository.RefreshModelView(ele.PackageID);
                           Main.EA_Repository.ShowInProjectView(ele);
                           return;
                        }
                     }
                     return;
                  }
               }
               MessageBox.Show("Unable to find link GUID");
               return;
            }
         }
         MessageBox.Show("You must select an EA_DocGen link element");
      }

      public static void followLink()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otElement)
         {
            EA.Element ele = (EA.Element)obj;

            if (ele.Name.StartsWith(EA_Constants.EA_DocGenBaseName)
               && ele.Name.IndexOf("Link") > 0)
            {

               if (ele.ElementID != lastLinkID)
               {
                  nextGuidIndex = 0;
               }

               char[] sep = new char[] {'\r', '\n'};
               string[] strings = ele.Notes.Split(sep, 50);
               int thisGUIDIndex = 0;
               for(int i=0; i < 2; i++)
               {
                  foreach(string s in strings)
                  {
                     if (s.Length > 0 && s[0] == '{')
                     {
                        if (thisGUIDIndex < nextGuidIndex)
                        {
                           thisGUIDIndex++;
                           continue;
                        }

                        object o = null;
                        if (ele.Name.StartsWith(EA_Constants.EA_DocGenDiagramLink))
                        {
                           o = Main.EA_Repository.GetDiagramByGuid(s);
                        }
                        else if (ele.Name.StartsWith(EA_Constants.EA_DocGenElementLink))
                        {
                           o = Main.EA_Repository.GetElementByGuid(s);
                        }
                        else if (ele.Name.StartsWith(EA_Constants.EA_DocGenPackageLink))
                        {
                           o = Main.EA_Repository.GetPackageByGuid(s);
                        }
                        else if (ele.Name.StartsWith(EA_Constants.EA_DocGenNameLink))
                        {
                           o = Main.EA_Repository.GetPackageByGuid(s);
                        }
                        if (o != null)
                        {
                           Main.EA_Repository.ShowInProjectView(o);
                           lastLinkID = ele.ElementID;
                           nextGuidIndex++;
                        }
                        else
                        {
                           MessageBox.Show("Unable to resolve link\r\n" + s);
                        }
                        return;
                     }
                  }
                  if (nextGuidIndex > 0)
                  {
                     nextGuidIndex = 0;
                  }
                  else
                  {
                     break;
                  }
               }
               MessageBox.Show("Unable to find link GUID");
               return;
            }
         }
         MessageBox.Show("You must select an EA_DocGen link element");
      }


      public static EA.Package get_selected_package()
      {
         object o;
         EA.ObjectType type;

         type = Main.EA_Repository.GetTreeSelectedItem(out o);
         if (type == EA.ObjectType.otElement)
         {
            return Main.EA_Repository.GetPackageByID(((EA.Element)o).PackageID);
         }
         else if (type == EA.ObjectType.otDiagram)
         {
            return Main.EA_Repository.GetPackageByID(((EA.Diagram)o).PackageID);
         }
         else if (type == EA.ObjectType.otPackage)
         {
            return (EA.Package)o;
         }
         return null;
      }



      public static void modifyOptions()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otElement)
         {
            EA.Element ele = (EA.Element)obj;

            if (0 == ele.Name.CompareTo(EA_Constants.EA_DocGenBaseName))
            {
               EA_DocGenOptions.initialise();

               if (true == EA_DocGenOptions.lookForAndProcess_EA_DocGen_Element( ele ))
               {
                  EA_DocGenOptionsForm dlg = new EA_DocGenOptionsForm();
                  dlg.populate();
                  DialogResult dlgRes = dlg.ShowDialog();
                  if (dlgRes == DialogResult.OK)
                  {
                     dlg.read();

                     EA_DocGenOptions.updateEA_DocGen(ele);
                  }
               }
            }
         }
      }


      /// <summary>
      /// Begins the document generation process, opening the dialog to capture input/output
      /// files. the createWordDoc dialog class does most of the work ofcoarse.
      /// </summary>
      public static void createWordDoc()
      {
         Main.threadCreateDocDialogRunning = true;

         try
         {
            // Get the package in or under which the EA project browser selection exists
            EA.Package pkg = EA_Utilities.get_selected_package();

            EA_DocGenOptions.initialise();

            // Make sure this package has an EA_DocGen element
            pkg = EA_DocGenOptions.lookForAndProcess_EA_DocGen_Element(pkg);
            if (pkg != null)
            {
               // bring up the dialog for doc generation
               createWordDoc dialog = new createWordDoc(pkg);
               dialog.Text = "Generate Document From Model Layout";
               dialog.textBox_template.Text    = ReadTag(pkg, "TEMPLATE");
               dialog.textBox_output_file.Text = ReadTag(pkg, "DOCFILE");
               dialog.ShowDialog();
               WriteTag(pkg, "TEMPLATE", dialog.textBox_template.Text); 
               WriteTag(pkg, "DOCFILE",  dialog.textBox_output_file.Text);
            }
            else
            {
               MessageBox.Show("ERROR, failed to find EA_DocGen element.");
            }
            
         }
         catch(Exception e)
         {
            MessageBox.Show(e.Message);
         }
         Main.threadCreateDocDialogRunning = false;
      }


      /// <summary>
      /// Creates a package under the specified parent package. the package is given a tree position
      /// as specified in order for it to be ordered in the model as the caller requires.
      /// </summary>
      /// <param name="parentPackage"></param>
      /// <param name="name"></param>
      /// <param name="treePos"></param>
      /// <returns></returns>
      public static EA.Package createPackage(EA.Package parentPackage, string name, int treePos)
      {
         EA.Package newobj = (EA.Package)parentPackage.Packages.AddNew(name, "Package");
         newobj.TreePos = treePos;
         newobj.Update();
         return newobj;
      }


      /// <summary>
      /// Generate a package hierarchy that reflects the document layout of BMS-00289, the
      /// ERG Product Software Design Document.
      /// </summary>
      public static void create_BMS00289_Layout()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            if (  ((EA.Package)obj).Packages.Count == 0
               && ((EA.Package)obj).Elements.Count == 0
               && ((EA.Package)obj).Diagrams.Count == 0 )
            {
               EA.Package parentPackage = ((EA.Package)obj);

               EA.Package newobj = null;
               EA.Package newobj2 = null;
               EA.Package newobj3 = null;
               EA.Package newobj4 = null;
               EA.Package newobj5 = null;

               newobj  = createPackage(parentPackage, "Introduction", 1);
               newobj2 = createPackage(newobj, "Purpose", 1);
               newobj2 = createPackage(newobj, "Scope", 2);
               newobj2 = createPackage(newobj, "Terminology", 3);
               newobj2 = createPackage(newobj, "References", 4);

               newobj  = createPackage(parentPackage, "Design Assumptions And Constraints", 2);

               newobj  = createPackage(parentPackage, "System Overview", 3);

               newobj  = createPackage(parentPackage, "High Level Design", 4);
               newobj2 = createPackage(newobj, "Software Architecture", 1);
               newobj2 = createPackage(newobj, "External Interfaces", 2);
               newobj2 = createPackage(newobj, "Internal Interfaces", 3);
               newobj2 = createPackage(newobj, "Memory And Processing Time Allocation", 4);
               newobj2 = createPackage(newobj, "Operational Modes", 5);
               newobj2 = createPackage(newobj, "Component Descriptions", 6);

               newobj = createPackage(parentPackage, "Detailed Design", 5);

               newobj = createPackage(parentPackage, "Unit Test Design",6);

               newobj2 = createPackage(newobj, "Test Data", 1);
               newobj2 = createPackage(newobj, "Test Stubs", 2);
               newobj2 = createPackage(newobj, "Other Elements", 3);
               newobj2 = createPackage(newobj, "Unit Test Traceability To Design", 4);
               newobj2 = createPackage(newobj, "Test Suites and Test Cases", 5);
               newobj3 = createPackage(newobj2, "Test Suite Name", 1);
               newobj4 = createPackage(newobj3, "Test Name", 1);
               newobj5 = createPackage(newobj4, "Description", 1);
               newobj5 = createPackage(newobj4, "Inputs", 2);
               newobj5 = createPackage(newobj4, "Expected Outputs", 3);

               newobj = createPackage(parentPackage, "Requirements Traceability", 7);

               // create an EA_DocGen element
               EA.Element newElement = (EA.Element)parentPackage.Elements.AddNew( "EA_DocGen", "InformationItem" );
               newElement.Notes = "[ElementTypes]\r\nRequirement\r\nClass\r\nComponent\r\n";
               newElement.Update();

               parentPackage.Packages.Refresh();

               // refresh project browser view
               Main.EA_Repository.RefreshModelView(parentPackage.PackageID);
            }
            else
            {
               MessageBox.Show("Can only insert layout into an empty package");
            }
         }
         else
         {
            MessageBox.Show("You must select a package into which the layout will be inserted");
         }
      }


      /// <summary>
      /// Generate a package hierarchy that reflects a basic document layout.
      /// </summary>
      public static void create_basic_Layout()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            if (  ((EA.Package)obj).Packages.Count == 0
               && ((EA.Package)obj).Elements.Count == 0
               && ((EA.Package)obj).Diagrams.Count == 0 )
            {
               EA.Package parentPackage = ((EA.Package)obj);

               EA.Package newobj = null;
               EA.Package newobj2 = null;
               //EA.Package newobj3 = null;
               //EA.Package newobj4 = null;
               //EA.Package newobj5 = null;

               newobj  = createPackage(parentPackage, "Introduction", 1);
               newobj2 = createPackage(newobj, "Purpose", 1);
               newobj2 = createPackage(newobj, "Scope", 2);
               newobj2 = createPackage(newobj, "Terminology", 3);
               newobj2 = createPackage(newobj, "References", 4);

               newobj  = createPackage(parentPackage, "Section 2 (rename me as required)", 2);

               newobj  = createPackage(parentPackage, "Section 3 (rename me as required)", 3);

               // create an EA_DocGen element
               EA.Element newElement = (EA.Element)parentPackage.Elements.AddNew( EA_Constants.EA_DocGenBaseName,
                                                                                  EA_Constants.EA_DocGenElementType );
               newElement.Notes = "[ElementTypes]\r\nRequirement\r\nClass\r\nComponent\r\n";
               newElement.Update();

               parentPackage.Packages.Refresh();

               // refresh project browser view
               Main.EA_Repository.RefreshModelView(parentPackage.PackageID);
            }
            else
            {
               MessageBox.Show("Can only insert layout into an empty package");
            }
         }
         else
         {
            MessageBox.Show("You must select a package into which the layout will be inserted");
         }
      }


      /// <summary>
      /// Generate a package hierarchy that reflects the standard design views.
      /// </summary>
      public static void create_StandardView_Layout()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            EA.Package parentPackage = ((EA.Package)obj);

            EA.Package newobj = null;

            newobj  = createPackage(parentPackage, "Component View", 1);

            newobj  = createPackage(parentPackage, "Deployment View", 2);

            newobj  = createPackage(parentPackage, "Document View", 3);

            newobj  = createPackage(parentPackage, "Logical View", 4);

            newobj = createPackage(parentPackage, "Dynamic View", 5);

            newobj = createPackage(parentPackage, "Requirement View",6);

            newobj = createPackage(parentPackage, "Use Case View", 7);

            parentPackage.Packages.Refresh();

            // refresh project browser view
            Main.EA_Repository.RefreshModelView(parentPackage.PackageID);
         }
         else
         {
            MessageBox.Show("You must select a package into which the layout will be inserted");
         }
      }


      /// <summary>
      /// This function works its way up the parental hierarchy to the root model, collecting the
      /// strings names of each package and prepending them to a string accumulator with a view to
      /// obtaing the full path of an element,diagram, or package.
      /// </summary>
      /// <param name="parentId"></param>
      /// <param name="instr"></param>
      /// <returns></returns>
      public static string GetPackagePath( int parentId, string instr )
      {
         if (parentId != 0)
         {
            EA.Package pkg;
            pkg = Main.EA_Repository.GetPackageByID( parentId );
            if (pkg != null)
            {
               instr = pkg.Name + "/" + instr;
               instr = GetPackagePath(pkg.ParentID, instr);
            }
         }
         return instr;
      }


      private static void copy_GUID_to_clipboard(object obj, EA.ObjectType objType, bool confirm)
      {
         GUID_Clipboard.copy(obj, objType, confirm);
      }


      /// <summary>
      /// For the selected item, copy its GUID to the internal add-in GUID clipboard and the
      /// global external clipboard. Also copy to the internal add-in GUID clipboard, the name of
      /// the element and its type. This will support the AddLinkElement() method.
      /// </summary>
      public static void copy_GUID_to_clipboard()
      {
         EA.ObjectType objType;
         object obj;
         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         GUID_Clipboard.copy(obj, objType, true);
      }


      public static void AddTestTraceabilityElement()
      {
         EA.ObjectType objType;
         object obj;
         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         AddTestTraceabilityElement(obj, objType);
      }
      public static void AddTestTraceabilityElement(object obj, EA.ObjectType objType)
      {
         if (objType == EA.ObjectType.otPackage)
         {
            object newobj = null;

            newobj = ((EA.Package)obj).Elements.AddNew(EA_Constants.EA_DocGenTestTraceability, EA_Constants.EA_DocGenElementType);
            if (newobj != null)
            {
               ((EA.Element)newobj).Update();
            }         
         }
         else
         {
            MessageBox.Show("You must select a package into which the element will be inserted");
         }
      }


      /// <summary>
      /// Using the internal add-in GUID clipboard, paste a test link element into the selected
      /// package.
      /// </summary>
      public static void AddTestLinkElement()
      {
         EA.ObjectType objType;
         object obj;
         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         AddTestLinkElement(obj, objType);
      }

      private static void AddTestLinkElement(object obj, EA.ObjectType objType)
      {
         if (objType == EA.ObjectType.otPackage)
         {
            object newobj = null;

            if (   GUID_Clipboard.objType == EA.ObjectType.otElement
                || GUID_Clipboard.objType == EA.ObjectType.otPackage)
            {
               newobj = ((EA.Package)obj).Elements.AddNew(EA_Constants.EA_DocGenTestLink + " - " + GUID_Clipboard.name, EA_Constants.EA_DocGenElementType);

               if (newobj != null)
               {
                  ((EA.Element)newobj).Notes = GUID_Clipboard.name + "\r\n" + GUID_Clipboard.guid;
                  ((EA.Element)newobj).Update();
               }
            }
            else
            {
               MessageBox.Show("The GUID clipboard must first contain the GUID of an element (normally, a class), or a package");
            }
         }
         else
         {
            MessageBox.Show("You must select a package into which the test link will be inserted");
         }
      }


      /// <summary>
      /// Using the internal add-in GUID clipboard, paste a link element into the selected
      /// package.
      /// </summary>
      public static void AddLinkElement()
      {
         EA.ObjectType objType;
         object obj;
         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         AddLinkElement(obj, objType);
      }

      private static void AddLinkElement(object obj, EA.ObjectType objType)
      {
         if (objType == EA.ObjectType.otPackage)
         {
            object newobj = null;

            if (GUID_Clipboard.objType == EA.ObjectType.otPackage)
            {
               newobj = ((EA.Package)obj).Elements.AddNew(EA_Constants.EA_DocGenPackageLink + " - " + GUID_Clipboard.name, EA_Constants.EA_DocGenElementType);
            }
            else if (GUID_Clipboard.objType == EA.ObjectType.otDiagram)
            {
               newobj = ((EA.Package)obj).Elements.AddNew(EA_Constants.EA_DocGenDiagramLink + " - " + GUID_Clipboard.name, EA_Constants.EA_DocGenElementType);
            }
            else if (GUID_Clipboard.objType == EA.ObjectType.otElement)
            {
               newobj = ((EA.Package)obj).Elements.AddNew(EA_Constants.EA_DocGenElementLink + " - " + GUID_Clipboard.name, EA_Constants.EA_DocGenElementType);
            }
            else if (GUID_Clipboard.objType == EA.ObjectType.otAttribute)
            {
               MessageBox.Show("Attribute links are not currently supported");
            }
            else if (GUID_Clipboard.objType == EA.ObjectType.otMethod)
            {
               MessageBox.Show("Method links are not currently supported");
            }

            if (newobj != null)
            {
               ((EA.Element)newobj).Notes = GUID_Clipboard.name + "\r\n" + GUID_Clipboard.guid;
               ((EA.Element)newobj).Update();
            }
         }
         else
         {
            MessageBox.Show("You must select a package into which the link will be inserted");
         }
      }


      public static void AddNameLinkElement()
      {
         EA.ObjectType objType;
         object obj;
         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         AddNameLinkElement(obj, objType);
      }

      private static void AddNameLinkElement(object obj, EA.ObjectType objType)
      {
         if (objType == EA.ObjectType.otPackage)
         {
            object newobj = null;

            if (GUID_Clipboard.objType == EA.ObjectType.otPackage)
            {
               newobj = ((EA.Package)obj).Elements.AddNew(EA_Constants.EA_DocGenNameLink + " - " + GUID_Clipboard.name, EA_Constants.EA_DocGenElementType);
               if (newobj != null)
               {
                  StringBuilder sb = new StringBuilder();
                  sb.Append(GUID_Clipboard.name);
                  sb.Append("\r\n");
                  sb.Append(GUID_Clipboard.guid);
                  sb.Append("\r\n");
                  sb.Append("### Add as many package names as you like below here.\r\n");
                  sb.Append("### Each should be of the form: package=name\r\n");
                  sb.Append("### Delete any unused package= lines from these notes.\r\n");
                  sb.Append("### The names are case sensitive and must match exactly\r\n");
                  sb.Append("### the names of the packages you wish to pull in to the\r\n");
                  sb.Append("### document model.\r\n");
                  sb.Append("package=\r\n");
                  sb.Append("package=\r\n");
                  sb.Append("package=\r\n");

                  ((EA.Element)newobj).Notes = sb.ToString();
                  ((EA.Element)newobj).Update();
               }            
            }
         }
         else
         {
            MessageBox.Show("You must select a package into which the name link will be inserted");
         }
      }


      public static void AddTableElement()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            object newobj = null;

            newobj = ((EA.Package)obj).Elements.AddNew(EA_Constants.EA_DocGenTable, EA_Constants.EA_DocGenElementType);
            if (newobj != null)
            {
               ((EA.Element)newobj).Notes = "title=insertYourTitleHere\r\n"
                                          + "columns=2\r\n"
                                          + "seperator=,\r\n"
                                          + "indent=1\r\n"
                                          + "widths=column1Width,column2Width\r\n"
                                          + "column1Title,column2Title\r\n"
                                          + "cellcontent,cellcontent\r\n"
                                          + "cellcontent,cellcontent\r\n"
                                          + "cellcontent,cellcontent\r\n"
                                          + "etc,etc";
               ((EA.Element)newobj).Update();
            }
         }
         else
         {
            MessageBox.Show("You must select a package into which the Table Element will be inserted");
         }
      }


      public static void AddTextElement()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            object newobj = null;

            newobj = ((EA.Package)obj).Elements.AddNew(EA_Constants.EA_DocGenText, EA_Constants.EA_DocGenElementType);
            if (newobj != null)
            {
               ((EA.Element)newobj).Notes = "Add your text here.";
               ((EA.Element)newobj).Update();
            }
         }
         else
         {
            MessageBox.Show("You must select a package into which the Text Element will be inserted");
         }
      }


      public static void AddRelationshipMatrixElement()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            RelationshipMatrixType dlg = new RelationshipMatrixType();
            DialogResult dlgRes = dlg.ShowDialog();
            if (dlgRes == DialogResult.OK)
            {
               object newobj = null;
               newobj = ((EA.Package)obj).Elements.AddNew(EA_Constants.EA_DocGenRelationshipMatrix, EA_Constants.EA_DocGenElementType);
               if (newobj != null)
               {
                  ((EA.Element)newobj).Notes  = EA_RelationshipMatrix.optionTemplateForRelationshipMatrix(dlg.style());
                  ((EA.Element)newobj).Update();
               }
            }
         }
         else
         {
            MessageBox.Show("You must select a package into which the RelationshipMatrix Element will be inserted");
         }
      }


      public static void GeneratePackagesFromElementList()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            if (GUID_Clipboard.objType == EA.ObjectType.otPackage)
            {
               EA.Package theFoundPackage = Main.EA_Repository.GetPackageByGuid(GUID_Clipboard.guid);
               if (theFoundPackage != null)
               {
                  EA.Package srcPackage = theFoundPackage;
                  EA.Package destPackage = ((EA.Package)obj);

                  foreach( EA.Element srcElement in srcPackage.Elements)
                  {
                     if (false == EA_Finders.elementNameExistsInPackage(destPackage, srcElement.Name))
                     {
                        createPackage(destPackage, srcElement.Name, 1);
                     }
                  }
               }
            }
            else
            {
               MessageBox.Show("You must first copy a Source Package GUID to the clipboard");
            }
         }
         else
         {
            MessageBox.Show("You must select a Destination Package into which the Generated Packages will be inserted");
         }
      }


      public static void GenerateSubPackageLinks()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            if (GUID_Clipboard.objType == EA.ObjectType.otPackage)
            {
               EA.Package theFoundPackage = Main.EA_Repository.GetPackageByGuid(GUID_Clipboard.guid);
               if (theFoundPackage != null)
               {
                  EA.Package srcPackage = theFoundPackage;
                  EA.Package destPackage = ((EA.Package)obj);

                  GUID_Clipboard.push();

                  foreach( EA.Package subPackage in srcPackage.Packages)
                  {
                     copy_GUID_to_clipboard( (object)subPackage, EA.ObjectType.otPackage, false);
                     AddLinkElement( (object)destPackage, EA.ObjectType.otPackage);
                  }

                  GUID_Clipboard.pop();
               }
            }
            else
            {
               MessageBox.Show("You must first copy a Source Package GUID to the clipboard");
            }
         }
         else
         {
            MessageBox.Show("You must select a Destination Package into which the Sub-Package Links will be inserted");
         }
      }


      public static void GenerateElementLinks()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            if (GUID_Clipboard.objType == EA.ObjectType.otPackage)
            {
               EA.Package theFoundPackage = Main.EA_Repository.GetPackageByGuid(GUID_Clipboard.guid);
               if (theFoundPackage != null)
               {
                  EA.Package srcPackage = theFoundPackage;
                  EA.Package destPackage = ((EA.Package)obj);

                  GUID_Clipboard.push();

                  foreach( EA.Element subElement in srcPackage.Elements)
                  {
                     copy_GUID_to_clipboard( (object)subElement, EA.ObjectType.otElement, false);
                     AddLinkElement( (object)destPackage, EA.ObjectType.otPackage);
                  }

                  GUID_Clipboard.pop();
               }
            }
            else
            {
               MessageBox.Show("You must first copy a Source Package GUID to the clipboard");
            }
         }
         else
         {
            MessageBox.Show("You must select a Destination Package into which the Element Links will be inserted");
         }
      }

      /// <summary>
      /// This function is designed to parse EA models/packages in a predefined way, whilst allowing
      /// a user to specify what processing is to be done upon or with each element found.
      /// </summary>
      /// <param name="thePackage"></param>
      /// <param name="worker"></param>
      /// <param name="recurse"></param>
      public static void findAndProcessPackageElements( EA.Package thePackage, EA_UtilitiesRecursionWorker worker, bool recurse)
      {
         worker.processPackage( thePackage );

         foreach (EA.Element theElement in thePackage.Elements)
         {
            worker.processElement( theElement );
         }

         if (recurse == true)
         {
            foreach (EA.Package subPackage in thePackage.Packages)
            {
               // RECURSION
               findAndProcessPackageElements( subPackage, worker, true);
            }
         }

      }


      public static void addDocumentReference()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            DocReferenceForm dlg = new DocReferenceForm();
            DialogResult dlgRes = dlg.ShowDialog();
            if (dlgRes == DialogResult.OK)
            {
               object newobj = null;

               newobj = ((EA.Package)obj).Elements.AddNew(dlg.textBox_DocNumber.Text, EA_Constants.EA_DocGenElementType);
               if (newobj != null)
               {
                  ((EA.Element)newobj).Notes = dlg.textBox_DocName.Text;
                  ((EA.Element)newobj).Update();
               }
            }
         }
      }


      public static void addTerminology()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            TerminologyForm dlg = new TerminologyForm();
            DialogResult dlgRes = dlg.ShowDialog();
            if (dlgRes == DialogResult.OK)
            {
               object newobj = null;

               newobj = ((EA.Package)obj).Elements.AddNew(dlg.textBox_Term.Text, EA_Constants.EA_DocGenElementType);
               if (newobj != null)
               {
                  ((EA.Element)newobj).Notes = dlg.textBox_TermExpansion.Text;
                  ((EA.Element)newobj).Update();
               }
            }
         }
      }


      public static string ReadTag(EA.Package thePackage, string tagName)
      {
         EA.Element theElement = Main.EA_Repository.GetElementByGuid(thePackage.PackageGUID);
         if (theElement != null)
         {
            return ReadTag(theElement, tagName);
         }
         return "";
      }

      public static string ReadTag(EA.Element theElement, string tagName)
      {
         string result;

         EA.TaggedValue tag = (EA.TaggedValue)theElement.TaggedValues.GetByName(tagName);
         if (null != tag)
         {
            result = tag.Value;
         }
         else
         {
            result = "";
         }
         return result;
      }

      public static bool WriteTag(EA.Package thePackage, string tagName, string value)
      {
         EA.Element theElement = Main.EA_Repository.GetElementByGuid(thePackage.PackageGUID);
         if (theElement != null)
         {
            return WriteTag(theElement, tagName, value);
         }
         return false;
      }

      public static bool WriteTag(EA.Element theElement, string tagName, string value)
      {
         bool result;
         EA.TaggedValue tag;
            
         tag = (EA.TaggedValue)theElement.TaggedValues.GetByName(tagName);
         if (null != tag)
         {
            tag.Value = value;
         }
         else
         {
            tag = (EA.TaggedValue)theElement.TaggedValues.AddNew(tagName, value);
         }

         if (tag != null)
         {
            result = tag.Update();
         }
         else
         {
            result = false;
         }
         return result;
      }


      public static void RemoveAPIStereotypeFromContent()
      {
         EA.ObjectType objType;
         object obj;
         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            RemoveAPIStereotypeFromContent((EA.Package)obj);
            Main.EA_Repository.RefreshModelView(((EA.Package)obj).PackageID);
         }
         else if (objType == EA.ObjectType.otDiagram)
         {
            RemoveAPIStereotypeFromDiagram((EA.Diagram)obj);
            Main.EA_Repository.RefreshModelView(((EA.Diagram)obj).PackageID);
         }
         else if (objType == EA.ObjectType.otElement)
         {
            RemoveAPIStereotypeFromContent((EA.Element)obj);
            Main.EA_Repository.RefreshModelView(((EA.Element)obj).PackageID);
         }
      }

      private static void RemoveAPIStereotypeFromPackage(EA.Package thePackage)
      {
         thePackage.StereotypeEx = thePackage.StereotypeEx.Replace(",API","");
         thePackage.StereotypeEx = thePackage.StereotypeEx.Replace("API,","");
         thePackage.StereotypeEx = thePackage.StereotypeEx.Replace("API","");
         thePackage.Update();
      }

      private static void RemoveAPIStereotypeFromDiagram(EA.Diagram theDiagram)
      {
         // diagrams only use one stereotype, not a list of them
         if (theDiagram.Stereotype.Equals("API"))
         {
            theDiagram.Stereotype = "";
            theDiagram.Update();
         }
      }

      private static void RemoveAPIStereotypeFromElement(EA.Element theElement)
      {
         theElement.StereotypeEx = theElement.StereotypeEx.Replace(",API","");
         theElement.StereotypeEx = theElement.StereotypeEx.Replace("API,","");
         theElement.StereotypeEx = theElement.StereotypeEx.Replace("API","");
         theElement.Update();
      }

      private static void RemoveAPIStereotypeFromContent(EA.Package thePackage)
      {
         RemoveAPIStereotypeFromPackage(thePackage);

         foreach(EA.Diagram diagram in thePackage.Diagrams)
         {
            RemoveAPIStereotypeFromDiagram(diagram);
         }

         foreach(EA.Element element in thePackage.Elements)
         {
            RemoveAPIStereotypeFromElement(element);
         }

         foreach(EA.Package package in thePackage.Packages)
         {
            RemoveAPIStereotypeFromContent(package); // recursion
         }
      }

      private static void RemoveAPIStereotypeFromContent(EA.Element theElement)
      {
         RemoveAPIStereotypeFromElement(theElement);

         foreach(EA.Diagram diagram in theElement.Diagrams)
         {
            RemoveAPIStereotypeFromDiagram(diagram);
         }

         foreach(EA.Element element in theElement.Elements)
         {
            RemoveAPIStereotypeFromContent(element); // recursion
         }
      }


      public static void MarkContentWithAPIStereotype()
      {
         EA.ObjectType objType;
         object obj;
         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            MarkContentWithAPIStereotype((EA.Package)obj);
            Main.EA_Repository.RefreshModelView(((EA.Package)obj).PackageID);
         }
         else if (objType == EA.ObjectType.otDiagram)
         {
            MarkDiagramWithAPIStereotype((EA.Diagram)obj);
            Main.EA_Repository.RefreshModelView(((EA.Diagram)obj).PackageID);
         }
         else if (objType == EA.ObjectType.otElement)
         {
            MarkContentWithAPIStereotype((EA.Element)obj);
            Main.EA_Repository.RefreshModelView(((EA.Element)obj).PackageID);
         }
      }

      private static void MarkPackageWithAPIStereotype(EA.Package thePackage)
      {
         if (thePackage.StereotypeEx.IndexOf("API") < 0)
         {
            if (thePackage.StereotypeEx.Length > 0)
               thePackage.StereotypeEx += ",API";
            else
               thePackage.StereotypeEx = "API";
            thePackage.Update();
         }
      }

      private static void MarkDiagramWithAPIStereotype(EA.Diagram theDiagram)
      {
         // diagrams only use one stereotype, not a list of them
         theDiagram.Stereotype = "API";
         theDiagram.Update();
      }

      private static void MarkElementWithAPIStereotype(EA.Element theElement)
      {
         if (theElement.StereotypeEx.IndexOf("API") < 0)
         {
            if (theElement.StereotypeEx.Length > 0)
               theElement.StereotypeEx += ",API";
            else
               theElement.Stereotype = "API";
            theElement.Update();
         }
      }

      private static void MarkContentWithAPIStereotype(EA.Package thePackage)
      {
         MarkPackageWithAPIStereotype(thePackage);

         foreach(EA.Diagram diagram in thePackage.Diagrams)
         {
            MarkDiagramWithAPIStereotype(diagram);
         }

         foreach(EA.Element element in thePackage.Elements)
         {
            MarkElementWithAPIStereotype(element);
         }

         foreach(EA.Package package in thePackage.Packages)
         {
            MarkContentWithAPIStereotype(package); // recursion
         }
      }

      private static void MarkContentWithAPIStereotype(EA.Element theElement)
      {
         MarkElementWithAPIStereotype(theElement);

         foreach(EA.Diagram diagram in theElement.Diagrams)
         {
            MarkDiagramWithAPIStereotype(diagram);
         }

         foreach(EA.Element element in theElement.Elements)
         {
            MarkContentWithAPIStereotype(element); // recursion
         }
      }

      /// <summary>
      /// This processes a requirement tag for use when sorting requirements, in a way designed to overcome 
      /// the problem of sorting alphanumeric strings that contain outline numberig but that do not use
      /// leading zero's in that nunmbering, which distorts the sorting outcome in a way that is undesirable 
      /// for the human reader.
      /// The function will also work ok if the input string does not contain any numbering.
      /// The output of the function is to be used in compare operations by IComparer derived classes.
      /// </summary>
      /// <param name="sIn"></param>
      /// <param name="desiredFieldWidth"></param>
      /// <returns></returns>
      public static string OutlineNumberMunging(string sIn, int desiredFieldWidth)
      {
         // create a "fabric" filled with 0's into which we can serialise our resulting string
         const int max_str_len = 100;     // should easily be big enough for a requirement tag.
         string sOut = new string('0',max_str_len);   
         char[] sOutChArr = sOut.ToCharArray();
         
         int iIn = 0;
         int iOut = 0;

         while (iIn < sIn.Length && iOut < max_str_len)
         {
            if ( System.Char.IsNumber(sIn[iIn]) )
            {
               // Here we have to work out how long the number is, and determine how many leading
               // zeros to give it. We assume that the desired field width as given to us is always going 
               // to be sufficient for our needs here. If this is not the case, then the worse that can 
               // happen is that the number will have no leading zeros, and the sorting of tags may not
               // be perfect.
               int iLookAhead = iIn+1;
               while (iLookAhead < sIn.Length && System.Char.IsNumber(sIn[iLookAhead]))
               {
                  iLookAhead++;
               }
               int numberLength = iLookAhead - iIn;

               int numberOfLeadingZerosRequired = desiredFieldWidth - numberLength;

               // advance by the count of leading zeros required.
               if (numberOfLeadingZerosRequired > 0)
                  iOut += numberOfLeadingZerosRequired;

               // Serialise the number. We dont have to serialise the leading zero's because our char array 
               // was initialised with 0's to begin with.
               while(numberLength > 0 && iOut < max_str_len)
               {
                  sOutChArr[iOut++] = sIn[iIn++];  // serialise a char forming the number
                  numberLength--;
               }
            }
            else if (sIn[iIn] == '.')  // do not feed '.' chars through to the output because they can mess up the sorting of tags
            {
               iOut++;
               iIn++;
            }
            else
            {
               sOutChArr[iOut++] = sIn[iIn++];  // just serialise the char from input to output
            }
         }
           
         // If we did produce an output string, return it, else return the input unaltered.
         if (iOut > 0)
            return new string(sOutChArr); 
         else
            return sIn;
      }


      #region Temporary or experimental code


      private static void parse_element(int parentId, EA.Element theElement, int recurse_level)
      {
         Main.EA_Repository.WriteOutput( Main.GUI_OUTPUT_TAB_NAME, 
            "ParentId:"
            + parentId.ToString()
            + ", Level:"
            + recurse_level.ToString()
            + ", TreePos:"
            + theElement.TreePos.ToString() 
            + ", ELE-ParentID:"
            + theElement.ParentID.ToString()
            + ", ELE-PackageID:"
            + theElement.PackageID.ToString()
            + ", ELE-ElementID:"
            + theElement.ElementID.ToString()
            + ",  ELE-Name: " 
            + theElement.Name, -1);
         
         foreach(EA.Diagram theDiagram in theElement.Diagrams)
         {
            Main.EA_Repository.WriteOutput( Main.GUI_OUTPUT_TAB_NAME, 
               "Level:"
               + recurse_level.ToString() 
               + ", ParentID:"
               + theDiagram.ParentID.ToString()
               + ", PackageID:"
               + theDiagram.PackageID.ToString()
               + ", DiagramID:"
               + theDiagram.DiagramID.ToString()
               + "  DIAGRAM: " 
               + theDiagram.Name, -1);
         }

         foreach(EA.Element subElement in theElement.Elements)
         {
            parse_element(theElement.ElementID, subElement, recurse_level+1);
         }
      }


      /// <summary>
      /// Parse a package structure in a similar way to that taken when users are generating a word
      /// document, only here we simply write diagnostic text to the output tab.
      /// </summary>
      /// <param name="thePackage"></param>
      /// <param name="recurse_level"></param>
      private static void parse_package(EA.Package thePackage, int recurse_level)
      {
         Main.EA_Repository.WriteOutput( Main.GUI_OUTPUT_TAB_NAME, 
                                      "Level:"
                                    + recurse_level.ToString() 
                                    + ", ParentID:"
                                    + thePackage.ParentID.ToString()
                                    + ", PackageID:"
                                    + thePackage.PackageID.ToString()
                                    + ",  PACKAGE: " 
                                    + thePackage.Name, -1);

         // default handling of diagrams
         foreach(EA.Diagram theDiagram in thePackage.Diagrams)
         {
            if (theDiagram.ParentID == 0)
            {
               Main.EA_Repository.WriteOutput( Main.GUI_OUTPUT_TAB_NAME, 
                  "Level:"
                  + recurse_level.ToString() 
                  + ", ParentID:"
                  + theDiagram.ParentID.ToString()
                  + ", PackageID:"
                  + theDiagram.PackageID.ToString()
                  + ", DiagramID:"
                  + theDiagram.DiagramID.ToString()
                  + "  DIAGRAM: " 
                  + theDiagram.Name, -1);
            }
         }

         foreach(EA.Element subElement in thePackage.Elements)
         {
            if (subElement.ParentID == 0 || thePackage.PackageID == subElement.ParentID)
               parse_element(thePackage.PackageID, subElement, recurse_level+1);
         }

         foreach(EA.Package lowerLevelPackage in thePackage.Packages)
         {
            parse_package(lowerLevelPackage, recurse_level+1);
         }
      }


      /// <summary>
      /// Parses a specified package in a similar way to what would be done if a user were generating
      /// a word document, but here do nothing except write diagnostic text to the output tab.
      /// </summary>
      public static void showDiscoveryOrder()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            EA.Package EA_ParentPackage = ((EA.Package)obj);

            Main.EA_Repository.EnsureOutputVisible(Main.GUI_OUTPUT_TAB_NAME);
            Main.EA_Repository.WriteOutput( Main.GUI_OUTPUT_TAB_NAME, "", -1);
            Main.EA_Repository.WriteOutput( Main.GUI_OUTPUT_TAB_NAME, "Showing Object Discovery order for " + EA_ParentPackage.Name, -1);

            parse_package(EA_ParentPackage, 1);
         }
         else
         {
            MessageBox.Show("You must select a package to parse");
         }
      }


      public static void SaveVersionControlledPackage()
      {
         EA.ObjectType objType;
         object obj;

         objType = Main.EA_Repository.GetTreeSelectedItem( out obj );
         if (objType == EA.ObjectType.otPackage)
         {
            EA.Package EA_Package = ((EA.Package)obj);

            if (EA_Package.IsControlled == true)
            {
               EA.Project EA_Project = Main.EA_Repository.GetProjectInterface();

               EA_Project.SaveControlledPackage( EA_Package.PackageGUID );

               //EA_Project.SaveControlledPackage( EA_Project.GUIDtoXML( EA_Package.PackageGUID ) );
            }
            else
            {
               MessageBox.Show("The package selected is not version controlled");
            }
          }
         else
         {
            MessageBox.Show("You must select a package");
         }
      }


      #endregion
        }

  
}