//TODO: Use an abstraction and a factory to manage filter-appliers
        public Interaction Apply(RequestFilter filter, Interaction interaction)
        {
            string headersKey = "$.headers.";
            string bodyKey    = "$.body.";
            string queryKey   = "$.query.";
            string pathKey    = "$.path";

            var requestBody = interaction.Request.Body;

            var requestBodyData = new DynamicObjectAccess(true).Flatten(requestBody, "");

            var requestQueryData = QueryToDictionary(interaction.Request.Query);

            if (filter.UrlMatcher.Matches(interaction.Request.Path))
            {
                if (filter.DataKey.StartsWith(headersKey))
                {
                    string dataKey = TrimStart(filter.DataKey, headersKey);

                    interaction = ApplyHeaderFilter(interaction, dataKey, filter.OverrideValue);
                }
                else if (filter.DataKey.StartsWith(bodyKey))
                {
                    string dataKey = TrimStart(filter.DataKey, bodyKey);

                    if (requestBodyData.ContainsKey(dataKey))
                    {
                        requestBodyData[dataKey] = filter.OverrideValue;
                    }
                }
                else if (filter.DataKey.StartsWith(queryKey))
                {
                    string dataKey = TrimStart(filter.DataKey, queryKey);

                    if (requestQueryData.ContainsKey(dataKey))
                    {
                        requestQueryData[dataKey] = filter.OverrideValue as string;
                    }
                }
                else if (filter.DataKey == pathKey)
                {
                    var path = filter.OverrideValue as string;

                    if (!string.IsNullOrEmpty(path))
                    {
                        interaction.Request.Path = path;
                    }
                }
            }

            requestBody = new DynamicObjectAccess(true).LoadInto(requestBody, requestBodyData);

            interaction.Request.Body = requestBody;

            interaction.Request.Query = DictionaryToQuery(requestQueryData);

            return(interaction);
        }
        private static EcmaType GetObjectEcmaType(object o)
        {
            var flattened = new DynamicObjectAccess().Flatten(o, "");

            var prototype = new ProtoType();

            foreach (var keyValuePair in flattened)
            {
                prototype.Add(keyValuePair.Key, keyValuePair.GetEcmaType());
            }

            var objectEcmaType = EcmaTypes.ObjectType(prototype);

            return(objectEcmaType);
        }