/// <summary> Parse the query and set the internal variables </summary>
        /// <param name="QueryString"> QueryString collection passed from the main page </param>
        /// <param name="Navigator"> Navigation object to hold the mode information </param>
        /// <param name="Base_URL">Requested base URL (without query string, etc..)</param>
        /// <param name="User_Languages"> Languages preferred by user, per their browser settings </param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections </param>
        /// <param name="Aggregation_Aliases"> List of all existing aliases for existing aggregationPermissions</param>
        /// <param name="All_Items_Lookup"> [REF] Lookup object used to pull basic information about any item loaded into this library</param>
        /// <param name="URL_Portals"> List of all web portals into this system </param>
        /// <param name="WebHierarchy"> Hierarchy of all non-aggregational web content pages and redirects </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        public static void Parse_Query(NameValueCollection QueryString,
			Navigation_Object Navigator,
			string Base_URL,
			string[] User_Languages,
			Aggregation_Code_Manager Code_Manager,
			Dictionary<string, string> Aggregation_Aliases,
			Item_Lookup_Object All_Items_Lookup,
			Portal_List URL_Portals,
            WebContent_Hierarchy WebHierarchy,
			Custom_Tracer Tracer )
        {
            if (Tracer != null)
                Tracer.Add_Trace("QueryString_Analyzer.Parse_Query", "Parse the query into the provided Navigation_Object");

            // Set default mode to error
            Navigator.Mode = Display_Mode_Enum.Error;

            // If this has 'verb' then this is an OAI-PMH request
            if ( QueryString["verb"] != null )
            {
                Navigator.Writer_Type = Writer_Type_Enum.OAI;
                return;
            }

            // Is there a TOC state set?
            if (QueryString["toc"] != null)
            {
                if (QueryString["toc"] == "y")
                {
                    Navigator.TOC_Display = TOC_Display_Type_Enum.Show;
                }
                else if ( QueryString["toc"] == "n" )
                {
                    Navigator.TOC_Display = TOC_Display_Type_Enum.Hide;
                }
            }

            // Determine the default language, per the browser settings
            if (User_Languages != null)
            {
                foreach (string thisLanguage in User_Languages)
                {
                    if (thisLanguage.IndexOf("en") == 0)
                    {
                        Navigator.Default_Language = Web_Language_Enum.English;
                        break;
                    }

                    if (thisLanguage.IndexOf("fr") == 0)
                    {
                        Navigator.Default_Language = Web_Language_Enum.French;
                        break;
                    }

                    if (thisLanguage.IndexOf("es") == 0)
                    {
                        Navigator.Default_Language = Web_Language_Enum.Spanish;
                        break;
                    }
                }
            }

            // Is there a language defined?  If so, load right into the navigator
            Navigator.Language = Navigator.Default_Language;
            if ( !String.IsNullOrEmpty(QueryString["l"]))
            {
                Navigator.Language = Web_Language_Enum_Converter.Code_To_Enum(QueryString["l"]);
            }

            // If there is flag indicating to show the trace route, save it
            if (QueryString["trace"] != null)
            {
                Navigator.Trace_Flag = QueryString["trace"].ToUpper() == "NO" ? Trace_Flag_Type_Enum.No : Trace_Flag_Type_Enum.Explicit;
            }
            else
            {
                Navigator.Trace_Flag = Trace_Flag_Type_Enum.Unspecified;
            }

            // Did the user request to have it render like it would for a search robot?
            if (QueryString["robot"] != null)
            {
                Navigator.Is_Robot = true;
            }

            // Was a fragment specified in the query string?
            if (QueryString["fragment"] != null)
            {
                Navigator.Fragment = QueryString["fragment"];
            }

            // Get the valid URL Portal
            Navigator.Default_Aggregation = "all";
            Portal urlPortal = URL_Portals.Get_Valid_Portal(Base_URL);
            Navigator.Instance_Abbreviation = urlPortal.Abbreviation;
            Navigator.Instance_Name = urlPortal.Name;
            if ( !String.IsNullOrEmpty(urlPortal.Base_PURL ))
                Navigator.Portal_PURL = urlPortal.Base_PURL;
            if (String.IsNullOrEmpty(urlPortal.Default_Aggregation))
            {
                Navigator.Aggregation = "";
            }
            else
            {
                Navigator.Default_Aggregation = urlPortal.Default_Aggregation;
                Navigator.Aggregation = urlPortal.Default_Aggregation;
            }
            if (!String.IsNullOrEmpty(urlPortal.Default_Web_Skin))
            {
                Navigator.Default_Skin = urlPortal.Default_Web_Skin;
                Navigator.Skin = urlPortal.Default_Web_Skin;
                Navigator.Skin_In_URL = false;
            }

            // Collect the interface string
            if (QueryString["n"] != null)
            {
                string currSkin = QueryString["n"].ToLower().Replace("'", "");

                // Save the interface
                if (currSkin.Length > 0)
                {
                    if (currSkin.IndexOf(",") > 0)
                        currSkin = currSkin.Substring(0, currSkin.IndexOf(","));
                    Navigator.Skin = currSkin.ToLower();
                    Navigator.Skin_In_URL = true;
                }
            }

            // Parse URL request different now, depending on if this is a legacy URL type or the new URL type
            Navigator.Mode = Display_Mode_Enum.None;

            // CHECK FOR LEGACY VALUES
            // Check for legacy bibid / vid information, since this will be supported indefinitely
            if (( QueryString["b"] != null ) || ( QueryString["bib"] != null ))
            {
                Navigator.BibID = QueryString["b"] ?? QueryString["bib"];

                if ( Navigator.BibID.Length > 0 )
                {
                    Navigator.Mode = Display_Mode_Enum.Item_Display;

                    if ( QueryString["v"] != null )
                        Navigator.VID = QueryString["v"];
                    else if ( QueryString["vid"] != null )
                        Navigator.VID = QueryString["vid"];
                }

                // No other item information is collected here anymore.. just return
                return;
            }

            // Set the default mode
            Navigator.Mode = Display_Mode_Enum.Aggregation;
            Navigator.Aggregation_Type = Aggregation_Type_Enum.Home;
            Navigator.Home_Type = Home_Type_Enum.List;

            // Get any url rewrite which occurred
            if (QueryString["urlrelative"] != null)
            {
                string urlrewrite = QueryString["urlrelative"].ToLower();
                if (urlrewrite.Length > 0)
                {
                    // Split the url relative list
                    string[] url_relative_info = urlrewrite.Split("/".ToCharArray());
                    List<string> url_relative_list = (from thisPart in url_relative_info where thisPart.Length > 0 select thisPart.ToLower()).ToList();

                    // Determine the main writer (html, json, xml, oai-pmh, etc..)
                    Navigator.Writer_Type = Writer_Type_Enum.HTML;
                    if ( url_relative_list.Count > 0 )
                    {
                        switch (url_relative_list[0])
                        {
                            case "l":
                                Navigator.Writer_Type = Writer_Type_Enum.HTML_LoggedIn;
                                url_relative_list.RemoveAt(0);
                                break;

                            case "my":
                                Navigator.Writer_Type = Writer_Type_Enum.HTML_LoggedIn;
                                break;

                            case "json":
                                Navigator.Writer_Type = Writer_Type_Enum.JSON;
                                url_relative_list.RemoveAt(0);
                                break;

                            case "dataset":
                                Navigator.Writer_Type = Writer_Type_Enum.DataSet;
                                url_relative_list.RemoveAt(0);
                                break;

                            case "dataprovider":
                                Navigator.Writer_Type = Writer_Type_Enum.Data_Provider;
                                url_relative_list.RemoveAt(0);
                                break;

                            case "xml":
                                Navigator.Writer_Type = Writer_Type_Enum.XML;
                                url_relative_list.RemoveAt(0);
                                break;

                            case "textonly":
                                Navigator.Writer_Type = Writer_Type_Enum.Text;
                                url_relative_list.RemoveAt(0);
                                break;
                        }
                    }

                    // Is the first part of the list one of these constants?
                    if (( url_relative_list.Count > 0 ) && ( url_relative_list[0].Length > 0 ))
                    {
                        switch ( url_relative_list[0] )
                        {
                            case "shibboleth":
                                Navigator.Mode = Display_Mode_Enum.My_Sobek;
                                Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Shibboleth_Landing;
                                break;

                            case "internal":
                                Navigator.Mode = Display_Mode_Enum.Internal;
                                Navigator.Internal_Type = Internal_Type_Enum.Aggregations_List;
                                if ( url_relative_list.Count > 1 )
                                {
                                    switch( url_relative_list[1] )
                                    {
                                        case "aggregations":
                                            Navigator.Internal_Type = Internal_Type_Enum.Aggregations_List;
                                            if (url_relative_list.Count > 2)
                                            {
                                                if (url_relative_list[2] == "tree")
                                                {
                                                    Navigator.Internal_Type = Internal_Type_Enum.Aggregations_Tree;
                                                }
                                            }
                                            break;

                                        case "cache":
                                            Navigator.Internal_Type = Internal_Type_Enum.Cache;
                                            break;

                                        case "new":
                                            Navigator.Internal_Type = Internal_Type_Enum.New_Items;
                                            if (url_relative_list.Count > 2)
                                            {
                                                Navigator.Info_Browse_Mode = url_relative_list[2];
                                            }
                                            break;

                                        case "failures":
                                            Navigator.Internal_Type = Internal_Type_Enum.Build_Failures;
                                            if (url_relative_list.Count > 2)
                                                Navigator.Info_Browse_Mode = url_relative_list[2];
                                            break;

                                        case "wordmarks":
                                            Navigator.Internal_Type = Internal_Type_Enum.Wordmarks;
                                            break;
                                    }
                                }
                                break;

                            case "contact":
                                Navigator.Mode = Display_Mode_Enum.Contact;
                                if ( url_relative_list.Count > 1 )
                                {
                                    if (url_relative_list[1] == "sent")
                                    {
                                        Navigator.Mode = Display_Mode_Enum.Contact_Sent;
                                    }
                                    else
                                    {
                                        Navigator.Aggregation = url_relative_list[1];
                                    }
                                }
                                if (QueryString["em"] != null)
                                    Navigator.Error_Message = QueryString["em"];
                                break;

                            case "folder":
                                Navigator.Mode = Display_Mode_Enum.Public_Folder;
                                if (url_relative_list.Count >= 2)
                                {
                                    try
                                    {
                                        Navigator.FolderID = Convert.ToInt32(url_relative_list[1]);
                                    }
                                    catch
                                    {
                                        Navigator.FolderID = -1;
                                    }

                                    // Look for result display type
                                    if (url_relative_list.Count >=3 )
                                    {
                                        switch (url_relative_list[2])
                                        {
                                            case "brief":
                                                Navigator.Result_Display_Type = Result_Display_Type_Enum.Brief;
                                                break;
                                            case "export":
                                                Navigator.Result_Display_Type = Result_Display_Type_Enum.Export;
                                                break;
                                            case "citation":
                                                Navigator.Result_Display_Type = Result_Display_Type_Enum.Full_Citation;
                                                break;
                                            case "image":
                                                Navigator.Result_Display_Type = Result_Display_Type_Enum.Full_Image;
                                                break;
                                            case "map":
                                                Navigator.Result_Display_Type = Result_Display_Type_Enum.Map;
                                                break;
                                            case "mapbeta":
                                                Navigator.Result_Display_Type = Result_Display_Type_Enum.Map_Beta;
                                                break;
                                            case "table":
                                                Navigator.Result_Display_Type = Result_Display_Type_Enum.Table;
                                                break;
                                            case "thumbs":
                                                Navigator.Result_Display_Type = Result_Display_Type_Enum.Thumbnails;
                                                break;
                                            default:
                                                Navigator.Result_Display_Type = Result_Display_Type_Enum.Brief;
                                                break;
                                        }
                                    }

                                    // Look for a page number
                                    if (url_relative_list.Count >= 4 )
                                    {
                                        string possible_page = url_relative_list[3];
                                        if ((possible_page.Length > 0) && (is_String_Number(possible_page)))
                                        {
                                            ushort page_result;
                                            UInt16.TryParse(possible_page, out page_result);
                                            Navigator.Page = page_result;
                                        }
                                    }
                                }
                                break;

                            case "register":
                                Navigator.Mode = Display_Mode_Enum.My_Sobek;
                                Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Preferences;
                                break;

                            case "my":
                                Navigator.Mode = Display_Mode_Enum.My_Sobek;
                                Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                                if (QueryString["return"] != null)
                                    Navigator.Return_URL = QueryString["return"];
                                if ( url_relative_list.Count > 1 )
                                {
                                    switch( url_relative_list[1] )
                                    {
                                        case "logon":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Logon;
                                            if (QueryString["return"] != null)
                                                Navigator.Return_URL = QueryString["return"];
                                            break;

                                        case "home":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Home;
                                            if (QueryString["return"] != null)
                                                Navigator.Return_URL = QueryString["return"];
                                            break;

                                        case "delete":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Delete_Item;
                                            if (url_relative_list.Count > 2)
                                                Navigator.BibID = url_relative_list[2].ToUpper();
                                            if (url_relative_list.Count > 3)
                                                Navigator.VID = url_relative_list[3];
                                            break;

                                        case "submit":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.New_Item;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "itempermissions":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Edit_Item_Permissions;
                                            if (url_relative_list.Count > 2)
                                                Navigator.BibID = url_relative_list[2].ToUpper();
                                            if (url_relative_list.Count > 3)
                                                Navigator.VID = url_relative_list[3];
                                            if (url_relative_list.Count > 4)
                                                Navigator.My_Sobek_SubMode = url_relative_list[4];
                                            break;

                                        case "behaviors":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Edit_Item_Behaviors;
                                            if (url_relative_list.Count > 2)
                                                Navigator.BibID = url_relative_list[2].ToUpper();
                                            if (url_relative_list.Count > 3)
                                                Navigator.VID = url_relative_list[3];
                                            if (url_relative_list.Count > 4)
                                                Navigator.My_Sobek_SubMode = url_relative_list[4];
                                            break;

                                        case "edit":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Edit_Item_Metadata;
                                            if (url_relative_list.Count > 2)
                                                Navigator.BibID = url_relative_list[2].ToUpper();
                                            if (url_relative_list.Count > 3)
                                                Navigator.VID = url_relative_list[3];
                                            if (url_relative_list.Count > 4)
                                                Navigator.My_Sobek_SubMode = url_relative_list[4];
                                            break;

                                        case "files":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.File_Management;
                                            if (url_relative_list.Count > 2)
                                                Navigator.BibID = url_relative_list[2].ToUpper();
                                            if (url_relative_list.Count > 3)
                                                Navigator.VID = url_relative_list[3];
                                            if (url_relative_list.Count > 4)
                                                Navigator.My_Sobek_SubMode = url_relative_list[4];
                                            break;

                                        case "images":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Page_Images_Management;
                                            if (url_relative_list.Count > 2)
                                                Navigator.BibID = url_relative_list[2].ToUpper();
                                            if (url_relative_list.Count > 3)
                                                Navigator.VID = url_relative_list[3];
                                            if (url_relative_list.Count > 4)
                                                Navigator.My_Sobek_SubMode = url_relative_list[4];
                                            break;

                                        case "addvolume":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Group_Add_Volume;
                                            if (url_relative_list.Count > 2)
                                                Navigator.BibID = url_relative_list[2].ToUpper();
                                            if (url_relative_list.Count > 3)
                                                Navigator.My_Sobek_SubMode = url_relative_list[3];
                                            break;

                                        case "autofill":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Group_AutoFill_Volumes;
                                            if (url_relative_list.Count > 2)
                                                Navigator.BibID = url_relative_list[2].ToUpper();
                                            if (url_relative_list.Count > 3)
                                                Navigator.My_Sobek_SubMode = url_relative_list[3];
                                            break;

                                        case "massupdate":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Group_Mass_Update_Items;
                                            if (url_relative_list.Count > 2)
                                                Navigator.BibID = url_relative_list[2].ToUpper();
                                            if (url_relative_list.Count > 3)
                                                Navigator.My_Sobek_SubMode = url_relative_list[3];
                                            break;

                                        case "groupbehaviors":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Edit_Group_Behaviors;
                                            if (url_relative_list.Count > 2)
                                                Navigator.BibID = url_relative_list[2].ToUpper();
                                            if (url_relative_list.Count > 3)
                                                Navigator.My_Sobek_SubMode = url_relative_list[3];
                                            break;

                                        case "serialhierarchy":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Edit_Group_Serial_Hierarchy;
                                            if (url_relative_list.Count > 2)
                                                Navigator.BibID = url_relative_list[2].ToUpper();
                                            if (url_relative_list.Count > 3)
                                                Navigator.My_Sobek_SubMode = url_relative_list[3];
                                            break;

                                        case "bookshelf":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Folder_Management;
                                            Navigator.Result_Display_Type = Result_Display_Type_Enum.Bookshelf;
                                            if (url_relative_list.Count > 2)
                                            {
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                                if (url_relative_list.Count > 3)
                                                {
                                                    switch (Navigator.My_Sobek_SubMode)
                                                    {
                                                        case "brief":
                                                            Navigator.Result_Display_Type = Result_Display_Type_Enum.Brief;
                                                            Navigator.My_Sobek_SubMode = url_relative_list[3];
                                                            break;

                                                        case "export":
                                                            Navigator.Result_Display_Type = Result_Display_Type_Enum.Export;
                                                            Navigator.My_Sobek_SubMode = url_relative_list[3];
                                                            break;

                                                        case "thumbs":
                                                            Navigator.Result_Display_Type = Result_Display_Type_Enum.Thumbnails;
                                                            Navigator.My_Sobek_SubMode = url_relative_list[3];
                                                            break;

                                                        case "table":
                                                            Navigator.Result_Display_Type = Result_Display_Type_Enum.Table;
                                                            Navigator.My_Sobek_SubMode = url_relative_list[3];
                                                            break;

                                                        case "citation":
                                                            Navigator.Result_Display_Type = Result_Display_Type_Enum.Full_Citation;
                                                            Navigator.My_Sobek_SubMode = url_relative_list[3];
                                                            break;

                                                        case "image":
                                                            Navigator.Result_Display_Type = Result_Display_Type_Enum.Full_Image;
                                                            Navigator.My_Sobek_SubMode = url_relative_list[3];
                                                            break;

                                                        default:
                                                            if (is_String_Number(url_relative_list[3]))
                                                            {
                                                                ushort page_result;
                                                                UInt16.TryParse(url_relative_list[3], out page_result);
                                                                Navigator.Page = page_result;
                                                            }
                                                            break;
                                                    }
                                                }
                                                if ((url_relative_list.Count > 4) && ( is_String_Number( url_relative_list[4] )))
                                                {
                                                    ushort page_result;
                                                    UInt16.TryParse(url_relative_list[4], out page_result);
                                                    Navigator.Page = page_result;
                                                }
                                            }
                                            break;

                                        case "preferences":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Preferences;
                                            break;

                                        case "logout":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Log_Out;
                                            if (QueryString["return"] != null)
                                                Navigator.Return_URL = QueryString["return"];
                                            break;

                                        case "shibboleth":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Shibboleth_Landing;
                                            if (QueryString["return"] != null)
                                                Navigator.Return_URL = QueryString["return"];
                                            break;

                                        case "itemtracking":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Item_Tracking;
                                            //if(url_relative_list.Count>3 && is_String_Number(url_relative_list[3]))
                                            //    Navigator.My_Sobek_SubMode = url_relative_list[3];
                                            break;

                                        case "searches":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.Saved_Searches;
                                            break;

                                        case "tags":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.User_Tags;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "stats":
                                            Navigator.My_Sobek_Type = My_Sobek_Type_Enum.User_Usage_Stats;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;
                                    }
                                }
                                break;

                            case "admin":
                                Navigator.Mode = Display_Mode_Enum.Administrative;
                                Navigator.Admin_Type = Admin_Type_Enum.Home;
                                if (QueryString["return"] != null)
                                    Navigator.Return_URL = QueryString["return"];
                                if (url_relative_list.Count > 1)
                                {
                                    switch (url_relative_list[1])
                                    {
                                        case "builder":
                                            Navigator.Admin_Type = Admin_Type_Enum.Builder_Status;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;
                                            break;

                                        case "addcoll":
                                            Navigator.Admin_Type = Admin_Type_Enum.Add_Collection_Wizard;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "aggregations":
                                            Navigator.Admin_Type = Admin_Type_Enum.Aggregations_Mgmt;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "editaggr":
                                            Navigator.Admin_Type = Admin_Type_Enum.Aggregation_Single;
                                            if (url_relative_list.Count > 2)
                                                Navigator.Aggregation = url_relative_list[2];
                                            if (url_relative_list.Count > 3)
                                                Navigator.My_Sobek_SubMode = url_relative_list[3];
                                            break;

                                        case "aliases":
                                            Navigator.Admin_Type = Admin_Type_Enum.Aliases;
                                            break;

                                        case "webskins":
                                            Navigator.Admin_Type = Admin_Type_Enum.Skins_Mgmt;
                                            break;

                                        case "editskin":
                                            Navigator.Admin_Type = Admin_Type_Enum.Skins_Single;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            if (url_relative_list.Count > 3)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2] + "/" + url_relative_list[3];
                                            break;

                                        case "defaults":
                                            Navigator.Admin_Type = Admin_Type_Enum.Default_Metadata;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "restrictions":
                                            Navigator.Admin_Type = Admin_Type_Enum.IP_Restrictions;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "portals":
                                            Navigator.Admin_Type = Admin_Type_Enum.URL_Portals;
                                            break;

                                        case "users":
                                            Navigator.Admin_Type = Admin_Type_Enum.Users;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "groups":
                                            Navigator.Admin_Type = Admin_Type_Enum.User_Groups;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "permissions":
                                            Navigator.Admin_Type = Admin_Type_Enum.User_Permissions_Reports;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "webadd":
                                            Navigator.Admin_Type = Admin_Type_Enum.WebContent_Add_New;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "webcontent":
                                            Navigator.Admin_Type = Admin_Type_Enum.WebContent_Mgmt;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "webhistory":
                                            Navigator.Admin_Type = Admin_Type_Enum.WebContent_History;
                                            break;

                                        case "websingle":
                                            Navigator.Admin_Type = Admin_Type_Enum.WebContent_Single;
                                            if (url_relative_list.Count > 2)
                                            {
                                                int possiblewebid;
                                                if (Int32.TryParse(url_relative_list[2], out possiblewebid))
                                                {
                                                    Navigator.WebContentID = possiblewebid;
                                                }
                                                if (url_relative_list.Count > 3)
                                                {
                                                    Navigator.My_Sobek_SubMode = url_relative_list[3];
                                                }
                                            }
                                            if ( Navigator.WebContentID < 1 )
                                                Navigator.Admin_Type = Admin_Type_Enum.WebContent_Mgmt;
                                            break;

                                        case "webusage":
                                            Navigator.Admin_Type = Admin_Type_Enum.WebContent_Usage;
                                            break;

                                        case "wordmarks":
                                            Navigator.Admin_Type = Admin_Type_Enum.Wordmarks;
                                            break;

                                        case "reset":
                                            Navigator.Admin_Type = Admin_Type_Enum.Reset;
                                            break;

                                        case "headings":
                                            Navigator.Admin_Type = Admin_Type_Enum.Thematic_Headings;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;

                                        case "settings":
                                            Navigator.Admin_Type = Admin_Type_Enum.Settings;
                                            if (url_relative_list.Count > 2)
                                                Navigator.My_Sobek_SubMode = url_relative_list[2];
                                            break;
                                    }
                                }
                                break;

                            case "preferences":
                                Navigator.Mode = Display_Mode_Enum.Preferences;
                                break;

                            case "reports":
                                Navigator.Mode = Display_Mode_Enum.Reports;
                                if (url_relative_list.Count > 1)
                                {
                                    Navigator.Report_Name = url_relative_list[1];
                                }
                                break;

                            case "stats":
                            case "statistics":
                                Navigator.Mode = Display_Mode_Enum.Statistics;
                                Navigator.Statistics_Type = Statistics_Type_Enum.Item_Count_Standard_View;
                                if ( url_relative_list.Count > 1 )
                                {
                                    switch( url_relative_list[1] )
                                    {
                                        case "itemcount":
                                            Navigator.Statistics_Type = Statistics_Type_Enum.Item_Count_Standard_View;
                                            if ( url_relative_list.Count > 2 )
                                            {
                                                switch( url_relative_list[2])
                                                {
                                                    case "arbitrary":
                                                        Navigator.Statistics_Type = Statistics_Type_Enum.Item_Count_Arbitrary_View;
                                                        if (url_relative_list.Count > 3)
                                                        {
                                                            Navigator.Info_Browse_Mode = url_relative_list[3];
                                                        }
                                                        break;

                                                    case "growth":
                                                        Navigator.Statistics_Type = Statistics_Type_Enum.Item_Count_Growth_View;
                                                        break;

                                                    case "text":
                                                        Navigator.Statistics_Type = Statistics_Type_Enum.Item_Count_Text;
                                                        break;

                                                    case "standard":
                                                        Navigator.Statistics_Type = Statistics_Type_Enum.Item_Count_Standard_View;
                                                        break;
                                                }
                                            }
                                            break;

                                        case "searches":
                                            Navigator.Statistics_Type = Statistics_Type_Enum.Recent_Searches;
                                            break;

                                        case "usage":
                                            Navigator.Statistics_Type = Statistics_Type_Enum.Usage_Overall;
                                            if ( url_relative_list.Count > 2 )
                                            {
                                                switch( url_relative_list[2])
                                                {
                                                    case "all":
                                                        Navigator.Statistics_Type = Statistics_Type_Enum.Usage_Overall;
                                                        break;

                                                    case "history":
                                                        Navigator.Statistics_Type = Statistics_Type_Enum.Usage_Collection_History;
                                                        if ( url_relative_list.Count > 3 )
                                                        {
                                                            switch( url_relative_list[3] )
                                                            {
                                                                case "text":
                                                                    Navigator.Statistics_Type = Statistics_Type_Enum.Usage_Collection_History_Text;
                                                                    break;

                                                                default:
                                                                    Navigator.Info_Browse_Mode = url_relative_list[3];
                                                                    break;
                                                            }

                                                            if ((String.IsNullOrEmpty(Navigator.Info_Browse_Mode)) && (url_relative_list.Count > 4))
                                                                Navigator.Info_Browse_Mode = url_relative_list[4];
                                                        }
                                                        break;

                                                    case "collections":
                                                        Navigator.Statistics_Type = Statistics_Type_Enum.Usage_Collections_By_Date;
                                                        if (url_relative_list.Count > 3)
                                                            Navigator.Info_Browse_Mode = url_relative_list[3];
                                                        break;

                                                    case "definitions":
                                                        Navigator.Statistics_Type = Statistics_Type_Enum.Usage_Definitions;
                                                        break;

                                                    case "titles":
                                                        Navigator.Statistics_Type = Statistics_Type_Enum.Usage_Titles_By_Collection;
                                                        if (( String.IsNullOrEmpty( Navigator.Info_Browse_Mode )) && ( url_relative_list.Count > 4 ))
                                                            Navigator.Info_Browse_Mode = url_relative_list[4];
                                                        break;

                                                    case "items":
                                                        Navigator.Statistics_Type = Statistics_Type_Enum.Usage_Item_Views_By_Date;
                                                        if ( url_relative_list.Count > 3 )
                                                        {
                                                            switch( url_relative_list[3] )
                                                            {
                                                                case "date":
                                                                    Navigator.Statistics_Type = Statistics_Type_Enum.Usage_Item_Views_By_Date;
                                                                    break;

                                                                case "top":
                                                                    Navigator.Statistics_Type = Statistics_Type_Enum.Usage_Items_By_Collection;
                                                                    break;

                                                                case "text":
                                                                    Navigator.Statistics_Type = Statistics_Type_Enum.Usage_By_Date_Text;
                                                                    break;

                                                                default:
                                                                    Navigator.Info_Browse_Mode = url_relative_list[3];
                                                                    break;
                                                            }

                                                            if (( String.IsNullOrEmpty( Navigator.Info_Browse_Mode )) && ( url_relative_list.Count > 4 ))
                                                                Navigator.Info_Browse_Mode = url_relative_list[4];
                                                        }
                                                        break;

                                                }
                                            }
                                            break;
                                    }
                                }
                                break;

                            case "partners":
                                if (( String.IsNullOrEmpty(Navigator.Default_Aggregation)) || ( Navigator.Default_Aggregation == "all"))
                                {
                                    Navigator.Mode = Display_Mode_Enum.Aggregation;
                                    Navigator.Aggregation_Type = Aggregation_Type_Enum.Home;
                                    Navigator.Aggregation = String.Empty;
                                    Navigator.Home_Type = Home_Type_Enum.Partners_List;
                                    if ((url_relative_list.Count > 1) && (url_relative_list[1] == "thumbs"))
                                    {
                                        Navigator.Home_Type = Home_Type_Enum.Partners_Thumbnails;
                                    }
                                }
                                else
                                {
                                    aggregation_querystring_analyze(Navigator, QueryString, Navigator.Default_Aggregation, url_relative_list);
                                }
                                break;

                            case "tree":
                                Navigator.Mode = Display_Mode_Enum.Aggregation;
                                Navigator.Aggregation_Type = Aggregation_Type_Enum.Home;
                                Navigator.Aggregation = String.Empty;
                                Navigator.Home_Type = Home_Type_Enum.Tree;
                                break;

                            case "brief":
                                Navigator.Mode = Display_Mode_Enum.Aggregation;
                                Navigator.Aggregation_Type = Aggregation_Type_Enum.Home;
                                Navigator.Aggregation = String.Empty;
                                Navigator.Home_Type = Home_Type_Enum.Descriptions;
                                break;

                            case "personalized":
                                Navigator.Mode = Display_Mode_Enum.Aggregation;
                                Navigator.Aggregation_Type = Aggregation_Type_Enum.Home;
                                Navigator.Aggregation = String.Empty;
                                Navigator.Home_Type = Home_Type_Enum.Personalized;
                                break;

                            case "inprocess":
                                Navigator.Aggregation = String.Empty;
                                Navigator.Mode = Display_Mode_Enum.Aggregation;
                                Navigator.Aggregation_Type = Aggregation_Type_Enum.Home;
                                Navigator.Aggregation_Type = Aggregation_Type_Enum.Private_Items;
                                Navigator.Page = 1;
                                if (url_relative_list.Count > 1)
                                {
                                    if (is_String_Number(url_relative_list[1]))
                                        Navigator.Page = Convert.ToUInt16(url_relative_list[1]);
                                }
                                if ((QueryString["o"] != null) && (is_String_Number(QueryString["o"])))
                                {
                                    Navigator.Sort = Convert.ToInt16(QueryString["o"]);
                                }
                                else
                                {
                                    Navigator.Sort = 0;
                                }
                                break;

                            case "all":
                            case "new":
                            case "edit":
                            case "map":
                            case "mapbeta":
                            case "advanced":
                            case "text":
                            case "results":
                            case "contains":
                            case "exact":
                            case "resultslike":
                            case "browseby":
                            case "info":
                            case "aggrmanage":
                            case "aggrhistory":
                            case "aggrpermissions":
                            case "geography":
                                aggregation_querystring_analyze(Navigator, QueryString, Navigator.Default_Aggregation, url_relative_list);
                                break;

                            // This was none of the main constant mode settings,
                            default:
                                // Always check the top-level static web content pages and redirects hierarchy first
                                if ((WebHierarchy != null) && (WebHierarchy.Root_Count > 0))
                                {
                                    WebContent_Hierarchy_Node matchedNode = WebHierarchy.Find(url_relative_list);
                                    if (matchedNode != null)
                                    {
                                        // Maybe this is a web content / info page
                                        Navigator.Mode = Display_Mode_Enum.Simple_HTML_CMS;

                                        // Get the URL reassembled
                                        string possible_info_mode = String.Empty;
                                        if (url_relative_list.Count == 1)
                                            possible_info_mode = url_relative_list[0];
                                        else if (url_relative_list.Count == 2)
                                            possible_info_mode = url_relative_list[0] + "/" + url_relative_list[1];
                                        else if (url_relative_list.Count == 3)
                                            possible_info_mode = url_relative_list[0] + "/" + url_relative_list[1] + "/" + url_relative_list[2];
                                        else if (url_relative_list.Count == 4)
                                            possible_info_mode = url_relative_list[0] + "/" + url_relative_list[1] + "/" + url_relative_list[2] + "/" + url_relative_list[3];
                                        else if (url_relative_list.Count > 4)
                                        {
                                            StringBuilder possibleInfoModeBuilder = new StringBuilder();
                                            if (url_relative_list.Count > 0)
                                            {
                                                possibleInfoModeBuilder.Append(url_relative_list[0]);
                                            }
                                            for (int i = 1; i < url_relative_list.Count; i++)
                                            {
                                                possibleInfoModeBuilder.Append("/" + url_relative_list[i]);
                                            }
                                            possible_info_mode = possibleInfoModeBuilder.ToString().Replace("'", "").Replace("\"", "");
                                        }

                                        // Set the source location
                                        Navigator.Info_Browse_Mode = possible_info_mode;
                                        Navigator.Page_By_FileName = Engine_ApplicationCache_Gateway.Settings.Servers.Base_Directory + "design\\webcontent\\" + possible_info_mode.Replace("/","\\") + "\\default.html";
                                        Navigator.WebContentID = matchedNode.WebContentID;
                                        Navigator.Redirect = matchedNode.Redirect;

                                        //// If it is missing, mark that
                                        //if ((!File.Exists(Navigator.Page_By_FileName)) && ( String.IsNullOrEmpty(Navigator.Redirect)))
                                        //{
                                        //    Navigator.Missing = true;
                                        //    Navigator.Info_Browse_Mode = possible_info_mode;
                                        //    Navigator.Page_By_FileName = Engine_ApplicationCache_Gateway.Settings.Servers.Base_Directory + "design\\webcontent\\missing.html";
                                        //}

                                        // If something was found, then check for submodes
                                        Navigator.WebContent_Type = WebContent_Type_Enum.Display;
                                        if (!String.IsNullOrEmpty(QueryString["mode"]))
                                        {
                                            switch (QueryString["mode"].ToLower())
                                            {
                                                case "edit":
                                                    Navigator.WebContent_Type = WebContent_Type_Enum.Edit;
                                                    break;

                                                case "menu":
                                                    Navigator.WebContent_Type = WebContent_Type_Enum.Manage_Menu;
                                                    break;

                                                case "milestones":
                                                    Navigator.WebContent_Type = WebContent_Type_Enum.Milestones;
                                                    break;

                                                case "permissions":
                                                    Navigator.WebContent_Type = WebContent_Type_Enum.Permissions;
                                                    break;

                                                case "usage":
                                                    Navigator.WebContent_Type = WebContent_Type_Enum.Usage;
                                                    break;

                                                case "verify":
                                                    Navigator.WebContent_Type = WebContent_Type_Enum.Delete_Verify;
                                                    break;
                                            }
                                        }

                                        return;
                                    }
                                }

                                // Check to see if the first term was an item aggregation alias, which
                                // allows for the alias to overwrite an existing aggregation code (limited usability
                                // but can be used to hide an existing aggregation easily)
                                if (Aggregation_Aliases.ContainsKey(url_relative_list[0]))
                                {
                                    // Perform all aggregation_style checks next
                                    string aggregation_code = Aggregation_Aliases[url_relative_list[0]];
                                    Navigator.Aggregation_Alias = url_relative_list[0];
                                    aggregation_querystring_analyze( Navigator, QueryString, aggregation_code, url_relative_list.GetRange(1, url_relative_list.Count - 1));
                                }
                                else if ( Code_Manager.isValidCode( url_relative_list[0] ))
                                {
                                    // This is an item aggregation call
                                    // Perform all aggregation_style checks next
                                    aggregation_querystring_analyze( Navigator, QueryString, url_relative_list[0], url_relative_list.GetRange(1, url_relative_list.Count - 1 ));
                                }
                                else if ((Engine_Database.Verify_Item_Lookup_Object(false, true, All_Items_Lookup, Tracer)) && (All_Items_Lookup.Contains_BibID(url_relative_list[0].ToUpper())))
                                {
                                    // This is a BibID for an existing title with at least one public item
                                    Navigator.BibID = url_relative_list[0].ToUpper();
                                    Navigator.Mode = Display_Mode_Enum.Item_Display;

                                    // Is the next part a VID?
                                    int current_list_index = 1;
                                    if (url_relative_list.Count > 1)
                                    {
                                        string possible_vid = url_relative_list[1].Trim().PadLeft(5, '0');
                                        if ((All_Items_Lookup.Contains_BibID_VID(Navigator.BibID, possible_vid)) || ( possible_vid == "00000" ))
                                        {
                                            Navigator.VID = possible_vid;
                                            current_list_index++;
                                        }
                                    }

                                    // Look for the item print mode now
                                    if ((url_relative_list.Count > current_list_index) && (url_relative_list[current_list_index] == "print"))
                                    {
                                        // This is an item print request
                                        Navigator.Mode = Display_Mode_Enum.Item_Print;

                                        // Since we need special characters for ranges, etc.. the viewer code
                                        // is in the options query string variable in this case
                                        if (QueryString["options"] != null)
                                        {
                                            Navigator.ViewerCode = QueryString["options"];
                                        }
                                    }
                                    else
                                    {
                                        // Look for the viewercode next
                                        if (url_relative_list.Count > current_list_index)
                                        {
                                            string possible_viewercode = url_relative_list[current_list_index].Trim();

                                            // Get the view code
                                            if (possible_viewercode.Length > 0)
                                            {
                                                // Get the viewer code
                                                Navigator.ViewerCode = possible_viewercode;

                                                // Now, get the page
                                                if ((Navigator.ViewerCode.Length > 0) && (Char.IsNumber(Navigator.ViewerCode[0])))
                                                {
                                                    // Look for the first number
                                                    int numberEnd = Navigator.ViewerCode.Length;
                                                    int count = 0;
                                                    foreach (char thisChar in Navigator.ViewerCode)
                                                    {
                                                        if (!Char.IsNumber(thisChar))
                                                        {
                                                            numberEnd = count;
                                                            break;
                                                        }
                                                        count++;
                                                    }

                                                    // Get the page
                                                    ushort testPage;
                                                    if (UInt16.TryParse(Navigator.ViewerCode.Substring(0, numberEnd), out testPage))
                                                        Navigator.Page = testPage;
                                                }
                                            }
                                            else
                                            {
                                                // Sequence is set to 1
                                                Navigator.Page = 1;
                                            }

                                            // Used or discarded the possible viewer code (used unless length of zero )
                                            current_list_index++;

                                            // Look for a subpage now, if there since there was a (possible) viewer code
                                            if (url_relative_list.Count > current_list_index)
                                            {
                                                string possible_subpage = url_relative_list[current_list_index].Trim();
                                                if (is_String_Number(possible_subpage))
                                                {
                                                    ushort testSubPage;
                                                    if (UInt16.TryParse(possible_subpage, out testSubPage))
                                                        Navigator.SubPage = testSubPage;
                                                }
                                            }
                                        }
                                    }

                                    // Collect number of thumbnails per page
                                    if (QueryString["nt"] != null)
                                    {
                                        short nt_temp;
                                        if (short.TryParse(QueryString["nt"], out nt_temp))
                                            Navigator.Thumbnails_Per_Page = nt_temp;
                                    }

                                    // Collect size of thumbnails per page
                                    if (QueryString["ts"] != null)
                                    {
                                        short ts_temp;
                                        if (short.TryParse(QueryString["ts"], out ts_temp))
                                            Navigator.Size_Of_Thumbnails = ts_temp;
                                    }

                                    // Collect the text search string
                                    if (QueryString["search"] != null)
                                        Navigator.Text_Search = QueryString["search"].Replace("+"," ");

                                    // If coordinates were here, save them
                                    if (QueryString["coord"] != null)
                                        Navigator.Coordinates = QueryString["coord"];

                                    // If a page is requested by filename (rather than sequenc), collect that
                                    if (QueryString["file"] != null)
                                        Navigator.Page_By_FileName = QueryString["file"];
                                }
                                else if ((String.IsNullOrEmpty(Navigator.Page_By_FileName)) && ((String.IsNullOrEmpty(Navigator.Default_Aggregation)) || (Navigator.Default_Aggregation == "all")))
                                {
                                    // This may be a top-level aggregation call
                                    // aggregation_querystring_analyze(Navigator, QueryString, Navigator.Default_Aggregation, url_relative_list);

                                    // Pass this unmatched query to the simple html cms to show the missing (custom) screen
                                    Navigator.Mode = Display_Mode_Enum.Simple_HTML_CMS;

                                    string possible_info_mode = String.Empty;
                                    if (url_relative_list.Count == 1)
                                        possible_info_mode = url_relative_list[0];
                                    else if (url_relative_list.Count == 2)
                                        possible_info_mode = url_relative_list[0] + "/" + url_relative_list[1];
                                    else if (url_relative_list.Count == 3)
                                        possible_info_mode = url_relative_list[0] + "/" + url_relative_list[1] + "/" + url_relative_list[2];
                                    else if (url_relative_list.Count == 4)
                                        possible_info_mode = url_relative_list[0] + "/" + url_relative_list[1] + "/" + url_relative_list[2] + "/" + url_relative_list[3];
                                    else if ( url_relative_list.Count > 4)
                                    {
                                        StringBuilder possibleInfoModeBuilder = new StringBuilder();
                                        if (url_relative_list.Count > 0)
                                        {
                                            possibleInfoModeBuilder.Append(url_relative_list[0]);
                                        }
                                        for (int i = 1; i < url_relative_list.Count; i++)
                                        {
                                            possibleInfoModeBuilder.Append("/" + url_relative_list[i]);
                                        }
                                        possible_info_mode = possibleInfoModeBuilder.ToString().Replace("'", "").Replace("\"", "");
                                    }

                                    string base_source = Engine_ApplicationCache_Gateway.Settings.Servers.Base_Directory + "design\\webcontent";

                                    // Set the source location
                                    Navigator.Missing = true;
                                    Navigator.Info_Browse_Mode = possible_info_mode;
                                    Navigator.WebContent_Type = WebContent_Type_Enum.Display;
                                    Navigator.Page_By_FileName = base_source + "\\missing.html";
                                    Navigator.WebContentID = -1;
                                }
                                break;
                        }
                    }
                }
            }
        }
        /// <summary> Writes the search or browse information in JSON format directly to the output stream  </summary>
        /// <param name="Output"> Stream to which to write the JSON search or browse information </param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        protected internal void display_search_results(TextWriter Output, Item_Lookup_Object All_Items_Lookup)
        {
            // If results are null, or no results, return empty string
            if ((RequestSpecificValues.Paged_Results == null) || (RequestSpecificValues.Results_Statistics == null) || (RequestSpecificValues.Results_Statistics.Total_Items <= 0))
                return;

            Output.Write("[");

            // Step through all the results
            int i = 1;
            foreach (iSearch_Title_Result titleResult in RequestSpecificValues.Paged_Results)
            {
                // Always get the first item for things like the main link and thumbnail
                iSearch_Item_Result firstItemResult = titleResult.Get_Item(0);

                // Determine a thumbnail
                string thumb = currentGreenstoneImageRoot + titleResult.BibID.Substring(0,2) + "/" + titleResult.BibID.Substring(2,2) + "/" + titleResult.BibID.Substring(4,2) + "/" + titleResult.BibID.Substring(6,2) + "/" + titleResult.BibID.Substring(8) + "/" + firstItemResult.VID + "/" + firstItemResult.MainThumbnail;
                if ((thumb.ToUpper().IndexOf(".JPG") < 0) && (thumb.ToUpper().IndexOf(".GIF") < 0))
                {
                    thumb = Static_Resources_Gateway.Nothumb_Jpg;
                }
                thumb = thumb.Replace("\\", "/").Replace("//", "/").Replace("http:/", "http://");

                // Was a previous item/title included here?
                if (i > 1)
                    Output.Write(",");
                Output.Write("{\"collection_item\":{\"name\":\"" + firstItemResult.Title.Trim().Replace("\"", "'") + "\",\"url\":\"" + UI_ApplicationCache_Gateway.Settings.Servers.System_Base_URL + titleResult.BibID + "/" + firstItemResult.VID + "\",\"collection_code\":\"\",\"id\":\"" + titleResult.BibID + "_" + firstItemResult.VID + "\",\"thumb_url\":\"" + thumb + "\"}}");

                i++;
            }

            Output.Write("]");
        }
        /// <summary> Refresh the item lookup object by pulling the data back from the database </summary>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        public static bool RefreshItems()
        {
            try
            {
                lock (itemLookupLock)
                {
                    if (itemLookup == null)
                    {
                        itemLookup = new Item_Lookup_Object();
                    }

                    Engine_Database.Verify_Item_Lookup_Object(true, true, itemLookup, null);
                }

                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary> Rebuilds all MarcXML files </summary>
        /// <param name="ResourceDirectory"> Directory under which all the resources within this SobekCM library exist </param>
        /// <returns> The number of encountered errors </returns>
        public int Rebuild_All_MARC_Files( string ResourceDirectory )
        {
            // Set the item for the current mode
            errors = 0;
            int successes = 0;

            DataSet item_list_table = SobekCM_Database.Get_Item_List(false, null);

            // Get the item list and build the hashtable
            Item_Lookup_Object itemList = new Item_Lookup_Object();
            Engine_Database.Populate_Item_Lookup_Object(false, itemList, tracer);

            foreach (DataRow thisRow in item_list_table.Tables[0].Rows)
            {
                string bibid = thisRow["BibID"].ToString();
                string vid = thisRow["VID"].ToString();

                if (!Create_MarcXML_File(bibid, vid, ResourceDirectory, itemList))
                {
                    errors++;
                }
                else
                {
                    successes++;
                    if (successes % 1000 == 0 )
                        Console.WriteLine(@"{0} complete", successes);
                }
            }

            return errors;
        }
        /// <summary> Rebuilds all static pages, including the RSS feeds and site maps </summary>
        /// <param name="Logger"> Log file to record progress </param>
        /// <param name="BuildAllCitationPages"> Flag indicates to build the individual static HTML pages for each digital resource </param>
        /// <param name="RssFeedLocation"> Location where the RSS feeds should be updated to </param>
        /// <param name="InstanceName"> Name of this instance </param>
        /// <param name="PrimaryLogId"> Log ID in the case this is the builder and it has been pre-logged </param>
        /// <returns> The number of encountered errors </returns>
        public int Rebuild_All_Static_Pages(LogFileXhtml Logger, bool BuildAllCitationPages, string RssFeedLocation, string InstanceName, long PrimaryLogId )
        {
            if (InstanceName.Length > 0)
                InstanceName = InstanceName + " - ";

            if (PrimaryLogId < 0)
            {
                Console.WriteLine("Rebuilding all static pages");
                Logger.AddNonError(InstanceName + "Rebuilding all static pages");
                PrimaryLogId = SobekCM_Database.Builder_Add_Log_Entry(-1, String.Empty, "Standard", "Rebuilding all static pages", String.Empty);
            }

            // Set the correct base directory
            if (staticSobekcmLocation.Length > 0)
                UI_ApplicationCache_Gateway.Settings.Servers.Base_Directory = staticSobekcmLocation;

            // Set the item for the current mode
            errors = 0;
            if (BuildAllCitationPages)
            {
                Console.WriteLine(InstanceName + "Rebuildig all citation pages");
                SobekCM_Database.Builder_Add_Log_Entry(PrimaryLogId, String.Empty, "Standard", "Rebuilding all item-level citation static pages", String.Empty);

                DataSet item_list_table = SobekCM_Database.Get_Item_List(false, null);

                // Get the item list and build the hashtable
                Item_Lookup_Object itemList = new Item_Lookup_Object();
                Engine_Database.Populate_Item_Lookup_Object(false, itemList, tracer);

                foreach (DataRow thisRow in item_list_table.Tables[0].Rows)
                {
                    //if (errors > 10000)
                    //{
                    //    logger.AddError("10000 errors encountered!");
                    //    Console.WriteLine("10000 errors encountered");

                    //    return errors;
                    //}
                    string bibid = thisRow["BibID"].ToString();
                    string vid = thisRow["VID"].ToString();
                    string itemDirectory = UI_ApplicationCache_Gateway.Settings.Servers.Image_Server_Network + bibid.Substring(0, 2) + "\\" + bibid.Substring(2, 2) + "\\" + bibid.Substring(4, 2) + "\\" + bibid.Substring(6, 2) + "\\" + bibid.Substring(8, 2) + "\\" + vid;
                    string staticDirectory = itemDirectory + "\\" + UI_ApplicationCache_Gateway.Settings.Resources.Backup_Files_Folder_Name;

                    // ********** TEMPORARY CLEAN UP ***********************//
                    // TODO: REMOVE THIS!
                    // *******************************************//
                    try
                    {
                        if (Directory.Exists(itemDirectory))
                        {
                            if (!Directory.Exists(staticDirectory))
                                Directory.CreateDirectory(staticDirectory);

                            if ( File.Exists(itemDirectory + "\\thumbs.db"))
                                File.Delete(itemDirectory + "\\thumbs.db");

                            if ( File.Exists(itemDirectory + "\\doc.xml"))
                                File.Delete(itemDirectory + "\\doc.xml");

                            if ( File.Exists(itemDirectory + "\\citation_mets.xml"))
                                File.Delete(itemDirectory + "\\citation_mets.xml");

                            if ( File.Exists(itemDirectory + "\\" + bibid + "_" + vid + ".html"))
                                File.Delete(itemDirectory + "\\" + bibid + "_" + vid + ".html");

                            if ( File.Exists(itemDirectory + "\\errors.xml"))
                                File.Delete(itemDirectory + "\\errors.xml");

                            if ( File.Exists(itemDirectory + "\\qc_error.html"))
                                File.Delete(itemDirectory + "\\qc_error.html");

                            string[] files = Directory.GetFileSystemEntries(itemDirectory, "*.job");
                            foreach( string thisFile in files )
                                File.Delete(thisFile);

                            files = Directory.GetFileSystemEntries(itemDirectory, "*.bridge*");
                            foreach (string thisFile in files)
                                File.Delete(thisFile);

                            files = Directory.GetFileSystemEntries(itemDirectory, "*.qc.jpg");
                            foreach (string thisFile in files)
                                File.Delete(thisFile);

                            files = Directory.GetFileSystemEntries(itemDirectory, "*_qc.jpg");
                            foreach (string thisFile in files)
                                File.Delete(thisFile);

                            files = Directory.GetFileSystemEntries(itemDirectory, "*_INGEST_xml.txt");
                            foreach (string thisFile in files)
                                File.Delete(thisFile);

                            files = Directory.GetFileSystemEntries(itemDirectory, "*_INGEST.xml");
                            if (files.Length > 0)
                            {
                                if (!Directory.Exists(itemDirectory + "\\fda_files"))
                                    Directory.CreateDirectory(itemDirectory + "\\fda_files");

                                foreach (string thisFile in files)
                                {
                                    string filename = Path.GetFileName(thisFile);
                                    File.Move(thisFile, itemDirectory + "\\fda_files\\" + filename);
                                }
                            }

                            if (File.Exists(itemDirectory + "\\original.mets.xml"))
                                File.Move(itemDirectory + "\\original.mets.xml", staticDirectory + "\\original.mets.xml");

                            files = Directory.GetFileSystemEntries(itemDirectory, "recd_*.mets.xml");
                            foreach (string thisFile in files)
                            {
                                string filename = Path.GetFileName(thisFile);
                                File.Move(thisFile, staticDirectory+ "\\" + filename);
                            }

                            files = Directory.GetFileSystemEntries(itemDirectory, "*.mets.bak");
                            foreach (string thisFile in files)
                            {
                                string filename = Path.GetFileName(thisFile);
                                File.Move(thisFile, staticDirectory + "\\" + filename);
                            }
                        }
                    }
                    catch
                    {
                        Console.WriteLine(InstanceName + "....Error cleaning up folder " + bibid + ":" + vid);
                        Logger.AddError("....Error cleaning up folder " + bibid + ":" + vid);
                    }
                    // ************* END TEMPORARY CLEAN UP ******************//

                    try
                    {
                        if (!Directory.Exists(staticDirectory))
                            Directory.CreateDirectory(staticDirectory);

                        string static_file = staticDirectory + "\\" + bibid + "_" + vid + ".html";

                        if (Create_Item_Citation_HTML(bibid, vid, static_file, itemDirectory, itemList))
                        {
                            // Also copy to the static page location server
                            string web_server_directory = UI_ApplicationCache_Gateway.Settings.Servers.Static_Pages_Location + bibid.Substring(0, 2) + "\\" + bibid.Substring(2, 2) + "\\" + bibid.Substring(4, 2) + "\\" + bibid.Substring(6, 2) + "\\" + bibid.Substring(8, 2) + "\\" + vid;
                            if (!Directory.Exists(web_server_directory))
                                Directory.CreateDirectory(web_server_directory);

                            string web_server_file_version = web_server_directory + "\\" + bibid + "_" + vid + ".html";
                            File.Copy(static_file, web_server_file_version, true);

                        }
                        else
                        {
                            errors++;
                            Console.WriteLine(InstanceName + "....Error creating citation file for: " + bibid + ":" + vid);
                            Logger.AddError("....Error creating citation file for: " + bibid + ":" + vid);
                        }
                    }
                    catch (Exception ee)
                    {
                        Console.WriteLine(InstanceName + "....Exception caught while creating citation file for: " + bibid + ":" + vid);
                        Logger.AddError("....Exception caught while creating citation file for: " + bibid + ":" + vid);

                        Console.WriteLine("........." + ee.Message);
                        Logger.AddError("........." + ee.Message);
                        Logger.AddError("........." + ee.StackTrace);
                    }
                }

                Console.WriteLine(InstanceName + "Done rebuilding all item-level citation static pages");
                Logger.AddNonError("Done rebuilding all item-level citation static pages");
                SobekCM_Database.Builder_Add_Log_Entry(PrimaryLogId, String.Empty, "Standard", "Done rebuilding all item-level citation static pages", String.Empty);

            }

            // Set the mode away from the display item mode
            currentMode.Mode = Display_Mode_Enum.Aggregation;
            currentMode.Aggregation_Type = Aggregation_Type_Enum.Home;
            currentMode.Skin = defaultSkin;

            // Get the default web skin
            Web_Skin_Object defaultSkinObject = assistant.Get_HTML_Skin(currentMode, Engine_ApplicationCache_Gateway.Web_Skin_Collection, false, null);

            // Get the list of all collections
            DataTable allCollections = SobekCM_Database.Get_Codes_Item_Aggregations( null);
            DataView collectionView = new DataView(allCollections) {Sort = "Name ASC"};

            // Build the basic site map first
            StreamWriter sitemap_writer = new StreamWriter(staticSobekcmDataLocation + "sitemap_collections.xml", false);
            sitemap_writer.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            sitemap_writer.WriteLine("<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">");
            sitemap_writer.WriteLine("\t<url>");
            sitemap_writer.WriteLine("\t\t<loc>" + primaryWebServerUrl + "</loc>");
            sitemap_writer.WriteLine("\t</url>");

            // Prepare to build all the links to static pages
            StringBuilder static_browse_links = new StringBuilder();
            StringBuilder recent_rss_link_builder = new StringBuilder();
            StringBuilder all_rss_link_builder = new StringBuilder();
            int col = 2;
            DataSet items;
            List<string> processed_codes = new List<string>();
            foreach (DataRowView thisCollectionView in collectionView)
            {
                // Clear the tracer
                tracer.Clear();

                if (!Convert.ToBoolean(thisCollectionView.Row["Hidden"]))
                {
                    // Build the static links pages
                    string code = thisCollectionView.Row["Code"].ToString().ToLower();
                    if ((!processed_codes.Contains(code)) && (code != "all"))
                    {
                        processed_codes.Add(code);

                        // Add this to the sitemap
                        sitemap_writer.WriteLine("\t<url>");
                        sitemap_writer.WriteLine("\t\t<loc>" + primaryWebServerUrl + code + "</loc>");
                        sitemap_writer.WriteLine("\t</url>");

                        Logger.AddNonError(InstanceName + ".....Building static links page for " + code);
                        Console.WriteLine(InstanceName + @"Building static links page for {0}", code);
                        SobekCM_Database.Builder_Add_Log_Entry(PrimaryLogId, String.Empty, "Standard", "Building static links page for " + code, String.Empty);

                        //Get the list of items for this collection
                        items = Engine_Database.Simple_Item_List(code, tracer);

                        // Get the item aggregation object
                        Item_Aggregation aggregation = SobekEngineClient.Aggregations.Get_Aggregation(code.ToLower(), UI_ApplicationCache_Gateway.Settings.System.Default_UI_Language, UI_ApplicationCache_Gateway.Settings.System.Default_UI_Language, tracer);

                        // Build the static browse pages
                        if (Build_All_Browse(aggregation, items))
                        {
                            static_browse_links.Append("<td><a href=\"" + code + "_all.html\">" + code + "</a></td>" + Environment.NewLine);
                            col++;
                        }

                        if (col > 5)
                        {
                            static_browse_links.Append("</tr>" + Environment.NewLine + "<tr>");
                            col = 1;
                        }

                        // Build the RSS feeds
                        Logger.AddNonError(InstanceName + ".....Building RSS feeds for " + code);
                        Console.WriteLine(InstanceName + @"Building RSS feeds for {0}", code);
                        SobekCM_Database.Builder_Add_Log_Entry(PrimaryLogId, String.Empty, "Standard", "Building RSS feeds for " + code, String.Empty);

                        if (Create_RSS_Feed(code, staticSobekcmDataLocation + "rss\\", thisCollectionView.Row["Name"].ToString(), items))
                        {
                            recent_rss_link_builder.Append("<img src=\"http://cdn.sobekrepository.org/images/misc/16px-Feed-icon.svg.png\" alt=\"RSS\" width=\"16\" height=\"16\">&nbsp;<a href=\"" + primaryWebServerUrl + "rss/" + code + "_short_rss.xml\">" + thisCollectionView.Row["Name"] + "</a><br />" + Environment.NewLine);
                            all_rss_link_builder.Append("<img src=\"http://cdn.sobekrepository.org/images/misc/16px-Feed-icon.svg.png\" alt=\"RSS\" width=\"16\" height=\"16\">&nbsp;<a href=\"" + primaryWebServerUrl + "rss/" + code + "_rss.xml\">" + thisCollectionView.Row["Name"] + "</a><br />" + Environment.NewLine);
                        }
                    }
                }
            }

            // Finish out the collection sitemap
            sitemap_writer.WriteLine("</urlset>");
            sitemap_writer.Flush();
            sitemap_writer.Close();

            items = Engine_Database.Simple_Item_List(String.Empty, tracer);
            Logger.AddNonError(InstanceName + ".....Building static links page for ALL ITEMS");
            Console.WriteLine(InstanceName + @"Building static links page for ALL ITEMS");
            SobekCM_Database.Builder_Add_Log_Entry(PrimaryLogId, String.Empty, "Standard", "Building static links page for ALL ITEMS", String.Empty);

            Item_Aggregation allAggregation = SobekEngineClient.Aggregations.Get_Aggregation("all", UI_ApplicationCache_Gateway.Settings.System.Default_UI_Language, UI_ApplicationCache_Gateway.Settings.System.Default_UI_Language, tracer);

            Build_All_Browse(allAggregation, items);

            Console.WriteLine(InstanceName + @"Building RSS feeds ALL ITEMS");
            Logger.AddNonError(InstanceName + ".....Building RSS feeds for ALL ITEMS");
            SobekCM_Database.Builder_Add_Log_Entry(PrimaryLogId, String.Empty, "Standard", "Building RSS feeds for ALL ITEMS", String.Empty);

            Create_RSS_Feed("all", staticSobekcmDataLocation + "rss\\", "All " + UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation + " Items", items);

            // Build the site maps
            Logger.AddNonError(InstanceName + ".....Building site maps");
            Console.WriteLine(InstanceName + @"Building site maps");
            SobekCM_Database.Builder_Add_Log_Entry(PrimaryLogId, String.Empty, "Standard", "Building site maps", String.Empty);

            int sitemaps = Build_Site_Maps();

            // Output the main browse and rss links pages
            Logger.AddNonError(InstanceName + "....Building main sitemaps and links page");
            Console.WriteLine(InstanceName + @"Building main sitemaps and links page");
            SobekCM_Database.Builder_Add_Log_Entry(PrimaryLogId, String.Empty, "Standard", "Building main sitemaps and links page", String.Empty);

            StreamWriter allListWriter = new StreamWriter(staticSobekcmDataLocation + "index.html", false);
            allListWriter.WriteLine("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
            allListWriter.WriteLine("<html xmlns=\"http://www.w3.org/1999/xhtml\" >");
            allListWriter.WriteLine("<head>");
            allListWriter.WriteLine("  <title>" + UI_ApplicationCache_Gateway.Settings.System.System_Name + " Site Map Links</title>");
            allListWriter.WriteLine();
            allListWriter.WriteLine("  <meta name=\"robots\" content=\"index, follow\">");
            allListWriter.WriteLine("  <link href=\"" + primaryWebServerUrl + "default/SobekCM.css\" rel=\"stylesheet\" type=\"text/css\" title=\"standard\" />");
            if (defaultSkinObject.CSS_Style.Length > 0)
            {
                allListWriter.WriteLine("  <link href=\"" + UI_ApplicationCache_Gateway.Settings.Servers.System_Base_URL + defaultSkinObject.CSS_Style + "\" rel=\"stylesheet\" type=\"text/css\" />");
            }

            allListWriter.WriteLine("</head>");
            allListWriter.WriteLine("<body>");

            allListWriter.WriteLine("<div id=\"container-inner\">");

            string banner = "<div id=\"sbkHmw_BannerDiv\"><a alt=\"All Collections\" href=\"" + primaryWebServerUrl + "\" style=\"padding-bottom:0px;margin-bottom:0px\"><img id=\"mainBanner\" src=\"" + primaryWebServerUrl + "design/aggregations/all/images/banners/coll.jpg\" alt=\"\" /></a></div>";
            Display_Header(allListWriter, defaultSkinObject, banner);

            allListWriter.WriteLine("<br /><br />This page is to provide static links to all resources in " + UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation + ". <br />");
            allListWriter.WriteLine("Click <a href=\"" + primaryWebServerUrl + "\">HERE</a> to return to main library. <br />");
            allListWriter.WriteLine("<br />");
            allListWriter.WriteLine("<br />");
            allListWriter.WriteLine("SITE MAPS<br />");
            allListWriter.WriteLine("<br />");
            allListWriter.WriteLine("<a href=\"sitemap_collections.xml\">Map to all the collection home pages</a><br />");
            if (sitemaps > 0)
            {
                for (int i = 1; i <= sitemaps; i++)
                {
                    allListWriter.WriteLine("<a href=\"sitemap" + i + ".xml\">Site Map File " + i + "</a><br />");
                }
                allListWriter.WriteLine("<br />");
                allListWriter.WriteLine("<br />");
            }
            else
            {
                allListWriter.WriteLine("NO SITE MAPS GENERATED!");
            }

            Display_Footer(allListWriter, defaultSkinObject);
            allListWriter.WriteLine("</div>");
            allListWriter.WriteLine("</body>");
            allListWriter.WriteLine("</html>");
            allListWriter.Flush();
            allListWriter.Close();

            // Create the list of all the RSS feeds
            try
            {
                Logger.AddNonError(InstanceName + ".....Building main rss feed page");
                Console.WriteLine(InstanceName + @"Building main rss feed page");
                SobekCM_Database.Builder_Add_Log_Entry(PrimaryLogId, String.Empty, "Standard", "Building main rss feed page", String.Empty);

                StreamWriter writer = new StreamWriter(staticSobekcmDataLocation + "rss\\index.htm", false);
                writer.WriteLine("<!DOCTYPE html>");
                writer.WriteLine("<html>");
                writer.WriteLine("<head>");
                writer.WriteLine("  <title>RSS Feeds for " + UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation + "</title>");
                writer.WriteLine();
                writer.WriteLine("  <meta name=\"robots\" content=\"index, follow\">");
                writer.WriteLine("  <link href=\"" + primaryWebServerUrl + "default/SobekCM.css\" rel=\"stylesheet\" type=\"text/css\" title=\"standard\" />");
                if (defaultSkinObject.CSS_Style.Length > 0)
                {
                    writer.WriteLine("  <link href=\"" + UI_ApplicationCache_Gateway.Settings.Servers.System_Base_URL + defaultSkinObject.CSS_Style + "\" rel=\"stylesheet\" type=\"text/css\" />");
                }
                writer.WriteLine("</head>");
                writer.WriteLine("<body>");

                writer.WriteLine("<div id=\"container-inner\">");

                string banner2 = "<div id=\"sbkHmw_BannerDiv\"><a alt=\"All Collections\" href=\"" + primaryWebServerUrl + "\" style=\"padding-bottom:0px;margin-bottom:0px\"><img id=\"mainBanner\" src=\"" + primaryWebServerUrl + "design/aggregations/all/images/banners/coll.jpg\" alt=\"\" /></a></div>";
                Display_Header(writer, defaultSkinObject, banner2);

                writer.WriteLine("<div id=\"pagecontainer\">");

                writer.WriteLine("<div class=\"ViewsBrowsesRow\">");
                writer.WriteLine("  <ul class=\"sbk_FauxUpwardTabsList\">");
                writer.WriteLine("    <li><a href=\"" + primaryWebServerUrl + "\">" + UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation + " HOME</a></li>");
                writer.WriteLine("    <li class=\"current\">RSS FEEDS</li>");
                writer.WriteLine("  </ul>");
                writer.WriteLine("</div>");
                writer.WriteLine();
                writer.WriteLine("<div class=\"SobekSearchPanel\">");
                writer.WriteLine("  <h1>RSS Feeds for the " + UI_ApplicationCache_Gateway.Settings.System.System_Name + "</h1>");
                writer.WriteLine("</div>");
                writer.WriteLine();

                writer.WriteLine("<div class=\"SobekHomeText\">");
                writer.WriteLine("<table width=\"700\" border=\"0\" align=\"center\">");
                writer.WriteLine("  <tr>");
                writer.WriteLine("    <td>");
                writer.WriteLine("      <br />");
                writer.WriteLine("      This page provides links to RSS feeds for items within " + UI_ApplicationCache_Gateway.Settings.System.System_Name + ".  The first group of RSS feeds below contains the last 20 items added to the collection.  The second group of items contains links to every item in a collection.  These rss feeds can grow quite lengthy and the load time is often non-trivial.<br />");
                writer.WriteLine("      <br />");
                writer.WriteLine("      In addition, the following three RSS feeds are provided:");
                writer.WriteLine("      <blockquote>");
                writer.WriteLine("        <img src=\"http://cdn.sobekrepository.org/images/misc/16px-Feed-icon.svg.png\" alt=\"RSS\" width=\"16\" height=\"16\">&nbsp;<a href=\"" + primaryWebServerUrl + "rss/all_rss.xml\">All items in " + UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation + "</a><br />");
                writer.WriteLine("        <img src=\"http://cdn.sobekrepository.org/images/misc/16px-Feed-icon.svg.png\" alt=\"RSS\" width=\"16\" height=\"16\">&nbsp;<a href=\"" + primaryWebServerUrl + "rss/all_short_rss.xml\">Most recently added items in " + UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation + " (last 100)</a><br />");
                writer.WriteLine("      </blockquote>");
                writer.WriteLine("      RSS feeds	are a way to keep up-to-date on new materials that are added to the Digital Collections. RSS feeds are written in XML    and require a news reader to access.<br />");
                writer.WriteLine("      <br />");
                writer.WriteLine("      You can download and install a <a href=\"http://dmoz.org/Reference/Libraries/Library_and_Information_Science/Technical_Services/Cataloguing/Metadata/RDF/Applications/RSS/News_Readers/\">news reader</a>.  Or, you can use a Web-based reader such as <a href=\"http://www.google.com/reader\">Google Reader </a>or <a href=\"http://my.yahoo.com/\">My Yahoo!</a>.");
                writer.WriteLine("      Follow the instructions in your reader to subscribe to the feed of   your choice. You will usually need to copy and paste the feed URL into the reader. <br />");
                writer.WriteLine("      <br />");
                writer.WriteLine("    </td>");
                writer.WriteLine("  </tr>");
                writer.WriteLine("</table>");

                writer.WriteLine("<table width=\"750\" border=\"0\" align=\"center\" cellpadding=\"1\" cellspacing=\"0\">");
                writer.WriteLine("	<tr>");
                writer.WriteLine("    <td bgcolor=\"#cccccc\">");
                writer.WriteLine("      <table width=\"100%\" border=\"0\" align=\"center\" cellpadding=\"2\" cellspacing=\"0\">");
                writer.WriteLine("		  <tr>");
                writer.WriteLine("          <td bgcolor=\"#f4f4f4\"><span class=\"groupname\"><span class=\"groupnamecaps\"> &nbsp; M</span>OST <span class=\"groupnamecaps\">R</span>ECENT <span class=\"groupnamecaps\">I</span>TEMS (BY COLLECTION)</span></td>");
                writer.WriteLine("        </tr>");
                writer.WriteLine("      </table>");
                writer.WriteLine("    </td>");
                writer.WriteLine("  </tr>");
                writer.WriteLine("<table>");

                writer.WriteLine("<div class=\"SobekHomeText\">");
                writer.WriteLine("<table width=\"700\" border=\"0\" align=\"center\">");
                writer.WriteLine("  <tr>");
                writer.WriteLine("    <td>");
                writer.WriteLine(recent_rss_link_builder.ToString());
                writer.WriteLine("      <br />");
                writer.WriteLine("    </td>");
                writer.WriteLine("  </tr>");
                writer.WriteLine("</table>");

                writer.WriteLine("<table width=\"750\" border=\"0\" align=\"center\" cellpadding=\"1\" cellspacing=\"0\">");
                writer.WriteLine("	<tr>");
                writer.WriteLine("    <td bgcolor=\"#cccccc\">");
                writer.WriteLine("      <table width=\"100%\" border=\"0\" align=\"center\" cellpadding=\"2\" cellspacing=\"0\">");
                writer.WriteLine("		  <tr>");
                writer.WriteLine("          <td bgcolor=\"#f4f4f4\"><span class=\"groupname\"><span class=\"groupnamecaps\"> &nbsp; A</span>LL <span class=\"groupnamecaps\">I</span>TEMS (BY COLLECTION) </span></td>");
                writer.WriteLine("        </tr>");
                writer.WriteLine("      </table>");
                writer.WriteLine("    </td>");
                writer.WriteLine("  </tr>");
                writer.WriteLine("<table>");

                writer.WriteLine("<div class=\"SobekHomeText\">");
                writer.WriteLine("<table width=\"700\" border=\"0\" align=\"center\">");
                writer.WriteLine("  <tr>");
                writer.WriteLine("    <td>");
                writer.WriteLine(all_rss_link_builder.ToString());
                writer.WriteLine("      <br />");
                writer.WriteLine("    </td>");
                writer.WriteLine("  </tr>");
                writer.WriteLine("</table>");

                writer.WriteLine("<br />");

                writer.WriteLine("</div>");
                writer.WriteLine("</div>");
                Display_Footer(writer, defaultSkinObject);
                writer.WriteLine("</div>");
                writer.WriteLine("</body>");
                writer.WriteLine("</html>");

                writer.Flush();
                writer.Close();
            }
            catch
            {
                Logger.AddError("ERROR BUILDING RSS INDEX.HTM FILE");
                Console.WriteLine(@"Error building RSS index.htm file");
                SobekCM_Database.Builder_Add_Log_Entry(PrimaryLogId, String.Empty, "Error", "Error building the main RSS feed page", String.Empty);

            }

            return errors;
        }
        /// <summary> Create the static HTML citation page for a single digital resource </summary>
        /// <param name="BIBID"> Bibliographic identifier for the digital resource </param>
        /// <param name="VID"> Volume idenfitier for the digital resource </param>
        /// <param name="Static_FileName"> Name of the resulting html file </param>
        /// <param name="Text_File_Directory"> Directory where any text files may exist for this resource </param>
        /// <param name="Item_List"> Item lookup object </param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        /// <remarks> THis is generally called by the SobekCM Builder windows application/scheduled task</remarks>
        public bool Create_Item_Citation_HTML(string BIBID, string VID, string Static_FileName, string Text_File_Directory, Item_Lookup_Object Item_List )
        {
            // Clear the current tracer
            tracer.Clear();

            // Set the item for the current mode
            currentMode.BibID = BIBID;
            currentMode.VID = VID;
            currentMode.ViewerCode = "citation";
            currentMode.Skin = defaultSkin;
            currentMode.Mode = Display_Mode_Enum.Item_Display;
            currentMode.Language = Web_Language_Enum.English;
            currentMode.Trace_Flag = Trace_Flag_Type_Enum.No;

            // Get the item
            SobekCM_Item currentItem;
            Page_TreeNode currentPage;
            SobekCM_Items_In_Title itemsInTitle;
            assistant.Get_Item(String.Empty, currentMode, Item_List, UI_ApplicationCache_Gateway.Settings.Servers.Image_URL, UI_ApplicationCache_Gateway.Icon_List, null, tracer, null, out currentItem, out currentPage, out itemsInTitle);
            if (currentItem == null)
                return false;

            if (currentItem.Behaviors.Aggregation_Count > 0)
                currentMode.Aggregation = currentItem.Behaviors.Aggregations[0].Code;

            // Get the current page
            int current_page_index = currentMode.Page.HasValue ? Math.Max(currentMode.Page.Value, ((ushort)1)) : 1;
            currentPage = SobekCM_Item_Factory.Get_Current_Page(currentItem, current_page_index, tracer);

            // Finish writing this
            Finish_writing_html(currentItem, currentPage, Static_FileName, Text_File_Directory);

            return true;
        }
        /// <summary> Creates the static MarcXML file for a digital resource </summary>
        /// <param name="BIBID"> Bibliographic identifier ( BibID )</param>
        /// <param name="VID"> Volume identifier ( VID ) </param>
        /// <param name="DestinationDirectory"> Directory where the resultant MarcXML file should be written </param>
        /// <param name="Item_List"> Item lookup object </param>
        /// <returns>  This will read the currently live METS file and build the digital object with additional
        /// information from the database before writing the MarcXML file </returns>
        public bool Create_MarcXML_File(string BIBID, string VID, string DestinationDirectory, Item_Lookup_Object Item_List )
        {
            // Clear the current tracer
            tracer.Clear();

            try
            {

                // Set the item for the current mode
                currentMode.BibID = BIBID;
                currentMode.VID = VID;
                currentMode.ViewerCode = "citation";
                currentMode.Skin = "";
                currentMode.Mode = Display_Mode_Enum.Item_Display;
                currentMode.Language = Web_Language_Enum.English;
                currentMode.Trace_Flag = Trace_Flag_Type_Enum.No;

                // Get the item
                SobekCM_Item currentItem;
                Page_TreeNode currentPage;
                SobekCM_Items_In_Title itemsInTitle;
                assistant.Get_Item(String.Empty, currentMode, Item_List, UI_ApplicationCache_Gateway.Settings.Servers.Image_URL, UI_ApplicationCache_Gateway.Icon_List, null, tracer, null, out currentItem, out currentPage, out itemsInTitle);
                currentMode.Aggregation = String.Empty;
                if (currentItem == null)
                    return false;

                if (currentItem.Behaviors.Aggregation_Count > 0)
                    currentMode.Aggregation = currentItem.Behaviors.Aggregations[0].Code;

                string marcFile = DestinationDirectory + currentItem.Web.File_Root + "\\" + currentItem.VID + "\\marc.xml";

                // Create the options dictionary used when saving information to the database, or writing MarcXML
                Dictionary<string, object> options = new Dictionary<string, object>();
                if (UI_ApplicationCache_Gateway.Settings.MarcGeneration != null)
                {
                    options["MarcXML_File_ReaderWriter:MARC Cataloging Source Code"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Cataloging_Source_Code;
                    options["MarcXML_File_ReaderWriter:MARC Location Code"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Location_Code;
                    options["MarcXML_File_ReaderWriter:MARC Reproduction Agency"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Reproduction_Agency;
                    options["MarcXML_File_ReaderWriter:MARC Reproduction Place"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.Reproduction_Place;
                    options["MarcXML_File_ReaderWriter:MARC XSLT File"] = UI_ApplicationCache_Gateway.Settings.MarcGeneration.XSLT_File;
                }
                options["MarcXML_File_ReaderWriter:System Name"] = UI_ApplicationCache_Gateway.Settings.System.System_Name;
                options["MarcXML_File_ReaderWriter:System Abbreviation"] = UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation;

                MarcXML_File_ReaderWriter marcWriter = new MarcXML_File_ReaderWriter();
                string errorMessage;
                return marcWriter.Write_Metadata(marcFile, currentItem, options, out errorMessage);
            }
            catch
            {
                return false;
            }
        }
        /// <summary> Find the static html file to display for an item view request, when requested by a search engine robot for indexing </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <returns> Location for the static html file to display for this item view request </returns>
        public string Get_Item_Static_HTML(Navigation_Object Current_Mode, Item_Lookup_Object All_Items_Lookup, Custom_Tracer Tracer)
        {
            // Must at least have a bib id of the proper length
            if (Current_Mode.BibID.Length < 10)
            {
                Current_Mode.Invalid_Item = true;
                return String.Empty;
            }

            // Get the title object for this
            Multiple_Volume_Item dbTitle = All_Items_Lookup.Title_By_Bib(Current_Mode.BibID);
            if (dbTitle == null)
            {
                Current_Mode.Invalid_Item = true;
                return String.Empty;
            }

            // Try to get the very basic information about this item, to determine if the
            // bib / vid combination is valid
            Single_Item selected_item = null;
            if (Current_Mode.VID.Length > 0)
            {
                selected_item = All_Items_Lookup.Item_By_Bib_VID(Current_Mode.BibID, Current_Mode.VID, Tracer);
            }
            else
            {
                if (dbTitle.Item_Count == 1)
                {
                    selected_item = All_Items_Lookup.Item_By_Bib_Only(Current_Mode.BibID);
                }
            }

            // If no valid item and not a valid item group display either, return
            if (selected_item == null)
            {
                Current_Mode.Invalid_Item = true;
                return String.Empty;
            }

            // Set the title to the info browse, just to store it somewhere
            Current_Mode.Info_Browse_Mode = selected_item.Title;

            // Get the text for this item
            string bibid = Current_Mode.BibID;
            string vid = selected_item.VID.PadLeft(5, '0');
            Current_Mode.VID = vid;
            string base_image_url = UI_ApplicationCache_Gateway.Settings.Servers.Base_Data_Directory + bibid.Substring(0, 2) + "\\" + bibid.Substring(2, 2) + "\\" + bibid.Substring(4, 2) + "\\" + bibid.Substring(6, 2) + "\\" + bibid.Substring(8, 2) + "\\" + bibid + "_" + vid + ".html";
            return base_image_url;
        }
        /// <summary> Performs a search ( or retrieves the search results from the cache ) and outputs the results and search url used  </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Aggregation_Object"> Object for the current aggregation object, against which this search is performed </param>
        /// <param name="Search_Stop_Words"> List of search stop workds </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <param name="Complete_Result_Set_Info"> [OUT] Information about the entire set of results </param>
        /// <param name="Paged_Results"> [OUT] List of search results for the requested page of results </param>
        public void Get_Search_Results(Navigation_Object Current_Mode,
                                       Item_Lookup_Object All_Items_Lookup,
                                       Item_Aggregation Aggregation_Object, 
                                       List<string> Search_Stop_Words,
                                       Custom_Tracer Tracer,
                                       out Search_Results_Statistics Complete_Result_Set_Info,
                                       out List<iSearch_Title_Result> Paged_Results )
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("SobekCM_Assistant.Get_Search_Results", String.Empty);
            }

            // Set output initially to null
            Paged_Results = null;
            Complete_Result_Set_Info = null;

            // Get the sort
            int sort = Current_Mode.Sort.HasValue ? Math.Max(Current_Mode.Sort.Value, ((ushort)1)) : 0;
            if ((sort != 0) && (sort != 1) && (sort != 2) && (sort != 10) && (sort != 11))
                sort = 0;

            // Depending on type of search, either go to database or Greenstone
            if (Current_Mode.Search_Type == Search_Type_Enum.Map)
            {
                // If this is showing in the map, only allow sot zero, which is by coordinates
                if ((Current_Mode.Result_Display_Type == Result_Display_Type_Enum.Map) || (Current_Mode.Result_Display_Type == Result_Display_Type_Enum.Default))
                {
                    Current_Mode.Sort = 0;
                    sort = 0;
                }

                try
                {
                    double lat1 = 1000;
                    double long1 = 1000;
                    double lat2 = 1000;
                    double long2 = 1000;
                    string[] terms = Current_Mode.Coordinates.Split(",".ToCharArray());
                    if (terms.Length < 2)
                    {
                        Current_Mode.Mode = Display_Mode_Enum.Search;
                        UrlWriterHelper.Redirect(Current_Mode);
                        return;
                    }
                    if (terms.Length < 4)
                    {
                        lat1 = Convert.ToDouble(terms[0]);
                        lat2 = lat1;
                        long1 = Convert.ToDouble(terms[1]);
                        long2 = long1;
                    }
                    if (terms.Length >= 4)
                    {
                        if (terms[0].Length > 0)
                            lat1 = Convert.ToDouble(terms[0]);
                        if (terms[1].Length > 0)
                            long1 = Convert.ToDouble(terms[1]);
                        if (terms[2].Length > 0)
                            lat2 = Convert.ToDouble(terms[2]);
                        if (terms[3].Length > 0)
                            long2 = Convert.ToDouble(terms[3]);
                    }

                    // If neither point is valid, return
                    if (((lat1 == 1000) || (long1 == 1000)) && ((lat2 == 1000) || (long2 == 1000)))
                    {
                        Current_Mode.Mode = Display_Mode_Enum.Search;
                        UrlWriterHelper.Redirect(Current_Mode);
                        return;
                    }

                    // If just the first point is valid, use that
                    if ((lat2 == 1000) || (long2 == 1000))
                    {
                        lat2 = lat1;
                        long2 = long1;
                    }

                    // If just the second point is valid, use that
                    if ((lat1 == 1000) || (long1 == 1000))
                    {
                        lat1 = lat2;
                        long1 = long2;
                    }

                    // Perform the search against the database
                    try
                    {
                        // Get the page count in the results
                        int current_page_index = Current_Mode.Page.HasValue ? Math.Max(Current_Mode.Page.Value, ((ushort)1)) : 1;

                        // Try to pull more than one page, so we can cache the next page or so
                        Multiple_Paged_Results_Args returnArgs = Engine_Database.Get_Items_By_Coordinates(Current_Mode.Aggregation, lat1, long1, lat2, long2, false, 20, current_page_index, sort, false, new List<short>(), true, Tracer);
                        List<List<iSearch_Title_Result>> pagesOfResults = returnArgs.Paged_Results;
                        Complete_Result_Set_Info = returnArgs.Statistics;

                        if ((pagesOfResults != null) && (pagesOfResults.Count > 0))
                            Paged_Results = pagesOfResults[0];
                    }
                    catch (Exception ee)
                    {
                        // Next, show the message to the user
                        Current_Mode.Mode = Display_Mode_Enum.Error;
                        string error_message = ee.Message;
                        if (error_message.ToUpper().IndexOf("TIMEOUT") >= 0)
                        {
                            error_message = "Database Timeout Occurred<br /><br />Try again in a few minutes.<br /><br />";
                        }
                        Current_Mode.Error_Message = error_message;
                        Current_Mode.Caught_Exception = ee;
                    }
                }
                catch
                {
                    Current_Mode.Mode = Display_Mode_Enum.Search;
                    UrlWriterHelper.Redirect(Current_Mode);
                }
            }
            else
            {
                List<string> terms = new List<string>();
                List<string> web_fields = new List<string>();

                // Split the terms correctly ( only use the database stop words for the split if this will go to the database ultimately)
                if ((Current_Mode.Search_Type == Search_Type_Enum.Full_Text) || (Current_Mode.Search_Fields.IndexOf("TX") >= 0))
                {
                    Split_Clean_Search_Terms_Fields(Current_Mode.Search_String, Current_Mode.Search_Fields, Current_Mode.Search_Type, terms, web_fields, null, Current_Mode.Search_Precision, ',');
                }
                else
                {
                    Split_Clean_Search_Terms_Fields(Current_Mode.Search_String, Current_Mode.Search_Fields, Current_Mode.Search_Type, terms, web_fields, Search_Stop_Words, Current_Mode.Search_Precision, ',');
                }

                // Get the count that will be used
                int actualCount = Math.Min(terms.Count, web_fields.Count);

                // Determine if this is a special search type which returns more rows and is not cached.
                // This is used to return the results as XML and DATASET
                bool special_search_type = false;
                int results_per_page = 20;
                if ((Current_Mode.Writer_Type == Writer_Type_Enum.XML) || (Current_Mode.Writer_Type == Writer_Type_Enum.DataSet))
                {
                    results_per_page = 1000000;
                    special_search_type = true;
                    sort = 2; // Sort by BibID always for these
                }

                // Determine if a date range was provided
                long date1 = -1;
                long date2 = -1;
                if (Current_Mode.DateRange_Date1.HasValue)
                {
                    date1 = Current_Mode.DateRange_Date1.Value;
                    if (Current_Mode.DateRange_Date2.HasValue)
                    {
                        if (Current_Mode.DateRange_Date2.Value >= Current_Mode.DateRange_Date1.Value)
                            date2 = Current_Mode.DateRange_Date2.Value;
                        else
                        {
                            date1 = Current_Mode.DateRange_Date2.Value;
                            date2 = Current_Mode.DateRange_Date1.Value;
                        }
                    }
                    else
                    {
                        date2 = date1;
                    }
                }
                if (date1 < 0)
                {
                    if ((Current_Mode.DateRange_Year1.HasValue ) && ( Current_Mode.DateRange_Year1.Value > 0 ))
                    {
                        DateTime startDate = new DateTime(Current_Mode.DateRange_Year1.Value, 1, 1);
                        TimeSpan timeElapsed = startDate.Subtract(new DateTime(1, 1, 1));
                        date1 = (long)timeElapsed.TotalDays;
                        if ((Current_Mode.DateRange_Year2.HasValue) && (Current_Mode.DateRange_Year2.Value > 0))
                        {
                            startDate = new DateTime(Current_Mode.DateRange_Year2.Value, 12, 31);
                            timeElapsed = startDate.Subtract(new DateTime(1, 1, 1));
                            date2 = (long)timeElapsed.TotalDays;
                        }
                        else
                        {
                            startDate = new DateTime(Current_Mode.DateRange_Year1.Value, 12, 31);
                            timeElapsed = startDate.Subtract(new DateTime(1, 1, 1));
                            date2 = (long) timeElapsed.TotalDays;
                        }
                    }
                }

                // Set the flags for how much data is needed.  (i.e., do we need to pull ANYTHING?  or
                // perhaps just the next page of results ( as opposed to pulling facets again).
                bool need_search_statistics = true;
                bool need_paged_results = true;
                if (!special_search_type)
                {
                    // Look to see if the search statistics are available on any cache..
                    Complete_Result_Set_Info = CachedDataManager.Retrieve_Search_Result_Statistics(Current_Mode, actualCount, web_fields, terms, date1, date2, Tracer);
                    if (Complete_Result_Set_Info != null)
                        need_search_statistics = false;

                    // Look to see if the paged results are available on any cache..
                    Paged_Results = CachedDataManager.Retrieve_Search_Results(Current_Mode, sort, actualCount, web_fields, terms, date1, date2, Tracer);
                    if (Paged_Results != null)
                        need_paged_results = false;
                }

                // If both were retrieved, do nothing else
                if ((need_paged_results) || (need_search_statistics))
                {
                    // Should this pull the search from the database, or from greenstone?
                    if ((Current_Mode.Search_Type == Search_Type_Enum.Full_Text) || (Current_Mode.Search_Fields.IndexOf("TX") >= 0))
                    {
                        try
                        {
                            // Get the page count in the results
                            int current_page_index = Current_Mode.Page.HasValue ? Math.Max(Current_Mode.Page.Value, ((ushort)1)) : 1;

                            // Perform the search against greenstone
                            Search_Results_Statistics recomputed_search_statistics;
                            Perform_Solr_Search(Tracer, terms, web_fields, actualCount, Current_Mode.Aggregation, current_page_index, sort, results_per_page, out recomputed_search_statistics, out Paged_Results);
                            if (need_search_statistics)
                                Complete_Result_Set_Info = recomputed_search_statistics;
                        }
                        catch (Exception ee)
                        {
                            Current_Mode.Mode = Display_Mode_Enum.Error;
                            Current_Mode.Error_Message = "Unable to perform search at this time";
                            Current_Mode.Caught_Exception = ee;
                        }

                        // If this was a special search, don't cache this
                        if (!special_search_type)
                        {
                            // Cache the search statistics, if it was needed
                            if ((need_search_statistics) && (Complete_Result_Set_Info != null))
                            {
                                CachedDataManager.Store_Search_Result_Statistics(Current_Mode, actualCount, web_fields, terms, date1, date2, Complete_Result_Set_Info, Tracer);
                            }

                            // Cache the search results
                            if ((need_paged_results) && (Paged_Results != null))
                            {
                                CachedDataManager.Store_Search_Results(Current_Mode, sort, actualCount, web_fields, terms, date1, date2, Paged_Results, Tracer);
                            }
                        }
                    }
                    else
                    {
                        // Try to pull more than one page, so we can cache the next page or so
                        List<List<iSearch_Title_Result>> pagesOfResults = new List<List<iSearch_Title_Result>>();

                        // Perform the search against the database
                        try
                        {
                            Search_Results_Statistics recomputed_search_statistics;
                            Perform_Database_Search(Tracer, terms, web_fields, date1, date2, actualCount, Current_Mode, sort, Aggregation_Object, All_Items_Lookup, results_per_page, !special_search_type, out recomputed_search_statistics, out pagesOfResults, need_search_statistics);
                            if (need_search_statistics)
                                Complete_Result_Set_Info = recomputed_search_statistics;

                            if ((pagesOfResults != null) && (pagesOfResults.Count > 0))
                                Paged_Results = pagesOfResults[0];
                        }
                        catch (Exception ee)
                        {
                            // Next, show the message to the user
                            Current_Mode.Mode = Display_Mode_Enum.Error;
                            string error_message = ee.Message;
                            if (error_message.ToUpper().IndexOf("TIMEOUT") >= 0)
                            {
                                error_message = "Database Timeout Occurred<br /><br />Try narrowing your search by adding more terms <br />or putting quotes around your search.<br /><br />";
                            }
                            Current_Mode.Error_Message = error_message;
                            Current_Mode.Caught_Exception = ee;
                        }

                        // If this was a special search, don't cache this
                        if (!special_search_type)
                        {
                            // Cache the search statistics, if it was needed
                            if ((need_search_statistics) && (Complete_Result_Set_Info != null))
                            {
                                CachedDataManager.Store_Search_Result_Statistics(Current_Mode, actualCount, web_fields, terms, date1, date2, Complete_Result_Set_Info, Tracer);
                            }

                            // Cache the search results
                            if ((need_paged_results) && (pagesOfResults != null))
                            {
                                CachedDataManager.Store_Search_Results(Current_Mode, sort, actualCount, web_fields, terms, date1, date2, pagesOfResults, Tracer);
                            }
                        }
                    }
                }
            }

            ////create search results json object and place into session state
            //DataTable TEMPsearchResults = new DataTable();
            //TEMPsearchResults.Columns.Add("BibID", typeof(string));
            //TEMPsearchResults.Columns.Add("Spatial_Coordinates", typeof(string));
            //foreach (iSearch_Title_Result searchTitleResult in Paged_Results)
            //{
            //	TEMPsearchResults.Rows.Add(searchTitleResult.BibID, searchTitleResult.Spatial_Coordinates);
            //}
            //HttpContext.Current.Session["TEMPSearchResultsJSON"] = Google_Map_ResultsViewer_Beta.Create_JSON_Search_Results_Object(TEMPsearchResults);
        }
        /// <summary> Get a digital resource for display or for editing </summary>
        /// <param name="Collection_Code"> Collection code to which this item must belong </param>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Base_URL"> Base URL for all the digital resource files for items to display </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="Current_User"> Currently logged on user information (used when editing an item)</param>
        /// <param name="Item_Viewer_Priority"> List of the globally defined item viewer priorities </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <param name="Current_Item"> [OUT] Built single digital resource ready for displaying or editing </param>
        /// <param name="Current_Page"> [OUT] Build current page for display </param>
        /// <param name="Items_In_Title"> [OUT] List of all the items in this title </param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        /// <remarks> This attempts to pull the objects from the cache.  If unsuccessful, it builds the objects from the
        /// database and hands off to the <see cref="CachedDataManager" /> to store in the cache.  If the item must be 
        /// built from scratch, the <see cref="SobekCM_Item_Factory"/> class is utilized. </remarks>
        public bool Get_Item(string Collection_Code, 
                             Navigation_Object Current_Mode, 
                             Item_Lookup_Object All_Items_Lookup, 
                             string Base_URL, 
                             Dictionary<string, Wordmark_Icon> Icon_Table, 
							 List<string> Item_Viewer_Priority,
							 Custom_Tracer Tracer, 
                             User_Object Current_User,
                             out SobekCM_Item Current_Item,
                             out Page_TreeNode Current_Page,
                             out SobekCM_Items_In_Title Items_In_Title)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("SobekCM_Assistant.Get_Item", String.Empty);
            }

            // Initially assign nulls
            Current_Item = null;
            Current_Page = null;
            Items_In_Title = null;

            // Check for legacy reference by itemid
            if ((Current_Mode.BibID.Length == 0) && (Current_Mode.ItemID_DEPRECATED.HasValue))
            {
                DataRow thisRowInfo = SobekCM_Database.Lookup_Item_By_ItemID(Current_Mode.ItemID_DEPRECATED.Value, Tracer);
                if (thisRowInfo == null)
                {
                    Current_Mode.Invalid_Item = true;
                    return false;
                }

                Current_Mode.Mode = Display_Mode_Enum.Legacy_URL;
                Current_Mode.Error_Message = Current_Mode.Base_URL + thisRowInfo["BibID"] + "/" + thisRowInfo["VID"];
                return false;
            }

            // Must at least have a bib id of the proper length
            if (Current_Mode.BibID.Length < 10)
            {
                Current_Mode.Invalid_Item = true;
                return false;
            }

            // Get the title object for this
            bool item_group_display = false;
            Multiple_Volume_Item dbTitle = All_Items_Lookup.Title_By_Bib(Current_Mode.BibID);
            if (dbTitle == null)
            {
                Current_Mode.Invalid_Item = true;
                return false;
            }

            // Try to get the very basic information about this item, to determine if the
            // bib / vid combination is valid
            Single_Item selected_item = null;

            // Certain mySobek modes only need the item group
            if (( Current_Mode.Mode == Display_Mode_Enum.My_Sobek ) && (( Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Edit_Group_Behaviors ) || ( Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Edit_Group_Serial_Hierarchy ) || ( Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Group_Add_Volume ) || ( Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Group_AutoFill_Volumes ) || ( Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Group_Mass_Update_Items )))
            {
                item_group_display = true;
            }

            // If this is not a mode that is only item group display, try to pull the item
            if (!item_group_display)
            {
                if (( !String.IsNullOrEmpty(Current_Mode.VID)) && (Current_Mode.VID != "00000"))
                {
                    selected_item = All_Items_Lookup.Item_By_Bib_VID(Current_Mode.BibID, Current_Mode.VID, Tracer);
                }
                else
                {
                    if ((dbTitle.Item_Count == 1) && (( String.IsNullOrEmpty(Current_Mode.VID)) || ( Current_Mode.VID != "00000")))
                    {
                        selected_item = All_Items_Lookup.Item_By_Bib_Only(Current_Mode.BibID);
                    }
                    else
                    {
                        item_group_display = true;
                    }
                }
            }

            // If no valid item and not a valid item group display either, return
            if ((selected_item == null) && (!item_group_display))
            {
                Current_Mode.Invalid_Item = true;
                return false;
            }

            // If this is for a single item, return that
            if (selected_item != null)
            {
                // Make sure the VID is set
                Current_Mode.VID = selected_item.VID;

                // Try to get this from the cache
                if ((Current_Mode.Mode == Display_Mode_Enum.My_Sobek) && ( Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Edit_Item_Metadata ) && (Current_User != null))
                    Current_Item = CachedDataManager.Retrieve_Digital_Resource_Object(Current_User.UserID, Current_Mode.BibID, Current_Mode.VID, Tracer);
                else
                    Current_Item = CachedDataManager.Retrieve_Digital_Resource_Object( Current_Mode.BibID, Current_Mode.VID, Tracer);

                // If not pulled from the cache, then we will have to build the item
                if (Current_Item == null)
                {
                    if (Tracer != null)
                    {
                        Tracer.Add_Trace("SobekCM_Assistant.Get_Item", "Build the item");
                    }

                    Current_Item = SobekCM_Item_Factory.Get_Item(Current_Mode.BibID, Current_Mode.VID, Icon_Table, Item_Viewer_Priority, Tracer);
                    if (Current_Item != null)
                    {
                        if ((Current_Mode.Mode == Display_Mode_Enum.My_Sobek) && (Current_Mode.My_Sobek_Type == My_Sobek_Type_Enum.Edit_Item_Metadata) && (Current_User != null))
                        {
                            string note_to_add = "Online edit by " + Current_User.Full_Name + " ( " + DateTime.Now.ToShortDateString() + " )";
                            Current_Item.METS_Header.Add_Creator_Individual_Notes( note_to_add );
                            CachedDataManager.Store_Digital_Resource_Object(Current_User.UserID, Current_Mode.BibID, Current_Mode.VID, Current_Item, Tracer);
                        }
                        else
                            CachedDataManager.Store_Digital_Resource_Object(Current_Mode.BibID, Current_Mode.VID, Current_Item, Tracer);
                    }
                }
                else
                {
                    if (Tracer != null)
                    {
                        Tracer.Add_Trace("SobekCM_Assistant.Get_Item", "Item found in the cache");
                    }
                }

                // If an item was requested and none was found, go to the current home
                if ((Current_Item == null))
                {
                    if (Tracer != null && !Tracer.Enabled)
                    {
                        Current_Mode.Mode = Display_Mode_Enum.Aggregation;
                        Current_Mode.Aggregation_Type = Aggregation_Type_Enum.Home;
                        return false;
                    }
                    return false;
                }

                // Get the page to display (printing has its own specification of page(s) to display)
                if (Current_Mode.Mode != Display_Mode_Enum.Item_Print)
                {
                    if (Tracer != null)
                    {
                        Tracer.Add_Trace("SobekCM_Assistant.Get_Item", "Get the current page");
                    }

                    // Get the page count in the results
                    int current_page_index = Current_Mode.Page.HasValue ? Math.Max(Current_Mode.Page.Value, ((ushort)1)) : 1;
                    Current_Page = SobekCM_Item_Factory.Get_Current_Page(Current_Item, current_page_index, Tracer);
                }
            }
            else
            {
                // Try to get this from the cache
                Current_Item = CachedDataManager.Retrieve_Digital_Resource_Object(Current_Mode.BibID, Tracer);

                // Have to build this item group information then
                if (Current_Item == null)
                {
                    string bibID = Current_Mode.BibID;
                    SobekCM_Item_Factory.Get_Item_Group(bibID, Tracer, out Items_In_Title, out Current_Item );
                    if (Tracer != null)
                    {
                        Tracer.Add_Trace("SobekCM_Assistant.Get_Item", "TEST LOG ENTRY");
                    }

                    if (Current_Item == null)
                    {
                        Exception ee = SobekCM_Database.Last_Exception;
                        if (Tracer != null)
                            Tracer.Add_Trace("SobekCM_Assistant.Get_Item", ee != null ? ee.Message : "NO DATABASE EXCEPTION", Custom_Trace_Type_Enum.Error);

                        Current_Mode.Invalid_Item = true;
                        return false;
                    }

                    // Put this back on the cache
                    Current_Item.METS_Header.RecordStatus_Enum = METS_Record_Status.BIB_LEVEL;
                    CachedDataManager.Store_Digital_Resource_Object(bibID, Current_Item, Tracer);
                    CachedDataManager.Store_Items_In_Title(bibID, Items_In_Title, Tracer);
                }
            }

            return true;
        }
        /// <summary> Get a digital resource for display or for editing </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="All_Items_Lookup"> Lookup object used to pull basic information about any item loaded into this library </param>
        /// <param name="Base_URL"> Base URL for all the digital resource files for items to display </param>
        /// <param name="Icon_Table"> Dictionary of all the wordmark/icons which can be tagged to the items </param>
        /// <param name="Item_Viewer_Priority"> List of the globally defined item viewer priorities  </param>
        /// <param name="Current_User"> Currently logged on user information (used when editing an item)</param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <param name="Current_Item"> [OUT] Built single digital resource ready for displaying or editing </param>
        /// <param name="Current_Page"> [OUT] Build current page for display </param>
        /// <param name="Items_In_Title"> [OUT] List of all the items in this title </param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        /// <remarks> This attempts to pull the objects from the cache.  If unsuccessful, it builds the objects from the
        /// database and hands off to the <see cref="CachedDataManager" /> to store in the cache.  If the item must be 
        /// built from scratch, the <see cref="SobekCM_Item_Factory"/> class is utilized. </remarks>
        public bool Get_Item(Navigation_Object Current_Mode,
                             Item_Lookup_Object All_Items_Lookup,
                             string Base_URL, 
                             Dictionary<string, Wordmark_Icon> Icon_Table,
							 List<string> Item_Viewer_Priority,
							 User_Object Current_User,
                             Custom_Tracer Tracer, 
                             out SobekCM_Item Current_Item, 
                             out Page_TreeNode Current_Page,
                             out SobekCM_Items_In_Title Items_In_Title )
        {
            return Get_Item(String.Empty, Current_Mode, All_Items_Lookup, Base_URL, Icon_Table, Item_Viewer_Priority, Tracer, Current_User, out Current_Item, out Current_Page, out Items_In_Title);
        }
        private void Perform_Database_Search(Custom_Tracer Tracer, List<string> Terms, List<string> Web_Fields, long Date1, long Date2, int ActualCount, Navigation_Object Current_Mode, int Current_Sort, Item_Aggregation Aggregation_Object, Item_Lookup_Object All_Items_Lookup, int Results_Per_Page, bool Potentially_Include_Facets, out Search_Results_Statistics Complete_Result_Set_Info, out List<List<iSearch_Title_Result>> Paged_Results, bool Need_Search_Statistics)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("SobekCM_Assistant.Perform_Database_Search", "Query the database for search results");
            }

            // Get the list of facets first
            List<short> facetsList = Aggregation_Object.Facets;
            if (!Potentially_Include_Facets)
                facetsList.Clear();

            // Set the return values to NULL initially
            Complete_Result_Set_Info = null;

            const bool INCLUDE_PRIVATE = false;

            // Special code for searching by bibid, oclc, or aleph
            if (ActualCount == 1)
            {
                // Is this a BIBID search?
                if ((Web_Fields[0] == "BI") && ( Terms[0].IndexOf("*") < 0 ) && ( Terms[0].Length >= 10 ))
                {
                    string bibid = Terms[0].ToUpper();
                    string vid = String.Empty;
                    if (bibid.Length > 10)
                    {
                        if ((bibid.IndexOf("_") == 10) && ( bibid.Length > 11 ))
                        {
                            vid = bibid.Substring(11).PadLeft(5, '0');
                            bibid = bibid.Substring(0, 10);
                        }
                        else if ((bibid.IndexOf(":") == 10) && ( bibid.Length > 11 ))
                        {
                            vid = bibid.Substring(11).PadLeft(5, '0');
                            bibid = bibid.Substring(0, 10);
                        }
                        else if (bibid.Length == 15)
                        {
                            vid = bibid.Substring(10);
                            bibid = bibid.Substring(0, 10);
                        }
                    }

                    if (bibid.Length == 10)
                    {
                        if (vid.Length == 5)
                        {
                            if (All_Items_Lookup.Contains_BibID_VID(bibid, vid))
                            {
                                string redirect_url = Current_Mode.Base_URL + bibid + "/" + vid;
                                if ( Current_Mode.Writer_Type == Writer_Type_Enum.HTML_LoggedIn )
                                    redirect_url = Current_Mode.Base_URL + "l/" + bibid + "/" + vid;
                                HttpContext.Current.Response.Redirect(redirect_url, false);
                                HttpContext.Current.ApplicationInstance.CompleteRequest();
                                Current_Mode.Request_Completed = true;
                                Paged_Results = null;
                                return;
                            }
                        }
                        else
                        {
                            if (All_Items_Lookup.Contains_BibID(bibid))
                            {
                                string redirect_url = Current_Mode.Base_URL + bibid;
                                if (Current_Mode.Writer_Type == Writer_Type_Enum.HTML_LoggedIn)
                                    redirect_url = Current_Mode.Base_URL + "l/" + bibid;
                                HttpContext.Current.Response.Redirect(redirect_url, false);
                                HttpContext.Current.ApplicationInstance.CompleteRequest();
                                Current_Mode.Request_Completed = true;
                                Paged_Results = null;
                                return;
                            }
                        }
                    }
                }

                // Was this a OCLC search?
                if ((Web_Fields[0] == "OC") && (Terms[0].Length > 0))
                {
                    bool is_number = Terms[0].All(Char.IsNumber);

                    if (is_number)
                    {
                        long oclc = Convert.ToInt64(Terms[0]);
                        Multiple_Paged_Results_Args returnArgs = Engine_Database.Items_By_OCLC_Number(oclc, false, Results_Per_Page, Current_Sort, Need_Search_Statistics, Tracer);
                        if (Need_Search_Statistics)
                            Complete_Result_Set_Info = returnArgs.Statistics;
                        Paged_Results = returnArgs.Paged_Results;
                        return;
                    }
                }

                // Was this a ALEPH search?
                if ((Web_Fields[0] == "AL") && (Terms[0].Length > 0))
                {
                    bool is_number = Terms[0].All(Char.IsNumber);

                    if (is_number)
                    {
                        int aleph = Convert.ToInt32(Terms[0]);
                        Multiple_Paged_Results_Args returnArgs = Engine_Database.Items_By_ALEPH_Number(aleph, false, Results_Per_Page, Current_Sort, Need_Search_Statistics, Tracer);
                        if (Need_Search_Statistics)
                            Complete_Result_Set_Info = returnArgs.Statistics;
                        Paged_Results = returnArgs.Paged_Results;
                        return;
                    }
                }
            }

            List<short> links = new List<short>();
            List<short> db_fields = new List<short>();
            List<string> db_terms = Terms.ToList();

            // Step through all the web fields and convert to db fields
            for (int i = 0; i < ActualCount; i++)
            {
                if (Web_Fields[i].Length > 1)
                {
                    // Find the joiner
                    if ((Web_Fields[i][0] == '+') || (Web_Fields[i][0] == '=') || (Web_Fields[i][0] == '-'))
                    {
                        if (Web_Fields[i][0] == '+')
                            links.Add(0);
                        if (Web_Fields[i][0] == '=')
                            links.Add(1);
                        if (Web_Fields[i][0] == '-')
                            links.Add(2);

                        Web_Fields[i] = Web_Fields[i].Substring(1);
                    }
                    else
                    {
                        links.Add(0);
                    }

                    // Find the db field number
                    db_fields.Add(Metadata_Field_Number(Web_Fields[i]));
                }

                // Also add starting and ending quotes to all the valid searches
                if (db_terms[i].Length > 0)
                {
                    if ((db_terms[i].IndexOf("\"") < 0) && (db_terms[i].IndexOf(" ") < 0))
                    {
                        // Since this is a single word, see what type of special codes to include
                        switch (Current_Mode.Search_Precision)
                        {
                            case Search_Precision_Type_Enum.Contains:
                                db_terms[i] = "\"" + db_terms[i] + "\"";
                                break;

                            case Search_Precision_Type_Enum.Inflectional_Form:
                                // If there are any non-characters, don't use inflectional for this term
                                bool inflectional = db_terms[i].All(Char.IsLetter);
                                if (inflectional)
                                {
                                    db_terms[i] = "FORMSOF(inflectional," + db_terms[i] + ")";
                                }
                                else
                                {
                                    db_terms[i] = "\"" + db_terms[i] + "\"";
                                }
                                break;

                            case Search_Precision_Type_Enum.Synonmic_Form:
                                // If there are any non-characters, don't use thesaurus for this term
                                bool thesaurus = db_terms[i].All(Char.IsLetter);
                                if (thesaurus)
                                {
                                    db_terms[i] = "FORMSOF(thesaurus," + db_terms[i] + ")";
                                }
                                else
                                {
                                    db_terms[i] = "\"" + db_terms[i] + "\"";
                                }
                                break;
                        }
                    }
                    else
                    {
                        if (Current_Mode.Search_Precision != Search_Precision_Type_Enum.Exact_Match)
                        {
                            db_terms[i] = "\"" + db_terms[i] + "\"";
                        }
                    }
                }
            }

            // Get the page count in the results
            int current_page_index = Current_Mode.Page.HasValue ? Math.Max(Current_Mode.Page.Value, ((ushort)1)) : 1;

            // If this is an exact match, just do the search
            if (Current_Mode.Search_Precision == Search_Precision_Type_Enum.Exact_Match)
            {
                Multiple_Paged_Results_Args returnArgs = Engine_Database.Perform_Metadata_Exact_Search_Paged(db_terms[0], db_fields[0], INCLUDE_PRIVATE, Current_Mode.Aggregation, Date1, Date2, Results_Per_Page, current_page_index, Current_Sort, Need_Search_Statistics, facetsList, Need_Search_Statistics, Tracer);
                if (Need_Search_Statistics)
                    Complete_Result_Set_Info = returnArgs.Statistics;
                Paged_Results = returnArgs.Paged_Results;
            }
            else
            {
                // Finish filling up the fields and links
                while (links.Count < 10)
                    links.Add(0);
                while (db_fields.Count < 10)
                    db_fields.Add(-1);
                while (db_terms.Count < 10)
                    db_terms.Add(String.Empty);

                // See if this is a simple search, which can use a more optimized search routine
                bool simplified_search = db_fields.All(Field => (Field <= 0));

                // Perform either the simpler metadata search, or the more complex
                if (simplified_search)
                {
                    StringBuilder searchBuilder = new StringBuilder();
                    for (int i = 0; i < db_terms.Count; i++)
                    {
                        if (db_terms[i].Length > 0)
                        {
                            if (i > 0)
                            {
                                if (i > links.Count)
                                {
                                    searchBuilder.Append(" AND ");
                                }
                                else
                                {
                                    switch (links[i])
                                    {
                                        case 0:
                                            searchBuilder.Append(" AND ");
                                            break;

                                        case 1:
                                            searchBuilder.Append(" OR ");
                                            break;

                                        case 2:
                                            searchBuilder.Append(" AND NOT ");
                                            break;
                                    }
                                }
                            }

                            searchBuilder.Append(db_terms[i]);
                        }
                    }

                    Multiple_Paged_Results_Args returnArgs = Engine_Database.Perform_Metadata_Search_Paged(searchBuilder.ToString(), INCLUDE_PRIVATE, Current_Mode.Aggregation, Date1, Date2, Results_Per_Page, current_page_index, Current_Sort, Need_Search_Statistics, facetsList, Need_Search_Statistics, Tracer);
                    if (Need_Search_Statistics)
                        Complete_Result_Set_Info = returnArgs.Statistics;
                    Paged_Results = returnArgs.Paged_Results;
                }
                else
                {
                    // Perform search in the database
                    Multiple_Paged_Results_Args returnArgs = Engine_Database.Perform_Metadata_Search_Paged(links[0], db_terms[0], db_fields[0], links[1], db_terms[1], db_fields[1], links[2], db_terms[2], db_fields[2], links[3], db_terms[3],
                                                                                                            db_fields[3], links[4], db_terms[4], db_fields[4], links[5], db_terms[5], db_fields[5], links[6], db_terms[6], db_fields[6], links[7], db_terms[7], db_fields[7], links[8], db_terms[8], db_fields[8],
                                                                                                            links[9], db_terms[9], db_fields[9], INCLUDE_PRIVATE, Current_Mode.Aggregation, Date1, Date2, Results_Per_Page, current_page_index, Current_Sort, Need_Search_Statistics, facetsList, Need_Search_Statistics, Tracer);
                    if (Need_Search_Statistics)
                        Complete_Result_Set_Info = returnArgs.Statistics;
                    Paged_Results = returnArgs.Paged_Results;
                }
            }
        }
        /// <summary> Verified the item lookup object is filled, or populates the item lookup object with all the valid bibids and vids in the system </summary>
        /// <param name="AlwaysRefresh"> Flag indicates if this should be refreshed, whether or not the item lookup object is filled </param>
        /// <param name="IncludePrivate"> Flag indicates whether to include private items in this list </param>
        /// <param name="ItemLookupObject"> Item lookup object to directly populate from the database </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        /// <returns> TRUE if successful or if the object is already filled, otherwise FALSE </returns>
        /// <remarks> This calls the 'SobekCM_Item_List_Web' stored procedure </remarks> 
        internal static bool Verify_Item_Lookup_Object(bool AlwaysRefresh, bool IncludePrivate, Item_Lookup_Object ItemLookupObject, Custom_Tracer Tracer)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("Engine_Database.Verify_Item_Lookup_Object", String.Empty);
            }

            // If no database string, don't try to connect
            if (String.IsNullOrEmpty(Connection_String))
                return false;

            lock (itemListPopulationLock)
            {
                bool updateList = true;
                if (( !AlwaysRefresh ) && ( ItemLookupObject != null))
                {
                    TimeSpan sinceLastUpdate = DateTime.Now.Subtract(ItemLookupObject.Last_Updated);
                    if (sinceLastUpdate.TotalMinutes <= 1)
                        updateList = false;
                }

                if (!updateList)
                {
                    return true;
                }

                // Have the database popoulate the little bit of bibid/vid information we retain
                bool returnValue = Populate_Item_Lookup_Object(IncludePrivate, ItemLookupObject, Tracer);
                if ((returnValue) && ( ItemLookupObject != null ))
                    ItemLookupObject.Last_Updated = DateTime.Now;
                return returnValue;
            }
        }
        /// <summary> Populates the item lookup object with all the valid bibids and vids in the system </summary>
        /// <param name="IncludePrivate"> Flag indicates whether to include private items in this list </param>
        /// <param name="ItemLookupObject"> Item lookup object to directly populate from the database </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        /// <remarks> This calls the 'SobekCM_Item_List_Web' stored procedure </remarks> 
        public static bool Populate_Item_Lookup_Object(bool IncludePrivate, Item_Lookup_Object ItemLookupObject, Custom_Tracer Tracer)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("Engine_Database.Populate_Item_Lookup_Object", String.Empty);
            }

            try
            {
                // Create the parameter list
                EalDbParameter[] parameters = new EalDbParameter[1];
                parameters[0] = new EalDbParameter("@include_private", IncludePrivate);

                // Get the data reader (wrapper)
                EalDbReaderWrapper readerWrapper = EalDbAccess.ExecuteDataReader(DatabaseType, Connection_String + "Connection Timeout=45", CommandType.StoredProcedure, "SobekCM_Item_List", parameters);

                // Pull out the database reader
                DbDataReader reader = readerWrapper.Reader;

                // Clear existing volumes
                ItemLookupObject.Clear();
                ItemLookupObject.Last_Updated = DateTime.Now;

                string currentBibid = String.Empty;
                Multiple_Volume_Item currentVolume = null;
                while (reader.Read())
                {
                    // Grab the values out
                    string newBib = reader.GetString(0);
                    string newVid = reader.GetString(1);
                    short newMask = reader.GetInt16(2);
                    string title = reader.GetString(3);

                    // Create a new multiple volume object?
                    if (newBib != currentBibid)
                    {
                        currentBibid = newBib;
                        currentVolume = new Multiple_Volume_Item(newBib);
                        ItemLookupObject.Add_Title(currentVolume);
                    }

                    // Add this volume
                    Single_Item newItem = new Single_Item(newVid, newMask, title);
                    if (currentVolume != null) currentVolume.Add_Item(newItem);
                }

                // Close the reader (which also closes the connection)
                readerWrapper.Close();

                // Return the first table from the returned dataset
                return true;
            }
            catch (Exception ee)
            {
                Last_Exception = ee;
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Engine_Database.Populate_Item_Lookup_Object", "Exception caught during database work", Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Engine_Database.Populate_Item_Lookup_Object", ee.Message, Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Engine_Database.Populate_Item_Lookup_Object", ee.StackTrace, Custom_Trace_Type_Enum.Error);
                }
                return false;
            }
        }