XMLState.cpp
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5*
6* ArmarX is free software; you can redistribute it and/or modify
7* it under the terms of the GNU General Public License version 2 as
8* published by the Free Software Foundation.
9*
10* ArmarX is distributed in the hope that it will be useful, but
11* WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17*
18* @package ArmarX::
19* @author Mirko Waechter ( mirko.waechter at kit dot edu)
20* @date 2013
21* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22* GNU General Public License
23*/
24
25#include "XMLState.h"
26
27#include <filesystem>
28#include <fstream>
29
30#include <SimoxUtility/algorithm/string/string_tools.h>
31
42
43using namespace armarx;
44using namespace rapidxml;
45
46
47NoUserCodeState::SubClassRegistry NoUserCodeState::Registry(NoUserCodeState::GetName(),
49
54
60
61std::string
63{
64 return "NoUserCodeState";
65}
66
69{
70 return new NoUserCodeState(*this);
71}
72
73VariantContainerBasePtr
75 StatechartProfilePtr selectedProfile,
77 std::string defaultValueJsonString)
78{
79 VariantContainerBasePtr result;
80 std::map<std::string, std::string> defaultValueMap;
81 for (RapidXmlReaderNode defaultValueNode : parameterNode.nodes("DefaultValue"))
82 {
83 if (defaultValueNode.has_attribute("profile"))
84 {
85 defaultValueMap.insert(std::make_pair(defaultValueNode.attribute_value("profile"),
86 defaultValueNode.attribute_value("value")));
87 }
88 else
89 {
90 defaultValueJsonString = defaultValueNode.attribute_value("value");
91 }
92 }
93
94 StatechartProfilePtr profile = selectedProfile;
95
96 while (profile)
97 {
98 if (defaultValueMap.find(profile->getName()) != defaultValueMap.end())
99 {
100 defaultValueJsonString = defaultValueMap.at(profile->getName());
101 break;
102 }
103
104 profile = profile->getParent();
105 }
106
107 JSONObjectPtr json(new JSONObject(ic));
108
109 if (!defaultValueJsonString.empty())
110 {
111 try
112 {
113 json->fromString(defaultValueJsonString);
114 result = VariantContainerBasePtr::dynamicCast(json->deserializeIceObject());
115
116 if (!result)
117 {
118 ARMARX_WARNING_S << "Could not deserialize param: " << defaultValueJsonString;
119 }
120 }
121 catch (JSONException& e)
122 {
123 ARMARX_WARNING_S << "Could not read default value for param: "
124 << defaultValueJsonString;
125 }
126 }
127 return result;
128}
129
131 const RapidXmlReaderNode& parameterNode,
133 StatechartProfilePtr selectedProfile)
134{
135 name = parameterNode.attribute_value("name");
136 optional = parameterNode.attribute_value("optional") == "no" ? false : true;
137 typeStr = parameterNode.attribute_value("type");
139
140 std::string defaultValueJsonString = parameterNode.attribute_value_or_default("default", "");
141
142 container = GetSelectedProfileValue(parameterNode, selectedProfile, ic, defaultValueJsonString);
143}
144
145std::string
150
151bool
156
157std::string
162
163ContainerTypePtr
168
169VariantContainerBasePtr
174
175namespace armarx
176{
177
187} // namespace armarx
188
190{
191 setXMLStateData(stateData);
192}
193
194void
195XMLState::setXMLStateData(const XMLStateConstructorParams& stateData)
196{
197 privateStateData.reset(new PrivateXmlStateClass{stateData.xmlFilepath,
198 stateData.reader,
200 stateData.selectedProfile,
201 stateData.uuidToXMLMap,
202 nullptr});
203
204 if (!privateStateData->stateReader && privateStateData->xmlFilepath.empty())
205 {
206 throw LocalException("Either a xml node or a filepath must be given.");
207 }
208 else if (!privateStateData->stateReader)
209 {
210 privateStateData->stateNode =
211 RapidXmlReader::FromFile(privateStateData->xmlFilepath.string())->getRoot("State");
212 }
213 else
214 {
215 privateStateData->stateNode = privateStateData->stateReader->getRoot("State");
216 privateStateData->xmlFilepath.clear();
217 }
218}
219
223
226{
227 return privateStateData->selectedProfile;
228}
229
230void
232{
233 // ARMARX_INFO_S << "defineSubstates of " << State::getStateName();
234 if (!privateStateData->stateNode.is_valid())
235 {
236 return;
237 }
239 if (!privateStateData->ic && context && context->getIceManager()->getCommunicator())
240 {
241 privateStateData->ic = context->getIceManager()->getCommunicator();
242 }
243
244 this->StateBase::inputParameters =
245 getParameters(privateStateData->stateNode.first_node("InputParameters"));
246 this->StateBase::outputParameters =
247 getParameters(privateStateData->stateNode.first_node("OutputParameters"));
248 this->StateBase::localParameters =
249 getParameters(privateStateData->stateNode.first_node("LocalParameters"));
250}
251
252StateParameterMap
254{
255 StateParameterMap result;
256
257 if (!parametersNode.is_valid())
258 {
259 return result;
260 }
261
262
263 for (RapidXmlReaderNode curParameterNode : parametersNode.nodes("Parameter"))
264 {
265 StateParameterDeserialization deserialization(
266 curParameterNode, privateStateData->ic, privateStateData->selectedProfile);
267
268 try
269 {
271 deserialization.getName(),
272 *deserialization.getTypePtr(),
273 deserialization.getOptional(),
274 deserialization.getContainer());
275 // ARMARX_VERBOSE << "Adding param: " << name << ", " << VariantContainerType::allTypesToString(typePtr) << ", optional: " << optional;
276 // ARMARX_VERBOSE << "JSON: " << jsonString;
277 }
279 {
280 ARMARX_WARNING << "The type '" << deserialization.getTypeStr()
281 << "' is unknown, Parameter '" << deserialization.getName()
282 << "' not added";
283 }
284 }
285
286 return result;
287}
288
289void
291{
292 ARMARX_DEBUG << "defineSubstates of " << State::getStateName();
293 if (!privateStateData->stateNode.is_valid())
294 {
295 ARMARX_WARNING << "stateNode is not valid!";
296
297 return;
298 }
299
300 const std::string stateName = privateStateData->stateNode.attribute_value("name");
301
302 addXMLSubstates(privateStateData->stateNode.first_node("Substates"), stateName);
303
304 addTransitions(privateStateData->stateNode.first_node("Transitions"));
305
306 setStartState(privateStateData->stateNode.first_node("StartState"));
307}
308
309void
310XMLState::addXMLSubstates(RapidXmlReaderNode substatesNode, const std::string& parentStateName)
311{
312 if (!substatesNode.is_valid())
313 {
314 return;
315 }
316
317 for (RapidXmlReaderNode curSubstateNode = substatesNode.first_node();
318 curSubstateNode.is_valid();
319 curSubstateNode = curSubstateNode.next_sibling())
320 {
321 addXMLSubstate(curSubstateNode, parentStateName);
322 }
323}
324
326XMLState::addXMLSubstate(RapidXmlReaderNode stateNode, const std::string& parentStateName)
327{
328 ARMARX_CHECK_EXPRESSION(privateStateData->uuidToXMLMap);
329
330 const std::string stateType = stateNode.name();
331
332
333 StateBasePtr state;
334
335 std::string stateTypeL = simox::alg::to_lower(stateType);
336
337 if (stateTypeL == "localstate")
338 {
339 const std::string refuuid = stateNode.attribute_value("refuuid");
340 const std::string instanceName = stateNode.attribute_value("name");
341
342 auto it = privateStateData->uuidToXMLMap->find(refuuid);
343
344 if (it == privateStateData->uuidToXMLMap->end())
345 {
346 throw LocalException("Could not find local state with UUID ") << refuuid;
347 }
348
349 RapidXmlReaderPtr substateReader = it->second;
350 const std::string stateName = substateReader->getRoot("State").attribute_value("name");
351 IceInternal::Handle<XMLState> xmlStateInstance =
353 stateName,
355 substateReader,
356 privateStateData->selectedProfile,
357 privateStateData->uuidToXMLMap,
358 privateStateData->ic)));
359 state = StateBasePtr::dynamicCast(xmlStateInstance);
360
361 if (!state)
362 {
363 ARMARX_DEBUG << "Using state with no code for " << stateName << " refuuid: " << refuuid
364 << " instanceName: " << instanceName;
365 state = StateBasePtr::dynamicCast(NoUserCodeState::CreateInstance(
367 substateReader,
368 privateStateData->selectedProfile,
369 privateStateData->uuidToXMLMap,
370 privateStateData->ic)));
371 // xmlStateInstance = IceInternal::Handle<XMLState>::dynamicCast(state);
372 }
373 // xmlStateInstance->setXMLStateData(XMLStateConstructorParams("", substateReader, privateStateData->selectedProfile, privateStateData->uuidToXMLMap, privateStateData->ic));
374
375 state->stateName = instanceName;
376 state = addState(StatePtr::dynamicCast(state));
377 ARMARX_DEBUG << "Added " << stateName << " with instanceName " << instanceName;
378 }
379 else if (stateTypeL == "remotestate")
380 {
381 const std::string instanceName = stateNode.attribute_value("name");
382 const std::string refuuid = stateNode.attribute_value("refuuid");
383 const std::string proxyName = ((!privateStateData->selectedProfile->isRoot())
384 ? privateStateData->selectedProfile->getName()
385 : "") +
386 stateNode.attribute_value("proxyName");
387 ARMARX_DEBUG << "Adding remote state with refuuid " << refuuid
388 << " and instance name: " << instanceName;
389 state = State::addRemoteState(refuuid, proxyName, instanceName);
390 }
391
392 else if (stateTypeL == "dynamicremotestate")
393 {
394 const std::string instanceName = stateNode.attribute_value("name");
395 ARMARX_DEBUG << "Adding dynamic remote state with instance name: " << instanceName;
396 state = State::addDynamicRemoteState(instanceName);
397 }
398 else if (stateTypeL == "endstate")
399 {
400 const std::string eventName = stateNode.attribute_value("name");
401 ARMARX_DEBUG << "Adding end state with event " << eventName;
402 EventPtr evt = StateUtility::createEvent(eventName);
404 state = addState(state);
405 }
406
407 else
408 {
409 throw LocalException("Unknown state type in XML - found state type: ") << stateType;
410 }
411
412 return state;
413}
414
417{
418
419
421
422 if (State::findSubstateByName(state->stateName))
423 {
425 "There exists already a substate with name '" + state->StateBase::stateName +
426 "' in this hierarchy level. In one hierarchy level (aka one substatelist) the names "
427 "must be unique.");
428 }
429
430 if (state->stateName.empty())
431 {
432 throw exceptions::local::eStatechartLogicError("The statename must not be empty");
433 }
434
435
436 state->__setParentState(this);
437 this->StateBase::subStateList.push_back(state);
439 state->init(context, this->StateBase::impl->manager);
440
441 return state;
442}
443
444void
445XMLState::addTransitions(const RapidXmlReaderNode& transitionsNode)
446{
447
448 if (!transitionsNode.is_valid())
449 {
450 ARMARX_WARNING << "transition node is not valid!";
451 return;
452 }
453
454 for (RapidXmlReaderNode curTransitionNode = transitionsNode.first_node("Transition");
455 curTransitionNode.is_valid();
456 curTransitionNode = curTransitionNode.next_sibling("Transition"))
457 {
458 const std::string eventName = curTransitionNode.attribute_value("eventName");
459
460 const std::string sourceStateName = curTransitionNode.attribute_value("from");
461
462 if (!curTransitionNode.has_attribute("to"))
463 {
464 ARMARX_INFO << "Skipping detached transition " << eventName;
465 continue;
466 }
467
468 const std::string destinationStateName = curTransitionNode.attribute_value("to");
469
470
472 StateBasePtr destination = State::findSubstateByName(destinationStateName);
473
474 if (!source)
475 {
476 throw LocalException("Could not find source state with name :") << sourceStateName;
477 }
478
479 if (!destination)
480 {
481 throw LocalException("Could not find source state with name :") << destinationStateName;
482 }
483
484 if (eventName.empty())
485 {
486 throw LocalException("Event name must not bet empty");
487 }
488
489 EventPtr event = State::createEvent(eventName);
490 ARMARX_DEBUG << "Adding Transition on event " << eventName;
491 ParameterMappingPtr mappingToNextStateInput =
492 getMapping(curTransitionNode.first_node("ParameterMappings"));
493 ParameterMappingPtr mappingsToParentsLocal =
494 getMapping(curTransitionNode.first_node("ParameterMappingsToParentsLocal"));
495 ParameterMappingPtr mappingsToParentsOutput =
496 getMapping(curTransitionNode.first_node("ParameterMappingsToParentsOutput"));
497
499 source,
500 destination,
501 mappingToNextStateInput,
502 mappingsToParentsLocal,
503 mappingsToParentsOutput);
504 }
505}
506
507void
508XMLState::setStartState(const RapidXmlReaderNode& startNode)
509{
510 if (!startNode.is_valid())
511 {
512 return;
513 }
514
515 PMPtr mapping = getMapping(startNode.first_node("ParameterMappings"));
516 this->setInitState(State::findSubstateByName(startNode.attribute_value("substateName")),
517 mapping);
518}
519
521XMLState::getMapping(const RapidXmlReaderNode& mappingNode)
522{
523 if (!mappingNode.is_valid())
524 {
525 return nullptr;
526 }
527
528 PMPtr mapping = PM::createMapping();
529
530 for (RapidXmlReaderNode curMappingNode = mappingNode.first_node("ParameterMapping");
531 curMappingNode.is_valid();
532 curMappingNode = curMappingNode.next_sibling("ParameterMapping"))
533 {
534 MappingSource sourceType =
535 PM::StringToMappingSource(curMappingNode.attribute_value("sourceType"));
536 const std::string fromParamName = curMappingNode.attribute_value("from");
537 const std::string targetParamName = curMappingNode.attribute_value("to");
538
539 mapping->addMappingEntry(sourceType,
540 fromParamName,
541 targetParamName,
542 GetSelectedProfileValue(curMappingNode,
543 privateStateData->selectedProfile,
544 privateStateData->ic));
545 }
546
547 return mapping;
548}
549
static SharedPointerType fromName(const std::string &name, XMLStateConstructorParams params)
static StatePtr createState(const EventPtr &event)
createState creates a finalstate instance with the specified event type.
Definition FinalState.h:170
The JSONObject class is used to represent and (de)serialize JSON objects.
Definition JSONObject.h:44
IceManagerPtr getIceManager() const
Returns the IceManager.
static ParameterMappingPtr createMapping()
Creates a new instance of a ParameterMapping. Since the constructors are private, this method must be...
static MappingSource StringToMappingSource(const std::string &mappingSourceString)
RapidXmlReaderNode first_node(const char *name=nullptr) const
std::string name() const
std::vector< RapidXmlReaderNode > nodes(const char *name=nullptr) const
static RapidXmlReaderNode NullNode()
std::string attribute_value(const char *attrName) const
std::string attribute_value_or_default(const char *attrName, const std::string &defaultValue) const
static RapidXmlReaderPtr FromFile(const std::string &path)
StateBasePtr findSubstateByName(const std::string &substateName)
Utility function to find a substate of this state by the name.
void __checkPhase(StatePhase allowedType, const char *functionName) const
Helper function for checking if a function was called in valid position of the statechart.
bool addParameterContainer(StateParameterMap &paramMap, const std::string &key, const ContainerType &containerType, bool optional, VariantContainerBasePtr defaultValue=VariantContainerBasePtr()) const
std::unique_ptr< Impl > impl
Definition StateBase.h:289
ContextType * getContext() const
Definition StateBase.h:71
std::string getStateName() const
getStateName
VariantContainerBasePtr container
Definition XMLState.h:92
VariantContainerBasePtr getContainer()
Definition XMLState.cpp:170
StateParameterDeserialization(RapidXmlReaderNode const &parameterNode, Ice::CommunicatorPtr ic, StatechartProfilePtr selectedProfile)
Definition XMLState.cpp:130
EventPtr createEvent()
Utility function to create a new Event.
Definition StateUtil.h:63
StateBasePtr setInitState(StateBasePtr initState, ParameterMappingPtr initialStateMapping=ParameterMappingPtr())
Sets the initial substate of this state.
Definition State.cpp:354
TransitionIceBase & addTransition(EventPtr event, StateIceBasePtr sourceState, StateIceBasePtr destinationState, ParameterMappingIceBasePtr mappingToNextStatesInput=nullptr, ParameterMappingIceBasePtr mappingToParentStatesLocal=nullptr, ParameterMappingIceBasePtr mappingToParentStatesOutput=nullptr)
Definition State.cpp:250
virtual RemoteStatePtr addDynamicRemoteState(std::string instanceName)
Function to add a new dynamic remote substate to this state.
Definition State.cpp:213
virtual RemoteStatePtr addRemoteState(std::string stateName, std::string proxyName, std::string instanceName="")
Function to add a new remote substate to this state.
Definition State.cpp:158
This class contains a statechart and provides the interfaces to distributed components.
static ContainerTypePtr FromString(const std::string &typeStr)
void defineParameters() override
Virtual function, in which input/local/output parameters can be specified.
Definition XMLState.cpp:231
StateParameterMap getParameters(RapidXmlReaderNode parametersNode)
Definition XMLState.cpp:253
~XMLState() override
Definition XMLState.cpp:220
StatePtr addState(StatePtr state)
Definition XMLState.cpp:416
void addXMLSubstates(RapidXmlReaderNode substatesNode, const std::string &parentStateName)
Definition XMLState.cpp:310
void defineSubstates() override
Virtual function, in which substates, transition and mappings can be added.
Definition XMLState.cpp:290
StateBasePtr addXMLSubstate(RapidXmlReaderNode stateNode, const std::string &parentStateName)
Definition XMLState.cpp:326
StatechartProfilePtr getSelectedProfile() const
Definition XMLState.cpp:225
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:213
::IceInternal::Handle<::Ice::Communicator > CommunicatorPtr
Definition IceManager.h:49
This file offers overloads of toIce() and fromIce() functions for STL container types.
VariantContainerBasePtr GetSelectedProfileValue(RapidXmlReaderNode parameterNode, StatechartProfilePtr selectedProfile, Ice::CommunicatorPtr ic, std::string defaultValueJsonString="")
Definition XMLState.cpp:74
std::shared_ptr< StringXMLNodeMap > StringXMLNodeMapPtr
Definition XMLState.h:42
std::shared_ptr< RapidXmlReader > RapidXmlReaderPtr
IceInternal::Handle< State > StatePtr
Definition State.h:44
ParameterMappingPtr PMPtr
std::shared_ptr< class StatechartProfile > StatechartProfilePtr
IceInternal::Handle< JSONObject > JSONObjectPtr
Definition JSONObject.h:34
IceInternal::Handle< Event > EventPtr
Typedef of EventPtr as IceInternal::Handle<Event> for convenience.
Definition Event.h:40
IceInternal::Handle< XMLStateFactoryBase > XMLStateFactoryBasePtr
Definition XMLState.h:64
IceInternal::Handle< StateBase > StateBasePtr
Definition StateBase.h:49
IceInternal::Handle< ParameterMapping > ParameterMappingPtr
Vertex source(const detail::edge_base< Directed, Vertex > &e, const PCG &)
This file contains rapidxml parser and DOM implementation.
StateBasePtr clone() const override
Pure virtual function to clone of the derived class type.
Definition XMLState.cpp:68
static SubClassRegistry Registry
Definition XMLState.h:162
static std::string GetName()
Definition XMLState.cpp:62
NoUserCodeState(XMLStateConstructorParams stateData)
Definition XMLState.cpp:50
static XMLStateFactoryBasePtr CreateInstance(XMLStateConstructorParams stateData)
Definition XMLState.cpp:56
RapidXmlReaderPtr stateReader
Definition XMLState.cpp:181
StatechartProfilePtr selectedProfile
Definition XMLState.cpp:183
StringXMLNodeMapPtr uuidToXMLMap
Definition XMLState.cpp:184
std::filesystem::path xmlFilepath
Definition XMLState.cpp:180
RapidXmlReaderNode stateNode
Definition XMLState.cpp:182
Ice::CommunicatorPtr ic
Definition XMLState.cpp:185
XMLStateConstructorParams(const std::string &xmlFilepath, RapidXmlReaderPtr reader, StatechartProfilePtr selectedProfile, StringXMLNodeMapPtr uuidToXMLMap, Ice::CommunicatorPtr ic)
Definition XMLState.cpp:550
StatechartProfilePtr selectedProfile
Definition XMLState.h:53
StringXMLNodeMapPtr uuidToXMLMap
Definition XMLState.h:54
Ice::CommunicatorPtr ic
Definition XMLState.h:55