fipa_acl  1.4
Public Member Functions | Static Public Attributes | Protected Member Functions | Friends | List of all members
fipa::acl::State Class Reference

implements a state of the StateMachine class More...

#include <state.h>

Inherited by fipa::acl::default_state::ConversationCancelling, fipa::acl::FinalState, and fipa::acl::UndefinedState.

Public Member Functions

 State ()
 empty constructor initializes default fields More...
 
 State (const StateId &id)
 constructor taking the unique name(id) of the state as arguement More...
 
Transition addTransition (const Transition &t)
 
const TransitiongetTransition (const ACLMessage &msg, const MessageArchive &archive, const RoleMapping &roleMapping) const
 Check whether the received message triggers a transition. More...
 
void consumeSubStateMachineMessage (const ACLMessage &msg, const fipa::acl::StateMachine &stateMachine, const fipa::acl::RoleMapping &roleMapping, int numberOfSubConversations)
 
const TransitiongetSubstateMachineProxiedTransition (const ACLMessage &msg, const MessageArchive &archive, const RoleMapping &roleMapping)
 Check whether the received message triggers a substatemachine proxied transition. This method is not const, as the generated transitions will be added when they trigger successfully. More...
 
void generateDefaultTransitions ()
 method that generates implicit generic transitions applicable to all states, that may or may not be speciffied in the configuration file such as not-understood transition (if it is specified it is not doubled); this method is to be called after all states specified in the configuration have been added to the state machine, preferably after all generic transition have been added as well More...
 
bool isFinal () const
 
bool isFinished () const
 method that returns whether the state is a finished state or not. In the case of a state with embedded state machines, this is a bit more coplex, see the implementation More...
 
bool isDefaultState () const
 Test if state belongs to the default state or not. More...
 
void setId (const StateId &id)
 setter method for the uid field of the state NOTE: maybe should be taken out and name only be allowed to be set on More...
 
std::string getId () const
 getter method for the uid field of the class More...
 
const std::vector< Transition > & getTransitions () const
 
const std::vector< EmbeddedStateMachine > & getEmbeddedStatemachines () const
 
void addEmbeddedStateMachine (fipa::acl::EmbeddedStateMachine embeddedStateMachine)
 
std::string toString () const
 
std::string toXML () const
 

Static Public Attributes

static const StateId UNDEFINED_ID = "__undefined__"
 
static const StateId NOT_UNDERSTOOD = "__internal_state:not_understood__"
 
static const StateId CONVERSATION_CANCELLING = "__internal_state:conversation_cancelling__"
 
static const StateId CONVERSATION_CANCEL_SUCCESS = "__internal_state:conversation_cancel_success__"
 
static const StateId CONVERSATION_CANCEL_FAILURE = "__internal_state:conversation_cancel_failure__"
 
static const StateId GENERAL_FAILURE_STATE = "__internal_state:general_failure__"
 

Protected Member Functions

void setFinal (bool final)
 setter method for the final field of the class When changing the final state flag make sure you either remove existing transitions or create the default transition if needed More...
 

Friends

class Transition
 
class default_transition::NotUnderstood
 
class default_transition::ConversationCancelling
 
class default_transition::ConversationCancelSuccess
 
class default_transition::ConversationCancelFailure
 
class default_transition::GeneralFailure
 
class StateMachineReader
 
class StateMachine
 

Detailed Description

implements a state of the StateMachine class

Definition at line 41 of file state.h.

Constructor & Destructor Documentation

◆ State() [1/2]

fipa::acl::State::State ( )

empty constructor initializes default fields

Definition at line 33 of file state.cpp.

34  : mId(State::UNDEFINED_ID)
35  , mIsFinal(false)
36 {
37 }
static const StateId UNDEFINED_ID
Definition: state.h:103

◆ State() [2/2]

fipa::acl::State::State ( const StateId id)

constructor taking the unique name(id) of the state as arguement

Parameters
idintended id for the state

Definition at line 39 of file state.cpp.

40  : mId(uid)
41  , mIsFinal(false)
42 {
43 }

Member Function Documentation

◆ addEmbeddedStateMachine()

void fipa::acl::State::addEmbeddedStateMachine ( fipa::acl::EmbeddedStateMachine  embeddedStateMachine)

Add an embedded state machine.

Definition at line 357 of file state.cpp.

358 {
359  mEmbeddedStateMachines.push_back(embeddedStateMachine);
360 }

◆ addTransition()

Transition fipa::acl::State::addTransition ( const Transition t)

Add a state transition

Returns
Transition with update source state field

Definition at line 45 of file state.cpp.

46 {
47  std::vector<Transition>::const_iterator it;
48  it = std::find(mTransitions.begin(), mTransitions.end(), t);
49  if( it == mTransitions.end())
50  {
51  Transition transition = t;
52  transition.setSourceState(mId);
53  mTransitions.push_back(transition);
54  return transition;
55  } else {
56  return *it;
57  }
58 }
friend class Transition
Definition: state.h:43

◆ consumeSubStateMachineMessage()

void fipa::acl::State::consumeSubStateMachineMessage ( const ACLMessage msg,
const fipa::acl::StateMachine stateMachine,
const fipa::acl::RoleMapping roleMapping,
int  numberOfSubConversations 
)

Tries to consume a message meant for a sub state machine.

Exceptions
runtime_errorif this does not work

Definition at line 147 of file state.cpp.

148 {
149  LOG_INFO("State consumeSubStateMachineMessage");
150 
151  // Loop through all not-ended sub state machines
152  for(std::vector<StateMachine>::iterator it0 = mSubStateMachines.begin(); it0 != mSubStateMachines.end(); it0++)
153  {
154  if(it0->inFinalState() || it0->inFailureState())
155  {
156  // StateMachine ended already
157  continue;
158  }
159  // Test if this StateMachine is correct by maintaining a copy of it
160  StateMachine copy = *it0;
161 
162  // Test the update
163  try {
164  LOG_DEBUG("Trying an existing sub state machine");
165  it0->consumeMessage(msg);
166  // It worked
167  return;
168  } catch(const std::runtime_error& e)
169  {
170  LOG_DEBUG("Sub state machine incorrect: ", e.what());
171  // The state machine was obviously not correct, we play back the copy
172  *it0 = copy;
173  }
174  }
175 
176  LOG_DEBUG("Trying to search for a fitting a embedded state machine");
177 
178  EmbeddedStateMachine* embeddedStateMachinePtr = NULL;
179  // We must be in a state that allows subProtocols
180  std::string protocol = msg.getProtocol();
181 
182  // Search for an embedded state machine with the same protocol
183  std::vector<EmbeddedStateMachine>::iterator it;
184  for(it = mEmbeddedStateMachines.begin(); it != mEmbeddedStateMachines.end(); it++)
185  {
186  // Protocol must match Regex
187  boost::regex peformativeRegex(it->name);
188  if(regex_match(protocol, peformativeRegex))
189  {
190  // Check that the sender role is correct
191  // This throws if the mapping does not exist
192  const AgentIDList l = roleMapping.getMapping().at(it->fromRole);
193  AgentIDList::const_iterator lit = std::find(l.begin(), l.end(), msg.getSender());
194  if(lit == l.end())
195  {
196  // Sender does not match
197  continue;
198  }
199 
200  // Check that the number of subconversations allows another one
201  if(mSubStateMachines.size() >= numberOfSubConversations)
202  {
203  continue;
204  }
205 
206  // This is the right ESM
207  embeddedStateMachinePtr = &(*it);
208  break;
209  }
210  }
211 
212  if(!embeddedStateMachinePtr)
213  {
214  // No fitting running or new embedded state machine found
215  LOG_ERROR("State consumeSubStateMachineMessage: No fitting sub state machine found");
216  throw std::runtime_error("State consumeSubStateMachineMessage: No fitting sub state machine found");
217  }
218 
219  LOG_DEBUG("Found a fitting embedded state machine and will try to create a sub state machine now");
220 
221  // Construct a new state machine with mapped sender role
222  if(!protocol.empty())
223  {
224  // Copy the given state machine
225  StateMachine subStateMachine = stateMachine;
226  subStateMachine.setSelf(msg.getSender());
227 
228  // update the message state machine
229  try {
230  LOG_DEBUG("Substate machine initialized, trying to consume message");
231  subStateMachine.consumeMessage(msg);
232  } catch(const std::runtime_error& e)
233  {
234  // Also constructing and using a new one did not work for that message.
235  std::string errorMsg = "Substatemachine creation failed: ";
236  errorMsg += " -- " + std::string(e.what());
237  throw std::runtime_error(errorMsg);
238  }
239 
240  // If that was successful, save the actual protocol and number of subconversations in the embedded state machine
241  LOG_DEBUG("New sub state machine consumed message");
242  mSubStateMachines.push_back(subStateMachine);
243  embeddedStateMachinePtr->actualProtocol = protocol;
244  embeddedStateMachinePtr->numberOfSubConversations = numberOfSubConversations;
245  } else {
246  LOG_ERROR("Protocol not set");
247  throw std::runtime_error("Protocol not set");
248  }
249 
250  LOG_DEBUG("State consumeSubStateMachineMessage successfully created new sub state machine");
251 }
const std::map< Role, AgentIDList > & getMapping() const
Definition: role.h:114
std::vector< AgentID > AgentIDList
Definition: agent_id.h:20
void setSelf(const AgentID &self)
friend class StateMachine
Definition: state.h:50

◆ generateDefaultTransitions()

void fipa::acl::State::generateDefaultTransitions ( )

method that generates implicit generic transitions applicable to all states, that may or may not be speciffied in the configuration file such as not-understood transition (if it is specified it is not doubled); this method is to be called after all states specified in the configuration have been added to the state machine, preferably after all generic transition have been added as well

Definition at line 60 of file state.cpp.

61 {
62  // Not adding any transition for final states without substatemachines
63  if(isFinal())
64  {
65  if(mEmbeddedStateMachines.empty())
66  {
67  return;
68  }
69  }
70  else if(mTransitions.empty())
71  {
72  throw std::runtime_error("Invalid state: non final state without transition defined");
73  }
74 
75  std::vector<Transition> transitions(mTransitions);
76 
77  std::vector<Transition>::const_iterator it = transitions.begin();
78  for (; it != transitions.end();++it)
79  {
80  // we don't generate a not-understood transition for not-understood message...
81  boost::regex peformativeRegex(it->getPerformativeRegExp());
82  if(regex_match(PerformativeTxt[ACLMessage::NOT_UNDERSTOOD], peformativeRegex))
83  {
84  continue;
85  } else {
86  // Add the not understood transition for every matching transition
87  default_transition::NotUnderstood transitionSender = default_transition::NotUnderstood(it->getSenderRole(), it->getReceiverRole(), mId);
88  addTransition(*dynamic_cast<Transition*>(&transitionSender));
89 
90  default_transition::NotUnderstood transitionReceiver = default_transition::NotUnderstood(it->getReceiverRole(), it->getSenderRole(), mId);
91  addTransition(*dynamic_cast<Transition*>(&transitionReceiver));
92  }
93 
94  if(regex_match(PerformativeTxt[ACLMessage::CANCEL], peformativeRegex))
95  {
96  continue;
97  } else {
98  // Add the cancel transition -- bidirectional regarding receiver/sender role
99  default_transition::ConversationCancelling transitionSender = default_transition::ConversationCancelling(it->getSenderRole(), it->getReceiverRole(), mId);
100  addTransition(*dynamic_cast<Transition*>(&transitionSender));
101 
102  default_transition::ConversationCancelling transitionReceiver = default_transition::ConversationCancelling(it->getReceiverRole(), it->getSenderRole(), mId);
103  addTransition(*dynamic_cast<Transition*>(&transitionReceiver));
104  }
105 
106  if(regex_match(PerformativeTxt[ACLMessage::FAILURE], peformativeRegex))
107  {
108  continue;
109  } else {
110  // Add default failure transition -- which only applies for self as receiver
112  addTransition(*dynamic_cast<Transition*>(&transitionReceiver));
113  }
114  }
115 
116  // Also add default states for each substatemachine that proxies
117  std::vector<EmbeddedStateMachine>::const_iterator it0 = mEmbeddedStateMachines.begin();
118  for (; it0 != mEmbeddedStateMachines.end();++it0)
119  {
120  if(!it0->proxiedTo.empty())
121  {
122  // Add the not understood transition for every matching transition
123  default_transition::NotUnderstood transitionSender0 = default_transition::NotUnderstood(it0->fromRole, it0->proxiedToRole, mId);
124  addTransition(*dynamic_cast<Transition*>(&transitionSender0));
125  default_transition::NotUnderstood transitionReceiver0 = default_transition::NotUnderstood(it0->proxiedToRole, it0->fromRole, mId);
126  addTransition(*dynamic_cast<Transition*>(&transitionReceiver0));
127 
128  // Add the cancel transition -- bidirectional regarding receiver/sender role
129  default_transition::ConversationCancelling transitionSender1 = default_transition::ConversationCancelling(it0->fromRole, it0->proxiedToRole, mId);
130  addTransition(*dynamic_cast<Transition*>(&transitionSender1));
131  default_transition::ConversationCancelling transitionReceiver1 = default_transition::ConversationCancelling(it0->proxiedToRole, it0->fromRole, mId);
132  addTransition(*dynamic_cast<Transition*>(&transitionReceiver1));
133 
134  // Add default failure transition -- which only applies for self as receiver
136  addTransition(*dynamic_cast<Transition*>(&transitionReceiver2));
137  }
138  }
139 }
bool isFinal() const
Definition: state.h:156
friend class default_transition::GeneralFailure
Definition: state.h:48
friend class default_transition::NotUnderstood
Definition: state.h:44
std::map< ACLMessage::Performative, std::string > PerformativeTxt
Definition: acl_message.cpp:15
friend class default_transition::ConversationCancelling
Definition: state.h:45
Transition addTransition(const Transition &t)
Definition: state.cpp:45

◆ getEmbeddedStatemachines()

const std::vector<EmbeddedStateMachine>& fipa::acl::State::getEmbeddedStatemachines ( ) const
inline

Retrieve embedded statemachine.

Returns
list of embedded statemachines

Definition at line 193 of file state.h.

193 { return mEmbeddedStateMachines; }

◆ getId()

std::string fipa::acl::State::getId ( ) const
inline

getter method for the uid field of the class

Definition at line 181 of file state.h.

181 { return mId; }

◆ getSubstateMachineProxiedTransition()

const Transition & fipa::acl::State::getSubstateMachineProxiedTransition ( const ACLMessage msg,
const MessageArchive archive,
const RoleMapping roleMapping 
)

Check whether the received message triggers a substatemachine proxied transition. This method is not const, as the generated transitions will be added when they trigger successfully.

Returns
the transition
Exceptions
runtime_errorif the msg is invalid in the current state

Definition at line 280 of file state.cpp.

281 {
282  if(archive.hasMessages())
283  {
284  const ACLMessage& initiatingMsg = archive.getInitiatingMessage();
285  // If state has substatemachine(s) && substatemachine(s) proxied_to not empty && actual_protocol != inform && response not already received:
286  // Genereate Transition on-the-fly, if posssible
287  std::vector<EmbeddedStateMachine>::iterator it0 = mEmbeddedStateMachines.begin();
288  for (; it0 != mEmbeddedStateMachines.end(); ++it0)
289  {
290  LOG_DEBUG("Checking if a transition needs to be generated");
291  // FIXME there can be other protocols that do not expect any responses
292  if(!it0->proxiedTo.empty() && it0->actualProtocol != "inform" && !it0->receivedProxiedReply )
293  {
294  LOG_DEBUG("Generating a transition");
295  // Generate a transition (any performative, not leaving the state)
296  Transition transition (it0->fromRole, it0->proxiedToRole, ".*", getId(), getId());
297  // And see if it triggers
298  if (transition.triggers(msg, initiatingMsg, roleMapping))
299  {
300  // Save that a proxied reply was received
301  it0->receivedProxiedReply = true;
302  mSubstateMachineProxiedTransitions.push_back(transition);
303  LOG_DEBUG("Transition triggered");
304  // We cannot use the local var to return as a reference
305  return mSubstateMachineProxiedTransitions.back();
306  }
307  }
308  }
309  }
310 
311  throw std::runtime_error("Message does not trigger any (incl. proxied) transitions in this state");
312 }
friend class Transition
Definition: state.h:43
std::string getId() const
getter method for the uid field of the class
Definition: state.h:181

◆ getTransition()

const Transition & fipa::acl::State::getTransition ( const ACLMessage msg,
const MessageArchive archive,
const RoleMapping roleMapping 
) const

Check whether the received message triggers a transition.

Returns
the transition
Exceptions
runtime_errorif the msg is invalid in the current state

Definition at line 253 of file state.cpp.

254 {
255  std::vector<Transition>::const_iterator it = mTransitions.begin();
256  for (; it != mTransitions.end(); ++it)
257  {
258  // TODO: better use the directly corresponding one
259  // but this should be ok for now
260  if(!archive.hasMessages())
261  {
262  // Initiating message, i.e. validation should only apply to performative
263  boost::regex peformativeRegex(it->getPerformativeRegExp());
264  if(regex_match(msg.getPerformative(), peformativeRegex))
265  {
266  return *it;
267  }
268  } else {
269  const ACLMessage& initiatingMsg = archive.getInitiatingMessage();
270  if (it->triggers(msg, initiatingMsg, roleMapping))
271  {
272  return *it;
273  }
274  }
275  }
276 
277  throw std::runtime_error("Message does not trigger any transition in this state");
278 }

◆ getTransitions()

const std::vector<Transition>& fipa::acl::State::getTransitions ( ) const
inline

Retrieve transitions associated with this state

Returns
list of transitions

Definition at line 187 of file state.h.

187 { return mTransitions; }

◆ isDefaultState()

bool fipa::acl::State::isDefaultState ( ) const

Test if state belongs to the default state or not.

Returns
true if state is default, false otherwise

Definition at line 141 of file state.cpp.

142 {
143  std::vector<StateId>::const_iterator cit = std::find(msDefaultStates.begin(), msDefaultStates.end(), mId);
144  return cit != msDefaultStates.end();
145 }

◆ isFinal()

bool fipa::acl::State::isFinal ( ) const
inline

Definition at line 156 of file state.h.

156 { return mIsFinal; }

◆ isFinished()

bool fipa::acl::State::isFinished ( ) const

method that returns whether the state is a finished state or not. In the case of a state with embedded state machines, this is a bit more coplex, see the implementation

Returns
true if state is finished, false otherwise

Definition at line 314 of file state.cpp.

315 {
316  if(!isFinal())
317  {
318  return false;
319  }
320 
321  // Check all subprotocols
322  std::vector<StateMachine>::const_iterator it;
323  for(it = mSubStateMachines.begin(); it != mSubStateMachines.end(); it++)
324  {
325  if(!it->inFinalState() && !it->inFailureState())
326  {
327  LOG_DEBUG("State not finished (subconversation still running)");
328  return false;
329  }
330  }
331 
332  // When there are embedded state machines, they all must have forwarded a proxied reply, if this was
333  // necessary in the first place
334  std::vector<EmbeddedStateMachine>::const_iterator it0 = mEmbeddedStateMachines.begin();
335  for (; it0 != mEmbeddedStateMachines.end(); ++it0)
336  {
337  // They must also all have started enough sub state machines
338  // Check that enough subprotocols have been started
339  if(it0->numberOfSubConversations != mSubStateMachines.size())
340  {
341  LOG_DEBUG("State not finished (subconversation still running)");
342  return false;
343  }
344 
345  // FIXME there can be other protocols that do not expect any responses
346  if(!it0->proxiedTo.empty() && it0->actualProtocol != "inform" && !it0->receivedProxiedReply )
347  {
348  LOG_DEBUG("State not finished (proxied response missing)");
349  return false;
350  }
351  }
352 
353  return true;
354 }
bool isFinal() const
Definition: state.h:156

◆ setFinal()

void fipa::acl::State::setFinal ( bool  final)
inlineprotected

setter method for the final field of the class When changing the final state flag make sure you either remove existing transitions or create the default transition if needed

Parameters
finalChange status of state

Definition at line 97 of file state.h.

97 { mIsFinal = final; }

◆ setId()

void fipa::acl::State::setId ( const StateId id)
inline

setter method for the uid field of the state NOTE: maybe should be taken out and name only be allowed to be set on

construction, as if we rename the state later on the state machine might crash(surely will actually)

Parameters
idto set as id for the state

Definition at line 176 of file state.h.

176 { mId = id; }

◆ toString()

std::string fipa::acl::State::toString ( ) const

Convert state to string representation

Definition at line 362 of file state.cpp.

363 {
364  std::stringstream state;
365  state << "state id: '" << mId << "', final: '" << mIsFinal << "'\n";
366  for(std::vector<Transition>::const_iterator it = mTransitions.begin(); it != mTransitions.end(); ++it)
367  {
368  state << "\t" << it->toString() << "\n";
369  }
370 
371  for(std::vector<EmbeddedStateMachine>::const_iterator it = mEmbeddedStateMachines.begin(); it != mEmbeddedStateMachines.end(); ++it)
372  {
373  state << "\t" << it->toString() << "\n";
374  }
375 
376  return state.str();
377 }

◆ toXML()

std::string fipa::acl::State::toXML ( ) const

Convert state to XML representation

Definition at line 379 of file state.cpp.

380 {
381  std::stringstream ss;;
382  ss << "<state id=\"" << mId << "\"";
383  if(mIsFinal)
384  {
385  ss << " final=\"yes\" /";
386  }
387  ss << ">" << std::endl;
388 
389  for(std::vector<Transition>::const_iterator it = mTransitions.begin(); it != mTransitions.end(); ++it)
390  {
391  ss << "\t" << it->toXML() << "\n";
392  }
393 
394  for(std::vector<EmbeddedStateMachine>::const_iterator it = mEmbeddedStateMachines.begin(); it != mEmbeddedStateMachines.end(); ++it)
395  {
396  ss << "\t" << it->toXML() << "\n";
397  }
398 
399  return ss.str();
400 }

Friends And Related Function Documentation

◆ default_transition::ConversationCancelFailure

Definition at line 47 of file state.h.

◆ default_transition::ConversationCancelling

Definition at line 45 of file state.h.

◆ default_transition::ConversationCancelSuccess

Definition at line 46 of file state.h.

◆ default_transition::GeneralFailure

Definition at line 48 of file state.h.

◆ default_transition::NotUnderstood

friend class default_transition::NotUnderstood
friend

Definition at line 44 of file state.h.

◆ StateMachine

friend class StateMachine
friend

Definition at line 50 of file state.h.

◆ StateMachineReader

friend class StateMachineReader
friend

Definition at line 49 of file state.h.

◆ Transition

friend class Transition
friend

Definition at line 43 of file state.h.

Member Data Documentation

◆ CONVERSATION_CANCEL_FAILURE

const StateId fipa::acl::State::CONVERSATION_CANCEL_FAILURE = "__internal_state:conversation_cancel_failure__"
static

Definition at line 107 of file state.h.

◆ CONVERSATION_CANCEL_SUCCESS

const StateId fipa::acl::State::CONVERSATION_CANCEL_SUCCESS = "__internal_state:conversation_cancel_success__"
static

Definition at line 106 of file state.h.

◆ CONVERSATION_CANCELLING

const StateId fipa::acl::State::CONVERSATION_CANCELLING = "__internal_state:conversation_cancelling__"
static

Definition at line 105 of file state.h.

◆ GENERAL_FAILURE_STATE

const StateId fipa::acl::State::GENERAL_FAILURE_STATE = "__internal_state:general_failure__"
static

Definition at line 108 of file state.h.

◆ NOT_UNDERSTOOD

const StateId fipa::acl::State::NOT_UNDERSTOOD = "__internal_state:not_understood__"
static

Definition at line 104 of file state.h.

◆ UNDEFINED_ID

const StateId fipa::acl::State::UNDEFINED_ID = "__undefined__"
static

Default states

Definition at line 103 of file state.h.


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