/// <summary>
        /// Updates the state machine to reflect the successful processing of a method.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="causeId">The cause id.</param>
        /// <returns></returns>
        public void CauseProcessingCompleted(ISystemContext context, uint causeId)
        {
            // get the transition.
            uint transitionId = GetTransitionForCause(context, causeId);

            if (transitionId == 0)
            {
                return;
            }

            // get the new state.
            uint newState = GetNewStateForTransition(context, transitionId);

            if (newState == 0)
            {
                return;
            }

            // save the last state.
            if (m_lastState == null)
            {
                m_lastState = new FiniteStateVariableState(this);
            }

            m_lastState.SetChildValue(context, null, CurrentState, false);

            // update state and transition variables.
            UpdateStateVariable(context, newState, CurrentState);
            UpdateTransitionVariable(context, transitionId, LastTransition);
        }
        /// <summary>
        /// Updates the current state variable.
        /// </summary>
        protected void UpdateStateVariable(ISystemContext context, uint stateId, FiniteStateVariableState variable)
        {
            if (variable == null)
            {
                return;
            }

            if (stateId == 0)
            {
                variable.Value    = null;
                variable.Id.Value = null;

                if (variable.Number != null)
                {
                    variable.Number.Value = 0;
                }

                return;
            }

            ElementInfo[] stateTable = StateTable;

            if (stateTable == null)
            {
                return;
            }

            for (int ii = 0; ii < stateTable.Length; ii++)
            {
                ElementInfo state = stateTable[ii];

                if (state.Id == stateId)
                {
                    variable.Value    = state.Name;
                    variable.Id.Value = new NodeId(state.Id, ElementNamespaceIndex);

                    if (variable.Number != null)
                    {
                        variable.Number.Value = state.Number;
                    }

                    return;
                }
            }
        }
        /// <summary>
        /// Causes the specified transition to occur.
        /// </summary>
        public ServiceResult DoTransition(
            ISystemContext context,
            uint transitionId,
            uint causeId,
            IList <object> inputArguments,
            IList <object> outputArguments)
        {
            // check for valid transition.
            uint newState = GetNewStateForTransition(context, transitionId);

            if (newState == 0)
            {
                return(StatusCodes.BadNotSupported);
            }

            // check the cause permissions.
            if (causeId != 0)
            {
                if (!IsCausePermitted(context, causeId, true))
                {
                    return(StatusCodes.BadUserAccessDenied);
                }
            }

            // do any pre-transition processing.
            ServiceResult result = InvokeCallback(
                OnBeforeTransition,
                context,
                this,
                transitionId,
                causeId,
                inputArguments,
                outputArguments);

            if (ServiceResult.IsBad(result))
            {
                return(result);
            }

            // save the last state.
            if (m_lastState == null)
            {
                m_lastState = new FiniteStateVariableState(this);
            }

            m_lastState.SetChildValue(context, null, CurrentState, false);

            // update state and transition variables.
            UpdateStateVariable(context, newState, CurrentState);
            UpdateTransitionVariable(context, transitionId, LastTransition);

            // do any post-transition processing.
            InvokeCallback(
                OnAfterTransition,
                context,
                this,
                transitionId,
                causeId,
                inputArguments,
                outputArguments);

            // report the event.
            if (this.AreEventsMonitored && !m_suppressTransitionEvents)
            {
                TransitionEventState e = CreateTransitionEvent(context, transitionId, causeId);

                if (e != null)
                {
                    UpdateTransitionEvent(context, transitionId, causeId, e);
                    ReportEvent(context, e);
                }
            }

            return(ServiceResult.Good);
        }
        /// <summary>
        /// Causes the specified transition to occur.
        /// </summary>
        public ServiceResult DoTransition(
            ISystemContext context, 
            uint transitionId, 
            uint causeId,
            IList<object> inputArguments,
            IList<object> outputArguments)
        {
            // check for valid transition.
            uint newState = GetNewStateForTransition(context, transitionId);

            if (newState == 0)
            {
                return StatusCodes.BadNotSupported;
            }

            // check the cause permissions.
            if (causeId != 0)
            {
                if (!IsCausePermitted(context, causeId, true))
                {
                    return StatusCodes.BadUserAccessDenied;
                }
            }
            
            // do any pre-transition processing.
            ServiceResult result = InvokeCallback(
                OnBeforeTransition,
                context, 
                this, 
                transitionId, 
                causeId,
                inputArguments,
                outputArguments);

            if (ServiceResult.IsBad(result))
            {
                return result;
            }

            // save the last state.
            if (m_lastState == null)
            {
                m_lastState = new FiniteStateVariableState(this);
            }

            m_lastState.SetChildValue(context, null, CurrentState, false);
            
            // update state and transition variables.
            UpdateStateVariable(context, newState, CurrentState);
            UpdateTransitionVariable(context, transitionId, LastTransition);
            
            // do any post-transition processing.
            InvokeCallback(
                OnAfterTransition,
                context, 
                this, 
                transitionId, 
                causeId,
                inputArguments,
                outputArguments);
            
            // report the event.
            if (this.AreEventsMonitored && !m_suppressTransitionEvents)
            {
                TransitionEventState e = CreateTransitionEvent(context, transitionId, causeId);

                if (e != null)
                {
                    UpdateTransitionEvent(context, transitionId, causeId, e);
                    ReportEvent(context, e);
                }
            }

            return ServiceResult.Good;
        }
        /// <summary>
        /// Updates the state machine to reflect the successful processing of a method.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="causeId">The cause id.</param>
        /// <returns></returns>
        public void CauseProcessingCompleted(ISystemContext context, uint causeId)
        {
            // get the transition.
            uint transitionId = GetTransitionForCause(context, causeId);

            if (transitionId == 0)
            {
                return;
            }

            // get the new state.
            uint newState = GetNewStateForTransition(context, transitionId);

            if (newState == 0)
            {
                return;
            }

            // save the last state.
            if (m_lastState == null)
            {
                m_lastState = new FiniteStateVariableState(this);
            }

            m_lastState.SetChildValue(context, null, CurrentState, false);

            // update state and transition variables.
            UpdateStateVariable(context, newState, CurrentState);
            UpdateTransitionVariable(context, transitionId, LastTransition);
        }
        /// <summary>
        /// Updates the current state variable.
        /// </summary>
        protected void UpdateStateVariable(ISystemContext context, uint stateId, FiniteStateVariableState variable)
        {
            if (variable == null)
            {
                return;
            }

            if (stateId == 0)
            {
                variable.Value = null;
                variable.Id.Value = null;

                if (variable.Number != null)
                {
                    variable.Number.Value = 0;
                }

                return;
            }

            ElementInfo[] stateTable = StateTable;

            if (stateTable == null)
            {
                return;
            }

            for (int ii = 0; ii < stateTable.Length; ii++)
            {
                ElementInfo state = stateTable[ii];

                if (state.Id == stateId)
                {
                    variable.Value = state.Name;
                    variable.Id.Value = new NodeId(state.Id, ElementNamespaceIndex);

                    if (variable.Number != null)
                    {
                        variable.Number.Value = state.Number;
                    }

                    return;
                }
            }
        }