/// <summary> Add a new child node to this node </summary>
        /// <param name="NewNode"> Fully built new root child node </param>
        public void Add_Child(WebContent_Hierarchy_Node NewNode)
        {
            // Ensure the collection has been built
            if (Children == null)
                Children = new Dictionary<string, WebContent_Hierarchy_Node>(StringComparer.OrdinalIgnoreCase);

            // Build the child node
            Children[NewNode.Segment] = NewNode;
        }
        /// <summary> Add a new child node to this node </summary>
        /// <param name="NewSegment"> Segment name for this element with the web content hierarchy </param>
        /// <param name="NewWebContentID"> [Optional] Primary key for this web content page, from the database </param>
        /// <returns> Built and added new child node </returns>
        public WebContent_Hierarchy_Node Add_Child(string NewSegment, int? NewWebContentID = null)
        {
            // Ensure the collection has been built
            if (Children == null)
                Children = new Dictionary<string, WebContent_Hierarchy_Node>(StringComparer.OrdinalIgnoreCase);

            // Build the child node
            WebContent_Hierarchy_Node returnValue = new WebContent_Hierarchy_Node { Segment = NewSegment };
            if (NewWebContentID.HasValue) returnValue.WebContentID = NewWebContentID.Value;
            Children[NewSegment] = returnValue;

            // Return the built child node
            return returnValue;
        }
        /// <summary> Add a single new node to the web hierarchy </summary>
        /// <param name="WebContentID"> Primary key to the web content page to add </param>
        /// <param name="Redirect"> Redirect URL associated with the final web content page </param>
        /// <param name="Level1"> First level URL segment for the web content page to add </param>
        /// <param name="Level2"> Second level URL segment for the web content page to add </param>
        /// <param name="Level3"> Third level URL segment for the web content page to add </param>
        /// <param name="Level4"> Fourth level URL segment for the web content page to add </param>
        /// <param name="Level5"> Fifth level URL segment for the web content page to add </param>
        /// <param name="Level6"> Seventh level URL segment for the web content page to add </param>
        /// <param name="Level7"> Seventh level URL segment for the web content page to add </param>
        /// <param name="Level8"> Eighth level URL segment for the web content page to add </param>
        public void Add_Single_Node(int WebContentID, string Redirect, string Level1, string Level2, string Level3, string Level4, string Level5, string Level6, string Level7, string Level8)
        {
            if (String.IsNullOrEmpty(Level1))
                return;

            WebContent_Hierarchy_Node node;

            // Handle the FIRST level of the hierarchy
            if (Children.ContainsKey(Level1))
            {
                node = Children[Level1];
            }
            else
            {
                node = new WebContent_Hierarchy_Node {Segment = Level1};
                Children[Level1] = node;
            }

            // If no second level, assign the values and return
            if (( node == null ) || (String.IsNullOrEmpty(Level2)))
            {
                if (node != null)
                {
                    node.WebContentID = WebContentID;
                    node.Redirect = Redirect;
                }
                return;
            }

            // Handle the SECOND level of the hierarchy
            if (( node.Children != null ) && ( node.Children.ContainsKey(Level2)))
            {
                node = node.Children[Level2];
            }
            else
            {
                node = node.Add_Child(Level2);
            }

            // If no third level, assign the values and return
            if ((node == null) || (String.IsNullOrEmpty(Level3)))
            {
                if (node != null)
                {
                    node.WebContentID = WebContentID;
                    node.Redirect = Redirect;
                }
                return;
            }

            // Handle the THIRD level of the hierarchy
            if ((node.Children != null) && (node.Children.ContainsKey(Level3)))
            {
                node = node.Children[Level3];
            }
            else
            {
                node = node.Add_Child(Level3);
            }

            // If no fourth level, assign the values and return
            if ((node == null) || (String.IsNullOrEmpty(Level4)))
            {
                if (node != null)
                {
                    node.WebContentID = WebContentID;
                    node.Redirect = Redirect;
                }
                return;
            }

            // Handle the FOURTH level of the hierarchy
            if ((node.Children != null) && (node.Children.ContainsKey(Level4)))
            {
                node = node.Children[Level4];
            }
            else
            {
                node = node.Add_Child(Level4);
            }

            // If no fifth level, assign the values and return
            if ((node == null) || (String.IsNullOrEmpty(Level5)))
            {
                if (node != null)
                {
                    node.WebContentID = WebContentID;
                    node.Redirect = Redirect;
                }
                return;
            }

            // Handle the FIFTH level of the hierarchy
            if ((node.Children != null) && (node.Children.ContainsKey(Level5)))
            {
                node = node.Children[Level5];
            }
            else
            {
                node = node.Add_Child(Level5);
            }

            // If no sixth level, assign the values and return
            if ((node == null) || (String.IsNullOrEmpty(Level6)))
            {
                if (node != null)
                {
                    node.WebContentID = WebContentID;
                    node.Redirect = Redirect;
                }
                return;
            }

            // Handle the SIXTH level of the hierarchy
            if ((node.Children != null) && (node.Children.ContainsKey(Level6)))
            {
                node = node.Children[Level6];
            }
            else
            {
                node = node.Add_Child(Level6);
            }

            // If no seventh level, assign the values and return
            if ((node == null) || (String.IsNullOrEmpty(Level7)))
            {
                if (node != null)
                {
                    node.WebContentID = WebContentID;
                    node.Redirect = Redirect;
                }
                return;
            }

            // Handle the SEVENTH level of the hierarchy
            if ((node.Children != null) && (node.Children.ContainsKey(Level7)))
            {
                node = node.Children[Level7];
            }
            else
            {
                node = node.Add_Child(Level7);
            }

            // If no eighth level, assign the values and return
            if ((node == null) || (String.IsNullOrEmpty(Level8)))
            {
                if (node != null)
                {
                    node.WebContentID = WebContentID;
                    node.Redirect = Redirect;
                }
                return;
            }

            // Handle the EIGHTH level of the hierarchy
            if ((node.Children != null) && (node.Children.ContainsKey(Level8)))
            {
                node = node.Children[Level8];
            }
            else
            {
                node = node.Add_Child(Level8);
            }
            if (node != null)
            {
                node.WebContentID = WebContentID;
                node.Redirect = Redirect;
            }
        }
        /// <summary> Gets the hierarchy of all global content pages AND redirects, used for looking for a match from a requested URL </summary>
        /// <param name="ReturnValue"> Web content hierarchy object to populate - should be pre-cleared </param>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <returns> Flag indicating if this ran successfully, TRUE if successful, otherwise FALSE </returns>
        /// <remarks> This calls the 'SobekCM_WebContent_All_Brief' stored procedure </remarks> 
        public static bool WebContent_Populate_All_Hierarchy(WebContent_Hierarchy ReturnValue, Custom_Tracer Tracer)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("Engine_Database.WebContent_Populate_All_Hierarchy", "Gets the hierarchy tree of all content pages and redirects");
            }

            try
            {
                // Create the database agnostic reader
                EalDbReaderWrapper readerWrapper = EalDbAccess.ExecuteDataReader(DatabaseType, Connection_String, CommandType.StoredProcedure, "SobekCM_WebContent_All_Brief");

                // Get ready to step through all the rows returned from the reader
                WebContent_Hierarchy_Node[] list = new WebContent_Hierarchy_Node[7];

                // Read through each milestone
                DbDataReader reader = readerWrapper.Reader;
                while (readerWrapper.Reader.Read())
                {
                    // Grab the values out
                    string redirect = (!reader.IsDBNull(9)) ? reader.GetString(9) : null;
                    int id = reader.GetInt32(0);

                    // Handle the first segment
                    string segment1 = reader.GetString(1);
                    if ((list[0] == null) || (String.Compare(list[0].Segment, segment1, StringComparison.OrdinalIgnoreCase)  != 0))
                    {
                        // Build the node and add to the root nodes
                        WebContent_Hierarchy_Node newNode = new WebContent_Hierarchy_Node(segment1, id, redirect);
                        ReturnValue.Add_Child( newNode );

                        // If there are additional non-null segments, than this node does not represent the
                        // actual node that corresponds to this web content page or redirect
                        if (!reader.IsDBNull(2))
                            newNode.WebContentID = -1;

                        // Also save in the right spot in the list and clear the next level
                        list[0] = newNode;
                        list[1] = null;
                    }

                    // If there is a second segment here, handle that
                    if (!reader.IsDBNull(2))
                    {
                        string segment2 = reader.GetString(2);

                        // Is this a new segment 2 value?
                        if ((list[1] == null) || (String.Compare(list[1].Segment, segment2, StringComparison.OrdinalIgnoreCase) != 0))
                        {
                            // Build the node and add to the current parent node
                            WebContent_Hierarchy_Node newNode = new WebContent_Hierarchy_Node(segment2, id, redirect);
                            list[0].Add_Child(newNode);

                            // If there are additional non-null segments, than this node does not represent the
                            // actual node that corresponds to this web content page or redirect
                            if (!reader.IsDBNull(3))
                                newNode.WebContentID = -1;

                            // Also save in the right spot in the list and clear the next level
                            list[1] = newNode;
                            list[2] = null;
                        }

                        // Is there a third segment to add as well
                        if (!reader.IsDBNull(3))
                        {
                            string segment3 = reader.GetString(3);

                            // Is this a new segment 3 value?
                            if ((list[2] == null) || (String.Compare(list[2].Segment, segment3, StringComparison.OrdinalIgnoreCase) != 0))
                            {
                                // Build the node and add to the current parent node
                                WebContent_Hierarchy_Node newNode = new WebContent_Hierarchy_Node(segment3, id, redirect);
                                list[1].Add_Child(newNode);

                                // If there are additional non-null segments, than this node does not represent the
                                // actual node that corresponds to this web content page or redirect
                                if (!reader.IsDBNull(4))
                                    newNode.WebContentID = -1;

                                // Also save in the right spot in the list and clear the next level
                                list[2] = newNode;
                                list[3] = null;
                            }

                            // Is there a fourth segment to add as well
                            if (!reader.IsDBNull(4))
                            {
                                string segment4 = reader.GetString(4);

                                // Is this a new segment 4 value?
                                if ((list[3] == null) || (String.Compare(list[3].Segment, segment4, StringComparison.OrdinalIgnoreCase) != 0))
                                {
                                    // Build the node and add to the current parent node
                                    WebContent_Hierarchy_Node newNode = new WebContent_Hierarchy_Node(segment4, id, redirect);
                                    list[2].Add_Child(newNode);

                                    // If there are additional non-null segments, than this node does not represent the
                                    // actual node that corresponds to this web content page or redirect
                                    if (!reader.IsDBNull(5))
                                        newNode.WebContentID = -1;

                                    // Also save in the right spot in the list and clear the next level
                                    list[3] = newNode;
                                    list[4] = null;
                                }

                                // Is there a fifth segment to add as well
                                if (!reader.IsDBNull(5))
                                {
                                    string segment5 = reader.GetString(5);

                                    // Is this a new segment 5 value?
                                    if ((list[4] == null) || (String.Compare(list[4].Segment, segment5, StringComparison.OrdinalIgnoreCase) != 0))
                                    {
                                        // Build the node and add to the current parent node
                                        WebContent_Hierarchy_Node newNode = new WebContent_Hierarchy_Node(segment5, id, redirect);
                                        list[3].Add_Child(newNode);

                                        // If there are additional non-null segments, than this node does not represent the
                                        // actual node that corresponds to this web content page or redirect
                                        if (!reader.IsDBNull(6))
                                            newNode.WebContentID = -1;

                                        // Also save in the right spot in the list and clear the next level
                                        list[4] = newNode;
                                        list[5] = null;
                                    }

                                    // Is there a sixth segment to add as well
                                    if (!reader.IsDBNull(6))
                                    {
                                        string segment6 = reader.GetString(6);

                                        // Is this a new segment 6 value?
                                        if ((list[5] == null) || (String.Compare(list[5].Segment, segment6, StringComparison.OrdinalIgnoreCase) != 0))
                                        {
                                            // Build the node and add to the current parent node
                                            WebContent_Hierarchy_Node newNode = new WebContent_Hierarchy_Node(segment6, id, redirect);
                                            list[4].Add_Child(newNode);

                                            // If there are additional non-null segments, than this node does not represent the
                                            // actual node that corresponds to this web content page or redirect
                                            if (!reader.IsDBNull(7))
                                                newNode.WebContentID = -1;

                                            // Also save in the right spot in the list and clear the next level
                                            list[5] = newNode;
                                            list[6] = null;
                                        }

                                        // Is there a seventh segment to add as well
                                        if (!reader.IsDBNull(7))
                                        {
                                            string segment7 = reader.GetString(7);

                                            // Is this a new segment 7 value?
                                            if ((list[6] == null) || (String.Compare(list[6].Segment, segment7, StringComparison.OrdinalIgnoreCase) != 0))
                                            {
                                                // Build the node and add to the current parent node
                                                WebContent_Hierarchy_Node newNode = new WebContent_Hierarchy_Node(segment7, id, redirect);
                                                list[5].Add_Child(newNode);

                                                // If there are additional non-null segments, than this node does not represent the
                                                // actual node that corresponds to this web content page or redirect
                                                if (!reader.IsDBNull(8))
                                                    newNode.WebContentID = -1;

                                                // Also save in the right spot in the list.. no next level to clear
                                                list[6] = newNode;
                                            }

                                            // Is there an eigth segment? (Will always be a new one since the bottom of the unique hierarchy list)
                                            if (!reader.IsDBNull(8))
                                            {
                                                string segment8 = reader.GetString(8);

                                                // Build the node and add to the current parent node
                                                WebContent_Hierarchy_Node newNode = new WebContent_Hierarchy_Node(segment8, id, redirect);
                                                list[6].Add_Child(newNode);

                                                // Note, this last node always represents the web content page or redirect if
                                                // it made it this far.  No need to check next level and assign id to -1 if not null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

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

                // Return the built list
                return true;
            }
            catch (Exception ee)
            {
                Last_Exception = ee;
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Engine_Database.WebContent_Populate_All_Hierarchy", "Exception caught during database work", Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Engine_Database.WebContent_Populate_All_Hierarchy", ee.Message, Custom_Trace_Type_Enum.Error);
                    Tracer.Add_Trace("Engine_Database.WebContent_Populate_All_Hierarchy", ee.StackTrace, Custom_Trace_Type_Enum.Error);
                }
                return false;
            }
        }