/// <summary>
 /// Raises a MessageReceived event.
 /// </summary>
 /// <param name="sender">Creator of event</param>
 /// <param name="e">Event arguments</param>
 protected void OnMessageReceived(object sender, MessageReceivedFromCommunicatorEventArgs e)
 {
     try
     {
         if (MessageReceived != null)
         {
             MessageReceived(sender, new MessageReceivedFromRemoteApplicationEventArgs
             {
                 Application = this,
                 Communicator = e.Communicator,
                 Message = e.Message
             });
         }
         else
         {
             //Disconnect communicator if there is not listener for incoming messages from this communicator.
             e.Communicator.Stop(false);
         }
     }
     catch (Exception ex)
     {
         Logger.Warn(ex.Message, ex);
     }
 }
        /// <summary>
        /// This method is just used to make a new connection with MDS server.
        /// It receives response of register message and adds communicator to Communicators if successfuly registered.
        /// </summary>
        /// <param name="sender">Creator object of event</param>
        /// <param name="e">Event arguments</param>
        private void Communicator_MessageReceived(object sender, MessageReceivedFromCommunicatorEventArgs e)
        {
            try
            {
                //Message must be MDSOperationResultMessage
                var message = e.Message as MDSOperationResultMessage;
                if (message == null)
                {
                    throw new MDSException("First message must be MDSOperationResultMessage");
                }

                //Check if remote MDS server accepted connection
                if(!message.Success)
                {
                    throw new MDSException("Remote MDS server did not accept connection.");
                }

                //Unregister from event and add communicator to Communicators list.
                e.Communicator.MessageReceived -= Communicator_MessageReceived;
                try
                {
                    AddCommunicator(e.Communicator);
                }
                catch (Exception ex)
                {
                    Logger.Warn(ex.Message, ex);
                    e.Communicator.Stop(false);
                }
            }
            catch (Exception ex)
            {
                Logger.Warn("Can not connected to remote MDS server: '" + Name + "'. Connection is being closed.");
                Logger.Warn(ex.Message, ex);
                try
                {
                    e.Communicator.Stop(false);
                }
                catch (Exception ex2)
                {
                    Logger.Warn(ex2.Message, ex2);                    
                }
            }
            finally
            {
                _reconnectingCommunicator = null;
            }
        }
        /// <summary>
        /// Processes a MDSChangeCommunicationWayMessage message.
        /// </summary>
        /// <param name="e">Event arguments from Communicator_MessageReceived method</param>
        private static void ProcessChangeCommunicationWayMessage(MessageReceivedFromCommunicatorEventArgs e)
        {
            var message = e.Message as MDSChangeCommunicationWayMessage;
            if (message == null)
            {
                return;
            }

            //Change communication way
            e.Communicator.CommunicationWay = message.NewCommunicationWay;
        }
 /// <summary>
 /// Processes a MDSOperationResultMessage message.
 /// </summary>
 /// <param name="e">Event arguments from Communicator_MessageReceived method</param>
 private void ProcessOperationResultMessage(MessageReceivedFromCommunicatorEventArgs e)
 {
     //Send message to message deliverer to process
     var handled = _messageDeliverer.HandleOperationResultMessage(e);
     /* If message is handled, OnResponseReceived event is raised, 
      * thus, caller of SendDataMessage (MDSPersistentRemoteApplicationBase.ProcessWaitingMessage) method 
      * gets response. */
     if (handled)
     {
         OnResponseReceived(e.Communicator, e.Message as MDSOperationResultMessage);
     }
 }
        /// <summary>
        /// When a communicator is received a message, this method handles event..
        /// </summary>
        /// <param name="sender">Creator of event</param>
        /// <param name="e">Event arguments</param>
        private void Communicator_MessageReceived(object sender, MessageReceivedFromCommunicatorEventArgs e)
        {
            //Update last incoming message time
            LastIncomingMessageTime = DateTime.Now;

            //Check if this is an ACK/Reject message for a data transfer message
            if ((e.Message.MessageTypeId == MDSMessageFactory.MessageTypeIdMDSOperationResultMessage) && 
                (!string.IsNullOrEmpty(e.Message.RepliedMessageId)))
            {
                ProcessOperationResultMessage(e);
                return;
            }

            //Check if this is an MDSChangeCommunicationWayMessage
            if (e.Message.MessageTypeId == MDSMessageFactory.MessageTypeIdMDSChangeCommunicationWayMessage)
            {
                ProcessChangeCommunicationWayMessage(e);
                return;
            }

            //Add message to incoming message queue to process as ordered
            _incomingMessageQueue.Add(e);
        }
            /// <summary>
            /// This method is used to get MDSOperationResultMessage objects (ACK/Reject messages) by MessageDeliverer class.
            /// It is called by MDSRemoteApplication's Communicator_MessageReceived method.
            /// </summary>
            /// <param name="e">Event arguments from Communicator_MessageReceived method</param>
            /// <returns>True, if message is handled by this method</returns>
            public bool HandleOperationResultMessage(MessageReceivedFromCommunicatorEventArgs e)
            {
                lock (_remoteApplication._communicators)
                {
                    var connectedCommunicator = _remoteApplication.FindCommunicator(e.Communicator);
                    if (connectedCommunicator != null && connectedCommunicator.ProcessingMessage != null && connectedCommunicator.ProcessingMessage.MessageId == e.Message.RepliedMessageId)
                    {
                        //Set communicator as free
                        connectedCommunicator.ProcessingMessage = null;

                        //Send receiver to end of the list
                        _remoteApplication._communicators.Remove(connectedCommunicator);
                        _remoteApplication._communicators.AddLast(connectedCommunicator);

                        //Suspend communicator if it rejected the message
                        var resultMessage = e.Message as MDSOperationResultMessage;
                        if (resultMessage != null && !resultMessage.Success)
                        {
                            connectedCommunicator.IsSuspended = true;
                            connectedCommunicator.SuspendExpireDate = DateTime.Now.AddSeconds(15);
                        }
                        else
                        {
                            //Pulse threads that are waiting for a free communicator
                            Monitor.PulseAll(_remoteApplication._communicators);
                        }

                        return true;
                    }
                }

                return false;
            }
 /// <summary>
 /// When a message received from a communicator, this method is called.
 /// This method just process Register messages. After a register message received
 /// from cummunicator, stops listen to events from this communicator anymore.
 /// </summary>
 /// <param name="sender">Sender (ICommunicator)</param>
 /// <param name="e">Event args</param>
 private void Communicator_MessageReceived(object sender, MessageReceivedFromCommunicatorEventArgs e)
 {
     if (e.Message.MessageTypeId != MDSMessageFactory.MessageTypeIdMDSRegisterMessage)
     {
         return;
     }
     
     try
     {
         ProcessRegisterMessage(e.Communicator, e.Message as MDSRegisterMessage);
     }
     catch (Exception ex)
     {
         Logger.Warn(ex.Message, ex);
     }
     finally
     {
         e.Communicator.MessageReceived -= Communicator_MessageReceived;                
     }
 }