public IFlowUiDefinition GetCurrentUiDefinition(FlowToken flowToken)
        {
            WorkflowFlowToken workflowFlowToken = (WorkflowFlowToken)flowToken;

            if (!WorkflowFacade.WorkflowExists(workflowFlowToken.WorkflowInstanceId))
            {
                Log.LogVerbose(LogTitle, "The workflow with Id = {0} does not exists", workflowFlowToken.WorkflowInstanceId);
                return(null);
            }


            using (GlobalInitializerFacade.CoreNotLockedScope)
            {
                Semaphore semaphore = WorkflowFacade.WaitForIdleStatus(workflowFlowToken.WorkflowInstanceId);
                if (semaphore != null)
                {
                    Log.LogVerbose(LogTitle, "The workflow with Id = {0} is running, waiting until its done.", workflowFlowToken.WorkflowInstanceId);

                    semaphore.WaitOne(TimeSpan.FromSeconds(10), true);

                    Log.LogVerbose(LogTitle, "Done waiting on the workflow with Id = {0}.", workflowFlowToken.WorkflowInstanceId);
                }
            }


            FormData formFunction = WorkflowFacade.GetFormData(workflowFlowToken.WorkflowInstanceId);

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

            FormFlowUiDefinition formFlowUiDefinition;

            if (formFunction.FormDefinition != null)
            {
                formFlowUiDefinition = new FormFlowUiDefinition(
                    ToXmlReader(formFunction.FormDefinition),
                    formFunction.ContainerType,
                    formFunction.ContainerLabel,
                    formFunction.Bindings,
                    formFunction.BindingsValidationRules
                    );
            }
            else if (formFunction.FormMarkupProvider != null)
            {
                formFlowUiDefinition = new FormFlowUiDefinition(
                    formFunction.FormMarkupProvider,
                    formFunction.ContainerType,
                    formFunction.ContainerLabel,
                    formFunction.Bindings,
                    formFunction.BindingsValidationRules
                    );
            }
            else
            {
                throw new NotImplementedException();
            }

            var markup = GetCustomToolbarMarkup(formFunction);

            if (markup != null)
            {
                formFlowUiDefinition.SetCustomToolbarMarkupProvider(markup);
            }

            AddEventHandles(formFlowUiDefinition, workflowFlowToken.WorkflowInstanceId);

            return(formFlowUiDefinition);
        }
        public static IUiControl Render(
            string consoleId,
            string elementProviderName,
            FlowToken flowToken,
            FormFlowUiDefinition formFlowUiCommand,
            IFormChannelIdentifier channel,
            bool debugMode,
            FlowControllerServicesContainer servicesContainer)
        {
            FlowControllerServicesContainer formServicesContainer = new FlowControllerServicesContainer(servicesContainer);

            formServicesContainer.AddService(new FormFlowRenderingService());
            formServicesContainer.AddService(new FormFlowWebRenderingService());

            IFormMarkupProvider         formMarkupProvider = formFlowUiCommand.MarkupProvider;
            IFormMarkupProvider         customToolbarItemsMarkupProvider = formFlowUiCommand.CustomToolbarItemsMarkupProvider;
            Dictionary <string, object> innerFormBindings = formFlowUiCommand.BindingsProvider.GetBindings();
            Dictionary <IFormEventIdentifier, FormFlowEventHandler> eventHandlers           = formFlowUiCommand.EventHandlers;
            Dictionary <string, List <ClientValidationRule> >       bindingsValidationRules = formFlowUiCommand.BindingsValidationRules;

            FormTreeCompiler formCompiler       = new FormTreeCompiler();
            IUiContainer     renderingContainer = GetRenderingContainer(channel, formFlowUiCommand.UiContainerType);

            // Setting state related objects so the delegate below can access them "fresh"
            CurrentFormTreeCompiler  = formCompiler;
            CurrentInnerFormBindings = innerFormBindings;
            CurrentControlContainer  = (IWebUiContainer)renderingContainer;


            Dictionary <string, object> containerEventHandlerStubs = new Dictionary <string, object>();

            foreach (IFormEventIdentifier eventIdentifier in eventHandlers.Keys)
            {
                IFormEventIdentifier localScopeEventIdentifier = eventIdentifier;  // See: Local variable usage with anonymous methods within loop control structures

                EventHandler handlerStub = delegate(object sender, EventArgs e)
                {
                    try
                    {
                        BaseEventHandler(consoleId, elementProviderName, flowToken, formFlowUiCommand, servicesContainer, eventHandlers, localScopeEventIdentifier, formServicesContainer);
                    }
                    catch (Exception ex)
                    {
                        formServicesContainer.GetService <IManagementConsoleMessageService>().ShowLogEntry(typeof(FormFlowUiDefinitionRenderer), ex);
                        throw;
                    }
                };

                containerEventHandlerStubs.Add(eventIdentifier.BindingName, handlerStub);

                if (innerFormBindings.ContainsKey(eventIdentifier.BindingName))
                {
                    innerFormBindings.Remove(eventIdentifier.BindingName);
                }

                innerFormBindings.Add(eventIdentifier.BindingName, handlerStub);
            }

            XDocument document;

            using (XmlReader formMarkupReader = formMarkupProvider.GetReader())
            {
                document = XDocument.Load(formMarkupReader);
                formMarkupReader.Close();
            }

            formCompiler.Compile(document, channel, innerFormBindings, debugMode, "", bindingsValidationRules);

            IUiControl innerForm = formCompiler.UiControl;

            IUiControl customToolbarItems = null;

            if (customToolbarItemsMarkupProvider != null)
            {
                var toolbarCompiler = new FormTreeCompiler();
                CurrentCustomToolbarFormTreeCompiler = toolbarCompiler;

                using (XmlReader formMarkupReader = customToolbarItemsMarkupProvider.GetReader())
                {
                    toolbarCompiler.Compile(formMarkupReader, channel, innerFormBindings, debugMode, bindingsValidationRules);
                }
                customToolbarItems = toolbarCompiler.UiControl;
            }

            CurrentControlTreeRoot = (IWebUiControl)innerForm;

            string label = formCompiler.Label;

            if (label.IsNullOrEmpty())
            {
                label = formFlowUiCommand.ContainerLabel ?? "";
            }

            string         labelField    = GetFormLabelField(document);
            ResourceHandle containerIcon = formCompiler.Icon;

            return(renderingContainer.Render(formCompiler.UiControl, customToolbarItems, channel, containerEventHandlerStubs, label, labelField, formCompiler.Tooltip, containerIcon));
        }
        private static void AddEventHandles(FormFlowUiDefinition formFlowUiDefinition, Guid instanceId)
        {
            IEnumerable <string> eventNames = WorkflowFacade.GetCurrentFormEvents(instanceId);

            FormData formData = WorkflowFacade.GetFormData(instanceId);

            foreach (string eventName in eventNames)
            {
                if (formData?.ExcludedEvents != null && formData.ExcludedEvents.Contains(eventName))
                {
                    continue;
                }

                switch (eventName)
                {
                case "Save":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Save, OnSave);
                    break;

                case "SaveAndPublish":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.SaveAndPublish, OnSaveAndPublish);
                    break;

                case "Next":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Next, OnNext);
                    break;

                case "Previous":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Previous, OnPrevious);
                    break;

                case "Finish":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Finish, OnFinish);
                    break;

                case "Cancel":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Cancel, OnCancel);
                    break;

                case "Preview":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.Preview, OnPreview);
                    break;

                case "CustomEvent01":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.CustomEvent01, OnCustomEvent01);
                    break;

                case "CustomEvent02":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.CustomEvent02, OnCustomEvent02);
                    break;

                case "CustomEvent03":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.CustomEvent03, OnCustomEvent03);
                    break;

                case "CustomEvent04":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.CustomEvent04, OnCustomEvent04);
                    break;

                case "CustomEvent05":
                    formFlowUiDefinition.EventHandlers.Add(StandardEventIdentifiers.CustomEvent05, OnCustomEvent05);
                    break;
                }
            }

            IEventHandleFilter eventHandlerFilter = WorkflowFacade.GetEventHandleFilter(instanceId);

            eventHandlerFilter?.Filter(formFlowUiDefinition.EventHandlers);
        }
        private static void BaseEventHandler(string consoleId,
                                             string elementProviderName,
                                             FlowToken flowToken,
                                             FormFlowUiDefinition formFlowUiCommand,
                                             FlowControllerServicesContainer servicesContainer,
                                             Dictionary <IFormEventIdentifier, FormFlowEventHandler> eventHandlers,
                                             IFormEventIdentifier localScopeEventIdentifier,
                                             FlowControllerServicesContainer formServicesContainer)
        {
            FormTreeCompiler            activeFormTreeCompiler  = CurrentFormTreeCompiler;
            Dictionary <string, object> activeInnerFormBindings = CurrentInnerFormBindings;

            FormFlowEventHandler           handler       = eventHandlers[localScopeEventIdentifier];
            Dictionary <string, Exception> bindingErrors = activeFormTreeCompiler.SaveAndValidateControlProperties();

            FormTreeCompiler activeCustomToolbarFormTreeCompiler = CurrentCustomToolbarFormTreeCompiler;

            if (activeCustomToolbarFormTreeCompiler != null)
            {
                var toolbarBindingErrors = activeCustomToolbarFormTreeCompiler.SaveAndValidateControlProperties();
                foreach (var pair in toolbarBindingErrors)
                {
                    bindingErrors.Add(pair.Key, pair.Value);
                }
            }

            formServicesContainer.AddService(new BindingValidationService(bindingErrors));

            handler.Invoke(flowToken, activeInnerFormBindings, formServicesContainer);

            if (formServicesContainer.GetService <IManagementConsoleMessageService>().CloseCurrentViewRequested)
            {
                ViewTransitionHelper.HandleCloseCurrentView(formFlowUiCommand.UiContainerType);
                return;
            }

            var  formFlowService   = formServicesContainer.GetService <IFormFlowRenderingService>();
            bool replacePageOutput = (formServicesContainer.GetService <IFormFlowWebRenderingService>().NewPageOutput != null);

            bool rerenderView = formFlowService.RerenderViewRequested;

            if (formFlowService.BindingPathedMessages != null)
            {
                ShowFieldMessages(CurrentControlTreeRoot, formFlowService.BindingPathedMessages, CurrentControlContainer,
                                  servicesContainer);
            }

            List <bool> boolCounterList = new List <bool> {
                replacePageOutput, rerenderView
            };

            if (boolCounterList.Count(f => f) > 1)
            {
                StringBuilder sb = new StringBuilder("Flow returned conflicting directives for post handling:\n");
                if (replacePageOutput)
                {
                    sb.AppendLine(" - Replace page output with new web control.");
                }
                if (rerenderView)
                {
                    sb.AppendLine(" - Rerender view.");
                }

                throw new InvalidOperationException(sb.ToString());
            }

            if (rerenderView)
            {
                Log.LogVerbose("FormFlowRendering", "Re-render requested");
                IFlowUiDefinition newFlowUiDefinition = FlowControllerFacade.GetCurrentUiDefinition(flowToken,
                                                                                                    servicesContainer);
                if (!(newFlowUiDefinition is FlowUiDefinitionBase))
                {
                    throw new NotImplementedException("Unable to handle transitions to ui definition of type " +
                                                      newFlowUiDefinition.GetType());
                }
                ViewTransitionHelper.HandleRerender(consoleId, elementProviderName, flowToken, formFlowUiCommand,
                                                    (FlowUiDefinitionBase)newFlowUiDefinition, servicesContainer);
            }

            if (replacePageOutput)
            {
                Log.LogVerbose("FormFlowRendering", "Replace pageoutput requested");
                IFormFlowWebRenderingService webRenderingService =
                    formServicesContainer.GetService <IFormFlowWebRenderingService>();
                Control newPageOutput = webRenderingService.NewPageOutput;

                foreach (Control control in GetNestedControls(newPageOutput).Where(f => f is ScriptManager).ToList())
                {
                    control.Parent.Controls.Remove(control);
                }

                Page currentPage = HttpContext.Current.Handler as Page;

                HtmlHead newHeadControl = GetNestedControls(newPageOutput).FirstOrDefault(f => f is HtmlHead) as HtmlHead;

                HtmlHead oldHeadControl = currentPage.Header;

                ControlCollection headContainer = null;
                bool headersHasToBeSwitched     = newHeadControl != null && oldHeadControl != null;
                if (headersHasToBeSwitched)
                {
                    headContainer = newHeadControl.Parent.Controls;
                    headContainer.Remove(newHeadControl);
                }

                currentPage.Controls.Clear();
                if (string.IsNullOrEmpty(webRenderingService.NewPageMimeType))
                {
                    currentPage.Response.ContentType = "text/html";
                }
                else
                {
                    currentPage.Response.ContentType = webRenderingService.NewPageMimeType;
                }
                currentPage.Controls.Add(newPageOutput);

                if (headersHasToBeSwitched)
                {
                    oldHeadControl.Controls.Clear();
                    oldHeadControl.InnerHtml = "";
                    oldHeadControl.InnerText = "";
                    if (newHeadControl.ID != null)
                    {
                        oldHeadControl.ID = newHeadControl.ID;
                    }
                    oldHeadControl.Title = newHeadControl.Title;

                    headContainer.AddAt(0, oldHeadControl);

                    foreach (Control c in newHeadControl.Controls.Cast <Control>().ToList())
                    {
                        oldHeadControl.Controls.Add(c);
                    }
                }
            }
        }