/// <summary>
        /// Processes the supplied ApplyWhen element.
        /// </summary>
        public override ProcessNodeResults ProcessNode(
            [NotNull] XElement element,
            [NotNull] IConfiguration configuration)
        {
            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (element.Name.LocalName != "Apply" ||
                element.Name.Namespace != XmlTemplate.ConfigGenXmlNamespace)
            {
                throw new ArgumentException("Supplied element should have name 'Apply' in the configgen namespace.", nameof(element));
            }

            IResult <ApplyElement, string> result = _applyElementCreator.Create(element);

            if (!result.Success)
            {
                element.Remove();
                return(ProcessNodeResults.CreateErrorResult(XmlTemplateErrorCodes.ApplyWhenElseFormatError, result.Error));
            }

            bool trueConditionAlreadyEvaluated = false;

            ApplyElement applyElement = result.Value;

            while (applyElement.PredicateSubNodes.Count > 0)
            {
                var subNode = applyElement.PredicateSubNodes.Dequeue();

                // if we've already evalutated a true, don't bother evaluating sub node conditions, just return a fail result
                ExpressionEvaluationResults evaluationResults = trueConditionAlreadyEvaluated
                    ? new ExpressionEvaluationResults(false, null, null, null)
                    : EvaluateCondition(subNode.Element, configuration, _configurationExpressionEvaluator);

                if (evaluationResults.ErrorCode != null)
                {
                    element.Remove();
                    return(ProcessNodeResults.CreateErrorResult(evaluationResults.ErrorCode, evaluationResults.ErrorMessage));
                }

                ProcessElement(subNode, evaluationResults.Result && !trueConditionAlreadyEvaluated);

                trueConditionAlreadyEvaluated |= evaluationResults.Result;
            }

            if (applyElement.FinalElseSubNode != null)
            {
                ProcessElement(applyElement.FinalElseSubNode, !trueConditionAlreadyEvaluated);
            }

            element.Remove();

            return(ProcessNodeResults.CreateSuccessResult());
        }
        public ProcessNodeResults ProcessNode(
            [NotNull] XElement element,
            [NotNull] IConfiguration configuration)
        {
            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            var attributeName = XName.Get("applyWhen", XmlTemplate.ConfigGenXmlNamespace);
            var attribute     = element.Attribute(attributeName);

            if (attribute == null)
            {
                throw new ArgumentException("Supplied element should contain an attribute with name 'applyWhen' in the configgen namespace.", nameof(element));
            }

            var expression = attribute.Value;

            if (expression.IsNullOrEmpty())
            {
                attribute.Remove();
                return(ProcessNodeResults.CreateErrorResult(XmlTemplateErrorCodes.ConditionProcessingError, "Condition error: and empty condition was encountered"));
            }

            ExpressionEvaluationResults evaluationResults = _evaluator.Evaluate(configuration.ConfigurationName, expression, element.Name);

            foreach (var usedToken in evaluationResults.UsedTokens)
            {
                if (configuration.Contains(usedToken))
                {
                    _tokenUsageTracker.OnTokenUsed(configuration.ConfigurationName, usedToken);
                }
                else
                {
                    _tokenUsageTracker.OnTokenNotRecognised(configuration.ConfigurationName, usedToken);
                }
            }

            if (evaluationResults.Result)
            {
                attribute.Remove();
            }
            else
            {
                element.Remove();
            }

            if (evaluationResults.ErrorCode != null)
            {
                return(ProcessNodeResults.CreateErrorResult(evaluationResults.ErrorCode, evaluationResults.ErrorMessage));
            }

            return(ProcessNodeResults.CreateSuccessResult());
        }
        public ProcessNodeResults ProcessNode(
            [NotNull] XElement element,
            [NotNull] IConfiguration configuration)
        {
            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            element.Remove();

            return(ProcessNodeResults.CreateErrorResult(
                       errorCode: XmlTemplateErrorCodes.BadMarkupError,
                       errorMessage: $"No node processor exists for the node of type 'element' with name '{element.Name.LocalName}'"));
        }
        public ProcessNodeResults ProcessNode(
            [NotNull] XElement element,
            [NotNull] IConfiguration configuration)
        {
            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            var configGenAttribute = element.Attributes().First(a => a.Name.Namespace == XmlTemplate.ConfigGenXmlNamespace);

            configGenAttribute.Remove();

            return(ProcessNodeResults.CreateErrorResult(
                       errorCode: XmlTemplateErrorCodes.BadMarkupError,
                       errorMessage: $"No node processor exists for the node of type 'attribute' with name '{configGenAttribute.Name.LocalName}'"));
        }