/// <summary> Refresh the URL portals list by pulling the data back from the database </summary>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        public static bool RefreshUrlPortals()
        {
            try
            {
                lock (portalsLock)
                {
                    if (portals == null)
                    {
                        portals = new Portal_List();
                    }

                    Engine_Database.Populate_URL_Portals(portals, null);
                }

                return(true);
            }
            catch
            {
                return(false);
            }
        }
        /// <summary> Constructor for a new instance of the Admin_HtmlSubwriter class </summary>
        /// <param name="Results_Statistics"> Information about the entire set of results for a browse of a user's bookshelf folder </param>
        /// <param name="Paged_Results"> Single page of results for a browse of a user's bookshelf folder, within the entire set </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Current_Item">Current item to edit, if the user is requesting to edit an item</param>
        /// <param name="Aggregation_Aliases"> List of all existing aliases for existing aggregations </param>
        /// <param name="Web_Skin_Collection"> Collection of all the web skins </param>
        /// <param name="Current_User"> Currently logged on user </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="IP_Restrictions"> List of all IP Restriction ranges in use by this digital library </param>
        /// <param name="URL_Portals"> List of all web portals into this system </param>
        /// <param name="Stats_Date_Range"> Object contains the start and end dates for the statistical data in the database </param>
        /// <param name="Thematic_Headings"> Headings under which all the highlighted collections on the home page are organized </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public Admin_HtmlSubwriter(Search_Results_Statistics Results_Statistics,
                                   List <iSearch_Title_Result> Paged_Results,
                                   Aggregation_Code_Manager Code_Manager,
                                   Item_Lookup_Object All_Items_Lookup,
                                   Item_Aggregation Hierarchy_Object,
                                   SobekCM_Skin_Object HTML_Skin,
                                   Language_Support_Info Translator,
                                   SobekCM_Navigation_Object Current_Mode,
                                   SobekCM_Item Current_Item,
                                   Dictionary <string, string> Aggregation_Aliases,
                                   SobekCM_Skin_Collection Web_Skin_Collection,
                                   User_Object Current_User,
                                   IP_Restriction_Ranges IP_Restrictions,
                                   Dictionary <string, Wordmark_Icon> Icon_Table,
                                   Portal_List URL_Portals,
                                   Statistics_Dates Stats_Date_Range,
                                   List <Thematic_Heading> Thematic_Headings,
                                   Custom_Tracer Tracer)
        {
            Tracer.Add_Trace("Admin_HtmlSubwriter.Constructor", "Saving values and geting user object back from the session");

            resultsStatistics = Results_Statistics;
            pagedResults      = Paged_Results;
            codeManager       = Code_Manager;
            itemList          = All_Items_Lookup;
            htmlSkin          = HTML_Skin;
            translator        = Translator;
            currentCollection = Hierarchy_Object;
            currentItem       = Current_Item;
            user           = Current_User;
            ipRestrictions = IP_Restrictions;
            iconTable      = Icon_Table;
            statsDates     = Stats_Date_Range;


            if (Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Log_Out)
            {
                Tracer.Add_Trace("Admin_HtmlSubwriter.Constructor", "Performing logout");

                HttpContext.Current.Session["user"] = null;
                HttpContext.Current.Response.Redirect("?");
            }

            if ((Current_Mode.My_Sobek_Type != My_Sobek_Type_Enum.Logon) && (user != null) && (user.Is_Temporary_Password))
            {
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.New_Password;
            }

            if (Current_Mode.Logon_Required)
            {
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Logon;
            }

            // If the user is not an admin, and admin was selected, reroute this
            if ((!Current_User.Is_System_Admin) && (!Current_User.Is_Portal_Admin))
            {
                Current_Mode.Mode             = Display_Mode_Enum.My_Sobek;
                Current_Mode.My_Sobek_Type    = My_Sobek_Type_Enum.Home;
                Current_Mode.My_Sobek_SubMode = String.Empty;
                HttpContext.Current.Response.Redirect(Current_Mode.Redirect_URL());
            }

            Tracer.Add_Trace("Admin_HtmlSubwriter.Constructor", "Building the my sobek viewer object");
            switch (Current_Mode.Admin_Type)
            {
            case Admin_Type_Enum.Aggregation_Single:
                adminViewer = new Aggregation_Single_AdminViewer(user, Current_Mode, codeManager, Thematic_Headings, Web_Skin_Collection, Tracer);
                break;

            case Admin_Type_Enum.Home:
                adminViewer = new Home_AdminViewer(user, Current_Mode, Tracer);
                break;

            case Admin_Type_Enum.Builder_Status:
                adminViewer = new Builder_AdminViewer(user, Current_Mode);
                break;

            case Admin_Type_Enum.Interfaces:
                adminViewer = new Skins_AdminViewer(user, Current_Mode, Web_Skin_Collection, Tracer);
                break;

            case Admin_Type_Enum.Forwarding:
                adminViewer = new Aliases_AdminViewer(user, Current_Mode, Aggregation_Aliases, Tracer);
                break;

            case Admin_Type_Enum.Wordmarks:
                adminViewer = new Wordmarks_AdminViewer(user, Current_Mode, Tracer);
                break;

            case Admin_Type_Enum.URL_Portals:
                adminViewer = new Portals_AdminViewer(user, Current_Mode, URL_Portals, Tracer);
                break;

            case Admin_Type_Enum.Users:
                adminViewer = new Users_AdminViewer(user, Current_Mode, codeManager, Tracer);
                break;

            case Admin_Type_Enum.User_Groups:
                adminViewer = new User_Group_AdminViewer(user, Current_Mode, codeManager, Tracer);
                break;

            case Admin_Type_Enum.Aggregations_Mgmt:
                adminViewer = new Aggregations_Mgmt_AdminViewer(user, Current_Mode, codeManager, Tracer);
                break;

            case Admin_Type_Enum.IP_Restrictions:
                adminViewer = new IP_Restrictions_AdminViewer(user, Current_Mode, ipRestrictions, Tracer);
                break;

            case Admin_Type_Enum.Thematic_Headings:
                adminViewer = new Thematic_Headings_AdminViewer(user, Current_Mode, Thematic_Headings, Tracer);
                break;

            case Admin_Type_Enum.Settings:
                adminViewer = new Settings_AdminViewer(user, Current_Mode, Tracer);
                break;

            case Admin_Type_Enum.Projects:
                if (Current_Mode.My_Sobek_SubMode.Length > 1)
                {
                    string project_code = Current_Mode.My_Sobek_SubMode.Substring(1);
                    Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Checking cache for valid project file");
                    if (user != null)
                    {
                        SobekCM_Item projectObject = Cached_Data_Manager.Retrieve_Project(user.UserID, project_code, Tracer);
                        if (projectObject != null)
                        {
                            Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Valid project file found in cache");
                            adminViewer = new Edit_Item_Metadata_MySobekViewer(user, Current_Mode, itemList, projectObject, codeManager, iconTable, htmlSkin, Tracer);
                        }
                        else
                        {
                            if (SobekCM_Database.Get_All_Projects_Templates(Tracer).Tables[0].Select("ProjectCode='" + project_code + "'").Length > 0)
                            {
                                Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Building project file from (possible) PMETS");
                                string       pmets_file = SobekCM_Library_Settings.Base_MySobek_Directory + "projects\\" + Current_Mode.My_Sobek_SubMode.Substring(1) + ".pmets";
                                SobekCM_Item pmets_item = File.Exists(pmets_file) ? SobekCM_Item.Read_METS(pmets_file) : new SobekCM_Item();
                                pmets_item.Bib_Info.Main_Title.Title = "Project level metadata for '" + project_code + "'";
                                pmets_item.Bib_Info.SobekCM_Type     = TypeOfResource_SobekCM_Enum.Project;
                                pmets_item.BibID            = project_code.ToUpper();
                                pmets_item.VID              = "00001";
                                pmets_item.Source_Directory = SobekCM_Library_Settings.Base_MySobek_Directory + "projects\\";

                                Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Adding project file to cache");

                                Cached_Data_Manager.Store_Project(user.UserID, project_code, pmets_item, Tracer);

                                adminViewer = new Edit_Item_Metadata_MySobekViewer(user, Current_Mode, itemList, pmets_item, codeManager, iconTable, htmlSkin, Tracer);
                            }
                        }
                    }
                }

                if (adminViewer == null)
                {
                    adminViewer = new Projects_AdminViewer(user, Current_Mode, Tracer);
                }
                break;
            }

            // Pass in the navigation and translator information
            adminViewer.CurrentMode = Current_Mode;
            adminViewer.Translator  = translator;
        }
        /// <summary> Constructor for a new instance of the MySobek_HtmlSubwriter class </summary>
        /// <param name="Results_Statistics"> Information about the entire set of results for a browse of a user's bookshelf folder </param>
        /// <param name="Paged_Results"> Single page of results for a browse of a user's bookshelf folder, within the entire set </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Translator"> Language support object which handles simple translational duties </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Current_Item">Current item to edit, if the user is requesting to edit an item</param>
        /// <param name="Aggregation_Aliases"> List of all existing aliases for existing aggregations </param>
        /// <param name="Web_Skin_Collection"> Collection of all the web skins </param>
        /// <param name="Current_User"> Currently logged on user </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="IP_Restrictions"> List of all IP Restriction ranges in use by this digital library </param>
        /// <param name="URL_Portals"> List of all web portals into this system </param>
        /// <param name="Stats_Date_Range"> Object contains the start and end dates for the statistical data in the database </param>
        /// <param name="Thematic_Headings"> Headings under which all the highlighted collections on the home page are organized </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        public MySobek_HtmlSubwriter(Search_Results_Statistics Results_Statistics,
                                     List <iSearch_Title_Result> Paged_Results,
                                     Aggregation_Code_Manager Code_Manager,
                                     Item_Lookup_Object All_Items_Lookup,
                                     Item_Aggregation Hierarchy_Object,
                                     SobekCM_Skin_Object HTML_Skin,
                                     Language_Support_Info Translator,
                                     SobekCM_Navigation_Object Current_Mode,
                                     SobekCM_Item Current_Item,
                                     Dictionary <string, string> Aggregation_Aliases,
                                     SobekCM_Skin_Collection Web_Skin_Collection,
                                     User_Object Current_User,
                                     IP_Restriction_Ranges IP_Restrictions,
                                     Dictionary <string, Wordmark_Icon> Icon_Table,
                                     Portal_List URL_Portals,
                                     Statistics_Dates Stats_Date_Range,
                                     List <Thematic_Heading> Thematic_Headings,
                                     Custom_Tracer Tracer)
        {
            Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Saving values and geting user object back from the session");

            resultsStatistics = Results_Statistics;
            pagedResults      = Paged_Results;
            codeManager       = Code_Manager;
            itemList          = All_Items_Lookup;
            htmlSkin          = HTML_Skin;
            translator        = Translator;
            currentCollection = Hierarchy_Object;
            currentItem       = Current_Item;
            user           = Current_User;
            ipRestrictions = IP_Restrictions;
            iconTable      = Icon_Table;
            statsDates     = Stats_Date_Range;


            if (Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Log_Out)
            {
                Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Performing logout");

                HttpContext.Current.Session["user"] = null;
                HttpContext.Current.Response.Redirect("?");
            }

            if ((Current_Mode.My_Sobek_Type != My_Sobek_Type_Enum.Logon) && (user != null) && (user.Is_Temporary_Password))
            {
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.New_Password;
            }

            if (Current_Mode.Logon_Required)
            {
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Logon;
            }

            Tracer.Add_Trace("MySobek_HtmlSubwriter.Constructor", "Building the my sobek viewer object");
            switch (Current_Mode.My_Sobek_Type)
            {
            case My_Sobek_Type_Enum.Home:
                mySobekViewer = new Home_MySobekViewer(user, Tracer);
                break;

            case My_Sobek_Type_Enum.New_Item:
                mySobekViewer = new New_Group_And_Item_MySobekViewer(user, Current_Mode, itemList, codeManager, iconTable, htmlSkin, translator, Tracer);
                break;

            case My_Sobek_Type_Enum.Folder_Management:
                mySobekViewer = new Folder_Mgmt_MySobekViewer(user, resultsStatistics, pagedResults, codeManager, itemList, currentCollection, htmlSkin, translator, Current_Mode, Tracer);
                break;

            case My_Sobek_Type_Enum.Saved_Searches:
                mySobekViewer = new Saved_Searches_MySobekViewer(user, translator, Current_Mode, Tracer);
                break;

            case My_Sobek_Type_Enum.Preferences:
                mySobekViewer = new Preferences_MySobekViewer(user, Tracer);
                break;

            case My_Sobek_Type_Enum.Logon:
                mySobekViewer = new Logon_MySobekViewer(Current_Mode, Tracer);
                break;

            case My_Sobek_Type_Enum.New_Password:
                mySobekViewer = new NewPassword_MySobekViewer(user, Tracer);
                break;

            case My_Sobek_Type_Enum.Delete_Item:
                mySobekViewer = new Delete_Item_MySobekViewer(user, Current_Mode, All_Items_Lookup, Tracer);
                break;

            case My_Sobek_Type_Enum.Edit_Item_Behaviors:
                mySobekViewer = new Edit_Item_Behaviors_MySobekViewer(user, Current_Mode, currentItem, codeManager, Tracer);
                break;

            case My_Sobek_Type_Enum.Edit_Item_Metadata:
                mySobekViewer = new Edit_Item_Metadata_MySobekViewer(user, Current_Mode, itemList, currentItem, codeManager, iconTable, htmlSkin, Tracer);
                break;

            case My_Sobek_Type_Enum.File_Management:
                mySobekViewer = new File_Management_MySobekViewer(user, Current_Mode, Current_Item, itemList, codeManager, iconTable, htmlSkin, translator, Tracer);
                break;

            case My_Sobek_Type_Enum.Edit_Group_Behaviors:
                mySobekViewer = new Edit_Group_Behaviors_MySobekViewer(user, Current_Mode, currentItem, codeManager, Tracer);
                break;

            case My_Sobek_Type_Enum.Edit_Group_Serial_Hierarchy:
                mySobekViewer = new Edit_Serial_Hierarchy_MySobekViewer(user);
                break;

            case My_Sobek_Type_Enum.Group_Add_Volume:
                // Pull the list of items tied to this group
                SobekCM_Items_In_Title itemsInTitle = Cached_Data_Manager.Retrieve_Items_In_Title(currentItem.BibID, Tracer);
                if (itemsInTitle == null)
                {
                    // Get list of information about this item group and save the item list
                    DataSet itemDetails = SobekCM_Database.Get_Item_Group_Details(currentItem.BibID, Tracer);
                    itemsInTitle = new SobekCM_Items_In_Title(itemDetails.Tables[1]);

                    // Store in cache if retrieved
                    Cached_Data_Manager.Store_Items_In_Title(currentItem.BibID, itemsInTitle, Tracer);
                }
                mySobekViewer = new Group_Add_Volume_MySobekViewer(user, Current_Mode, itemList, currentItem, codeManager, iconTable, htmlSkin, itemsInTitle, translator, Tracer);
                break;

            case My_Sobek_Type_Enum.Group_AutoFill_Volumes:
                mySobekViewer = new Group_AutoFill_Volume_MySobekViewer(user);
                break;

            case My_Sobek_Type_Enum.Group_Mass_Update_Items:
                mySobekViewer = new Mass_Update_Items_MySobekViewer(user, Current_Mode, currentItem, codeManager, Tracer);
                break;

            case My_Sobek_Type_Enum.User_Tags:
                mySobekViewer = new User_Tags_MySobekViewer(user, Tracer);
                break;

            case My_Sobek_Type_Enum.User_Usage_Stats:
                mySobekViewer = new User_Usage_Stats_MySobekViewer(user, Current_Mode, statsDates, Tracer);
                break;
            }

            // Pass in the navigation and translator information
            mySobekViewer.CurrentMode = Current_Mode;
            mySobekViewer.Translator  = translator;
        }
        /// <summary> Constructor for a new instance of the Portals_AdminViewer class </summary>
        /// <param name="User"> Authenticated user information </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="URL_Portals"> List of all web portals into this system </param>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        public Portals_AdminViewer(User_Object User, SobekCM_Navigation_Object Current_Mode, Portal_List URL_Portals, Custom_Tracer Tracer)
            : base(User)
        {
            Tracer.Add_Trace("Portals_AdminViewer.Constructor", String.Empty);

            portals = URL_Portals;

            // Save the mode
            currentMode = Current_Mode;

            // Set action message to nothing to start
            actionMessage = String.Empty;

            // If the user cannot edit this, go back
            if (!user.Is_System_Admin)
            {
                Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                HttpContext.Current.Response.Redirect(Current_Mode.Redirect_URL());
            }

            // Handle any post backs
            if (Current_Mode.isPostBack)
            {
                try
                {
                    // Pull the standard values from the form
                    NameValueCollection form = HttpContext.Current.Request.Form;
                    string save_value        = form["admin_portal_tosave"];
                    string action_value      = form["admin_portal_action"];

                    // Switch, depending on the request
                    if (action_value != null)
                    {
                        switch (action_value.Trim().ToLower())
                        {
                        case "edit":
                            // Get the values from the form for this new portal
                            string edit_name = form["form_portal_name"].Trim();
                            string edit_abbr = form["form_portal_abbr"].Trim();
                            string edit_skin = form["form_portal_skin"].Trim();
                            string edit_aggr = form["form_portal_aggregation"].Trim();
                            string edit_url  = form["form_portal_url"].Trim();
                            string edit_purl = form["form_portal_purl"].Trim();
                            int    portalid  = Convert.ToInt32(save_value);

                            // Look for this to see if this was the pre-existing default
                            bool isDefault = false;
                            if (portals.Default_Portal.ID == portalid)
                            {
                                isDefault = true;
                            }


                            // Don't edit if the URL segment is empty and this is NOT default
                            if ((!isDefault) && (edit_url.Trim().Length == 0))
                            {
                                actionMessage = "ERROR: Non default portals MUST have a url segment associated.";
                            }
                            else
                            {
                                // Now, save this portal information
                                int edit_id = SobekCM_Database.Edit_URL_Portal(portalid, edit_url, true, isDefault, edit_abbr, edit_name, edit_aggr, edit_skin, edit_purl, Tracer);
                                if (edit_id > 0)
                                {
                                    actionMessage = "Edited existing URL portal '" + edit_name + "'";
                                }
                                else
                                {
                                    actionMessage = "Error editing URL portal.";
                                }
                            }
                            break;

                        case "delete":
                            actionMessage = SobekCM_Database.Delete_URL_Portal(Convert.ToInt32(save_value), Tracer) ? "URL portal deleted" : "Error deleting the URL portal";
                            break;

                        case "new":
                            // Get the values from the form for this new portal
                            string new_name = form["admin_portal_name"];
                            string new_abbr = form["admin_portal_abbr"];
                            string new_skin = form["admin_portal_skin"];
                            string new_aggr = form["admin_portal_aggregation"];
                            string new_url  = form["admin_portal_url"];
                            string new_purl = form["admin_portal_purl"];

                            // Save this to the database
                            int new_id = SobekCM_Database.Edit_URL_Portal(-1, new_url, true, false, new_abbr, new_name, new_aggr, new_skin, new_purl, Tracer);
                            if (new_id > 0)
                            {
                                actionMessage = "Saved new URL portal '" + new_name + "'";
                            }
                            else
                            {
                                actionMessage = "Error saving URL portal.";
                            }
                            break;
                        }
                    }
                }
                catch (Exception)
                {
                    actionMessage = "Exception caught while handling request";
                }

                // Reload all the URL portals
                SobekCM_Database.Populate_URL_Portals(portals, Tracer);
            }
        }