/// <summary>
 /// This method can start, stop, resume or pause a group of components of the specified type.
 /// </summary>
 /// <param name="action">The action required</param>
 /// <param name="components">The components to which the action should be provided</param>
 /// <param name="componentType">The component type.</param>
 public virtual void ComponentsStatusChange(XimuraServiceStatusAction action,
     ICollection components, Type componentType)
 {
     ComponentsStatusChange(action, components, componentType, mNotifyAfter, mNotifyBefore);
 }
        /// <summary>
        /// This method can start, stop, resume or pause a group of components of the specified type.
        /// </summary>
        /// <param name="action">The action required</param>
        /// <param name="components">The components to which the action should be provided</param>
        /// <param name="componentType">The component type.</param>
        public virtual void ComponentsStatusChange(XimuraServiceStatusAction action,
            ICollection components, Type componentType,
            ComponentStatusChangeNotify NotifyAfter, ComponentStatusChangeNotify NotifyBefore)
        {
            if (components == null)
                return;

            bool donotNotifyBefore = NotifyBefore == null;
            bool doNotifyAfter = NotifyAfter != null;

            foreach (object objService in components)
            {
                IXimuraService service = objService as IXimuraService;
                if (service != null &&
                    (componentType == null || (componentType.IsInstanceOfType(service))))
                {
                    try
                    {
                        switch (action)
                        {
                            case XimuraServiceStatusAction.Start:
                                if (service.ServiceStatus == XimuraServiceStatus.Stopped ||
                                    service.ServiceStatus == XimuraServiceStatus.NotStarted)
                                {
                                    if (donotNotifyBefore || NotifyBefore(action, service))
                                    {
                                        service.Start();
                                        if (doNotifyAfter) NotifyAfter(action, service);
                                    }
                                }
                                break;
                            case XimuraServiceStatusAction.Stop:
                                if (service.ServiceStatus != XimuraServiceStatus.Stopped ||
                                    service.ServiceStatus != XimuraServiceStatus.Stopping ||
                                    service.ServiceStatus != XimuraServiceStatus.NotStarted ||
                                    service.ServiceStatus != XimuraServiceStatus.Undefined)
                                {
                                    if (donotNotifyBefore || NotifyBefore(action, service))
                                    {
                                        service.Stop();
                                        if (doNotifyAfter) NotifyAfter(action, service);
                                    }
                                }
                                break;
                            case XimuraServiceStatusAction.Pause:
                                if (service.ServiceStatus == XimuraServiceStatus.Started)
                                {
                                    if (donotNotifyBefore || NotifyBefore(action, service))
                                    {
                                        service.Pause();
                                        if (doNotifyAfter) NotifyAfter(action, service);
                                    }
                                }
                                break;
                            case XimuraServiceStatusAction.Continue:
                                if (service.ServiceStatus == XimuraServiceStatus.Paused)
                                    if (service.ServiceStatus == XimuraServiceStatus.Started)
                                    {
                                        if (donotNotifyBefore || NotifyBefore(action, service))
                                        {
                                            service.Continue();
                                            if (doNotifyAfter) NotifyAfter(action, service);
                                        }
                                    }
                                break;
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("ComponentsStatusChange -> " + action.ToString() +
                            " -> " + ex.Message, "Start error.");
                        throw ex;
                    }
                }
            }
        }
        /// <summary>
        /// This overriden method checks on start whether the command has a priority set, 
        /// if it does has a priority set, the command is not started.
        /// </summary>
        /// <param name="action">The service action.</param>
        /// <param name="service">The service.</param>
        /// <returns>Returns true if the service can start.</returns>
        protected override bool ComponentsStatusBeforeChange(XimuraServiceStatusAction action, IXimuraService service)
        {
            //We only want to start commands that do not have a priority.
            if (action == XimuraServiceStatusAction.Start &&
                CommandExtender.CommandHasPriority(service))
                return false;

            return base.ComponentsStatusBeforeChange(action, service);
        }
		/// <summary>
		/// This method is called after the status of the service has been changed.
		/// </summary>
		/// <param name="action">The action, i.e. start, stop, etc.</param>
		/// <param name="service">The component service to change.</param>
		protected virtual void ComponentsStatusAfterChange(
			XimuraServiceStatusAction action,IXimuraService service)
		{

		}
		/// <summary>
		/// This method is called before the status of a component is changed. You may override 
		/// this method to make additional checks before the component status is changed.
		/// </summary>
		/// <param name="action">The action, i.e. start, stop, etc.</param>
		/// <param name="service">The component service to change.</param>
		/// <returns>This method should return true if you want the status to change. 
		/// If this method returns false the status of the service will not change.</returns>
		protected virtual bool ComponentsStatusBeforeChange(
			XimuraServiceStatusAction action,IXimuraService service)
		{
			return true;
		}
		/// <summary>
		/// This method can start, stop, resume or pause a group of components of the specified type.
		/// </summary>
		/// <param name="action">The action required</param>
		/// <param name="components">The components to which the action should be provided</param>
		/// <param name="componentType">The component type.</param>
		protected virtual void ComponentsStatusChange(XimuraServiceStatusAction action, 
			ICollection components, Type componentType)
		{
			if (components == null)
				return;

			foreach(object objService in components)
			{
				IXimuraService service = objService as IXimuraService;
				if (service != null && 
					(componentType==null || (componentType.IsInstanceOfType(service))))
				{
					try
					{
						switch (action)
						{
							case XimuraServiceStatusAction.Start:
								if (service.ServiceEnabled && 
                                    (service.ServiceStatus == XimuraServiceStatus.Stopped ||
									service.ServiceStatus == XimuraServiceStatus.NotStarted))
								{
									if (ComponentsStatusBeforeChange(action, service))
									{
                                        if (service is IXimuraServiceParentSettings)
                                            ServiceParentSettingsSet((IXimuraServiceParentSettings)service);
										service.Start();
										ComponentsStatusAfterChange(action, service);
									}
								}
								break;
							case XimuraServiceStatusAction.Stop:
								if (service.ServiceStatus != XimuraServiceStatus.Stopped ||
									service.ServiceStatus != XimuraServiceStatus.Stopping ||
									service.ServiceStatus != XimuraServiceStatus.NotStarted ||
									service.ServiceStatus != XimuraServiceStatus.Undefined)
								{
									if (ComponentsStatusBeforeChange(action, service))
									{
										service.Stop();
										ComponentsStatusAfterChange(action, service);
									}				
								}
								break;
							case XimuraServiceStatusAction.Pause:
								if (service.ServiceStatus == XimuraServiceStatus.Started)
								{
									if (ComponentsStatusBeforeChange(action, service))
									{
										service.Pause();
										ComponentsStatusAfterChange(action, service);
									}				
								}								
								break;
							case XimuraServiceStatusAction.Continue:
								if (service.ServiceStatus == XimuraServiceStatus.Paused)
									if (service.ServiceStatus == XimuraServiceStatus.Started)
									{
										if (ComponentsStatusBeforeChange(action, service))
										{
											service.Continue();
											ComponentsStatusAfterChange(action, service);
										}				
									}									
								break;
						}
					}
					catch (Exception ex)
					{
                        string message = "ComponentsStatusChange: " + objService.ToString() + " -> " 
                            + action.ToString() + " -> " + ex.Message;
#if (DEBUG)
                        Debug.WriteLine(message, action.ToString() + " error.");
#endif
                        throw new XimuraComponentServiceException(message,ex);
					}
				}
			}
		}
		/// <summary>
		/// This method can start, stop, resume or pause a group of components.
		/// </summary>
		/// <param name="action">The action required</param>
		/// <param name="components">The components to which the action should be provided</param>
		protected virtual void ComponentsStatusChange(XimuraServiceStatusAction action, ICollection components)
		{
			ComponentsStatusChange(action,components,null);
		}