/// <summary> Stores the item aggregation hierarchy to the cache  </summary>
        /// <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_Aggregation_Hierarchy(Aggregation_Hierarchy StoreObject, Custom_Tracer Tracer)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("CachedDataManager.Store_Aggregation_Hierarchy", "Entering Store_Item_Aggregation method");
            }

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

            // Determine the key
            const string KEY = "AGGR_HIERARCHY";

            const int LOCAL_EXPIRATION = 15;

            // Locally cache if this doesn't exceed the limit
            if (Tracer != null)
            {
                Tracer.Add_Trace("CachedDataManager.Store_Aggregation_Hierarchy", "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> [HELPER] Gets the entire collection hierarchy (used for hierarchical tree displays) </summary>
        /// <param name="Tracer"></param>
        /// <returns> Fully built aggregation hierarchy </returns>
        /// <remarks> This may be public now, but this will be converted into a private helped class with
        /// the release of SobekCM 5.0 </remarks>
        public static Aggregation_Hierarchy get_aggregation_hierarchy(Custom_Tracer Tracer)
        {
            // Get the aggregation code manager
            Aggregation_Hierarchy returnValue = CachedDataManager.Aggregations.Retrieve_Aggregation_Hierarchy(Tracer);

            if (returnValue != null)
            {
                Tracer.Add_Trace("AggregationServices.get_aggregation_hierarchy", "Found aggregation hierarchy in the cache");
                return(returnValue);
            }

            Tracer.Add_Trace("AggregationServices.get_aggregation_hierarchy", "Aggregation hierarchy NOT found in the cache.. will build");

            // Build the collection hierarchy (from the database)
            returnValue = Item_Aggregation_Utilities.Get_Collection_Hierarchy(Tracer);

            // Store in the cache
            if (returnValue != null)
            {
                Tracer.Add_Trace("AggregationServices.get_aggregation_hierarchy", "Storing built aggregation hierarchy in cache");
                CachedDataManager.Aggregations.Store_Aggregation_Hierarchy(returnValue, Tracer);
            }
            else
            {
                Tracer.Add_Trace("AggregationServices.get_aggregation_hierarchy", "Aggregation hierarchy not built correctly, NULL returned from Item_Aggregation_Utilities.Get_Collection_Hierarchy method");
            }

            return(returnValue);
        }
        /// <summary> Gets the entire collection hierarchy (used for hierarchical tree displays) </summary>
        /// <param name="Response"></param>
        /// <param name="UrlSegments"></param>
        /// <param name="QueryString"></param>
        /// <param name="Protocol"></param>
        /// <param name="IsDebug"></param>
        public void GetCollectionHierarchy(HttpResponse Response, List <string> UrlSegments, NameValueCollection QueryString, Microservice_Endpoint_Protocol_Enum Protocol, bool IsDebug)
        {
            Custom_Tracer tracer = new Custom_Tracer();

            tracer.Add_Trace("AggregationServices.GetCollectionHierarchy", "Return the hierarchical list of all active and unhidden aggregations");

            try
            {
                // Get the aggregation code manager
                Aggregation_Hierarchy returnValue = get_aggregation_hierarchy(tracer);

                // If this was debug mode, then just write the tracer
                if (IsDebug)
                {
                    Response.ContentType = "text/plain";
                    Response.Output.WriteLine("DEBUG MODE DETECTED");
                    Response.Output.WriteLine();
                    Response.Output.WriteLine(tracer.Text_Trace);

                    return;
                }

                // Get the JSON-P callback function
                string json_callback = "parseCollectionHierarchy";
                if ((Protocol == Microservice_Endpoint_Protocol_Enum.JSON_P) && (!String.IsNullOrEmpty(QueryString["callback"])))
                {
                    json_callback = QueryString["callback"];
                }

                // Use the base class to serialize the object according to request protocol
                Serialize(returnValue, Response, Protocol, json_callback);
            }
            catch (Exception ee)
            {
                if (IsDebug)
                {
                    Response.ContentType = "text/plain";
                    Response.Output.WriteLine("EXCEPTION CAUGHT!");
                    Response.Output.WriteLine();
                    Response.Output.WriteLine(ee.Message);
                    Response.Output.WriteLine();
                    Response.Output.WriteLine(ee.StackTrace);
                    Response.Output.WriteLine();
                    Response.Output.WriteLine(tracer.Text_Trace);
                    return;
                }

                Response.ContentType = "text/plain";
                Response.Output.WriteLine("Error completing request");
                Response.StatusCode = 500;
            }
        }
        /// <summary> Adds the entire collection hierarchy under the ALL aggregation object </summary>
        /// <param name="Tracer">Trace object keeps a list of each method executed and important milestones in rendering </param>
        /// <returns> TRUE if successful, otherwise FALSE </returns>
        /// <remarks> This is postponed until it is needed for the TREE VIEW on the home page, to allow the system to start
        /// faster, even with a great number of item aggregationPermissions in the hierarchy </remarks>
        public static Aggregation_Hierarchy Get_Collection_Hierarchy(Custom_Tracer Tracer)
        {
            if (Tracer != null)
            {
                Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Collection_Hierarchy", "Preparing to create the aggregation hierarchy object");
            }

            // Get the database table
            DataSet childInfo = Engine_Database.Get_Aggregation_Hierarchies(Tracer);

            if (childInfo == null)
            {
                if (Tracer != null)
                {
                    Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Collection_Hierarchy", "NULL value returned from database lookup");
                }

                return(null);
            }

            // Build the return value
            Aggregation_Hierarchy returnValue = new Aggregation_Hierarchy();

            // Add all the collections
            if (Tracer != null)
            {
                Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Collection_Hierarchy", "Add all the child aggregations to the hierarchy");
            }
            add_hierarchy_children(returnValue.Collections, childInfo.Tables[0]);

            // Add all the institutions
            if (Tracer != null)
            {
                Tracer.Add_Trace("Item_Aggregation_Utilities.Get_Collection_Hierarchy", "Add all the institutions to the hierarchy");
            }
            add_hierarchy_children(returnValue.Institutions, childInfo.Tables[1]);

            return(returnValue);
        }
        /// <summary> Retrieves the item aggregation hierarchy from the cache  </summary>
        /// <param name="Tracer"> Trace object keeps a list of each method executed and important milestones in rendering</param>
        /// <returns> Either NULL or the item aggregation hierarchy </returns>
        public Aggregation_Hierarchy Retrieve_Aggregation_Hierarchy(Custom_Tracer Tracer)
        {
            // If the cache is disabled, just return before even tracing
            if ((settings.Disabled) || (HttpContext.Current == null))
            {
                return(null);
            }

            if (Tracer != null)
            {
                Tracer.Add_Trace("CachedDataManager.Retrieve_Aggregation_Hierarchy", "");
            }

            // Determine the key
            const string KEY = "AGGR_HIERARCHY";

            // See if this is in the local cache first
            Aggregation_Hierarchy returnValue = HttpContext.Current.Cache.Get(KEY) as Aggregation_Hierarchy;

            if (returnValue != null)
            {
                if (Tracer != null)
                {
                    Tracer.Add_Trace("CachedDataManager.Retrieve_Aggregation_Hierarchy", "Found item aggregation hierarchy on local cache");
                }

                return(returnValue);
            }

            if (Tracer != null)
            {
                Tracer.Add_Trace("CachedDataManager.Retrieve_Aggregation_Hierarchy", "Aggregation hierarchy not found in either the local cache ");
            }

            // Since everything failed, just return null
            return(null);
        }