/// <summary>
        /// Requests a cancellation of the output process.
        /// The cancellation is asynchronous and therefore the output process will need some time
        /// to finish with the state "Aborted".
        /// </summary>
        void IOutputProcess.Cancel()
        {
            lock (_syncLock)
            {
                if ((_currentState != OutputProcessState.Queued) &&
                    (_currentState != OutputProcessState.InProcess))
                {
                    return;
                }
            }

            var request = new TaskCancelRequestEnvelope()
            {
                TaskCancelRequest = new TaskCancelRequest()
                {
                    Id          = MessageId.Next,
                    Destination = this.Destination,
                    Source      = this.Source
                }
            };

            request.TaskCancelRequest.Task = new Types.Task[]
            {
                new Types.Task()
                {
                    Id = this.Id.ToString(), Type = TaskType.Output
                }
            };

            lock (_syncLock)
            {
                if ((_currentState == OutputProcessState.Queued) ||
                    (_currentState == OutputProcessState.InProcess))
                {
                    _currentState = OutputProcessState.Aborting;
                }
            }

            var response = (TaskCancelResponse)_messageDispatcher.SendAndWaitForResponse(request,
                                                                                         request.TaskCancelRequest.Id,
                                                                                         typeof(TaskCancelResponse));

            if (response == null)
            {
                throw new ArgumentException("Waiting for the message 'TaskCancelResponse' failed.");
            }

            if ((response.Task == null) || (response.Task[0] == null))
            {
                if (string.Compare(response.Task[0].Status, "CancelError", true) == 0)
                {
                    throw new ApplicationException("Cancellation of output process failed.");
                }
            }
        }
        /// <summary>
        /// Starts the output process by sending the according request to the storage system.
        /// </summary>
        void IOutputProcess.Start()
        {
            lock (_syncLock)
            {
                if (_currentState != OutputProcessState.Created)
                {
                    return;
                }
            }

            var request = new OutputRequestEnvelope()
            {
                OutputRequest = this
            };
            var outputMessageInterceptor = new MessageInterceptor(this.Id, typeof(OutputMessage));

            _messageDispatcher.AddInterceptor(outputMessageInterceptor);

            var response = (OutputResponse)_messageDispatcher.SendAndWaitForResponse(request,
                                                                                     this.Id,
                                                                                     typeof(OutputResponse));

            if (response == null)
            {
                _messageDispatcher.RemoveInterceptor(outputMessageInterceptor);
                outputMessageInterceptor.Dispose();
                throw new ArgumentException("Waiting for the message 'OutputResponse' failed.");
            }

            if ((response.Details == null) || (Enum.TryParse <OutputProcessState>(response.Details.Status, out _currentState) == false))
            {
                _currentState = OutputProcessState.Unknown;
            }

            if (_currentState != OutputProcessState.Queued)
            {
                if (_finished != null)
                {
                    this.Trace("Raising event 'Finished'.");
                    _finished(this, new EventArgs());
                }
            }
            else
            {
                // wait for completion
                if (ThreadPool.QueueUserWorkItem(new WaitCallback(WaitForOutputMessage),
                                                 outputMessageInterceptor) == false)
                {
                    throw new ApplicationException("Starting observation thread failed.");
                }
            }
        }
        /// <summary>
        /// Asynchronous thread which waits for the completion of the specified output message interceptor.
        /// </summary>
        /// <param name="messageInterceptor">The message interceptor to wait for.</param>
        private void WaitForOutputMessage(object messageInterceptor)
        {
            try
            {
                using (var interceptor = messageInterceptor as MessageInterceptor)
                {
                    bool orderNotFinished = true;
                    while (orderNotFinished)
                    {
                        interceptor.Wait();

                        var outputMessage = (OutputMessage)interceptor.Message;

                        if (outputMessage != null)
                        {
                            lock (_syncLock)
                            {
                                if (outputMessage.Article != null)
                                {
                                    foreach (var article in outputMessage.Article)
                                    {
                                        if (article.Pack != null)
                                        {
                                            foreach (var pack in article.Pack)
                                            {
                                                pack.ArticleId = TextConverter.UnescapeInvalidXmlChars(article.Id);
                                            }

                                            _dispensedPackList.AddRange(article.Pack);
                                        }
                                    }
                                }

                                if (outputMessage.Box != null)
                                {
                                    foreach (var box in outputMessage.Box)
                                    {
                                        _boxList.Add(box.Number);
                                    }
                                }

                                if (Enum.TryParse <OutputProcessState>(outputMessage.Details.Status, out _currentState) == false)
                                {
                                    _currentState = OutputProcessState.Unknown;
                                }
                            }
                        }
                        else
                        {
                            this.Error("Waiting for the message 'OutputMessage' failed.");

                            lock (_syncLock)
                            {
                                _currentState = OutputProcessState.Unknown;
                            }
                        }

                        if (_currentState.Equals(OutputProcessState.BoxReleased))
                        {
                            if (_boxReleased != null)
                            {
                                lock (_syncLock)
                                {
                                    this.Trace("Raising event 'Box Released'.");
                                    _boxReleased(this, new EventArgs());
                                    _dispensedPackList.Clear();
                                }
                            }
                        }
                        else
                        {
                            orderNotFinished = false;
                            _messageDispatcher.RemoveInterceptor(interceptor);
                            if (_finished != null)
                            {
                                this.Trace("Raising event 'Finished'.");
                                _finished(this, new EventArgs());
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.Error("Receiving and processing 'OutputMessage' failed!", ex);
            }
        }
        /// <summary>
        /// Asynchronous thread which waits for the completion of the specified output message interceptor.
        /// </summary>
        /// <param name="messageInterceptor">The message interceptor to wait for.</param>
        private void WaitForOutputMessage(object messageInterceptor)
        {
            try
            {
                using (var interceptor = messageInterceptor as MessageInterceptor)
                {
                    bool orderNotFinished = true;

                    while (orderNotFinished)
                    {
                        interceptor.Wait();

                        var outputMessage = interceptor.Message as OutputMessage;

                        if (outputMessage != null)
                        {
                            lock (_syncLock)
                            {
                                this._boxList.Clear();

                                this._dispensedPackList.Clear();
                                this._dispensedPackList.AddRange(outputMessage.GetPacks());

                                if (outputMessage.Box != null)
                                {
                                    foreach (var box in outputMessage.Box)
                                    {
                                        _boxList.Add(box.Number);
                                    }
                                }

                                if (Enum.TryParse <OutputProcessState>(outputMessage.Details.Status,
                                                                       out _currentState) == false)
                                {
                                    _currentState = OutputProcessState.Unknown;
                                }
                            }
                        }
                        else
                        {
                            this.Error("Waiting for the message 'OutputMessage' failed.");

                            lock (_syncLock)
                            {
                                _currentState = OutputProcessState.Unknown;
                            }
                        }

                        if (_currentState.Equals(OutputProcessState.BoxReleased))
                        {
                            if (_boxReleased != null)
                            {
                                lock (_syncLock)
                                {
                                    this.Trace("Raising event 'Box Released'.");
                                    _boxReleased(this, new EventArgs());
                                }
                            }
                        }
                        else if (_currentState.Equals(OutputProcessState.Completed) ||
                                 _currentState.Equals(OutputProcessState.Incomplete) ||
                                 _currentState.Equals(OutputProcessState.Aborted))
                        {
                            orderNotFinished = false;
                            _messageDispatcher.RemoveInterceptor(interceptor);
                            if (_finished != null)
                            {
                                this.Trace("Raising event 'Finished'.");
                                _finished(this, new EventArgs());
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.Error("Receiving and processing 'OutputMessage' failed!", ex);
            }
        }