00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifdef _MSC_VER
00014 #pragma warning( disable : 4786 ) // 'identifier' : identifier was truncated to 'number' characters in the debug information
00015
00016
00017 #pragma warning( disable : 4251 ) // 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
00018 #endif
00019 #ifdef __INTEL_COMPILER
00020 #pragma warning( disable : 985 ) // == C4786
00021 #endif
00022
00023 #include "FSM.h"
00024 #include "FiniteStateMachine-config.h"
00025 #include "FSMErrorCodes.h"
00026
00027 namespace FSM {
00028
00029 static const char* FSM_PARAM_TOSTATE = "ToState";
00030
00031
00032 const string ClassName = "CFSMTransition";
00033
00035
00037
00038 :m_Event("ANY")
00039 ,m_FromState("")
00040 {
00041 }
00042
00043 CFSMTransition::~CFSMTransition()
00044 {
00045 for(Condition_List::iterator i = m_Conditions.begin() ; i != m_Conditions.end() ; ++i)
00046 {
00047 (*i)->DeleteThis();
00048 }
00049
00050 for(Action_List::iterator j = m_Actions.begin() ; j != m_Actions.end() ; ++j)
00051 {
00052 (*j)->DeleteThis();
00053 }
00054
00055 m_Actions.clear();
00056 m_Conditions.clear();
00057 m_Event="ANY";
00058 m_FromState = "";
00059 }
00060
00062
00064
00065 {
00066 CFSMAction *action;
00067
00068 action = (CFSMAction *)GetFSM()->Create(className);
00069 if(action==NULL)
00070 {
00071 iRethrow();
00072 return NULL;
00073 }
00074
00075 m_Actions.push_back(action);
00076 return action;
00077 }
00078
00079 CFSMAction* CFSMTransition::GetAction(int index) const
00080 {
00081 CFSMAction* res = NULL;
00082 Action_List::const_iterator item = m_Actions.begin();
00083 int n=0;
00084 for (n=0; n<index; ++n)
00085 {
00086 if(item==m_Actions.end()) break;
00087 ++item;
00088 }
00089 if (item!=m_Actions.end())
00090 {
00091 res = (*item);
00092 }
00093 if (!res)
00094 {
00095 iThrow(CRITICAL(FSM_ACTION_NOT_FOUND));
00096 }
00097 return res;
00098 }
00099
00100 bool CFSMTransition::DeleteAction(CFSMAction *action)
00101 {
00102 bool res = false;
00103 Action_List::iterator i = m_Actions.begin();
00104 while(!(i==m_Actions.end()))
00105 {
00106 if ((*i)==action)
00107 {
00108 (*i)->DeleteThis();
00109 m_Actions.erase(i);
00110 res = true;
00111 break;
00112 }
00113 ++i;
00114 }
00115 if(!res)
00116 {
00117 iThrow(CRITICAL(FSM_ACTION_NOT_FOUND));
00118 }
00119 return res;
00120 }
00121
00122 Action_List::const_iterator CFSMTransition::GetActionsBegin() const
00123 {
00124 return m_Actions.begin();
00125 }
00126
00127 Action_List::const_iterator CFSMTransition::GetActionsEnd() const
00128 {
00129 return m_Actions.end();
00130 }
00131
00133
00135
00136 {
00137 CFSMCondition *condition;
00138
00139 condition = (CFSMCondition *)GetFSM()->Create(className);
00140 if(condition==NULL)
00141 {
00142 iRethrow();
00143 return NULL;
00144 }
00145
00146 m_Conditions.push_back(condition);
00147 return condition;
00148 }
00149
00150 CFSMCondition* CFSMTransition::GetCondition(int index) const
00151 {
00152 CFSMCondition* res = NULL;
00153 Condition_List::const_iterator item = m_Conditions.begin();
00154 int n=0;
00155 for (n=0; n<index; ++n)
00156 {
00157 if(item==m_Conditions.end()) break;
00158 ++item;
00159 }
00160 if (item!=m_Conditions.end())
00161 {
00162 res = (*item);
00163 }
00164 if (!res)
00165 {
00166 iThrow(CRITICAL(FSM_ACTION_NOT_FOUND));
00167 }
00168 return res;
00169 }
00170
00171 bool CFSMTransition::DeleteCondition(CFSMCondition *condition)
00172 {
00173 bool res = false;
00174 Condition_List::iterator i = m_Conditions.begin();
00175 while(!(i==m_Conditions.end()))
00176 {
00177 if ((*i)==condition)
00178 {
00179 (*i)->DeleteThis();
00180 m_Conditions.erase(i);
00181 res = true;
00182 break;
00183 }
00184 ++i;
00185 }
00186 if(!res)
00187 {
00188 iThrow(CRITICAL(FSM_CONDITION_NOT_FOUND));
00189 }
00190 return res;
00191 }
00192
00193 Condition_List::const_iterator CFSMTransition::GetConditionsBegin() const
00194 {
00195 return m_Conditions.begin();
00196 }
00197
00198 Condition_List::const_iterator CFSMTransition::GetConditionsEnd() const
00199 {
00200 return m_Conditions.end();
00201 }
00202
00204
00206
00207 {
00208 m_FromState = stateName;
00209 }
00210
00211 void CFSMTransition::SetOnEvent(const char *event)
00212 {
00213 m_Event = event;
00214 }
00215
00216 CFSMState* CFSMTransition::GetFromState() const
00217 {
00218 CFSMState *res = NULL;
00219 res = GetFSM()->GetState(m_FromState.c_str());
00220 if (!res)
00221 {
00222 iRethrow();
00223 }
00224 return res;
00225 }
00226
00227 const char* CFSMTransition::GetOnEvent() const
00228 {
00229 if (m_Event.empty()) return "";
00230 else return m_Event.c_str();
00231 }
00232
00234
00236
00237 {
00238 bool res=true;
00239 retval=true;
00240
00241 if (m_Event.empty())
00242 {
00243 iThrow(WARNING(FSM_PARAM_NOT_SET), "OnEvent", GetNameOfClass());
00244 return false;
00245 }
00246 if (m_Event!="ANY" && m_Event!=event)
00247 {
00248 retval = false;
00249 return true;
00250 }
00251
00252 for(Condition_List::iterator i = m_Conditions.begin() ; i != m_Conditions.end() ; ++i)
00253 {
00254 retval = (*i)->CheckCondition(event, a, b);
00255 if(retval==false)
00256 {
00257 break;
00258 }
00259 }
00260 return res;
00261 }
00262
00263 bool CFSMTransition::Execute(const char* event, void* a, void* b)
00264 {
00265 bool res = true;
00266
00267
00268 Action_List::const_iterator j = m_Actions.begin();
00269 while(!(j==m_Actions.end()))
00270 {
00271 res = (*j)->Execute(event, a, b);
00272 if (!res)
00273 {
00274 iRethrow();
00275 break;
00276 }
00277 ++j;
00278 }
00279
00280 return res;
00281 }
00282
00284
00286
00287 {
00288 bool res = true;
00289 for(Condition_List::iterator i = m_Conditions.begin() ; i != m_Conditions.end() ; ++i)
00290 {
00291 res = (*i)->Activate();
00292 if(!res)
00293 {
00294 iRethrow();
00295 break;
00296 }
00297 }
00298 return res;
00299 }
00300
00301 bool CFSMTransition::Deactivate()
00302 {
00303 bool res = true;
00304 for(Condition_List::iterator i = m_Conditions.begin() ; i != m_Conditions.end() ; ++i)
00305 {
00306 res = (*i)->Deactivate();
00307 if(!res)
00308 {
00309 iRethrow();
00310 break;
00311 }
00312 }
00313 return res;
00314 }
00315
00318
00320
00322
00323 :m_ToState("")
00324 {
00325 }
00326
00327 CFSMSimpleTransition::~CFSMSimpleTransition()
00328 {
00329 m_ToState = "";
00330 }
00331
00333
00335
00336 void CFSMSimpleTransition::SetToState(const char *stateName)
00337 {
00338 m_ToState = stateName;
00339 }
00340
00341 CFSMState*
00342 CFSMSimpleTransition::GetToState() const
00343 {
00344 CFSMState *res = NULL;
00345 if (m_ToState.empty())
00346 {
00347 res = GetFSM()->GetState(GetFromState()->GetName());
00348 } else
00349 {
00350 res = GetFSM()->GetState(m_ToState.c_str());
00351 }
00352 if (!res)
00353 {
00354 iRethrow();
00355 }
00356 return res;
00357 }
00358
00359
00361
00363
00364 {
00365 if (!out->SaveParameter(FSM_PARAM_TOSTATE, GetToState()->GetName())) {iRethrow(); return false;}
00366 return true;
00367 }
00368
00369 bool CFSMSimpleTransition::SetParameter(const char* paramName, const char* paramValue)
00370 {
00371 bool res = false;
00372 if (strcmp(paramName, FSM_PARAM_TOSTATE)==0)
00373 {
00374 SetToState(paramValue);
00375 res = true;
00376 } else
00377
00378 {
00379 iThrow(CRITICAL(FSM_UNKNOWN_PARAM), paramName, GetNameOfClass());
00380 }
00381 return res;
00382 }
00383
00385
00387
00388 bool CFSMSimpleTransition::Execute(const char* event, void* a, void* b)
00389 {
00390 bool res = CFSMTransition::Execute(event, a, b);
00391 if (res)
00392 {
00393
00394 CFSMState *newState = GetToState();
00395 if (newState)
00396 {
00397 if( ! GetFSM()->SwitchToState( newState ) )
00398 {
00399 iRethrow();
00400 }
00401 } else
00402 {
00403 iRethrow();
00404 }
00405 } else
00406 {
00407 iRethrow();
00408 }
00409
00410 return res;
00411 }
00412
00414
00416
00417 {
00418 return new CFSMSimpleTransition;
00419 }
00420
00421 void CFSMSimpleTransition::DeleteThis()
00422 {
00423 delete this;
00424 }
00425
00428
00430
00432
00433 {
00434 }
00435
00436 CFSMPushTransition::~CFSMPushTransition()
00437 {
00438 }
00439
00440
00442
00444
00446
00448
00449 bool CFSMPushTransition::Execute(const char* event, void* a, void* b)
00450 {
00451 bool res = CFSMTransition::Execute(event, a, b);
00452 if (res)
00453 {
00454
00455 CFSMState *newState = GetToState();
00456 if (newState)
00457 {
00458 if( ! GetFSM()->PushState( newState ) )
00459 {
00460 iRethrow();
00461 }
00462 } else
00463 {
00464 iRethrow();
00465 }
00466 } else
00467 {
00468 iRethrow();
00469 }
00470
00471 return res;
00472 }
00473
00475
00477
00478 {
00479 return new CFSMPushTransition;
00480 }
00481
00482 void CFSMPushTransition::DeleteThis()
00483 {
00484 delete this;
00485 }
00486
00489
00491
00493
00494 {
00495 }
00496
00497 CFSMPopTransition::~CFSMPopTransition()
00498 {
00499 }
00500
00501
00503
00505
00507
00509
00510 bool CFSMPopTransition::Execute(const char* event, void* a, void* b)
00511 {
00512 bool res = CFSMTransition::Execute(event, a, b);
00513 if (res)
00514 {
00515
00516 if( ! GetFSM()->PopState() )
00517 {
00518 iRethrow();
00519 }
00520 } else
00521 {
00522 iRethrow();
00523 }
00524
00525 return res;
00526 }
00527
00529
00531
00532 {
00533 return new CFSMPopTransition;
00534 }
00535
00536 void CFSMPopTransition::DeleteThis()
00537 {
00538 delete this;
00539 }
00541
00542 };
00543