7 #include <boost/assign/list_of.hpp>
8 #include <boost/regex.hpp>
12 #include <base-logging/Logging.hpp>
24 std::vector<StateId> State::msDefaultStates = boost::assign::list_of
34 : mId(
State::UNDEFINED_ID)
47 std::vector<Transition>::const_iterator it;
48 it = std::find(mTransitions.begin(), mTransitions.end(), t);
49 if( it == mTransitions.end())
53 mTransitions.push_back(transition);
65 if(mEmbeddedStateMachines.empty())
70 else if(mTransitions.empty())
72 throw std::runtime_error(
"Invalid state: non final state without transition defined");
75 std::vector<Transition> transitions(mTransitions);
77 std::vector<Transition>::const_iterator it = transitions.begin();
78 for (; it != transitions.end();++it)
81 boost::regex peformativeRegex(it->getPerformativeRegExp());
91 addTransition(*dynamic_cast<Transition*>(&transitionReceiver));
100 addTransition(*dynamic_cast<Transition*>(&transitionSender));
103 addTransition(*dynamic_cast<Transition*>(&transitionReceiver));
112 addTransition(*dynamic_cast<Transition*>(&transitionReceiver));
117 std::vector<EmbeddedStateMachine>::const_iterator it0 = mEmbeddedStateMachines.begin();
118 for (; it0 != mEmbeddedStateMachines.end();++it0)
120 if(!it0->proxiedTo.empty())
124 addTransition(*dynamic_cast<Transition*>(&transitionSender0));
126 addTransition(*dynamic_cast<Transition*>(&transitionReceiver0));
130 addTransition(*dynamic_cast<Transition*>(&transitionSender1));
132 addTransition(*dynamic_cast<Transition*>(&transitionReceiver1));
136 addTransition(*dynamic_cast<Transition*>(&transitionReceiver2));
143 std::vector<StateId>::const_iterator cit = std::find(msDefaultStates.begin(), msDefaultStates.end(), mId);
144 return cit != msDefaultStates.end();
149 LOG_INFO(
"State consumeSubStateMachineMessage");
152 for(std::vector<StateMachine>::iterator it0 = mSubStateMachines.begin(); it0 != mSubStateMachines.end(); it0++)
154 if(it0->inFinalState() || it0->inFailureState())
164 LOG_DEBUG(
"Trying an existing sub state machine");
165 it0->consumeMessage(msg);
168 }
catch(
const std::runtime_error& e)
170 LOG_DEBUG(
"Sub state machine incorrect: ", e.what());
176 LOG_DEBUG(
"Trying to search for a fitting a embedded state machine");
183 std::vector<EmbeddedStateMachine>::iterator it;
184 for(it = mEmbeddedStateMachines.begin(); it != mEmbeddedStateMachines.end(); it++)
187 boost::regex peformativeRegex(it->name);
188 if(regex_match(protocol, peformativeRegex))
193 AgentIDList::const_iterator lit = std::find(l.begin(), l.end(), msg.
getSender());
201 if(mSubStateMachines.size() >= numberOfSubConversations)
207 embeddedStateMachinePtr = &(*it);
212 if(!embeddedStateMachinePtr)
215 LOG_ERROR(
"State consumeSubStateMachineMessage: No fitting sub state machine found");
216 throw std::runtime_error(
"State consumeSubStateMachineMessage: No fitting sub state machine found");
219 LOG_DEBUG(
"Found a fitting embedded state machine and will try to create a sub state machine now");
222 if(!protocol.empty())
230 LOG_DEBUG(
"Substate machine initialized, trying to consume message");
232 }
catch(
const std::runtime_error& e)
235 std::string errorMsg =
"Substatemachine creation failed: ";
236 errorMsg +=
" -- " + std::string(e.what());
237 throw std::runtime_error(errorMsg);
241 LOG_DEBUG(
"New sub state machine consumed message");
242 mSubStateMachines.push_back(subStateMachine);
246 LOG_ERROR(
"Protocol not set");
247 throw std::runtime_error(
"Protocol not set");
250 LOG_DEBUG(
"State consumeSubStateMachineMessage successfully created new sub state machine");
255 std::vector<Transition>::const_iterator it = mTransitions.begin();
256 for (; it != mTransitions.end(); ++it)
263 boost::regex peformativeRegex(it->getPerformativeRegExp());
270 if (it->triggers(msg, initiatingMsg, roleMapping))
277 throw std::runtime_error(
"Message does not trigger any transition in this state");
287 std::vector<EmbeddedStateMachine>::iterator it0 = mEmbeddedStateMachines.begin();
288 for (; it0 != mEmbeddedStateMachines.end(); ++it0)
290 LOG_DEBUG(
"Checking if a transition needs to be generated");
292 if(!it0->proxiedTo.empty() && it0->actualProtocol !=
"inform" && !it0->receivedProxiedReply )
294 LOG_DEBUG(
"Generating a transition");
298 if (transition.
triggers(msg, initiatingMsg, roleMapping))
301 it0->receivedProxiedReply =
true;
302 mSubstateMachineProxiedTransitions.push_back(transition);
303 LOG_DEBUG(
"Transition triggered");
305 return mSubstateMachineProxiedTransitions.back();
311 throw std::runtime_error(
"Message does not trigger any (incl. proxied) transitions in this state");
322 std::vector<StateMachine>::const_iterator it;
323 for(it = mSubStateMachines.begin(); it != mSubStateMachines.end(); it++)
325 if(!it->inFinalState() && !it->inFailureState())
327 LOG_DEBUG(
"State not finished (subconversation still running)");
334 std::vector<EmbeddedStateMachine>::const_iterator it0 = mEmbeddedStateMachines.begin();
335 for (; it0 != mEmbeddedStateMachines.end(); ++it0)
339 if(it0->numberOfSubConversations != mSubStateMachines.size())
341 LOG_DEBUG(
"State not finished (subconversation still running)");
346 if(!it0->proxiedTo.empty() && it0->actualProtocol !=
"inform" && !it0->receivedProxiedReply )
348 LOG_DEBUG(
"State not finished (proxied response missing)");
359 mEmbeddedStateMachines.push_back(embeddedStateMachine);
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)
368 state <<
"\t" << it->toString() <<
"\n";
371 for(std::vector<EmbeddedStateMachine>::const_iterator it = mEmbeddedStateMachines.begin(); it != mEmbeddedStateMachines.end(); ++it)
373 state <<
"\t" << it->toString() <<
"\n";
381 std::stringstream ss;;
382 ss <<
"<state id=\"" << mId <<
"\"";
385 ss <<
" final=\"yes\" /";
387 ss <<
">" << std::endl;
389 for(std::vector<Transition>::const_iterator it = mTransitions.begin(); it != mTransitions.end(); ++it)
391 ss <<
"\t" << it->toXML() <<
"\n";
394 for(std::vector<EmbeddedStateMachine>::const_iterator it = mEmbeddedStateMachines.begin(); it != mEmbeddedStateMachines.end(); ++it)
396 ss <<
"\t" << it->toXML() <<
"\n";
412 namespace default_state {
419 addTransition(*dynamic_cast<Transition*>(&transitionSuccess));
422 addTransition(*dynamic_cast<Transition*>(&transitionFailure));
void consumeMessage(const ACLMessage &msg)
describes the structure and operation of a transition of the state machine
std::string actualProtocol
void addEmbeddedStateMachine(fipa::acl::EmbeddedStateMachine embeddedStateMachine)
implements a state of the StateMachine class
bool isFinished() const
method that returns whether the state is a finished state or not. In the case of a state with embedde...
static const StateId GENERAL_FAILURE_STATE
describes the structure and operation of a state machine
static const StateId CONVERSATION_CANCEL_FAILURE
static const StateId CONVERSATION_CANCELLING
FinalState(const StateId &id)
void setSourceState(const StateId &stateId)
const ACLMessage & getInitiatingMessage() const
const Transition & getTransition(const ACLMessage &msg, const MessageArchive &archive, const RoleMapping &roleMapping) const
Check whether the received message triggers a transition.
State()
empty constructor initializes default fields
std::string getPerformative() const
void consumeSubStateMachineMessage(const ACLMessage &msg, const fipa::acl::StateMachine &stateMachine, const fipa::acl::RoleMapping &roleMapping, int numberOfSubConversations)
std::string getId() const
getter method for the uid field of the class
void generateDefaultTransitions()
method that generates implicit generic transitions applicable to all states, that may or may not be s...
std::vector< AgentID > AgentIDList
bool triggers(const ACLMessage &msg, const ACLMessage &initiatingMsg, const RoleMapping &roleMapping) const
check whether a certain message trigger the execution of the transition
void setSelf(const AgentID &self)
void setFinal(bool final)
setter method for the final field of the class When changing the final state flag make sure you eithe...
Mapping between roles and actual agent ids.
An embedded state machine with mappings.
std::string toString() const
std::map< ACLMessage::Performative, std::string > PerformativeTxt
AgentID getSender() const
std::string getProtocol() const
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...
std::string toXML() const
static const StateId CONVERSATION_CANCEL_SUCCESS
static const StateId UNDEFINED_ID
static const StateId NOT_UNDERSTOOD
const std::map< Role, AgentIDList > & getMapping() const
Transition addTransition(const Transition &t)
int numberOfSubConversations
const Transition & getSubstateMachineProxiedTransition(const ACLMessage &msg, const MessageArchive &archive, const RoleMapping &roleMapping)
Check whether the received message triggers a substatemachine proxied transition. This method is not ...
bool isDefaultState() const
Test if state belongs to the default state or not.