/// <summary> Constructor for a new instance of the RequestCache class </summary>
 /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
 /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
 /// <param name="Results_Statistics"> Information about the entire set of results for a search or browse </param>
 /// <param name="Paged_Results"> Single page of results for a search or browse, within the entire set </param>
 /// <param name="Browse_Object"> Object contains all the basic information about any browse or info display </param>
 /// <param name="Current_Item"> Current item to display </param>
 /// <param name="Current_Page"> Current page within the item</param>
 /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
 /// <param name="Current_User"> Currently logged on user </param>
 /// <param name="Public_Folder"> Object contains the information about the public folder to display </param>
 /// <param name="Site_Map"> Optional site map object used to render a navigational tree-view on left side of static web content pages </param>
 /// <param name="Items_In_Title"> List of items within the current title ( used for the Item Group display )</param>
 /// <param name="Static_Web_Content"> HTML content-based browse, info, or imple CMS-style web content objects.  These are objects which are read from a static HTML file and much of the head information must be maintained </param>
 /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
 public RequestCache(Navigation_Object Current_Mode,
     Item_Aggregation Hierarchy_Object,
     Search_Results_Statistics Results_Statistics,
     List<iSearch_Title_Result> Paged_Results,
     Item_Aggregation_Child_Page Browse_Object,
     SobekCM_Item Current_Item,
     Page_TreeNode Current_Page,
     Web_Skin_Object HTML_Skin,
     User_Object Current_User,
     Public_User_Folder Public_Folder,
     SobekCM_SiteMap Site_Map,
     SobekCM_Items_In_Title Items_In_Title,
     HTML_Based_Content Static_Web_Content,
     Custom_Tracer Tracer)
 {
     this.Current_Mode = Current_Mode;
     this.Hierarchy_Object = Hierarchy_Object;
     this.Results_Statistics = Results_Statistics;
     this.Paged_Results = Paged_Results;
     this.Browse_Object = Browse_Object;
     this.Current_Item = Current_Item;
     this.Current_Page = Current_Page;
     this.HTML_Skin = HTML_Skin;
     this.Current_User = Current_User;
     this.Public_Folder = Public_Folder;
     this.Site_Map = Site_Map;
     this.Items_In_Title = Items_In_Title;
     this.Static_Web_Content = Static_Web_Content;
     this.Tracer = Tracer;
 }
        /// <summary> Method returns the table of results for the browse indicated </summary>
        /// <param name="ItemAggr"> Item Aggregation from which to return the browse </param>
        /// <param name = "ChildPageObject">Object with all the information about the browse</param>
        /// <param name = "Page"> Page of results requested for the indicated browse </param>
        /// <param name = "Sort"> Sort applied to the results before being returned </param>
        /// <param name="Potentially_Include_Facets"> Flag indicates if facets could be included in this browse results </param>
        /// <param name = "Need_Browse_Statistics"> Flag indicates if the browse statistics (facets and total counts) are required for this browse as well </param>
        /// <param name = "Tracer">Trace object keeps a list of each method executed and important milestones in rendering</param>
        /// <param name="Results_Per_Page"> Number of results to retrieve per page</param>
        /// <returns> Resutls for the browse or info in table form </returns>
        public static Multiple_Paged_Results_Args Get_Browse_Results(Item_Aggregation ItemAggr, Item_Aggregation_Child_Page ChildPageObject,
                                                                      int Page, int Sort, int Results_Per_Page, bool Potentially_Include_Facets, bool Need_Browse_Statistics,
                                                                      Custom_Tracer Tracer)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Browse_Results", String.Empty);
            }

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

            // Pull data from the database if necessary
            if ((ChildPageObject.Code == "all") || (ChildPageObject.Code == "new"))
            {
                // Get this browse from the database
                if ((ItemAggr.ID < 0) || (ItemAggr.Code.ToUpper() == "ALL"))
                {
                    if (ChildPageObject.Code == "new")
                        return Engine_Database.Get_All_Browse_Paged(true, false, Results_Per_Page, Page, Sort, Need_Browse_Statistics, facetsList, Need_Browse_Statistics, Tracer);
                    return Engine_Database.Get_All_Browse_Paged(false, false, Results_Per_Page, Page, Sort, Need_Browse_Statistics, facetsList, Need_Browse_Statistics, Tracer);
                }

                if (ChildPageObject.Code == "new")
                {
                    return Engine_Database.Get_Item_Aggregation_Browse_Paged(ItemAggr.Code, true, false, Results_Per_Page, Page, Sort, Need_Browse_Statistics, facetsList, Need_Browse_Statistics, Tracer);
                }
                return Engine_Database.Get_Item_Aggregation_Browse_Paged(ItemAggr.Code, false, false, Results_Per_Page, Page, Sort, Need_Browse_Statistics, facetsList, Need_Browse_Statistics, Tracer);
            }

            // Default return NULL
            return null;
        }
 /// <summary> Constructor for a new instance of the AggregationViewBag class </summary>
 /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
 /// <param name="Results_Statistics"> Information about the entire set of results for a browse </param>
 /// <param name="Paged_Results"> Single page of results for a browse, within the entire set </param>
 /// <param name="Browse_Object"> Object contains all the basic information about any browse or info display </param>
 /// <param name="Static_Web_Content"> HTML content-based aggregation browse or info.  These are objects which are read from a static HTML file and much of the head information must be maintained </param>
 public AggregationViewBag(Item_Aggregation Hierarchy_Object,
     Search_Results_Statistics Results_Statistics,
     List<iSearch_Title_Result> Paged_Results,
     Item_Aggregation_Child_Page Browse_Object,
     HTML_Based_Content Static_Web_Content)
 {
     this.Hierarchy_Object = Hierarchy_Object;
     this.Results_Statistics = Results_Statistics;
     this.Paged_Results = Paged_Results;
     this.Browse_Object = Browse_Object;
     this.Static_Web_Content = Static_Web_Content;
 }
        /// <summary> Constructor for a new instance of the simple aggregation class </summary>
        /// <param name="FullAggregation"> Full (language-specific) aggregation object </param>
        public Simple_Aggregation(Item_Aggregation FullAggregation)
        {
            // Assign the simple properties
            Language        = Web_Language_Enum_Converter.Enum_To_Code(FullAggregation.Language);
            ID              = FullAggregation.ID;
            Code            = FullAggregation.Code;
            Name            = FullAggregation.Name;
            BannerImage     = FullAggregation.BannerImage;
            Last_Item_Added = FullAggregation.Last_Item_Added;

            // Assign search fields
            if ((FullAggregation.Search_Fields != null) && (FullAggregation.Search_Fields.Count > 0))
            {
                Search_Fields = new List <Item_Aggregation_Metadata_Type>();
                foreach (Item_Aggregation_Metadata_Type searchField in FullAggregation.Search_Fields)
                {
                    Search_Fields.Add(new Item_Aggregation_Metadata_Type(searchField.DisplayTerm, searchField.SobekCode));
                }
            }

            // Assign browseable fields
            if ((FullAggregation.Browseable_Fields != null) && (FullAggregation.Browseable_Fields.Count > 0))
            {
                Browseable_Fields = new List <Item_Aggregation_Metadata_Type>();
                foreach (Item_Aggregation_Metadata_Type searchField in FullAggregation.Browseable_Fields)
                {
                    Browseable_Fields.Add(new Item_Aggregation_Metadata_Type(searchField.DisplayTerm, searchField.SobekCode));
                }
            }

            // Assign searches and views
            if ((FullAggregation.Views_And_Searches != null) && (FullAggregation.Views_And_Searches.Count > 0))
            {
                Views_And_Searches = new List <string>();
                foreach (Item_Aggregation_Views_Searches_Enum viewEnum in FullAggregation.Views_And_Searches)
                {
                    Views_And_Searches.Add(viewEnum.ToString("G"));
                }
            }

            // Assign the name and code of each child page
            if ((FullAggregation.Child_Pages != null) && (FullAggregation.Child_Pages.Count > 0))
            {
                Child_Pages = new List <Simple_Aggregation_Child_Page>();
                foreach (Item_Aggregation_Child_Page thisChild in FullAggregation.Child_Pages)
                {
                    Child_Pages.Add(new Simple_Aggregation_Child_Page(thisChild.Code, thisChild.Label));
                }
            }
        }
 /// <summary> Constructor for a new instance of the RequestCache class </summary>
 /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
 /// <param name="Results_Statistics"> Information about the entire set of results for a search or browse </param>
 /// <param name="Paged_Results"> Single page of results for a search or browse, within the entire set </param>
 /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
 /// <param name="Current_User"> Currently logged on user </param>
 /// <param name="Public_Folder"> Object contains the information about the public folder to display </param>
 /// <param name="Top_Collection"> Item aggregation for the top-level collection, which is used in a number of places, for example 
 /// showing the correct banner, even when it is not the "current" aggregation </param>
 /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
 public RequestCache(Navigation_Object Current_Mode,
     Search_Results_Statistics Results_Statistics,
     List<iSearch_Title_Result> Paged_Results,
     Web_Skin_Object HTML_Skin,
     User_Object Current_User,
     Public_User_Folder Public_Folder,
     Item_Aggregation Top_Collection,
     Custom_Tracer Tracer)
 {
     this.Current_Mode = Current_Mode;
     this.Results_Statistics = Results_Statistics;
     this.Paged_Results = Paged_Results;
     this.HTML_Skin = HTML_Skin;
     this.Current_User = Current_User;
     this.Public_Folder = Public_Folder;
     this.Top_Collection = Top_Collection;
     this.Tracer = Tracer;
 }
        /// <summary> Adds the banner to the response stream from either the html web skin
        /// or from the current item aggreagtion object, depending on flags in the web skin object </summary>
        /// <param name="Output"> Stream to which to write the HTML for the banner </param>
        /// <param name="Banner_Division_Name"> Name for the wrapper division around the banner </param>
        /// <param name="Hierarchy_Object"> Current item aggregation object to display </param>
        /// <param name="HTML_Skin"> HTML Web skin which controls the overall appearance of this digital library </param>
        /// <param name="Web_Page_Title"> Web page title to add behind the banner image </param>
        /// <param name="CurrentMode"> Mode / navigation information for the current request</param>
        /// <remarks> This is called by several html subwriters that otherwise tell this class to suppress writing the banner </remarks>
        public static void Add_Banner(TextWriter Output, string Banner_Division_Name, string Web_Page_Title, Navigation_Object CurrentMode, Web_Skin_Object HTML_Skin, Item_Aggregation Hierarchy_Object)
        {
            Output.WriteLine("<!-- Write the main collection, interface, or institution banner -->");
            if ((HTML_Skin != null) && (HTML_Skin.Override_Banner.HasValue) && (HTML_Skin.Override_Banner.Value))
            {
                if ( !String.IsNullOrEmpty(HTML_Skin.Banner_HTML))
                    Output.WriteLine(HTML_Skin.Banner_HTML);
            }
            else
            {
                string url_options = UrlWriterHelper.URL_Options(CurrentMode);
                if (url_options.Length > 0)
                    url_options = "?" + url_options;

                if ((Hierarchy_Object != null) && (Hierarchy_Object.Code != "all"))
                {
                    Output.WriteLine("<section id=\"sbkAhs_BannerDiv\" role=\"banner\" title=\"" + Hierarchy_Object.ShortName + "\">");
                    Output.WriteLine("  <h1 class=\"hidden-element\">" + Web_Page_Title + "</h1>");
                    Output.WriteLine("  <a alt=\"" + Hierarchy_Object.ShortName + "\" href=\"" + CurrentMode.Base_URL + Hierarchy_Object.Code + url_options + "\"><img id=\"mainBanner\" src=\"" + CurrentMode.Base_URL + Hierarchy_Object.Get_Banner_Image(HTML_Skin) + "\"  alt=\"" + Hierarchy_Object.ShortName + "\" /></a>");
                    Output.WriteLine("</section>");
                }
                else
                {
                    if ((Hierarchy_Object != null) && (Hierarchy_Object.Get_Banner_Image(HTML_Skin).Length > 0))
                    {
                        Output.WriteLine("<section id=\"sbkAhs_BannerDiv\" role=\"banner\" title=\"" + Hierarchy_Object.ShortName + "\">");
                        Output.WriteLine("  <h1 class=\"hidden-element\">" + Web_Page_Title + "</h1>");
                        Output.WriteLine("  <a alt=\"" + Hierarchy_Object.ShortName + "\" href=\"" + CurrentMode.Base_URL + url_options + "\"><img id=\"mainBanner\" src=\"" + CurrentMode.Base_URL + Hierarchy_Object.Get_Banner_Image(HTML_Skin) + "\"  alt=\"" + Hierarchy_Object.ShortName + "\" /></a>");
                        Output.WriteLine("</section>");
                    }
                    else
                    {
                        string skin_url = CurrentMode.Base_Design_URL + "skins/" + CurrentMode.Skin + "/";
                        Output.WriteLine("<section id=\"sbkAhs_BannerDiv\" role=\"banner\"><h1 class=\"hidden-element\">" + Web_Page_Title + "</h1><a href=\"" + CurrentMode.Base_URL + url_options + "\"><img id=\"mainBanner\" src=\"" + skin_url + "default.jpg\" alt=\"\" /></a></section>");
                    }
                }
            }
            Output.WriteLine();
        }
        /// <summary> Get the language specific item aggregation, from the complete item aggregation object </summary>
        /// <param name="CompAggr"> Copmlete item aggregation object </param>
        /// <param name="RequestedLanguage"> Language version requested </param>
        /// <param name="Tracer"></param>
        /// <returns> The language-specific aggregation, built from the complete aggregation object, or NULL if an error occurred </returns>
        public static Item_Aggregation Get_Item_Aggregation(Complete_Item_Aggregation CompAggr, Web_Language_Enum RequestedLanguage, Custom_Tracer Tracer)
        {
            // If the complete aggregation was null, return null
            if (CompAggr == null)
            {
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "Complete item aggregation was NULL.. aborting and returning NULL");
                }

                return null;
            }

            if (Tracer != null)
            {
                Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "Building language-specific item aggregation from the complete object");
            }

            // Build the item aggregation
            Item_Aggregation returnValue = new Item_Aggregation(RequestedLanguage, CompAggr.ID, CompAggr.Code)
            {
                Active = CompAggr.Active,
                BannerImage = CompAggr.Banner_Image(RequestedLanguage, null ),
                Child_Types = CompAggr.Child_Types,
                Contact_Email = CompAggr.Contact_Email,
                ContactForm = CompAggr.ContactForm,
                CSS_File = CompAggr.CSS_File,
                Default_BrowseBy = CompAggr.Default_BrowseBy,
                Default_Result_View = CompAggr.Default_Result_View,
                Default_Skin = CompAggr.Default_Skin,
                Description = CompAggr.Description,
                Display_Options = CompAggr.Display_Options,
                FrontBannerObj = CompAggr.Front_Banner_Image(RequestedLanguage),
                Hidden = CompAggr.Hidden,
                Last_Item_Added = CompAggr.Last_Item_Added,
                Name = CompAggr.Name,
                Rotating_Highlights = CompAggr.Rotating_Highlights,
                ShortName = CompAggr.ShortName,
                Statistics = CompAggr.Statistics,
                Type = CompAggr.Type
            };

            // Copy the map search and browse information
            if (CompAggr.Map_Search_Display != null) returnValue.Map_Search_Display = CompAggr.Map_Search_Display.Copy();
            if (CompAggr.Map_Browse_Display != null) returnValue.Map_Browse_Display = CompAggr.Map_Browse_Display.Copy();

            // Copy any children aggregations over
            if (CompAggr.Active_Children_Count > 0)
            {
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "...Copying children objects");
                }

                returnValue.Children = new List<Item_Aggregation_Related_Aggregations>();
                foreach (Item_Aggregation_Related_Aggregations thisAggr in CompAggr.Children)
                {
                    returnValue.Children.Add(thisAggr);
                }
            }

            // Copy any parent aggregations over
            if (CompAggr.Parent_Count > 0)
            {
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "...Copying parent objects");
                }

                returnValue.Parents = new List<Item_Aggregation_Related_Aggregations>();
                foreach (Item_Aggregation_Related_Aggregations thisAggr in CompAggr.Parents)
                {
                    returnValue.Parents.Add(thisAggr);
                }
            }

            // Copy all the facet information over
            if (Tracer != null)
            {
                Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "...Copying facets");
            }
            foreach (short thisFacet in CompAggr.Facets)
            {
                returnValue.Facets.Add(thisFacet);
            }

            // Copy over all the results views
            if (Tracer != null)
            {
                Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "...Copying result views");
            }
            foreach (Result_Display_Type_Enum display in CompAggr.Result_Views)
            {
                returnValue.Result_Views.Add(display);
            }

            // Copy all the views and searches over
            if (Tracer != null)
            {
                Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "...Copying views and searches");
            }
            if (CompAggr.Views_And_Searches != null)
            {
                foreach (Item_Aggregation_Views_Searches_Enum viewsSearches in CompAggr.Views_And_Searches)
                {
                    returnValue.Views_And_Searches.Add(viewsSearches);
                }
            }

            // Copy all the setting values
            if ((CompAggr.Settings != null) && (CompAggr.Settings.Count > 0))
            {
                foreach (StringKeyValuePair setting in CompAggr.Settings)
                {
                    returnValue.Add_Setting(setting.Key, setting.Value );
                }
            }

            // Copy over any web skin limitations
            if ((CompAggr.Web_Skins != null) && (CompAggr.Web_Skins.Count > 0))
            {
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "...Copying web skins");
                }

                returnValue.Web_Skins = new List<string>();
                foreach (string thisSkin in CompAggr.Web_Skins)
                {
                    returnValue.Web_Skins.Add(thisSkin);
                }
            }

            // Language-specific (and simplified) metadata type info
            if (Tracer != null)
            {
                Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "...Copying search anbd browseable fields");
            }
            foreach (Complete_Item_Aggregation_Metadata_Type thisAdvSearchField in CompAggr.Search_Fields)
            {
                returnValue.Search_Fields.Add(new Item_Aggregation_Metadata_Type(thisAdvSearchField.DisplayTerm, thisAdvSearchField.SobekCode));
            }
            foreach (Complete_Item_Aggregation_Metadata_Type thisAdvSearchField in CompAggr.Browseable_Fields)
            {
                returnValue.Browseable_Fields.Add(new Item_Aggregation_Metadata_Type(thisAdvSearchField.DisplayTerm, thisAdvSearchField.SobekCode));
            }

            // Language-specific (and simplified) child pages information
            if ((CompAggr.Child_Pages != null) && (CompAggr.Child_Pages.Count > 0))
            {
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "...Copying child pages");
                }

                returnValue.Child_Pages = new List<Item_Aggregation_Child_Page>();
                foreach (Complete_Item_Aggregation_Child_Page fullPage in CompAggr.Child_Pages)
                {
                    Item_Aggregation_Child_Page newPage = new Item_Aggregation_Child_Page
                    {
                        Browse_Type = fullPage.Browse_Type,
                        Code = fullPage.Code,
                        Parent_Code = fullPage.Parent_Code,
                        Source_Data_Type = fullPage.Source_Data_Type
                    };

                    string label = fullPage.Get_Label(RequestedLanguage);
                    if (!String.IsNullOrEmpty(label))
                        newPage.Label = label;

                    string source = fullPage.Get_Static_HTML_Source(RequestedLanguage);
                    if (!String.IsNullOrEmpty(label))
                        newPage.Source = source;

                    returnValue.Child_Pages.Add(newPage);
                }
            }

            // Language-specific (and simplified) highlight information
            if ((CompAggr.Highlights != null) && (CompAggr.Highlights.Count > 0))
            {
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "...Copying relevant highlights");
                }

                returnValue.Highlights = new List<Item_Aggregation_Highlights>();
                int day_integer = DateTime.Now.DayOfYear + 1;
                int highlight_to_use = day_integer % CompAggr.Highlights.Count;

                // If this is for rotating highlights, show up to eight
                if ((CompAggr.Rotating_Highlights.HasValue ) && ( CompAggr.Rotating_Highlights.Value ))
                {
                    // Copy over just the eight highlights we should use
                    int number = Math.Min(8, CompAggr.Highlights.Count);
                    for (int i = 0; i < number; i++)
                    {
                        Complete_Item_Aggregation_Highlights thisHighlight = CompAggr.Highlights[highlight_to_use];

                        Item_Aggregation_Highlights newHighlight = new Item_Aggregation_Highlights
                        {
                            Image = thisHighlight.Image,
                            Link = thisHighlight.Link
                        };

                        string text = thisHighlight.Get_Text(RequestedLanguage);
                        if (!String.IsNullOrEmpty(text))
                            newHighlight.Text = text;

                        string tooltip = thisHighlight.Get_Tooltip(RequestedLanguage);
                        if (!String.IsNullOrEmpty(tooltip))
                            newHighlight.Tooltip = tooltip;

                        returnValue.Highlights.Add(newHighlight);

                        highlight_to_use++;
                        if (highlight_to_use >= CompAggr.Highlights.Count)
                            highlight_to_use = 0;
                    }
                }
                else
                {
                    Complete_Item_Aggregation_Highlights thisHighlight = CompAggr.Highlights[highlight_to_use];

                    Item_Aggregation_Highlights newHighlight = new Item_Aggregation_Highlights
                    {
                        Image = thisHighlight.Image,
                        Link = thisHighlight.Link
                    };

                    string text = thisHighlight.Get_Text(RequestedLanguage);
                    if (!String.IsNullOrEmpty(text))
                        newHighlight.Text = text;

                    string tooltip = thisHighlight.Get_Tooltip(RequestedLanguage);
                    if (!String.IsNullOrEmpty(tooltip))
                        newHighlight.Tooltip = tooltip;

                    returnValue.Highlights.Add(newHighlight);
                }
            }

            // Language-specific source page
            if (Tracer != null)
            {
                Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "Getting the home page source");
            }
            returnValue.HomePageSource = String.Empty;
            HTML_Based_Content homeHtml = Get_Home_HTML(CompAggr, RequestedLanguage, null);
            returnValue.HomePageHtml = homeHtml;
            returnValue.Custom_Home_Page = (CompAggr.Home_Page_File(RequestedLanguage) != null) && (CompAggr.Home_Page_File(RequestedLanguage).isCustomHome);

            if (Tracer != null)
            {
                Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Item_Aggregation", "Returning fully built item aggregation object");
            }
            return returnValue;
        }
        /// <summary> Stores the item aggregation object to the cache  </summary>
        /// <param name="AggregationCode"> Code for the item aggregation to store </param>
        /// <param name="Language"> Current language code (item aggregation instances are currently language-specific)</param>
        /// <param name="StoreObject"> Item aggregation object to store for later retrieval </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        public void Store_Item_Aggregation(string AggregationCode, Web_Language_Enum Language, Item_Aggregation StoreObject, Custom_Tracer Tracer)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("CachedDataManager.Store_Item_Aggregation", "Entering Store_Item_Aggregation method");
            }

            // Don't store nulls
            if (StoreObject == null)
                return;

            // If the cache is disabled, just return before even tracing
            if (settings.Disabled)
            {
                if (Tracer != null) Tracer.Add_Trace("CachedDataManager.Store_Item_Aggregation", "Caching is disabled");
                return;
            }

            // Determine the key
            string key = "AGGR|" + AggregationCode.ToUpper() + "|" + Web_Language_Enum_Converter.Enum_To_Code(Language);

            const int LOCAL_EXPIRATION = 15;

            // Locally cache if this doesn't exceed the limit
            if (Tracer != null)
            {
                Tracer.Add_Trace("CachedDataManager.Store_Item_Aggregation", "Adding object '" + key + "' to the local cache with expiration of " + LOCAL_EXPIRATION + " minute(s)");
            }

            HttpContext.Current.Cache.Insert(key, StoreObject, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(LOCAL_EXPIRATION));
        }
        /// <summary> Add the header to the output </summary>
        /// <param name="Output"> Stream to which to write the HTML for this header </param>
        /// <param name="RequestSpecificValues"> All the necessary, non-global data specific to the current request </param>
        /// <param name="Behaviors"> List of behaviors from the html subwriters </param>
        /// <param name="Current_Aggregation"> Current aggregation object, if there is one </param>
        /// <param name="Current_Item"> Current item object, if there is one </param>
        public static void Add_Footer(TextWriter Output, RequestCache RequestSpecificValues, List<HtmlSubwriter_Behaviors_Enum> Behaviors, Item_Aggregation Current_Aggregation, BriefItemInfo Current_Item)
        {
            // Determine which header and footer to display
            bool useItemFooter = (RequestSpecificValues.Current_Mode.Mode == Display_Mode_Enum.Item_Display) || (RequestSpecificValues.Current_Mode.Mode == Display_Mode_Enum.Item_Print) || ((Behaviors != null) && (Behaviors.Contains(HtmlSubwriter_Behaviors_Enum.MySobek_Subwriter_Mimic_Item_Subwriter)));

            // Get the current contact URL
            Display_Mode_Enum thisMode = RequestSpecificValues.Current_Mode.Mode;
            RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Contact;
            string contact = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);

            // Restore the old mode
            RequestSpecificValues.Current_Mode.Mode = thisMode;

            // Get the URL options
            string url_options = UrlWriterHelper.URL_Options(RequestSpecificValues.Current_Mode);
            string urlOptions1 = String.Empty;
            string urlOptions2 = String.Empty;
            if (url_options.Length > 0)
            {
                urlOptions1 = "?" + url_options;
                urlOptions2 = "&" + url_options;
            }

            // Create the mySobek text
            string mySobekLinks = create_mysobek_link(RequestSpecificValues, url_options, "staff login");

            // Get the base url
            string base_url = RequestSpecificValues.Current_Mode.Base_URL;
            if (RequestSpecificValues.Current_Mode.Writer_Type == Writer_Type_Enum.HTML_LoggedIn)
                base_url = base_url + "l/";

            // Look for the collection code and name
            string collection_code = String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.Aggregation) ? String.Empty : RequestSpecificValues.Current_Mode.Aggregation;
            string bibid = String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.BibID) ? String.Empty : RequestSpecificValues.Current_Mode.BibID;
            string vid = String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.BibID) ? String.Empty : RequestSpecificValues.Current_Mode.BibID;
            string mode = String.Empty;
            switch (RequestSpecificValues.Current_Mode.Mode)
            {
                case Display_Mode_Enum.Item_Display:
                    mode = "item";
                    break;

                case Display_Mode_Enum.Aggregation:
                case Display_Mode_Enum.Search:
                    mode = "aggregation";
                    break;

                case Display_Mode_Enum.Results:
                    mode = "results";
                    break;
            }

            // Get the skin url
            string skin_url = RequestSpecificValues.Current_Mode.Base_Design_URL + "skins/" + RequestSpecificValues.HTML_Skin.Skin_Code + "/";

            bool end_div = true;// !((RequestSpecificValues.Current_Mode.Mode == Display_Mode_Enum.Simple_HTML_CMS) && (RequestSpecificValues.Site_Map != null));

            string version = UI_ApplicationCache_Gateway.Settings.Static.Current_Web_Version;
            if (version.IndexOf(" ") > 0)
                version = version.Split(" ".ToCharArray())[0];

            // Get the session id
            string sessionId = HttpContext.Current.Session.SessionID ?? String.Empty;
            string userid = ((RequestSpecificValues.Current_User != null) && (RequestSpecificValues.Current_User.UserID > 0)) ? RequestSpecificValues.Current_User.UserID.ToString() : String.Empty;

            StringBuilder footerBuilder = new StringBuilder();
            if (useItemFooter)
            {
                footerBuilder.Append(RequestSpecificValues.HTML_Skin.Footer_Item_HTML);
            }
            else
            {
                if (( RequestSpecificValues.HTML_Skin.Footer_Has_Container_Directive.HasValue) && (RequestSpecificValues.HTML_Skin.Footer_Has_Container_Directive.Value))
                {
                    footerBuilder.Append(RequestSpecificValues.HTML_Skin.Footer_HTML);
                }
                else
                {
                    footerBuilder.Append(RequestSpecificValues.HTML_Skin.Footer_HTML + Environment.NewLine + "</div>");
                }
            }

            // Make all the replacements
            footerBuilder.Replace("<%COLLCODE%>", collection_code);
            footerBuilder.Replace("<%BIBID%>", bibid);
            footerBuilder.Replace("<%VID%>", vid);
            footerBuilder.Replace("<%MODE%>", mode);
            footerBuilder.Replace("<%MYSOBEK%>", mySobekLinks);
            footerBuilder.Replace("<%CONTACT%>", contact);
            footerBuilder.Replace("<%URLOPTS%>", url_options);
            footerBuilder.Replace("<%?URLOPTS%>", urlOptions1);
            footerBuilder.Replace("<%&URLOPTS%>", urlOptions2);
            footerBuilder.Replace("<%VERSION%>", version);
            footerBuilder.Replace("<%BASEURL%>", base_url);
            footerBuilder.Replace("<%SKINURL%>", skin_url);
            footerBuilder.Replace("<%INSTANCENAME%>", RequestSpecificValues.Current_Mode.Instance_Name);
            footerBuilder.Replace("<%SESSIONID%>", sessionId);
            footerBuilder.Replace("<%USERID%>", userid);
            if ((!useItemFooter) && ( RequestSpecificValues.HTML_Skin.Footer_Has_Container_Directive.HasValue) && (RequestSpecificValues.HTML_Skin.Footer_Has_Container_Directive.Value))
                footerBuilder.Replace("<%CONTAINER%>", "</div>");

            // Write this to the stream
            Output.WriteLine(footerBuilder.ToString().Trim());
        }
        /// <summary> Apply the individual user settings to this static text, replacing all directives with the actual data from this HTTP request </summary>
        /// <param name="Display_Text"> Display text to apply the individual request's settings to </param>
        /// <param name="Aggregation"> Current item aggregation, used for any custom directives which may exist </param>
        /// <param name="Web_Skin_Code"> Code for the current web skin</param>
        /// <param name="Base_Skin_Code"> Code for the base web skin from which the current web skin inherits</param>
        /// <param name="Base_URL"> Base URL for the current request </param>
        /// <param name="URL_Options"> Current URL Options </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <returns> Static text for this info/browse with substitutions made to support the current request </returns>
        /// <remarks> This actually reads the HTML file each time this is requested </remarks>
        public string Apply_Settings_To_Static_Text(string Display_Text, Item_Aggregation Aggregation, string Web_Skin_Code, string Base_Skin_Code, string Base_URL, string URL_Options, Custom_Tracer Tracer)
        {
            //// Replace any item aggregation specific custom directives
            //if ((Aggregation != null) && ( Aggregation.Custom_Directives != null ))
            //{
            //    foreach (string thisKey in Aggregation.Custom_Directives.Keys)
            //    {
            //        if (Display_Text.IndexOf(thisKey) > 0)
            //        {
            //            Display_Text = Display_Text.Replace(thisKey, Aggregation.Custom_Directives[thisKey].Replacement_HTML);
            //        }
            //    }
            //}

            string urlOptions1 = String.Empty;
            string urlOptions2 = String.Empty;
            if (URL_Options.Length > 0)
            {
                urlOptions1 = "?" + URL_Options;
                urlOptions2 = "&" + URL_Options;
            }

            // Replace the standard directives next
            Display_Text = Display_Text.Replace("<%URLOPTS%>", URL_Options).Replace("<%?URLOPTS%>", urlOptions1).Replace("<%&URLOPTS%>", urlOptions2).Replace("<%INTERFACE%>", Web_Skin_Code).Replace("<%WEBSKIN%>", Web_Skin_Code).Replace("<%BASEURL%>", Base_URL);
            Display_Text = Display_Text.Replace("[%URLOPTS%]", URL_Options).Replace("[%?URLOPTS%]", urlOptions1).Replace("[%&URLOPTS%]", urlOptions2).Replace("[%INTERFACE%]", Web_Skin_Code).Replace("[%WEBSKIN%]", Web_Skin_Code).Replace("[%BASEURL%]", Base_URL);

            // Replace some additional (more complex) values
            string tabstart = "<img src=\"" + Base_URL + "design/skins/" + Base_Skin_Code + "/tabs/cLD.gif\" border=\"0\" class=\"tab_image\" /><span class=\"tab\">";
            string tabend = "</span><img src=\"" + Base_URL + "design/skins/" + Base_Skin_Code + "/tabs/cRD.gif\" border=\"0\" class=\"tab_image\" />";
            string select_tabstart = "<img src=\"" + Base_URL + "design/skins/" + Base_Skin_Code + "/tabs/cLD_s.gif\" border=\"0\" class=\"tab_image\" /><span class=\"tab_s\">";
            string select_tabend = "</span><img src=\"" + Base_URL + "design/skins/" + Base_Skin_Code + "/tabs/cRD_s.gif\" border=\"0\" class=\"tab_image\" />";
            Display_Text = Display_Text.Replace("<%TABSTART%>", tabstart).Replace("<%TABEND%>", tabend).Replace("<%SELECTED_TABSTART%>", select_tabstart).Replace("<%SELECTED_TABEND%>", select_tabend);

            if (Display_Text.IndexOf("<body>") >= 0)
            {
                Display_Text = Display_Text.Substring(Display_Text.IndexOf("<body>") + 6);
                Display_Text = Display_Text.Substring(0, Display_Text.IndexOf("</body>"));
            }
            return Display_Text;
        }
        /// <summary> Gets the item aggregation and search fields for the current item aggregation </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        /// <param name="Aggregation_Object"> [OUT] Fully-built object for the current aggregation object </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. </remarks>
        protected static bool Get_Top_Level_Collection(Navigation_Object Current_Mode, Custom_Tracer Tracer, out Item_Aggregation Aggregation_Object)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("abstractHtmlSubwriter.Get_Top_Level_Collection", String.Empty);
            }

            string languageCode = Web_Language_Enum_Converter.Enum_To_Code(Current_Mode.Language);

            // Get the ALL collection group
            try
            {
                // Try to pull this from the cache
                Aggregation_Object = CachedDataManager.Aggregations.Retrieve_Item_Aggregation("all", Web_Language_Enum_Converter.Code_To_Enum(languageCode), Tracer);
                if (Aggregation_Object != null)
                    return true;

                // Get the item aggregation from the Sobek Engine Client
                Aggregation_Object = SobekEngineClient.Aggregations.Get_Aggregation("all", Web_Language_Enum_Converter.Code_To_Enum(languageCode), UI_ApplicationCache_Gateway.Settings.System.Default_UI_Language, Tracer);
            }
            catch (Exception ee)
            {
                Aggregation_Object = null;
                Current_Mode.Error_Message = "Error pulling the item aggregation corresponding to all collection groups : " + ee.Message;
                return false;
            }

            // If this is null, just stop
            if (Aggregation_Object == null)
            {
                Current_Mode.Error_Message = "Unable to pull the item aggregation corresponding to all collection groups";
                return false;
            }

            return true;
        }
        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> Add the search results (and item browses) main menu </summary>
        /// <param name="Output"> Stream to which to write the HTML for this menu </param>
        /// <param name="RequestSpecificValues"> All the necessary, non-global data specific to the current request </param>
        /// <param name="Hierarchy_Object"> Aggregation object for which to show this aggregation search results menu </param>
        /// <param name="Include_Bookshelf_View"> Flag indicates if the bookshelf view should be included in the list of possible views </param>
        public static void Add_Aggregation_Search_Results_Menu(TextWriter Output, RequestCache RequestSpecificValues, Item_Aggregation Hierarchy_Object, bool Include_Bookshelf_View )
        {
            Output.WriteLine("<!-- Add the main search results menu -->");
            Output.WriteLine("<nav id=\"sbkAgm_MenuBar\" class=\"sbkMenu_Bar\" role=\"navigation\" aria-label=\"Search results menu\">");
            Output.WriteLine("<h2 class=\"hidden-element\">Search results menu</h2>");

            // Get ready to draw the tabs
            string home = "Home";
            string collection_home = UI_ApplicationCache_Gateway.Translation.Get_Translation(Hierarchy_Object.ShortName, RequestSpecificValues.Current_Mode.Language) + " Home";
            string sobek_home_text = RequestSpecificValues.Current_Mode.Instance_Abbreviation + " Home";
            string myCollections = "My Collections";
            string otherSearches_text = "Search Options";
            const string list_view_text = "List View";
            const string brief_view_text = "Brief View";
            const string tree_view_text = "Tree View";
            const string partners_text = "Browse Partners";
            string bookshelf_view = "Bookshelf View";
            string brief_view = "Brief View";
            string map_view = "Map View";
            string table_view = "Table View";
            string thumbnail_view = "Thumbnail View";
            const string EXPORT_VIEW = "Export";

            if (RequestSpecificValues.Current_Mode.Language == Web_Language_Enum.Spanish)
            {
                home = "INICIO";
                collection_home = "INICIO " + UI_ApplicationCache_Gateway.Translation.Get_Translation(Hierarchy_Object.ShortName, RequestSpecificValues.Current_Mode.Language);
                sobek_home_text = "INICIO " + RequestSpecificValues.Current_Mode.Instance_Abbreviation.ToUpper();
                myCollections = "MIS COLECCIONES";
                bookshelf_view = "VISTA BIBLIOTECA";
                map_view = "VISTA MAPA";
                brief_view = "VISTA BREVE";
                table_view = "VISTA TABLERA";
                thumbnail_view = "VISTA MINIATURA";
            }

            if (RequestSpecificValues.Current_Mode.Language == Web_Language_Enum.French)
            {
                home = "PAGE D'ACCUEIL";
                sobek_home_text = "PAGE D'ACCUEIL";
                bookshelf_view = "MODE MA BIBLIOTHEQUE";
                map_view = "MODE CARTE";
                brief_view = "MODE SIMPLE";
                table_view = "MODE DE TABLE";
                thumbnail_view = "MODE IMAGETTE";
            }

            // Add the sharing buttons if this is not restricted by IP address or checked out
            if (!RequestSpecificValues.Current_Mode.Is_Robot)
            {
                Output.WriteLine("  <div id=\"menu-right-actions\">");

                string save_text = "Save";
                string send_text = "Send";
                string print_text = "Print";

                Output.WriteLine("    <span id=\"printbutton\" class=\"action-sf-menu-item\" onclick=\"window.print();return false;\"><img src=\"" + Static_Resources_Gateway.Printer_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"printbuttonspan\">" + print_text + "</span></span>");

                if (RequestSpecificValues.Current_Mode.Mode != Display_Mode_Enum.My_Sobek)
                {
                    if ((RequestSpecificValues.Current_User != null) && (RequestSpecificValues.Current_User.LoggedOn))
                    {
                        Output.WriteLine("    <span id=\"sendbutton\" class=\"action-sf-menu-item\" onclick=\"email_form_open();\"><img src=\"" + Static_Resources_Gateway.Email_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"sendbuttonspan\">" + send_text + "</span></span>");

                        Output.WriteLine("    <span id=\"savebutton\" class=\"action-sf-menu-item\" onclick=\"save_search_form_open();\"><img src=\"" + Static_Resources_Gateway.Plussign_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"addbuttonspan\">" + save_text + "</span></span>");
                    }
                    else
                    {
                        string returnUrl = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);
                        Display_Mode_Enum currMode = RequestSpecificValues.Current_Mode.Mode;
                        RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.My_Sobek;
                        RequestSpecificValues.Current_Mode.My_Sobek_Type = My_Sobek_Type_Enum.Logon;
                        RequestSpecificValues.Current_Mode.Return_URL = returnUrl;
                        string logOnUrl = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);
                        RequestSpecificValues.Current_Mode.Mode = currMode;
                        RequestSpecificValues.Current_Mode.Return_URL = String.Empty;

                        Output.WriteLine("    <span id=\"sendbutton\" class=\"action-sf-menu-item\" onclick=\"window.location='" + logOnUrl + "';\"><img src=\"" + Static_Resources_Gateway.Email_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"sendbuttonspan\">" + send_text + "</span></span>");

                        Output.WriteLine("    <span id=\"savebutton\" class=\"action-sf-menu-item\" onclick=\"window.location='" + logOnUrl + "';\"><img src=\"" + Static_Resources_Gateway.Plussign_Png + "\" alt=\"\" style=\"vertical-align:middle\" /><span id=\"addbuttonspan\">" + save_text + "</span></span>");
                    }

                    Output.WriteLine("    <span id=\"sharebutton\" class=\"action-sf-menu-item\" onclick=\"return toggle_share_form2('share_button');\"><span id=\"sharebuttonspan\">Share</span></span>");
                }
                Output.WriteLine("  </div>");
                Output.WriteLine();
            }

            // Save the current mode and browse
            Display_Mode_Enum thisMode = RequestSpecificValues.Current_Mode.Mode;
            Aggregation_Type_Enum thisAggrType = RequestSpecificValues.Current_Mode.Aggregation_Type;
            Search_Type_Enum thisSearch = RequestSpecificValues.Current_Mode.Search_Type;
            Home_Type_Enum thisHomeType = RequestSpecificValues.Current_Mode.Home_Type;
            Result_Display_Type_Enum resultsType = RequestSpecificValues.Current_Mode.Result_Display_Type;
            ushort? page = RequestSpecificValues.Current_Mode.Page;
            string browse_code = RequestSpecificValues.Current_Mode.Info_Browse_Mode;
            string aggregation = RequestSpecificValues.Current_Mode.Aggregation;
            if ((thisMode == Display_Mode_Enum.Aggregation) && ((thisAggrType == Aggregation_Type_Enum.Browse_Info) || (thisAggrType == Aggregation_Type_Enum.Child_Page_Edit)))
            {
                browse_code = RequestSpecificValues.Current_Mode.Info_Browse_Mode;
            }

            // Remove any search string
            string current_search = RequestSpecificValues.Current_Mode.Search_String;
            RequestSpecificValues.Current_Mode.Search_String = String.Empty;

            Output.WriteLine("  <ul class=\"sf-menu\" id=\"sbkAgm_Menu\">");

            // Add any PRE-MENU instance options
            bool pre_menu_options_exist = false;
            string first_pre_menu_option = String.Empty;
            string second_pre_menu_option = String.Empty;
            if (UI_ApplicationCache_Gateway.Settings.Contains_Additional_Setting("Aggregation Viewer.Static First Menu Item"))
                first_pre_menu_option = UI_ApplicationCache_Gateway.Settings.Get_Additional_Setting("Aggregation Viewer.Static First Menu Item");
            if (UI_ApplicationCache_Gateway.Settings.Contains_Additional_Setting("Aggregation Viewer.Static Second Menu Item"))
                second_pre_menu_option = UI_ApplicationCache_Gateway.Settings.Get_Additional_Setting("Aggregation Viewer.Static Second Menu Item");
            if ((first_pre_menu_option.Length > 0) || (second_pre_menu_option.Length > 0))
            {
                pre_menu_options_exist = true;
                if (first_pre_menu_option.Length > 0)
                {
                    string[] first_splitter = first_pre_menu_option.Replace("[", "").Replace("]", "").Split(";".ToCharArray());
                    if (first_splitter.Length > 0)
                    {
                        Output.WriteLine("    <li><a href=\"" + first_splitter[1] + "\" title=\"" + HttpUtility.HtmlEncode(first_splitter[0]) + "\">" + HttpUtility.HtmlEncode(first_splitter[0]) + "</a></li>");
                    }
                }
                if (second_pre_menu_option.Length > 0)
                {
                    string[] second_splitter = second_pre_menu_option.Replace("[", "").Replace("]", "").Split(";".ToCharArray());
                    if (second_splitter.Length > 0)
                    {
                        Output.WriteLine("    <li><a href=\"" + second_splitter[1] + "\" title=\"" + HttpUtility.HtmlEncode(second_splitter[0]) + "\">" + HttpUtility.HtmlEncode(second_splitter[0]) + "</a></li>");
                    }
                }
            }

            // Add the HOME tab
            if ((Hierarchy_Object.Code == "all") || (Hierarchy_Object.Code == RequestSpecificValues.Current_Mode.Default_Aggregation))
            {
                // Add the 'SOBEK HOME' first menu option and suboptions
                RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Aggregation;
                RequestSpecificValues.Current_Mode.Aggregation_Type = Aggregation_Type_Enum.Home;
                RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.List;

                if (Hierarchy_Object.Code == "all")
                {

                    // If some instance-wide pre-menu items existed, don't use the home image
                    if (pre_menu_options_exist)
                    {
                        Output.Write("    <li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + sobek_home_text + "</a>");
                    }
                    else
                    {
                        Output.Write("    <li id=\"sbkAgm_Home\" class=\"sbkMenu_Home\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\" class=\"sbkMenu_NoPadding\"><img src=\"" + Static_Resources_Gateway.Home_Png + "\" alt=\"Home\" /> <div class=\"sbkMenu_HomeText\">" + sobek_home_text + "</div></a>");
                    }

                    if ((UI_ApplicationCache_Gateway.Thematic_Headings != null) && (UI_ApplicationCache_Gateway.Thematic_Headings.Count > 0))
                    {
                        Output.WriteLine("<ul id=\"sbkAgm_HomeSubMenu\">");
                        Output.WriteLine("      <li id=\"sbkAgm_HomeListView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + list_view_text + "</a></li>");
                        RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Descriptions;
                        Output.WriteLine("      <li id=\"sbkAgm_HomeBriefView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + brief_view_text + "</a></li>");
                        if (UI_ApplicationCache_Gateway.Settings.System.Include_TreeView_On_System_Home)
                        {
                            RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Tree;
                            Output.WriteLine("      <li id=\"sbkAgm_HomeTreeView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + tree_view_text + "</a></li>");
                        }
                        Output.WriteLine("    </ul></li>");
                    }
                    else
                    {
                        Output.WriteLine("</li>");
                    }
                }
                else
                {
                    Output.WriteLine("    <li id=\"sbkAgm_Home\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\" class=\"sbkAgm_NoPadding\"><img src=\"" + Static_Resources_Gateway.Home_Png + "\" /> <div class=\"sbkAgm_HomeText\">" + sobek_home_text + "</div></a></li>");
                }
            }
            else
            {

                // Add the 'SOBEK HOME' first menu option and suboptions
                RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Aggregation;
                RequestSpecificValues.Current_Mode.Aggregation_Type = Aggregation_Type_Enum.Home;
                RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.List;

                // If some instance-wide pre-menu items existed, don't use the home image
                if (pre_menu_options_exist)
                {
                    Output.WriteLine("    <li id=\"sbkAgm_Home\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + home + "</a><ul id=\"sbkAgm_HomeSubMenu\">");
                }
                else
                {
                    Output.WriteLine("    <li id=\"sbkAgm_Home\" class=\"sbkMenu_Home\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\" class=\"sbkMenu_NoPadding\"><img src=\"" + Static_Resources_Gateway.Home_Png + "\" alt=\"Home\" /> <div class=\"sbkMenu_HomeText\">" + home + "</div></a><ul id=\"sbkAgm_HomeSubMenu\">");
                }

                Output.WriteLine("      <li id=\"sbkAgm_AggrHome\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + collection_home + "</a></li>");

                RequestSpecificValues.Current_Mode.Aggregation = String.Empty;
                if (RequestSpecificValues.Current_Mode.Default_Aggregation != "all")
                {
                    Output.WriteLine("      <li id=\"sbkAgm_InstanceHome\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + sobek_home_text + "</a></li>");
                }
                else
                {
                    Output.WriteLine("      <li id=\"sbkAgm_InstanceHome\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + sobek_home_text + "</a><ul id=\"sbkAgm_InstanceHomeSubMenu\">");

                    if ((UI_ApplicationCache_Gateway.Thematic_Headings != null) && (UI_ApplicationCache_Gateway.Thematic_Headings.Count > 0))
                    {
                        Output.WriteLine("        <li id=\"sbkAgm_HomeListView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + list_view_text + "</a></li>");
                        RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Descriptions;
                        Output.WriteLine("        <li id=\"sbkAgm_HomeBriefView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + brief_view_text + "</a></li>");
                        if (UI_ApplicationCache_Gateway.Settings.System.Include_TreeView_On_System_Home)
                        {
                            RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Tree;
                            Output.WriteLine("        <li id=\"sbkAgm_HomeTreeView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + tree_view_text + "</a></li>");
                        }
                    }
                    else
                    {
                        Output.WriteLine("        <li id=\"sbkAgm_HomeListView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + sobek_home_text + "</a></li>");
                    }
                    if ((RequestSpecificValues.Current_User != null) && (RequestSpecificValues.Current_User.LoggedOn))
                    {
                        RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Personalized;
                        Output.WriteLine("        <li id=\"sbkAgm_HomePersonalized\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + myCollections + "</a></li>");
                    }
                    if (UI_ApplicationCache_Gateway.Settings.System.Include_Partners_On_System_Home)
                    {
                        RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Partners_List;
                        Output.WriteLine("        <li id=\"sbkAgm_HomePartners\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + partners_text + "</a></li>");
                    }
                    Output.WriteLine("      </ul></li>");
                }

                Output.WriteLine("    </ul></li>");

                RequestSpecificValues.Current_Mode.Aggregation = Hierarchy_Object.Code;
            }

            // Add any additional search types
            RequestSpecificValues.Current_Mode.Mode = thisMode;
            List<string> other_searches = new List<string>();
            for (int i = 1; i < Hierarchy_Object.Views_And_Searches.Count; i++)
            {
                other_searches.Add(Aggregation_Nav_Bar_HTML_Factory.Menu_Get_Nav_Bar_HTML(Hierarchy_Object.Views_And_Searches[i], RequestSpecificValues.Current_Mode, UI_ApplicationCache_Gateway.Translation));
            }
            if (other_searches.Count == 1)
            {
                Output.WriteLine(other_searches[0]);
            }
            else if (other_searches.Count > 1)
            {
                Output.WriteLine("    <li><a href=\"\">" + otherSearches_text + "</a><ul id=\"sbkAgm_SearchSubMenu\">");
                foreach (string thisOtherSearch in other_searches)
                {
                    Output.Write("      " + thisOtherSearch);
                }

                Output.WriteLine("    </ul></li>");
            }

            // Replace any search string
            RequestSpecificValues.Current_Mode.Search_String = current_search;
            RequestSpecificValues.Current_Mode.Info_Browse_Mode = browse_code;
            RequestSpecificValues.Current_Mode.Aggregation_Type = thisAggrType;
            RequestSpecificValues.Current_Mode.Search_Type = thisSearch;
            RequestSpecificValues.Current_Mode.Mode = thisMode;
            RequestSpecificValues.Current_Mode.Home_Type = thisHomeType;
            RequestSpecificValues.Current_Mode.Result_Display_Type = resultsType;
            RequestSpecificValues.Current_Mode.Aggregation = aggregation;
            RequestSpecificValues.Current_Mode.Page = page;

            Result_Display_Type_Enum resultView = RequestSpecificValues.Current_Mode.Result_Display_Type;
            if (Include_Bookshelf_View)
            {
                if (resultView == Result_Display_Type_Enum.Bookshelf)
                {
                    Output.WriteLine("    <li class=\"selected-sf-menu-item-link\"><a href=\"\">" + bookshelf_view + "</a></li>");
                }
                else
                {
                    RequestSpecificValues.Current_Mode.Result_Display_Type = Result_Display_Type_Enum.Bookshelf;
                    Output.WriteLine("    <li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode).Replace("&", "&amp;") + "\">" + bookshelf_view + "</a></li>");
                }
            }

            if (( !String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.Coordinates)) || (Hierarchy_Object.Result_Views.Contains(Result_Display_Type_Enum.Map)))
            {
                if (resultView == Result_Display_Type_Enum.Map)
                {
                    Output.WriteLine("    <li class=\"selected-sf-menu-item-link\"><a href=\"\">" + map_view + "</a></li>");
                }
                else
                {
                    RequestSpecificValues.Current_Mode.Result_Display_Type = Result_Display_Type_Enum.Map;
                    Output.WriteLine("    <li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode).Replace("&", "&amp;") + "\">" + map_view + "</a></li>");
                }
            }

            if (Hierarchy_Object.Result_Views.Contains(Result_Display_Type_Enum.Brief))
            {
                if (resultView == Result_Display_Type_Enum.Brief)
                {
                    Output.WriteLine("    <li class=\"selected-sf-menu-item-link\"><a href=\"\">" + brief_view + "</a></li>");
                }
                else
                {
                    RequestSpecificValues.Current_Mode.Result_Display_Type = Result_Display_Type_Enum.Brief;
                    Output.WriteLine("    <li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode).Replace("&", "&amp;") + "\">" + brief_view + "</a></li>");
                }
            }

            if (Hierarchy_Object.Result_Views.Contains(Result_Display_Type_Enum.Table))
            {
                if (resultView == Result_Display_Type_Enum.Table)
                {
                    Output.WriteLine("    <li class=\"selected-sf-menu-item-link\"><a href=\"\">" + table_view + "</a></li>");
                }
                else
                {
                    RequestSpecificValues.Current_Mode.Result_Display_Type = Result_Display_Type_Enum.Table;
                    Output.WriteLine("    <li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode).Replace("&", "&amp;") + "\">" + table_view + "</a></li>");
                }
            }

            if (Hierarchy_Object.Result_Views.Contains(Result_Display_Type_Enum.Thumbnails))
            {
                if (resultView == Result_Display_Type_Enum.Thumbnails)
                {
                    Output.WriteLine("    <li class=\"selected-sf-menu-item-link\"><a href=\"\">" + thumbnail_view + "</a></li>");
                }
                else
                {
                    RequestSpecificValues.Current_Mode.Result_Display_Type = Result_Display_Type_Enum.Thumbnails;
                    Output.WriteLine("    <li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode).Replace("&", "&amp;") + "\">" + thumbnail_view + "</a></li>");
                }
            }

            if ((Include_Bookshelf_View) && ((resultView == Result_Display_Type_Enum.Export) || (RequestSpecificValues.Current_Mode.Writer_Type == Writer_Type_Enum.HTML_LoggedIn)))
            {
                RequestSpecificValues.Current_Mode.Page = 1;
                if (resultView == Result_Display_Type_Enum.Export)
                {
                    Output.WriteLine("    <li class=\"selected-sf-menu-item-link\"><a href=\"\">" + EXPORT_VIEW + "</a></li>");
                }
                else
                {
                    RequestSpecificValues.Current_Mode.Result_Display_Type = Result_Display_Type_Enum.Export;
                    Output.WriteLine("    <li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode).Replace("&", "&amp;") + "\">" + EXPORT_VIEW + "</a></li>");
                }
            }

            // Return the code and mode back
            RequestSpecificValues.Current_Mode.Info_Browse_Mode = browse_code;
            RequestSpecificValues.Current_Mode.Aggregation_Type = thisAggrType;
            RequestSpecificValues.Current_Mode.Search_Type = thisSearch;
            RequestSpecificValues.Current_Mode.Mode = thisMode;
            RequestSpecificValues.Current_Mode.Home_Type = thisHomeType;
            RequestSpecificValues.Current_Mode.Result_Display_Type = resultsType;
            RequestSpecificValues.Current_Mode.Aggregation = aggregation;
            RequestSpecificValues.Current_Mode.Page = page;

            Output.WriteLine("  </ul>");
            Output.WriteLine("</nav>");
            Output.WriteLine();

            Output.WriteLine("<!-- Initialize the main user menu -->");
            Output.WriteLine("<script>");
            Output.WriteLine("  jQuery(document).ready(function () {");
            Output.WriteLine("     jQuery('ul.sf-menu').superfish({");

            Output.WriteLine("          onBeforeShow: function() { ");
            Output.WriteLine("               if ( $(this).attr('id') == 'sbkAgm_SubCollectionsMenu')");
            Output.WriteLine("               {");
            Output.WriteLine("                 var thisWidth = $(this).width();");
            Output.WriteLine("                 var parent = $('#sbkAgm_SubCollections');");
            Output.WriteLine("                 var offset = $('#sbkAgm_SubCollections').offset();");
            Output.WriteLine("                 if ( $(window).width() < offset.left + thisWidth )");
            Output.WriteLine("                 {");
            Output.WriteLine("                   var newleft = thisWidth - parent.width();");
            Output.WriteLine("                   $(this).css('left', '-' + newleft + 'px');");
            Output.WriteLine("                 }");
            Output.WriteLine("               }");
            Output.WriteLine("          }");

            Output.WriteLine("    });");
            Output.WriteLine("  });");
            Output.WriteLine("</script>");
            Output.WriteLine();
        }
        /// <summary> Add the aggregation-level main menu </summary>
        /// <param name="Output"> Stream to which to write the HTML for this menu </param>
        /// <param name="RequestSpecificValues"> All the necessary, non-global data specific to the current request </param>
        /// <param name="Hierarchy_Object"> Aggregation object for which to show this aggregation main menu </param>
        public static void Add_Aggregation_Main_Menu(TextWriter Output, RequestCache RequestSpecificValues, Item_Aggregation Hierarchy_Object )
        {
            Output.WriteLine("<!-- Add the main aggregation menu -->");
            Output.WriteLine("<nav id=\"sbkAgm_MenuBar\" class=\"sbkMenu_Bar\" role=\"navigation\" aria-label=\"Aggregation menu\">");
            Output.WriteLine("<h2 class=\"hidden-element\">Aggregation menu</h2>");
            Output.WriteLine("  <ul class=\"sf-menu\" id=\"sbkAgm_Menu\">");

            // Get ready to draw the tabs
            string home = "Home";
            string collection_home = UI_ApplicationCache_Gateway.Translation.Get_Translation(Hierarchy_Object.ShortName, RequestSpecificValues.Current_Mode.Language ) + " Home";
            string sobek_home_text = RequestSpecificValues.Current_Mode.Instance_Abbreviation + " Home";
            string viewItems = "View Items";
            string allItems = "View All Items";
            string newItems = "View Recently Added Items";
            string myCollections = "My Collections";
            string partners = "Browse Partners";
            string browseBy = "Browse By";
            const string BROWSE_MAP = "Map Browse";
            const string list_view_text = "List View";
            const string brief_view_text = "Brief View";
            const string tree_view_text = "Tree View";
            const string partners_text = "Browse Partners";

            if (RequestSpecificValues.Current_Mode.Language == Web_Language_Enum.Spanish)
            {
                home = "INICIO";
                collection_home = "INICIO " + UI_ApplicationCache_Gateway.Translation.Get_Translation(Hierarchy_Object.ShortName, RequestSpecificValues.Current_Mode.Language);
                sobek_home_text = "INICIO " + RequestSpecificValues.Current_Mode.Instance_Abbreviation.ToUpper();
                allItems = "TODOS LOS ARTÍCULOS";
                newItems = "NUEVOS ARTÍCULOS";
                browseBy = "BÚSQUEDA POR";
                partners = "AFILIADOS";
                myCollections = "MIS COLECCIONES";
                viewItems = "VER ARTÍCULOS";
            }

            if (RequestSpecificValues.Current_Mode.Language == Web_Language_Enum.French)
            {
                home = "PAGE D'ACCUEIL";
                sobek_home_text = "PAGE D'ACCUEIL";
                allItems = "TOUS LES ARTICLES";
                newItems = "NOUVEAUX ARTICLES";
                browseBy = "PARCOURIR PAR";
                viewItems = "VOIR ARTICLES";
            }

            // Save the current mode and browse
            Display_Mode_Enum thisMode = RequestSpecificValues.Current_Mode.Mode;
            Aggregation_Type_Enum thisAggrType = RequestSpecificValues.Current_Mode.Aggregation_Type;
            Search_Type_Enum thisSearch = RequestSpecificValues.Current_Mode.Search_Type;
            Home_Type_Enum thisHomeType = RequestSpecificValues.Current_Mode.Home_Type;
            Result_Display_Type_Enum resultsType = RequestSpecificValues.Current_Mode.Result_Display_Type;
            ushort? page = RequestSpecificValues.Current_Mode.Page;
            string browse_code = RequestSpecificValues.Current_Mode.Info_Browse_Mode;
            string aggregation = RequestSpecificValues.Current_Mode.Aggregation;
            if ((thisMode == Display_Mode_Enum.Aggregation) && ((thisAggrType == Aggregation_Type_Enum.Browse_Info) || (thisAggrType == Aggregation_Type_Enum.Child_Page_Edit)))
            {
                browse_code = RequestSpecificValues.Current_Mode.Info_Browse_Mode;
            }

            // Get the home search type (just to do a matching in case it was explicitly requested)
            Item_Aggregation_Views_Searches_Enum homeView = Item_Aggregation_Views_Searches_Enum.Basic_Search;
            if (Hierarchy_Object.Views_And_Searches.Count > 0)
            {
                homeView = Hierarchy_Object.Views_And_Searches[0];
            }

            // Remove any search string
            string current_search = RequestSpecificValues.Current_Mode.Search_String;
            RequestSpecificValues.Current_Mode.Search_String = String.Empty;

            // Add any PRE-MENU instance options
            bool pre_menu_options_exist = false;
            string first_pre_menu_option = String.Empty;
            string second_pre_menu_option = String.Empty;
            if (UI_ApplicationCache_Gateway.Settings.Contains_Additional_Setting("Aggregation Viewer.Static First Menu Item"))
                first_pre_menu_option = UI_ApplicationCache_Gateway.Settings.Get_Additional_Setting("Aggregation Viewer.Static First Menu Item");
            if (UI_ApplicationCache_Gateway.Settings.Contains_Additional_Setting("Aggregation Viewer.Static Second Menu Item"))
                second_pre_menu_option = UI_ApplicationCache_Gateway.Settings.Get_Additional_Setting("Aggregation Viewer.Static Second Menu Item");
            if ((first_pre_menu_option.Length > 0) || (second_pre_menu_option.Length > 0))
            {
                pre_menu_options_exist = true;
                if (first_pre_menu_option.Length > 0)
                {
                    string[] first_splitter = first_pre_menu_option.Replace("[", "").Replace("]", "").Split(";".ToCharArray());
                    if (first_splitter.Length > 0)
                    {
                        Output.WriteLine("    <li><a href=\"" + first_splitter[1] + "\" title=\"" + HttpUtility.HtmlEncode(first_splitter[0]) + "\">" + HttpUtility.HtmlEncode(first_splitter[0]) + "</a></li>");
                    }
                }
                if (second_pre_menu_option.Length > 0)
                {
                    string[] second_splitter = second_pre_menu_option.Replace("[", "").Replace("]", "").Split(";".ToCharArray());
                    if (second_splitter.Length > 0)
                    {
                        Output.WriteLine("    <li><a href=\"" + second_splitter[1] + "\" title=\"" + HttpUtility.HtmlEncode(second_splitter[0]) + "\">" + HttpUtility.HtmlEncode(second_splitter[0]) + "</a></li>");
                    }
                }
            }

            bool isOnHome = (((RequestSpecificValues.Current_Mode.Mode == Display_Mode_Enum.Aggregation) && (RequestSpecificValues.Current_Mode.Aggregation_Type == Aggregation_Type_Enum.Home)) ||
                 ((RequestSpecificValues.Current_Mode.Mode == Display_Mode_Enum.Search) &&
                  (Aggregation_Nav_Bar_HTML_Factory.Do_Search_Types_Match(homeView, RequestSpecificValues.Current_Mode.Search_Type))));

            // Add the HOME tab
            if ((Hierarchy_Object.Code == "all") || ( Hierarchy_Object.Code == RequestSpecificValues.Current_Mode.Default_Aggregation))
            {
                // Add the 'SOBEK HOME' first menu option and suboptions
                RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Aggregation;
                RequestSpecificValues.Current_Mode.Aggregation_Type = Aggregation_Type_Enum.Home;
                RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.List;

                if (Hierarchy_Object.Code == "all")
                {
                    // What is considered HOME changes here at the top level
                    if ((thisHomeType == Home_Type_Enum.Partners_List) || (thisHomeType == Home_Type_Enum.Partners_Thumbnails) || (thisHomeType == Home_Type_Enum.Personalized))
                        isOnHome = false;

                    // If some instance-wide pre-menu items existed, don't use the home image
                    if (pre_menu_options_exist)
                    {
                        if (isOnHome)
                            Output.Write("    <li id=\"selected-sf-menu-item-link\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + sobek_home_text + "</a>");
                        else
                            Output.Write("    <li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + sobek_home_text + "</a>");
                    }
                    else
                    {
                        if ( isOnHome )
                            Output.Write("    <li id=\"sbkAgm_Home\" class=\"sbkMenu_Home selected-sf-menu-item-link\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\" class=\"sbkMenu_NoPadding\"><img src=\"" + Static_Resources_Gateway.Home_Png + "\" alt=\"Home\" /> <div class=\"sbkMenu_HomeText\">" + sobek_home_text + "</div></a>");
                        else
                            Output.Write("    <li id=\"sbkAgm_Home\" class=\"sbkMenu_Home\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\" class=\"sbkMenu_NoPadding\"><img src=\"" + Static_Resources_Gateway.Home_Png + "\" alt=\"Home\" /> <div class=\"sbkMenu_HomeText\">" + sobek_home_text + "</div></a>");
                    }

                    if (( UI_ApplicationCache_Gateway.Thematic_Headings != null ) && ( UI_ApplicationCache_Gateway.Thematic_Headings.Count > 0 ))
                    {
                        Output.WriteLine("<ul id=\"sbkAgm_HomeSubMenu\">");
                        Output.WriteLine("      <li id=\"sbkAgm_HomeListView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + list_view_text + "</a></li>");
                        RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Descriptions;
                        Output.WriteLine("      <li id=\"sbkAgm_HomeBriefView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + brief_view_text + "</a></li>");
                        if (UI_ApplicationCache_Gateway.Settings.System.Include_TreeView_On_System_Home)
                        {
                            RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Tree;
                            Output.WriteLine("      <li id=\"sbkAgm_HomeTreeView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + tree_view_text + "</a></li>");
                        }
                        Output.WriteLine("    </ul></li>");
                    }
                    else
                    {
                        Output.WriteLine("</li>");
                    }
                }
                else
                {
                    Output.WriteLine("    <li id=\"sbkAgm_Home\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\" class=\"sbkAgm_NoPadding\"><img src=\"" + Static_Resources_Gateway.Home_Png + "\" alt=\"\" /> <div class=\"sbkAgm_HomeText\">" + sobek_home_text + "</div></a></li>");
                }
            }
            else
            {

                // Add the 'SOBEK HOME' first menu option and suboptions
                RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Aggregation;
                RequestSpecificValues.Current_Mode.Aggregation_Type = Aggregation_Type_Enum.Home;
                RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.List;

                // If some instance-wide pre-menu items existed, don't use the home image
                if (pre_menu_options_exist)
                {
                    if (isOnHome)
                    {
                        Output.WriteLine("    <li id=\"sbkAgm_Home\" class=\"selected-sf-menu-item-link\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + home + "</a><ul id=\"sbkAgm_HomeSubMenu\">");
                    }
                    else
                    {
                        Output.WriteLine("    <li id=\"sbkAgm_Home\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + home + "</a><ul id=\"sbkAgm_HomeSubMenu\">");
                    }
                }
                else
                {
                    if (isOnHome)
                    {
                        Output.WriteLine("    <li id=\"sbkAgm_Home\" class=\"selected-sf-menu-item-link sbkMenu_Home\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\" class=\"sbkMenu_NoPadding\"><img src=\"" + Static_Resources_Gateway.Home_Png + "\" alt=\"Home\" /> <div class=\"sbkMenu_HomeText\">" + home + "</div></a><ul id=\"sbkAgm_HomeSubMenu\">");
                    }
                    else
                    {
                        Output.WriteLine("    <li id=\"sbkAgm_Home\" class=\"sbkMenu_Home\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\" class=\"sbkMenu_NoPadding\"><img src=\"" + Static_Resources_Gateway.Home_Png + "\" alt=\"Home\" /> <div class=\"sbkMenu_HomeText\">" + home + "</div></a><ul id=\"sbkAgm_HomeSubMenu\">");
                    }
                }

                Output.WriteLine("      <li id=\"sbkAgm_AggrHome\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + collection_home + "</a></li>");

                RequestSpecificValues.Current_Mode.Aggregation = String.Empty;
                if (RequestSpecificValues.Current_Mode.Default_Aggregation != "all")
                {
                    Output.WriteLine("      <li id=\"sbkAgm_InstanceHome\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + sobek_home_text + "</a></li>");
                }
                else
                {
                    Output.Write("      <li id=\"sbkAgm_InstanceHome\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + sobek_home_text + "</a>");
                    Output.WriteLine("<ul id=\"sbkAgm_InstanceHomeSubMenu\">");

                    if ((UI_ApplicationCache_Gateway.Thematic_Headings != null) && (UI_ApplicationCache_Gateway.Thematic_Headings.Count > 0))
                    {
                        Output.WriteLine("        <li id=\"sbkAgm_HomeListView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + list_view_text + "</a></li>");
                        RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Descriptions;
                        Output.WriteLine("        <li id=\"sbkAgm_HomeBriefView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + brief_view_text + "</a></li>");
                        if (UI_ApplicationCache_Gateway.Settings.System.Include_TreeView_On_System_Home)
                        {
                            RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Tree;
                            Output.WriteLine("        <li id=\"sbkAgm_HomeTreeView\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + tree_view_text + "</a></li>");
                        }
                    }
                    if ((RequestSpecificValues.Current_User != null) && (RequestSpecificValues.Current_User.LoggedOn))
                    {
                        RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Personalized;
                        Output.WriteLine("        <li id=\"sbkAgm_HomePersonalized\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + myCollections + "</a></li>");
                    }
                    if (UI_ApplicationCache_Gateway.Settings.System.Include_Partners_On_System_Home)
                    {
                        RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Partners_List;
                        Output.WriteLine("        <li id=\"sbkAgm_HomePartners\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + partners_text + "</a></li>");
                    }
                    Output.WriteLine("      </ul></li>");
                }

                Output.WriteLine("    </ul></li>");

                RequestSpecificValues.Current_Mode.Aggregation = Hierarchy_Object.Code;
            }

            // Add any additional search types
            RequestSpecificValues.Current_Mode.Mode = thisMode;
            for (int i = 1; i < Hierarchy_Object.Views_And_Searches.Count; i++)
            {
                Output.Write("    " + Aggregation_Nav_Bar_HTML_Factory.Menu_Get_Nav_Bar_HTML(Hierarchy_Object.Views_And_Searches[i], RequestSpecificValues.Current_Mode, UI_ApplicationCache_Gateway.Translation));
            }

            // Replace any search string
            RequestSpecificValues.Current_Mode.Search_String = current_search;

            // Check for the existence of any BROWSE BY pages
            if (Hierarchy_Object.Has_Browse_By_Pages)
            {
                RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Aggregation;
                RequestSpecificValues.Current_Mode.Aggregation_Type = Aggregation_Type_Enum.Browse_By;
                RequestSpecificValues.Current_Mode.Info_Browse_Mode = String.Empty;

                // Get sorted collection of (public) browse bys linked to this aggregation
                ReadOnlyCollection<Item_Aggregation_Child_Page> public_browses = Hierarchy_Object.Browse_By_Pages;
                if (public_browses.Count > 0)
                {
                    if (((thisMode == Display_Mode_Enum.Aggregation) && (thisAggrType == Aggregation_Type_Enum.Browse_By)) || (RequestSpecificValues.Current_Mode.Is_Robot))
                    {
                        Output.WriteLine("    <li id=\"sbkAgm_BrowseBy\" class=\"selected-sf-menu-item-link\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + browseBy + "</a><ul id=\"sbkAgm_BrowseBySubMenu\">");
                    }
                    else
                    {
                        Output.WriteLine("    <li id=\"sbkAgm_BrowseBy\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + browseBy + "</a><ul id=\"sbkAgm_BrowseBySubMenu\">");
                    }

                    foreach (Item_Aggregation_Child_Page thisBrowse in public_browses)
                    {
                        // Static HTML or metadata browse by?
                        if (thisBrowse.Source_Data_Type == Item_Aggregation_Child_Source_Data_Enum.Static_HTML)
                        {
                            RequestSpecificValues.Current_Mode.Info_Browse_Mode = thisBrowse.Code;
                            Output.WriteLine("      <li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode).Replace("&", "&amp") + "\">" + thisBrowse.Label + "</a></li>");
                        }
                        else
                        {
                            Metadata_Search_Field facetField = UI_ApplicationCache_Gateway.Settings.Metadata_Search_Field_By_Display_Name(thisBrowse.Code);
                            if (facetField != null)
                            {
                                RequestSpecificValues.Current_Mode.Info_Browse_Mode = thisBrowse.Code.ToLower().Replace(" ", "_");
                                Output.WriteLine("      <li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode).Replace("&", "&amp") + "\">" + facetField.Display_Term + "</a></li>");
                            }
                        }
                    }

                    Output.WriteLine("    </ul></li>");
                }
            }

            // Check for the existence of any MAP BROWSE pages
            if (Hierarchy_Object.Views_And_Searches.Contains(Item_Aggregation_Views_Searches_Enum.Map_Browse))
            {
                RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Aggregation;
                RequestSpecificValues.Current_Mode.Aggregation_Type = Aggregation_Type_Enum.Browse_Map;
                RequestSpecificValues.Current_Mode.Info_Browse_Mode = String.Empty;

                if ((thisMode == Display_Mode_Enum.Aggregation) && (thisAggrType == Aggregation_Type_Enum.Browse_Map))
                {
                    Output.WriteLine("    <li id=\"sbkAgm_MapBrowse\" class=\"selected-sf-menu-item-link\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + BROWSE_MAP + "</a></li>");
                }
                else
                {
                    Output.WriteLine("    <li id=\"sbkAgm_MapBrowse\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + BROWSE_MAP + "</a></li>");
                }
            }

            // Add all the browses and child pages
            RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Aggregation;
            RequestSpecificValues.Current_Mode.Aggregation_Type = Aggregation_Type_Enum.Browse_Info;

            // Find the URL for all these browses
            RequestSpecificValues.Current_Mode.Info_Browse_Mode = "XYXYXYXYXY";
            string redirect_url = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);
            RequestSpecificValues.Current_Mode.Page = 1;
               // RequestSpecificValues.Current_Mode.Mode = thisMode;

            // Only show ALL and NEW if they are in the collection list of searches and views
            int included_browses = 0;
            if (Hierarchy_Object.Views_And_Searches.Contains(Item_Aggregation_Views_Searches_Enum.All_New_Items))
            {
                // First, look for 'ALL'
                if (Hierarchy_Object.Contains_Browse_Info("all"))
                {
                    bool includeNew = ((Hierarchy_Object.Contains_Browse_Info("new")) && (!RequestSpecificValues.Current_Mode.Is_Robot));
                    if (includeNew)
                    {
                        if (( thisMode == Display_Mode_Enum.Aggregation ) && ((browse_code == "all") || (browse_code == "new" )))
                        {
                            Output.WriteLine("    <li id=\"sbkAgm_ViewItems\" class=\"selected-sf-menu-item-link\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", "all").Replace("/info/", "/") + "\">" + viewItems + "</a><ul id=\"sbkAgm_ViewItemsSubMenu\">");
                        }
                        else
                        {
                            Output.WriteLine("    <li id=\"sbkAgm_ViewItems\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", "all").Replace("/info/", "/") + "\">" + viewItems + "</a><ul id=\"sbkAgm_ViewItemsSubMenu\">");
                        }

                        Output.WriteLine("    <li id=\"sbkAgm_AllBrowse\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", "all").Replace("/info/", "/") + "\">" + allItems + "</a></li>");
                        Output.WriteLine("    <li id=\"sbkAgm_NewBrowse\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", "new").Replace("/info/", "/") + "\">" + newItems + "</a></li>");

                        Output.WriteLine("    </ul></li>");
                    }
                    else
                    {
                        if (( thisMode == Display_Mode_Enum.Aggregation ) && (browse_code == "all"))
                        {
                            Output.WriteLine("    <li id=\"sbkAgm_ViewItems\" class=\"selected-sf-menu-item-link\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", "all").Replace("/info/", "/") + "\">" + viewItems + "</a></li>");
                        }
                        else
                        {
                            Output.WriteLine("    <li id=\"sbkAgm_ViewItems\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", "all").Replace("/info/", "/") + "\">" + viewItems + "</a></li>");
                        }
                    }

                    included_browses++;
                }
            }

            RequestSpecificValues.Current_Mode.Result_Display_Type = Result_Display_Type_Enum.NONE;
            redirect_url = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);

            // Are there any additional browses to include?
            ReadOnlyCollection<Item_Aggregation_Child_Page> otherBrowses = Hierarchy_Object.Browse_Home_Pages;
            if (otherBrowses.Count > included_browses)
            {
                // Determine the hierarchy
                List<Item_Aggregation_Child_Page> menuPages = new List<Item_Aggregation_Child_Page>();
                List<Item_Aggregation_Child_Page> topPages = new List<Item_Aggregation_Child_Page>();
                Dictionary<string, Item_Aggregation_Child_Page> pagesDictionary = new Dictionary<string, Item_Aggregation_Child_Page>();
                Dictionary<Item_Aggregation_Child_Page, List<Item_Aggregation_Child_Page>> parentToChild = new Dictionary<Item_Aggregation_Child_Page, List<Item_Aggregation_Child_Page>>();

                // Now, step through the sorted list
                foreach (Item_Aggregation_Child_Page thisBrowseObj in otherBrowses.Where(ThisBrowseObj => (ThisBrowseObj.Code != "all") && (ThisBrowseObj.Code != "new")))
                {
                    // Add to the list, to avoid re-iterating through this
                    menuPages.Add(thisBrowseObj);

                    // Add this child page to the dictionary
                    pagesDictionary.Add(thisBrowseObj.Code.ToLower(), thisBrowseObj);

                    // Is this a  top-level page?
                    if (String.IsNullOrEmpty(thisBrowseObj.Parent_Code))
                        topPages.Add(thisBrowseObj);
                }

                // Now, build the hierarchy
                foreach (Item_Aggregation_Child_Page thisPage in menuPages)
                {
                    if (!String.IsNullOrEmpty(thisPage.Parent_Code))
                    {
                        if (pagesDictionary.ContainsKey(thisPage.Parent_Code.ToLower()))
                        {
                            Item_Aggregation_Child_Page parentPage = pagesDictionary[thisPage.Parent_Code.ToLower()];
                            if (!parentToChild.ContainsKey(parentPage))
                                parentToChild[parentPage] = new List<Item_Aggregation_Child_Page>();
                            parentToChild[parentPage].Add(thisPage);
                        }
                    }
                }

                // Now, add each top-level page, with children
                foreach (Item_Aggregation_Child_Page topPage in topPages)
                {
                    RequestSpecificValues.Current_Mode.Info_Browse_Mode = topPage.Code;
                    bool selected = false;
                    if (browse_code == topPage.Code)
                        selected = true;
                    else
                    {
                        if ((parentToChild.ContainsKey(topPage)) && (parentToChild[topPage].Count > 0))
                        {
                            foreach (Item_Aggregation_Child_Page middlePages in parentToChild[topPage])
                            {
                                if (browse_code == middlePages.Code)
                                {
                                    selected = true;
                                }
                            }
                        }
                    }

                    if (selected)
                    {
                        Output.Write("    <li id=\"sbkAgm_" + topPage.Code.Replace(" ", "") + "Browse\" class=\"selected-sf-menu-item-link\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", topPage.Code) + "\">" + topPage.Label + "</a>");
                    }
                    else
                    {

                        Output.Write("    <li id=\"sbkAgm_" + topPage.Code.Replace(" ", "") + "Browse\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", topPage.Code) + "\">" + topPage.Label + "</a>");
                    }

                    if ((parentToChild.ContainsKey(topPage)) && ( parentToChild[topPage].Count > 0 ))
                    {
                        Output.WriteLine("<ul id=\"sbkAgm_" + topPage.Code.Replace(" ", "") + " + SubMenu\">");
                        foreach (Item_Aggregation_Child_Page middlePages in parentToChild[topPage])
                        {
                            RequestSpecificValues.Current_Mode.Info_Browse_Mode = middlePages.Code;
                            if (browse_code == middlePages.Code)
                            {
                                Output.Write("    <li id=\"sbkAgm_" + middlePages.Code.Replace(" ", "") + "Browse\" class=\"selected-sf-menu-item-link submenu-item-selected\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", middlePages.Code) + "\">" + middlePages.Label + "</a>");
                            }
                            else
                            {
                                Output.Write("    <li id=\"sbkAgm_" + middlePages.Code.Replace(" ", "") + "Browse\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", middlePages.Code) + "\">" + middlePages.Label + "</a>");
                            }

                            if ((parentToChild.ContainsKey(middlePages)) && (parentToChild[middlePages].Count > 0))
                            {
                                Output.WriteLine("<ul id=\"sbkAgm_" + middlePages.Code.Replace(" ", "") + " + SubMenu\">");
                                foreach (Item_Aggregation_Child_Page bottomPages in parentToChild[middlePages])
                                {
                                    RequestSpecificValues.Current_Mode.Info_Browse_Mode = bottomPages.Code;
                                    if (browse_code == bottomPages.Code)
                                    {
                                        Output.Write("    <li id=\"sbkAgm_" + bottomPages.Code.Replace(" ", "") + "Browse\" class=\"selected-sf-menu-item-link submenu-item-selected\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", bottomPages.Code) + "\">" + bottomPages.Label + "</a></li>");
                                    }
                                    else
                                    {
                                        Output.Write("    <li id=\"sbkAgm_" + bottomPages.Code.Replace(" ", "") + "Browse\"><a href=\"" + redirect_url.Replace("XYXYXYXYXY", bottomPages.Code) + "\">" + bottomPages.Label + "</a></li>");
                                    }
                                }
                                Output.Write("    </ul>");
                            }
                            Output.WriteLine("</li>");
                        }
                        Output.Write("    </ul>");
                    }

                    Output.WriteLine("</li>");
                }
            }

            // If this is NOT the all collection, then show subcollections
            if ((Hierarchy_Object.Code != "all") && (Hierarchy_Object.Children_Count > 0))
            {
                // Verify some of the children are active and not hidden
                // Keep the last aggregation alias
                string lastAlias = RequestSpecificValues.Current_Mode.Aggregation_Alias;
                RequestSpecificValues.Current_Mode.Aggregation_Alias = String.Empty;
                RequestSpecificValues.Current_Mode.Info_Browse_Mode = String.Empty;

                // Collect the html to write (this alphabetizes the children)
                List<string> html_list = new List<string>();
                foreach (Item_Aggregation_Related_Aggregations childAggr in Hierarchy_Object.Children)
                {
                    Item_Aggregation_Related_Aggregations latest = UI_ApplicationCache_Gateway.Aggregations[childAggr.Code];
                    if ((latest != null) && (!latest.Hidden) && (latest.Active))
                    {
                        string name = childAggr.ShortName;
                        if (name.ToUpper() == "ADDED AUTOMATICALLY")
                            name = childAggr.Code + " ( Added Automatically )";

                        RequestSpecificValues.Current_Mode.Aggregation = childAggr.Code.ToLower();
                        html_list.Add("      <li><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + UI_ApplicationCache_Gateway.Translation.Get_Translation(name, RequestSpecificValues.Current_Mode.Language) + "</a></li>");
                    }
                }

                if (html_list.Count > 0)
                {
                    string childTypes = Hierarchy_Object.Child_Types.Trim();
                    Output.WriteLine("    <li id=\"sbkAgm_SubCollections\"><a href=\"#subcolls\">" + UI_ApplicationCache_Gateway.Translation.Get_Translation(childTypes, RequestSpecificValues.Current_Mode.Language) + "</a><ul id=\"sbkAgm_SubCollectionsMenu\">");
                    foreach (string thisHtml in html_list)
                    {
                        Output.WriteLine(thisHtml);
                    }
                    Output.WriteLine("    </ul></li>");

                    // Restore the old alias
                    RequestSpecificValues.Current_Mode.Aggregation_Alias = lastAlias;
                }
            }

            // If there is a user and this is the main home page, show MY COLLECTIONS
            if ((RequestSpecificValues.Current_User != null) && (RequestSpecificValues.Current_User.LoggedOn))
            {
                if (Hierarchy_Object.Code == "all")
                {
                    RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Aggregation;
                    RequestSpecificValues.Current_Mode.Aggregation_Type = Aggregation_Type_Enum.Home;
                    RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Personalized;

                    // Show personalized
                    if (thisHomeType == Home_Type_Enum.Personalized)
                    {
                        Output.WriteLine("    <li id=\"sbkAgm_MyCollections\" class=\"selected-sf-menu-item-link\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + myCollections + "</a></li>");
                    }
                    else
                    {
                        Output.WriteLine("    <li id=\"sbkAgm_MyCollections\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + myCollections + "</a></li>");
                    }
                }
                else
                {
                    if (RequestSpecificValues.Current_User.Is_Aggregation_Admin(Hierarchy_Object.Code))
                    {
                        // Return the code and mode back
                        RequestSpecificValues.Current_Mode.Info_Browse_Mode = String.Empty;
                        RequestSpecificValues.Current_Mode.Search_Type = thisSearch;
                        RequestSpecificValues.Current_Mode.Mode = thisMode;
                        RequestSpecificValues.Current_Mode.Home_Type = thisHomeType;

                        Output.Write(Aggregation_Nav_Bar_HTML_Factory.Menu_Get_Nav_Bar_HTML(Item_Aggregation_Views_Searches_Enum.Admin_View, RequestSpecificValues.Current_Mode, UI_ApplicationCache_Gateway.Translation));
                    }
                }
            }

            // Show institutional lists?
            if (Hierarchy_Object.Code == "all")
            {
                // Is this library set to show the partners tab?
                if (UI_ApplicationCache_Gateway.Settings.System.Include_Partners_On_System_Home)
                {
                    RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Aggregation;
                    RequestSpecificValues.Current_Mode.Aggregation_Type = Aggregation_Type_Enum.Home;
                    RequestSpecificValues.Current_Mode.Home_Type = Home_Type_Enum.Partners_List;

                    if (((thisHomeType == Home_Type_Enum.Partners_List) || (thisHomeType == Home_Type_Enum.Partners_Thumbnails)))
                    {
                        Output.WriteLine("    <li id=\"sbkAgm_Partners\" class=\"selected-sf-menu-item-link\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + partners + "</a></li>");
                    }
                    else
                    {
                        Output.WriteLine("    <li id=\"sbkAgm_Partners\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + partners + "</a></li>");
                    }
                }
            }

            // Return the code and mode back
            RequestSpecificValues.Current_Mode.Info_Browse_Mode = browse_code;
            RequestSpecificValues.Current_Mode.Aggregation_Type = thisAggrType;
            RequestSpecificValues.Current_Mode.Search_Type = thisSearch;
            RequestSpecificValues.Current_Mode.Mode = thisMode;
            RequestSpecificValues.Current_Mode.Home_Type = thisHomeType;
            RequestSpecificValues.Current_Mode.Result_Display_Type = resultsType;
            RequestSpecificValues.Current_Mode.Aggregation = aggregation;
            RequestSpecificValues.Current_Mode.Page = page;

            Output.WriteLine("  </ul>");
            Output.WriteLine("</nav>");
            Output.WriteLine();

            Output.WriteLine("<!-- Initialize the main user menu -->");
            Output.WriteLine("<script>");
            Output.WriteLine("  jQuery(document).ready(function () {");
            Output.WriteLine("     jQuery('ul.sf-menu').superfish({");

            Output.WriteLine("          onBeforeShow: function() { ");
            Output.WriteLine("               if ( $(this).attr('id') == 'sbkAgm_SubCollectionsMenu')");
            Output.WriteLine("               {");
            Output.WriteLine("                 var thisWidth = $(this).width();");
            Output.WriteLine("                 var parent = $('#sbkAgm_SubCollections');");
            Output.WriteLine("                 var offset = $('#sbkAgm_SubCollections').offset();");
            Output.WriteLine("                 if ( $(window).width() < offset.left + thisWidth )");
            Output.WriteLine("                 {");
            Output.WriteLine("                   var newleft = thisWidth - parent.width();");
            Output.WriteLine("                   $(this).css('left', '-' + newleft + 'px');");
            Output.WriteLine("                 }");
            Output.WriteLine("               }");
            Output.WriteLine("          }");

            Output.WriteLine("    });");
            Output.WriteLine("  });");
            Output.WriteLine("</script>");
            Output.WriteLine();
        }
        public static bool Add_SubCollection_Buttons(TextWriter Output, RequestCache RequestSpecificValues, Item_Aggregation hierarchyObject)
        {
            bool children_icons_added = false;

            // Verify some of the children are active and not hidden
            // Keep the last aggregation alias
            string lastAlias = RequestSpecificValues.Current_Mode.Aggregation_Alias;
            RequestSpecificValues.Current_Mode.Aggregation_Alias = String.Empty;

            // Collect the html to write (this alphabetizes the children)
            List<string> html_list = new List<string>();
            int aggreCount = -1;
            foreach (Item_Aggregation_Related_Aggregations childAggr in hierarchyObject.Children)
            {
                children_icons_added = true;
                aggreCount++;
                Item_Aggregation_Related_Aggregations latest = UI_ApplicationCache_Gateway.Aggregations[childAggr.Code];
                if ((latest != null) && (!latest.Hidden) && (latest.Active))
                {
                    string name = childAggr.Name;
                    string thisDescription = latest.Description;

                    if (name.ToUpper() == "ADDED AUTOMATICALLY")
                        name = childAggr.Code + " ( Added Automatically )";

                    RequestSpecificValues.Current_Mode.Aggregation = childAggr.Code.ToLower();
                    string image_url = RequestSpecificValues.Current_Mode.Base_URL + "design/aggregations/" + childAggr.Code + "/images/buttons/coll.gif";
                    if ((name.IndexOf("The ") == 0) && (name.Length > 4))
                    {
                        html_list.Add("  <li class=\"sbkAghsw_CollectionButton\">" + Environment.NewLine + "      <span id=\"sbkAghsw_CollectionButtonImg" + aggreCount + "\" class=\"sbkAghsw_CollectionButtonImg\"><span class=\"spanHoverText\" style=\"display:none\">" + thisDescription + "</span><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\"><img src=\"" + image_url + "\" alt=\"" + UI_ApplicationCache_Gateway.Translation.Get_Translation(name, RequestSpecificValues.Current_Mode.Language).Replace("&", "&amp;").Replace("\"", "&quot;") + "\" /></a></span>" + Environment.NewLine + "      <span class=\"sbkAghsw_CollectionButtonTxt\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + UI_ApplicationCache_Gateway.Translation.Get_Translation(name, RequestSpecificValues.Current_Mode.Language).Replace("&", "&amp;").Replace("\"", "&quot;") + "</a></span>" + Environment.NewLine + "  </li>");
                    }
                    else
                    {
                        html_list.Add("  <li class=\"sbkAghsw_CollectionButton\">" + Environment.NewLine + "      <span id=\"sbkAghsw_CollectionButtonImg" + aggreCount + "\" class=\"sbkAghsw_CollectionButtonImg\"><span class=\"spanHoverText\" style=\"display:none\">" + thisDescription + "</span><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\"><img src=\"" + image_url + "\" alt=\"" + UI_ApplicationCache_Gateway.Translation.Get_Translation(name, RequestSpecificValues.Current_Mode.Language).Replace("&", "&amp;").Replace("\"", "&quot;") + "\" /></a></span>" + Environment.NewLine + "      <span class=\"sbkAghsw_CollectionButtonTxt\"><a href=\"" + UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode) + "\">" + UI_ApplicationCache_Gateway.Translation.Get_Translation(name, RequestSpecificValues.Current_Mode.Language).Replace("&", "&amp;").Replace("\"", "&quot;") + "</a></span>" + Environment.NewLine + "  </li>");
                    }
                }
            }

            if ((html_list.Count > 0) && (String.Compare(hierarchyObject.Code, "all", StringComparison.OrdinalIgnoreCase) != 0))
            {
                string childTypes = hierarchyObject.Child_Types.Trim();
                if (childTypes.IndexOf(" ") > 0)
                {
                    TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
                    childTypes = textInfo.ToTitleCase(childTypes);
                }

                string translatedChild = UI_ApplicationCache_Gateway.Translation.Get_Translation(childTypes, RequestSpecificValues.Current_Mode.Language);
                Output.WriteLine("<section id=\"sbkAghsw_Children\" role=\"navigation\" aria-label=\"" + translatedChild + "\">");
                Output.WriteLine("<h2 id=\"subcolls\">" + translatedChild + "</h2>");

                Output.WriteLine("<ul class=\"sbkAghsw_CollectionButtonList\">");

                foreach (string thisHtml in html_list)
                {
                    Output.WriteLine(thisHtml);
                }

                Output.WriteLine("</ul>");
                Output.WriteLine("</section>");

                // Restore the old alias
                RequestSpecificValues.Current_Mode.Aggregation_Alias = lastAlias;
            }

            RequestSpecificValues.Current_Mode.Aggregation = hierarchyObject.Code;

            return children_icons_added;
        }
        /// <summary> Gets the browse or info object and any other needed data for display ( text to display) </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Aggregation_Object"> Item Aggregation object</param>
        /// <param name="Base_Directory"> Base directory location under which the the CMS/info source file will be found</param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <param name="Browse_Object"> [OUT] Stores all the information about this browse or info </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>
        /// <param name="Browse_Info_Display_Text"> [OUT] Static HTML-based content to be displayed if this is browing a staticly created html source file </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 </remarks>
        protected static bool Get_Browse_Info(Navigation_Object Current_Mode,
                                    Item_Aggregation Aggregation_Object,
                                    string Base_Directory,
                                    Custom_Tracer Tracer,
                                    out Item_Aggregation_Child_Page Browse_Object,
                                    out Search_Results_Statistics Complete_Result_Set_Info,
                                    out List<iSearch_Title_Result> Paged_Results,
                                    out HTML_Based_Content Browse_Info_Display_Text)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("abstractHtmlSubwriter.Get_Browse_Info", String.Empty);
            }

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

            // First, make sure the browse submode is valid
            Browse_Object = Aggregation_Object.Child_Page_By_Code(Current_Mode.Info_Browse_Mode);

            if (Browse_Object == null)
            {
                Current_Mode.Error_Message = "Unable to retrieve browse/info item '" + Current_Mode.Info_Browse_Mode + "'";
                return false;
            }

            // Is this a table result, or a string?
            switch (Browse_Object.Source_Data_Type)
            {
                case Item_Aggregation_Child_Source_Data_Enum.Database_Table:

                    // Set the current sort to ZERO, if currently set to ONE and this is an ALL BROWSE.
                    // Those two sorts are the same in this case
                    int sort = Current_Mode.Sort.HasValue ? Math.Max(Current_Mode.Sort.Value, ((ushort)1)) : 1;
                    if ((sort == 0) && (Browse_Object.Code == "all"))
                        sort = 1;

                    // Special code if this is a JSON browse
                    string browse_code = Current_Mode.Info_Browse_Mode;
                    if (Current_Mode.Writer_Type == Writer_Type_Enum.JSON)
                    {
                        browse_code = browse_code + "_JSON";
                        sort = 12;
                    }

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

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

                    // 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_browse_statistics = true;
                    bool need_paged_results = true;
                    if (!special_search_type)
                    {
                        // Look to see if the browse statistics are available on any cache for this browse
                        Complete_Result_Set_Info = CachedDataManager.Retrieve_Browse_Result_Statistics(Aggregation_Object.Code, browse_code, Tracer);
                        if (Complete_Result_Set_Info != null)
                            need_browse_statistics = false;

                        // Look to see if the paged results are available on any cache..
                        Paged_Results = CachedDataManager.Retrieve_Browse_Results(Aggregation_Object.Code, browse_code, current_page_index, sort, Tracer);
                        if (Paged_Results != null)
                            need_paged_results = false;
                    }

                    // Was a copy found in the cache?
                    if ((!need_browse_statistics) && (!need_paged_results))
                    {
                        if (Tracer != null)
                        {
                            Tracer.Add_Trace("SobekCM_Assistant.Get_Browse_Info", "Browse statistics and paged results retrieved from cache");
                        }
                    }
                    else
                    {
                        if (Tracer != null)
                        {
                            Tracer.Add_Trace("SobekCM_Assistant.Get_Browse_Info", "Building results information");
                        }

                        // Try to pull more than one page, so we can cache the next page or so
                        List<List<iSearch_Title_Result>> pagesOfResults;

                        // Get from the hierarchy object
                            Multiple_Paged_Results_Args returnArgs = Item_Aggregation_Utilities.Get_Browse_Results(Aggregation_Object, Browse_Object, current_page_index, sort, results_per_page, !special_search_type, need_browse_statistics, Tracer);
                            if (need_browse_statistics)
                            {
                                Complete_Result_Set_Info = returnArgs.Statistics;
                            }
                            pagesOfResults = returnArgs.Paged_Results;
                            if ((pagesOfResults != null) && (pagesOfResults.Count > 0))
                                Paged_Results = pagesOfResults[0];

                        // Save the overall result set statistics to the cache if something was pulled
                        if (!special_search_type)
                        {
                            if ((need_browse_statistics) && (Complete_Result_Set_Info != null))
                            {
                                CachedDataManager.Store_Browse_Result_Statistics(Aggregation_Object.Code, browse_code, Complete_Result_Set_Info, Tracer);
                            }

                            // Save the overall result set statistics to the cache if something was pulled
                            if ((need_paged_results) && (Paged_Results != null))
                            {
                                CachedDataManager.Store_Browse_Results(Aggregation_Object.Code, browse_code, current_page_index, sort, pagesOfResults, Tracer);
                            }
                        }
                    }
                    break;

                case Item_Aggregation_Child_Source_Data_Enum.Static_HTML:
                    Browse_Info_Display_Text = SobekEngineClient.Aggregations.Get_Aggregation_HTML_Child_Page(Aggregation_Object.Code, Aggregation_Object.Language, UI_ApplicationCache_Gateway.Settings.System.Default_UI_Language, Browse_Object.Code, Tracer);
                    break;
            }
            return true;
        }
        /// <summary> Gets the item aggregation and search fields for the current item aggregation </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        /// <param name="Aggregation_Object"> [OUT] Fully-built object for the current aggregation object </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. </remarks>
        protected static bool Get_Collection(Navigation_Object Current_Mode, Custom_Tracer Tracer, out Item_Aggregation Aggregation_Object)
        {
            string languageCode = Web_Language_Enum_Converter.Enum_To_Code(Current_Mode.Language);

            if (Tracer != null)
            {
                Tracer.Add_Trace("abstractHtmlSubwriter.Get_Collection", "Get " + Current_Mode.Aggregation + " for " + languageCode );
            }

            // If there is an aggregation listed, try to get that now
            if ((Current_Mode.Aggregation.Length > 0) && (Current_Mode.Aggregation != "all"))
            {
                // Try to pull the aggregation information
                Aggregation_Object = CachedDataManager.Aggregations.Retrieve_Item_Aggregation(Current_Mode.Aggregation, Web_Language_Enum_Converter.Code_To_Enum(languageCode), Tracer);
                if (Aggregation_Object != null)
                {
                    set_web_skin_from_aggregation(Current_Mode, Aggregation_Object);
                    return true;
                }

                // Get the item aggregation from the Sobek Engine Client (which checks the local cache as well)
                Aggregation_Object = SobekEngineClient.Aggregations.Get_Aggregation(Current_Mode.Aggregation, Web_Language_Enum_Converter.Code_To_Enum(languageCode), UI_ApplicationCache_Gateway.Settings.System.Default_UI_Language, Tracer);

                // Return if this was valid
                if (Aggregation_Object != null)
                {
                    set_web_skin_from_aggregation(Current_Mode, Aggregation_Object);
                    return true;
                }

                Current_Mode.Error_Message = "Invalid item aggregation '" + Current_Mode.Aggregation + "' referenced.";
                return false;
            }

            return Get_Top_Level_Collection(Current_Mode, Tracer, out Aggregation_Object);
        }
        /// <summary> Gets the item aggregation and search fields for the current item aggregation </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</param>
        /// <param name="Code_Manager"> List of valid collection codes, including mapping from the Sobek collections to Greenstone collections</param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        /// <param name="Aggregation_Object"> [OUT] Fully-built object for the current aggregation object </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. </remarks>
        public bool Get_Entire_Collection_Hierarchy(Navigation_Object Current_Mode, Aggregation_Code_Manager Code_Manager, Custom_Tracer Tracer, out Item_Aggregation Aggregation_Object)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("SobekCM_Assistant.Get_Entire_Collection_Hierarchy", String.Empty);
            }

            string languageCode = Web_Language_Enum_Converter.Enum_To_Code(Current_Mode.Language);

            // If there is an aggregation listed, try to get that now
            if ((Current_Mode.Aggregation.Length > 0) && (Current_Mode.Aggregation != "all"))
            {
                // Try to pull the aggregation information
                Aggregation_Object = Get_Item_Aggregation(Current_Mode.Aggregation, languageCode, Current_Mode.Is_Robot, Tracer );

                // Return if this was valid
                if (Aggregation_Object != null)
                {
                    if ((Current_Mode.Skin_In_URL != true) && ( !String.IsNullOrEmpty(Aggregation_Object.Default_Skin )))
                    {
                        Current_Mode.Skin = Aggregation_Object.Default_Skin.ToLower();
                    }
                    return true;
                }

                Current_Mode.Error_Message = "Invalid item aggregation '" + Current_Mode.Aggregation + "' referenced.";
                return false;
            }
            // Get the collection group
            Aggregation_Object = Get_All_Collections(languageCode, Current_Mode.Is_Robot, Tracer );

            // If this is null, just stop
            if (Aggregation_Object == null)
            {
                Current_Mode.Error_Message = "Unable to pull the item aggregation corresponding to all collection groups";
                return false;
            }

            return true;
        }
        private static void set_web_skin_from_aggregation(Navigation_Object Current_Mode, Item_Aggregation Aggregation_Object)
        {
            // If th aggregation can only display under certain web skins, see if the current is acceptable
            // Do NOT do this replacement if the web skin is in the URL and this is admin mode
            if ((!Current_Mode.Skin_In_URL) || (Current_Mode.Mode != Display_Mode_Enum.Administrative))
            {
                // Is there a list of acceptible web skins?
                if ((Aggregation_Object.Web_Skins != null) && (Aggregation_Object.Web_Skins.Count > 0))
                {
                    string currentWebSkin = Current_Mode.Skin;
                    bool acceptableSkin = false;
                    foreach (string aggrWebSkin in Aggregation_Object.Web_Skins)
                    {
                        if (String.Compare(currentWebSkin, aggrWebSkin, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            acceptableSkin = true;
                            break;
                        }
                    }

                    // If no match found, assign the skin
                    if (!acceptableSkin)
                    {
                        // Use default skin if there
                        if (!String.IsNullOrWhiteSpace(Aggregation_Object.Default_Skin))
                        {
                            Current_Mode.Skin = Aggregation_Object.Default_Skin.ToLower();
                        }
                        else
                        {
                            Current_Mode.Skin = Aggregation_Object.Web_Skins[0];
                        }

                        // Let the nav object know this was a default
                        Current_Mode.Default_Skin = Current_Mode.Skin;
                    }
                }
            }
        }
        /// <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> Build the browse all static HTML file that includes links to all items in a particular collection </summary>
        /// <param name="Aggregation"> Aggregation object for which to build the browse ALL static html page </param>
        /// <param name="AllItems"> List of all items linked to that aggregation/collection </param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        public bool Build_All_Browse(Item_Aggregation Aggregation, DataSet AllItems)
        {
            if (AllItems == null)
                return false;

            // Set the default web skin
            currentMode.Skin = defaultSkin;
            currentMode.Aggregation = Aggregation.Code;
            currentMode.Aggregation_Type = Aggregation_Type_Enum.Home;
            currentMode.Is_Robot = true;

            if (staticSobekcmLocation.Length > 0)
                UI_ApplicationCache_Gateway.Settings.Servers.Base_Directory = staticSobekcmLocation;

            // Pull the item aggregation object
            if (( Aggregation.Web_Skins != null ) && ( Aggregation.Web_Skins.Count > 0))
                currentMode.Skin = Aggregation.Web_Skins[0];

               // Get the skin object
            Custom_Tracer tracer = new Custom_Tracer();
            Web_Skin_Object skinObject = assistant.Get_HTML_Skin(currentMode, Engine_ApplicationCache_Gateway.Web_Skin_Collection, false, tracer);
            if (skinObject == null)
                return true;

            StreamWriter writer = new StreamWriter(staticSobekcmDataLocation + Aggregation.Code.ToLower() + "_all.html", false);
            writer.WriteLine("<!DOCTYPE html>");
            writer.WriteLine("<html>");
            writer.WriteLine("<head>");
            writer.WriteLine("  <title>" + UI_ApplicationCache_Gateway.Settings.System.System_Abbreviation + " - " + Aggregation.Name + "</title>");
            writer.WriteLine();
            writer.WriteLine("  <!-- " + UI_ApplicationCache_Gateway.Settings.System.System_Name + " : SobekCM Digital Repository -->");
            writer.WriteLine();
            writer.WriteLine("  <link href=\"" + UI_ApplicationCache_Gateway.Settings.Servers.System_Base_URL + "default/SobekCM.min.css\" rel=\"stylesheet\" type=\"text/css\" />");
            writer.WriteLine("  <script type=\"text/javascript\" src=\"" + UI_ApplicationCache_Gateway.Settings.Servers.System_Base_URL + "default/scripts/jquery/jquery-1.10.2.min.js\"></script>");
            writer.WriteLine("  <script type=\"text/javascript\" src=\"" + UI_ApplicationCache_Gateway.Settings.Servers.System_Base_URL + "default/scripts/sobekcm_full.min.js\"></script>");
            writer.WriteLine("  <meta name=\"robots\" content=\"index, follow\" />");
            if (!(String.IsNullOrEmpty(skinObject.CSS_Style)))
            {
                writer.WriteLine("  <link href=\"" + UI_ApplicationCache_Gateway.Settings.Servers.System_Base_URL + skinObject.CSS_Style + "\" rel=\"stylesheet\" type=\"text/css\" />");
            }
            if ( !String.IsNullOrEmpty(Aggregation.CSS_File))
            {
                writer.WriteLine("  <link href=\"" + currentMode.Base_Design_URL + "aggregations/" + skinObject.Skin_Code + "/" + skinObject.CSS_Style + "\" rel=\"stylesheet\" type=\"text/css\" />");
            }
            writer.WriteLine("</head>");
            writer.WriteLine("<body>");

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

            string banner = "<div id=\"sbkHmw_BannerDiv\"><a alt=\"" + Aggregation.Name + "\" href=\"" + primaryWebServerUrl + Aggregation.Code.ToLower() + "\" style=\"padding-bottom:0px;margin-bottom:0px\"><img id=\"mainBanner\" src=\"" + primaryWebServerUrl + "design/aggregations/" + Aggregation.Code + "/images/banners/coll.jpg\" alt=\"\" /></a></div>";
            Display_Header(writer, skinObject, banner);

            //		MainMenus_Helper_HtmlSubWriter.Add_Aggregation_Main_Menu(writer, currentMode, null, Aggregation, translations, codeManager );

            writer.WriteLine("<div class=\"sbkPrsw_DescPanel sbkPrsw_BrowseDescPanel\">");
            writer.WriteLine("  <h1>All Items</h1>");
            writer.WriteLine("</div>");

            writer.WriteLine("<div class=\"sbkPrsw_ResultsNavBarImbed\">");
            writer.WriteLine("  <br />");
            writer.WriteLine("  " + AllItems.Tables[0].Rows.Count + " of " + AllItems.Tables[0].Rows.Count + " matching titles");
            writer.WriteLine("</div>");
            writer.WriteLine();

            writer.WriteLine("<div id=\"sbkPrsw_ViewTypeSelectRow\">");
            writer.WriteLine("  <ul class=\"sbk_FauxDownwardTabsList\">");
            writer.WriteLine("    <li>BRIEF VIEW</li>");
            writer.WriteLine("    <li class=\"current\">TABLE VIEW</li>");
            writer.WriteLine("    <li>THUMBNAIL VIEW</li>");
            writer.WriteLine("  </ul>");
            writer.WriteLine("</div>");
            writer.WriteLine();

            writer.WriteLine("<div class=\"sbkPrsw_ResultsPanel\" id=\"main-content\">");

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

            // Add links for each item
            if (AllItems.Tables[0].Rows.Count > 0)
            {
                foreach (DataRow thisRow in AllItems.Tables[0].Rows)
                {
                    // Determine the folder
                    string bibid = thisRow["BibID"].ToString();
                    string vid = thisRow["VID"].ToString();

                    writer.WriteLine("<a href=\"" + primaryWebServerUrl + bibid + "/" + vid + "\">" + thisRow["Title"] + "</a><br />");
                }
            }
            else
            {
                writer.WriteLine("<h1>NO ITEMS IN AGGREGATION</h1>");
            }

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

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

            Display_Footer(writer, skinObject);

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

            writer.WriteLine("</body>");
            writer.WriteLine("</html>");

            writer.Flush();
            writer.Close();

            return true;
        }
        /// <summary> Add the header to the output </summary>
        /// <param name="Output"> Stream to which to write the HTML for this header </param>
        /// <param name="RequestSpecificValues"> All the necessary, non-global data specific to the current request </param>
        /// <param name="Container_CssClass"> Class name for the container around the page </param>
        /// <param name="Web_Page_Title"> Title for this web page, to include behind the banner possibly </param>
        /// <param name="Behaviors"> List of behaviors from the html subwriters </param>
        /// <param name="Current_Aggregation"> Current aggregation object, if there is one </param>
        /// <param name="Current_Item"> Current item object, if there is one </param>
        public static void Add_Header(TextWriter Output, RequestCache RequestSpecificValues, string Container_CssClass, string Web_Page_Title, List<HtmlSubwriter_Behaviors_Enum> Behaviors, Item_Aggregation Current_Aggregation, BriefItemInfo Current_Item )
        {
            // Get the url options
            string url_options = UrlWriterHelper.URL_Options(RequestSpecificValues.Current_Mode);
            string modified_url_options = String.Empty;
            if (url_options.Length > 0)
                modified_url_options = "?" + url_options;

            // Get the current contact URL
            Display_Mode_Enum thisMode = RequestSpecificValues.Current_Mode.Mode;
            RequestSpecificValues.Current_Mode.Mode = Display_Mode_Enum.Contact;
            string contact = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);

            // Restore the old mode
            RequestSpecificValues.Current_Mode.Mode = thisMode;

            // Determine which header and footer to display
            bool useItemHeader = (RequestSpecificValues.Current_Mode.Mode == Display_Mode_Enum.Item_Display) || (RequestSpecificValues.Current_Mode.Mode == Display_Mode_Enum.Item_Print) || ((Behaviors != null) && (Behaviors.Contains(HtmlSubwriter_Behaviors_Enum.MySobek_Subwriter_Mimic_Item_Subwriter)));

            // Create the breadcrumbs text
            string breadcrumbs = "&nbsp; &nbsp; ";
            if (useItemHeader)
            {
                StringBuilder breadcrumb_builder = new StringBuilder("<a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + modified_url_options + "\">" + RequestSpecificValues.Current_Mode.Instance_Abbreviation + " Home</a>");

                int codes_added = 0;
                if ((RequestSpecificValues.Current_Mode.Aggregation.Length > 0) && (RequestSpecificValues.Current_Mode.Aggregation != "all"))
                {
                    breadcrumb_builder.Append(" &nbsp;|&nbsp; <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + RequestSpecificValues.Current_Mode.Aggregation + modified_url_options + "\">" + UI_ApplicationCache_Gateway.Aggregations.Get_Collection_Short_Name(RequestSpecificValues.Current_Mode.Aggregation) + "</a>");
                    codes_added++;
                }

                if (Current_Item != null)
                {
                    if (( Current_Item.Behaviors.Aggregation_Code_List != null ) && ( Current_Item.Behaviors.Aggregation_Code_List.Count > 0))
                    {
                        foreach (string aggrCode in Current_Item.Behaviors.Aggregation_Code_List)
                        {
                            if (aggrCode.ToLower() != RequestSpecificValues.Current_Mode.Aggregation)
                            {
                                if (( String.Compare(aggrCode,Current_Item.Behaviors.Source_Institution_Aggregation, StringComparison.OrdinalIgnoreCase ) != 0 ) &&
                                    ( String.Compare(aggrCode, "i" + Current_Item.Behaviors.Source_Institution_Aggregation, StringComparison.OrdinalIgnoreCase) != 0) &&
                                    ( String.Compare(aggrCode, Current_Item.Behaviors.Holding_Location_Aggregation, StringComparison.OrdinalIgnoreCase) != 0) &&
                                    (String.Compare(aggrCode, "i" + Current_Item.Behaviors.Holding_Location_Aggregation, StringComparison.OrdinalIgnoreCase) != 0))
                                {
                                    Item_Aggregation_Related_Aggregations thisAggr = UI_ApplicationCache_Gateway.Aggregations[aggrCode];
                                    if ((thisAggr != null) && (thisAggr.Active))
                                    {
                                        breadcrumb_builder.Append(" &nbsp;|&nbsp; <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL +
                                                                  aggrCode.ToLower() + modified_url_options + "\">" +
                                                                  thisAggr.ShortName +
                                                                  "</a>");
                                        codes_added++;
                                    }
                                }
                            }
                            if (codes_added == 5)
                                break;
                        }
                    }

                    if (codes_added < 5)
                    {
                        if ( !String.IsNullOrEmpty(Current_Item.Behaviors.Source_Institution_Aggregation))
                        {
                            // Add source code
                            string source_code = Current_Item.Behaviors.Source_Institution_Aggregation;
                            if ((source_code[0] != 'i') && (source_code[0] != 'I'))
                                source_code = "I" + source_code;
                            Item_Aggregation_Related_Aggregations thisSourceAggr = UI_ApplicationCache_Gateway.Aggregations[source_code];
                            if ((thisSourceAggr != null) && (!thisSourceAggr.Hidden) && (thisSourceAggr.Active))
                            {
                                string source_name = thisSourceAggr.ShortName;
                                if (source_name.ToUpper() != "ADDED AUTOMATICALLY")
                                {
                                    breadcrumb_builder.Append(" &nbsp;|&nbsp; <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL +
                                                              source_code.ToLower() + modified_url_options + "\">" +
                                                              source_name + "</a>");
                                }
                            }

                            // Add the holding code
                            if (( !String.IsNullOrEmpty(Current_Item.Behaviors.Holding_Location_Aggregation)) &&
                                (String.Compare(Current_Item.Behaviors.Source_Institution_Aggregation, Current_Item.Behaviors.Source_Institution_Aggregation, StringComparison.OrdinalIgnoreCase) != 0 ))
                            {
                                // Add holding code
                                string holding_code = Current_Item.Behaviors.Holding_Location_Aggregation;
                                if ((holding_code[0] != 'i') && (holding_code[0] != 'I'))
                                    holding_code = "I" + holding_code;

                                Item_Aggregation_Related_Aggregations thisAggr = UI_ApplicationCache_Gateway.Aggregations[holding_code];
                                if ((thisAggr != null) && (!thisAggr.Hidden) && (thisAggr.Active))
                                {
                                    string holding_name = thisAggr.ShortName;

                                    if (holding_name.ToUpper() != "ADDED AUTOMATICALLY")
                                    {
                                        breadcrumb_builder.Append(" &nbsp;|&nbsp; <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL +
                                                                  holding_code.ToLower() + modified_url_options + "\">" +
                                                                  holding_name + "</a>");
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (!String.IsNullOrEmpty(Current_Item.Behaviors.Holding_Location_Aggregation))
                            {
                                // Add holding code
                                string holding_code = Current_Item.Behaviors.Holding_Location_Aggregation;
                                if ((holding_code[0] != 'i') && (holding_code[0] != 'I'))
                                    holding_code = "I" + holding_code;
                                string holding_name = UI_ApplicationCache_Gateway.Aggregations.Get_Collection_Short_Name(holding_code);
                                if (holding_name.ToUpper() != "ADDED AUTOMATICALLY")
                                {
                                    breadcrumb_builder.Append(" &nbsp;|&nbsp; <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL +
                                                              holding_code.ToLower() + modified_url_options + "\">" +
                                                              holding_name + "</a>");
                                }
                            }
                        }
                    }
                }
                breadcrumbs = breadcrumb_builder.ToString();
            }
            else
            {
                switch (RequestSpecificValues.Current_Mode.Mode)
                {
                    case Display_Mode_Enum.Error:
                        breadcrumbs = "<a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + modified_url_options + "\">" + RequestSpecificValues.Current_Mode.Instance_Abbreviation + " Home</a>";
                        break;

                    case Display_Mode_Enum.Aggregation:
                        if ((RequestSpecificValues.Current_Mode.Aggregation_Type == Aggregation_Type_Enum.Home) || (RequestSpecificValues.Current_Mode.Aggregation_Type == Aggregation_Type_Enum.Home_Edit))
                        {
                            if ((RequestSpecificValues.Current_Mode.Aggregation.Length > 0) && (RequestSpecificValues.Current_Mode.Aggregation != "all"))
                            {
                                breadcrumbs = "<a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + modified_url_options + "\">" + RequestSpecificValues.Current_Mode.Instance_Abbreviation + " Home</a>";
                            }
                        }
                        else
                        {
                            breadcrumbs = "<a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + modified_url_options + "\">" + RequestSpecificValues.Current_Mode.Instance_Abbreviation + " Home</a>";
                            if ((RequestSpecificValues.Current_Mode.Aggregation.Length > 0) && (RequestSpecificValues.Current_Mode.Aggregation != "all"))
                            {
                                breadcrumbs = breadcrumbs + " &nbsp;|&nbsp; <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + RequestSpecificValues.Current_Mode.Aggregation + modified_url_options + "\">" + UI_ApplicationCache_Gateway.Aggregations.Get_Collection_Short_Name(RequestSpecificValues.Current_Mode.Aggregation) + "</a>";
                            }
                        }
                        break;

                    default:
                        breadcrumbs = "<a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + modified_url_options + "\">" + RequestSpecificValues.Current_Mode.Instance_Abbreviation + " Home</a>";
                        if ((RequestSpecificValues.Current_Mode.Aggregation.Length > 0) && (RequestSpecificValues.Current_Mode.Aggregation != "all"))
                        {
                            breadcrumbs = breadcrumbs + " &nbsp;|&nbsp; <a href=\"" + RequestSpecificValues.Current_Mode.Base_URL + RequestSpecificValues.Current_Mode.Aggregation + modified_url_options + "\">" + UI_ApplicationCache_Gateway.Aggregations.Get_Collection_Short_Name(RequestSpecificValues.Current_Mode.Aggregation) + "</a>";
                        }
                        break;
                }
            }

            // Create the mySobek text
            string mySobekLinks = create_mysobek_link(RequestSpecificValues, url_options, null);

            // Look for some basic mode data
            string collection_code = String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.Aggregation) ? String.Empty : RequestSpecificValues.Current_Mode.Aggregation;
            string bibid = String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.BibID) ? String.Empty : RequestSpecificValues.Current_Mode.BibID;
            string vid = String.IsNullOrEmpty(RequestSpecificValues.Current_Mode.BibID) ? String.Empty : RequestSpecificValues.Current_Mode.BibID;
            string mode = String.Empty;
            switch (RequestSpecificValues.Current_Mode.Mode)
            {
                case Display_Mode_Enum.Item_Display:
                    mode = "item";
                    break;

                case Display_Mode_Enum.Aggregation:
                case Display_Mode_Enum.Search:
                    mode = "aggregation";
                    break;

                case Display_Mode_Enum.Results:
                    mode = "results";
                    break;
            }

            // Get the language selections
            Web_Language_Enum language = RequestSpecificValues.Current_Mode.Language;
            RequestSpecificValues.Current_Mode.Language = Web_Language_Enum.TEMPLATE;
            string template_language = UrlWriterHelper.Redirect_URL(RequestSpecificValues.Current_Mode);
            string english = template_language.Replace("l=XXXXX", "l=en");
            string french = template_language.Replace("l=XXXXX", "l=fr");
            string spanish = template_language.Replace("l=XXXXX", "l=es");
            RequestSpecificValues.Current_Mode.Language = language;

            if (RequestSpecificValues.Current_Mode.Is_Robot)
            {
                english = String.Empty;
                french = String.Empty;
                spanish = String.Empty;
            }

            // Determine which container to use, depending on the current mode
            string container_inner = Container_CssClass;

            // Get the skin url
            string skin_url = RequestSpecificValues.Current_Mode.Base_Design_URL + "skins/" + RequestSpecificValues.Current_Mode.Skin + "/";

            // Determine the URL options for replacement
            string urlOptions1 = String.Empty;
            string urlOptions2 = String.Empty;
            if (url_options.Length > 0)
            {
                urlOptions1 = "?" + url_options;
                urlOptions2 = "&" + url_options;
            }

            // Determine the possible banner to display
            string banner = String.Empty;
            if (( Behaviors != null ) && ( !Behaviors.Contains(HtmlSubwriter_Behaviors_Enum.Suppress_Banner)))
            {
                if ((RequestSpecificValues.HTML_Skin != null) && (RequestSpecificValues.HTML_Skin.Override_Banner.HasValue) && (RequestSpecificValues.HTML_Skin.Override_Banner.Value))
                {
                    banner = !String.IsNullOrEmpty(RequestSpecificValues.HTML_Skin.Banner_HTML) ? RequestSpecificValues.HTML_Skin.Banner_HTML : String.Empty;
                }
                else
                {
                    if (Current_Aggregation!= null)
                    {
                        string banner_image = Current_Aggregation.Get_Banner_Image( RequestSpecificValues.HTML_Skin);
                        if (Current_Aggregation.Code != "all")
                        {
                            if (banner_image.Length > 0)
                                banner = "<section id=\"sbkHmw_BannerDiv\" role=\"banner\" title=\"" + Current_Aggregation.ShortName + "\"><h1 class=\"hidden-element\">" + Web_Page_Title + "</h1><a alt=\"" + Current_Aggregation.ShortName + "\" href=\"" + RequestSpecificValues.Current_Mode.Base_URL + Current_Aggregation.Code + urlOptions1 + "\"><img id=\"mainBanner\" src=\"" + RequestSpecificValues.Current_Mode.Base_URL + banner_image + "\"  alt=\"" + Current_Aggregation.ShortName + "\" /></a></section>";
                        }
                        else
                        {
                            if (banner_image.Length > 0)
                            {
                                banner = "<section id=\"sbkHmw_BannerDiv\" role=\"banner\" title=\"" + Current_Aggregation.ShortName + "\"><h1 class=\"hidden-element\">" + Web_Page_Title + "</h1><a alt=\"" + Current_Aggregation.ShortName + "\"  href=\"" + RequestSpecificValues.Current_Mode.Base_URL + urlOptions1 + "\"><img id=\"mainBanner\" src=\"" + RequestSpecificValues.Current_Mode.Base_URL + banner_image + "\"  alt=\"" + Current_Aggregation.ShortName + "\" /></a></section>";
                            }
                            else
                            {
                                banner = "<section id=\"sbkHmw_BannerDiv\" role=\"banner\" title=\"" + Current_Aggregation.ShortName + "\"><h1 class=\"hidden-element\">" + Web_Page_Title + "</h1><a alt=\"" + Current_Aggregation.ShortName + "\"  href=\"" + RequestSpecificValues.Current_Mode.Base_URL + urlOptions1 + "\"><img id=\"mainBanner\" src=\"" + skin_url + "default.jpg\" alt=\"" + Current_Aggregation.ShortName + "\" /></a></section>";
                            }
                        }
                    }
                }
            }

            // Get the session id and user id
            string sessionId = HttpContext.Current.Session.SessionID ?? String.Empty;
            string userid = ((RequestSpecificValues.Current_User != null) && (RequestSpecificValues.Current_User.UserID > 0)) ? RequestSpecificValues.Current_User.UserID.ToString() : String.Empty;

            // Add the appropriate header
            StringBuilder headerBuilder = new StringBuilder();
            try
            {
                if (useItemHeader)
                {
                    headerBuilder.Append(RequestSpecificValues.HTML_Skin.Header_Item_HTML);
                }
                else
                {
                    headerBuilder.Append(RequestSpecificValues.HTML_Skin.Header_HTML);

                    if ((!String.IsNullOrEmpty(container_inner)) && ((!RequestSpecificValues.HTML_Skin.Header_Has_Container_Directive.HasValue) || (!RequestSpecificValues.HTML_Skin.Header_Has_Container_Directive.Value)))
                        headerBuilder.Insert(0, "<div id=\"" + container_inner + "\">" + Environment.NewLine);
                }

                // Do all the replacements
                headerBuilder.Replace("<%COLLCODE%>", collection_code);
                headerBuilder.Replace("<%BIBID%>", bibid);
                headerBuilder.Replace("<%VID%>", vid);
                headerBuilder.Replace("<%MODE%>", mode);
              //              headerBuilder.Replace("<%COLLNAME%>", collection_name);
                headerBuilder.Replace("<%CONTACT%>", contact);
                headerBuilder.Replace("<%URLOPTS%>", url_options);
                headerBuilder.Replace("<%?URLOPTS%>", urlOptions1);
                headerBuilder.Replace("<%&URLOPTS%>", urlOptions2);
                headerBuilder.Replace("<%BREADCRUMBS%>", breadcrumbs);
                headerBuilder.Replace("<%MYSOBEK%>", mySobekLinks);
                headerBuilder.Replace("<%ENGLISH%>", english);
                headerBuilder.Replace("<%FRENCH%>", french);
                headerBuilder.Replace("<%SPANISH%>", spanish);
                headerBuilder.Replace("<%BASEURL%>", RequestSpecificValues.Current_Mode.Base_URL);
                headerBuilder.Replace("\"container-inner\"", "\"" + container_inner + "\"");
                headerBuilder.Replace("<%BANNER%>", banner);
                headerBuilder.Replace("<%SKINURL%>", skin_url);
                if (( !useItemHeader) && ( !String.IsNullOrEmpty(container_inner)) && (RequestSpecificValues.HTML_Skin.Header_Has_Container_Directive.HasValue) && (RequestSpecificValues.HTML_Skin.Header_Has_Container_Directive.Value))
                    headerBuilder.Replace("<%CONTAINER%>", "<div id=\"" + container_inner + "\">");
                else
                    headerBuilder.Replace("<%CONTAINER%>", String.Empty);
                headerBuilder.Replace("<%INSTANCENAME%>", RequestSpecificValues.Current_Mode.Instance_Name);
                headerBuilder.Replace("<%SESSIONID%>", sessionId);
                headerBuilder.Replace("<%USERID%>", userid);
            }
            catch (Exception ee)
            {
                RequestSpecificValues.Tracer.Add_Trace("HeaderFooter_Helper_HtmlSubWriter.Add_Header", "EXCEPTION CAUGHT while trying to write the header.");
                if (RequestSpecificValues.HTML_Skin == null)
                    RequestSpecificValues.Tracer.Add_Trace("HeaderFooter_Helper_HtmlSubWriter.Add_Header", "HTML Skin was NULL");
                else if (RequestSpecificValues.HTML_Skin.Header_Item_HTML == null)
                    RequestSpecificValues.Tracer.Add_Trace("HeaderFooter_Helper_HtmlSubWriter.Add_Header", "HTML Skin was not NULL, but Header_Item_HTML property was NULL");
            }

            // Write the header
            Output.WriteLine(headerBuilder.ToString());
        }