<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to DesignDecisions</title><link>https://sourceforge.net/p/esitools/wiki2/DesignDecisions/</link><description>Recent changes to DesignDecisions</description><atom:link href="https://sourceforge.net/p/esitools/wiki2/DesignDecisions/feed" rel="self"/><language>en</language><lastBuildDate>Fri, 27 Jun 2014 21:49:50 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/esitools/wiki2/DesignDecisions/feed" rel="self" type="application/rss+xml"/><item><title>DesignDecisions modified by Graham Shanks</title><link>https://sourceforge.net/p/esitools/wiki2/DesignDecisions/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v1
+++ v2
@@ -25,14 +25,14 @@

 There are a number of consequences of this: 

-  1. We need to store additional intermediate objects as member variables to ensure that we can release intermediate objects in the correct order 
-  2. Certain simple functions need to reorganised to ensure that objects are released. For instance the obvious implementation of the NumberOfRows methods is 
-        
+1. We need to store additional intermediate objects as member variables to ensure that we can release intermediate objects in the correct order 
+
+2. Certain simple functions need to reorganised to ensure that objects are released. For instance the obvious implementation of the NumberOfRows methods is 
+
         public int NumberOfRows { get { return myWorksheet.UsedRange.Rows.Count; } }
-        
-
-However this creates two temporary COM objects that cannot be released properly. The solution is to refactor this to replace the temporaries with assignments to actual variables so that we can release them properly: 
-        
+
+3. However this creates two temporary COM objects that cannot be released properly. The solution is to refactor this to replace the temporaries with assignments to actual variables so that we can release them properly: 
+
         public int NumberOfRows
         {
           get
@@ -47,10 +47,9 @@
             return result;
           }
         }
-        
-
-  3. Care needs to be taken to ensure that objects are released even in the presence of exceptions - in practise this means that methods that use interop functions need to include exception handlers to perform proper clean-up. In fact the actual implementation of NumberOfRows is: 
-        
+
+4. Care needs to be taken to ensure that objects are released even in the presence of exceptions - in practise this means that methods that use interop functions need to include exception handlers to perform proper clean-up. In fact the actual implementation of NumberOfRows is: 
+
         public int NumberOfRows
         {
           get
@@ -80,18 +79,19 @@
         }

-  4. Users really need to call the _Dispose_ method on the Excel wrappers (e.g. CRfile and CRstatus). In fact we implement the _IDisposable_ interface allowing us to use the _using_ construct, which leads to much nicer looking user code: 
-    
-    using (ChangeRequest.CRfile file = new ChangeRequest.CRfile("FooBar.xls"))
-    {
-      System.Console.Writeline("Change request version: {0}", file.version);
-      ...
-    }
+5. Users really need to call the _Dispose_ method on the Excel wrappers (e.g. CRfile and CRstatus). In fact we implement the _IDisposable_ interface allowing us to use the _using_ construct, which leads to much nicer looking user code: 
+
+
+        using (ChangeRequest.CRfile file = new ChangeRequest.CRfile("FooBar.xls"))
+        {
+          System.Console.Writeline("Change request version: {0}", file.version);
+          ...
+        }

 ## Accessing Excel Headers and Footers

-I found that the unit tests for manipulating Excel headers and footers was taking a long time (the test took about 5 minutes). I originally thought that the problem was creating and deleting the Page Setup object. However, as many first thoughts about performance are, this was wrong. The problem is that any access to element in the page setup references the default printer. In my case the defualt printer is a network printer, so if disconnected from the network (which is the case for most of my work on ESI tools) then the access to the printer is the reason for the slow performance (). The way round this is to set the printer to the Microsoft XPS Document Writer, which is guaranteed to be local. Unfortunately we need to also determine which port the printer is on. Since the port is not necessarily the same on all computers we need to loop through possible ports - most are of the form nexx (where xx is is a numeric value), or LPTx (where x is numeric). We loop through each of the ports trying to set the active printer to "Microsoft XPS Document Writer on XYZ" (where XYZ is the port) if we succeed then we continue - if we don't succeed then we revert to using the default printer and take the performance hit. On my machine using the Microsoft XPS Document Writer results in a 10x performance gain (~30s against ~300s for the header/footer test) which is definately worthwhile. 
+I found that the unit tests for manipulating Excel headers and footers was taking a long time (the test took about 5 minutes). I originally thought that the problem was creating and deleting the Page Setup object. However, as many first thoughts about performance are, this was wrong. The problem is that any access to element in the page setup references the default printer. In my case the default printer is a network printer, so if disconnected from the network (which is the case for most of my work on ESI tools) then the access to the printer is the reason for the slow performance (). The way round this is to set the printer to the Microsoft XPS Document Writer, which is guaranteed to be local. Unfortunately we need to also determine which port the printer is on. Since the port is not necessarily the same on all computers we need to loop through possible ports - most are of the form nexx (where xx is is a numeric value), or LPTx (where x is numeric). We loop through each of the ports trying to set the active printer to "Microsoft XPS Document Writer on XYZ" (where XYZ is the port) if we succeed then we continue - if we don't succeed then we revert to using the default printer and take the performance hit. On my machine using the Microsoft XPS Document Writer results in a 10x performance gain (~30s against ~300s for the header/footer test) which is definately worthwhile. 

 ## Out of Data Change Requests

@@ -105,25 +105,12 @@

 We should catch mismatches conflicts between the Change Request Number (CRN) contained in the file name (e.g., _CR166 - Add My Frigate.xls_) and the CRN contained inside the Change Request (CR) file. 

-**Name CRN**
-**Internal CRN**
-**Comments**
-
-0 
-0 
-This is valid and indicates that the CR is new 
-
-0 
-Non-Zero 
-This may indicate that the CR Submitter created a new CR by copying from a previous one. This is OK, but the Tool Superviser ought to check the CR referenced in the CR to check that this is not a mistake. The Registrar shall report an error. 
-
-Non-zero 
-0 
-For version 1 CRs this is expected and shall not be flagged as an error. For version 2 CRs this is probably a simple error by the CR Submitter (possibly it is meant to be an update, with the Submitter merely editing her original file rather than the official one posted back to the reflector. The Tool Supervisor ought to check. The Registrar shall report an error. 
-
-Non-zero 
-Non-zero 
-If the two CRNs are the same then this is OK, however if they are not the same then this is an error, which the Registrar shall report 
+**Name CRN** | **Internal CRN** | **Comments**
+-------------|------------------|--------------
+0            | 0                | This is valid and indicates that the CR is new 
+0            | Non-Zero         | This may indicate that the CR Submitter created a new CR by copying from a previous one. This is OK, but the Tool Superviser ought to check the CR referenced in the CR to check that this is not a mistake. The Registrar shall report an error. 
+Non-zero     | 0                | For version 1 CRs this is expected and shall not be flagged as an error. For version 2 CRs this is probably a simple error by the CR Submitter (possibly it is meant to be an update, with the Submitter merely editing her original file rather than the official one posted back to the reflector. The Tool Supervisor ought to check. The Registrar shall report an error. 
+Non-zero     | Non-zero         | If the two CRNs are the same then this is OK, however if they are not the same then this is an error, which the Registrar shall report 

 ## Verification Mode of Operation

@@ -180,177 +167,33 @@

 OK, this is one that I've put a lot of thought into and it should start from a fresh DB. The issue is tracking updated CRs. Consider the ASLAV CR posted by Bernard Leclerc in October last year (CR2308). His original CR was for: 

-Add 
-1 
-1 
-39 
-5 
-1 
-ASLAV 
-
-Add 
-1 
-1 
-39 
-5 
-1 
-1 
-ASLAV-25 
-
-Add 
-1 
-1 
-39 
-5 
-1 
-2 
-ASLAV-PC 
-
-Add 
-1 
-1 
-39 
-5 
-1 
-3 
-ASLAV-C 
-
-Add 
-1 
-1 
-39 
-5 
-1 
-4 
-ASLAV-S 
-
-Add 
-1 
-1 
-39 
-5 
-1 
-5 
-ASLAV-A 
-
-Add 
-1 
-1 
-39 
-5 
-1 
-6 
-ASLAV-F 
-
-Add 
-1 
-1 
-39 
-5 
-1 
-7 
-ASLAV-R 
+**Type**|**Kind**|**Domain**|**Country**|**Category**|**Subcategory**|**Specific**|**Name**
+--------|--------|----------|-----------|------------|---------------|------------|--------
+Add     | 1      | 1        | 39        | 5          | 1             |            | ASLAV 
+Add     | 1      | 1        | 39        | 5          | 1             | 1          | ASLAV-25 
+Add     | 1      | 1        | 39        | 5          | 1             | 2          | ASLAV-PC 
+Add     | 1      | 1        | 39        | 5          | 1             | 3          | ASLAV-C 
+Add     | 1      | 1        | 39        | 5          | 1             | 4          | ASLAV-S 
+Add     | 1      | 1        | 39        | 5          | 1             | 5          | ASLAV-A 
+Add     | 1      | 1        | 39        | 5          | 1             | 6          | ASLAV-F 
+Add     | 1      | 1        | 39        | 5          | 1             | 7          | ASLAV-R 

 After some discussions an update was posted (CR2308A) with the following: 

-Add 
-1 
-1 
-39 
-Country 39 = Canada 
-
-Add 
-1 
-1 
-39 
-2 
-Category 2 = Armored Fighting Vehicle 
-
-Add 
-1 
-1 
-39 
-2 
-1 
-Subcategory 1 = Light Armored Vehicle (LAV) 
-
-Add 
-1 
-1 
-39 
-2 
-1 
-1 
-ASLAV-25 Reconnaissance 
-
-Add 
-1 
-1 
-39 
-2 
-1 
-2 
-ASLAV-PC Personnel Carrier 
-
-Add 
-1 
-1 
-39 
-2 
-1 
-3 
-ASLAV-S Surveillance 
-
-Add 
-1 
-1 
-39 
-3 
-Category 3 = Armored Utility Vehicle 
-
-Add 
-1 
-1 
-39 
-3 
-1 
-Subcategory 1 = Light Armored Vehicle (LAV) 
-
-Add 
-1 
-1 
-39 
-3 
-1 
-1 
-ASLAV-C Command 
-
-Add 
-1 
-1 
-39 
-3 
-1 
-2 
-ASLAV-A Ambulance 
-
-Add 
-1 
-1 
-39 
-3 
-1 
-3 
-ASLAV-F Fitters 
-
-Add 
-1 
-1 
-39 
-3 
-1 
-4 
-ASLAV-R Recovery 
+**Type**|**Kind**|**Domain**|**Country**|**Category**|**Subcategory**|**Specific**|**Name**
+--------|--------|----------|-----------|------------|---------------|------------|--------
+Add     | 1      | 1        | 39        |   |   |   | Country 39 = Canada 
+Add     | 1      | 1        | 39        | 2 |   |   | Category 2 = Armored Fighting Vehicle 
+Add     | 1      | 1        | 39        | 2 | 1 |   | Subcategory 1 = Light Armored Vehicle (LAV) 
+Add     | 1      | 1        | 39        | 2 | 1 | 1 | ASLAV-25 Reconnaissance 
+Add     | 1      | 1        | 39        | 2 | 1 | 2 | ASLAV-PC Personnel Carrier 
+Add     | 1      | 1        | 39        | 2 | 1 | 3 | ASLAV-S Surveillance 
+Add     | 1      | 1        | 39        | 3 |   |   | Category 3 = Armored Utility Vehicle 
+Add     | 1      | 1        | 39        | 3 | 1 |   | Subcategory 1 = Light Armored Vehicle (LAV) 
+Add     | 1      | 1        | 39        | 3 | 1 | 1 | ASLAV-C Command 
+Add     | 1      | 1        | 39        | 3 | 1 | 2 | ASLAV-A Ambulance 
+Add     | 1      | 1        | 39        | 3 | 1 | 3 | ASLAV-F Fitters 
+Add     | 1      | 1        | 39        | 3 | 1 | 4 | ASLAV-R Recovery 

 If we don't start from a fresh DB then the Updater needs to undo CR2308. Since these are all additions then this is not too difficult, but it does mean that it needs to process the original CR file and undo the additions, then process the new file and add the new enumerations. If the CR updates the description for an enumeration then the problem is even worse since the old description is not in the database any more, nor is it contained in the CR. To undo a changed description then the Updater has to process all previous CRs all the way back to the last baseline (i.e., approved XML database) just in case one of them added or changed the description and, if none of the previous CRs affected the enumeration or its description, then extract the description from the baselined XML database. 

@@ -430,55 +273,30 @@

 The Op Manual (SISO-REF-010.1) show examples on how categories that are in the XML file, but not contained in the CR are automatically added. For example consider the following CR: 

-**Change Type**
-**Enumeration**
-**Name**
-
-Add 
-1.3.224.5.1 
-Type 77 
+**Change Type** | **Enumeration** | **Name**
+----------------|-----------------|---------
+Add             | 1.3.224.5.1     | Type 77 

 Currently the UK has no category 5 entities. However, category 5 for the surface domain is defined. Therefore the toolset will automatically add the "missing" category, so that it would be as if the submitter had asked for the following: 

-**Change Type**
-**Enumeration**
-**Name**
-
-Add 
-1.3.224.5 
-Destroyer (DD) 
-
-Add 
-1.3.224.5.1 
-Type 77 
+**Change Type** | **Enumeration** | **Name**
+----------------|-----------------|----------
+Add             | 1.3.224.5       | Destroyer (DD) 
+Add             | 1.3.224.5.1     | Type 77 

 The civilian aircraft modifications extended this by specifying subcategories as well, so 

-**Change Type**
-**Enumeration**
-**Name**
-
-Add 
-1.2.225.85.11 
-Cessna 172 Skyhawk 
+**Change Type** | **Enumeration** | **Name**
+----------------|-----------------|----------
+Add             | 1.2.225.85.11   | Cessna 172 Skyhawk 

 The toolset will automatically add the category and subcategory as follows: 

-**Change Type**
-**Enumeration**
-**Name**
-
-Add 
-1.2.225.85 
-Civilian Fixed Wing Aircraft, Large (up to 255,000 lbs / 115,666 kg) 
-
-Add 
-1.2.225.85.11 
-Single Piston Engine 
-
-Add 
-1.2.225.85.11.1 
-Cessna 172 Skyhawk 
+**Change Type** | **Enumeration** | **Name**
+----------------|-----------------|----------
+Add             | 1.2.225.85      | Civilian Fixed Wing Aircraft, Large (up to 255,000 lbs / 115,666 kg) 
+Add             | 1.2.225.85.11   | Single Piston Engine 
+Add             | 1.2.225.85.11.1 | Cessna 172 Skyhawk 

 Early versions of the toolset hard wired the look up. Ideally we would like to use information in the XML database to drive this information 

@@ -501,9 +319,9 @@

 To show how the toolset fills in the missing elements take the following example of an old British glider: 

-Add 
-1.2.224.83.1.1 
-Vickers-Slingsby T-65 Vega 
+**Change Type** | **Enumeration** | **Name**
+----------------|-----------------|----------
+Add             | 1.2.224.83.1.1  | Vickers-Slingsby T-65 Vega 

 Working through the flowchart we get the following: 

@@ -522,9 +340,9 @@

 Consider the slightly modified version of the above example: 

-Add 
-1.2.224.83.3.1 
-Vickers-Slingsby T-65 Vega 
+**Change Type** | **Enumeration** | **Name**
+----------------|-----------------|----------
+Add             | 1.2.224.83.3.1  | Vickers-Slingsby T-65 Vega 

 Working through the flowchart we get the following: 

@@ -542,9 +360,9 @@

 To show what happens when the user tries to add something that is already specified in a category/subcategory table consider the following: 

-Add 
-1.2.224.83.1 
-Sail Plane 
+**Change Type** | **Enumeration** | **Name**
+----------------|-----------------|----------
+Add             | 1.2.224.83.1    | Sail Plane 

 Working through the flowchart we get the following: 

@@ -563,25 +381,12 @@

 Each entity type category and subcategory definition table has an associated _Applicability_ attribute which is a string with kind, domain and, if applicable, category. To make things more readable we use the letter _X_ in place of the country code. Ranges are allowed (since, for instance, some subcategory tables are applicable to multiple catagories). So for instance we have 

-**Applicability**
-**Table UID**
-**Description**
-
-1.2.X 
-10 
-Categories for air platforms 
-
-1.2.X.81 
-275 
-Subcategories for Civilian Ultralight Aircraft, Rigid Wing 
-
-1.2.X.83 
-276 
-Subcategories for Civilian Fixed Wing Aircraft, Glider 
-
-1.2.X.84-88 
-277 
-Subcategories for Civilian Fixed Wing Aircraft Light Sport; Small; Medium; Large; and Heavy 
+**Applicability** | **Table UID** | **Description**
+------------------|---------------|----------------
+1.2.X             | 10            | Categories for air platforms 
+1.2.X.81          | 275           | Subcategories for Civilian Ultralight Aircraft, Rigid Wing 
+1.2.X.83          | 276           | Subcategories for Civilian Fixed Wing Aircraft, Glider 
+1.2.X.84-88       | 277           | Subcategories for Civilian Fixed Wing Aircraft Light Sport; Small; Medium; Large; and Heavy 

 So a search for entity _1.2.225_ will return table 10, a search for entity _1.2.224.83_ (see example 1) will return table 276, a search for _1.2.222.85_ will return table 277 (85 is in the range 84 to 88), whereas both _1.2.72.82_ and _1.2.224.83.1_ will not find any table. 

&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Graham Shanks</dc:creator><pubDate>Fri, 27 Jun 2014 21:49:50 -0000</pubDate><guid>https://sourceforge.net06b9a106b878651fe112268c3b39be998f46e7b7</guid></item><item><title>DesignDecisions modified by &lt;REDACTED&gt;</title><link>https://sourceforge.net/p/esitools/wiki2/DesignDecisions/</link><description>&lt;div class="markdown_content"&gt;&lt;h1 id="design-decisions"&gt;Design Decisions&lt;/h1&gt;
&lt;p&gt;This section records some of the design decisions made during the development of the EBV tools. Note that these are decisions made about the design of the tools, and to a lesser extent the work flow, not decisions about the requirements, which are decided by the Enumerations Working Group (EWG) of the DIS Product Support Group. &lt;/p&gt;
&lt;h2 id="rationale-for-info-tool"&gt;Rationale for Info tool&lt;/h2&gt;
&lt;p&gt;Manual Change Requests (CRs) often add tables into the database, each table requires the allocation of a UID - which is one greater than the largest current UID. Since the Registrar already does this calculation, and it would be error prone to do this manually, the Info tool will calculate and display the current largest UID to the user &lt;/p&gt;
&lt;h2 id="ensuring-proper-clean-up-of-excel-interop-objects"&gt;Ensuring proper clean-up of Excel interop objects&lt;/h2&gt;
&lt;p&gt;One of the major problems of using Excel via interop is ensuring that the interop objects are cleaned up properly. The issue, and its solution, is described by Microsoft in &lt;a href="http://support.microsoft.com/kb/317109" rel="nofollow"&gt;http://support.microsoft.com/kb/317109&lt;/a&gt;. A good discussion of the issue can be found at &lt;a href="http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c" rel="nofollow"&gt;http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c&lt;/a&gt;. Note that so long as the com objects are released properly it appears not be be necessary (so far) to force the garbage collection to cycle. &lt;/p&gt;
&lt;p&gt;The basic rule is to assign all COM objects to variable and to call &lt;code&gt;ReleaseComObject&lt;/code&gt; on all variables in reverse order of their creation. Oh, and assign the variable to &lt;code&gt;nul&lt;/code&gt; after the release. To prevent the creation of temporary objects we need to obey the two dots rule: never use two dots with COM objects. So instead of &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;Workbook&lt;/span&gt; &lt;span class="n"&gt;myWorkbook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Workbooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;which creates a temporary Workbooks object which can never be released, we need to use &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;Workbooks&lt;/span&gt; &lt;span class="n"&gt;myBooks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Workbooks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Workbook&lt;/span&gt; &lt;span class="n"&gt;myWorkbook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myBooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then &lt;code&gt;myBooks&lt;/code&gt; and &lt;code&gt;myWorkbook&lt;/code&gt; can be safely released. &lt;/p&gt;
&lt;p&gt;There are a number of consequences of this: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We need to store additional intermediate objects as member variables to ensure that we can release intermediate objects in the correct order &lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Certain simple functions need to reorganised to ensure that objects are released. For instance the obvious implementation of the NumberOfRows methods is &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;NumberOfRows&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;myWorksheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UsedRange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;However this creates two temporary COM objects that cannot be released properly. The solution is to refactor this to replace the temporaries with assignments to actual variables so that we can release them properly: &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;NumberOfRows&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Range&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myWorksheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UsedRange&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Range&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InteropServices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReleaseComObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InteropServices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReleaseComObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Care needs to be taken to ensure that objects are released even in the presence of exceptions - in practise this means that methods that use interop functions need to include exception handlers to perform proper clean-up. In fact the actual implementation of NumberOfRows is: &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;NumberOfRows&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;get&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Range&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Range&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;try&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myWorksheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UsedRange&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;finally&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InteropServices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReleaseComObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InteropServices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReleaseComObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Users really need to call the &lt;em&gt;Dispose&lt;/em&gt; method on the Excel wrappers (e.g. CRfile and CRstatus). In fact we implement the &lt;em&gt;IDisposable&lt;/em&gt; interface allowing us to use the &lt;em&gt;using&lt;/em&gt; construct, which leads to much nicer looking user code: &lt;/p&gt;
&lt;p&gt;using (ChangeRequest.CRfile file = new ChangeRequest.CRfile("FooBar.xls"))&lt;br /&gt;
{&lt;br /&gt;
  System.Console.Writeline("Change request version: {0}", file.version);&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="accessing-excel-headers-and-footers"&gt;Accessing Excel Headers and Footers&lt;/h2&gt;
&lt;p&gt;I found that the unit tests for manipulating Excel headers and footers was taking a long time (the test took about 5 minutes). I originally thought that the problem was creating and deleting the Page Setup object. However, as many first thoughts about performance are, this was wrong. The problem is that any access to element in the page setup references the default printer. In my case the defualt printer is a network printer, so if disconnected from the network (which is the case for most of my work on ESI tools) then the access to the printer is the reason for the slow performance (&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/8b2a0988-7d09-4abf-a4d3-76e81f708d40/" rel="nofollow"&gt;http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/8b2a0988-7d09-4abf-a4d3-76e81f708d40/&lt;/a&gt;). The way round this is to set the printer to the Microsoft XPS Document Writer, which is guaranteed to be local. Unfortunately we need to also determine which port the printer is on. Since the port is not necessarily the same on all computers we need to loop through possible ports - most are of the form nexx (where xx is is a numeric value), or LPTx (where x is numeric). We loop through each of the ports trying to set the active printer to "Microsoft XPS Document Writer on XYZ" (where XYZ is the port) if we succeed then we continue - if we don't succeed then we revert to using the default printer and take the performance hit. On my machine using the Microsoft XPS Document Writer results in a 10x performance gain (~30s against ~300s for the header/footer test) which is definately worthwhile. &lt;/p&gt;
&lt;h2 id="out-of-data-change-requests"&gt;Out of Data Change Requests&lt;/h2&gt;
&lt;p&gt;Over time the templates used for Change Requests (CRs) have evolved (although it is expected that the rate of change of templates will be slower in the future, there may still be changes in the future). Although we don't want to update every CR to the very latest template since this causes far too much traffic on the reflector for very little benefit (this was done in the early days, but is seen to be no longer worth while), there are certain minimum versions that are required. Currently we need to have support for UUIDs in the CR. CRs without UUID support need upgrading and are termed &lt;em&gt;Out Of Date&lt;/em&gt;. CRs that use the latest template have the &lt;em&gt;Uses Latest Template&lt;/em&gt; property. &lt;em&gt;Out Of Date&lt;/em&gt; CRs need to be updated (automatically) to the latest templates. CRs that are not &lt;em&gt;Out Of Date&lt;/em&gt; but do not use the latest template are not automatically upgraded, however the user can use the &lt;em&gt;Upgrader&lt;/em&gt; tool to force an upgrade to the latest tempate. &lt;/p&gt;
&lt;h2 id="split-between-user-interface-and-business-logic"&gt;Split between User Interface and Business Logic&lt;/h2&gt;
&lt;p&gt;In order to maximise the potential reuse of the ESI tool code the user interface has been split from the main code (often called business logic by many commentators). The main code for each of the tools is contained in a separate assembly from the tool itself. With most of the tools being command line tools, this ends up with the tool executable just consisting of a call to the Execute method of the assembly, passing the command line parameters as parameters. &lt;/p&gt;
&lt;h2 id="change-request-number-crn-checking"&gt;Change Request Number (CRN) Checking&lt;/h2&gt;
&lt;p&gt;We should catch mismatches conflicts between the Change Request Number (CRN) contained in the file name (e.g., &lt;em&gt;CR166 - Add My Frigate.xls&lt;/em&gt;) and the CRN contained inside the Change Request (CR) file. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Name CRN&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Internal CRN&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Comments&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;0 &lt;br /&gt;
0 &lt;br /&gt;
This is valid and indicates that the CR is new &lt;/p&gt;
&lt;p&gt;0 &lt;br /&gt;
Non-Zero &lt;br /&gt;
This may indicate that the CR Submitter created a new CR by copying from a previous one. This is OK, but the Tool Superviser ought to check the CR referenced in the CR to check that this is not a mistake. The Registrar shall report an error. &lt;/p&gt;
&lt;p&gt;Non-zero &lt;br /&gt;
0 &lt;br /&gt;
For version 1 CRs this is expected and shall not be flagged as an error. For version 2 CRs this is probably a simple error by the CR Submitter (possibly it is meant to be an update, with the Submitter merely editing her original file rather than the official one posted back to the reflector. The Tool Supervisor ought to check. The Registrar shall report an error. &lt;/p&gt;
&lt;p&gt;Non-zero &lt;br /&gt;
Non-zero &lt;br /&gt;
If the two CRNs are the same then this is OK, however if they are not the same then this is an error, which the Registrar shall report &lt;/p&gt;
&lt;h2 id="verification-mode-of-operation"&gt;Verification Mode of Operation&lt;/h2&gt;
&lt;p&gt;During the development of the Registrar application it became apparent that an extra mode of operation would be useful, namely the &lt;strong&gt;verify&lt;/strong&gt; mode. This mode would be used by the tool maintainer to check that the CR Status file was a correct reflection of the submitted CRs. &lt;/p&gt;
&lt;p&gt;It performs the following for each CR in a specified directory: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If the CR has not got a CRN in the file name then ignore it (it is a new CR and not processed yet) &lt;/li&gt;
&lt;li&gt;If the CR is not in the CR Status file then report an error &lt;/li&gt;
&lt;li&gt;Check that the CRN in the file name matches the CRN inside the file, report an error if it doesn't &lt;/li&gt;
&lt;li&gt;Check that the CR's revision letter (from the file name) matches the revision letter in the CR Status file, report an error if it doesn't &lt;/li&gt;
&lt;li&gt;Check that the title of the CR matches the title in the CR Status file, report an error if it doesn't &lt;/li&gt;
&lt;li&gt;Check that the submitter of the CR matches the submitter in the CR Status file, if it doesn't and the submitter name in the CR Status file is empty then update if; if it doesn't match and the name in the CR Status file is not empty then report an error &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For example: &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;registrar&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;C:\Path\To\Status\File\CR Status.xls&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the status file is in the same directory as the change requests (and has the name "CR Status.xls" then this simplifies to: &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;registrar&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="upgrade-mode-of-operation"&gt;Upgrade Mode of Operation&lt;/h2&gt;
&lt;p&gt;During development of the Change Request utilities it became apparent that handling different versions of the templates was becoming increasingly messy. It was decided that rather than support all previous versions of the templates the Change Request code should only handle the latest version. Rather than upgrade all previous versions by hand, we should get the tool set to do it. The obvious place to do this is within the Registrar (a separate tool was considered, but the sequence of events would then be: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run the registrar tool on the CR file, which would throw an exception &lt;/li&gt;
&lt;li&gt;Manually kick off the upgrade tool &lt;/li&gt;
&lt;li&gt;Manually re-run the registrar tool on the CR file &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is more work for the tool custodian, therefore the sensible thing to do would be incorporate this functionality into the Registrar. As well as performing the upgrade automatically when registering the CR, a separate mode &lt;strong&gt;upgrade&lt;/strong&gt; of operation is provided. &lt;/p&gt;
&lt;p&gt;To use this mode of operation a source file and the template file must be provided as follows: &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;registrar&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;Old&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;CR&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xls&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;To&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;Blank&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;EntityType&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;CR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xls&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The template file is defaulted, so the easiest thing is to copy the template file into the current directory. The command line then simplifies to the following: &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;registrar&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;Old&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;CR&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xls&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The upgrader function runs before the registration function but after the check for matching CRNs (the upgrader function can thus work with the preconditions that the CRN within the file matches the CRN in the file name). If the CR file contains a CRN then the revision letter is upgraded (if there is no revision letter then the the CR becomes rev A) &lt;/p&gt;
&lt;h1 id="updater-design-decisions"&gt;Updater Design Decisions&lt;/h1&gt;
&lt;h2 id="updater-starts-from-a-fresh-database"&gt;Updater Starts from a Fresh Database&lt;/h2&gt;
&lt;p&gt;Lance Marrou wrote: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;3. Does each time the Updater run, it starts from a "fresh" DB? I don't think so, though I don't think that would be a bad idea either. If it doesn't, then the updater does in fact need to process withdrawn elements otherwise said element changes (add OR delete) won't actually be removed. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;OK, this is one that I've put a lot of thought into and it should start from a fresh DB. The issue is tracking updated CRs. Consider the ASLAV CR posted by Bernard Leclerc in October last year (CR2308). His original CR was for: &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
5 &lt;br /&gt;
1 &lt;br /&gt;
ASLAV &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
5 &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
ASLAV-25 &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
5 &lt;br /&gt;
1 &lt;br /&gt;
2 &lt;br /&gt;
ASLAV-PC &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
5 &lt;br /&gt;
1 &lt;br /&gt;
3 &lt;br /&gt;
ASLAV-C &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
5 &lt;br /&gt;
1 &lt;br /&gt;
4 &lt;br /&gt;
ASLAV-S &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
5 &lt;br /&gt;
1 &lt;br /&gt;
5 &lt;br /&gt;
ASLAV-A &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
5 &lt;br /&gt;
1 &lt;br /&gt;
6 &lt;br /&gt;
ASLAV-F &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
5 &lt;br /&gt;
1 &lt;br /&gt;
7 &lt;br /&gt;
ASLAV-R &lt;/p&gt;
&lt;p&gt;After some discussions an update was posted (CR2308A) with the following: &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
Country 39 = Canada &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
2 &lt;br /&gt;
Category 2 = Armored Fighting Vehicle &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
2 &lt;br /&gt;
1 &lt;br /&gt;
Subcategory 1 = Light Armored Vehicle (LAV) &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
2 &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
ASLAV-25 Reconnaissance &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
2 &lt;br /&gt;
1 &lt;br /&gt;
2 &lt;br /&gt;
ASLAV-PC Personnel Carrier &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
2 &lt;br /&gt;
1 &lt;br /&gt;
3 &lt;br /&gt;
ASLAV-S Surveillance &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
3 &lt;br /&gt;
Category 3 = Armored Utility Vehicle &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
3 &lt;br /&gt;
1 &lt;br /&gt;
Subcategory 1 = Light Armored Vehicle (LAV) &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
3 &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
ASLAV-C Command &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
3 &lt;br /&gt;
1 &lt;br /&gt;
2 &lt;br /&gt;
ASLAV-A Ambulance &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
3 &lt;br /&gt;
1 &lt;br /&gt;
3 &lt;br /&gt;
ASLAV-F Fitters &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1 &lt;br /&gt;
1 &lt;br /&gt;
39 &lt;br /&gt;
3 &lt;br /&gt;
1 &lt;br /&gt;
4 &lt;br /&gt;
ASLAV-R Recovery &lt;/p&gt;
&lt;p&gt;If we don't start from a fresh DB then the Updater needs to undo CR2308. Since these are all additions then this is not too difficult, but it does mean that it needs to process the original CR file and undo the additions, then process the new file and add the new enumerations. If the CR updates the description for an enumeration then the problem is even worse since the old description is not in the database any more, nor is it contained in the CR. To undo a changed description then the Updater has to process all previous CRs all the way back to the last baseline (i.e., approved XML database) just in case one of them added or changed the description and, if none of the previous CRs affected the enumeration or its description, then extract the description from the baselined XML database. &lt;/p&gt;
&lt;h2 id="allocation-of-x-values"&gt;Allocation of 'X' Values&lt;/h2&gt;
&lt;p&gt;Lance Marrou wrote: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Registrar needs access to the DB in order to auto-generate the 'x' values and send them back out. &lt;span&gt;[snip]&lt;/span&gt; &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Registrar does not access the DB nor should it. The Updater already needs to walk the entity type hierarchy and other parts of the XML structure making it the ideal place to auto-generate the 'x' values (it is a short step from checking that a suggested value is not already allocated to determining the next unused value). &lt;/p&gt;
&lt;p&gt;Obviously if the CR contains any 'x' values then the updater needs to modify the CR. The question does the modified CR become an updated CR or just a new version of the CR? For instance, consider the following use case: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Somebody submits a CR, called "Add FooBar.xls", and wants the tool set to automatically allocate values for one or more enumerations (i.e., 'x' values) &lt;/li&gt;
&lt;li&gt;The Registrar picks up the CR, determines that it is a new CR and allocates it a number, renaming the file to "CR2048 - Add FooBar.xls", say. &lt;/li&gt;
&lt;li&gt;The Updater takes the new CR file, realises that it contains 'x'values to be added and parses the XML database to find out what value should be used for the enumerations, it then: &lt;ol&gt;
&lt;li&gt;Updates the XML database with enumeration and its value &lt;/li&gt;
&lt;li&gt;Updates the CR and saves it &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The question is what should the file name in step 3b) be? The choices are: &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Option A&lt;/em&gt; - make this a new revision, so the file name would become "CR2048A - Add FooBar.xls" &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Option B&lt;/em&gt; - save it with the same file name, i.e. "CR2048 - Add FooBar.xls" &lt;/p&gt;
&lt;p&gt;With Option B then only the modified CR file ("CR2048 - Add FooBar.xls") should be sent to the reflector. &lt;/p&gt;
&lt;p&gt;With Option A, both the assigned CR file ("CR2048 - Add FooBar.xls") and the updated CR file ("CR2048A - Add FooBar.xls") should be sent to the reflector. &lt;/p&gt;
&lt;p&gt;If Option A is chosen the the Updater would need to send the updated CR to the reflector - adding this would not be particularly difficult, so this is not an issue. &lt;/p&gt;
&lt;p&gt;However if Option B is chosen then I think that neither the Registrar nor the Updater should send the CR file to the reflector - both tools should merely add the CR file to a queue which another tool (either the Status Publisher or a new Publisher) would read and send the CR file back to the reflector. &lt;/p&gt;
&lt;p&gt;In fact, after a bit more thought I think that having a separate publisher is a good idea. This allows the Updater to operate in a mode that would be useful to people who want to add exercise specific enumerations for their own internal use - just create a set of CR forms containing the exercise specific enumerations, run the Updater on them and you have your exercise specific XML database. &lt;/p&gt;
&lt;p&gt;Option B has been selected &lt;/p&gt;
&lt;h2 id="dependent-change-requests"&gt;Dependent Change Requests&lt;/h2&gt;
&lt;p&gt;Lance Marrou wrote: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I just had a though that maybe we should consider how to handle dependent change requests. These would be follow-up change requests that require approval of a previous change request. The current example that made me think of this is CR1924 and CR1925. 1925 contains Link 16 Terminals that use the new Radio Category requested in 1924. If 1924 were to be rejected or even updated, then 1925 would be severely affected (possibly being similarly rejected depending on the CR contents). This should be something we consider for the next quarter perhaps as I can see it would require changes to the templates and the Registrar and Updater (or maybe just Updater). For now, obviously the workaround is manual &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I'm not sure we need to expend too much effort on this. I think it is unlikely that we would reject a CR without someone realising that the other CR is affected. However, let's consider what would happen if this did actually occur. &lt;/p&gt;
&lt;p&gt;Perhaps the missing information from the tool chain description is that when adding an enumeration (in particular when adding an entity type or radio type) the Updater also validates if the "parent" enumeration already exists and reports an error if it doesn't exist. &lt;/p&gt;
&lt;p&gt;Now, if the first CR were updated to change the category then when the Updater is run then the mismatch with the second CR would cause an error to be raised - the reflector would be notified and the second CR could then be modified accordingly &lt;/p&gt;
&lt;p&gt;If we went all the way through to rejecting the first CR, then when the release candidate was created then the mismatch would be detected. The production of the release candidate would be halted and the reflector notified. We then have the opportunity to correct the problem (reconsider the rejection of the first CR, reject the second CR as well, put both on hold, etc.) &lt;/p&gt;
&lt;p&gt;In both situations you postulate the problem would be detected and not affect the final approved product. I think it would be worth waiting to see if there is a real problem before going to a lot of effort to stop it. &lt;/p&gt;
&lt;h2 id="producing-the-list-of-change-requests-in-the-revision-history"&gt;Producing the List of Change Requests in the Revision History&lt;/h2&gt;
&lt;p&gt;Since the CR status file is not guaranteed to be ordered by change request number, creating a consistent set of change request ranges for the revision history is more difficult than it might first appear. The CR status file provides a method for iterating over all CRs that have been disposed by the EWG. To enable us to turn this into a list of change request ranges/individual change request IDs we need a class that: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the user can add change request IDs one at a time &lt;/li&gt;
&lt;li&gt;sorts the change request IDs into increasing order &lt;/li&gt;
&lt;li&gt;can 'output' the stored IDs as a set of individual IDs/Ranges &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So for instance the following input set: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1722 1701 1698 1702 1708 1700 1699 1707 1695 &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;is ordered as follows: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1695 1698 1699 1700 1701 1702 1707 1708 1722 &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and will produce the following output: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1695 1698-1702 1707-1708 1722 &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Output is performed by a visitor class, providing functions for processing a single change request ID, e.g. &lt;em&gt;Process(int ID)&lt;/em&gt;, and processing a change request ID range, e.g. &lt;em&gt;Process(int value_min, int value_max)&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="add-missing-categories-etc"&gt;Add Missing Categories, etc.&lt;/h2&gt;
&lt;p&gt;The Op Manual (SISO-REF-010.1) show examples on how categories that are in the XML file, but not contained in the CR are automatically added. For example consider the following CR: &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Change Type&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Enumeration&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Name&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1.3.224.5.1 &lt;br /&gt;
Type 77 &lt;/p&gt;
&lt;p&gt;Currently the UK has no category 5 entities. However, category 5 for the surface domain is defined. Therefore the toolset will automatically add the "missing" category, so that it would be as if the submitter had asked for the following: &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Change Type&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Enumeration&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Name&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1.3.224.5 &lt;br /&gt;
Destroyer (DD) &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1.3.224.5.1 &lt;br /&gt;
Type 77 &lt;/p&gt;
&lt;p&gt;The civilian aircraft modifications extended this by specifying subcategories as well, so &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Change Type&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Enumeration&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Name&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1.2.225.85.11 &lt;br /&gt;
Cessna 172 Skyhawk &lt;/p&gt;
&lt;p&gt;The toolset will automatically add the category and subcategory as follows: &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Change Type&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Enumeration&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Name&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1.2.225.85 &lt;br /&gt;
Civilian Fixed Wing Aircraft, Large (up to 255,000 lbs / 115,666 kg) &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1.2.225.85.11 &lt;br /&gt;
Single Piston Engine &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1.2.225.85.11.1 &lt;br /&gt;
Cessna 172 Skyhawk &lt;/p&gt;
&lt;p&gt;Early versions of the toolset hard wired the look up. Ideally we would like to use information in the XML database to drive this information &lt;/p&gt;
&lt;p&gt;When adding an entity type the toolset follows the logic shown in the following figure: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The toolset checks if the entity to be added exists. If it does then an error is generated and the process terminates. However, in this case the entity doesn't exists so we proceed to the second step &lt;/li&gt;
&lt;li&gt;The toolset checks if the entity type to be added is predefined, i.e. it appears in one of the category (or subcategory) tables. The &lt;a class="" href="http://www.sisostds.org/DigitalLibrary.aspx?EntryId=29547" rel="nofollow"&gt;OpMan&lt;/a&gt; recommends that such entity types are not included in CRs, but it is not strictly speaking forbidden. The check has two parts: &lt;ol&gt;
&lt;li&gt;We check to see if the parent entity type has an associated table. If it does not then the entity cannot be predefined and we proceed to step 4. &lt;/li&gt;
&lt;li&gt;Next we find if the type is defined in its parents table. If it isn't then an error is generated (categories/subcategories must be added to the appropriate table before use) and the process terminates. Otherwise we proceed to step 3 &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;If we get here then the entity type to be added is predefined, so we check that the description matches that already in the database. If it doesn't match then an error is generated (predefined descriptions cannot be changed when adding and entity) and the process terminates. If it does match, we generate a warning and continue to the next step. &lt;/li&gt;
&lt;li&gt;The tool set checks if the parent exists. If it does then we add the entity to its parent and exits successfully. Otherwise we procedd to the next step &lt;/li&gt;
&lt;li&gt;The parent does not exist so we check if the parent is predefined. Again the check has two parts: &lt;ol&gt;
&lt;li&gt;We check if the parent's parent (ie. the new entity's grandparent) has an associated table. If it doesn't then the parent is not predefined and an error is generated (no parent exists) and the process terminates &lt;/li&gt;
&lt;li&gt;Next we check that the parent is in the grandparent's table If it doesn't then an error is generated (categories/subcategories must be added to the appropriate table before use) and the process terminates. &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Finally we add the missing ancestor(s), i.e. the parent and possibly grandparent to the database then add the new entity to the now existing parent and exit successfully &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Fundamental to this process is how to determine if the entity type is predefined. The method is to associated database tables (as defined by their UID) with a set of entity types. The entity type is compared with this set and if it matches then the entity type is predefined. Early implementations hard wired this decision, but it is hoped that additional data can be added to the database to help this. For instance, the "Subcategories for Air Platform Category 83" table (UID 276) has a single element of "1.2.X.83" &lt;/p&gt;
&lt;h3 id="worked-example-1"&gt;Worked Example 1&lt;/h3&gt;
&lt;p&gt;To show how the toolset fills in the missing elements take the following example of an old British glider: &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1.2.224.83.1.1 &lt;br /&gt;
Vickers-Slingsby T-65 Vega &lt;/p&gt;
&lt;p&gt;Working through the flowchart we get the following: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Entity 1.2.224.83.1.1 is not in the database so we proceed to step 2 &lt;/li&gt;
&lt;li&gt;We check to see if the entity is predefined: &lt;ol&gt;
&lt;li&gt;Entity 1.2.224.83.1 does not have an associated table so we move to step 4 &lt;/li&gt;
&lt;li&gt;&lt;em&gt;This step is skipped&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;em&gt;This step is skipped&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;The entity 1.2.224.83.1 does not exist &lt;/li&gt;
&lt;li&gt;We check to see if the entity's parent is predefined: &lt;ol&gt;
&lt;li&gt;The grandparent 1.2.224.83 does have an associated table (UID = 276) so we proceed to the next step &lt;/li&gt;
&lt;li&gt;Subcategory 1 appears in table 276 so we proceed to the next step &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;We add both the grandparent (&lt;em&gt;1.2.224.83 - Civilian Fixed Wing Aircraft, Glider&lt;/em&gt;) and parent (&lt;em&gt;1.2.224.83.1 - Sail Plane&lt;/em&gt;) are added before finally adding the new entity itself &lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="worked-example-2"&gt;Worked Example 2&lt;/h3&gt;
&lt;p&gt;Consider the slightly modified version of the above example: &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1.2.224.83.3.1 &lt;br /&gt;
Vickers-Slingsby T-65 Vega &lt;/p&gt;
&lt;p&gt;Working through the flowchart we get the following: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Entity 1.2.224.83.3.1 is not in the database so we proceed to step 2 &lt;/li&gt;
&lt;li&gt;We check to see if the entity is predefined: &lt;ol&gt;
&lt;li&gt;Entity 1.2.224.83.3 does not have an associated table so we move to step 4 &lt;/li&gt;
&lt;li&gt;&lt;em&gt;This step is skipped&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;em&gt;This step is skipped&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;The entity 1.2.224.83.3 does not exist &lt;/li&gt;
&lt;li&gt;We check to see if the entity's parent is predefined: &lt;ol&gt;
&lt;li&gt;The grandparent 1.2.224.83 does have an associated table (UID = 276) so we proceed to the next step &lt;/li&gt;
&lt;li&gt;Subcategory 3 does not appears in table 276, and we cannot modify table 276 when adding an entity, so we generate an error and terminate &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="worked-example-3"&gt;Worked Example 3&lt;/h3&gt;
&lt;p&gt;To show what happens when the user tries to add something that is already specified in a category/subcategory table consider the following: &lt;/p&gt;
&lt;p&gt;Add &lt;br /&gt;
1.2.224.83.1 &lt;br /&gt;
Sail Plane &lt;/p&gt;
&lt;p&gt;Working through the flowchart we get the following: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Entity 1.2.224.83.1 is not in the database so we proceed to step 2 &lt;/li&gt;
&lt;li&gt;We check to see if the entity is predefined: &lt;ol&gt;
&lt;li&gt;Entity 1.2.224.83 does have an associated table (UID = 276) so we continue &lt;/li&gt;
&lt;li&gt;Subcategory 1 is in table 276 so we proceed to step 3 &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;The description provided in the CR matches that in table 276 so we generate a warning and proceed to the next step &lt;/li&gt;
&lt;li&gt;The entity 1.2.224.83 does not exist &lt;/li&gt;
&lt;li&gt;We check to see if the entity's parent is predefined: &lt;ol&gt;
&lt;li&gt;The grandparent 1.2.224 does have an associated table (UID = 10) so we proceed to the next step &lt;/li&gt;
&lt;li&gt;Subcategory 83 appears in table 10 so we proceed to the next step &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;We add the parent (&lt;em&gt;1.2.224.83 - Civilian Fixed Wing Aircraft, Glider&lt;/em&gt;) and then add the new entity itself &lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="how-associated-tables-are-found"&gt;How Associated Tables are Found&lt;/h3&gt;
&lt;p&gt;Each entity type category and subcategory definition table has an associated &lt;em&gt;Applicability&lt;/em&gt; attribute which is a string with kind, domain and, if applicable, category. To make things more readable we use the letter &lt;em&gt;X&lt;/em&gt; in place of the country code. Ranges are allowed (since, for instance, some subcategory tables are applicable to multiple catagories). So for instance we have &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Applicability&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Table UID&lt;/strong&gt;&lt;br /&gt;
&lt;strong&gt;Description&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.2.X &lt;br /&gt;
10 &lt;br /&gt;
Categories for air platforms &lt;/p&gt;
&lt;p&gt;1.2.X.81 &lt;br /&gt;
275 &lt;br /&gt;
Subcategories for Civilian Ultralight Aircraft, Rigid Wing &lt;/p&gt;
&lt;p&gt;1.2.X.83 &lt;br /&gt;
276 &lt;br /&gt;
Subcategories for Civilian Fixed Wing Aircraft, Glider &lt;/p&gt;
&lt;p&gt;1.2.X.84-88 &lt;br /&gt;
277 &lt;br /&gt;
Subcategories for Civilian Fixed Wing Aircraft Light Sport; Small; Medium; Large; and Heavy &lt;/p&gt;
&lt;p&gt;So a search for entity &lt;em&gt;1.2.225&lt;/em&gt; will return table 10, a search for entity &lt;em&gt;1.2.224.83&lt;/em&gt; (see example 1) will return table 276, a search for &lt;em&gt;1.2.222.85&lt;/em&gt; will return table 277 (85 is in the range 84 to 88), whereas both &lt;em&gt;1.2.72.82&lt;/em&gt; and &lt;em&gt;1.2.224.83.1&lt;/em&gt; will not find any table. &lt;/p&gt;
&lt;h2 id="track-changes"&gt;Track Changes&lt;/h2&gt;
&lt;p&gt;Speed is not the most important thing in the ESI tool set but there is no doubt that the major operations (updating the XML database for a release and generating the Word document) do take a long time. Therefore it is worth addressing speed problems in tasks that occur frequently in these operations. &lt;/p&gt;
&lt;p&gt;One thing that I noticed when watching the Word Generator in action was that updates slowed down when track changes were on (most obvious when updating the emitter table). Looking at the code I noticed that it was turning track changes on, writing the text into the cell, and then turning track changes off again. My first attempt to speed things up (implemented in v20 draft 0) was based upon the observation that the emitter table contains 4 columns but generally only 2 of them are populated on each row. So I changed the emitter processor to only write non empty text in the cell. Net gain: 50% increase in speed for the emitter processing. &lt;/p&gt;
&lt;p&gt;Job done? Well no. When v20 draft 0 was released the spacing on the emitter table was strange; the first few rows were double line height, before settling down to the desired single line height. &lt;/p&gt;
&lt;p&gt;When a row is appended to a table each cell "inherits" the cell height from the previous row. When text is written to a cell the cell height is set to be the minimum of the text (so a single word would be single line height). If no text is written to the cell it retains inherited height. The height of the row is the maximum height of all cells in that row. In the emitter table the heading row is double line height so all the cells in the first row are all doubkle line height by default. Since the first row in the emitter table has blank NATO Reporting Name and Commercial Designation then the first row becomes double line height if we do not write the empty string into these cells. Single line height does not happen until the 23rd row when the Commercial Designation cell is written to for the first time. &lt;/p&gt;
&lt;h2 id="microsoft-words-broken-list-numbering"&gt;Microsoft Word's Broken List Numbering&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;AutoWord&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RangeEx&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AutoWord&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RangeEx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;End&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Office&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WdListType&lt;/span&gt; &lt;span class="n"&gt;previousListType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Office&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WdListType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wdListNoNumbering&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;listTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Styles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Letter List&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;ListTemplate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Office&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Paragraph&lt;/span&gt; &lt;span class="n"&gt;paragraph&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TheRange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Paragraphs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Office&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WdListType&lt;/span&gt; &lt;span class="n"&gt;listType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Office&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WdListType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wdListSimpleNumbering&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;listType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;needsUpdate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;originalListValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;previousListType&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;listType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;originalListValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;needsUpdate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;//var listTemplate = paragraph.Range.ListFormat.ListTemplate;&lt;/span&gt;
      &lt;span class="c1"&gt;//paragraph.Range.ListFormat.ApplyListTemplate(listTemplate, false);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s"&gt;&amp;quot;{0} {1} -&amp;gt; {2} {3}: {4}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="n"&gt;originalListValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;needsUpdate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;paragraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;previousListType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;</description><pubDate>Fri, 27 Jun 2014 15:06:34 -0000</pubDate><guid>https://sourceforge.netca4b9445c125eaff46ad966186bb0ccf0fa29dab</guid></item></channel></rss>