/// <summary> Stores a site map navigational object for static web content pages </summary>
        /// <param name="StoreObject"> Sitemap object to be locally cached </param>
        /// <param name="SiteMap_File"> Name of the site map file which indicates the site map to retrieve from memory </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        public static void Store_Site_Map( SobekCM_SiteMap StoreObject, string SiteMap_File, Custom_Tracer Tracer)
        {
            // If the cache is disabled, just return before even tracing
            if ( Settings.Disabled )
                return;

            // Determine the key
            string key = "SITEMAP_" + SiteMap_File;

            // Store this on the local cache, if not there and storing on the cache server failed
            if (HttpContext.Current.Cache[key] == null)
            {
                if (Tracer != null)
                {
                    Tracer.Add_Trace("CachedDataManager.Store_Site_Map", "Adding object '" + key + "' to the local cache with expiration of 3 minutes");
                }

                HttpContext.Current.Cache.Insert(key, StoreObject, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(3));
            }
        }
 /// <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> Gets the simple CMS/info object and text to display </summary>
        /// <param name="Current_Mode"> Mode / navigation information for the current request</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="Simple_Web_Content"> [OUT] Built browse object which contains information like title, banner, etc.. and the entire text to be displayed </param>
        /// <param name="Site_Map"> [OUT] Optional navigational site map object related to this page </param>
        /// <returns>TRUE if successful, otherwise FALSE </returns>
        /// <remarks> This always pulls the data directly from disk; this text is not cached. </remarks>
        public bool Get_Simple_Web_Content_Text(Navigation_Object Current_Mode, string Base_Directory, Custom_Tracer Tracer, out HTML_Based_Content Simple_Web_Content, out SobekCM_SiteMap Site_Map )
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("SobekCM_Assistant.Get_Simple_Web_Content_Text", String.Empty);
            }

            Site_Map = null;
            Simple_Web_Content = null;

            // Get the web content object
            if ((( Current_Mode.WebContentID.HasValue ) && ( Current_Mode.WebContentID.Value > 0 )) && (( !Current_Mode.Missing.HasValue ) || ( !Current_Mode.Missing.Value )))
                Simple_Web_Content = SobekEngineClient.WebContent.Get_HTML_Based_Content(Current_Mode.WebContentID.Value, true, Tracer);

            // If somehow this is null and this was for DEFAULT, just add the page
            if (Simple_Web_Content == null)
            {
                Simple_Web_Content = SobekEngineClient.WebContent.Get_Special_Missing_Page(Tracer);
            }

            if (Simple_Web_Content == null)
            {
                Current_Mode.Error_Message = "Unable to retrieve simple text item '" + Current_Mode.Info_Browse_Mode.Replace("_", "\\") + "'";
                return false;
            }

            // If this is a redirect, just return
            if (!String.IsNullOrEmpty(Simple_Web_Content.Redirect))
                return true;

            if ( String.IsNullOrEmpty(Simple_Web_Content.Content))
            {
                Current_Mode.Error_Message = "Unable to read the file for display";
                return false;
            }

            // Look for a site map
            if (!String.IsNullOrEmpty(Simple_Web_Content.SiteMap))
            {
                // Look in the cache first
                Site_Map = CachedDataManager.Retrieve_Site_Map(Simple_Web_Content.SiteMap, Tracer);

                // If this was NULL, pull it
                if (Site_Map == null)
                {
                    string sitemap_file = Simple_Web_Content.SiteMap;
                    if (!sitemap_file.ToLower().Contains(".sitemap"))
                        sitemap_file = sitemap_file + ".sitemap";

                    // Only continue if the file exists
                    if (File.Exists(UI_ApplicationCache_Gateway.Settings.Servers.Base_Directory + "design\\webcontent\\sitemaps\\" + sitemap_file))
                    {
                        if (Tracer != null)
                        {
                            Tracer.Add_Trace("SobekCM_Assistant.Get_Simple_Web_Content_Text", "Reading site map file");
                        }

                        // Try to read this sitemap file
                        Site_Map = SobekCM_SiteMap_Reader.Read_SiteMap_File(UI_ApplicationCache_Gateway.Settings.Servers.Base_Directory + "design\\webcontent\\sitemaps\\" + sitemap_file);

                        // If the sitemap file was succesfully read, cache it
                        if (Site_Map != null)
                        {
                            CachedDataManager.Store_Site_Map(Site_Map, Simple_Web_Content.SiteMap, Tracer);
                        }
                    }
                    else if (File.Exists(UI_ApplicationCache_Gateway.Settings.Servers.Base_Directory + "design\\webcontent\\" + sitemap_file))
                    {
                        // This is just for some legacy material
                        if (Tracer != null)
                        {
                            Tracer.Add_Trace("SobekCM_Assistant.Get_Simple_Web_Content_Text", "Reading site map file");
                        }

                        // Try to read this sitemap file
                        Site_Map = SobekCM_SiteMap_Reader.Read_SiteMap_File(UI_ApplicationCache_Gateway.Settings.Servers.Base_Directory + "design\\webcontent\\" + sitemap_file);

                        // If the sitemap file was succesfully read, cache it
                        if (Site_Map != null)
                        {
                            CachedDataManager.Store_Site_Map(Site_Map, Simple_Web_Content.SiteMap, Tracer);
                        }
                    }
                }
            }

            // Since this is not cached, we can apply the individual user settings to the static text which was read right here
            Simple_Web_Content.Content = Simple_Web_Content.Apply_Settings_To_Static_Text(Simple_Web_Content.Content, null, Current_Mode.Skin, Current_Mode.Base_Skin, Current_Mode.Base_URL, UrlWriterHelper.URL_Options(Current_Mode), Tracer);

            return true;
        }
        /// <summary> Reads an existing site map file and returns the fully built <see cref="SobekCM_SiteMap" /> object </summary>
        /// <param name="SiteMap_File"> Sitemap file to read </param>
        /// <returns> Fully built sitemap object </returns>
        public static SobekCM_SiteMap Read_SiteMap_File(string SiteMap_File)
        {
            Stream reader = null;
            XmlTextReader nodeReader = null;
            SobekCM_SiteMap siteMap = null;
            int nodeValue = 1;

            Stack<SobekCM_SiteMap_Node> nodesStack = new Stack<SobekCM_SiteMap_Node>();

            try
            {
                // Create and open the readonly file stream
                reader = new FileStream(SiteMap_File, FileMode.Open, FileAccess.Read);

                // create the XML node reader
                nodeReader = new XmlTextReader(reader);

                // Read through the XML document
                while (nodeReader.Read())
                {
                    if (nodeReader.NodeType == XmlNodeType.Element)
                    {
                        // Handle the main sitemap tag
                        if (nodeReader.Name == "siteMap")
                        {
                            // This is the first node read, so it may have additional information
                            siteMap = new SobekCM_SiteMap();

                            // Look for the optional default breadcrumbs attribute
                            if (nodeReader.MoveToAttribute("default_breadcrumb"))
                            {
                                siteMap.Default_Breadcrumb = nodeReader.Value;
                            }

                            // Look for the optional width attribute
                            if (nodeReader.MoveToAttribute("width"))
                            {
                                short width;
                                Int16.TryParse(nodeReader.Value, out width);
                                siteMap.Width = width;
                            }

                            // Look for the optional url restriction attribute
                            if (nodeReader.MoveToAttribute("restrictedRobotUrl"))
                            {
                                siteMap.Restricted_Robot_URL = nodeReader.Value;
                            }
                        }

                        // Handle a new siteMapNode
                        if (nodeReader.Name == "siteMapNode")
                        {
                            string url = String.Empty;
                            string title = String.Empty;
                            string description = String.Empty;
                            bool empty = false;

                            // Before moving to any attributes, check to see if this is empty
                            if (nodeReader.IsEmptyElement)
                                empty = true;

                            // Step through the attributes
                            while (nodeReader.MoveToNextAttribute())
                            {
                                switch (nodeReader.Name)
                                {
                                    case "url":
                                        url = nodeReader.Value;
                                        break;

                                    case "title":
                                        title = nodeReader.Value;
                                        break;

                                    case "description":
                                        description = nodeReader.Value;
                                        break;
                                }
                            }

                            // Create the new node
                            SobekCM_SiteMap_Node newNode = new SobekCM_SiteMap_Node(url, title, description, nodeValue++);

                            // Add to the parent
                            if (nodesStack.Count == 0)
                            {
                                // This is the first node read so it should be the root node
                                if (siteMap != null) siteMap.RootNodes.Add(newNode);
                            }
                            else
                            {
                                nodesStack.Peek().Add_Child_Node(newNode);
                            }

                            // Add this to the stack, at least until the end of this node is found
                            // if this is not an empty element
                            if (!empty)
                                nodesStack.Push(newNode);
                        }
                    }
                    else if ((nodeReader.NodeType == XmlNodeType.EndElement) && ( nodeReader.Name == "siteMapNode" ))
                    {
                        nodesStack.Pop();
                    }
                }
            }
            finally
            {
                if (nodeReader != null)
                    nodeReader.Close();
                if (reader != null)
                    reader.Close();
            }

            return siteMap;
        }