Class builds the static HTML page for a digital resource to allow indexing by search engines
        /// <summary> Continuously execute the processes in a recurring background thread </summary>
        public void Execute_In_Background()
        {
            // Set the variable which will control background execution
            int time_between_polls = Engine_ApplicationCache_Gateway.Settings.Builder_Override_Seconds_Between_Polls;
            if (( time_between_polls < 0 ) || ( Engine_ApplicationCache_Gateway.Settings.Database_Connections.Count == 1 ))
                time_between_polls = Convert.ToInt32(Engine_ApplicationCache_Gateway.Settings.Builder.Seconds_Between_Polls);

            // Determine the new log name
            string log_name = "incoming_" + controllerStarted.Year + "_" + controllerStarted.Month.ToString().PadLeft(2, '0') + "_" + controllerStarted.Day.ToString().PadLeft(2, '0') + ".html";
            string local_log_name = Engine_ApplicationCache_Gateway.Settings.Local_Log_Directory + "\\" + log_name;
            if (String.IsNullOrEmpty(Engine_ApplicationCache_Gateway.Settings.Local_Log_Directory))
            {
                local_log_name = logFileDirectory + "\\" + log_name;
            }

            // Create the new log file
            LogFileXhtml preloader_logger = new LogFileXhtml(local_log_name, "SobekCM Incoming Packages Log", "UFDC_Builder.exe", true);

            // start with warnings on imagemagick and ghostscript not being installed
            if ((String.IsNullOrEmpty(MultiInstance_Builder_Settings.ImageMagick_Executable)) || (!File.Exists(MultiInstance_Builder_Settings.ImageMagick_Executable)))
            {
                Console.WriteLine("WARNING: Could not find ImageMagick installed.  Some image processing will be unavailable.");
                preloader_logger.AddNonError("WARNING: Could not find ImageMagick installed.  Some image processing will be unavailable.");
            }

            if ((String.IsNullOrEmpty(MultiInstance_Builder_Settings.Ghostscript_Executable)) || (!File.Exists(MultiInstance_Builder_Settings.Ghostscript_Executable)))
            {
                Console.WriteLine("WARNING: Could not find GhostScript installed.  Some PDF processing will be unavailable.");
                preloader_logger.AddNonError("WARNING: Could not find GhostScript installed.  Some PDF processing will be unavailable.");
            }

            // Set the time for the next feed building event to 10 minutes from now
            feedNextBuildTime = DateTime.Now.Add(new TimeSpan(0, 10, 0));

            // First, step through each active configuration and see if building is currently aborted
            // while doing very minimal processes
            aborted = false;
            Console.WriteLine("Checking for initial abort condition");
            preloader_logger.AddNonError("Checking for initial abort condition");
            string abort_message = String.Empty;
            Builder_Operation_Flag_Enum abort_flag = Builder_Operation_Flag_Enum.STANDARD_OPERATION;
            foreach (Database_Instance_Configuration dbConfig in instances)
            {
                if ((!aborted) && (dbConfig.Is_Active) && (dbConfig.Can_Abort))
                {
                    SobekCM_Database.Connection_String = dbConfig.Connection_String;
                    Library.Database.SobekCM_Database.Connection_String = dbConfig.Connection_String;

                    // Check that this should not be skipped or aborted
                    Builder_Operation_Flag_Enum operationFlag = Abort_Database_Mechanism.Builder_Operation_Flag;
                    switch (operationFlag)
                    {
                        case Builder_Operation_Flag_Enum.ABORT_REQUESTED:
                        case Builder_Operation_Flag_Enum.ABORTING:
                            abort_message = "PREVIOUS ABORT flag found in " + dbConfig.Name;
                            abort_flag = Builder_Operation_Flag_Enum.LAST_EXECUTION_ABORTED;
                            Console.WriteLine(abort_message);
                            preloader_logger.AddNonError(abort_message);
                            aborted = true;
                            Abort_Database_Mechanism.Builder_Operation_Flag = Builder_Operation_Flag_Enum.LAST_EXECUTION_ABORTED;
                            break;

                        case Builder_Operation_Flag_Enum.NO_BUILDING_REQUESTED:
                            abort_message = "PREVIOUS NO BUILDING flag found in " + dbConfig.Name;
                            Console.WriteLine(abort_message);
                            preloader_logger.AddNonError(abort_message);
                            aborted = true;
                            break;

                    }
                }
            }

            // If initially aborted, step through each instance and set a message
            if (aborted)
            {
                // Add messages in each active instance
                foreach (Database_Instance_Configuration dbConfig in instances)
                {
                    if (dbConfig.Is_Active)
                    {
                        Console.WriteLine("Setting previous abort flag message in " + dbConfig.Name);
                        preloader_logger.AddNonError("Setting previous abort flag message in " + dbConfig.Name);
                        SobekCM_Database.Connection_String = dbConfig.Connection_String;
                        Library.Database.SobekCM_Database.Connection_String = dbConfig.Connection_String;
                        Library.Database.SobekCM_Database.Builder_Add_Log_Entry(-1, String.Empty, "Standard", abort_message, String.Empty);

                        // Save information about this last run
                        Library.Database.SobekCM_Database.Set_Setting("Builder Version", Engine_ApplicationCache_Gateway.Settings.Current_Builder_Version);
                        Library.Database.SobekCM_Database.Set_Setting("Builder Last Run Finished", DateTime.Now.ToString());
                        Library.Database.SobekCM_Database.Set_Setting("Builder Last Message", abort_message);

                        // Finally, set the builder flag appropriately
                        if (abort_flag != Builder_Operation_Flag_Enum.STANDARD_OPERATION)
                            Abort_Database_Mechanism.Builder_Operation_Flag = abort_flag;
                    }
                }

                // Do nothing else
                return;
            }

            // Build all the bulk loader objects
            List<Worker_BulkLoader> loaders = new List<Worker_BulkLoader>();
            bool activeInstanceFound = false;
            foreach (Database_Instance_Configuration dbConfig in instances)
            {
                if (!dbConfig.Is_Active)
                {
                    loaders.Add(null);
                    Console.WriteLine(dbConfig.Name + " is set to INACTIVE");
                    preloader_logger.AddNonError(dbConfig.Name + " is set to INACTIVE");
                }
                else
                {
                    activeInstanceFound = true;
                    SobekCM_Database.Connection_String = dbConfig.Connection_String;
                    Library.Database.SobekCM_Database.Connection_String = dbConfig.Connection_String;

                    // At this point warn on mossing the Ghostscript and ImageMagick, to get it into each instances database logs
                    if ((String.IsNullOrEmpty(MultiInstance_Builder_Settings.ImageMagick_Executable)) || (!File.Exists(MultiInstance_Builder_Settings.ImageMagick_Executable)))
                    {
                        Library.Database.SobekCM_Database.Builder_Add_Log_Entry(-1, String.Empty, "Standard", "WARNING: Could not find ImageMagick installed.  Some image processing will be unavailable.", String.Empty);
                    }

                    if ((String.IsNullOrEmpty(MultiInstance_Builder_Settings.Ghostscript_Executable)) || (!File.Exists(MultiInstance_Builder_Settings.Ghostscript_Executable)))
                    {
                        Library.Database.SobekCM_Database.Builder_Add_Log_Entry(-1, String.Empty, "Standard", "WARNING: Could not find GhostScript installed.  Some PDF processing will be unavailable.", String.Empty);
                    }

                    Console.WriteLine(dbConfig.Name + " - Preparing to begin polling");
                    preloader_logger.AddNonError(dbConfig.Name + " - Preparing to begin polling");
                    Library.Database.SobekCM_Database.Builder_Add_Log_Entry(-1, String.Empty, "Standard", "Preparing to begin polling", String.Empty);

                    Worker_BulkLoader newLoader = new Worker_BulkLoader(preloader_logger, verbose, dbConfig, (instances.Count > 1), logFileDirectory);
                    loaders.Add(newLoader);
                }
            }

            // If no active instances, just exit
            if (!activeInstanceFound)
            {
                Console.WriteLine("No active databases in the config file");
                preloader_logger.AddError("No active databases in config file... Aborting");
                return;
            }

            // Set the maximum number of packages to process before moving to the next instance
            if (loaders.Count > 1)
                MultiInstance_Builder_Settings.Instance_Package_Limit = 100;

            bool firstRun = true;

            // Loop continually until the end hour is achieved
            do
            {
                // Is it time to build any RSS/XML feeds?
                if (DateTime.Compare(DateTime.Now, feedNextBuildTime) >= 0)
                {
                    feedNextBuildTime = DateTime.Now.Add(new TimeSpan(0, 10, 0));
                }

                bool skip_sleep = false;

                // Step through each instance
                for (int i = 0; i < instances.Count; i++)
                {
                    if (loaders[i] != null)
                    {
                        // Get the instance
                        Database_Instance_Configuration dbInstance = instances[i];

                        // Set the database connection strings
                        Engine_Database.Connection_String = dbInstance.Connection_String;
                        SobekCM_Database.Connection_String = dbInstance.Connection_String;
                        Library.Database.SobekCM_Database.Connection_String = dbInstance.Connection_String;

                        // Look for abort
                        if ((dbInstance.Can_Abort) && (CheckForAbort()))
                        {
                            aborted = true;
                            if (Abort_Database_Mechanism.Builder_Operation_Flag != Builder_Operation_Flag_Enum.NO_BUILDING_REQUESTED)
                            {
                                abort_flag = Builder_Operation_Flag_Enum.LAST_EXECUTION_ABORTED;
                                Abort_Database_Mechanism.Builder_Operation_Flag = Builder_Operation_Flag_Enum.ABORTING;
                            }
                            break;
                        }

                        // Refresh all settings, etc..
                        loaders[i].Refresh_Settings_And_Item_List();

                        // Pull the abort/pause flag
                        Builder_Operation_Flag_Enum currentPauseFlag = Abort_Database_Mechanism.Builder_Operation_Flag;

                        // If not paused, run the prebuilder
                        if (currentPauseFlag != Builder_Operation_Flag_Enum.PAUSE_REQUESTED)
                        {
                            if (firstRun)
                            {

                                //    // Always build an endeca feed first (so it occurs once a day)
                                //    if (Engine_ApplicationCache_Gateway.Settings.Build_MARC_Feed_By_Default)
                                //    {
                                //        Create_Complete_MarcXML_Feed(false);
                                //    }
                                //}

                                // CLear the old logs
                                Console.WriteLine(dbInstance.Name + " - Expiring old log entries");
                                preloader_logger.AddNonError(dbInstance.Name + " - Expiring old log entries");
                                Library.Database.SobekCM_Database.Builder_Add_Log_Entry(-1, String.Empty, "Standard", "Expiring old log entries", String.Empty);
                                Library.Database.SobekCM_Database.Builder_Expire_Log_Entries(Engine_ApplicationCache_Gateway.Settings.Builder.Log_Expiration_Days);

                                // Rebuild all the static pages
                                Console.WriteLine(dbInstance.Name + " - Rebuilding all static pages");
                                preloader_logger.AddNonError(dbInstance.Name + " - Rebuilding all static pages");
                                long staticRebuildLogId = Library.Database.SobekCM_Database.Builder_Add_Log_Entry(-1, String.Empty, "Standard", "Rebuilding all static pages", String.Empty);

                                Static_Pages_Builder builder = new Static_Pages_Builder(Engine_ApplicationCache_Gateway.Settings.Servers.Application_Server_URL, Engine_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location, Engine_ApplicationCache_Gateway.URL_Portals.Default_Portal.Default_Web_Skin);
                                builder.Rebuild_All_Static_Pages(preloader_logger, false, Engine_ApplicationCache_Gateway.Settings.Local_Log_Directory, dbInstance.Name, staticRebuildLogId);

                            }

                            skip_sleep = skip_sleep || Run_BulkLoader(loaders[i], verbose);

                            // Look for abort
                            if ((!aborted) && (dbInstance.Can_Abort) && (CheckForAbort()))
                            {
                                aborted = true;
                                if (Abort_Database_Mechanism.Builder_Operation_Flag != Builder_Operation_Flag_Enum.NO_BUILDING_REQUESTED)
                                {
                                    abort_flag = Builder_Operation_Flag_Enum.LAST_EXECUTION_ABORTED;
                                    Abort_Database_Mechanism.Builder_Operation_Flag = Builder_Operation_Flag_Enum.ABORTING;
                                }
                                break;
                            }
                        }
                        else
                        {
                            preloader_logger.AddNonError( dbInstance.Name +  " - Building paused");
                            Library.Database.SobekCM_Database.Builder_Add_Log_Entry(-1, String.Empty, "Standard", "Building temporarily PAUSED", String.Empty);
                        }
                    }
                }

                if (aborted)
                    break;

                // No longer the first run
                firstRun = false;

                // Publish the log
                publish_log_file(local_log_name);

                // Sleep for correct number of milliseconds
                if ( !skip_sleep )
                    Thread.Sleep(1000 * time_between_polls);

            } while (DateTime.Now.Hour < BULK_LOADER_END_HOUR);

            // Do the final work for all of the different dbInstances
            if (!aborted)
            {
                for (int i = 0; i < instances.Count; i++)
                {
                    if (loaders[i] != null)
                    {
                        // Get the instance
                        Database_Instance_Configuration dbInstance = instances[i];

                        // Set the database flag
                        SobekCM_Database.Connection_String = dbInstance.Connection_String;
                        Library.Database.SobekCM_Database.Connection_String = dbInstance.Connection_String;

                        // Pull the abort/pause flag
                        Builder_Operation_Flag_Enum currentPauseFlag2 = Abort_Database_Mechanism.Builder_Operation_Flag;

                        // If not paused, run the prebuilder
                        if (currentPauseFlag2 != Builder_Operation_Flag_Enum.PAUSE_REQUESTED)
                        {
                            // Initiate the recreation of the links between metadata and collections
                            Library.Database.SobekCM_Database.Admin_Update_Cached_Aggregation_Metadata_Links();
                        }

                        // Clear the memory
                        loaders[i].ReleaseResources();
                    }
                }
            }
            else
            {
                // Mark the aborted in each instance
                foreach (Database_Instance_Configuration dbConfig in instances )
                {
                    if (dbConfig.Is_Active)
                    {
                        Console.WriteLine("Setting abort flag message in " + dbConfig.Name);
                        preloader_logger.AddNonError("Setting abort flag message in " + dbConfig.Name);
                        SobekCM_Database.Connection_String = dbConfig.Connection_String;
                        Library.Database.SobekCM_Database.Connection_String = dbConfig.Connection_String;
                        Library.Database.SobekCM_Database.Builder_Add_Log_Entry(-1, String.Empty, "Standard", "Building ABORTED per request from database key", String.Empty);

                        // Save information about this last run
                        Library.Database.SobekCM_Database.Set_Setting("Builder Version", Engine_ApplicationCache_Gateway.Settings.Current_Builder_Version);
                        Library.Database.SobekCM_Database.Set_Setting("Builder Last Run Finished", DateTime.Now.ToString());
                        Library.Database.SobekCM_Database.Set_Setting("Builder Last Message", "Building ABORTED per request");

                        // Finally, set the builder flag appropriately
                        if ( abort_flag == Builder_Operation_Flag_Enum.LAST_EXECUTION_ABORTED )
                            Abort_Database_Mechanism.Builder_Operation_Flag = Builder_Operation_Flag_Enum.LAST_EXECUTION_ABORTED;
                    }
                }
            }

            // Publish the log
            publish_log_file(local_log_name);

            //// Initiate a solr/lucene index optimization since we are done loading for a while
            //if (DateTime.Now.Day % 2 == 0)
            //{
            //	if (Engine_ApplicationCache_Gateway.Settings.Document_Solr_Index_URL.Length > 0)
            //	{
            //		Console.WriteLine("Initiating Solr/Lucene document index optimization");
            //		Solr_Controller.Optimize_Document_Index(Engine_ApplicationCache_Gateway.Settings.Document_Solr_Index_URL);
            //	}
            //}
            //else
            //{
            //	if (Engine_ApplicationCache_Gateway.Settings.Page_Solr_Index_URL.Length > 0)
            //	{
            //		Console.WriteLine("Initiating Solr/Lucene page index optimization");
            //		Solr_Controller.Optimize_Page_Index(Engine_ApplicationCache_Gateway.Settings.Page_Solr_Index_URL);
            //	}
            //}
            //// Sleep for twenty minutes to end this (the index rebuild might take some time)
            //Thread.Sleep(1000 * 20 * 60);
        }
        /// <summary> Immediately perform all requested tasks </summary>
        /// <param name="BuildProductionMarcxmlFeed"> Flag indicates if the MarcXML feed for OPACs should be produced </param>
        /// <param name="BuildTestMarcxmlFeed"> Flag indicates if the items set to be put in a TEST feed should have their MarcXML feed produced</param>
        /// <param name="RunBulkloader"> Flag indicates if the preload </param>
        /// <param name="CompleteStaticRebuild"> Flag indicates whether to rebuild all the item static pages </param>
        /// <param name="MarcRebuild"> Flag indicates if all the MarcXML files for each resource should be rewritten from the METS/MODS metadata files </param>
        public void Execute_Immediately(bool BuildProductionMarcxmlFeed, bool BuildTestMarcxmlFeed, bool RunBulkloader, bool CompleteStaticRebuild, bool MarcRebuild )
        {
            // start with warnings on imagemagick and ghostscript not being installed
            if (Engine_ApplicationCache_Gateway.Settings.ImageMagick_Executable.Length == 0)
            {
                Console.WriteLine("WARNING: Could not find ImageMagick installed.  Some image processing will be unavailable.");
            }
            if (Engine_ApplicationCache_Gateway.Settings.Ghostscript_Executable.Length == 0)
            {
                Console.WriteLine("WARNING: Could not find GhostScript installed.  Some PDF processing will be unavailable.");
            }

            if (CompleteStaticRebuild)
            {
                Console.WriteLine("Beginning static rebuild");
                LogFileXhtml staticRebuildLog = new LogFileXhtml( logFileDirectory  + "\\static_rebuild.html");
                Static_Pages_Builder builder = new Static_Pages_Builder(Engine_ApplicationCache_Gateway.Settings.Servers.Application_Server_URL, Engine_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location, Engine_ApplicationCache_Gateway.Settings.Servers.Application_Server_Network);
                builder.Rebuild_All_Static_Pages(staticRebuildLog, true, Engine_ApplicationCache_Gateway.Settings.Local_Log_Directory, String.Empty, -1);
            }

            if ( MarcRebuild )
            {
                Static_Pages_Builder builder = new Static_Pages_Builder(Engine_ApplicationCache_Gateway.Settings.Servers.Application_Server_URL, Engine_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location, Engine_ApplicationCache_Gateway.Settings.Servers.Application_Server_Network);
                builder.Rebuild_All_MARC_Files(Engine_ApplicationCache_Gateway.Settings.Servers.Image_Server_Network);
            }

            if (BuildProductionMarcxmlFeed)
            {
                Create_Complete_MarcXML_Feed(false);
            }

            if (BuildTestMarcxmlFeed)
            {
                Create_Complete_MarcXML_Feed(true);
            }

            // Create the log
            string directory = Engine_ApplicationCache_Gateway.Settings.Local_Log_Directory;
            if (!Directory.Exists(directory))
                Directory.CreateDirectory(directory);

            // Run the PRELOADER
            if (RunBulkloader)
            {
                Run_BulkLoader( verbose );
            }
            else
            {
                Console.WriteLine("PreLoader skipped per command line arguments");
            }
        }
        private void Recreate_Library_XML_and_RSS(long Builderid, Static_Pages_Builder StaticBuilder, InstanceWide_Settings Settings )
        {
            // Update the RSS Feeds and Item Lists for ALL
            // Build the simple XML result for this build
            OnProcess("........Building XML list for all digital resources", "Aggregation Updates", String.Empty, String.Empty, Builderid);
            try
            {
                DataSet simple_list = Engine_Database.Simple_Item_List(String.Empty, null);
                if (simple_list != null)
                {
                    try
                    {
                        string aggregation_list_file = Settings.Servers.Static_Pages_Location + "\\all.xml";
                        if (File.Exists(aggregation_list_file))
                            File.Delete(aggregation_list_file);
                        simple_list.WriteXml(aggregation_list_file, XmlWriteMode.WriteSchema);
                    }
                    catch (Exception ee)
                    {
                        OnError("........Error in building XML list for all digital resources on " + Settings.Servers.Static_Pages_Location + "\n" + ee.Message, String.Empty, String.Empty, Builderid);
                    }
                }
            }
            catch (Exception ee)
            {
                OnError("........Error in building XML list for all digital resources\n" + ee.Message, String.Empty, String.Empty, Builderid);
            }

            // Create the RSS feed for all ufdc items
            try
            {
                OnProcess("........Building RSS feed for all digital resources", "Aggregation Updates", String.Empty, String.Empty, Builderid);
                DataSet complete_list = Engine_Database.Simple_Item_List(String.Empty, null);

                StaticBuilder.Create_RSS_Feed("all", Settings.Local_Log_Directory, "All Items", complete_list);
                try
                {
                    File.Copy(Settings.Local_Log_Directory + "all_rss.xml", Settings.Servers.Static_Pages_Location + "\\rss\\all_rss.xml", true);
                    File.Copy(Settings.Local_Log_Directory + "all_short_rss.xml", Settings.Servers.Static_Pages_Location + "\\rss\\all_short_rss.xml", true);
                }
                catch (Exception ee)
                {
                    OnError("........Error in copying RSS feed for all digital resources to " + Settings.Servers.Static_Pages_Location + "\n" + ee.Message, String.Empty, String.Empty, Builderid);
                }
            }
            catch (Exception ee)
            {
                OnError("........Error in building RSS feed for all digital resources\n" + ee.Message, String.Empty, String.Empty, Builderid);
            }
        }
        /// <summary> Builds the static aggregation-level (and instance-level) browse and RSS feed files </summary>
        /// <param name="AggregationsAffected"> List of aggregations affected during the last process of incoming digital resources </param>
        /// <param name="ProcessedItems"> List of all items just processed (or reprocessed) </param>
        /// <param name="DeletedItems"> List of all delete requests just processed </param>
        /// <param name="Settings"> Instance-wide settings which may be required for this process </param>
        public override void DoWork(List<string> AggregationsAffected, List<BibVidStruct> ProcessedItems, List<BibVidStruct> DeletedItems, InstanceWide_Settings Settings)
        {
            if (AggregationsAffected.Count == 0)
                return;

            long updatedId = OnProcess("....Performing some aggregation update functions", "Aggregation Updates", String.Empty, String.Empty, -1);

            // Create the new statics page builder
            // IN THIS CASE, WE DO NEED TO SET THE SINGLETON, SINCE THIS CALLS THE LIBRARIES
            Engine_ApplicationCache_Gateway.Settings = Settings;
            Static_Pages_Builder staticBuilder = new Static_Pages_Builder(Settings.Servers.Application_Server_URL, Settings.Servers.Static_Pages_Location, Settings.Servers.Application_Server_Network);

            // Step through each aggregation with new items
            foreach (string thisAggrCode in AggregationsAffected)
            {
                // Some aggregations can be excluded
                if ((thisAggrCode != "IUF") && (thisAggrCode != "ALL") && (thisAggrCode.Length > 1))
                {
                    // Get the display aggregation code (lower leading 'i')
                    string display_code = thisAggrCode;
                    if (display_code[0] == 'I')
                        display_code = 'i' + display_code.Substring(1);

                    // Get this item aggregations
                    Complete_Item_Aggregation aggregationCompleteObj = Engine_Database.Get_Item_Aggregation(thisAggrCode, false, null);
                    Item_Aggregation aggregationObj = Item_Aggregation_Utilities.Get_Item_Aggregation( aggregationCompleteObj, Engine_ApplicationCache_Gateway.Settings.System.Default_UI_Language, null);

                    // Get the list of items for this aggregation
                    DataSet aggregation_items = Engine_Database.Simple_Item_List(thisAggrCode, null);

                    // Create the XML list for this aggregation
                    OnProcess("........Building XML item list for " + display_code, "Aggregation Updates", String.Empty, String.Empty, updatedId);
                    try
                    {
                        string aggregation_list_file = Settings.Servers.Static_Pages_Location + "\\" + thisAggrCode.ToLower() + ".xml";
                        if (File.Exists(aggregation_list_file))
                            File.Delete(aggregation_list_file);
                        aggregation_items.WriteXml(aggregation_list_file, XmlWriteMode.WriteSchema);
                    }
                    catch (Exception ee)
                    {
                        OnError("........Error in building XML list for " + display_code + " on " + Settings.Servers.Static_Pages_Location + "\n" + ee.Message, String.Empty, String.Empty, updatedId);
                    }

                    OnProcess("........Building RSS feed for " + display_code, "Aggregation Updates", String.Empty, String.Empty, updatedId);
                    try
                    {
                        staticBuilder.Create_RSS_Feed(thisAggrCode.ToLower(), Settings.Local_Log_Directory, aggregationObj.Name, aggregation_items);
                        try
                        {
                            File.Copy(Settings.Local_Log_Directory + thisAggrCode.ToLower() + "_rss.xml", Settings.Servers.Static_Pages_Location + "\\rss\\" + thisAggrCode.ToLower() + "_rss.xml", true);
                            File.Copy(Settings.Local_Log_Directory + thisAggrCode.ToLower() + "_short_rss.xml", Settings.Servers.Static_Pages_Location + "\\rss\\" + thisAggrCode.ToLower() + "_short_rss.xml", true);
                        }
                        catch (Exception ee)
                        {
                            OnError("........Error in copying RSS feed for " + display_code + " to " + Settings.Servers.Static_Pages_Location + "\n" + ee.Message, String.Empty, String.Empty, updatedId);
                        }
                    }
                    catch (Exception ee)
                    {
                        OnError("........Error in building RSS feed for " + display_code + "\n" + ee.Message, String.Empty, String.Empty, updatedId);
                    }

                    OnProcess("........Building static HTML browse page of links for " + display_code, "Aggregation Updates", String.Empty, String.Empty, updatedId);
                    try
                    {
                        staticBuilder.Build_All_Browse(aggregationObj, aggregation_items);
                        try
                        {
                            File.Copy(Settings.Local_Log_Directory + thisAggrCode.ToLower() + "_rss.xml", Settings.Servers.Static_Pages_Location + "\\rss\\" + thisAggrCode.ToLower() + "_rss.xml", true);
                            File.Copy(Settings.Local_Log_Directory + thisAggrCode.ToLower() + "_short_rss.xml", Settings.Servers.Static_Pages_Location + "\\rss\\" + thisAggrCode.ToLower() + "_short_rss.xml", true);
                        }
                        catch (Exception ee)
                        {
                            OnError("........Error in copying RSS feed for " + display_code + " to " + Settings.Servers.Static_Pages_Location + "\n" + ee.Message, String.Empty, String.Empty, updatedId);
                        }
                    }
                    catch (Exception ee)
                    {
                        OnError("........Error in building RSS feed for " + display_code + "\n" + ee.Message, String.Empty, String.Empty, updatedId);
                    }

                }
            }

            // Build the full instance-wide XML and RSS here as well
            Recreate_Library_XML_and_RSS(updatedId, staticBuilder, Settings);
        }
        ///  <summary> Constructor for a new instance of the Worker_BulkLoader class </summary>
        ///  <param name="Logger"> Log file object for logging progress </param>
        ///  <param name="Verbose"> Flag indicates if the builder is in verbose mode, where it should log alot more information </param>
        ///  <param name="InstanceName"> Name of this instance, likely from the Builder config </param>
        /// <param name="Can_Abort"></param>
        public Worker_BulkLoader(LogFileXHTML Logger, bool Verbose, string InstanceName, bool Can_Abort )
        {
            // Save the log file and verbose flag
            logger = Logger;
            verbose = Verbose;
            instanceName = InstanceName;
            canAbort = Can_Abort;
            multiInstanceBuilder = SobekCM_Library_Settings.Database_Connections.Count > 1;

            Add_NonError_To_Log("Worker_BulkLoader.Constructor: Start", verbose, String.Empty, String.Empty, -1);

            // Create the METS validation objects
            thisMetsValidator = new SobekCM_METS_Validator( String.Empty );
            metsSchemeValidator = new METS_Validator_Object(false);

            Add_NonError_To_Log("Worker_BulkLoader.Constructor: Created Validators", verbose, String.Empty, String.Empty, -1);

            // Create new list of collections to build
            aggregations_to_refresh = new List<string>();
            items_by_aggregation = new Dictionary<string, List<string>>();

            // get all the info
            Refresh_Settings_And_Item_List();

            // Ensure there is SOME instance name
            if (instanceName.Length == 0)
                instanceName = SobekCM_Library_Settings.System_Name;

            // Create the new statics page builder
            staticBuilder = new Static_Pages_Builder(SobekCM_Library_Settings.Application_Server_URL, SobekCM_Library_Settings.Static_Pages_Location, SobekCM_Library_Settings.Application_Server_Network);

            Add_NonError_To_Log("Worker_BulkLoader.Constructor: Created Static Pages Builder", verbose, String.Empty, String.Empty, -1);

            // Get the list of collection codes
            codeManager = new Aggregation_Code_Manager();
            SobekCM_Database.Populate_Code_Manager(codeManager, null);

            Add_NonError_To_Log("Worker_BulkLoader.Constructor: Populated code manager with " + codeManager.All_Aggregations.Count + " aggregations.", verbose, String.Empty, String.Empty, -1);

            // Set some defaults
            aborted = false;

            // Get the executable path/file for ghostscript and imagemagick
            ghostscript_executable = SobekCM_Library_Settings.Ghostscript_Executable;
            imagemagick_executable = SobekCM_Library_Settings.ImageMagick_Executable;

            Add_NonError_To_Log("Worker_BulkLoader.Constructor: Done", verbose, String.Empty, String.Empty, -1);
        }