/// <summary>
        /// Pushes the <see cref="TargetState"/> onto the workflow navigation context stack.
        /// </summary>
        public override void Execute()
        {
            IWorkflowManager        workflowManager = ServiceRegistration.Get <IWorkflowManager>();
            NavigationContextConfig config          = new NavigationContextConfig {
                NavigationContextDisplayLabel = _displayLabel,
                AdditionalContextVariables    = _workflowNavigationContextVariables
            };

            workflowManager.NavigatePushTransient(_transientState, config);
        }
    private void ShowSingleChannelGuide(IChannel channel)
    {
      if (channel == null || CurrentChannelGroup == null)
        return;

      int channelId = channel.ChannelId;
      int groupId = CurrentChannelGroup.ChannelGroupId;
      IWorkflowManager workflowManager = ServiceRegistration.Get<IWorkflowManager>();
      NavigationContextConfig navigationContextConfig = new NavigationContextConfig();
      navigationContextConfig.AdditionalContextVariables = new Dictionary<string, object>();
      navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_CHANNEL_ID] = channelId;
      navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_GROUP_ID] = groupId;
      Guid stateId = new Guid("A40F05BB-022E-4247-8BEE-16EB3E0B39C5");
      if (workflowManager.IsAnyStateContainedInNavigationStack(new Guid[] { stateId }))
        workflowManager.NavigatePopToState(stateId, false);
      else
        workflowManager.NavigatePush(stateId, navigationContextConfig);
    }
예제 #3
0
 // Maybe called asynchronously.
 protected void NavigatePushInternal(Guid stateId, NavigationContextConfig config)
 {
   EnterWriteLock("NavigatePush");
   try
   {
     WorkflowState state;
     if (!_states.TryGetValue(stateId, out state))
       throw new ArgumentException(string.Format("WorkflowManager: Workflow state '{0}' is not available", stateId));
     try
     {
       if (DoPushNavigationContext(state, config))
         UpdateScreen_NeedsLock(true, true);
       WorkflowManagerMessaging.SendNavigationCompleteMessage();
     }
     catch (Exception e)
     {
       ServiceRegistration.Get<ILogger>().Error("WorkflowManager.NavigatePushInternal: Error in workflow model or screen", e);
       NavigatePopInternal(1);
     }
   }
   finally
   {
     ExitWriteLock();
   }
 }
예제 #4
0
 // Maybe called asynchronously.
 protected void NavigatePushTransientInternal(WorkflowState state, NavigationContextConfig config)
 {
   EnterWriteLock("NavigatePushTransient");
   try
   {
     try
     {
       if (DoPushNavigationContext(state, config))
         UpdateScreen_NeedsLock(true, true);
       WorkflowManagerMessaging.SendNavigationCompleteMessage();
     }
     catch (Exception e)
     {
       ServiceRegistration.Get<ILogger>().Error("WorkflowManager.NavigatePushTransientInternal: Error in workflow model or screen", e);
       NavigatePopInternal(1);
     }
   }
   finally
   {
     ExitWriteLock();
   }
 }
예제 #5
0
 public void NavigatePushTransientAsync(WorkflowState state, NavigationContextConfig config)
 {
   IThreadPool threadPool = ServiceRegistration.Get<IThreadPool>();
   threadPool.Add(() => NavigatePushTransientInternal(state, config));
 }
예제 #6
0
    /// <summary>
    /// Synchronous method which pushes the given workflow <paramref name="state"/> onto the navigation stack.
    /// </summary>
    /// <remarks>
    /// This method rethrows all exceptions which are thrown by workflow models. In case an exception is thrown,
    /// the internal state is still valid but the caller must pop the current navigation context from the workflow stack.
    /// </remarks>
    /// <param name="state">Workflow state to push.</param>
    /// <param name="config">Additional navigation context configuration.</param>
    /// <returns><c>true</c> if the push action was successful, else <c>false</c>.</returns>
    protected bool DoPushNavigationContext(WorkflowState state, NavigationContextConfig config)
    {
      if (config == null)
        config = EMPTY_NAVIGATION_CONTEXT_CONFIG;
      EnterWriteLock("DoPushNavigationContext");
      try
      {
        ILogger logger = ServiceRegistration.Get<ILogger>();
        NavigationContext current = CurrentNavigationContext;

        if (current != null && current.WorkflowState.IsTemporary && state.WorkflowType == WorkflowType.Workflow)
        {
          logger.Info("Current workflow state '{0}' is temporary, popping it from navigation stack", current.WorkflowState.Name);
          // The next statement can throw an exception - don't catch it - our caller should pop the current navigation context
          bool workflowStatePopped;
          DoPopNavigationContext(1, out workflowStatePopped);
        }

        NavigationContext predecessor = CurrentNavigationContext;
        logger.Info("WorkflowManager: Pushing workflow state '{0}' (id='{1}') onto the navigation stack...", state.Name, state.StateId);

        // Find non-transient state. If new state is transient, search for last non-transient state on stack.
        WorkflowState nonTransientState = state.IsTransient ? FindLastNonTransientState() : state;
        if (nonTransientState == null)
        {
          logger.Error("WorkflowManager: No non-transient state found on workflow context stack to be used as reference state. Workflow state to be pushed is '{0}' (id: '{1}')",
              state.Name, state.StateId);
          return false;
        }

        // Initialize workflow model
        Guid? workflowModelId = nonTransientState.WorkflowModelId;
        IWorkflowModel workflowModel = null;
        if (workflowModelId.HasValue)
        {
          object model = GetOrLoadModel(workflowModelId.Value);
          if (model is IWorkflowModel)
          {
            logger.Debug("WorkflowManager: Using workflow model with id '{0}' for new workflow state '{1}'",
                workflowModelId.Value, state.StateId);
            workflowModel = (IWorkflowModel) model;
          }
          else
            logger.Error("WorkflowManager: Model with id '{0}', which is used as workflow model in state '{1}', doesn't implement the interface '{2}'",
                workflowModelId.Value, state.StateId, typeof(IWorkflowModel).Name);
        }

        // Create new workflow context
        NavigationContext newContext = new NavigationContext(state, config.NavigationContextDisplayLabel, predecessor, workflowModel);
        if (config.AdditionalContextVariables != null)
          lock (newContext.SyncRoot)
            CollectionUtils.AddAll(newContext.ContextVariables, config.AdditionalContextVariables);

        // Check if state change is accepted
        bool canEnter = true;
        if (workflowModel != null)
          try
          {
            canEnter = workflowModel.CanEnterState(predecessor, newContext);
          }
          catch (Exception e)
          {
            logger.Error("WorkflowManager: Error checking if workflow model '{0}' can enter workflow state '{1}'", e,
              workflowModel.ModelId, newContext.WorkflowState.StateId);
            canEnter = false;
          }
        if (!canEnter)
        {
          logger.Debug("WorkflowManager: Workflow model with id '{0}' doesn't accept the state being pushed onto the workflow context stack. Reverting to old workflow state.", workflowModelId);
          return false;
        }

        // Store model exceptions
        IList<Exception> delayedExceptions = new List<Exception>();

        // Push new context
        logger.Debug("WorkflowManager: Entering workflow state '{0}'", state.Name);
        _navigationContextStack.Push(newContext);

        Guid? predecessorModelId = predecessor == null ? null : predecessor.WorkflowModelId;

        // Communicate context change to models
        bool modelChange = workflowModelId != predecessorModelId;

        // - Handle predecessor workflow model
        IWorkflowModel predecessorWorkflowModel = predecessorModelId.HasValue ?
            GetOrLoadModel(predecessorModelId.Value) as IWorkflowModel : null;
        if (predecessorWorkflowModel != null)
          if (modelChange)
          {
            logger.Debug("WorkflowManager: Deactivating predecessor workflow model '{0}'", predecessorModelId.Value);
            try
            {
              predecessorWorkflowModel.Deactivate(predecessor, newContext);
            }
            catch (Exception e)
            {
              logger.Error("WorkflowManager: Error deactivating workflow model '{0}'", e, predecessorWorkflowModel.ModelId);
              delayedExceptions.Add(e);
            }
          }
        // else: same model is currently active - model context change will be handled in the next block

        // - Handle new workflow model
        if (workflowModel != null)
          if (modelChange)
          {
            if (predecessor == null)
              logger.Debug("WorkflowManager: Starting first model context with workflow state '{0}' in workflow model '{1}'",
                  newContext.WorkflowState.StateId, workflowModelId.Value);
            else
              logger.Debug("WorkflowManager: Entering model context with workflow state '{0}' (old state was '{1}') in new workflow model '{2}'",
                  newContext.WorkflowState.StateId, predecessor.WorkflowState.StateId, workflowModelId.Value);
            try
            {
              workflowModel.EnterModelContext(predecessor, newContext);
            }
            catch (Exception e)
            {
              logger.Error("WorkflowManager: Error entering model context of workflow model '{0}' for workflow state '{1}'", e,
                  workflowModel.ModelId, newContext.WorkflowState.StateId);
              delayedExceptions.Add(e);
            }
          }
          else
          {
            logger.Debug("WorkflowManager: Changing model context to workflow state '{0}' (old state was '{1}') in workflow model '{2}'",
                newContext.WorkflowState.StateId, predecessor == null ? null : predecessor.WorkflowState.StateId.ToString(), workflowModelId.Value);
            try
            {
              workflowModel.ChangeModelContext(predecessor, newContext, true);
            }
            catch (Exception e)
            {
              logger.Error("WorkflowManager: Error changing model context of workflow model '{0}' from workflow state '{1}' to workflow state '{2}'",
                e, workflowModel.ModelId, predecessor.WorkflowState.StateId, newContext.WorkflowState.StateId);
              delayedExceptions.Add(e);
            }
          }
        if (state.WorkflowType == WorkflowType.Workflow)
        {
          // Compile menu actions
          logger.Debug("WorkflowManager: Compiling menu actions for workflow state '{0}'", state.Name);
          IDictionary<Guid, WorkflowAction> menuActions = new Dictionary<Guid, WorkflowAction>();
          foreach (WorkflowAction action in FilterActionsBySourceState(state.StateId, _menuActions.Values))
            menuActions.Add(action.ActionId, action);
          if (workflowModel != null)
            try
            {
              workflowModel.UpdateMenuActions(newContext, menuActions);
            }
            catch (Exception e)
            {
              logger.Error("WorkflowManager: Error updating menu actions in workflow model '{0}' for workflow state '{1}'", e,
                  workflowModel.ModelId, newContext.WorkflowState.StateId);
              delayedExceptions.Add(e);
            }
          newContext.SetMenuActions(menuActions.Values);
        }
        if (delayedExceptions.Count > 0)
          throw delayedExceptions.First();
        WorkflowManagerMessaging.SendStatePushedMessage(newContext);
        return true;
      }
      finally
      {
        ExitWriteLock();
        IterateCache_NoLock();
      }
    }
예제 #7
0
 public void NavigatePushAsync(Guid stateId, NavigationContextConfig config)
 {
   IThreadPool threadPool = ServiceRegistration.Get<IThreadPool>();
   threadPool.Add(() => NavigatePushInternal(stateId, config));
 }
예제 #8
0
 public void NavigatePushTransient(WorkflowState state, NavigationContextConfig config)
 {
   NavigatePushTransientInternal(state, config);
 }
예제 #9
0
 public void NavigatePush(Guid stateId, NavigationContextConfig config)
 {
   NavigatePushInternal(stateId, config);
 }
 /// <summary>
 /// Pushes the <see cref="TargetState"/> onto the workflow navigation context stack.
 /// </summary>
 public override void Execute()
 {
   IWorkflowManager workflowManager = ServiceRegistration.Get<IWorkflowManager>();
   NavigationContextConfig config = new NavigationContextConfig {
     NavigationContextDisplayLabel = _displayLabel,
     AdditionalContextVariables = _workflowNavigationContextVariables
   };
   workflowManager.NavigatePushTransient(_transientState, config);
 }
 private static void Show(NavigationContextConfig context)
 {
   IWorkflowManager workflowManager = ServiceRegistration.Get<IWorkflowManager>();
   Guid stateId = new Guid("3C6081CB-88DC-44A7-9E17-8D7BFE006EE5");
   if (workflowManager.IsAnyStateContainedInNavigationStack(new Guid[] { stateId }))
     workflowManager.NavigatePopToState(stateId, false);
   else
     workflowManager.NavigatePush(stateId, context);
 }
 public static void Show(IProgram program)
 {
   NavigationContextConfig navigationContextConfig = new NavigationContextConfig();
   navigationContextConfig.AdditionalContextVariables = new Dictionary<string, object>();
   navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_PROGRAM] = program;
   navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_MODE] = false;
   Show(navigationContextConfig);
 }
 public static void Show(ISchedule schedule)
 {
   NavigationContextConfig navigationContextConfig = new NavigationContextConfig();
   navigationContextConfig.AdditionalContextVariables = new Dictionary<string, object>();
   navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_SCHEDULE] = schedule;
   navigationContextConfig.AdditionalContextVariables[SlimTvClientModel.KEY_MODE] = true;
   Show(navigationContextConfig);
 }