Adding merge command line program that merges multiple MSA modules into a single...
authorlhauch <lhauch@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 18 Sep 2006 22:02:06 +0000 (22:02 +0000)
committerlhauch <lhauch@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 18 Sep 2006 22:02:06 +0000 (22:02 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1553 6f19259b-4bc3-4df7-8a09-765794883524

Tools/Source/Merge/build.xml [new file with mode: 0644]
Tools/Source/Merge/readme.txt [new file with mode: 0644]
Tools/Source/Merge/src/org/tianocore/Merge/CombineMsa.java [new file with mode: 0644]
Tools/Source/Merge/src/org/tianocore/Merge/Merge.java [new file with mode: 0644]
Tools/Source/Merge/src/org/tianocore/Merge/MergeCmd.java [new file with mode: 0644]

diff --git a/Tools/Source/Merge/build.xml b/Tools/Source/Merge/build.xml
new file mode 100644 (file)
index 0000000..e6e8aa6
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>\r
+<!--\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+-->\r
+<project name="Merge" default="Merge" basedir=".">\r
+  <taskdef resource="net/sf/antcontrib/antlib.xml"/>\r
+  <property environment="env"/>\r
+  <property name="WORKSPACE" value="${env.WORKSPACE}"/>\r
+  <path id="classpath">\r
+    <fileset dir="${WORKSPACE}/Tools/Jars" includes="*.jar"/>\r
+    <fileset dir="${env.XMLBEANS_HOME}/lib" includes="*.jar"/>\r
+  </path>\r
+  <property name="buildDir" value="build"/>\r
+  <property name="installLocation" value="${WORKSPACE}/Tools/bin"/>\r
+  <target name="Merge" depends="install"/>\r
+  <target name="source">\r
+    <mkdir dir="${buildDir}"/>\r
+    <javac srcdir="src" destdir="${buildDir}">\r
+      <classpath refid="classpath"/>\r
+      <!-- <compilerarg value="-Xlint"/> -->\r
+    </javac>\r
+  </target>\r
+  <target name="clean">\r
+    <delete dir="${buildDir}"/>\r
+  </target>\r
+  <target name="cleanall">\r
+    <delete dir="${buildDir}"/>\r
+    <delete file="${installLocation}/Merge.jar"/>\r
+  </target>\r
+  <target name="install" depends="source">\r
+    <jar destfile="${installLocation}/Merge.jar">\r
+      <fileset dir="${buildDir}"/>\r
+    </jar>\r
+  </target>\r
+</project>\r
diff --git a/Tools/Source/Merge/readme.txt b/Tools/Source/Merge/readme.txt
new file mode 100644 (file)
index 0000000..cf423c3
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2006, Intel Corporation   All rights reserved.
+#
+# This program and the accompanying materials are licensed and made
+# available under the terms and conditions of the BSD License which
+# accompanies this distribution.  The full text of the license may 
+# be found at  http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Overview
+--------
+The Merge program is designed to merge the contents of similar modules into a
+single module for size reduction. The combined module will link in one copy of
+the libraries, rather than have multiple copies of the libraries linked in to
+each individual driver.
+
+Rules:
+  The ModuleType must be identical for each of the (leaf) modules.
+  At least one architecture type must be common for all modules, and the merged
+module will only support the common architecture types.
+  ALL modules to be merged must be in a directory structure below the location
+of the merged module.
+  The package must be within a directly directory line with the merged module's
+MSA file. (Parent directories.)
+  The copying of the files from the "leaf" directory into the merge module's
+directory structure must be handled by an external program.
+  The merge program must be run everytime a leaf module is modified.
+  The external copy program must also be run everytime a leaf module is modified.
+  Two or more leaf modules must be specified.
+  The merged module must be added to a package (SPD) file before it can be used.
+  PCD Driver Modules cannot be merged, nor combined with other modules.
+  Leaf Module Global BuildOptions and UserExtensions are not merged.
+
+
+merge Usage:  
+  merge [-v] -t target [-u UiName] [-p PackageFile] dir1\leaf1 ... dirN\leafN [-h | -? | --help]
+    where:
+      -h | -? | --help            OPTIONAL - This Help Text
+      -t Target                   REQUIRED - The Name of the new Merge Module MSA file
+      -p Package                  OPTIONAL - The Name of the Package (SPD) file to add the target
+      -u UiName                   OPTIONAL - The User Interface Name for the Target Module
+      -v                          OPTIONAL - Verbose, print information messages.
+      -o OutputFileBasename       OPTIONAL - Set the Output Filename for this module to Basename
+      dir1\leaf1 ... dirN\leafN   REQUIRED The path to two or more MSA files that will be merged
+
+
diff --git a/Tools/Source/Merge/src/org/tianocore/Merge/CombineMsa.java b/Tools/Source/Merge/src/org/tianocore/Merge/CombineMsa.java
new file mode 100644 (file)
index 0000000..7383c59
--- /dev/null
@@ -0,0 +1,2002 @@
+// @file\r
+//   This Class processes multiple MSA files and merges them into a single, \r
+//   merged MSA file. It will optionally add the merged MSA file into a package.\r
+//\r
+//\r
+//  Copyright (c) 2006, Intel Corporation    All rights reserved.\r
+//\r
+//  This program and the accompanying materials are licensed and made\r
+//  available under the terms and conditions of the BSD License which\r
+//  accompanies this distribution.  The full text of the license may \r
+//  be found at  http://opensource.org/licenses/bsd-license.php\r
+//\r
+//  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+//  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+//\r
+\r
+package org.tianocore.Merge;\r
+\r
+import java.io.*;\r
+import java.util.*;\r
+// import java.lang.*;\r
+// import java.lang.ExceptionInInitializerError;\r
+\r
+// import org.apache.xmlbeans.*;\r
+import org.apache.xmlbeans.XmlCursor;\r
+// import org.apache.xmlbeans.XmlObject;\r
+import org.apache.xmlbeans.XmlOptions;\r
+import org.apache.xmlbeans.XmlException;\r
+import org.tianocore.*;\r
+\r
+// import org.tianocore.*;\r
+import org.tianocore.ModuleSurfaceAreaDocument.*;\r
+import org.tianocore.MsaHeaderDocument.*;\r
+import org.tianocore.LicenseDocument.*;\r
+import org.tianocore.ModuleDefinitionsDocument.*;\r
+import org.tianocore.LibraryClassDefinitionsDocument.*;\r
+import org.tianocore.SourceFilesDocument.*;\r
+import org.tianocore.PackageDependenciesDocument.*;\r
+import org.tianocore.ProtocolsDocument.*;\r
+import org.tianocore.EventsDocument.*;\r
+import org.tianocore.HobsDocument.*;\r
+import org.tianocore.PPIsDocument.*;\r
+import org.tianocore.VariablesDocument.*;\r
+import org.tianocore.BootModesDocument.*;\r
+import org.tianocore.SystemTablesDocument.*;\r
+import org.tianocore.DataHubsDocument.*;\r
+import org.tianocore.HiiPackagesDocument.*;\r
+import org.tianocore.GuidsDocument.*;\r
+import org.tianocore.ExternsDocument.*;\r
+import org.tianocore.PcdCodedDocument.*;\r
+import org.tianocore.ModuleBuildOptionsDocument.*;\r
+import org.tianocore.UserExtensionsDocument.*;\r
+\r
+import org.tianocore.PackageSurfaceAreaDocument.*;\r
+import org.tianocore.MsaFilesDocument.*;\r
+\r
+public class CombineMsa {\r
+\r
+    private final int DEBUG = 0;\r
+\r
+    private final int PASS = 0;\r
+\r
+    private final int FAIL = 1;\r
+\r
+    private final int FOUND = 0;\r
+\r
+    private final int NOTFOUND = 1;\r
+\r
+    private int result = PASS;\r
+\r
+    private String licenseTxt = "";\r
+\r
+    private ArrayList<String> aLicenses = new ArrayList<String>();\r
+\r
+    private String Copyright = "";\r
+\r
+    private ArrayList<String> aCopyright = new ArrayList<String>();\r
+\r
+    private String Abstract = "\n      Merged Modules: \n";\r
+\r
+    private String Description = "\n      Merging Modules: \n";\r
+\r
+    private String sArchitectures = "";\r
+\r
+    private MsaHeader header = null;\r
+\r
+    private final String Specification = "FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052";\r
+\r
+    private ModuleSurfaceArea mergeMsaFile = null;\r
+\r
+    private ModuleSurfaceArea leafMsa = null;\r
+\r
+    private ModuleDefinitions moduleDefs = null;\r
+\r
+    private LibraryClassDefinitions libClassDefs = null;\r
+\r
+    private ArrayList<String> aLibClassDefs = new ArrayList<String>();\r
+\r
+    private int libraryClassIndex = 0;\r
+\r
+    private SourceFiles mergeSourceFiles = null;\r
+\r
+    private int sourceFileIndex = 0;\r
+\r
+    private PackageDependencies mergePackageDependencies = null;\r
+\r
+    private ArrayList<String> aPackageList = new ArrayList<String>();\r
+\r
+    private int packageDependenciesIndex = 0;\r
+\r
+    private Protocols mergeProtocols = null;\r
+\r
+    private ArrayList<String> aProtocolList = new ArrayList<String>();\r
+\r
+    private ArrayList<String> aProtocolNotifyList = new ArrayList<String>();\r
+\r
+    private int protocolIndex = 0;\r
+\r
+    private int protocolNotifyIndex = 0;\r
+\r
+    private Events mergeEvents = null;\r
+\r
+    private Events.CreateEvents mergeCreateEvents = null;\r
+\r
+    private Events.SignalEvents mergeSignalEvents = null;\r
+\r
+    private ArrayList<String> aCreateEventsList = new ArrayList<String>();\r
+\r
+    private ArrayList<String> aSignalEventsList = new ArrayList<String>();\r
+\r
+    private int createEventIndex = 0;\r
+\r
+    private int signalEventIndex = 0;\r
+\r
+    private Hobs mergeHobs = null;\r
+\r
+    private ArrayList<String> aHobsList = new ArrayList<String>();\r
+\r
+    private int hobsIndex = 0;\r
+\r
+    private PPIs mergePpis = null;\r
+\r
+    private ArrayList<String> aPpiList = new ArrayList<String>();\r
+\r
+    private ArrayList<String> aPpiNotifyList = new ArrayList<String>();\r
+\r
+    private int ppiIndex = 0;\r
+\r
+    private int ppiNotifyIndex = 0;\r
+\r
+    private Variables mergeVariables = null;\r
+\r
+    private ArrayList<String> aVariablesList = new ArrayList<String>();\r
+\r
+    private int variablesIndex = 0;\r
+\r
+    private BootModes mergeBootModes = null;\r
+\r
+    private ArrayList<String> aBootModesList = new ArrayList<String>();\r
+\r
+    private int bootModesIndex = 0;\r
+\r
+    private SystemTables mergeSystemTables = null;\r
+\r
+    private ArrayList<String> aSystemTablesList = new ArrayList<String>();\r
+\r
+    private int systemTableIndex = 0;\r
+\r
+    private DataHubs mergeDataHubs = null;\r
+\r
+    private ArrayList<String> aDataHubsList = new ArrayList<String>();\r
+\r
+    private int dataHubsIndex = 0;\r
+\r
+    private HiiPackages mergeHiiPackages = null;\r
+\r
+    private ArrayList<String> aHiiPackagesList = new ArrayList<String>();\r
+\r
+    private int hiiPackageIndex = 0;\r
+\r
+    private Guids mergeGuids = null;\r
+\r
+    private ArrayList<String> aGuidsList = new ArrayList<String>();\r
+\r
+    private int guidsIndex = 0;\r
+\r
+    private Externs mergeExterns = null;\r
+\r
+    private ArrayList<String> aEntryPointList = new ArrayList<String>();\r
+\r
+    private ArrayList<String> aUnloadImageList = new ArrayList<String>();\r
+\r
+    private ArrayList<String> aDriverBindingList = new ArrayList<String>();\r
+\r
+    private ArrayList<String> aConstructorList = new ArrayList<String>();\r
+\r
+    private ArrayList<String> aDestructorList = new ArrayList<String>();\r
+\r
+    private ArrayList<String> aVirtualAddressMapList = new ArrayList<String>();\r
+\r
+    private ArrayList<String> aExitBootServicesList = new ArrayList<String>();\r
+\r
+    private int externsIndex = 0;\r
+\r
+    private ArrayList<String> aSpecArray = new ArrayList<String>();\r
+\r
+    private int specIndex = 0;\r
+\r
+    private PcdCoded mergePcdCoded = null;\r
+\r
+    private ArrayList<String> aPcdCNameList = new ArrayList<String>();\r
+\r
+    private ArrayList<String> aPcdItemTypeList = new ArrayList<String>();\r
+\r
+    private int pcdIndex = 0;\r
+\r
+    private ModuleBuildOptions mergeBuildOptions = null;\r
+\r
+    private UserExtensions mergeUserExtensions = null;\r
+\r
+    private XmlCursor cursor = null;\r
+\r
+    private String mergeUsage = "";\r
+\r
+    private String leafUsage = "";\r
+\r
+    private int VERBOSE = 0;\r
+\r
+    // The combineMsaFiles routine is the primary routine for creating a \r
+    // Merged MSA file.\r
+\r
+    public int combineMsaFiles(String msaFilename, ArrayList<String> msaFiles, String uiName, String spdFilename,\r
+                               String baseName, int Flags) {\r
+        // msaFile has been verified to either not exist, or, if it does exist, \r
+        // it will be over written.\r
+        // All files in the msaFiles ArrayList have been verifed to exist.\r
+        // If the uiName is not null, we will have a new UI Name for the merged \r
+        // module.\r
+        // If the uiName is null, we will use the module name from the first \r
+        // Leaf module.\r
+        // If the spdFile is not null, the Package (SPD) file has been verified \r
+        // to exist.\r
+        // If the spdFile is null, don't attempt to add the new msa file.\r
+\r
+        if (Flags > 0)\r
+            VERBOSE = 1;\r
+        if (mergeMsaFile == null) {\r
+            //\r
+            // create the data structure for the merged Module\r
+            //\r
+            mergeMsaFile = ModuleSurfaceArea.Factory.newInstance();\r
+\r
+            System.out.println("Merging " + msaFiles.size() + " Modules");\r
+            //\r
+            // we always require a Header and a Module Definition section.\r
+            // These will be added to the mergeMsaFile after we have completed \r
+            // all processing of the Leaf MSA files.\r
+            //\r
+            header = MsaHeaderDocument.Factory.newInstance().addNewMsaHeader();\r
+            moduleDefs = ModuleDefinitionsDocument.Factory.newInstance().addNewModuleDefinitions();\r
+            //\r
+            // A merged module cannot be created from binary modules - we force \r
+            // the new module to be source here, however we will test every \r
+            // module to make sure that none are binary; exiting the program if\r
+            // a module is binary\r
+            //\r
+            moduleDefs.setBinaryModule(false);\r
+\r
+            for (int i = 0; i < msaFiles.size(); i++) {\r
+                String leafFilename = msaFiles.get(i).toString();\r
+                leafMsa = getLeafFile(leafFilename);\r
+                if (leafMsa == null) {\r
+                    System.out.println("Could not read Leaf MSA file: " + leafFilename);\r
+                    System.exit(FAIL);\r
+                }\r
+                if (i == 0) {\r
+                    //\r
+                    // Special code for first file, since this file is used \r
+                    // to initialize some of the data in the mergeMsaFile.                        \r
+                    // Set the Merge module's ModuleName to the name in the \r
+                    // first Leaf Module.  If a new module name is given, \r
+                    // over write it later, just before writing the Merge \r
+                    // Module MSA file.\r
+                    header.setModuleName(leafMsa.getMsaHeader().getModuleName().toString());\r
+                    //\r
+                    // All modules must be of the same module type, we set it \r
+                    // here, and test the other Leaf modules' type later.\r
+                    header.setModuleType(leafMsa.getMsaHeader().getModuleType());\r
+                    //\r
+                    // This is a new Module, so we need a new GUID\r
+                    header.setGuidValue(UUID.randomUUID().toString());\r
+                    //\r
+                    // Use the version from the first Leaf module as the \r
+                    // Merge Module version number.\r
+                    header.setVersion(leafMsa.getMsaHeader().getVersion().toString());\r
+                    //\r
+                    // There is no special requirement for processing the \r
+                    // following, so we just fall through on these elements \r
+                    // of the header.\r
+                    // Abstract will be added after parsing all leaf MSA files.\r
+                    // Description will be added after parsing all leaf MSA files.\r
+                    // Copyright will be added after parsing all leaf MSA files.\r
+                    // License will be added after parsing all leaf MSA files.\r
+                    //\r
+                    // Force the specification to match this tool's spec version.\r
+                    header.setSpecification(Specification);\r
+                    //\r
+                    // Set the Merged Module's Output Basename to match the first \r
+                    // leaf module\r
+                    String OutputFileName = leafMsa.getModuleDefinitions().getOutputFileBasename().toString();\r
+                    //\r
+                    // Just in case someone put a space character in the first\r
+                    // leaf module's output filename, replace the spaces with\r
+                    // an underscore.\r
+                    OutputFileName.replace(" ", "_");\r
+                    moduleDefs.setOutputFileBasename(OutputFileName);\r
+                    //\r
+                    // We start with the first module's list of supported \r
+                    // architectures.  As we process the additional leaf modules,\r
+                    // we may have to remove some supported architectures from \r
+                    // the list, as we can only build for the "least common \r
+                    // denominator" subset of architectures.\r
+                    sArchitectures = leafMsa.getModuleDefinitions().getSupportedArchitectures().toString();\r
+                    if ((DEBUG > 5) || (VERBOSE > 5))\r
+                        System.out.println("New Header:  \"" + header.getModuleName().toString() + "\"");\r
+                }\r
+                //\r
+                // We test the license in each leaf module, and will only print\r
+                // licenses that are may be different in wording (white spaces \r
+                // and line feeds are ignored in this test.)\r
+                if (leafMsa.getMsaHeader().getLicense() != null)\r
+                    licenseTxt += checkDuplicateStrings(leafMsa.getMsaHeader().getLicense().getStringValue().trim(),\r
+                                                        aLicenses);\r
+                if ((DEBUG > 10) || (VERBOSE > 10))\r
+                    System.out.println("License:   " + licenseTxt);\r
+                //\r
+                // We test the copyright line from each leaf module, and will \r
+                // add additional copyright lines only if they are different \r
+                // in wording (white spaces and line feeds are ignored in this\r
+                // test.)\r
+                if (leafMsa.getMsaHeader().getCopyright() != null)\r
+                    Copyright += checkDuplicateStrings(leafMsa.getMsaHeader().getCopyright().toString().trim(),\r
+                                                       aCopyright);\r
+                if ((DEBUG > 10) || (VERBOSE > 10))\r
+                    System.out.println("Copyright: " + Copyright);\r
+                //\r
+                // ALL leaf modules must be of the same Module Type, if not, \r
+                // print an error and exit.\r
+                if (header.getModuleType() != leafMsa.getMsaHeader().getModuleType()) {\r
+                    System.out.println("ERROR: Module Types different!");\r
+                    System.out.println("  Expected: " + header.getModuleType());\r
+                    System.out.println("  " + leafFilename + " ModuleType: " + leafMsa.getMsaHeader().getModuleType());\r
+                    System.out.println("Merge ABORTED!");\r
+                    System.exit(FAIL);\r
+                }\r
+                //\r
+                // Combine the Abstract and Descriptions into a single \r
+                // description entry, prefixing each with the Leaf MSA filename,\r
+                // so you know which description is from which Leaf module.\r
+                Description += "      -- " + leafFilename + " -- \n      Abstract:    "\r
+                               + leafMsa.getMsaHeader().getAbstract().toString() + "\n      Description: "\r
+                               + leafMsa.getMsaHeader().getDescription().toString() + "\n";\r
+                //\r
+                // Use the Abstract of the Merged Module to list the Leaf \r
+                // Module's MSA files.\r
+                Abstract += "      -- " + leafFilename + " -- \n";\r
+                //\r
+                // Ignore ClonedFrom right now\r
+                //\r
+\r
+                // Process Supported Architectures\r
+                // A merged module supports the lowest common set of \r
+                // architectures\r
+                String testArch = "";\r
+                if (leafMsa.getModuleDefinitions().getSupportedArchitectures() == null) {\r
+                    System.out\r
+                              .println("Module " + leafFilename + " does not have the Supported Architectures defined!");\r
+                    System.out.println("Supported Architectures is a required element!");\r
+                    System.out.println("Merge ABORTED!");\r
+                    System.exit(FAIL);\r
+                }\r
+                testArch = leafMsa.getModuleDefinitions().getSupportedArchitectures().toString();\r
+                String aArch[] = sArchitectures.split(" ");\r
+                for (int ictr = 0; ictr < aArch.length; ictr++) {\r
+                    if (!testArch.contains(aArch[ictr])) {\r
+                        sArchitectures = sArchitectures.replace(aArch[ictr], "");\r
+                    }\r
+                }\r
+                if (sArchitectures.length() < 2) {\r
+                    System.out.println("ERROR: The Leaf Modules' Supported Architectures are mutually exclusive.");\r
+                    System.out.println("At least one architecture must be common to all Leaf Modules!");\r
+                    System.out.println("Merge Aborting!");\r
+                    System.exit(FAIL);\r
+                }\r
+                //\r
+                // Now start to process the rest of the Leaf Module's MSA files.\r
+                // We will only test a Leaf module's section if it has data, skipping\r
+                // empty sections\r
+                // As part of this process, we will only create a Library Class Definition\r
+                // if one was defined, and we will only do it one time.\r
+                if (leafMsa.isSetLibraryClassDefinitions()) {\r
+                    // \r
+                    //  If libClassDefs == null, create a new libClassDefs and add\r
+                    //  this module's libClassDefs to the merge Module's\r
+                    //  If libClassDefs != null, check that we have only unique LibraryClass entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the LibraryClass as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the LibraryClass as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  The RecommendedInstance attributes can be ignored!\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      The SupModuleList must be identical for all Leaf Modules!\r
+                    //  Probable Enhancement\r
+                    //      The SupModuleList should be combined to include all possible supported module types.\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each LibraryClass, otherwize fail the Merge\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    if (libClassDefs == null)\r
+                        libClassDefs = LibraryClassDefinitionsDocument.Factory.newInstance()\r
+                                                                              .addNewLibraryClassDefinitions();\r
+                    //\r
+                    // Get the Leaf LibraryClassDefinitions Section\r
+                    LibraryClassDefinitions leafLibClassDef = leafMsa.getLibraryClassDefinitions();\r
+                    //\r
+                    // We only need to test there are entries in the Leaf LibraryClassDefinitions section!\r
+                    if (leafLibClassDef.getLibraryClassList().size() > 0) {\r
+                        for (int index = 0; index < leafLibClassDef.getLibraryClassList().size(); index++) {\r
+                            //\r
+                            // We can use the Keyword to search to see if the Leaf's Library Class was already\r
+                            // added to the Merge Module.\r
+                            String test = "";\r
+                            String leafKeyword = leafLibClassDef.getLibraryClassList().get(index).getKeyword()\r
+                                                                .toString().trim();\r
+\r
+                            leafUsage = "";\r
+                            if (leafLibClassDef.getLibraryClassList().get(index).getUsage() != null)\r
+                                leafUsage = leafLibClassDef.getLibraryClassList().get(index).getUsage().toString()\r
+                                                           .trim();\r
+\r
+                            String leafSupArchList = "";\r
+                            if (leafLibClassDef.getLibraryClassList().get(index).getSupArchList() != null)\r
+                                leafSupArchList = leafLibClassDef.getLibraryClassList().get(index).getSupArchList()\r
+                                                                 .toString().trim();\r
+\r
+                            String leafSupModuleList = "";\r
+                            if (leafLibClassDef.getLibraryClassList().get(index).getSupModuleList() != null)\r
+                                leafSupModuleList = leafLibClassDef.getLibraryClassList().get(index).getSupModuleList()\r
+                                                                   .toString().trim();\r
+\r
+                            test = checkDuplicateStrings(leafKeyword, aLibClassDefs);\r
+                            if (test.length() > 0) {\r
+                                // The checkDuplicateStrings returns "" if a duplicate was found.\r
+                                // Here, the Leaf LibraryClass gets entered because the Keyword was not found.\r
+                                // No more testing is required, since this is the first instance of the LibraryClass\r
+                                libClassDefs.addNewLibraryClass();\r
+                                libClassDefs.setLibraryClassArray(libraryClassIndex++,\r
+                                                                  leafLibClassDef.getLibraryClassList().get(index));\r
+                            } else {\r
+                                // The Merged Module has already specified the Library Class\r
+                                // Check ATTRIBUTES, following the rules above.\r
+                                // Since we cannot get the LibraryClass entry using the Keyword, we have to search\r
+                                // all of the Merged Module's LibraryClass statements until we find a match.\r
+                                // Also, we may have more than one LibraryClass with the same Keyword, but different\r
+                                // Usage, SupArchList, FeatureFlag or SupModuleList\r
+                                for (int nidx = 0; nidx < libraryClassIndex; nidx++) {\r
+                                    String mergeKeyword = libClassDefs.getLibraryClassList().get(nidx).getKeyword()\r
+                                                                      .trim();\r
+\r
+                                    if (leafKeyword.contentEquals(mergeKeyword)) {\r
+                                        // We have the FIRST match, let's check usage, remember, we can have more than one LibraryClass Keyword.\r
+                                        mergeUsage = libClassDefs.getLibraryClassList().get(nidx).getUsage().toString()\r
+                                                                 .trim();\r
+                                        // If the usage is identical, check the SupArchList next\r
+                                        if (!leafUsage.contentEquals(mergeUsage)) {\r
+                                            if (checkUsage().trim().contains("DIFFERENT")) {\r
+                                                //  See if there is another entry for PRODUCED or CONSUME\r
+                                                int anotherLC = NOTFOUND;\r
+                                                for (int iidx = nidx + 1; iidx < libraryClassIndex; iidx++) {\r
+                                                    String innerTestKeyword = libClassDefs.getLibraryClassList()\r
+                                                                                          .get(iidx).getKeyword()\r
+                                                                                          .toString().trim();\r
+                                                    if (leafKeyword.contentEquals(innerTestKeyword)) {\r
+                                                        anotherLC = FOUND;\r
+                                                        mergeUsage = libClassDefs.getLibraryClassList().get(iidx)\r
+                                                                                 .getUsage().toString().trim();\r
+                                                        if (checkProduced()) {\r
+                                                            libClassDefs\r
+                                                                        .getLibraryClassList()\r
+                                                                        .get(iidx)\r
+                                                                        .setUsage(\r
+                                                                                  org.tianocore.UsageTypes.ALWAYS_PRODUCED);\r
+                                                        }\r
+                                                        // Both Usage types are CONSUMED\r
+                                                        if (checkConsumed()) {\r
+                                                            libClassDefs\r
+                                                                        .getLibraryClassList()\r
+                                                                        .get(iidx)\r
+                                                                        .setUsage(\r
+                                                                                  org.tianocore.UsageTypes.ALWAYS_CONSUMED);\r
+                                                        }\r
+                                                        if (((mergeUsage.contains("TO_START")) && (leafUsage\r
+                                                                                                            .contains("TO_START"))))\r
+                                                            anotherLC = FOUND;\r
+                                                        if (((mergeUsage.contains("BY_START")) && (leafUsage\r
+                                                                                                            .contains("BY_START"))))\r
+                                                            anotherLC = FOUND;\r
+                                                    }\r
+                                                }\r
+                                                if (anotherLC == NOTFOUND) {\r
+                                                    // we need to add the leaf Library Class\r
+                                                    libClassDefs.addNewLibraryClass();\r
+                                                    libClassDefs\r
+                                                                .setLibraryClassArray(\r
+                                                                                      libraryClassIndex++,\r
+                                                                                      leafLibClassDef\r
+                                                                                                     .getLibraryClassList()\r
+                                                                                                     .get(index));\r
+                                                }\r
+                                            }\r
+\r
+                                            // Both Usage types are PRODUCED\r
+                                            if (checkUsage().trim().contains("PRODUCED")) {\r
+                                                libClassDefs.getLibraryClassList().get(nidx)\r
+                                                            .setUsage(org.tianocore.UsageTypes.ALWAYS_PRODUCED);\r
+                                            }\r
+                                            // Both Usage types are CONSUMED\r
+                                            if (checkUsage().trim().contains("CONSUMED")) {\r
+                                                libClassDefs.getLibraryClassList().get(nidx)\r
+                                                            .setUsage(org.tianocore.UsageTypes.ALWAYS_CONSUMED);\r
+                                            }\r
+                                        }\r
+                                        // Usage testing completed\r
+                                        // Check SupArchList\r
+                                        String mergeSupArchList = "";\r
+                                        if (libClassDefs.getLibraryClassList().get(nidx).getSupArchList() != null)\r
+                                            mergeSupArchList = libClassDefs.getLibraryClassList().get(nidx)\r
+                                                                           .getSupArchList().toString().trim();\r
+                                        if (!mergeSupArchList.equalsIgnoreCase(leafSupArchList)) {\r
+                                            System.out\r
+                                                      .println("ERROR: Library Class, keyword: " + leafKeyword\r
+                                                               + " defines a different set of supported architectures.");\r
+                                            System.out\r
+                                                      .println("Version 0.1 of the merge tool requires that they must be identical!");\r
+                                            System.out.println("First instance of the Library used: "\r
+                                                               + mergeSupArchList);\r
+                                            System.out.println("While this module, " + leafFilename + " uses: "\r
+                                                               + leafSupArchList);\r
+                                            System.out.println("Merge ABORTED!");\r
+                                            System.exit(FAIL);\r
+                                        }\r
+                                        // Architecture Testing completed\r
+                                        // Check SupModuleType\r
+                                        String mergeSupModuleList = "";\r
+                                        if (libClassDefs.getLibraryClassList().get(nidx).getSupModuleList() != null)\r
+                                            mergeSupModuleList = libClassDefs.getLibraryClassList().get(nidx)\r
+                                                                             .getSupModuleList().toString().trim();\r
+                                        if (!mergeSupModuleList.equalsIgnoreCase(leafSupModuleList)) {\r
+                                            System.out.println("ERROR: Library Class, keyword: " + leafKeyword\r
+                                                               + " defines a different set of supported modules.");\r
+                                            System.out\r
+                                                      .println("Version 0.1 of the merge tool requires that they must be identical!");\r
+                                            System.out.println("First instance of the Library used: "\r
+                                                               + mergeSupModuleList);\r
+                                            System.out.println("While this module, " + leafFilename + " uses: "\r
+                                                               + leafSupModuleList);\r
+                                            System.out.println("Merge ABORTED!");\r
+                                            System.exit(FAIL);\r
+                                        }\r
+                                        // Supported Module Testing completed\r
+                                        // Check FeatureFlage\r
+                                        //  Next version, not this one.\r
+                                    }\r
+                                } // end of processing of duplicate Library Class entries\r
+                            } // end duplicate entry\r
+                        } // end of test loop for duplicates   \r
+                    } // endif Merge Module LibraryModuleDefinitions existed\r
+                } // endif of LibraryModuleDefinition Tests\r
+\r
+                if (leafMsa.isSetSourceFiles()) {\r
+                    // TODO: test for NULL settings\r
+                    // Add Sourcefiles to the Merge Module. NOTE: ONLY MODIFY THE Filename, prepending the path to the MSA file.\r
+                    // First get the path portion of the leafMSA file, which will be prepended to the filename\r
+                    // everything else stays intact.\r
+                    if (mergeSourceFiles == null)\r
+                        mergeSourceFiles = SourceFilesDocument.Factory.newInstance().addNewSourceFiles();\r
+\r
+                    String pathToMsa = getPathPartOfLeafMsa(leafFilename);\r
+                    if (DEBUG > 10)\r
+                        System.out.println("PATH TO SOURCE FILES: " + pathToMsa);\r
+                    if (leafMsa.getSourceFiles().getFilenameList() != null) {\r
+                        List<FilenameDocument.Filename> leafSourceFiles = leafMsa.getSourceFiles().getFilenameList();\r
+                        for (int index = 0; index < leafSourceFiles.size(); index++) {\r
+                            String leafFile = leafSourceFiles.get(index).getStringValue().toString();\r
+                            leafFile = pathToMsa + leafFile;\r
+                            leafSourceFiles.get(index).setStringValue(leafFile);\r
+                            mergeSourceFiles.addNewFilename();\r
+                            mergeSourceFiles.setFilenameArray(sourceFileIndex++, leafSourceFiles.get(index));\r
+                        }\r
+                    }\r
+                }\r
+\r
+                if (leafMsa.isSetPackageDependencies()) {\r
+                    //\r
+                    //  If mergePackageDependencies == null, create a new mergePackageDependencies and\r
+                    //  add the leaf module's Package Dependencies section to the merge Module's\r
+                    //  If mergePackageDependencies != null, test the leaf Package entries against\r
+                    //  what has already been added to the mergePackageDependencies data structure.\r
+                    //\r
+                    //  Add Unique Package entries.\r
+                    //  For this Merge Tool a Package is defined as PackageGuid\r
+                    //\r
+                    //   ABORT THE MERGE WITH FAIL if the PACKAGE VERSION NUMBERS ARE DIFFERENT\r
+                    //     between Leaf modules\r
+                    //\r
+                    //  Version 0.1 of the tool\r
+                    //      SupArchList, if it exists, must be identical for all Leaf Modules\r
+                    //  Probable Enhancement\r
+                    //      Just specify the lowest common denominator\r
+                    //\r
+                    //  Create the working copy if one does not exist!\r
+                    // TODO: CODE GOES HERE\r
+                    if (mergePackageDependencies == null)\r
+                        mergePackageDependencies = PackageDependenciesDocument.Factory.newInstance()\r
+                                                                                      .addNewPackageDependencies();\r
+\r
+                    PackageDependencies leafPackageDependencies = leafMsa.getPackageDependencies();\r
+                    if (leafPackageDependencies.sizeOfPackageArray() > 0) {\r
+                        for (int index = 0; index < leafPackageDependencies.sizeOfPackageArray(); index++) {\r
+                            String packageGuid = leafPackageDependencies.getPackageArray(index).getPackageGuid();\r
+                            String test = checkDuplicateStrings(packageGuid, aPackageList);\r
+                            if (test.length() > 0) {\r
+                                mergePackageDependencies.addNewPackage();\r
+                                mergePackageDependencies\r
+                                                        .setPackageArray(packageDependenciesIndex++,\r
+                                                                         leafPackageDependencies.getPackageArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+                } // endif PackageDependencies\r
+\r
+                if (leafMsa.isSetProtocols()) {\r
+                    // TODO: \r
+                    //  TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //  Add Usage Merging routines\r
+                    //  \r
+                    //  If mergeProtocols == null, create a new mergeProtocols and add\r
+                    //  leaf module's Protocols section to the merge Module's\r
+                    //\r
+                    //  Keep ALL Protocol entries before ProtocolNotify entries!\r
+                    //\r
+                    //  If mergeProtocols != null, check that we have only unique Protocol and ProtocolNotify entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the Protocol or ProtocolNotify as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the Protocol or ProtocolNotify as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique Protocol or ProtocolNotify Entry, otherwise fail the Merge\r
+                    //\r
+                    //  HelpText RULE:\r
+                    //  HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename\r
+                    //  is the leaf Module's path and filename to the MSA file!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+\r
+                    if (mergeProtocols == null)\r
+                        mergeProtocols = ProtocolsDocument.Factory.newInstance().addNewProtocols();\r
+\r
+                    Protocols leafProtocols = leafMsa.getProtocols();\r
+                    // Handle Protocol Entries First\r
+                    if (leafProtocols.sizeOfProtocolArray() > 0) {\r
+                        for (int index = 0; index < leafProtocols.sizeOfProtocolArray(); index++) {\r
+                            String protocolCName = leafProtocols.getProtocolArray(index).getProtocolCName();\r
+                            String test = checkDuplicateStrings(protocolCName, aProtocolList);\r
+                            if (test.length() > 0) {\r
+                                // new Protocol\r
+                                mergeProtocols.addNewProtocol();\r
+                                mergeProtocols.setProtocolArray(protocolIndex++, leafProtocols.getProtocolArray(index));\r
+                            } else {\r
+                                // Found an existing protocol\r
+                                leafUsage = leafProtocols.getProtocolArray(index).getUsage().toString().trim();\r
+                                for (int nidx = 0; nidx < protocolIndex; nidx++) {\r
+                                    if (mergeProtocols.getProtocolArray(nidx).getProtocolCName()\r
+                                                      .contains(protocolCName)) {\r
+                                        // Found one entry that matches.\r
+                                        mergeUsage = mergeProtocols.getProtocolArray(nidx).getUsage().toString().trim();\r
+                                        if (!mergeUsage.contentEquals(leafUsage)) {\r
+                                            // Usages are different\r
+                                            if (checkUsage().trim().contains("DIFFERENT")) {\r
+                                                // We need to check to see if there's another entry\r
+                                                int anotherProtocol = NOTFOUND;\r
+                                                for (int iidx = nidx + 1; iidx < protocolIndex; iidx++) {\r
+\r
+                                                    if (mergeProtocols.getProtocolArray(iidx).getUsage().toString()\r
+                                                                      .trim().contains(protocolCName)) {\r
+                                                        anotherProtocol = FOUND;\r
+                                                        mergeUsage = libClassDefs.getLibraryClassList().get(iidx)\r
+                                                                                 .getUsage().toString().trim();\r
+                                                        if (checkProduced()) {\r
+                                                            mergeProtocols\r
+                                                                          .getProtocolArray(nidx)\r
+                                                                          .setUsage(\r
+                                                                                    org.tianocore.UsageTypes.ALWAYS_PRODUCED);\r
+                                                            anotherProtocol = FOUND;\r
+                                                        }\r
+                                                        // Both Usage types are CONSUMED\r
+                                                        if (checkConsumed()) {\r
+                                                            mergeProtocols\r
+                                                                          .getProtocolArray(nidx)\r
+                                                                          .setUsage(\r
+                                                                                    org.tianocore.UsageTypes.ALWAYS_CONSUMED);\r
+                                                            anotherProtocol = FOUND;\r
+                                                        }\r
+                                                        if (((mergeUsage.contains("TO_START")) && (leafUsage\r
+                                                                                                            .contains("TO_START"))))\r
+                                                            anotherProtocol = FOUND;\r
+                                                        if (((mergeUsage.contains("BY_START")) && (leafUsage\r
+                                                                                                            .contains("BY_START"))))\r
+                                                            anotherProtocol = FOUND;\r
+                                                    }\r
+                                                }\r
+                                                if (anotherProtocol == NOTFOUND) {\r
+                                                    mergeProtocols.addNewProtocol();\r
+                                                    mergeProtocols\r
+                                                                  .setProtocolArray(\r
+                                                                                    protocolIndex++,\r
+                                                                                    leafProtocols\r
+                                                                                                 .getProtocolArray(index));\r
+                                                }\r
+                                            } else {\r
+                                                // usage types are either both PRODUCED or CONSUMED\r
+                                                if (checkProduced())\r
+                                                    mergeProtocols.getProtocolArray(nidx)\r
+                                                                  .setUsage(org.tianocore.UsageTypes.ALWAYS_PRODUCED);\r
+                                                if (checkConsumed())\r
+                                                    mergeProtocols.getProtocolArray(nidx)\r
+                                                                  .setUsage(org.tianocore.UsageTypes.ALWAYS_CONSUMED);\r
+                                            }\r
+                                        }\r
+                                    }\r
+                                } // end of Usage Test\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                    // Handle ProtocolNotify Entries Second\r
+                    if (leafProtocols.sizeOfProtocolNotifyArray() > 0) {\r
+                        for (int index = 0; index < leafProtocols.sizeOfProtocolNotifyArray(); index++) {\r
+                            String protocolNotifyCName = leafProtocols.getProtocolNotifyArray(index)\r
+                                                                      .getProtocolNotifyCName();\r
+                            String test = checkDuplicateStrings(protocolNotifyCName, aProtocolNotifyList);\r
+                            if (test.length() > 0) {\r
+                                mergeProtocols.addNewProtocolNotify();\r
+                                mergeProtocols.setProtocolNotifyArray(protocolNotifyIndex++,\r
+                                                                      leafProtocols.getProtocolNotifyArray(index));\r
+                            } else {\r
+                                // We have an existing ProtocolNotify Entry\r
+                                leafUsage = leafProtocols.getProtocolNotifyArray(index).getUsage().toString().trim();\r
+                                for (int nidx = 0; nidx < protocolIndex; nidx++) {\r
+                                    if (mergeProtocols.getProtocolNotifyArray(nidx).getProtocolNotifyCName()\r
+                                                      .contains(protocolNotifyCName)) {\r
+                                        // Found one entry that matches.\r
+                                        mergeUsage = mergeProtocols.getProtocolNotifyArray(nidx).getUsage().toString().trim();\r
+                                        if (!mergeUsage.contentEquals(leafUsage)) {\r
+                                            // Usages are different\r
+                                            if (checkUsage().trim().contains("DIFFERENT")) {\r
+                                                // We need to check to see if there's another entry\r
+                                                int anotherProtocol = NOTFOUND;\r
+                                                for (int iidx = nidx + 1; iidx < protocolIndex; iidx++) {\r
+\r
+                                                    if (mergeProtocols.getProtocolNotifyArray(iidx).getUsage().toString()\r
+                                                                      .trim().contains(protocolNotifyCName)) {\r
+                                                        anotherProtocol = FOUND;\r
+                                                        mergeUsage = libClassDefs.getLibraryClassList().get(iidx)\r
+                                                                                 .getUsage().toString().trim();\r
+                                                        if (checkProduced()) {\r
+                                                            mergeProtocols\r
+                                                                          .getProtocolNotifyArray(nidx)\r
+                                                                          .setUsage(\r
+                                                                                    org.tianocore.UsageTypes.ALWAYS_PRODUCED);\r
+                                                            anotherProtocol = FOUND;\r
+                                                        }\r
+                                                        // Both Usage types are CONSUMED\r
+                                                        if (checkConsumed()) {\r
+                                                            mergeProtocols\r
+                                                                          .getProtocolNotifyArray(nidx)\r
+                                                                          .setUsage(\r
+                                                                                    org.tianocore.UsageTypes.ALWAYS_CONSUMED);\r
+                                                            anotherProtocol = FOUND;\r
+                                                        }\r
+                                                        if (((mergeUsage.contains("TO_START")) && (leafUsage\r
+                                                                                                            .contains("TO_START"))))\r
+                                                            anotherProtocol = FOUND;\r
+                                                        if (((mergeUsage.contains("BY_START")) && (leafUsage\r
+                                                                                                            .contains("BY_START"))))\r
+                                                            anotherProtocol = FOUND;\r
+                                                    }\r
+                                                }\r
+                                                if (anotherProtocol == NOTFOUND) {\r
+                                                    mergeProtocols.addNewProtocolNotify();\r
+                                                    mergeProtocols\r
+                                                                  .setProtocolNotifyArray(\r
+                                                                                    protocolNotifyIndex++,\r
+                                                                                    leafProtocols\r
+                                                                                                 .getProtocolNotifyArray(index));\r
+                                                }\r
+                                            } else {\r
+                                                // usage types are either both PRODUCED or CONSUMED\r
+                                                if (checkProduced())\r
+                                                    mergeProtocols.getProtocolNotifyArray(nidx)\r
+                                                                  .setUsage(org.tianocore.UsageTypes.ALWAYS_PRODUCED);\r
+                                                if (checkConsumed())\r
+                                                    mergeProtocols.getProtocolNotifyArray(nidx)\r
+                                                                  .setUsage(org.tianocore.UsageTypes.ALWAYS_CONSUMED);\r
+                                            }\r
+                                        }\r
+                                    }\r
+                                } // end of Usage Test\r
+                            } // end of Usage test\r
+                        }\r
+                    }\r
+\r
+                } // endif Protocols\r
+\r
+                if (leafMsa.isSetEvents()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    //  "Unique" Entries are based on EventsTypes:EventGuidCName attributes\r
+                    //    NOTE: The EventGuidCName can appear once and only once in a CreateEvents Section\r
+                    //          The SAME EventGuidCName can appear once and only once in the SignalEvents Section\r
+                    //    Two EventGuidCName entries, one in CreateEvents the other in SignalEvents IS PERMITTED!\r
+                    //\r
+                    //  If mergeEvents == null, create a new mergeEvents and add\r
+                    //  leaf module's Events section to the merge Module's\r
+                    //\r
+                    //  Keep ALL CreateEvents entries before SignalEvents entries!\r
+                    //\r
+                    //  If mergeEvents != null, check that we have only unique CreateEvents and SignalEvents entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the CreateEvents.EventTypes or SignalEvents.EventTypes as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the CreateEvents.EventTypes or SignalEvents.EventTypes as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique EventTypes, otherwise fail the Merge\r
+                    //\r
+                    //  The EventTypes.EventType elements must be identical for all instances of\r
+                    //    the EventGuidCName  FAIL THE MERGE WITH ERROR indicating the Leaf file name that \r
+                    //    was different.\r
+                    //\r
+                    //\r
+                    //  HelpText RULE:\r
+                    //  HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename\r
+                    //  is the leaf Module's path and filename to the MSA file!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // TODO: Code goes here\r
+\r
+                    if (mergeCreateEvents == null)\r
+                        mergeCreateEvents = EventsDocument.Events.CreateEvents.Factory.newInstance();\r
+\r
+                    Events leafEvents = leafMsa.getEvents();\r
+                    if (leafEvents.getCreateEvents() != null) {\r
+                        Events.CreateEvents leafCreateEvents = leafEvents.getCreateEvents();\r
+                        if (leafCreateEvents.sizeOfEventTypesArray() > 0) {\r
+                            for (int index = 0; index < leafCreateEvents.sizeOfEventTypesArray(); index++) {\r
+                                String EventGuidCName = leafCreateEvents.getEventTypesArray(index).getEventGuidCName();\r
+                                String test = checkDuplicateStrings(EventGuidCName, aCreateEventsList);\r
+                                if (test.length() > 0) {\r
+                                    mergeCreateEvents.addNewEventTypes();\r
+                                    mergeCreateEvents.setEventTypesArray(createEventIndex++,\r
+                                                                         leafEvents.getCreateEvents()\r
+                                                                                   .getEventTypesArray(index));\r
+\r
+                                }\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                    if (mergeSignalEvents == null)\r
+                        mergeSignalEvents = EventsDocument.Events.SignalEvents.Factory.newInstance();\r
+\r
+                    if (leafEvents.getSignalEvents() != null) {\r
+                        Events.SignalEvents leafSignalEvents = leafEvents.getSignalEvents();\r
+                        if (leafSignalEvents.sizeOfEventTypesArray() > 0) {\r
+                            for (int index = 0; index < leafSignalEvents.sizeOfEventTypesArray(); index++) {\r
+                                String EventGuidCName = leafSignalEvents.getEventTypesArray(index).getEventGuidCName();\r
+                                String test = checkDuplicateStrings(EventGuidCName, aSignalEventsList);\r
+                                if (test.length() > 0) {\r
+                                    mergeSignalEvents.addNewEventTypes();\r
+                                    mergeSignalEvents.setEventTypesArray(signalEventIndex++,\r
+                                                                         leafEvents.getSignalEvents()\r
+                                                                                   .getEventTypesArray(index));\r
+                                }\r
+                            }\r
+                        }\r
+                    }\r
+                } // endif Events                \r
+\r
+                if (leafMsa.isSetHobs()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    //  "Unique" Entries are based on Hobs.HobTypes:HobGuidCName attribute\r
+                    //\r
+                    //  If mergeHobs == null, create a new mergeHobs and add\r
+                    //  leaf module's Hobs section to the merge Module's\r
+                    //\r
+                    //  \r
+                    //  If mergeHobs != null, check that we have only unique Hobs.HobTypes entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the Hobs.HobTypes as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the Hobs.HobTypes as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique HobTypes element, otherwise fail the Merge\r
+                    //\r
+                    //  The HobTypes.HobType elements must be identical for all instances of\r
+                    //    the HobGuidCName  FAIL THE MERGE WITH ERROR indicating the Leaf file name that \r
+                    //    was different.\r
+                    //\r
+                    //\r
+                    //  HelpText RULE:\r
+                    //  HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename\r
+                    //  is the leaf Module's path and filename to the MSA file!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // TODO: Code goes here\r
+                    if (mergeHobs == null)\r
+                        mergeHobs = HobsDocument.Factory.newInstance().addNewHobs();\r
+\r
+                    Hobs leafHobs = leafMsa.getHobs();\r
+                    if (leafHobs.sizeOfHobTypesArray() > 0) {\r
+                        for (int index = 0; index < leafHobs.sizeOfHobTypesArray(); index++) {\r
+                            String hobGuidCName = leafHobs.getHobTypesArray(index).getHobType().toString();\r
+                            String test = checkDuplicateStrings(hobGuidCName, aHobsList);\r
+                            if (test.length() > 0) {\r
+                                mergeHobs.addNewHobTypes();\r
+                                mergeHobs.setHobTypesArray(hobsIndex++, leafHobs.getHobTypesArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+                } // endif Hobs                \r
+\r
+                if (leafMsa.isSetPPIs()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    //  Keep only Unique Ppi or PpiNotify elements, based on the PpiCName and PpiNotifyCName respectively.\r
+\r
+                    //  If mergePpi == null, create a new mergePpi and add\r
+                    //  leaf module's PPIs section to the merge Module's\r
+                    //\r
+                    //  Keep ALL Ppi entries before PpiNotify entries!\r
+                    //\r
+                    //  If mergePpi != null, check that we have only unique Ppi and PpiNotify entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the Ppi or PpiNotify as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the Ppi or PpiNotify as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique Ppi or PpiNotify Entry, otherwise fail the Merge\r
+                    //\r
+                    //  HelpText RULE:\r
+                    //  HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename\r
+                    //  is the leaf Module's path and filename to the MSA file!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // TODO: Code Goes Here!\r
+                    if (mergePpis == null)\r
+                        mergePpis = PPIsDocument.Factory.newInstance().addNewPPIs();\r
+\r
+                    PPIs leafPPIs = leafMsa.getPPIs();\r
+                    // Handle the PPI Entries First\r
+                    if (leafPPIs.sizeOfPpiArray() > 0) {\r
+                        for (int index = 0; index < leafPPIs.sizeOfPpiArray(); index++) {\r
+                            String ppiCName = leafPPIs.getPpiArray(index).getPpiCName();\r
+                            String test = checkDuplicateStrings(ppiCName, aPpiList);\r
+                            if (test.length() > 0) {\r
+                                mergePpis.addNewPpi();\r
+                                mergePpis.setPpiArray(ppiIndex++, leafPPIs.getPpiArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                    // Handle the PpiNotify Second\r
+                    if (leafPPIs.sizeOfPpiNotifyArray() > 0) {\r
+                        for (int index = 0; index < leafPPIs.sizeOfPpiNotifyArray(); index++) {\r
+                            String ppiNotifyCName = leafPPIs.getPpiNotifyArray(index).getPpiNotifyCName();\r
+                            String test = checkDuplicateStrings(ppiNotifyCName, aPpiNotifyList);\r
+                            if (test.length() > 0) {\r
+                                mergePpis.addNewPpiNotify();\r
+                                mergePpis.setPpiNotifyArray(ppiNotifyIndex++, leafPPIs.getPpiNotifyArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                } // endif Ppis\r
+\r
+                if (leafMsa.isSetVariables()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    //  Keep only Unique Variable elements, based on the VariableName element.\r
+                    //\r
+                    //  If mergeVariables == null, create a new mergeVariables and add\r
+                    //  leaf module's Variables section to the merge Module's\r
+                    //\r
+                    //  If mergeVariables != null, check that we have only unique Variable entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the Variable as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the Variable as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique Variable entry, otherwise fail the Merge\r
+                    //\r
+                    //  HelpText RULE:\r
+                    //  HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename\r
+                    //  is the leaf Module's path and filename to the MSA file!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // TODO: Code Goes Here!\r
+                    if (mergeVariables == null)\r
+                        mergeVariables = VariablesDocument.Factory.newInstance().addNewVariables();\r
+\r
+                    Variables leafVariables = leafMsa.getVariables();\r
+                    if (leafVariables.sizeOfVariableArray() > 0) {\r
+                        for (int index = 0; index < leafVariables.sizeOfVariableArray(); index++) {\r
+                            String variableGuidCName = leafVariables.getVariableArray(index).getGuidCName();\r
+                            String test = checkDuplicateStrings(variableGuidCName, aVariablesList);\r
+                            if (test.length() > 0) {\r
+                                mergeVariables.addNewVariable();\r
+                                mergeVariables\r
+                                              .setVariableArray(variablesIndex++, leafVariables.getVariableArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                }// endif Variables\r
+\r
+                if (leafMsa.isSetBootModes()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    //  Keep only Unique BootMode elements, based on the BootModeName Attribute.\r
+                    //\r
+                    //  If mergeBootModes == null, create a new mergeBootModes and add\r
+                    //  leaf module's BootModes section to the merge Module's\r
+                    //\r
+                    //  If mergeBootModes != null, check that we have only unique BootMode entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the BootMode as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the BootMode as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique BootMode entry, otherwise fail the Merge\r
+                    //\r
+                    //  HelpText RULE:\r
+                    //  HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename\r
+                    //  is the leaf Module's path and filename to the MSA file!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // TODO: Code Goes Here!\r
+                    if (mergeBootModes == null)\r
+                        mergeBootModes = BootModesDocument.Factory.newInstance().addNewBootModes();\r
+\r
+                    BootModes leafBootModes = leafMsa.getBootModes();\r
+                    if (leafBootModes.sizeOfBootModeArray() > 0) {\r
+                        for (int index = 0; index < leafBootModes.sizeOfBootModeArray(); index++) {\r
+                            String bootModeName = leafBootModes.getBootModeArray(index).getBootModeName().toString();\r
+                            String test = checkDuplicateStrings(bootModeName, aBootModesList);\r
+                            if (test.length() > 0) {\r
+                                mergeBootModes.addNewBootMode();\r
+                                mergeBootModes\r
+                                              .setBootModeArray(bootModesIndex++, leafBootModes.getBootModeArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                }// endif BootMode\r
+\r
+                if (leafMsa.isSetSystemTables()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    //  Keep only Unique SystemTableCNames elements, based on the SystemTableCName element.\r
+                    //\r
+                    //  If mergeSystemTables == null, create a new mergeSystemTables and add\r
+                    //  leaf module's Variables section to the merge Module's\r
+                    //\r
+                    //  If mergeSystemTables != null, check that we have only unique SystemTableCNames entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the SystemTableCName as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the SystemTableCName as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique SystemTableCNames entry, otherwise fail the Merge\r
+                    //\r
+                    //  HelpText RULE:\r
+                    //  HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename\r
+                    //  is the leaf Module's path and filename to the MSA file!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // TODO: Code Goes Here!\r
+                    if (mergeSystemTables == null)\r
+                        mergeSystemTables = SystemTablesDocument.Factory.newInstance().addNewSystemTables();\r
+\r
+                    SystemTables leafSystemTables = leafMsa.getSystemTables();\r
+                    if (leafSystemTables.sizeOfSystemTableCNamesArray() > 0) {\r
+                        for (int index = 0; index < leafSystemTables.sizeOfSystemTableCNamesArray(); index++) {\r
+                            String systemTableCName = leafSystemTables.getSystemTableCNamesArray(index)\r
+                                                                      .getSystemTableCName();\r
+                            String test = checkDuplicateStrings(systemTableCName, aSystemTablesList);\r
+                            if (test.length() > 0) {\r
+                                mergeSystemTables.addNewSystemTableCNames();\r
+                                mergeSystemTables\r
+                                                 .setSystemTableCNamesArray(\r
+                                                                            systemTableIndex++,\r
+                                                                            leafSystemTables\r
+                                                                                            .getSystemTableCNamesArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                }// endif SystemTables\r
+\r
+                if (leafMsa.isSetDataHubs()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    //  Keep only Unique DataHubs elements, based on the DataHubRecord.DataHubCName element.\r
+                    //\r
+                    //  If mergeDataHubs == null, create a new mergeDataHubs and add\r
+                    //  leaf module's DataHubs section to the merge Module's\r
+                    //\r
+                    //  If mergeDataHubs != null, check that we have only unique DataHubRecord entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the DataHubCName as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the DataHubCName as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique DataHubRecord entry, otherwise fail the Merge\r
+                    //\r
+                    //  HelpText RULE:\r
+                    //  HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename\r
+                    //  is the leaf Module's path and filename to the MSA file!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // TODO: Code Goes Here!\r
+                    if (mergeDataHubs == null)\r
+                        mergeDataHubs = DataHubsDocument.Factory.newInstance().addNewDataHubs();\r
+\r
+                    DataHubs leafDataHubs = leafMsa.getDataHubs();\r
+                    if (leafDataHubs.sizeOfDataHubRecordArray() > 0) {\r
+                        for (int index = 0; index < leafDataHubs.sizeOfDataHubRecordArray(); index++) {\r
+                            String dataHubCName = leafDataHubs.getDataHubRecordArray(index).getDataHubCName();\r
+                            String test = checkDuplicateStrings(dataHubCName, aDataHubsList);\r
+                            if (test.length() > 0) {\r
+                                mergeDataHubs.addNewDataHubRecord();\r
+                                mergeDataHubs.setDataHubRecordArray(dataHubsIndex++,\r
+                                                                    leafDataHubs.getDataHubRecordArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                }// endif DataHubs\r
+\r
+                if (leafMsa.isSetHiiPackages()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    //  Keep only Unique HiiPackage elements, based on the HiiPackage.HiiCName element.\r
+                    //\r
+                    //  If mergeHiiPackages == null, create a new mergeHiiPackages and add\r
+                    //  leaf module's DataHubs section to the merge Module's\r
+                    //\r
+                    //  If mergeHiiPackages != null, check that we have only unique HiiPackage entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the HiiPackage as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the HiiPackage as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique HiiPackage entry, otherwise fail the Merge\r
+                    //\r
+                    //  HelpText RULE:\r
+                    //  HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename\r
+                    //  is the leaf Module's path and filename to the MSA file!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // TODO: Code Goes Here!\r
+                    if (mergeHiiPackages == null)\r
+                        mergeHiiPackages = HiiPackagesDocument.Factory.newInstance().addNewHiiPackages();\r
+\r
+                    HiiPackages leafHiiPackages = leafMsa.getHiiPackages();\r
+                    if (leafHiiPackages.sizeOfHiiPackageArray() > 0) {\r
+                        for (int index = 0; index < leafHiiPackages.sizeOfHiiPackageArray(); index++) {\r
+                            String hiiCName = leafHiiPackages.getHiiPackageArray(index).getHiiCName();\r
+                            String test = checkDuplicateStrings(hiiCName, aHiiPackagesList);\r
+                            if (test.length() > 0) {\r
+                                mergeHiiPackages.addNewHiiPackage();\r
+                                mergeHiiPackages.setHiiPackageArray(hiiPackageIndex++,\r
+                                                                    leafHiiPackages.getHiiPackageArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                }// endif HiiPackage\r
+\r
+                if (leafMsa.isSetGuids()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    //  Keep only Unique Guids elements, based on the GuidCNames.GuidCName element.\r
+                    //\r
+                    //  If mergeGuids == null, create a new mergeGuids and add\r
+                    //  leaf module's Guids section to the merge Module's\r
+                    //\r
+                    //  If mergeGuids != null, check that we have only unique GuidCNames entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the GuidCNames as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the GuidCNames as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique GuidCNames entry, otherwise fail the Merge\r
+                    //\r
+                    //  HelpText RULE:\r
+                    //  HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename\r
+                    //  is the leaf Module's path and filename to the MSA file!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // TODO: Code Goes Here!\r
+                    if (mergeGuids == null)\r
+                        mergeGuids = GuidsDocument.Factory.newInstance().addNewGuids();\r
+\r
+                    Guids leafGuids = leafMsa.getGuids();\r
+                    if (leafGuids.sizeOfGuidCNamesArray() > 0) {\r
+                        for (int index = 0; index < leafGuids.sizeOfGuidCNamesArray(); index++) {\r
+                            String hiiCName = leafGuids.getGuidCNamesArray(index).getGuidCName();\r
+                            String test = checkDuplicateStrings(hiiCName, aGuidsList);\r
+                            if (test.length() > 0) {\r
+                                mergeGuids.addNewGuidCNames();\r
+                                mergeGuids.setGuidCNamesArray(guidsIndex++, leafGuids.getGuidCNamesArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                }// endif GuidCNames\r
+\r
+                if (leafMsa.isSetExterns()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    // FAIL THE MERGE if Externs.PcdIsDriver is present\r
+                    // FAIL THE MERGE if Externs.TianoR8FlashMap_h is TRUE\r
+                    //\r
+                    //  Keep only Unique Extern elements, based on the Extern.* elements.\r
+                    //\r
+                    //  If mergeExterns == null, create a new mergeExterns and add\r
+                    //  leaf module's Extern section to the merge Module's\r
+                    //\r
+                    //  If mergeExterns != null, check that we have only unique Extern.* entries\r
+                    //\r
+                    //  After storing the initial LEAF MODULE'S SPECIFICATION SECTION\r
+                    //  ALL other Leaf Modules must declare the exact same specifications\r
+                    //  If they do not, FAIL the MERGE with an error message, printing the\r
+                    //  name of the leaf MSA that did not match, along with\r
+                    //  Expected: from the merge module's specification list\r
+                    //  Got:      from the leaf file that fails!\r
+                    //\r
+                    //  For Each <Extern>\r
+                    //    For each pair of <ModuleEntryPoint> and/or <ModuleUnloadImage>\r
+                    //          The ModuleUnloadImage value must be identical for an identical pair of ModuleEntryPoint values\r
+                    //          If not, FAIL THE MERGE, giving the current leaf MSA filename as the failure, along with the\r
+                    //          additional error information as follows:\r
+                    //      -- leafFilename --\r
+                    //      ModuleEntryPoint: \r
+                    //      Expected ModuleUnloadImage:  fromMergeModule\r
+                    //      Got ModuleUnloadImage:       fromLeaf\r
+                    //      Merge Aborted!\r
+                    //    More than one <Extern> Section with a pair of <ModuleEntryPoint><ModuleUnloadImage> is allowed\r
+                    //\r
+                    //    For each pair of one <Constructor> and/or one <Destructor> elements\r
+                    //       The <Extern> section containing the <Constructor> <Destructor> pairs \r
+                    //        The Destructor value in all leaf modules must be identical for all Constructor elements that are identical.\r
+                    //      More than one <Extern> Section with Constructor/Destructor pair is permitted.\r
+                    //\r
+                    //  For each Set four elements, DriverBinding, ComponentName, DriverConfig and DriverDiag,\r
+                    //      1 DriverBinding and\r
+                    //         0 or 1 ComponentName and/or\r
+                    //         0 or 1 DriverConfig and/or\r
+                    //         0 or 1 DriverDiag \r
+                    //        elements must appear in 1 <Extern> Section.\r
+                    //\r
+                    //      A ComponentName cannot be used without a DriverBinding element.\r
+                    //      A DriverConfig element cannot appear without a DriverBinding element. \r
+                    //      A DriverDiag element cannot appear without a DriverBinding element\r
+                    //      These elements are matched within a single <Extern> Section uniquely defined by the DriverBinding element.  \r
+                    //    Multiple <Extern> sections of this type are permitted.\r
+                    //\r
+                    //  Each pair of SetVirtualAddressMapCallBack and ExitBootServiceCallBack elements MUST \r
+                    //  BE in one Extern Section.  ONE AND ONLY ONE of this section is permitted.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique Extern entry, otherwise fail the Merge\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // TODO: Code Goes Here!\r
+                    if (mergeExterns == null)\r
+                        mergeExterns = ExternsDocument.Factory.newInstance().addNewExterns();\r
+\r
+                    Externs leafExterns = leafMsa.getExterns();\r
+                    // PCD IS DRIVER NOT ALLOWED IN A MERGED Module\r
+                    if (leafExterns.isSetPcdIsDriver()) {\r
+                        System.out.println("The Module: " + leafFilename + " is a PCD Driver and CANNOT BE MERGED!");\r
+                        System.out.println("Merge Aborted");\r
+                        System.err.flush();\r
+                        System.exit(FAIL);\r
+                    }\r
+\r
+                    // TIANO R8 FLASHMAP.H NOT ALLOWED IN A MERGED Module\r
+                    if (leafExterns.isSetTianoR8FlashMapH()) {\r
+                        System.out.println("The Module: " + leafFilename\r
+                                           + " set the Tiano R8 FlashMap.h Flag and CANNOT BE MERGED!");\r
+                        System.out.println("Merge Aborted");\r
+                        System.err.flush();\r
+                        System.exit(FAIL);\r
+                    }\r
+\r
+                    // Add the Specification Array, one time only.\r
+                    if (leafExterns.sizeOfSpecificationArray() > 0) {\r
+                        for (int index = 0; index < leafExterns.sizeOfSpecificationArray(); index++) {\r
+                            String spec = leafExterns.getSpecificationArray(index);\r
+                            String test = checkSpecs(spec, leafFilename, aSpecArray);\r
+                            if (test.length() > 0) {\r
+                                mergeExterns.addNewSpecification();\r
+                                mergeExterns.setSpecificationArray(specIndex++, test);\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                    if (leafExterns.sizeOfExternArray() > 0) {\r
+                        for (int index = 0; index < leafExterns.sizeOfExternArray(); index++) {\r
+                            String test = "";\r
+                            if (leafExterns.getExternArray(index).isSetModuleEntryPoint()) {\r
+                                // ModuleEntryPoint, if an Unload Image is paired with\r
+                                // the Module Entry point, it will piggy back on the\r
+                                // Module Entry Point Extern\r
+                                String moduleEntryPoint = leafExterns.getExternArray(index).getModuleEntryPoint();\r
+                                test = checkDuplicateStrings(moduleEntryPoint, aEntryPointList);\r
+\r
+                            } else if (leafExterns.getExternArray(index).isSetModuleUnloadImage()) {\r
+                                // Module Unload Image is here in case there is no\r
+                                // Entry Point - not very typical\r
+                                String moduleUnloadImage = leafExterns.getExternArray(index).getModuleUnloadImage();\r
+                                test = checkDuplicateStrings(moduleUnloadImage, aUnloadImageList);\r
+\r
+                            } else if (leafExterns.getExternArray(index).isSetConstructor()) {\r
+                                // Constructors must be unique, if a Destructor is\r
+                                // paired with a constructor, it will pigback on\r
+                                // the constructor\r
+                                String constructor = leafExterns.getExternArray(index).getConstructor();\r
+                                test = checkDuplicateStrings(constructor, aConstructorList);\r
+\r
+                            } else if (leafExterns.getExternArray(index).isSetDestructor()) {\r
+                                // Destructors must be unique\r
+                                String destructor = leafExterns.getExternArray(index).getDestructor();\r
+                                test = checkDuplicateStrings(destructor, aDestructorList);\r
+\r
+                            } else if (leafExterns.getExternArray(index).isSetDriverBinding()) {\r
+                                // Driver Bindings must be unique\r
+                                // Fixed the MSA files - ComponentName, Driver Config and\r
+                                // Driver Diag statments must be inside of an Extern that \r
+                                // has a Driver Binding\r
+                                String driverBinding = leafExterns.getExternArray(index).getDriverBinding();\r
+                                test = checkDuplicateStrings(driverBinding, aDriverBindingList);\r
+\r
+                            } else if (leafExterns.getExternArray(index).isSetSetVirtualAddressMapCallBack()) {\r
+                                // Handle Virtual Address Map and Exit Boot Services Call Backs\r
+                                // in a single Extern if they are present\r
+                                String virtualAddressMap = leafExterns.getExternArray(index)\r
+                                                                      .getSetVirtualAddressMapCallBack();\r
+                                test = checkDuplicateStrings(virtualAddressMap, aVirtualAddressMapList);\r
+\r
+                            } else if (leafExterns.getExternArray(index).isSetExitBootServicesCallBack()) {\r
+                                // Handle a stand alone Exit Boot Services Call Back\r
+                                String exitBootServices = leafExterns.getExternArray(index)\r
+                                                                     .getExitBootServicesCallBack();\r
+                                test = checkDuplicateStrings(exitBootServices, aExitBootServicesList);\r
+                            } else {\r
+                                // Unknown Extern  FAIL  - May be an invalid Component Name in it's own Extern Statement\r
+                                System.out.println("Unknown EXTERN defined in Module: " + leafFilename);\r
+                                System.out.println("Value: " + leafExterns.getExternArray(index).toString());\r
+                                System.out.println("Merge Aborted!");\r
+                                System.err.flush();\r
+                                System.exit(FAIL);\r
+                            }\r
+\r
+                            if (test.length() > 0) {\r
+                                mergeExterns.addNewExtern();\r
+                                mergeExterns.setExternArray(externsIndex++, leafExterns.getExternArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+                }// endif mergeExterns\r
+\r
+                if (leafMsa.isSetPcdCoded()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    //  Keep only Unique PcdCoded elements, based on the PcdCoded.PcdEntry.C_Name element.\r
+                    //\r
+                    //  If mergePcdCoded == null, create a new mergePcdCoded and add\r
+                    //  leaf module's PcdCoded section to the merge Module's\r
+                    //\r
+                    //  If mergePcdCoded != null, check that we have only unique PcdEntry entries\r
+                    //  IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,\r
+                    //     Mark the PcdEntry as ALWAYS_PRODUCED\r
+                    //  IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,\r
+                    //     Mark the PcdEntry as ALWAYS_CONSUMED\r
+                    //  It is permissable to have one PRODUCED and one CONSUMED entry\r
+                    //  TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START\r
+                    //     and another Leaf uses BY_START, create two entries, one for each.\r
+                    //\r
+                    //  First PASS of the TOOL \r
+                    //      SupArchList must be identical for all Leaf Modules!  Fail the Merge if not, reporting\r
+                    //      this as an error!\r
+                    //  Probable Enhancement\r
+                    //      The SupArchList, if set, must be for the "Lowest Common Denominator"\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the FeatureFlag - we are not using it now.\r
+                    //  Probable Enhancement\r
+                    //      FeatureFlags must be identical for each unique HiiPackage entry, otherwise fail the Merge\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      Ignore the PcdEntry:Usage Attribute\r
+                    //  Probable Enhancment\r
+                    //      Have Usage Combined like was done for the Library Class\r
+                    //\r
+                    //  First PASS of the TOOL\r
+                    //      If Different PcdItemTypes, Abort The MERGE\r
+                    //\r
+                    //  Probably Enhancement\r
+                    //      The PcdItemType Should be checked using the following rules\r
+                    //          Feature Flag MUST ALWAYS BE A FEATURE FLAG\r
+                    //          If different Item Types occur, mark the PCD as DYNAMIC\r
+                    //\r
+                    //  HelpText RULE:\r
+                    //  HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename\r
+                    //  is the leaf Module's path and filename to the MSA file!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // TODO: Code Goes Here!\r
+                    if (mergePcdCoded == null)\r
+                        mergePcdCoded = PcdCodedDocument.Factory.newInstance().addNewPcdCoded();\r
+\r
+                    PcdCoded leafPcdCoded = leafMsa.getPcdCoded();\r
+                    if (leafPcdCoded.sizeOfPcdEntryArray() > 0) {\r
+                        for (int index = 0; index < leafPcdCoded.sizeOfPcdEntryArray(); index++) {\r
+                            String pcdCName = leafPcdCoded.getPcdEntryArray(index).getCName();\r
+                            String pcdItemType = leafPcdCoded.getPcdEntryArray(index).getPcdItemType().toString();\r
+                            String test = checkPcd(pcdCName, pcdItemType, leafFilename, aPcdCNameList);\r
+                            if (test.length() > 0) {\r
+                                mergePcdCoded.addNewPcdEntry();\r
+                                mergePcdCoded.setPcdEntryArray(pcdIndex++, leafPcdCoded.getPcdEntryArray(index));\r
+                            }\r
+                        }\r
+                    }\r
+\r
+                }// endif PcdCoded\r
+\r
+                if (leafMsa.isSetModuleBuildOptions()) {\r
+                    // TODO: TEST FOR NULL SETTINGS so we don't get an error!\r
+                    //\r
+                    // Any element that appear within a leaf's ModuleBuildOptions should be appended to\r
+                    // the Merge Module's BuildOptions section.\r
+                    //\r
+                    //  NO ATTEMPT IS MADE TO VERIFY UNIQUENESS ON ANYTHING WITHIN THIS SECTION!\r
+                    //\r
+                    // Create the working copy if one does not exist!\r
+                    // if (mergeBuildOptions == null)\r
+                    //    mergeBuildOptions = ModuleBuildOptionsDocument.Factory.newInstance().addNewModuleBuildOptions();\r
+\r
+                    // ModuleBuildOptions leafModuleBuildOptions = leafMsa.getModuleBuildOptions();\r
+\r
+                    // mergeBuildOptions.addNewModuleBuildOptions();\r
+                    // mergeBuildOptions.setModuleBuildOptions(leafModuleBuildOptions);\r
+\r
+                    //\r
+                    // TODO: Code Goes Here!\r
+                } // endif ModuleBuildOptions\r
+\r
+                // Need to process any UserExtensions here too.\r
+                if (leafMsa.getUserExtensionsList() != null) {\r
+\r
+                    if (mergeUserExtensions == null)\r
+                        mergeUserExtensions = UserExtensionsDocument.Factory.newInstance().addNewUserExtensions();\r
+\r
+                    // for (int index = 0; index < leafMsa.getUserExtensionsList().size(); index++)\r
+\r
+                }\r
+\r
+            } // Completed parsing all leaf files.\r
+\r
+            header.setAbstract(Abstract);\r
+            header.setCopyright(Copyright);\r
+            header.setDescription(Description);\r
+            License mLicense = License.Factory.newInstance();\r
+            mLicense.setStringValue(licenseTxt);\r
+            header.setLicense(mLicense);\r
+            if ((DEBUG > 0) || (VERBOSE > 0))\r
+                System.out.println("Merged Module supports: " + sArchitectures + " architectures.");\r
+            List<String> lArchitectures = new ArrayList<String>();\r
+            String s[] = sArchitectures.replace("  ", " ").trim().split(" ");\r
+            for (int idx = 0; idx < s.length; idx++) {\r
+                lArchitectures.add(s[idx]);\r
+                if (DEBUG > 7)\r
+                    System.out.println("Adding architecture: " + s[idx]);\r
+            }\r
+            moduleDefs.setSupportedArchitectures(lArchitectures);\r
+\r
+        } // endif mergeMsaFile == null\r
+\r
+        if ((uiName != null) && (uiName.length() > 0) && (result == PASS)) {\r
+            // TODO: Stub for replacing the msaFile UiName\r
+            if ((DEBUG > 0) || (VERBOSE > 0))\r
+                System.out.println("Updating the uiName: " + uiName);\r
+            header.setModuleName(uiName);\r
+        }\r
+\r
+        if ((baseName != null) && (baseName.length() > 0) && (result == PASS)) {\r
+            if ((DEBUG > 0) || (VERBOSE > 0))\r
+                System.out.println("Setting the Output Filename:" + baseName);\r
+            moduleDefs.setOutputFileBasename(baseName);\r
+        }\r
+\r
+        if (result == PASS) {\r
+            // TODO: Stub to write out the new MSA file\r
+            File outMsa = new File(msaFilename);\r
+            try {\r
+                if (DEBUG > 2)\r
+                    System.out.println("SAVING new MSA FILE: " + msaFilename);\r
+\r
+                mergeMsaFile.setMsaHeader(header);\r
+                mergeMsaFile.setModuleDefinitions(moduleDefs);\r
+                // ALL THE REST OF THE SECTIONS ARE OPTIONAL\r
+                // SO check that they are not null before adding them to the merged MSA file!\r
+                if (libClassDefs != null)\r
+                    mergeMsaFile.setLibraryClassDefinitions(libClassDefs);\r
+                if (mergeSourceFiles != null)\r
+                    mergeMsaFile.setSourceFiles(mergeSourceFiles);\r
+                if (mergePackageDependencies != null)\r
+                    mergeMsaFile.setPackageDependencies(mergePackageDependencies);\r
+                if (mergeProtocols != null)\r
+                    mergeMsaFile.setProtocols(mergeProtocols);\r
+\r
+                if ((mergeCreateEvents != null) || (mergeSignalEvents != null)) {\r
+                    if (mergeEvents == null)\r
+                        mergeEvents = EventsDocument.Factory.newInstance().addNewEvents();\r
+\r
+                    if (mergeCreateEvents.getEventTypesList().size() > 0) {\r
+                        mergeEvents.addNewCreateEvents();\r
+                        mergeEvents.setCreateEvents(mergeCreateEvents);\r
+                    }\r
+                    if (mergeSignalEvents.getEventTypesList().size() > 0) {\r
+                        mergeEvents.addNewSignalEvents();\r
+                        mergeEvents.setSignalEvents(mergeSignalEvents);\r
+                    }\r
+\r
+                    mergeMsaFile.setEvents(mergeEvents);\r
+                }\r
+\r
+                if (mergeHobs != null)\r
+                    mergeMsaFile.setHobs(mergeHobs);\r
+\r
+                if (mergePpis != null)\r
+                    mergeMsaFile.setPPIs(mergePpis);\r
+\r
+                if (mergeVariables != null)\r
+                    mergeMsaFile.setVariables(mergeVariables);\r
+\r
+                if (mergeBootModes != null)\r
+                    mergeMsaFile.setBootModes(mergeBootModes);\r
+\r
+                if (mergeSystemTables != null)\r
+                    mergeMsaFile.setSystemTables(mergeSystemTables);\r
+\r
+                if (mergeDataHubs != null)\r
+                    mergeMsaFile.setDataHubs(mergeDataHubs);\r
+\r
+                if (mergeHiiPackages != null)\r
+                    mergeMsaFile.setHiiPackages(mergeHiiPackages);\r
+\r
+                if (mergeGuids != null)\r
+                    mergeMsaFile.setGuids(mergeGuids);\r
+\r
+                if (mergeExterns != null)\r
+                    mergeMsaFile.setExterns(mergeExterns);\r
+\r
+                if (mergePcdCoded != null)\r
+                    mergeMsaFile.setPcdCoded(mergePcdCoded);\r
+\r
+                XmlCursor cursor = XmlConfig.setupXmlCursor(mergeMsaFile.newCursor());\r
+                XmlOptions options = XmlConfig.setupXmlOptions();\r
+                ModuleSurfaceAreaDocument msaDoc = ModuleSurfaceAreaDocument.Factory.newInstance();\r
+                msaDoc.addNewModuleSurfaceArea();\r
+                msaDoc.setModuleSurfaceArea(mergeMsaFile);\r
+                msaDoc.save(outMsa, options);\r
+                System.out.println("The Merged MSA file: " + msaFilename + ", has been created!");\r
+            } catch (IOException e) {\r
+                System.out.println("Problem writing the output file: " + msaFilename + " " + e);\r
+                result = FAIL;\r
+            }\r
+        }\r
+\r
+        if ((spdFilename != null) && (result == PASS)) {\r
+            // TODO: Stub for adding the msaFile to the <MsaFiles><Filename> in the spdFile\r
+            String msaLine = getPathFromSpd(spdFilename, msaFilename);\r
+            System.out.println("Updating the SPD file (" + spdFilename + ") with: " + msaLine);\r
+            try {\r
+                File spdFile = new File(spdFilename);\r
+                PackageSurfaceAreaDocument spdDoc = PackageSurfaceAreaDocument.Factory.parse(spdFile);\r
+                PackageSurfaceArea spd = spdDoc.getPackageSurfaceArea();\r
+\r
+                // MsaFiles mergeMsaFilesForSpd = MsaFilesDocument.Factory.newInstance().addNewMsaFiles();\r
+                List<String> msaFilenames = spd.getMsaFiles().getFilenameList();\r
+                msaFilenames.add(msaLine);\r
+                XmlCursor cursor = XmlConfig.setupXmlCursor(spd.newCursor());\r
+                XmlOptions options = XmlConfig.setupXmlOptions();\r
+                spdDoc.save(spdFile, options);\r
+            } catch (IOException e) {\r
+                System.out.println("I/O Exception on spd file: " + spdFilename + " " + e);\r
+            } catch (XmlException x) {\r
+                System.out.println("XML Exception on SPD file: " + spdFilename + " " + x);\r
+            }\r
+        } else if ((spdFilename == null) && (result == PASS)) {\r
+\r
+            System.out.println("The file: " + msaFilename + ", must be added to a package file before it can be used!");\r
+        }\r
+        return result;\r
+    }\r
+\r
+    public ModuleSurfaceArea getLeafFile(String filename) {\r
+        File leafMsaFile = new File(filename);\r
+        if ((DEBUG > 1) || (VERBOSE > 1))\r
+            System.out.println("Processing MSA File: " + filename);\r
+        try {\r
+            leafMsa = ModuleSurfaceAreaDocument.Factory.parse(leafMsaFile).getModuleSurfaceArea();\r
+            if ((DEBUG > 4) || (VERBOSE > 4))\r
+                System.out.println("Binary: " + leafMsa.getModuleDefinitions().getBinaryModule());\r
+            if (leafMsa.getModuleDefinitions().getBinaryModule()) {\r
+                System.out.println("ERROR: Binary Module was specified in MSA: " + filename);\r
+                System.out.println("Merge Aborted!");\r
+                System.err.flush();\r
+                return null;\r
+            }\r
+        } catch (IOException e) {\r
+            System.out.println("I/O Exception on filename: " + filename + " " + e);\r
+            System.out.println("Merge Aborted!");\r
+            System.err.flush();\r
+            System.exit(FAIL);\r
+        } catch (XmlException x) {\r
+            System.out.println("XML Exception reading file: " + filename + " " + x);\r
+            System.out.println("Merge Aborted!");\r
+            System.err.flush();\r
+            System.exit(FAIL);\r
+        }\r
+        return leafMsa;\r
+    }\r
+\r
+    private String getPathFromSpd(String spdFn, String msaFn) {\r
+        String path2Msa = null;\r
+\r
+        spdFn = spdFn.replace("\\", "/").trim();\r
+        String s[] = spdFn.split("/");\r
+        String justSpdFilename = s[s.length - 1];\r
+\r
+        String Cwd = System.getProperty("user.dir");\r
+        Cwd = Cwd.replace("\\", "/").trim();\r
+        if ((DEBUG > 10) || (VERBOSE > 10)) {\r
+            System.out.println("Current directory = " + Cwd);\r
+        }\r
+        String sp[] = Cwd.split("/");\r
+        int theDirectory = sp.length - (s.length - 1);\r
+        if (DEBUG > 10)\r
+            System.out.println("The Directory length: " + theDirectory + " s.length: " + s.length + " sp.length: "\r
+                               + (sp.length - 1));\r
+\r
+        String path2Spd = "";\r
+        for (int ictr = 0; ictr < theDirectory; ictr++) {\r
+            path2Spd += sp[ictr] + "/";\r
+            if (DEBUG > 10)\r
+                System.out.println("Creating path to SPD file: " + path2Spd);\r
+        }\r
+\r
+        String testPath2Spd = path2Spd + justSpdFilename;\r
+\r
+        File tFile = new File(testPath2Spd);\r
+        if (!tFile.exists()) {\r
+            System.out.println("The specified SPD file, " + spdFn + " does not exist at: " + testPath2Spd);\r
+            System.out.println("Please use the FrameworkWizard to add this MSA file to the package.");\r
+            System.exit(FAIL);\r
+        }\r
+        path2Msa = Cwd.replace(path2Spd, "");\r
+        path2Msa = path2Msa + "/" + msaFn;\r
+        return path2Msa;\r
+    }\r
+\r
+    private String checkDuplicateStrings(String aString, ArrayList<String> aList) {\r
+\r
+        for (int lctr = 0; lctr < aList.size(); lctr++) {\r
+            if (DEBUG > 8)\r
+                System.out.println("Comparing: \n" + aString.replace(" ", "").replace("\n", "") + "\nTo: \n"\r
+                                   + aList.get(lctr).replace(" ", "").replace("\n", "").toString().trim());\r
+            if (aString.replace(" ", "").replace("\n", "").contains(\r
+                                                                    aList.get(lctr).replace(" ", "").replace("\n", "")\r
+                                                                         .toString().trim())) {\r
+                if ((DEBUG > 3) || (VERBOSE > 3))\r
+                    System.out.println("Found a duplicate String, skipping!");\r
+                return "";\r
+            }\r
+        }\r
+        if ((DEBUG > 3) || (VERBOSE > 3))\r
+            System.out.println("Returning UNIQUE String!\n " + aString);\r
+        aList.add(aString);\r
+        return aString;\r
+    }\r
+\r
+    private String checkSpecs(String specName, String filename, ArrayList<String> aList) {\r
+        // Check Specifications\r
+        // Skip of Specs are identical\r
+        String spec[] = new String[2];\r
+        spec = specName.replace("  ", " ").trim().split(" ");\r
+        String specInMem[] = new String[2];\r
+        if ((DEBUG > 10) || (VERBOSE > 10))\r
+            System.out.println("Specification: " + specName);\r
+\r
+        for (int lctr = 0; lctr < aList.size(); lctr++) {\r
+            if (DEBUG > 8)\r
+                System.out.println("Comparing: \n" + specName.replace(" ", "").replace("\n", "") + "\nTo: \n"\r
+                                   + aList.get(lctr).replace(" ", "").replace("\n", "").toString().trim());\r
+            if (specName.replace(" ", "").replace("\n", "").contains(\r
+                                                                     aList.get(lctr).replace(" ", "").replace("\n", "")\r
+                                                                          .toString().trim())) {\r
+                if ((DEBUG > 3) || (VERBOSE > 3))\r
+                    System.out.println("Found a duplicate String, skipping!");\r
+                return "";\r
+            }\r
+            specInMem = aList.get(lctr).replace("  ", " ").trim().split(" ");\r
+            if (spec[0].contentEquals(specInMem[0])) {\r
+                if (!spec[1].contains(specInMem[1])) {\r
+                    System.out.println("Module: " + filename + " is coded to " + specName);\r
+                    System.out.println("Merge needs to be coded to: " + aList.get(lctr));\r
+                    System.out.println("Merge Aborted!");\r
+                    System.err.flush();\r
+                    System.exit(FAIL);\r
+                }\r
+            }\r
+\r
+        }\r
+        if ((DEBUG > 3) || (VERBOSE > 3))\r
+            System.out.println("Returning Specification: " + specName);\r
+        aList.add(specName);\r
+        return specName;\r
+    }\r
+\r
+    private String checkPcd(String pcdName, String itemType, String filename, ArrayList<String> aList) {\r
+\r
+        for (int lctr = 0; lctr < aList.size(); lctr++) {\r
+            if (DEBUG > 8)\r
+                System.out.println("Comparing: \n" + pcdName.replace(" ", "").replace("\n", "") + "\nTo: \n"\r
+                                   + aList.get(lctr).replace(" ", "").replace("\n", "").toString().trim());\r
+            if (pcdName.replace(" ", "").replace("\n", "").contains(\r
+                                                                    aList.get(lctr).replace(" ", "").replace("\n", "")\r
+                                                                         .toString().trim())) {\r
+                if (!aPcdItemTypeList.get(lctr).contains(itemType)) {\r
+                    System.out\r
+                              .println("The Pcd Item Type for " + pcdName + " in file: " + filename + "does not match!");\r
+                    System.out.println("Expected:   " + aPcdItemTypeList.get(lctr));\r
+                    System.out.println("Was set to: " + itemType);\r
+                    System.out.println("Merge Aborted!");\r
+                    System.err.flush();\r
+                    System.exit(FAIL);\r
+                }\r
+                if ((DEBUG > 3) || (VERBOSE > 3))\r
+                    System.out.println("Found a duplicate String, skipping!");\r
+                return "";\r
+            }\r
+        }\r
+        if ((DEBUG > 3) || (VERBOSE > 3))\r
+            System.out.println("Returning UNIQUE String!\n " + pcdName);\r
+        aPcdItemTypeList.add(itemType);\r
+        aList.add(pcdName);\r
+        return pcdName;\r
+    }\r
+\r
+    private String checkUsage() {\r
+        String result = "";\r
+        // Usage types are different\r
+        if (((mergeUsage.contains("CONSUMED")) && (leafUsage.contains("PRODUCED")))\r
+            || ((mergeUsage.contains("PRODUCED")) && (leafUsage.contains("CONSUMED")))\r
+            || ((mergeUsage.contains("TO_START")) && (leafUsage.contains("BY_START")))\r
+            || ((mergeUsage.contains("BY_START")) && (leafUsage.contains("TO_START")))) {\r
+            result = "DIFFERENT";\r
+        }\r
+        // Both Usage types are PRODUCED\r
+        if (((mergeUsage.contains("ALWAYS_PRODUCED")) && (leafUsage.contains("SOMETIMES_PRODUCED")))\r
+            || ((mergeUsage.contains("SOMETIMES_PRODUCED")) && (leafUsage.contains("ALWAYS_PRODUCED")))) {\r
+            result = "PRODUCED";\r
+        }\r
+\r
+        // Both Usage types are CONSUMED\r
+        if (((mergeUsage.contains("ALWAYS_CONSUMED")) && (leafUsage.contains("SOMETIMES_CONSUMED")))\r
+            || ((mergeUsage.contains("SOMETIMES_CONSUMED")) && (leafUsage.contains("ALWAYS_CONSUMED")))) {\r
+            result = "CONSUMED";\r
+        }\r
+        return result;\r
+    }\r
+\r
+    private boolean checkProduced() {\r
+        boolean result = false;\r
+\r
+        if (((mergeUsage.contains("ALWAYS_PRODUCED")) && (leafUsage.contains("SOMETIMES_PRODUCED")))\r
+            || ((mergeUsage.contains("SOMETIMES_PRODUCED")) && (leafUsage.contains("ALWAYS_PRODUCED")))) {\r
+            result = true;\r
+        }\r
+        return result;\r
+    }\r
+\r
+    private boolean checkConsumed() {\r
+        boolean result = false;\r
+\r
+        if (((mergeUsage.contains("ALWAYS_CONSUMED")) && (leafUsage.contains("SOMETIMES_CONSUMED")))\r
+            || ((mergeUsage.contains("SOMETIMES_CONSUMED")) && (leafUsage.contains("ALWAYS_CONSUMED")))) {\r
+            result = true;\r
+        }\r
+        return result;\r
+    }\r
+\r
+    private String getPathPartOfLeafMsa(String sFilename) {\r
+        String pathName = "";\r
+        String s[] = sFilename.replace("\\", "/").trim().split("/");\r
+        for (int j = 0; j < (s.length - 1); j++) {\r
+            pathName += s[j] + "/";\r
+        }\r
+        return pathName;\r
+    }\r
+\r
+    private static class XmlConfig {\r
+        public static XmlCursor setupXmlCursor(XmlCursor cursor) {\r
+            String uri = "http://www.TianoCore.org/2006/Edk2.0";\r
+            cursor.push();\r
+            cursor.toNextToken();\r
+            cursor.insertNamespace("", uri);\r
+            cursor.insertNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");\r
+            cursor.pop();\r
+            return cursor;\r
+\r
+        }\r
+\r
+        public static XmlOptions setupXmlOptions() {\r
+            XmlOptions options = new XmlOptions();\r
+            options.setCharacterEncoding("UTF-8");\r
+            options.setSavePrettyPrint();\r
+            options.setSavePrettyPrintIndent(2);\r
+            return options;\r
+        }\r
+\r
+    }\r
+}\r
diff --git a/Tools/Source/Merge/src/org/tianocore/Merge/Merge.java b/Tools/Source/Merge/src/org/tianocore/Merge/Merge.java
new file mode 100644 (file)
index 0000000..6f72786
--- /dev/null
@@ -0,0 +1,24 @@
+// @file
+// Merge wrapper
+//
+//  Copyright (c) 2006, Intel Corporation    All rights reserved.
+//
+//  This program and the accompanying materials are licensed and made
+//  available under the terms and conditions of the BSD License which
+//  accompanies this distribution.  The full text of the license may 
+//  be found at  http://opensource.org/licenses/bsd-license.php
+//
+//  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+
+package org.tianocore.Merge;
+
+public class Merge {
+
+  public static void main(String[] args) {
+      if (new MergeCmd().MergeCmdLine(args) != 0)
+          System.exit(1);
+      System.exit(0);
+  }
+}
diff --git a/Tools/Source/Merge/src/org/tianocore/Merge/MergeCmd.java b/Tools/Source/Merge/src/org/tianocore/Merge/MergeCmd.java
new file mode 100644 (file)
index 0000000..1e44d2f
--- /dev/null
@@ -0,0 +1,211 @@
+// @file\r
+//  MergeCmd command-line interface to the classes that combine\r
+//      multiple MSA files into a single MSA file.\r
+//\r
+//  Copyright (c) 2006, Intel Corporation    All rights reserved.\r
+//\r
+//  This program and the accompanying materials are licensed and made\r
+//  available under the terms and conditions of the BSD License which\r
+//  accompanies this distribution.  The full text of the license may \r
+//  be found at  http://opensource.org/licenses/bsd-license.php\r
+//\r
+//  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+//  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+//    This program is the command line interface to the CombineMsa class, which\r
+//    will take the following arguments:\r
+//\r
+//  Input:\r
+//      -t Target   The MSA file that will be created\r
+//      -u UiName   The UiName for the merged MSA   OPTIONAL\r
+//                  If not provided, the UiName will come from the\r
+//                  first leaf MSA file\r
+//      -p Package  The SPD file that the new MSA file will be added to.  OPTIONAL\r
+//      leaf.msa    The path and filename of the MSA files to be merged into the Target.\r
+//\r
+//  Output:\r
+//      Target.msa\r
+//\r
+//  Modifies - OPTIONAL\r
+//      Package.spd\r
+//\r
+\r
+package org.tianocore.Merge;\r
+\r
+import java.io.*;\r
+import java.util.*;\r
+\r
+// import org.tianocore.Merge.CombineMsa;\r
+\r
+public class MergeCmd {\r
+\r
+    private static int DEBUG = 1;\r
+    \r
+    private static final String copyright  = "Copyright (c) 2006, Intel Corporation      All rights reserved.";\r
+    \r
+    private static final String version = "Version 0.1";\r
+    \r
+    private int VERBOSE = 0;\r
+\r
+    private String targetFile = null;\r
+\r
+    private ArrayList<String> leafFiles = new ArrayList<String>();\r
+\r
+    private String spdFile = null;\r
+\r
+    private String uiName = null;\r
+    \r
+    private String fileBasename = null;\r
+\r
+    private final int ESUCCESS = 0;\r
+\r
+    private final int EFAILURE = 1;\r
+\r
+    private final static int FOUND = 1;\r
+\r
+    private final static int NOTFOUND = 0;\r
+\r
+    private int result = ESUCCESS;\r
+\r
+    public int MergeCmdLine(String[] args) {\r
+        result = parseCmdLine(args);\r
+        if (result == ESUCCESS) {\r
+            if ((DEBUG > 7) || (VERBOSE > 5)) {\r
+                System.out.println("Parse Succeeded!");\r
+                System.out.println("CWD: " + System.getProperty("user.dir"));\r
+                System.out.println("Merge Module Name:   " + targetFile);\r
+                System.out.println("Found Leaf Module:   " + leafFiles.size());\r
+                if (spdFile != null)\r
+                    System.out.println("Package Name:        " + spdFile);\r
+                if (uiName != null)\r
+                    System.out.println("User Interface Name: " + uiName);\r
+            }\r
+            CombineMsa newMsa = new CombineMsa();\r
+            result = newMsa.combineMsaFiles(targetFile, leafFiles, uiName, spdFile, fileBasename, VERBOSE);\r
+        }\r
+        return result;\r
+    }\r
+\r
+    private int parseCmdLine(String[] args) {\r
+\r
+        if (args.length == NOTFOUND) {\r
+            outputUsage();\r
+            System.exit(EFAILURE);\r
+        }\r
+\r
+        for (int i = 0; i < args.length; i++) {\r
+            if (args[i].toLowerCase().contains("-t")) {\r
+                i++;\r
+                targetFile = args[i];\r
+                targetFile.replace(" ", "_");\r
+                if (!targetFile.toLowerCase().contains(".msa"))\r
+                    targetFile = targetFile + ".msa";\r
+\r
+\r
+            } else if (args[i].toLowerCase().contains("-p")) {\r
+                i++;\r
+                spdFile = args[i];\r
+                if (!spdFile.toLowerCase().contains(".spd"))\r
+                    spdFile = spdFile + ".spd";\r
+                spdFile = spdFile.replace("\\", "/").trim();\r
+                if (testFile(spdFile) == NOTFOUND) {\r
+                    System.out.println("WARNING: The Package file: " + spdFile + " does NOT exist!");\r
+                    System.out.print("Do you want to continue anyway [y|N]? ");\r
+                    String inputLine = null;\r
+                    try {\r
+                        BufferedReader inputString = new BufferedReader(new InputStreamReader(System.in));\r
+                        inputLine = inputString.readLine();\r
+                        if ((inputLine.length() == 0) || (!inputLine.toLowerCase().contains("y"))) {\r
+                            System.out.println("Merge Aborted at user request!");\r
+                            System.exit(EFAILURE);\r
+                        } else {\r
+                            spdFile = null;\r
+                            System.out\r
+                                      .println("Continuing with the Merge.  Don't forget to add the new MSA file to a Package.");\r
+                        }\r
+                    } catch (IOException e) {\r
+                        System.out.println("IOException: " + e);\r
+                    }\r
+                }\r
+            } else if (args[i].toLowerCase().contains("-u")) {\r
+                i++;\r
+                uiName = args[i];\r
+            } else if (args[i].toLowerCase().contains("-o")) {\r
+                i++;\r
+                fileBasename = args[i];\r
+            } else if (args[i].toLowerCase().contains("-v")) {\r
+                VERBOSE++;\r
+            } else if ((args[i].toLowerCase().contains("-h")) || (args[i].toLowerCase().contains("-?"))\r
+                       || (args[i].toLowerCase().contains("/h")) || (args[i].toLowerCase().contains("--help"))) {\r
+                outputUsage();\r
+                System.exit(EFAILURE);\r
+            } else {\r
+                if (args[i].startsWith("-")) {\r
+                    System.out.println("Invalid Argument: " + args[i]);\r
+                    outputUsage();\r
+                    System.out.println("Merge Aborted!");\r
+                    System.exit(EFAILURE);\r
+                }\r
+                String leafFile = args[i];\r
+                if (!leafFile.toLowerCase().contains(".msa"))\r
+                    leafFile = leafFile + ".msa";\r
+\r
+                if (testFile(leafFile) == NOTFOUND) {\r
+                    System.out.println("ERROR: The Leaf MSA File: " + leafFile + " was NOT FOUND!");\r
+                    System.out.println("Merge Aborted!");\r
+                    System.exit(EFAILURE);\r
+                } else {\r
+                    if (DEBUG > 9)\r
+                        System.out.println("Found Leaf Module:   " + leafFile);\r
+                    leafFiles.add(leafFile);\r
+                }\r
+            }\r
+        }\r
+        if (testFile(targetFile) == FOUND) {\r
+            System.out.println("WARNING: The targetfile: " + targetFile + "Already Exists!");\r
+            System.out.print("Do you want to over write it [y|N]? ");\r
+            String inputLine = null;\r
+            try {\r
+                BufferedReader inputString = new BufferedReader(new InputStreamReader(System.in));\r
+                inputLine = inputString.readLine();\r
+                if ((inputLine.length() == 0) || (!inputLine.toLowerCase().contains("y"))) {\r
+                    System.out.println("Please correct the options, then try again.");\r
+                    System.out.println("Merge Aborted at user request!");\r
+                    System.exit(EFAILURE);\r
+                }\r
+            } catch (IOException e) {\r
+                System.out.println("IOException: " + e);\r
+            }\r
+\r
+        }\r
+        return ESUCCESS;\r
+    }\r
+\r
+    private static int testFile(String Filename) {\r
+        File tFile = new File(Filename);\r
+        if (DEBUG > 8)\r
+            System.out.println("File is located: " + tFile.getPath());\r
+        if (tFile.exists())\r
+            return FOUND;\r
+        else\r
+            return NOTFOUND;\r
+    }\r
+\r
+    private static void outputUsage() {\r
+        \r
+        \r
+        System.out.println("Merge, " + version);\r
+        System.out.println(copyright);\r
+        System.out.println("Usage:");\r
+        System.out.println("  merge [-v] -t target [-u UiName] [-p PackageFile] dir1" + File.separator + "leaf1 ... dirN" + File.separator + "leafN [-h | -? | --help]");\r
+        System.out.println("    where:");\r
+        System.out.println("      -h | -? | --help            OPTIONAL - This Help Text");\r
+        System.out.println("      -t Target                   REQUIRED - The Name of the new Merge Module MSA file");\r
+        System.out.println("      -p Package                  OPTIONAL - The Name of the Package (SPD) file to add the target");\r
+        System.out.println("      -u UiName                   OPTIONAL - The User Interface Name for the Target Module");\r
+        System.out.println("      -v                          OPTIONAL - Verbose, print information messages.");\r
+        System.out.println("      -o OutputFileBasename       OPTIONAL - Set the Output Filename for this module to Basename");\r
+        System.out.println("      dir1" + File.separator + "leaf1 ... dirN" + File.separator + "leafN   REQUIRED The path to two or more MSA files that will be merged");\r
+        System.out.println("");\r
+    }\r
+}\r