/// <summary>
        /// The token key, which might be a property of the <paramref name="application"/> object or an
        /// application value in the application data.
        /// </summary>
        /// <param name="application">The application to source data from.</param>
        /// <param name="token">The token key.</param>
        /// <param name="path">Specifies the path to the token. Defaults to <see langword="null"/>.</param>
        /// <returns>The value of the token.</returns>
        /// <remarks>Order of precedence: (1) <paramref name="application"/> object; (2) application data.</remarks>
        public static object GetTokenValue(this Application application, string token, ApplicationDataPath path = null)
        {
            object tokenValue;
            if (application.TryGetPropertyValue(token, '.', out tokenValue))
            {
                return tokenValue;
            }

            // We are going to be be popping items so we should create our own copy of the path.
            ApplicationDataPath pathIterator = new ApplicationDataPath(path ?? new ApplicationDataPath());
            string tokenPath = pathIterator.ToString(token);
            tokenValue = application.ApplicationData.GetValue<object>(tokenPath, null);

            while (tokenValue == null && pathIterator.Count != 0)
            {
                pathIterator.TraverseUp();
                tokenPath = pathIterator.ToString(token);
                tokenValue = application.ApplicationData.GetValue<object>(tokenPath, null);
            }

            return tokenValue;
        }
        /// <summary>
        /// Implements the validation logic for the receiver.
        /// </summary>
        /// <param name="objectToValidate">The object to validate.</param>
        /// <param name="currentTarget">The object on the behalf of which the validation is performed.</param>
        /// <param name="key">The key that identifies the source of objectToValidate.</param>
        /// <param name="validationResults">The validation results to which the outcome of the validation should be stored.</param>
        public override void DoValidate(object objectToValidate, object currentTarget, string key, ValidationResults validationResults)
        {
            if (objectToValidate == null)
            {
                return;
            }

            object[] arr = (object[])objectToValidate;
            Dictionary<string, object>[] items = arr.Length > 0 ? objectToValidate as Dictionary<string, object>[] : new Dictionary<string, object>[0];
            for (int i = 0; i < items.Length; i++)
            {
                Dictionary<string, object> item = items[i];
                ApplicationDataPath path = new ApplicationDataPath(key);
                path.Last().Index = i;
                this.WrappedValidator.DoValidate(item, currentTarget, path.ToString(), validationResults);
            }
        }
        /// <summary>
        /// Implements the validation logic for the receiver.
        /// </summary>
        /// <param name="objectToValidate">The object to validate.</param>
        /// <param name="currentTarget">The object on the behalf of which the validation is performed.</param>
        /// <param name="key">The key that identifies the source of objectToValidate.</param>
        /// <param name="validationResults">The validation results to which the outcome of the validation should be stored.</param>
        public override void DoValidate(object objectToValidate, object currentTarget, string key, ValidationResults validationResults)
        {
            if (objectToValidate == null)
            {
                return;
            }

            ControlValueValidator controlValueValidator = this.WrappedValidator as ControlValueValidator;
            LikertControl likert = this.AllControls.FindRecursive<LikertControl>(key);

            Dictionary<string, object> items = objectToValidate as Dictionary<string, object>;
            ApplicationDataPath path = new ApplicationDataPath(key);
            foreach (KeyValuePair<string, object> item in items)
            {
                string tag = likert.Questions.First(q => q.Name == item.Key).Label;
                controlValueValidator.SetTag(tag);
                this.WrappedValidator.DoValidate(item.Value, currentTarget, path.ToString(item.Key), validationResults);
            }
        }
 public void TokenAtRoot()
 {
     ApplicationDataPath path = new ApplicationDataPath();
     Assert.AreEqual("token", path.ToString("token"));
 }
 public void TokenAtLevelTwo()
 {
     ApplicationDataPath path = new ApplicationDataPath();
     path.Prepend("Inner", 3);
     path.Prepend("Outer", 2);
     Assert.AreEqual("Outer[2].Inner[3].token", path.ToString("token"));
 }
 public void TokenAtLevelOne()
 {
     ApplicationDataPath path = new ApplicationDataPath();
     path.Prepend("Repeater1", 2);
     Assert.AreEqual("Repeater1[2].token", path.ToString("token"));
 }
 public void HasEmptyIndex()
 {
     ApplicationDataPath path = new ApplicationDataPath();
     path.Prepend("Inner", null);
     Assert.AreEqual("Inner.token", path.ToString("token"));
 }
        /// <summary>
        /// Runs a calculation for all instances of a repeater and adds the result to <paramref name="resultsContainer"/>.
        /// </summary>
        /// <param name="control">The calculation to run.</param>
        /// <param name="relativePath">The relative path to <paramref name="control"/> within <paramref name="resultsContainer"/> and <paramref name="applicationContainer"/>.</param>
        /// <param name="absolutePath">The absolute path to <paramref name="control"/> from the root of the application data.</param>
        /// <param name="resultsContainer">A dictionary of results.</param>
        /// <param name="applicationContainer">The application data container.</param>
        /// <param name="exceptionList">A list that <see cref="ExpressionEvaluatorException"/>s will be added to before returning to the client.</param>
        private void CalculateRepeater(CalculationControl control, ApplicationDataPath relativePath, ApplicationDataPath absolutePath, Dictionary<string, object> resultsContainer, Dictionary<string, object> applicationContainer, List<ExpressionEvaluatorException> exceptionList)
        {
            if (relativePath.Count == 0)
            {
                try
                {
                    var result = this.Evaluate(control.CalculationExpression, absolutePath);
                    resultsContainer[control.Name] = result;
                    applicationContainer[control.Name] = result;
                }
                catch (ExpressionEvaluatorException e)
                {
                    e.Tag = absolutePath.ToString(control.Name);
                    exceptionList.Add(e);
                }

                return;
            }

            ApplicationDataPathSegment segment = relativePath.TraverseDown();

            Dictionary<string, object>[] repeaterCalculationResults = (Dictionary<string, object>[])resultsContainer[segment.Name];
            Dictionary<string, object>[] repeaterApplicationData = applicationContainer.GetRepeaterItemsOrDefault(segment.Name);

            for (var i = 0; i < repeaterCalculationResults.Length; i++)
            {
                segment.Index = i;
                absolutePath.FirstOrDefault(s => s.Name == segment.Name).Index = segment.Index;
                this.CalculateRepeater(control, new ApplicationDataPath(relativePath), absolutePath, repeaterCalculationResults[i], repeaterApplicationData[i], exceptionList);
            }
        }
 /// <summary>
 /// Converts a string in format <code>RepeaterName-Index-FieldName</code> to a string based
 /// repeater path in the format <code>RepeaterName[Index].FieldName</code> which is used to
 /// pre-populate application data.
 /// </summary>
 /// <param name="paramKey">The parameter key.</param>
 /// <param name="repeaterRegex">The repeater regex.</param>
 /// <returns>A string based repeater path in the format <code>RepeaterName[Index].FieldName</code></returns>
 private string DetermineRepeaterPath(string paramKey, Regex repeaterRegex)
 {
     Match match = repeaterRegex.Match(paramKey);
     ApplicationDataPath path = new ApplicationDataPath();
     path.Append(match.Groups["RepeaterName"].Value, int.Parse(match.Groups["Index"].Value));
     return path.ToString(match.Groups["FieldName"].Value);
 }