/// <summary> Refress all of the settings within this gateway </summary>
        /// <param name="DbInstance"> Database instance to use when pulling the new data  </param>
        /// <returns> TRUE if successful, FALSE if any errors occurred </returns>
        public static bool RefreshAll(Database_Instance_Configuration DbInstance)
        {
            bool error = !RefreshSettings(DbInstance);

            error = error | !RefreshConfiguration(DbInstance);
            error = error | !RefreshStatsDateRange();
            error = error | !RefreshTranslations();
            error = error | !RefreshWebSkins();
            error = error | !RefreshCodes();
            error = error | !RefreshStopWords();
            error = error | !RefreshIP_Restrictions();
            error = error | !RefreshThematicHeadings();
            error = error | !RefreshUserGroups();
            error = error | !RefreshCollectionAliases();
            error = error | !RefreshMimeTypes();
            error = error | !RefreshIcons();
            error = error | !RefreshDefaultMetadataTemplates();
            error = error | !RefreshUrlPortals();
            error = error | !RefreshWebContentHierarchy();
            error = error | !RefreshTitles();

            Last_Refresh = DateTime.Now;

            return(!error);
        }
 /// <summary> Constructor for a new instance of the Single_Instance_Configuration class </summary>
 public Single_Instance_Configuration()
 {
     Is_Active          = true;
     Name               = String.Empty;
     Microservices      = new MicroservicesClient_Configuration();
     DatabaseConnection = new Database_Instance_Configuration();
 }
        /// <summary> Refreshes the values from the database settings </summary>
        /// <returns> A fully builder instance-wide setting object </returns>
        public static InstanceWide_Settings Build_Settings(Database_Instance_Configuration DbInstance)
        {
            InstanceWide_Settings returnValue = new InstanceWide_Settings();

            // Don't read the configuration file now.. we already have the db data
            Engine_Database.Connection_String = DbInstance.Connection_String;

            DataSet sobekCMSettings = Engine_Database.Get_Settings_Complete(false, null);

            if (sobekCMSettings == null)
            {
                return(null);
            }

            Refresh(returnValue, sobekCMSettings);

            return(returnValue);
        }
        /// <summary> Refresh the settings object by pulling the data back from the database </summary>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        public static bool RefreshConfiguration(Database_Instance_Configuration DbInstance)
        {
            try
            {
                lock (configurationLock)
                {
                    if (configuration == null)
                    {
                        configuration = Configuration_Files_Reader.Read_Config_Files(Settings);
                    }
                    else
                    {
                        InstanceWide_Configuration newConfig = Configuration_Files_Reader.Read_Config_Files(Settings);
                        configuration = newConfig;
                    }
                }

                return(true);
            }
            catch
            {
                return(false);
            }
        }
        /// <summary> Refresh the settings object by pulling the data back from the database </summary>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        public static bool RefreshSettings(Database_Instance_Configuration DbInstance)
        {
            try
            {
                lock (settingsLock)
                {
                    if (settings == null)
                    {
                        settings = InstanceWide_Settings_Builder.Build_Settings(DbInstance);
                    }
                    else
                    {
                        InstanceWide_Settings newSettings = InstanceWide_Settings_Builder.Build_Settings(DbInstance);
                        settings = newSettings;
                    }
                }

                return(true);
            }
            catch
            {
                return(false);
            }
        }
        /// <summary> Reads the inficated configuration file </summary>
        /// <param name="SettingsObject"> Settings instance to be populated with the metadata types </param>
        /// <param name="ConfigFile"> Configuration file to read </param>
        /// <exception>File is checked for existence first, otherwise all encountered exceptions will be thrown</exception>
        public static void Read_Configuration_File(InstanceWide_Settings SettingsObject, string ConfigFile)
        {
            if (!File.Exists(ConfigFile))
            {
                return;
            }

            SettingsObject.Database_Connection = null;

            StreamReader  reader    = new StreamReader(ConfigFile);
            XmlTextReader xmlReader = new XmlTextReader(reader);

            while (xmlReader.Read())
            {
                if (xmlReader.NodeType == XmlNodeType.Element)
                {
                    string node_name = xmlReader.Name.ToLower();
                    switch (node_name)
                    {
                    case "connection_string":
                        Database_Instance_Configuration newDb = new Database_Instance_Configuration();
                        if (xmlReader.MoveToAttribute("type"))
                        {
                            if (xmlReader.Value.ToLower() == "postgresql")
                            {
                                newDb.Database_Type = EalDbTypeEnum.PostgreSQL;
                            }
                        }
                        if (xmlReader.MoveToAttribute("isHosted"))
                        {
                            if (xmlReader.Value.ToLower() == "true")
                            {
                                SettingsObject.Servers.isHosted = true;
                            }
                        }

                        xmlReader.Read();
                        newDb.Connection_String            = xmlReader.Value;
                        SettingsObject.Database_Connection = newDb;
                        break;

                    case "erroremails":
                        xmlReader.Read();
                        SettingsObject.Email.System_Error_Email = xmlReader.Value;
                        break;

                    case "errorpage":
                        xmlReader.Read();
                        SettingsObject.Servers.System_Error_URL = xmlReader.Value;
                        break;

                    case "ghostscript_executable":
                        xmlReader.Read();
                        SettingsObject.Builder.Ghostscript_Executable = xmlReader.Value;
                        break;

                    case "imagemagick_executable":
                        xmlReader.Read();
                        SettingsObject.Builder.ImageMagick_Executable = xmlReader.Value;
                        break;

                    case "pause_between_polls":
                        xmlReader.Read();
                        int testValue;
                        if (Int32.TryParse(xmlReader.Value, out testValue))
                        {
                            SettingsObject.Builder.Override_Seconds_Between_Polls = testValue;
                        }
                        break;
                    }
                }
            }

            xmlReader.Close();
            reader.Close();
        }
        /// <summary> Continuously execute the processes in a recurring background thread </summary>
        public void Execute_In_Background()
        {
            // Load all the settings
            SobekCM_Library_Settings.Refresh(Library.Database.SobekCM_Database.Get_Settings_Complete(null));

            // Set the variable which will control background execution
            int time_between_polls = SobekCM_Library_Settings.Builder_Override_Seconds_Between_Polls;

            if ((time_between_polls < 0) || (SobekCM_Library_Settings.Database_Connections.Count == 1))
            {
                time_between_polls = Convert.ToInt32(SobekCM_Library_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 = SobekCM_Library_Settings.Local_Log_Directory + "\\" + 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 (SobekCM_Library_Settings.ImageMagick_Executable.Length == 0)
            {
                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 (SobekCM_Library_Settings.Ghostscript_Executable.Length == 0)
            {
                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 SobekCM_Library_Settings.Database_Connections)
            {
                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 SobekCM_Library_Settings.Database_Connections)
                {
                    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", SobekCM_Library_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 SobekCM_Library_Settings.Database_Connections)
            {
                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
                    if (SobekCM_Library_Settings.ImageMagick_Executable.Length == 0)
                    {
                        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 (SobekCM_Library_Settings.Ghostscript_Executable.Length == 0)
                    {
                        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.Name, dbConfig.Can_Abort);
                    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;
            }

            bool firstRun = true;


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

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

                        // Set the database connection strings
                        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 (SobekCM_Library_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(SobekCM_Library_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(SobekCM_Library_Settings.Application_Server_URL, SobekCM_Library_Settings.Static_Pages_Location, SobekCM_Library_Settings.Application_Server_Network);
                                builder.Rebuild_All_Static_Pages(preloader_logger, false, SobekCM_Library_Settings.Local_Log_Directory, dbInstance.Name, staticRebuildLogId);



                                // Process any pending FDA reports from the FDA Report DropBox
                                Process_Any_Pending_FDA_Reports(loaders[i]);
                            }

                            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;
                            }


                            if (rebuildRssFeeds)
                            {
                                loaders[i].Build_Feeds();
                            }

                            // Clear memory from this loader
                            loaders[i].Clear_Item_List();
                        }
                        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
                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 < SobekCM_Library_Settings.Database_Connections.Count; i++)
                {
                    if (loaders[i] != null)
                    {
                        // Get the instance
                        Database_Instance_Configuration dbInstance = SobekCM_Library_Settings.Database_Connections[i];

                        // Set the database flag
                        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)
                        {
                            // Refresh all settings, etc..
                            loaders[i].Refresh_Settings_And_Item_List();

                            // 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].Clear_Item_List();
                    }
                }
            }
            else
            {
                // Mark the aborted in each instance
                foreach (Database_Instance_Configuration dbConfig in SobekCM_Library_Settings.Database_Connections)
                {
                    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", SobekCM_Library_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 (SobekCM_Library_Settings.Document_Solr_Index_URL.Length > 0)
            //	{
            //		Console.WriteLine("Initiating Solr/Lucene document index optimization");
            //		Solr_Controller.Optimize_Document_Index(SobekCM_Library_Settings.Document_Solr_Index_URL);
            //	}
            //}
            //else
            //{
            //	if (SobekCM_Library_Settings.Page_Solr_Index_URL.Length > 0)
            //	{
            //		Console.WriteLine("Initiating Solr/Lucene page index optimization");
            //		Solr_Controller.Optimize_Page_Index(SobekCM_Library_Settings.Page_Solr_Index_URL);
            //	}
            //}
            //// Sleep for twenty minutes to end this (the index rebuild might take some time)
            //Thread.Sleep(1000 * 20 * 60);
        }