00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mitkStateMachineFactory.h"
00019 #include "mitkGlobalInteraction.h"
00020 #include <vtkXMLDataElement.h>
00021 #include <mitkProperties.h>
00022 #include <mitkStringProperty.h>
00023 #include <mitkConfig.h>
00024 #include <mitkStandardFileLocations.h>
00025
00030
00031
00032
00033
00034
00035 const std::string STYLE = "STYLE";
00036 const std::string NAME = "NAME";
00037 const std::string ID = "ID";
00038 const std::string START_STATE = "START_STATE";
00039 const std::string NEXT_STATE_ID = "NEXT_STATE_ID";
00040 const std::string EVENT_ID = "EVENT_ID";
00041 const std::string SIDE_EFFECT_ID = "SIDE_EFFECT_ID";
00042 const std::string ISTRUE = "TRUE";
00043 const std::string ISFALSE = "FALSE";
00044 const std::string STATE_MACHINE = "stateMachine";
00045 const std::string STATE = "state";
00046 const std::string TRANSITION = "transition";
00047 const std::string STATE_MACHINE_NAME = "stateMachine";
00048 const std::string ACTION = "action";
00049 const std::string BOOL_PARAMETER = "boolParameter";
00050 const std::string INT_PARAMETER = "intParameter";
00051 const std::string FLOAT_PARAMETER = "floatParameter";
00052 const std::string DOUBLE_PARAMETER = "doubleParameter";
00053 const std::string STRING_PARAMETER = "stringParameter";
00054 const std::string VALUE = "VALUE";
00055
00056 #include <vtkObjectFactory.h>
00057 namespace mitk
00058 {
00059 vtkStandardNewMacro(StateMachineFactory);
00060 }
00061
00062 mitk::StateMachineFactory::StateMachineFactory()
00063 : m_AktStateMachineName(""), m_SkipStateMachine(false)
00064 {}
00065
00066 mitk::StateMachineFactory::~StateMachineFactory()
00067 {
00068
00069
00070 while (!m_AllStateMachineMap.empty())
00071 {
00072 StateMachineMapType* temp = m_AllStateMachineMap.begin()->second;
00073 m_AllStateMachineMap.erase(m_AllStateMachineMap.begin());
00074 delete temp;
00075 }
00076
00077
00078 m_StartStates.clear();
00079
00080
00081 if (m_AktTransition)
00082 delete m_AktTransition;
00083 }
00084
00085
00089 mitk::State* mitk::StateMachineFactory::GetStartState(const char * type)
00090 {
00091 StartStateMapIter tempState = m_StartStates.find(type);
00092 if( tempState != m_StartStates.end() )
00093 return (tempState)->second.GetPointer();
00094
00095 MITK_ERROR << "Error in StateMachineFactory: StartState for pattern \""<< type<< "\"not found! StateMachine might not work!\n";
00096 return NULL;
00097 }
00098
00102 bool mitk::StateMachineFactory::LoadBehavior(std::string fileName)
00103 {
00104 if ( fileName.empty() )
00105 return false;
00106
00107 m_LastLoadedBehavior = fileName;
00108
00109 this->SetFileName(fileName.c_str());
00110
00111 return this->Parse();
00112 }
00113
00117 bool mitk::StateMachineFactory::LoadBehaviorString(std::string xmlString)
00118 {
00119 if ( xmlString.empty() )
00120 return false;
00121
00122 m_LastLoadedBehavior = "String";
00123
00124 return ( this->Parse(xmlString.c_str(), xmlString.length()) );
00125 }
00126
00127 bool mitk::StateMachineFactory::LoadStandardBehavior()
00128 {
00129 std::string xmlFileName( mitk::StandardFileLocations::GetInstance()->FindFile("StateMachine.xml", "Core/Code/Interactions") );
00130
00131 if (!xmlFileName.empty())
00132 return this->LoadBehavior(xmlFileName);
00133 else
00134 return false;
00135 }
00136
00137
00143 bool mitk::StateMachineFactory::RParse(mitk::State::StateMap* states, mitk::State::StateMapIter thisState, HistorySet *history)
00144 {
00145 history->insert((thisState->second)->GetId());
00146 std::set<int> nextStatesSet = (thisState->second)->GetAllNextStates();
00147
00148
00149
00150 std::set<int>::iterator position = nextStatesSet.find((thisState->second)->GetId());
00151 if (position != nextStatesSet.end())
00152 {
00153 nextStatesSet.erase(position);
00154 }
00155
00156
00157 if ( nextStatesSet.empty() )
00158 {
00159 MITK_INFO<<std::endl<<"Warning! An inconsistent state or a dead end was produced. Check pattern "<< m_AktStateMachineName<<". Continuing anyway."<<std::endl;
00160 return true;
00161 }
00162 bool ok = true;
00163
00164 for (std::set<int>::iterator i = nextStatesSet.begin(); i != nextStatesSet.end(); i++)
00165 {
00166 if ( history->find(*i) == history->end() )
00167 {
00168 mitk::State::StateMapIter nextState = states->find(*i);
00169 if (nextState == states->end())
00170 {
00171 MITK_INFO<<std::endl<<"Didn't find a state in StateMap! Check pattern "<< m_AktStateMachineName<<"!"<<std::endl;
00172 ok = false;
00173 }
00174 else
00175 ok = RParse( states, nextState, history);
00176 }
00177 }
00178 return ok;
00179 }
00180
00184 bool mitk::StateMachineFactory::ConnectStates(mitk::State::StateMap *states)
00185 {
00186 if (states->size() > 1)
00187 {
00188
00189 HistorySet *history = new HistorySet;
00190 mitk::State::StateMapIter firstState = states->begin();
00191
00192 bool ok = RParse( states, firstState, history);
00193
00194 if ( (states->size() == history->size()) && ok )
00195 {
00196 delete history;
00197 }
00198 else
00199 {
00200 delete history;
00201 MITK_INFO<<std::endl;
00202 MITK_INFO<<"Warning: An unreachable state was produced! Please check pattern "<< m_AktStateMachineName<<" inside StateMachinePattern-File. Continuing anyway!"<<std::endl;
00203
00204 }
00205 }
00206
00207 for (mitk::State::StateMapIter tempState = states->begin(); tempState != states->end(); tempState++)
00208 {
00209
00210 bool tempbool = ( ( tempState->second )->ConnectTransitions( states ) );
00211 if ( tempbool == false )
00212 {
00213 MITK_INFO<<std::endl;
00214 MITK_INFO<<"Warning: Connection of states was not successful in pattern "<< m_AktStateMachineName<<"!"<<std::endl;
00215 return false;
00216 }
00217 }
00218 return true;
00219 }
00220
00221 void mitk::StateMachineFactory::StartElement (const char* elementName, const char **atts)
00222 {
00223
00224 if (m_SkipStateMachine)
00225 return;
00226
00227 std::string name(elementName);
00228
00229 if ( name == STATE_MACHINE )
00230 {
00231 std::string tempStateMachineName = ReadXMLStringAttribut( NAME, atts );
00232 if (m_AllStateMachineMap.find(tempStateMachineName) != m_AllStateMachineMap.end())
00233 {
00234
00235 STATEMACHINE_FATAL<<"State machine pattern " << tempStateMachineName << " already exists! Skipping state machine pattern";
00236 m_SkipStateMachine = true;
00237 }
00238 else
00239 {
00240 m_AktStateMachineName = tempStateMachineName;
00241 m_AllStateMachineMap[ m_AktStateMachineName ] = new StateMachineMapType;
00242 }
00243 }
00244
00245 else if ( name == STATE )
00246 {
00247 std::string stateMachinName = ReadXMLStringAttribut( NAME, atts ) ;
00248 int id = ReadXMLIntegerAttribut( ID, atts );
00249
00250
00251 m_AktState = mitk::State::New(stateMachinName , id);
00252
00253
00254 StateMachineMapType* stateMachine = m_AllStateMachineMap[ m_AktStateMachineName ];
00255 (*stateMachine)[id] = m_AktState;
00256
00257 std::pair<mitk::State::StateMapIter,bool> ok = m_AllStatesOfOneStateMachine.insert(mitk::State::StateMap::value_type(id , m_AktState));
00258
00259 if ( ok.second == false )
00260 {
00261 MITK_INFO<<std::endl;
00262 MITK_INFO<<"Warning from StateMachineFactory: STATE_ID was not unique in pattern "<< m_AktStateMachineName<<"!"<<std::endl;
00263 return;
00264 }
00265 if ( ReadXMLBooleanAttribut( START_STATE, atts ) )
00266 m_StartStates.insert(StartStateMap::value_type(m_AktStateMachineName, m_AktState));
00267 }
00268
00269 else if ( name == TRANSITION )
00270 {
00271 std::string transitionName = ReadXMLStringAttribut( NAME, atts ) ;
00272 int nextStateId = ReadXMLIntegerAttribut( NEXT_STATE_ID, atts );
00273 int eventId = ReadXMLIntegerAttribut( EVENT_ID, atts );
00274 m_AktTransition = new Transition(transitionName, nextStateId, eventId);
00275 if ( m_AktState )
00276 m_AktState->AddTransition( m_AktTransition );
00277 }
00278
00279 else if ( name == ACTION )
00280 {
00281 int actionId = ReadXMLIntegerAttribut( ID, atts );
00282 m_AktAction = Action::New( actionId );
00283 m_AktTransition->AddAction( m_AktAction );
00284 }
00285
00286 else if ( name == BOOL_PARAMETER )
00287 {
00288 if ( !m_AktAction )
00289 return;
00290
00291 bool value = ReadXMLBooleanAttribut( VALUE, atts );
00292 std::string name = ReadXMLStringAttribut( NAME, atts );
00293 m_AktAction->AddProperty( name.c_str(), BoolProperty::New( value ) );
00294 }
00295
00296 else if ( name == INT_PARAMETER )
00297 {
00298 if ( !m_AktAction )
00299 return;
00300
00301 int value = ReadXMLIntegerAttribut( VALUE, atts );
00302 std::string name = ReadXMLStringAttribut( NAME, atts );
00303 m_AktAction->AddProperty( name.c_str(), IntProperty::New( value ) );
00304 }
00305
00306 else if ( name == FLOAT_PARAMETER )
00307 {
00308 if ( !m_AktAction )
00309 return;
00310
00311 float value = ReadXMLIntegerAttribut( VALUE, atts );
00312 std::string name = ReadXMLStringAttribut( NAME, atts );
00313 m_AktAction->AddProperty( name.c_str(), FloatProperty::New( value ) );
00314 }
00315
00316 else if ( name == DOUBLE_PARAMETER )
00317 {
00318 if ( !m_AktAction )
00319 return;
00320
00321 double value = ReadXMLDoubleAttribut( VALUE, atts );
00322 std::string name = ReadXMLStringAttribut( NAME, atts );
00323 m_AktAction->AddProperty( name.c_str(), DoubleProperty::New( value ) );
00324 }
00325
00326 else if ( name == STRING_PARAMETER )
00327 {
00328 if ( !m_AktAction )
00329 return;
00330
00331 std::string value = ReadXMLStringAttribut( VALUE, atts );
00332 std::string name = ReadXMLStringAttribut( NAME, atts );
00333 m_AktAction->AddProperty( name.c_str(), StringProperty::New( value ) );
00334 }
00335 }
00336
00337 void mitk::StateMachineFactory::EndElement (const char* elementName)
00338 {
00339 bool ok = true;
00340 std::string name(elementName);
00341
00342
00343 if (m_SkipStateMachine && (name != STATE_MACHINE) )
00344 return;
00345
00346
00347 if ( name == STATE_MACHINE_NAME )
00348 {
00349 if (m_SkipStateMachine)
00350 {
00351 m_SkipStateMachine = false;
00352 return;
00353 }
00354
00355 ok = ConnectStates(&m_AllStatesOfOneStateMachine);
00356 m_AllStatesOfOneStateMachine.clear();
00357 }
00358 else if ( name == STATE_MACHINE )
00359 {
00360
00361 }
00362 else if ( name == TRANSITION )
00363 {
00364 m_AktTransition = NULL;
00365 }
00366 else if ( name == ACTION )
00367 {
00368 m_AktAction = NULL;
00369 }
00370 else if ( name == STATE )
00371 {
00372 m_AktState = NULL;
00373 }
00374 }
00375
00376 std::string mitk::StateMachineFactory::ReadXMLStringAttribut( std::string name, const char** atts )
00377 {
00378 if(atts)
00379 {
00380 const char** attsIter = atts;
00381
00382 while(*attsIter)
00383 {
00384 if ( name == *attsIter )
00385 {
00386 attsIter++;
00387 return *attsIter;
00388 }
00389 attsIter++;
00390 attsIter++;
00391 }
00392 }
00393
00394 return std::string();
00395 }
00396
00397 int mitk::StateMachineFactory::ReadXMLIntegerAttribut( std::string name, const char** atts )
00398 {
00399 std::string s = ReadXMLStringAttribut( name, atts );
00400 return atoi( s.c_str() );
00401 }
00402
00403 float mitk::StateMachineFactory::ReadXMLFloatAttribut( std::string name, const char** atts )
00404 {
00405 std::string s = ReadXMLStringAttribut( name, atts );
00406 return (float) atof( s.c_str() );
00407 }
00408
00409 double mitk::StateMachineFactory::ReadXMLDoubleAttribut( std::string name, const char** atts )
00410 {
00411 std::string s = ReadXMLStringAttribut( name, atts );
00412 return atof( s.c_str() );
00413 }
00414
00415 bool mitk::StateMachineFactory::ReadXMLBooleanAttribut( std::string name, const char** atts )
00416 {
00417 std::string s = ReadXMLStringAttribut( name, atts );
00418
00419 if ( s == ISTRUE )
00420 return true;
00421 else
00422 return false;
00423 }
00424
00425 mitk::State* mitk::StateMachineFactory::GetState( const char * type, int StateId )
00426 {
00427
00428 AllStateMachineMapType::iterator i = m_AllStateMachineMap.find( type );
00429 if ( i == m_AllStateMachineMap.end() )
00430 return false;
00431
00432
00433 StateMachineMapType* sm = m_AllStateMachineMap[type];
00434
00435
00436 if ( sm != NULL )
00437 return (*sm)[StateId].GetPointer();
00438 else
00439 return NULL;
00440 }
00441
00442 bool mitk::StateMachineFactory::AddStateMachinePattern(const char * type, mitk::State* startState, mitk::StateMachineFactory::StateMachineMapType* allStatesOfStateMachine)
00443 {
00444 if (startState == NULL || allStatesOfStateMachine == NULL)
00445 return false;
00446
00447
00448 StartStateMapIter tempState = m_StartStates.find(type);
00449 if( tempState != m_StartStates.end() )
00450 {
00451 STATEMACHINE_WARN << "Pattern " << type << " has already been added!\n";
00452 return false;
00453 }
00454
00455
00456 m_StartStates.insert(StartStateMap::value_type(type, startState));
00457
00458
00459 m_AllStateMachineMap.insert(AllStateMachineMapType::value_type(type, allStatesOfStateMachine));
00460 return true;
00461 }
00462