/// <summary>
 /// Apply the updates to the <paramref name="securityConfiguration"/> object.
 /// </summary>
 /// <param name="securityConfiguration">
 /// The security configuration to apply the changes on.
 /// </param>
 public void Apply(SecurityConfiguration securityConfiguration)
 {
     this.ApplyApplicationEntitlements(securityConfiguration);
     this.ApplyPageEntitlements(securityConfiguration);
     this.ApplyControlEntitlements(securityConfiguration);
     this.ApplyMetadataEntitlements(securityConfiguration);
     this.ApplyStateUpdates(securityConfiguration);
 }
        /// <summary>
        /// Imports the products.
        /// </summary>
        /// <param name="sessionData">The session data.</param>
        /// <param name="migrationData">Contains the products to import.</param>
        /// <param name="systemRoleMap">A map of role ids, where the old id is the key and the new id is the value.</param>
        /// <param name="organisationMap">A map of organisation ids, where the old id is the key and the new id is the value.</param>
        /// <param name="validationResults">A list of validation results.</param>
        /// <param name="migrationResults">A list to which import results will be appended.</param>
        private void ImportProducts(SessionData sessionData, MigrationData migrationData, Dictionary<string, string> systemRoleMap, Dictionary<string, string> organisationMap, MigrationDataResults validationResults, MigrationDataResults migrationResults)
        {
            const string importedMessage = "Imported via Workbench";
            Dictionary<string, string> validatorMap = this.ImportValidators(sessionData.UserId, migrationData.Validators);
            Dictionary<string, string> serviceEndpointMap = this.ImportServiceEndpoints(sessionData, migrationData, validationResults, migrationResults);
            Dictionary<string, string> dataSetMap = this.ImportDataSets(sessionData, migrationData, validationResults, migrationResults);

            SystemSettings settings = this.manager.GetSystemSettings(sessionData.UserId);
            if (settings.EnableFormApprovals)
            {
                migrationData.Products.ForEach(p => p.BranchName = Constants.DefaultImportBranch);
            }

            foreach (ProductDefinition product in migrationData.Products)
            {
                if (!validationResults.GetNotificationsFor(product).CanImport)
                {
                    continue;
                }

                ProductDataSourceConfiguration dataSourceConfiguration = migrationData.ProductDataSourceConfigurations[product.Id];

                if (organisationMap.ContainsKey(product.OrganisationId))
                {
                    product.OrganisationId = organisationMap[product.OrganisationId];
                }

                WorkflowConfigurationContainer workflowConfiguration = migrationData.WorkflowConfigurations[product.Id];

                ApplicationEntitlementList applicationEntitlements = new ApplicationEntitlementList(migrationData.Security.SelectMany(s => s.ApplicationEntitlements).Where(e => e.ProductId == product.Id));
                PageEntitlementList pageEntitlements = new PageEntitlementList(migrationData.Security.SelectMany(s => s.PageEntitlements).Where(e => e.ProductId == product.Id));
                ControlEntitlementList controlEntitlements = new ControlEntitlementList(migrationData.Security.SelectMany(s => s.ControlEntitlements).Where(e => e.ProductId == product.Id));
                MetadataEntitlementList metadataEntitlements = new MetadataEntitlementList(migrationData.Security.SelectMany(s => s.MetadataEntitlements).Where(e => e.ProductId == product.Id));
                SecurityConfiguration securityConfiguration = new SecurityConfiguration(applicationEntitlements, pageEntitlements, controlEntitlements, metadataEntitlements);

                foreach (KeyValuePair<string, string> kvp in systemRoleMap)
                {
                    foreach (ApplicationEntitlement entitlement in applicationEntitlements.Where(e => e.RoleId == kvp.Key))
                    {
                        entitlement.RoleId = systemRoleMap[entitlement.RoleId];
                    }

                    foreach (PageEntitlement entitlement in pageEntitlements.Where(e => e.RoleId == kvp.Key))
                    {
                        entitlement.RoleId = systemRoleMap[entitlement.RoleId];
                    }

                    foreach (ControlEntitlement entitlement in controlEntitlements.Where(e => e.RoleId == kvp.Key))
                    {
                        entitlement.RoleId = systemRoleMap[entitlement.RoleId];
                    }

                    foreach (MetadataEntitlement entitlement in metadataEntitlements.Where(e => e.RoleId == kvp.Key))
                    {
                        entitlement.RoleId = systemRoleMap[entitlement.RoleId];
                    }

                    foreach (EmailWorkflowTransitionAction emailTransition in workflowConfiguration.Configuration.States.SelectMany(s => s.Transitions).SelectMany(t => t.TransitionActionList).OfType<EmailWorkflowTransitionAction>().Where(ewt => ewt.PdfRenderRole == kvp.Key))
                    {
                        emailTransition.PdfRenderRole = systemRoleMap[emailTransition.PdfRenderRole];
                    }
                }

                string mappedId;

                // Update control validators with new IDs
                IEnumerable<ControlRegexValidator> controlValidators = product.FormDefinition.Pages.AllControls.AllValidators();
                foreach (ControlRegexValidator validator in controlValidators)
                {
                    bool available = validatorMap.TryGetValue(validator.ValidatorId, out mappedId);
                    if (available)
                    {
                        validator.ValidatorId = mappedId;
                    }
                }

                // Update prebuilt option sources with new IDs
                List<ControlWithOptions> prebuiltOptionControls = product.FormDefinition.Pages.AllControls.FindAllRecursive<ControlWithOptions>(x => x.OptionSource.Type == OptionSourceType.Prebuilt);
                foreach (ControlWithOptions prebuiltOptionControl in prebuiltOptionControls)
                {
                    bool available = dataSetMap.TryGetValue(((PrebuiltOptionSource)prebuiltOptionControl.OptionSource).DataSetId, out mappedId);
                    if (available)
                    {
                        ((PrebuiltOptionSource)prebuiltOptionControl.OptionSource).DataSetId = mappedId;
                    }
                }

                // Update service endpoints with new IDs
                this.UpdateServiceEndpoints(product, dataSourceConfiguration, workflowConfiguration.Configuration, serviceEndpointMap);

                product.EditComment = importedMessage;
                ProductVariation productVariation = null;
                if (product.IsChildForm)
                {
                    productVariation = migrationData.ProductVariations.Exists(p => p.ProductId == product.Id)
                        ? migrationData.ProductVariations.First(p => p.ProductId == product.Id)
                        : new ProductVariation
                        {
                            AddedControls = new List<int>(),
                            EditedControls = new List<int>(),
                            RemovedControls = new List<int>()
                        };
                }

                Product savedProduct = this.manager.SaveProduct(sessionData, product, workflowConfiguration.Configuration, securityConfiguration, dataSourceConfiguration, productVariation);
                migrationResults.AddNotification(savedProduct, MessageType.Information, string.Format(Messages.Import_ProductSuccess, savedProduct.Name, savedProduct.Version));
            }
        }
        public string SaveProduct(string product, string workflow, string security, string dataSource, string productVariation)
        {
            try
            {
                SessionData sessionData = Global.VerifySession(this.Context.Request);
                ProductDefinition productObj = JsonConvert.DeserializeObject<ProductDefinition>(product);
                WorkflowConfiguration workflowConfiguration = JsonConvert.DeserializeObject<WorkflowConfiguration>(workflow);
                ProductDataSourceConfiguration dataSourceConfiguration = JsonConvert.DeserializeObject<ProductDataSourceConfiguration>(dataSource);
                ProductVariation productVariationObj = productObj.IsChildForm ? JsonConvert.DeserializeObject<ProductVariation>(productVariation) : null;
                SecurityConfigurationUpdates securityConfigurationUpdates = JsonConvert.DeserializeObject<SecurityConfigurationUpdates>(security);
                SecurityConfiguration securityConfiguration;
                if (!string.IsNullOrWhiteSpace(productObj.Id))
                {
                    securityConfiguration = this.workbenchManager.GetSecurityConfiguration(
                        productObj.Id,
                        productObj.Version);
                }
                else
                {
                    securityConfiguration = new SecurityConfiguration();
                }

                securityConfigurationUpdates.Apply(securityConfiguration);

                productObj = this.workbenchManager.SaveProduct(sessionData, productObj, workflowConfiguration, securityConfiguration, dataSourceConfiguration, productVariationObj);
                this.workbenchManager.SavePaperForm(sessionData, this.pdfWriter, productObj, this.Server.MapPath("~"));

                var result = new
                    {
                        productObj.Id,
                        productObj.Version,
                        productObj.BranchName,
                        productObj.WorkflowState
                    };
                return JsonConvert.SerializeObject(result);
            }
            catch (InvalidSessionException e)
            {
                JObject jobj = Context.HandleWebServiceException(e, true, HttpStatusCode.BadRequest, ExceptionMessages.SessionExpired);
                return JsonConvert.SerializeObject(jobj);
            }
            catch (SecurityException e)
            {
                JObject jobj = Context.HandleWebServiceException(e, false, HttpStatusCode.BadRequest, e.Message);
                return JsonConvert.SerializeObject(jobj);
            }
            catch (Exception e)
            {
                JObject jobj = Context.HandleWebServiceException(e);
                return JsonConvert.SerializeObject(jobj);
            }
        }
 /// <summary>
 /// Apply the application entitlements updates to the <paramref name="securityConfiguration"/> object.
 /// </summary>
 /// <param name="securityConfiguration">
 /// The security configuration to apply the changes on.
 /// </param>
 private void ApplyApplicationEntitlements(SecurityConfiguration securityConfiguration)
 {
     foreach (var applicationEntitlement in this.ApplicationEntitlements.Updated)
     {
         var existent = securityConfiguration.ApplicationEntitlements.FirstOrDefault(e => e.StateName == applicationEntitlement.StateName && e.RoleId == applicationEntitlement.RoleId);
         if (existent == null)
         {
             securityConfiguration.ApplicationEntitlements.Add(applicationEntitlement);
         }
         else
         {
             existent.AccessLevel = applicationEntitlement.AccessLevel;
             if (applicationEntitlement.AccessLevel == AccessLevel.NoAccess)
             {
                 securityConfiguration.PageEntitlements.RemoveAll(e => e.StateName == applicationEntitlement.StateName && e.RoleId == applicationEntitlement.RoleId);
                 securityConfiguration.ControlEntitlements.RemoveAll(e => e.StateName == applicationEntitlement.StateName && e.RoleId == applicationEntitlement.RoleId);
                 securityConfiguration.MetadataEntitlements.RemoveAll(e => e.StateName == applicationEntitlement.StateName && e.RoleId == applicationEntitlement.RoleId);
             }
         }
     }
 }
        /// <summary>
        /// Apply the state updates to the <paramref name="securityConfiguration"/> object.
        /// </summary>
        /// <param name="securityConfiguration">
        /// The security configuration to apply the changes on.
        /// </param>
        private void ApplyStateUpdates(SecurityConfiguration securityConfiguration)
        {
            foreach (var update in this.StateUpdates)
            {
                if (update.UpdateType == WorkflowStateUpdateType.Remove)
                {
                    securityConfiguration.ApplicationEntitlements.RemoveAll(e => e.StateName == update.StateName);
                    securityConfiguration.PageEntitlements.RemoveAll(e => e.StateName == update.StateName);
                    securityConfiguration.ControlEntitlements.RemoveAll(e => e.StateName == update.StateName);
                    securityConfiguration.MetadataEntitlements.RemoveAll(e => e.StateName == update.StateName);
                }
                else
                {
                    foreach (var entitlement in securityConfiguration.ApplicationEntitlements.Where(entitlement => entitlement.StateName.Equals(update.StateName)))
                    {
                        entitlement.StateName = update.NewStateName;
                    }

                    foreach (var entitlement in securityConfiguration.PageEntitlements.Where(entitlement => entitlement.StateName.Equals(update.StateName)))
                    {
                        entitlement.StateName = update.NewStateName;
                    }

                    foreach (var entitlement in securityConfiguration.ControlEntitlements.Where(entitlement => entitlement.StateName.Equals(update.StateName)))
                    {
                        entitlement.StateName = update.NewStateName;
                    }

                    foreach (var entitlement in securityConfiguration.MetadataEntitlements.Where(entitlement => entitlement.StateName.Equals(update.StateName)))
                    {
                        entitlement.StateName = update.NewStateName;
                    }
                }
            }
        }
        /// <summary>
        /// Apply the page entitlements updates to the <paramref name="securityConfiguration"/> object.
        /// </summary>
        /// <param name="securityConfiguration">
        /// The security configuration to apply the changes on.
        /// </param>
        private void ApplyPageEntitlements(SecurityConfiguration securityConfiguration)
        {
            foreach (var pageEntitlement in this.PageEntitlements.Updated)
            {
                var existent = securityConfiguration.PageEntitlements.FirstOrDefault(e => e.StateName == pageEntitlement.StateName && e.RoleId == pageEntitlement.RoleId && e.PageId == pageEntitlement.PageId);
                if (existent == null)
                {
                    securityConfiguration.PageEntitlements.Add(pageEntitlement);
                }
                else
                {
                    existent.AccessLevel = pageEntitlement.AccessLevel;
                }
            }

            foreach (var pageEntitlement in this.PageEntitlements.Removed)
            {
                if (pageEntitlement.StateName == null && pageEntitlement.RoleId == null)
                {
                    securityConfiguration.PageEntitlements.RemoveAll(e => e.PageId == pageEntitlement.PageId);
                }
                else
                {
                    var existent = securityConfiguration.PageEntitlements.FirstOrDefault(e => e.StateName == pageEntitlement.StateName && e.RoleId == pageEntitlement.RoleId && e.PageId == pageEntitlement.PageId);
                    if (existent == null)
                    {
                        continue;
                    }

                    securityConfiguration.PageEntitlements.Remove(existent);
                }
            }
        }
        /// <summary>
        /// Apply the metadata entitlements updates to the <paramref name="securityConfiguration"/> object.
        /// </summary>
        /// <param name="securityConfiguration">
        /// The security configuration to apply the changes on.
        /// </param>
        private void ApplyMetadataEntitlements(SecurityConfiguration securityConfiguration)
        {
            foreach (var metadataEntitlement in this.MetadataEntitlements.Updated)
            {
                var existent = securityConfiguration.MetadataEntitlements.FirstOrDefault(e => e.StateName == metadataEntitlement.StateName && e.RoleId == metadataEntitlement.RoleId && e.ControlName == metadataEntitlement.ControlName);
                if (existent == null)
                {
                    securityConfiguration.MetadataEntitlements.Add(metadataEntitlement);
                }
                else
                {
                    existent.AccessLevel = metadataEntitlement.AccessLevel;
                }
            }

            foreach (var metadataEntitlement in this.MetadataEntitlements.Removed)
            {
                var existent = securityConfiguration.MetadataEntitlements.FirstOrDefault(e => e.StateName == metadataEntitlement.StateName && e.RoleId == metadataEntitlement.RoleId && e.ControlName == metadataEntitlement.ControlName);
                if (existent == null)
                {
                    continue;
                }

                securityConfiguration.MetadataEntitlements.Remove(existent);
            }
        }