Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkStateMachineContainer.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 #include <algorithm>
16 #include <vtkObjectFactory.h>
17 #include <vtkXMLDataElement.h>
18 
19 // us
20 #include "usGetModuleContext.h"
21 #include "usModule.h"
22 #include "usModuleResource.h"
23 #include "usModuleResourceStream.h"
24 
29 // XML StateMachine Tags
30 const std::string NAME = "name";
31 const std::string CONFIG = "statemachine";
32 const std::string STATE = "state";
33 const std::string STATEMODE = "state_mode";
34 const std::string TRANSITION = "transition";
35 const std::string EVENTCLASS = "event_class";
36 const std::string EVENTVARIANT = "event_variant";
37 const std::string STARTSTATE = "startstate";
38 const std::string TARGET = "target";
39 const std::string ACTION = "action";
40 const std::string CONDITION = "condition";
41 const std::string INVERTED = "inverted";
42 
43 namespace mitk
44 {
45  vtkStandardNewMacro(StateMachineContainer);
46 }
47 
48 mitk::StateMachineContainer::StateMachineContainer() : m_StartStateFound(false), m_errors(false)
49 {
50 }
51 
53 {
54 }
55 
59 bool mitk::StateMachineContainer::LoadBehavior(const std::string &fileName, const us::Module *module)
60 {
61  if (module == nullptr)
62  {
63  module = us::GetModuleContext()->GetModule();
64  }
65  us::ModuleResource resource = module->GetResource("Interactions/" + fileName);
66  if (!resource.IsValid())
67  {
68  mitkThrow() << ("Resource not valid. State machine pattern not found:" + fileName);
69  }
70  us::ModuleResourceStream stream(resource);
71  this->SetStream(&stream);
72  m_Filename = fileName;
73  return this->Parse() && !m_errors;
74 }
75 
77 {
78  return m_StartState;
79 }
80 
84 void mitk::StateMachineContainer::ConnectStates()
85 {
86  for (auto it = m_States.begin(); it != m_States.end(); ++it)
87  {
88  if ((*it)->ConnectTransitions(&m_States) == false)
89  m_errors = true;
90  }
91 }
92 
93 void mitk::StateMachineContainer::StartElement(const char *elementName, const char **atts)
94 {
95  std::string name(elementName);
96 
97  if (name == CONFIG)
98  {
99  //
100  }
101  else if (name == STATE)
102  {
103  std::string stateName = ReadXMLStringAttribut(NAME, atts);
104  std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::toupper);
105  std::string stateMode = ReadXMLStringAttribut(STATEMODE, atts);
106  std::transform(stateMode.begin(), stateMode.end(), stateMode.begin(), ::toupper);
107  bool isStartState = ReadXMLBooleanAttribut(STARTSTATE, atts);
108 
109  if (isStartState)
110  {
111  m_StartStateFound = true;
112  }
113 
114  // sanitize state modes
115  if (stateMode == "" || stateMode == "REGULAR")
116  {
117  stateMode = "REGULAR";
118  }
119  else if (stateMode != "GRAB_INPUT" && stateMode != "PREFER_INPUT")
120  {
121  MITK_WARN << "Invalid State Modus " << stateMode << ". Mode assumed to be REGULAR";
122  stateMode = "REGULAR";
123  }
124  m_CurrState = mitk::StateMachineState::New(stateName, stateMode);
125 
126  if (isStartState)
127  m_StartState = m_CurrState;
128  }
129  else if (name == TRANSITION)
130  {
131  std::string eventClass = ReadXMLStringAttribut(EVENTCLASS, atts);
132  std::string eventVariant = ReadXMLStringAttribut(EVENTVARIANT, atts);
133  std::string target = ReadXMLStringAttribut(TARGET, atts);
134  std::transform(target.begin(), target.end(), target.begin(), ::toupper);
135 
137  mitk::StateMachineTransition::New(target, eventClass, eventVariant);
138  if (m_CurrState)
139  {
140  m_CurrState->AddTransition(transition);
141  }
142  else
143  {
144  MITK_WARN << "Malformed Statemachine Pattern. Transition has no origin. \n Will be ignored.";
145  MITK_WARN << "Malformed Transition details: target=" << target << ", event class:" << eventClass
146  << ", event variant:" << eventVariant;
147  }
148  m_CurrTransition = transition;
149  }
150 
151  else if (name == ACTION)
152  {
153  std::string actionName = ReadXMLStringAttribut(NAME, atts);
155  if (m_CurrTransition)
156  m_CurrTransition->AddAction(action);
157  else
158  MITK_WARN << "Malformed state machine Pattern. Action without transition. \n Will be ignored.";
159  }
160 
161  else if (name == CONDITION)
162  {
163  if (!m_CurrTransition)
164  MITK_WARN << "Malformed state machine Pattern. Condition without transition. \n Will be ignored.";
165 
166  std::string conditionName = ReadXMLStringAttribut(NAME, atts);
167  std::string inverted = ReadXMLStringAttribut(INVERTED, atts);
168  if (inverted == "" || inverted == "false")
169  {
170  m_CurrTransition->AddCondition(mitk::StateMachineCondition(conditionName, false));
171  }
172  else
173  {
174  m_CurrTransition->AddCondition(mitk::StateMachineCondition(conditionName, true));
175  }
176  }
177 }
178 
179 void mitk::StateMachineContainer::EndElement(const char *elementName)
180 {
181  std::string name(elementName);
182 
183  if (name == CONFIG)
184  {
185  if (m_StartState.IsNull())
186  {
187  MITK_ERROR << "State machine pattern has no start state and cannot be used: " << m_Filename;
188  }
189  ConnectStates();
190  }
191  else if (name == TRANSITION)
192  {
193  m_CurrTransition = nullptr;
194  }
195  else if (name == ACTION)
196  {
197  //
198  }
199  else if (name == CONDITION)
200  {
201  //
202  }
203  else if (name == STATE)
204  {
205  m_States.push_back(m_CurrState);
206  m_CurrState = nullptr;
207  }
208 }
209 
210 std::string mitk::StateMachineContainer::ReadXMLStringAttribut(std::string name, const char **atts)
211 {
212  if (atts)
213  {
214  const char **attsIter = atts;
215 
216  while (*attsIter)
217  {
218  if (name == *attsIter)
219  {
220  attsIter++;
221  return *attsIter;
222  }
223  attsIter++;
224  attsIter++;
225  }
226  }
227 
228  return std::string();
229 }
230 
231 bool mitk::StateMachineContainer::ReadXMLBooleanAttribut(std::string name, const char **atts)
232 {
233  std::string s = ReadXMLStringAttribut(name, atts);
234  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
235  if (s == "TRUE")
236  return true;
237  else
238  return false;
239 }
const std::string STATE
bool LoadBehavior(const std::string &fileName, const us::Module *module)
Loads XML resource.
#define MITK_ERROR
Definition: mitkLogMacros.h:20
static Pointer New(const std::string &_arg)
const std::string ACTION
const std::string STARTSTATE
const std::string NAME
This class builds up all the necessary structures for a statemachine. and stores one start-state for ...
DataCollection - Class to facilitate loading/accessing structured data.
static Pointer New(const std::string &_arga, const std::string &_argb)
const std::string CONFIG
void StartElement(const char *elementName, const char **atts) override
Derived from XMLReader.
#define MITK_WARN
Definition: mitkLogMacros.h:19
#define mitkThrow()
Module * GetModule() const
const std::string INVERTED
ModuleResource GetResource(const std::string &path) const
Definition: usModule.cpp:267
vtkStandardNewMacro(AnatomicalStructureColorPresets)
StateMachineState::Pointer GetStartState() const
Returns the StartState of the StateMachine.
const std::string STATEMODE
const std::string EVENTVARIANT
static Pointer New(const std::string &_arga, const std::string &_argb, const std::string &_argc)
const std::string CONDITION
Represents a condition, that has to be fulfilled in order to execute a state machine transition after...
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
const std::string EVENTCLASS
void EndElement(const char *elementName) override
Derived from XMLReader.
const std::string TRANSITION
const std::string TARGET