public void AppendsToEnd()
 {
     ApplicationDataPath path = new ApplicationDataPath();
     path.Append("Foo", 42);
     path.Append("Bar", 16);
     Assert.AreEqual(16, path.Last().Index);
 }
 public void HasCorrectNumberOfItems()
 {
     ApplicationDataPath path = new ApplicationDataPath();
     path.Append("Foo", 42);
     path.Append("Bar", 16);
     Assert.AreEqual(2, path.Count);
 }
            public void DefaultIndex()
            {
                ApplicationDataPath path = new ApplicationDataPath("Foo[1].Bar");

                Assert.AreEqual(2, path.Count);
                Assert.AreEqual("Bar", path.Last().Name);
                Assert.IsNull(path.Last().Index);
            }
 /// <summary>
 /// Recurses up through the control tree and adds any repeater controls to <paramref name="path"/>.
 /// </summary>
 /// <param name="control">The control which acts as the this instance.</param>
 /// <param name="controlList">The control list.</param>
 /// <param name="path">A <see cref="ApplicationDataPath"/> to update.</param>
 private static void CreatePathTemplate(this Control control, ControlList controlList, ApplicationDataPath path)
 {
     Control parent = control.GetRepeaterAncestor(controlList);
     if (parent != null)
     {
         path.Prepend(parent.Name);
         parent.CreatePathTemplate(controlList, path);
     }
 }
            public void MatchesOriginal()
            {
                ApplicationDataPath original = new ApplicationDataPath();
                original.Prepend("Bar", 42);
                original.Prepend("Foo", 10);

                ApplicationDataPath copy = new ApplicationDataPath(original);

                Assert.AreEqual(original.Count, copy.Count);
                Assert.AreEqual(original.Last().Name, copy.Last().Name);
                Assert.AreEqual(original.Last().Index, copy.Last().Index);
            }
            public void IsNotOriginal()
            {
                ApplicationDataPath original = new ApplicationDataPath();
                original.Prepend("Bar", 42);
                original.Prepend("Foo", 10);

                ApplicationDataPath copy = new ApplicationDataPath(original);

                copy.TraverseDown();

                Assert.AreNotEqual(original.Count, copy.Count);
            }
        /// <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);
            }
        }
        /// <summary>
        /// Runs a calculation and adds the result to <paramref name="resultsContainer"/>.
        /// </summary>
        /// <param name="control">The calculation to run.</param>
        /// <param name="resultsContainer">A dictionary of results.</param>
        /// <param name="exceptionList">A list that <see cref="ExpressionEvaluatorException"/>s will be added to before returning to the client.</param>
        private void Calculate(CalculationControl control, Dictionary<string, object> resultsContainer, List<ExpressionEvaluatorException> exceptionList)
        {
            ApplicationDataPath absolutePath = control.CreatePathTemplate(this.controlList);
            if (control.IsRepeaterDescendant(this.controlList))
            {
                ApplicationDataPath relativePath = new ApplicationDataPath(absolutePath);
                this.CalculateRepeater(control, relativePath, absolutePath, resultsContainer, this.Application.ApplicationData, exceptionList);
                return;
            }

            try
            {
                resultsContainer[control.Name] = this.Evaluate(control.CalculationExpression, absolutePath);
                this.Application.ApplicationData.SetValue(control.Name, resultsContainer[control.Name], true);
            }
            catch (ExpressionEvaluatorException e)
            {
                e.Tag = control.Name;
                exceptionList.Add(e);
            }
        }
        /// <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;
        }
            public void TraverseTreeBottom()
            {
                Application application = new Application();
                application.ApplicationData.Add("RootChild", "RootChild Value");

                var outerRepeater = new List<Dictionary<string, object>> { new Dictionary<string, object>() };
                var innerRepeater = new List<Dictionary<string, object>> { new Dictionary<string, object>() };

                innerRepeater[0].Add("InnerChild", "InnerChild Value");
                outerRepeater[0].Add("InnerRepeater", innerRepeater.ToArray());
                outerRepeater[0].Add("OuterChild", "OuterChild Value");
                application.ApplicationData.Add("OuterRepeater", outerRepeater.ToArray());

                ApplicationDataPath path = new ApplicationDataPath();
                path.Prepend("InnerRepeater", 0);
                path.Prepend("OuterRepeater", 0);
                string value = application.GetTokenValue("InnerChild", path).ToString();

                Assert.AreEqual("InnerChild Value", value);
            }
        public void TestRepeaterCalculation()
        {
            ExpressionEvaluator evaluator = new ExpressionEvaluator(new Application(this.postedData));
            ApplicationDataPath path = new ApplicationDataPath();
            path.Append("key4");

            path.First().Index = 0;
            Assert.AreEqual(50, evaluator.Evaluate<int>("{%child1%} - {%child2%}", path));

            path.First().Index = 1;
            Assert.AreEqual(150, evaluator.Evaluate<int>("{%child1%} - {%child2%}", path));
        }
 public void NullString()
 {
     ApplicationDataPath path = new ApplicationDataPath((string)null);
     Assert.AreEqual(0, path.Count);
 }
 public void EmptyString()
 {
     ApplicationDataPath path = new ApplicationDataPath(string.Empty);
     Assert.AreEqual(0, path.Count);
 }
        /// <summary>
        /// Gets the replacement string for a token.
        /// </summary>
        /// <param name="token">The token being replaced.</param>
        /// <param name="format">A format string.</param>
        /// <param name="application">The application to source data from.</param>
        /// <param name="controls">The controls.</param>
        /// <param name="path">Specifies the path to the token.</param>
        /// <param name="defaultReplaceValue">The default replace value.</param>
        /// <returns>
        /// The replacement string.
        /// </returns>
        /// <remarks>
        /// Order of precedence: (1) Timestamp; (2) <paramref name="application" /> object; (3) application data.
        /// </remarks>
        private string GetReplacementString(string token, string format, Application application, ControlList controls, ApplicationDataPath path, string defaultReplaceValue)
        {
            Control control = controls.FindRecursive(c => c.Name == token);
            object value = this.GetTokenValue(token, application, control, path);
            if (value == null)
            {
                return defaultReplaceValue;
            }

            if (value is Array)
            {
                object[] valueArray = value as object[];
                StringBuilder builder = new StringBuilder();
                if (valueArray.Length == 0)
                {
                    return defaultReplaceValue;
                }

                string appendFormat = valueArray[0] is string ? "'{0}'" : "{0}";
                builder.AppendFormat(appendFormat, valueArray[0]);
                for (var i = 1; i < valueArray.Length; i++)
                {
                    builder.Append(",");
                    builder.AppendFormat(appendFormat, valueArray[i]);
                }

                return builder.ToString();
            }

            string formatString = string.IsNullOrEmpty(format) ? "{0}" : string.Format("{{0:{0}}}", format.Substring(1, format.Length - 2));
            return string.Format(CultureInfo.CurrentCulture, formatString, value);
        }
        /// <summary>
        /// Gets the value of a token.
        /// </summary>
        /// <param name="token">The token being replaced.</param>
        /// <param name="application">The application to source data from.</param>
        /// <param name="control">The control.</param>
        /// <param name="path">Specifies the path to the token.</param>
        /// <returns>
        /// The value of the token.
        /// </returns>
        /// <remarks>
        /// Order of precedence: (1) Timestamp; (2) Application URL (3) <paramref name="application" /> object; (4) application data.
        /// </remarks>
        private object GetTokenValue(string token, Application application, Control control, ApplicationDataPath path)
        {
            if (token.StartsWith(FormatterResources.TimestampToken, StringComparison.CurrentCultureIgnoreCase))
            {
                return DateTime.Now;
            }

            if (token.StartsWith(FormatterResources.ApplicationUrlToken, StringComparison.CurrentCultureIgnoreCase))
            {
                string url = string.Format(FormatterResources.ApplicationUrlFormat, this.BaseUrl, application.FormId, application.Id);
                return string.Format(FormatterResources.ApplicationAnchor, url);
            }

            if (application == null)
            {
                return null;
            }

            string valueStr = application.GetTokenValue(token, path) as string;
            if (control is DateControl)
            {
                DateTime dateValue;
                if (valueStr != null && DateTime.TryParseExact(valueStr, DateControl.SYSTEM_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out dateValue))
                {
                    return dateValue.ToString(DateControl.USER_FORMAT);
                }
            }

            var calculationControl = control as CalculationControl;
            if (calculationControl == null || !calculationControl.FormatAsCurrency || valueStr == null)
            {
                return application.GetTokenValue(token, path);
            }

            decimal decimalVal;
            bool parsed = decimal.TryParse(valueStr, out decimalVal);
            if (parsed)
            {
                return string.Format("{0:C}", decimalVal);
            }

            return application.GetTokenValue(token, path);
        }
Example #17
0
 public bool IsEqual(LDDEnvironment other)
 {
     return(ProgramFilesPath.Equals(other.ProgramFilesPath, StringComparison.InvariantCultureIgnoreCase) &&
            ApplicationDataPath.Equals(other.ApplicationDataPath, StringComparison.InvariantCultureIgnoreCase));
 }
 /// <summary>
 /// Creates a <see cref="ApplicationDataPath"/> template - with default indices -
 /// for <paramref name="control"/>.
 /// </summary>
 /// <param name="control">The control which acts as the this instance.</param>
 /// <param name="controlList">The control list.</param>
 /// <returns>A <see cref="ApplicationDataPath"/> template - with default indices -
 /// for <paramref name="control"/>.</returns>
 public static ApplicationDataPath CreatePathTemplate(this Control control, ControlList controlList)
 {
     ApplicationDataPath path = new ApplicationDataPath();
     control.CreatePathTemplate(controlList, path);
     return path;
 }
 public void TokenAtRoot()
 {
     ApplicationDataPath path = new ApplicationDataPath();
     Assert.AreEqual("token", path.ToString("token"));
 }
            public void NestedRepeaterValueUsingIndex()
            {
                Application application = new Application();

                Dictionary<string, object>[] outerRepeater = new Dictionary<string, object>[1];
                outerRepeater[0] = new Dictionary<string, object> { { "child-of-outer-1", "outer 1 text" } };
                Dictionary<string, object>[] innerRepeater = new Dictionary<string, object>[1];
                innerRepeater[0] = new Dictionary<string, object> { { "child-of-inner-1", "inner 1 text 1" }, { "child-of-inner-2", "inner 1 text 2" } };
                outerRepeater[0].Add("child-of-outer-2", innerRepeater);

                application.ApplicationData.Add("control-at-root", "root");
                application.ApplicationData.Add("repeater-at-root", outerRepeater);

                ApplicationDataPath path = new ApplicationDataPath();
                path.Prepend("child-of-outer-2", 0);
                path.Prepend("repeater-at-root", 0);

                string replacedAppValue1 = this.formatterNullDefault.Format(@"{%child-of-inner-2%}", application, new ControlList(), string.Empty, string.Empty, string.Empty, path);
                Assert.AreEqual("inner 1 text 2", replacedAppValue1);
            }
 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>
        /// Replaces tokens within <paramref name="str" /> with values from <paramref name="application" />.
        /// </summary>
        /// <param name="str">The string to search and replace in.</param>
        /// <param name="application">The application to source data from.</param>
        /// <param name="pageList">The page list.</param>
        /// <param name="defaultReplaceValue">The default replace value which will override the value set via
        /// <see cref="StringFormatter(string, string, string)" />.</param>
        /// <param name="nonReplacementPrefix">A prefix to be included in the pattern search but retained when substituting a value.</param>
        /// <param name="nonReplacementSuffix">A suffix to be included in the pattern search but retained when substituting a value.</param>
        /// <param name="path">Specifies the path to the token. Defaults to <see langword="null" />.</param>
        /// <returns>
        /// A formatted string with values from <paramref name="application" />.
        /// </returns>
        /// <remarks>
        /// Passing in <see langword="null" /> for <paramref name="defaultReplaceValue" /> means no replacement will take place when no suitable replacement value can be found.
        /// The token will remain in place.
        /// </remarks>
        public string Format(string str, Application application, PageList pageList, string defaultReplaceValue, string nonReplacementPrefix = "", string nonReplacementSuffix = "", ApplicationDataPath path = null)
        {
            ApplicationDataPath thisPath = path;
            string pattern = string.Format(
                            @"{0}({1})([^({2}[)]+)(\[[^(\])]+\])?\.?([^({2}[)]*)({2}){3}",
                            !string.IsNullOrEmpty(nonReplacementPrefix) ? string.Format("(?<={0})", nonReplacementPrefix) : string.Empty,
                            this.PlaceHolderPrefix,
                            this.PlaceHolderSuffix,
                            !string.IsNullOrEmpty(nonReplacementSuffix) ? string.Format("(?={0})", nonReplacementSuffix) : string.Empty);

            Regex r = new Regex(pattern, RegexOptions.IgnoreCase);
            str = r.Replace(str, match => this.ReplaceTokens(match, application, pageList, thisPath, defaultReplaceValue));

            return str;
        }
            public void TwoLevels()
            {
                ApplicationDataPath path = new ApplicationDataPath("Foo[1].Bar[3]");

                Assert.AreEqual(2, path.Count);
                Assert.AreEqual("Bar", path.Last().Name);
                Assert.AreEqual(3, path.Last().Index);
            }
        /// <summary>
        /// Replaces the match with the appropriate email token.
        /// </summary>
        /// <param name="match">The matched token.</param>
        /// <param name="application">The application.</param>
        /// <param name="pageList">The page list.</param>
        /// <param name="thisPath">The this path.</param>
        /// <param name="defaultReplaceValue">The default replace value.</param>
        /// <returns>
        /// The replaced email token.
        /// </returns>
        private string ReplaceTokens(Match match, Application application, PageList pageList, ApplicationDataPath thisPath, string defaultReplaceValue)
        {
            SummaryControl summary = null;
            string token = match.Groups[2].Value;

            List<Page> pagesToOutput = new List<Page>();
            foreach (Page page in pageList)
            {
                summary = page.Controls.FindRecursive<SummaryControl>(c => c.Type == ControlType.Summary && c.Name == token);
                if (summary == null)
                {
                    pagesToOutput.Add(page);
                }
                else
                {
                    break;
                }
            }

            if (summary == null)
            {
                return match.Value;
            }

            if (!summary.IncludedControls.All)
            {
                pagesToOutput = pageList.Where(p => p.Controls.Any(c => summary.IncludedControls.Controls.Contains(c.Name))).ToList();
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendLine(string.Format("<table style='{0}'>", FormatterResources.TableStyles));

            foreach (var page in pagesToOutput)
            {
                this.WriteHeaderRow(sb, page.PageTitle, FormatterResources.PageStyles);

                ControlList controlsToOutput = summary.IncludedControls.All ?
                                                    page.Controls :
                                                    new ControlList(page.Controls.FindAllRecursive(c => summary.IncludedControls.Controls.Contains(c.Name) && (c is ValueControl || c is RepeaterControl)));

                foreach (var control in controlsToOutput)
                {
                    if (control is RepeaterControl)
                    {
                        this.WriteRepeater(sb, control as RepeaterControl, summary.IncludedControls, application.ApplicationData);
                    }
                    else if (control is LikertControl)
                    {
                        this.WriteLikert(sb, control as LikertControl, application.ApplicationData);
                    }
                    else if (control is IControlWithOptions)
                    {
                        this.WriteOptionValue(sb, control as ControlWithOptions, application.ApplicationData);
                    }
                    else if (control is CalculationControl)
                    {
                        var controlWithLabel = control as IControlWithLabel;
                        this.WriteRow(sb, controlWithLabel.Label, this.GetValueToWrite(control, application.ApplicationData.GetValue<string>(control.Name)));
                    }
                    else
                    {
                        var valueControl = control as ValueControl;
                        if (valueControl != null && controlsToOutput.All(c => c.Id != control.ParentId))
                        {
                            this.WriteRow(sb, valueControl.Label, this.GetValueToWrite(control, application.ApplicationData.GetValue<string>(control.Name)));
                        }
                    }
                }
            }

            sb.AppendLine("</table>");

            return sb.ToString();
        }
            public void OneLevelIntegerAsName()
            {
                ApplicationDataPath path = new ApplicationDataPath("10");

                Assert.AreEqual(1, path.Count);
                Assert.AreEqual("10", path.Last().Name);
                Assert.IsNull(path.Last().Index);
            }
 public void LeavesObjectInCorrectState()
 {
     ApplicationDataPath path = new ApplicationDataPath();
     path.Append("Foo", 42);
     path.Append("Bar", 16);
     path.TraverseUp();
     Assert.AreEqual(42, path.First().Index);
 }
 public void PrependsToStart()
 {
     ApplicationDataPath path = new ApplicationDataPath();
     path.Prepend("Foo", 42);
     path.Prepend("Bar", 16);
     Assert.AreEqual(42, path.Last().Index);
 }
 public void ReturnsFirstItem()
 {
     ApplicationDataPath path = new ApplicationDataPath();
     path.Append("Foo", 42);
     path.Append("Bar", 16);
     ApplicationDataPathSegment segment = path.TraverseUp();
     Assert.AreEqual(16, segment.Index);
 }
        /// <summary>
        /// Replaces the match with the appropriate email token.
        /// </summary>
        /// <param name="match">The matched token.</param>
        /// <param name="application">The application.</param>
        /// <param name="controls">The controls.</param>
        /// <param name="thisPath">The this path.</param>
        /// <param name="defaultReplaceValue">The default replace value.</param>
        /// <returns>
        /// The replaced email token.
        /// </returns>
        private string ReplaceTokens(Match match, Application application, ControlList controls, ApplicationDataPath thisPath, string defaultReplaceValue)
        {
            string token = match.Groups[2].Value;
            string format = match.Groups[3].Value;

            ApplicationDataPath path;
            if (thisPath == null && !string.IsNullOrWhiteSpace(match.Groups[4].Value))
            {
                token = match.Groups[4].Value;
                path = new ApplicationDataPath(string.Format(@"{0}[{1}]", match.Groups[2].Value, match.Groups[3].Value));
            }
            else
            {
                path = thisPath;
            }

            string replacementString = this.GetReplacementString(token, format, application, controls, path, defaultReplaceValue);
            if (replacementString == null)
            {
                return match.ToString();
            }

            return this.replacements.Aggregate(replacementString, (current, kvp) => current.Replace(kvp.Key, kvp.Value));
        }