/// <summary>
 /// Initializes a new instance of the <see cref="MultiExpressionEvaluator"/> class.
 /// </summary>
 /// <param name="application">The <see cref="Application"/> instance used to substitute values
 /// into the expressions.</param>
 /// <param name="controls">The control list.</param>
 public MultiExpressionEvaluator(Application application, ControlList controls)
     : base(application)
 {
     this.controlList = controls;
     this.orderedCalculations = controls.FindAllRecursive<CalculationControl>(c => c != null).SortByEvaluationOrder();
 }
        /// <summary>
        /// Creates a PDF document of <paramref name="application"/> and sends it to <paramref name="target"/>.
        /// </summary>
        /// <param name="application">The application to create a PDF for.</param>
        /// <param name="controlList">The form control list.</param>
        /// <param name="target">The target stream.</param>
        public void WritePdfToStream(Application application, ControlList controlList, Stream target)
        {
            Document document = this.CreateDocument();

            Table metaTable = document.AppendTable(2, this.BorderColour);
            metaTable.AppendRow(this.DefaultStyle.Font.Size, "Application ID", application.ApplicationIdDisplay ?? application.ApplicationId);
            metaTable.AppendRow(this.DefaultStyle.Font.Size, "Created", application.Created.ToLocalTime().ToString(ApplicationPdfWriter.SHORT_DATETIME_FORMAT));
            metaTable.AppendRow(this.DefaultStyle.Font.Size, "Modified", application.Modified.HasValue ? application.Modified.Value.ToLocalTime().ToString(ApplicationPdfWriter.SHORT_DATETIME_FORMAT) : string.Empty);

            document.AppendVerticalSpace();

            Table appDataTable = document.AppendTable(2, this.BorderColour);

            OptionSourceProviderRegister register = new OptionSourceProviderRegister();
            register.Register(new RepeaterOptionSourceProvider(application.ApplicationData));
            controlList.FindAllRecursive<ControlWithOptions>(c => c.OptionSource.Type == OptionSourceType.Repeater).ForEach(c => c.LoadOptions(register));

            this.WriteValue(appDataTable, controlList, application.ApplicationData, 0);

            this.WritePdf(document, target);
            this.CleanUp();
        }
        /// <summary>
        /// Validates an application.
        /// </summary>
        /// <param name="application">The application to validate.</param>
        /// <param name="pagesToValidate">The pagesToValidate to validate.</param>
        /// <param name="controls">A list of all controls.</param>
        /// <param name="controlsAccess">The control access list for the current user.</param>
        /// <param name="subpageControlId">The id of the control acting as the current subpage. If <see langword="null" />, then all controls are validated.</param>
        /// <param name="product">The product object.</param>
        /// <returns>
        /// The <see cref="ValidationResults" />.
        /// </returns>
        private ValidationResults ValidateApplication(Application application, PageList pagesToValidate, ControlList controls, List<ControlAccess> controlsAccess, int? subpageControlId = null, ProductDefinition product = null)
        {
            List<ControlWithOptions> controlsWithOptions = controls.FindAllRecursive<ControlWithOptions>();

            if (controlsWithOptions.Any())
            {
                this.RegisterOptionControls(application.FormOrganisationId, true, controlsWithOptions, application.ApplicationData);
            }

            var controlList = pagesToValidate.AllControls;
            var ruleList = pagesToValidate.AllRules;

            if (subpageControlId != null)
            {
                var subpageControl = controlList.FindRecursive<GroupControl>(x => x.Id == subpageControlId);
                if (subpageControl != null)
                {
                    controlList = new ControlList { subpageControl };

                    TruthConditionList validRules = new TruthConditionList();
                    validRules.AddRange(ruleList.Where(rule => controlList.FindRecursive(x => x.Id.ToString().Equals(((ValidateTruthCondition)rule).Error.Position)) != null));

                    ruleList = validRules;
                }
            }

            ServiceEndpointList endpointList = pagesToValidate.AllExternalRuleHandlers.Count > 0 ?
                     this.DataAccess.GetServiceEndpointList() :
                     new ServiceEndpointList();

            RegexValidatorList regexValidators = this.DataAccess.GetValidatorList();

            if (product != null)
            {
                this.FillControlReferences(pagesToValidate, product.FormDefinition.Pages.AllControls);
                foreach (var referencedControls in pagesToValidate.Select(p => p.ReferencedControls))
                {
                    foreach (var control in referencedControls)
                    {
                        var exists = controls.FindRecursive(control.Name) != null;
                        if (exists)
                        {
                            continue;
                        }

                        controls.AddRange(referencedControls);
                    }
                }
            }

            ApplicationValidator validator = new ApplicationValidator(controls, controlList, controlsAccess, ruleList, pagesToValidate.AllExternalRuleHandlers, endpointList, this.endpointCommunicator, regexValidators);
            return validator.Validate(application);
        }