fipa_acl  1.4
transition.cpp
Go to the documentation of this file.
1 
2 #include "transition.h"
3 #include "state.h"
4 #include "statemachine.h"
5 
6 #include <iostream>
7 #include <stdexcept>
8 #include <boost/regex.hpp>
9 #include <base-logging/Logging.hpp>
10 
11 namespace fipa {
12 namespace acl {
13 
15  : mSenderRole()
16  , mReceiverRole()
17  , mPerformativeRegExp()
18  , mSourceStateId()
19  , mTargetStateId()
20 {
21 }
22 
23 Transition::Transition(const Role& senderRole, const Role& receiverRole, const fipa::acl::ACLMessage::Performative& performative, const fipa::acl::StateId& sourceState, const fipa::acl::StateId& targetState)
24  : mSenderRole(senderRole)
25  , mReceiverRole(receiverRole)
26  , mPerformativeRegExp(PerformativeTxt[performative])
27  , mSourceStateId(sourceState)
28  , mTargetStateId(targetState)
29 {
30 }
31 
32 
33 Transition::Transition(const Role& senderRole, const Role& receiverRole, const std::string& performativeRegExp, const StateId& sourceState, const StateId& targetState)
34  : mSenderRole(senderRole)
35  , mReceiverRole(receiverRole)
36  , mPerformativeRegExp(performativeRegExp)
37  , mSourceStateId(sourceState)
38  , mTargetStateId(targetState)
39 {
40 }
41 
42 bool Transition::triggers(const ACLMessage& msg, const ACLMessage& initiatingMsg, const RoleMapping& roleMapping) const
43 {
44  // Set the standard validation flags
46  if( validateMessage(msg, initiatingMsg, roleMapping, flags) )
47  {
48  return true;
49  } else {
50  LOG_DEBUG("Message validation failed: message does not apply to transition");
51  }
52  return false;
53 }
54 
55 bool Transition::validateMessage(const ACLMessage& msg, const ACLMessage& validatorMsg, const RoleMapping& roleMapping, validation::Flags flags) const
56 {
57  if( flags == validation::NONE)
58  {
59  return true;
60  }
61 
62  // Test performative against transition performative
63  // not the validator message one
64  if (validation::PERFORMATIVE & flags)
65  {
66  boost::regex performativeRegex(mPerformativeRegExp);
67  if(!regex_match(msg.getPerformative(), performativeRegex))
68  {
69  LOG_DEBUG("Performative validation failed: was '%s' but expected: '%s'", msg.getPerformative().c_str(), mPerformativeRegExp.c_str());
70  return false;
71  }
72  }
73 
74  if( validation::SENDER & flags)
75  {
76  AgentID senderAgent = msg.getSender();
77  if(!roleMapping.isExpected(mSenderRole, senderAgent))
78  {
79  LOG_DEBUG("Sender validation failed: '%s' unexpected for role '%s'", senderAgent.getName().c_str(), mSenderRole.getId().c_str());
80  return false;
81  }
82  }
83 
84  if(validation::RECEIVERS & flags)
85  {
86  if(!validateReceivers(msg, roleMapping))
87  {
88  LOG_DEBUG("Receivers validation failed");
89  return false;
90  }
91  }
92 
93  if(validation::CONVERSATION_ID & flags)
94  {
95  if (msg.getConversationID() != validatorMsg.getConversationID())
96  {
97  LOG_DEBUG("ConversationID validation failed: was '%s' but expected: '%s'", msg.getConversationID().c_str(), validatorMsg.getConversationID().c_str());
98  return false;
99  }
100  }
101 
102  if(validation::PROTOCOL & flags)
103  {
104  if (msg.getProtocol() != validatorMsg.getProtocol())
105  {
106  LOG_DEBUG("Protocol validation failed: was '%s' but expected: '%s'", msg.getProtocol().c_str(), validatorMsg.getProtocol().c_str());
107  return false;
108  }
109  }
110 
111  if(validation::ENCODING & flags)
112  {
113  if (msg.getEncoding() != validatorMsg.getEncoding())
114  {
115  LOG_DEBUG("Encoding validation failed: was '%s' but expected: '%s'", msg.getEncoding().c_str(), validatorMsg.getEncoding().c_str());
116  return false;
117  }
118  }
119 
120  if(validation::LANGUAGE & flags)
121  {
122  if (msg.getLanguage() != validatorMsg.getLanguage())
123  {
124  LOG_DEBUG("Language validation failed: was '%s' but expected: '%s'", msg.getLanguage().c_str(), validatorMsg.getLanguage().c_str());
125  return false;
126  }
127  }
128 
129  if(validation::ONTOLOGY & flags)
130  {
131  if (msg.getOntology() != validatorMsg.getOntology())
132  {
133  LOG_DEBUG("Ontology validation failed: was '%s' but expected: '%s'", msg.getOntology().c_str(), validatorMsg.getOntology().c_str());
134  return false;
135  }
136  }
137 
138  if(validation::IN_REPLY_TO & flags)
139  {
140  if (msg.getInReplyTo() != validatorMsg.getInReplyTo())
141  {
142  LOG_DEBUG("InReplyTo validation failed: was '%s' but expected: '%s'", msg.getInReplyTo().c_str(), validatorMsg.getInReplyTo().c_str());
143  return false;
144  }
145  }
146 
147  return true;
148 }
149 
150 std::string Transition::toString() const
151 {
152  std::stringstream transition;
153  transition << "transition: sender role: '" << mSenderRole.getId() << "', ";
154  transition << "receiver role: '" << mReceiverRole.getId() << "', ";
155  transition << "performative: '" << mPerformativeRegExp << "', ";
156  transition << "source state: '" << mSourceStateId << "', ";
157  transition << "target state: '" << mTargetStateId << "'";
158 
159  return transition.str();
160 }
161 
162 std::string Transition::toXML() const
163 {
164  std::stringstream transition;
165  transition << "<transition ";
166  transition << "performative=\"" << mPerformativeRegExp << "\" ";
167  transition << "from=\"" << mSenderRole.getId() << "\" ";
168  transition << "to=\"" << mReceiverRole.getId() << "\" ";
169  transition << "target=\"" << mTargetStateId << "\" ";
170  transition << "/>";
171 
172  return transition.str();
173 }
174 
175 bool Transition::validateReceivers(const ACLMessage& msg, const RoleMapping& roleMapping) const
176 {
177  AgentIDList actualReceivers = msg.getAllReceivers();
178  if(actualReceivers.empty())
179  {
180  std::string errorMsg = "No receivers set for this message: conversation id: " + msg.getConversationID() + " sender: " + msg.getSender().getName();
181  LOG_ERROR("%s",errorMsg.c_str());
182  throw std::runtime_error(errorMsg);
183  }
184 
185  // Test whether the actual receivers are expected -- according to the current role to agent mapping
186  AgentIDList::const_iterator ait = actualReceivers.begin();
187  for(; ait != actualReceivers.end(); ++ait)
188  {
189  if(!roleMapping.isExpected(mReceiverRole, *ait))
190  {
191  return false;
192  }
193  }
194 
195  return true;
196 }
197 
198 bool Transition::operator==(const Transition& other) const
199 {
200  if(mSourceStateId != other.mSourceStateId)
201  {
202  return false;
203  } else if (mTargetStateId != other.mTargetStateId)
204  {
205  return false;
206  } else if (mSenderRole != other.mSenderRole)
207  {
208  return false;
209  } else if (mReceiverRole != other.mReceiverRole)
210  {
211  return false;
212  } else if (mPerformativeRegExp != other.mPerformativeRegExp)
213  {
214  return false;
215  }
216 
217  return true;
218 }
219 
220 // FIPA include definitions of some default protocol elements
221 // This library considers not-understood and cancel interaction-protocol as
222 // default ones and embeds them into the standard construction of the state machine
223 namespace default_transition
224 {
225 
226 NotUnderstood::NotUnderstood(const Role& senderRole, const Role& receiverRole, const StateId& sourceState)
227  : Transition(senderRole, receiverRole, ACLMessage::NOT_UNDERSTOOD, sourceState, State::NOT_UNDERSTOOD)
228 {
229 }
230 
231 ConversationCancelling::ConversationCancelling(const Role& senderRole, const Role& receiverRole, const StateId& sourceState)
232  : Transition(senderRole, receiverRole, ACLMessage::CANCEL, sourceState, State::CONVERSATION_CANCELLING)
233 {
234 }
235 
236 // We loosen the role restriction here, to facilitate the integrating of the default states -- now we just need
237 // one state per direction (which works multidirectional)
238 // TODO: consider solving this issue using an embedded state machine
240  : Transition( Role(".*"), Role(".*"), ACLMessage::INFORM, State::CONVERSATION_CANCELLING, State::CONVERSATION_CANCEL_SUCCESS)
241 {
242 }
243 
245  : Transition(Role(".*"), Role(".*"), ACLMessage::FAILURE, State::CONVERSATION_CANCELLING, State::CONVERSATION_CANCEL_FAILURE)
246 {
247 }
248 
250  : Transition(Role(".*"), SelfRole(), ACLMessage::FAILURE, sourceState, State::GENERAL_FAILURE_STATE)
251 {}
252 
253 }
254 
255 } // end of acl
256 } // end of fipa
std::string getEncoding() const
Definition: acl_message.h:258
describes the structure and operation of a transition of the state machine
implements a state of the StateMachine class
Definition: state.h:41
GeneralFailure(const StateId &sourceState)
Definition: transition.cpp:249
bool operator==(const Transition &t) const
Definition: transition.cpp:198
describes the structure and operation of a state machine
std::string toString() const
Definition: transition.cpp:150
const std::string & getName() const
setter and getter methods for all fields; they do not result in deep-copies assignments/retreivals, but this can be easily changed if needed through the overloaded operator which do
Definition: agent_id.h:90
std::string StateId
Definition: state.h:35
std::string getPerformative() const
Definition: acl_message.h:139
std::string toXML() const
Definition: transition.cpp:162
std::vector< AgentID > AgentIDList
Definition: agent_id.h:20
std::string getOntology() const
Definition: acl_message.h:248
bool triggers(const ACLMessage &msg, const ACLMessage &initiatingMsg, const RoleMapping &roleMapping) const
check whether a certain message trigger the execution of the transition
Definition: transition.cpp:42
Performative
an enum of all the predefined fipa message performatives so far, presented in the order used in the m...
Definition: acl_message.h:64
Mapping between roles and actual agent ids.
Definition: role.h:98
std::string getLanguage() const
Definition: acl_message.h:268
std::string getInReplyTo() const
Definition: acl_message.h:207
std::map< ACLMessage::Performative, std::string > PerformativeTxt
Definition: acl_message.cpp:15
AgentID getSender() const
Definition: acl_message.h:311
std::string getProtocol() const
Definition: acl_message.h:238
RoleId getId() const
Definition: role.h:52
describes the structure and operation of a state, as part of a state machine
This class provides a representation of a message conforming to the FIPA specification SC00061...
Definition: acl_message.h:55
bool validateMessage(const ACLMessage &msg, const ACLMessage &validatorMsg, const RoleMapping &roleMapping, validation::Flags flags=validation::ALL) const
method that validates all parameters of a message
Definition: transition.cpp:55
NotUnderstood(const Role &senderRole, const Role &receiverRole, const StateId &stateId)
Definition: transition.cpp:226
ConversationCancelling(const Role &senderRole, const Role &receiverRole, const StateId &stateId)
Definition: transition.cpp:231
Transition()
empty constructor for the transition class; initializes fields
Definition: transition.cpp:14
bool isExpected(const Role &role, const AgentID &agent) const
Definition: role.cpp:120
Implements the general AgentID functionality, which is present throughout the fipa specifications(FIP...
Definition: agent_id.h:37
AgentIDList getAllReceivers() const
Definition: acl_message.h:166
std::string getConversationID() const
Definition: acl_message.h:227