/// <summary>
        /// Add the specified data to the cache.
        /// </summary>
        /// <param name="data">
        /// The <see cref="IFlowData"/> to use as a key.
        /// </param>
        /// <param name="value">
        /// The <code>TValue</code> to store with the key.
        /// </param>
        public virtual void Put(IFlowData data, TValue value)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            _internalCache.Put(data.GenerateKey(GetFilter()), value);
        }
        /// <summary>
        /// Get the <code>TValue</code> associated with the key generated
        /// from the supplied <see cref="IFlowData"/> instance.
        /// </summary>
        /// <param name="data">
        /// The <see cref="IFlowData"/> to use as a key.
        /// </param>
        /// <returns>
        /// If a matching item exists in the cache then the
        ///  <code>TValue</code> is returned. If not, the default value
        /// is returned. (i.e. null for reference types, 0 for int, etc)
        /// </returns>
#pragma warning disable CA1043 // Use Integral Or String Argument For Indexers
        // At a lower level, the flow data is converted to a string
        // key that is used on the cache itself.
        // We allow an IFlowData instance to be supplied as the key
        // at this level for convenience.
        public virtual TValue this[IFlowData data]
#pragma warning restore CA1043 // Use Integral Or String Argument For Indexers
        {
            get
            {
                if (data == null)
                {
                    throw new ArgumentNullException(nameof(data));
                }
                return(_internalCache[data.GenerateKey(GetFilter())]);
            }
        }
        private void ServeContent(IContextAdapter context, IFlowData flowData, ContentType contentType)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (flowData == null)
            {
                throw new ArgumentNullException(nameof(flowData));
            }

            context.Response.Clear();
            context.Response.ClearHeaders();

            // Get the hash code.
            var hash = flowData.GenerateKey(_pipeline.EvidenceKeyFilter).GetHashCode();

            if (int.TryParse(context.Request.GetHeaderValue("If-None-Match"),
                             out int previousHash) &&
                hash == previousHash)
            {
                // The response hasn't changed so respond with a 304.
                context.Response.StatusCode = 304;
            }
            else
            {
                // Otherwise, return the requested content to the client.
                string content = null;
                switch (contentType)
                {
                case ContentType.JavaScript:
                    var jsElement = flowData.Pipeline.GetElement <JavaScriptBuilderElement>();
                    if (jsElement == null)
                    {
                        throw new PipelineConfigurationException(
                                  Messages.ExceptionNoJavaScriptBuilder);
                    }
                    var jsData = flowData.GetFromElement(jsElement);
                    content = jsData?.JavaScript;
                    break;

                case ContentType.Json:
                    var jsonElement = flowData.Pipeline.GetElement <JsonBuilderElement>();
                    if (jsonElement == null)
                    {
                        throw new PipelineConfigurationException(
                                  Messages.ExceptionNoJsonBuilder);
                    }
                    var jsonData = flowData.GetFromElement(jsonElement);
                    content = jsonData?.Json;
                    break;

                default:
                    break;
                }

                int length = 0;
                if (content != null && content.Length > 0)
                {
                    length = Encoding.UTF8.GetBytes(content).Length;
                }

                context.Response.StatusCode = 200;
                SetHeaders(context,
                           hash.ToString(CultureInfo.InvariantCulture),
                           length,
                           contentType == ContentType.JavaScript ? "x-javascript" : "json");

                context.Response.Write(content);
            }
        }