/// <summary>
        /// Gets the match.
        /// </summary>
        /// <param name="matchElement">The match element.</param>
        /// <returns></returns>
        private Pattern GetMatch(XmlNode matchElement, ref IRuleFlagProcessor ruleFlags)
        {
            string url        = null;
            bool   ignoreCase = true;        // from schema definition
            bool   negate     = false;       // from schema definition

            if (matchElement.Attributes["url"] != null)
            {
                url = matchElement.Attributes["url"].Value;
            }

            if (matchElement.Attributes["ignoreCase"] != null)
            {
                ignoreCase = XmlConvert.ToBoolean(matchElement.Attributes["ignoreCase"].Value);
            }

            if (matchElement.Attributes["negate"] != null)
            {
                negate = XmlConvert.ToBoolean(matchElement.Attributes["negate"].Value);
            }

            // validationType="nonEmptyString"
            if (String.IsNullOrEmpty(url))
            {
                throw new RuleSetException("Match URL must be a non-empty value.");
            }

            var patternOptions = Manager.RuleOptions;

            if (ignoreCase)
            {
                ruleFlags.Add(new RF.NoCaseFlag());
                patternOptions |= RegexOptions.IgnoreCase;
            }

            return(new Pattern(url, negate, patternOptions));
        }
        /// <summary>
        /// Gets the match.
        /// </summary>
        /// <param name="matchElement">The match element.</param>
        /// <returns></returns>
        private Pattern GetMatch(XmlNode matchElement, ref IRuleFlagProcessor ruleFlags)
        {
            string url = null;
            var ignoreCase = true; // from schema definition
            var negate = false; // from schema definition

            if (matchElement.Attributes["url"] != null)
            {
                url = matchElement.Attributes["url"].Value;
            }

            if (matchElement.Attributes["ignoreCase"] != null)
            {
                ignoreCase = XmlConvert.ToBoolean(matchElement.Attributes["ignoreCase"].Value);
            }

            if (matchElement.Attributes["negate"] != null)
            {
                negate = XmlConvert.ToBoolean(matchElement.Attributes["negate"].Value);
            }

            // validationType="nonEmptyString"
            if (string.IsNullOrEmpty(url))
            {
                throw new RuleSetException("Match URL must be a non-empty value.");
            }

            var patternOptions = UrlRewriterManager.RuleOptions;

            if (ignoreCase)
            {
                ruleFlags.Add(new  NoCaseFlag());
                patternOptions |= RegexOptions.IgnoreCase;
            }

            return new Pattern(url, negate, patternOptions);
        }
        /// <summary>
        /// Gets the action.
        /// </summary>
        /// <param name="actionElement">The action element.</param>
        /// <param name="ruleFlags">The rule flags.</param>
        /// <returns></returns>
        private IRuleAction GetAction(XmlNode actionElement, Pattern pattern, ref IRuleFlagProcessor ruleFlags)
        {
            ActionType   type = ActionType.None;
            string       url  = null;
            bool         appendQueryString = true;     // from schema definition
            RedirectType redirectType      = RedirectType.Permanent;
            uint         statusCode        = 0U;
            uint         subStatusCode     = 0U; // from schema definition
            string       statusReason      = null;
            string       statusDescription = null;

            if (actionElement.Attributes["type"] != null)
            {
                try { type = (ActionType)Enum.Parse(typeof(ActionType), actionElement.Attributes["type"].Value, true); }
                catch (Exception exc) { Manager.Log("Action: " + exc.Message, "Error"); }
            }

            if (actionElement.Attributes["url"] != null)
            {
                url = actionElement.Attributes["url"].Value;
            }

            if (actionElement.Attributes["appendQueryString"] != null)
            {
                appendQueryString = XmlConvert.ToBoolean(actionElement.Attributes["appendQueryString"].Value);
            }

            if (actionElement.Attributes["redirectType"] != null)
            {
                try { redirectType = (RedirectType)Enum.Parse(typeof(RedirectType), actionElement.Attributes["redirectType"].Value, true); }
                catch (Exception exc) { Manager.Log("Action: " + exc.Message, "Error"); }
            }

            if (actionElement.Attributes["statusCode"] != null)
            {
                statusCode = XmlConvert.ToUInt32(actionElement.Attributes["statusCode"].Value);
            }

            if (actionElement.Attributes["subStatusCode"] != null)
            {
                subStatusCode = XmlConvert.ToUInt32(actionElement.Attributes["subStatusCode"].Value);
            }

            if (actionElement.Attributes["statusReason"] != null)
            {
                statusReason = actionElement.Attributes["statusReason"].Value;
            }

            if (actionElement.Attributes["statusDescription"] != null)
            {
                statusDescription = actionElement.Attributes["statusDescription"].Value;
            }

            if (String.IsNullOrEmpty(url))
            {
                throw new RuleSetException("Action URL must be a non-empty value.");
            }

            // validationType="requireTrimmedString"
            url = url.Trim();

            if (type == ActionType.Redirect)
            {
                ruleFlags.Add(new RF.RedirectFlag((int)redirectType));
            }
            else if (statusCode > 0U)
            {
                // validationType="integerRange" validationParameter="300,307,exclude"
                if (statusCode >= 300U && statusCode <= 307U)
                {
                    throw new RuleSetException("Action Status Code should not be an int between 300 - 307, use the redirectType for this range.");
                }

                if (statusCode < 1U || statusCode > 999U)
                {
                    throw new RuleSetException("Action Status Code should be between 1 - 999.");
                }

                if (subStatusCode < 0U || subStatusCode > 999U)
                {
                    throw new RuleSetException("Action Sub Status Code should be between 0 - 999.");
                }

                ruleFlags.Add(new RF.ResponseStatusFlag(statusCode, subStatusCode, statusReason, statusDescription));
            }

            IRuleAction substitution = new DefaultRuleAction();

            substitution.Init(pattern, url);

            return(substitution);
        }
        /// <summary>
        /// Gets the action.
        /// </summary>
        /// <param name="actionElement">The action element.</param>
        /// <param name="ruleFlags">The rule flags.</param>
        /// <returns></returns>
        private IRuleAction GetAction(XmlNode actionElement, Pattern pattern, ref IRuleFlagProcessor ruleFlags)
        {
            var type = ActionType.None;
            string url = null;
            var appendQueryString = true; // from schema definition
            var redirectType = RedirectType.Permanent;
            var statusCode = 0U;
            var subStatusCode = 0U; // from schema definition
            string statusReason = null;
            string statusDescription = null;

            if (actionElement.Attributes["type"] != null)
            {
                try { type = (ActionType)Enum.Parse(typeof(ActionType), actionElement.Attributes["type"].Value, true); }
                catch (Exception exc)
                {
                    Logger.Error("Action: " + exc.Message, exc);
                }
            }

            if (actionElement.Attributes["url"] != null)
            {
                url = actionElement.Attributes["url"].Value;
            }

            if (actionElement.Attributes["appendQueryString"] != null)
            {
                appendQueryString = XmlConvert.ToBoolean(actionElement.Attributes["appendQueryString"].Value);
            }

            if (actionElement.Attributes["redirectType"] != null)
            {
                try { redirectType = (RedirectType)Enum.Parse(typeof(RedirectType), actionElement.Attributes["redirectType"].Value, true); }
                catch (Exception exc) { Logger.Error("Action: " + exc.Message, exc); }
            }

            if (actionElement.Attributes["statusCode"] != null)
            {
                statusCode = XmlConvert.ToUInt32(actionElement.Attributes["statusCode"].Value);
            }

            if (actionElement.Attributes["subStatusCode"] != null)
            {
                subStatusCode = XmlConvert.ToUInt32(actionElement.Attributes["subStatusCode"].Value);
            }

            if (actionElement.Attributes["statusReason"] != null)
                statusReason = actionElement.Attributes["statusReason"].Value;

            if (actionElement.Attributes["statusDescription"] != null)
            {
                statusDescription = actionElement.Attributes["statusDescription"].Value;
            }

            if (string.IsNullOrEmpty(url))
            {
                throw new RuleSetException("Action URL must be a non-empty value.");
            }

            // validationType="requireTrimmedString"
            url = url.Trim();

            if (type == ActionType.Redirect)
            {
                ruleFlags.Add(new RedirectFlag((int)redirectType));
            }
            else if (statusCode > 0U)
            {
                // validationType="integerRange" validationParameter="300,307,exclude"
                if (statusCode >= 300U && statusCode <= 307U)
                {
                    throw new RuleSetException("Action Status Code should not be an int between 300 - 307, use the redirectType for this range.");
                }

                if (statusCode < 1U || statusCode > 999U)
                {
                    throw new RuleSetException("Action Status Code should be between 1 - 999.");
                }

                if (subStatusCode < 0U || subStatusCode > 999U)
                {
                    throw new RuleSetException("Action Sub Status Code should be between 0 - 999.");
                }

                ruleFlags.Add(new ResponseStatusFlag(statusCode, subStatusCode, statusReason, statusDescription));
            }

            IRuleAction substitution = new DefaultRuleAction();
            substitution.Init(pattern, url);

            return substitution;
        }