fipa_acl  1.4
Public Member Functions | Static Public Member Functions | List of all members
fipa::acl::Conversation Class Reference

#include <conversation.h>

Inherits fipa::acl::ConversationObservable.

Public Member Functions

 Conversation (const std::string &owner, const fipa::acl::ConversationID &conversationId=fipa::acl::ConversationID())
 
 Conversation (const std::string &owner, const fipa::acl::ACLMessage &initiator)
 
 Conversation (const Conversation &other)
 
virtual ~Conversation ()
 
void setProtocol (const fipa::acl::Protocol &protocol)
 
fipa::acl::Protocol getProtocol () const
 
void setContentLanguage (const fipa::acl::ContentLanguage &language)
 
fipa::acl::ContentLanguage getContentLanguage () const
 
void setNumberOfSubConversations (int amount)
 
void update (const fipa::acl::ACLMessage &msg)
 
std::vector
< fipa::acl::ACLMessage
getMessages () const
 
fipa::acl::ACLMessage getLastMessage () const
 
bool hasEnded () const
 
bool hasMessages () const
 
std::string getOwner () const
 
std::string toString () const
 
- Public Member Functions inherited from fipa::acl::ConversationObservable
 ConversationObservable ()
 
 ConversationObservable (const ConversationObservable &other)
 
 ConversationObservable (const fipa::acl::ConversationID &conversationId)
 
virtual ~ConversationObservable ()
 
void setConversationId (const fipa::acl::ConversationID &conversationId)
 
fipa::acl::ConversationID getConversationId () const
 
void addObserver (const ConversationObserverPtr &observer)
 
void removeObserver (const ConversationObserverPtr &observer)
 
void notify (const fipa::acl::ACLMessage &msg, conversation::EventType eventType)
 
conversation::Status getStatus () const
 
ConversationObserverList getObservers () const
 
void detachObservers ()
 
bool hasObservers () const
 

Static Public Member Functions

static fipa::acl::ConversationID generateConversationID (const std::string &topic="")
 
static std::string toString (const std::vector< fipa::acl::ACLMessage > &messages)
 

Additional Inherited Members

- Protected Attributes inherited from fipa::acl::ConversationObservable
fipa::acl::ConversationID mConversationId
 

Detailed Description

A Conversation represents a flow of messages which have the conversation id and (commonly) the protocol in common

A conversation can be observed and observers will be notified when the conversation is updated

Definition at line 257 of file conversation.h.

Constructor & Destructor Documentation

fipa::acl::Conversation::Conversation ( const std::string &  owner,
const fipa::acl::ConversationID conversationId = fipa::acl::ConversationID() 
)

Constructor of an empty conversation Owner and conversation id need to be provided

Parameters
ownerOwner of the conversation will be the current agent
conversationIdConversation id - If no conversation id is provided, one will automatically be generated

Definition at line 100 of file conversation.cpp.

101  : ConversationObservable(conversationId)
102  , mOwner(owner)
103  , mNumberOfSubConversations(0)
104 {
105  if(mConversationId.empty())
106  {
108  }
109  LOG_DEBUG("Conversation created with id: %s\n", conversationId.c_str());
110 }
static fipa::acl::ConversationID generateConversationID(const std::string &topic="")
fipa::acl::ConversationID mConversationId
Definition: conversation.h:231
fipa::acl::Conversation::Conversation ( const std::string &  owner,
const fipa::acl::ACLMessage initiator 
)

Constructor of a Conversation that requires an iniating message, i.e. includes a call to update

Definition at line 112 of file conversation.cpp.

114  , mOwner(owner)
115  , mNumberOfSubConversations(0)
116 {
117  update(initiator);
118  LOG_DEBUG("Conversation created with id: %s\n", initiator.getConversationID().c_str());
119  assert(!mConversationId.empty());
120 }
fipa::acl::ConversationID mConversationId
Definition: conversation.h:231
void update(const fipa::acl::ACLMessage &msg)
std::string getConversationID() const
Definition: acl_message.h:227
fipa::acl::Conversation::Conversation ( const Conversation other)

Definition at line 122 of file conversation.cpp.

123  : ConversationObservable(other)
124  , mOwner(other.mOwner)
125  , mProtocol(other.mProtocol)
126  , mContentLanguage(other.mContentLanguage)
127  , mNumberOfSubConversations(other.mNumberOfSubConversations)
128  , mMessages(other.mMessages)
129  , mStateMachine(other.mStateMachine)
130 {
131 }
fipa::acl::Conversation::~Conversation ( )
virtual

Conversation destructor cleans also all related commands in the command controller

Definition at line 133 of file conversation.cpp.

134 {
135 }

Member Function Documentation

fipa::acl::ConversationID fipa::acl::Conversation::generateConversationID ( const std::string &  topic = "")
static

Create a new ConversationID

Definition at line 285 of file conversation.cpp.

286 {
287  uuid_t uuid;
288  uuid_generate(uuid);
289 
290  char conversationId[37];
291  uuid_unparse(uuid, conversationId);
292  return std::string(conversationId) + "--" + topic + "--" + base::Time::now().toString();
293 }
std::string fipa::acl::Conversation::getContentLanguage ( ) const

Get content language (which is set by the initiating message)

Returns
ContentLanguage

Definition at line 137 of file conversation.cpp.

138 {
139  return mContentLanguage;
140 }
fipa::acl::ACLMessage fipa::acl::Conversation::getLastMessage ( ) const

Get the last message of a conversation

Returns
Last message of the conversation

Definition at line 245 of file conversation.cpp.

246 {
247  boost::unique_lock<boost::mutex> lock(mMutex);
248  return mMessages.back();
249 }
std::vector<fipa::acl::ACLMessage> fipa::acl::Conversation::getMessages ( ) const
inline

Get all messages in order of this conversation

Definition at line 322 of file conversation.h.

322 { return mMessages; }
std::string fipa::acl::Conversation::getOwner ( ) const

Get the name of the owner of this conversation, this is equal to the agent name of the system

Definition at line 280 of file conversation.cpp.

281 {
282  return mOwner;
283 }
fipa::acl::Protocol fipa::acl::Conversation::getProtocol ( ) const
inline

Get protocol (which is set by the initiating message)

Returns
Protocol

Definition at line 291 of file conversation.h.

291 { return mProtocol; }
bool fipa::acl::Conversation::hasEnded ( ) const

Check if conversation has ended. This is closely related to the interaction protocol flow, i.e. only when the protocol has been validated the conversation will end

Returns
true if conversation ended, false otherwise

Definition at line 251 of file conversation.cpp.

252 {
253  try
254  {
255  if(!mStateMachine.inFinalState())
256  {
257  LOG_DEBUG("Conversation did not end");
258  return false;
259 
260  }
261  LOG_DEBUG("Conversation ended");
262  return true;
263  }
264  catch(const std::runtime_error& e)
265  {
266  // This very probably means the state machine has not been initialized properly,
267  // as there was no message yet to know the protocol. Therefore, technically
268  // the conversation did not end!
269  LOG_WARN_S << "Runtime error when testing if conversation ended. Therefore not ended. Message: " << e.what();
270  return false;
271  }
272 }
bool inFinalState() const
bool fipa::acl::Conversation::hasMessages ( ) const

Check if this is an active conversation

Returns
true if conversation is active and has messages, false if is not active, i.e. has not started (yet)

Definition at line 274 of file conversation.cpp.

275 {
276  boost::unique_lock<boost::mutex> lock(mMutex);
277  return !mMessages.empty();
278 }
void fipa::acl::Conversation::setContentLanguage ( const fipa::acl::ContentLanguage language)
inline

Set content language

Definition at line 296 of file conversation.h.

296 { mContentLanguage = language; }
void fipa::acl::Conversation::setNumberOfSubConversations ( int  amount)
inline

For protocols requiring a proxy/propagate behaviour, the number of sub conversations to be started needs to be known in order to monitor the end of the conversation correctly. E.g. a broker would set this to m, as soon as he knows that m agents will be contacted.

This MUST be called BEFORE an actual message of a sub conversation is sent.

Definition at line 311 of file conversation.h.

311 { mNumberOfSubConversations = amount; }
void fipa::acl::Conversation::setProtocol ( const fipa::acl::Protocol protocol)
inline

Set the protocol for this conversation

Definition at line 285 of file conversation.h.

285 { mProtocol = protocol; }
std::string fipa::acl::Conversation::toString ( const std::vector< fipa::acl::ACLMessage > &  messages)
static

Convert message list to string

Definition at line 295 of file conversation.cpp.

296 {
297  std::stringstream ss;
298  std::vector<fipa::acl::ACLMessage>::const_iterator cit = messages.begin();
299  for(; cit != messages.end(); ++cit)
300  {
301  ss << cit->toString() << std::endl;
302  }
303  return ss.str();
304 }
std::string fipa::acl::Conversation::toString ( ) const

Convert conversation to string

Definition at line 306 of file conversation.cpp.

307 {
308  std::stringstream ss;
309  ss << "Conversation: " << std::endl;
310  if(!mMessages.empty())
311  {
312  ss << " id: " << mMessages.front().getConversationID();
313  }
314  ss << std::endl;
315  ss << " owner: " << mOwner << std::endl;
316  ss << " protocol: " << mProtocol << std::endl;
317  ss << " language: " << mContentLanguage << std::endl;
318  ss << " # subconversations: " << mNumberOfSubConversations << std::endl;
319  ss << " # messages " << mMessages.size() << std::endl;
320  ss << "BEGIN " << std::endl;
321  ss << toString(mMessages) << std::endl;
322  ss << "END" << std::endl;
323 
324  return ss.str();
325 }
std::string toString() const
void fipa::acl::Conversation::update ( const fipa::acl::ACLMessage msg)

Update a conversation using an incoming message

Parameters
msgincoming or outgoing message

Definition at line 142 of file conversation.cpp.

143 {
144  boost::unique_lock<boost::mutex> lock(mMutex);
145 
146  LOG_INFO("Update conversation: id '%s'", msg.getConversationID().c_str());
147  LOG_INFO("Update message: performative: '%s' content: '%s'", msg.getPerformative().c_str(), msg.getContent().c_str());
148 
149 
150  bool newConversation = false;
151  try {
152  // If protocol is unset we don't have a valid message
153  // Thus at this point the conversation is not yet initialized
154  if(mProtocol.empty())
155  {
156  std::string protocol = msg.getProtocol();
157  try {
158  if(!protocol.empty())
159  {
160  mStateMachine = msStateMachineFactory.getStateMachine(protocol);
161  mStateMachine.setSelf( fipa::acl::AgentID(mOwner) );
162 
163  mProtocol = protocol;
164  mContentLanguage = msg.getLanguage();
166 
167  } else {
168  LOG_ERROR("Protocol not set");
169  throw std::runtime_error("Protocol not set");
170  }
171  } catch(const std::runtime_error& e)
172  {
173  LOG_FATAL("Conversation could not retrieve statemachine for protocol '%s'. Check if protocol specification was loaded -- '%s'", protocol.c_str(), e.what());
174  throw;
175  }
176 
177  newConversation = true;
178 
179  } else if( mProtocol != msg.getProtocol())
180  {
181  // This probably means, it's a subProtocol message
182  try {
183  mStateMachine.consumeSubStateMachineMessage(msg, msStateMachineFactory.getStateMachine(msg.getProtocol()), mNumberOfSubConversations);
184  } catch(const std::runtime_error& e)
185  {
186  std::string errorMsg = "Conversation: unexpected message with performative '" + msg.getPerformative() + "' for the protocol '" + msg.getProtocol() + "' ";
187  errorMsg += " current state: '" + mStateMachine.getCurrentStateId() + "',";
188  errorMsg += " role mapping -- " + mStateMachine.getRoleMapping().toString();
189  errorMsg += " -- " + std::string(e.what()) + "\n";
190  throw conversation::ProtocolException(errorMsg);
191  }
192 
193  notifyAll(msg, false);
194  return;
195  } else if( msg.getProtocol().empty())
196  {
197  LOG_WARN("Conversation: received message has no protocol being set. Current conversation using '%s'", mProtocol.c_str());
198  }
199 
200  if( msg.getLanguage().empty())
201  {
202  LOG_INFO("Conversation: received message has not language being set. Current conversation using '%s'", mContentLanguage.c_str());
203  } else if(mContentLanguage != msg.getLanguage())
204  {
205  LOG_INFO("Conversation: message with different content language being inserted: current '%s' - to be inserted '%s'", mContentLanguage.c_str(), msg.getLanguage().c_str());
206  }
207 
208  // update the message state machine
209  try {
210  mStateMachine.consumeMessage(msg);
211  } catch(const std::runtime_error& e)
212  {
213  std::string errorMsg = "Conversation: unexpected message with performative '" + msg.getPerformative() + "' for the protocol '" + msg.getProtocol() + "' ";
214  errorMsg += " current state: '" + mStateMachine.getCurrentStateId() + "',";
215  errorMsg += " role mapping -- " + mStateMachine.getRoleMapping().toString();
216  errorMsg += " -- " + std::string(e.what()) + "\n";
217  throw conversation::ProtocolException(errorMsg);
218  }
219 
220  notifyAll(msg, newConversation);
221 
222  } catch(...)
223  {
224  // Notify only to handle internally
225  throw;
226  }
227 }
void consumeMessage(const ACLMessage &msg)
std::string getContent() const
Definition: acl_message.h:294
std::string toString() const
Definition: role.cpp:165
static StateMachine getStateMachine(const std::string &protocol)
std::string getPerformative() const
Definition: acl_message.h:139
const RoleMapping & getRoleMapping() const
Definition: statemachine.h:109
void setSelf(const AgentID &self)
std::string getLanguage() const
Definition: acl_message.h:268
std::string getProtocol() const
Definition: acl_message.h:238
StateId getCurrentStateId() const
Definition: statemachine.h:129
fipa::acl::ConversationID mConversationId
Definition: conversation.h:231
void consumeSubStateMachineMessage(const ACLMessage &msg, const fipa::acl::StateMachine &stateMachine, int numberOfSubConversations)
Implements the general AgentID functionality, which is present throughout the fipa specifications(FIP...
Definition: agent_id.h:37
std::string getConversationID() const
Definition: acl_message.h:227

The documentation for this class was generated from the following files: