40 iceCommunicator(iceCommunicator), info(info)
47 QByteArray utf8Xml = xmlString.toUtf8();
60 QString version = readAttribute(stateNode,
"version");
62 if (version !=
"1.0" && version !=
"1.1" && version !=
"1.2")
65 "Only statechart XML definition version 1.0 - 1.2 are supported right now!");
68 if (readAttribute(stateNode,
"type",
false) ==
81 loadedState->setStateName(readAttribute(stateNode,
"name"));
82 loadedState->setSize(QSizeF(readAttribute(stateNode,
"width").
toFloat(),
83 readAttribute(stateNode,
"height").
toFloat()));
84 loadedState->setDescription(readDescription(stateNode));
92 while ((curNode = inputParameterNI.
getNext()))
94 parameterList.unite(readParameterList(curNode));
97 loadedState->setInputParameters(parameterList);
99 parameterList.clear();
103 while ((curNode = localParameterNI.
getNext()))
105 parameterList.unite(readParameterList(curNode));
108 loadedState->setLocalParameters(parameterList);
110 parameterList.clear();
112 XmlNodeIterator outputParameterNI(stateNode,
"OutputParameters",
false);
114 while ((curNode = outputParameterNI.
getNext()))
116 parameterList.unite(readParameterList(curNode));
119 loadedState->setOutputParameters(parameterList);
124 while ((curNode = substatesNI.
getNext()))
126 substateList.unite(readSubstateList(curNode));
129 loadedState->replaceSubstates(substateList);
134 while ((curNode = eventNI.
getNext()))
136 eventList.append(readEventList(curNode));
139 loadedState->setOutgoingEvents(eventList);
146 readStartState(startStateNode);
152 while ((curNode = transitionNI.
getNext()))
154 transitionList.append(readTransitionList(curNode));
157 loadedState->replaceTransitions(transitionList);
165 return descriptionNode ? QString::fromUtf8(descriptionNode->
value()) :
"";
176 while ((curNode = eventNI.getNext()))
180 event->description = readDescription(curNode);
182 for (EventList::const_iterator i = eventList.begin(); i != eventList.end(); ++i)
184 if ((*i)->name == event->name)
190 eventList.append(event);
197XmlReader::readParameterList(rapidxml::xml_node<>* parameterListNode)
const
200 rapidxml::xml_node<>* curNode;
202 XmlNodeIterator parameterNI(parameterListNode,
"Parameter",
false);
204 while ((curNode = parameterNI.getNext()))
207 stateParameter->type = readAttribute(curNode,
"type");
209 stateParameter->description = readDescription(curNode);
212 stateParameter->setDefaultValueJson(readAttribute(curNode,
"default",
false));
214 if (!stateParameter->getDefaultValueJson().isEmpty())
216 std::function<bool(std::string, std::string)> loadVar;
217 loadVar = [&](std::string curType, std::string prevType)
219 if (curType == prevType)
227 jsonObject->fromString(stateParameter->getDefaultValueJson().toUtf8().data());
229 stateParameter->profileDefaultValues[QString::fromUtf8(
231 VariantContainerBasePtr::dynamicCast(jsonObject->deserializeIceObject()),
232 stateParameter->getDefaultValueJson()};
234 catch (Ice::NoValueFactoryException& e)
236 ARMARX_INFO_S <<
"Variant missing - trying to load variant " << e.type
238 info->loadLibraryOfVariant(e.type);
240 return loadVar(e.type, curType);
249 catch (exceptions::user::UnknownTypeException& e)
252 << stateParameter->type;
254 catch (
const armarx::JSONException& e)
256 throw XmlReaderException(
"Could not parse JSON: " +
257 stateParameter->getDefaultValueJson().toStdString());
263 XmlNodeIterator defaultValueNI(curNode,
"DefaultValue",
false);
264 rapidxml::xml_node<>* defaultValueCurNode;
266 while ((defaultValueCurNode = defaultValueNI.getNext()))
268 QString profileName = readAttribute(defaultValueCurNode,
"profile",
false);
270 if (profileName.size() == 0)
275 QString valueJson = readAttribute(defaultValueCurNode,
"value",
true);
276 VariantContainerBasePtr valueVariant;
277 std::function<bool(std::string, std::string)> loadVar;
278 loadVar = [&](std::string curType, std::string prevType)
280 if (curType == prevType)
288 jsonObject->fromString(valueJson.toUtf8().data());
291 VariantContainerBasePtr::dynamicCast(jsonObject->deserializeIceObject());
293 catch (Ice::NoValueFactoryException& e)
295 ARMARX_INFO_S <<
"Variant missing - trying to load variant " << e.type
297 info->loadLibraryOfVariant(e.type);
299 return loadVar(e.type, curType);
308 catch (exceptions::user::UnknownTypeException& e)
311 << stateParameter->type;
313 catch (
const armarx::JSONException& e)
315 throw XmlReaderException(
"Could not parse JSON: " + valueJson.toStdString());
318 stateParameter->profileDefaultValues[profileName] =
319 QPair<VariantContainerBasePtr, QString>(valueVariant, valueJson);
322 QString optionalStr = readAttribute(curNode,
"optional");
324 if (optionalStr ==
"yes")
326 stateParameter->optional =
true;
328 else if (optionalStr ==
"no")
330 stateParameter->optional =
false;
334 throw XmlReaderException(
"\"optional\" attribute must have value \"yes\" or \"no\"!");
337 QString parameterName = readAttribute(curNode,
"name");
339 if (stateParameterMap.contains(parameterName))
341 throw XmlReaderException(
"Duplicate parameter name: " + parameterName.toStdString());
344 stateParameterMap[parameterName] = stateParameter;
347 return stateParameterMap;
351XmlReader::readParameterMappingList(rapidxml::xml_node<>* parameterMappingListNode)
const
354 rapidxml::xml_node<>* curNode;
356 XmlNodeIterator parameterMappingNI(parameterMappingListNode,
"ParameterMapping",
false);
358 while ((curNode = parameterMappingNI.getNext()))
361 new statechartmodel::ParameterMapping());
362 parameterMapping->sourceKey = readAttribute(curNode,
"from");
363 parameterMapping->destinationKey = readAttribute(curNode,
"to");
365 QString mappingSourceString = readAttribute(curNode,
"sourceType");
368 if (parameterMapping->source == eMappingSourcesCount)
370 throw XmlReaderException(
"Unknown value for sourceType: \"" +
371 mappingSourceString.toStdString() +
"\"");
375 XmlNodeIterator defaultValueNI(curNode,
"DefaultValue",
false);
376 rapidxml::xml_node<>* defaultValueCurNode;
378 while ((defaultValueCurNode = defaultValueNI.getNext()))
380 QString profileName = readAttribute(defaultValueCurNode,
"profile",
false);
382 if (profileName.size() == 0)
387 QString valueJson = readAttribute(defaultValueCurNode,
"value",
true);
388 parameterMapping->profileValues[profileName] = valueJson;
392 parameterMappingList.append(parameterMapping);
395 return parameterMappingList;
399XmlReader::readStartState(rapidxml::xml_node<>* startStateNode)
const
401 loadedState->setStartState(
402 getSubstateByInstanceName(readAttribute(startStateNode,
"substateName")));
404 rapidxml::xml_node<>* parameterMappingsNode =
405 XmlNodeIterator(startStateNode,
"ParameterMappings",
false).getNext();
407 if (parameterMappingsNode)
409 loadedState->setStartStateInputMapping(readParameterMappingList(parameterMappingsNode));
412 rapidxml::xml_node<>* supportPointsNode =
413 XmlNodeIterator(startStateNode,
"SupportPoints",
false).getNext();
414 SupportPoints points;
415 if (supportPointsNode)
417 rapidxml::xml_node<>* supportPointNode;
418 XmlNodeIterator supportPointNI(supportPointsNode,
"SupportPoint",
false);
420 while ((supportPointNode = supportPointNI.getNext()))
422 QPointF supportPoint(readAttribute(supportPointNode,
"posX").
toFloat(),
423 readAttribute(supportPointNode,
"posY").
toFloat());
425 supportPoints.append(supportPoint);
428 loadedState->setTransitionSupportPoints(transition, points);
434XmlReader::readSubstateList(rapidxml::xml_node<>* substateListNode)
const
437 rapidxml::xml_node<>* curNode = substateListNode->
first_node();
444 if (!stateInstanceFactory)
446 throw XmlReaderException(
"Invalid substate type: \"" + std::string(curNode->
name()) +
452 QString stateInstanceName = stateInstance->getInstanceName();
454 if (stateInstanceMap.contains(stateInstanceName))
456 throw XmlReaderException(
"Duplicate substate name: " + stateInstanceName.toStdString());
459 stateInstanceMap[stateInstanceName] = stateInstance;
464 return stateInstanceMap;
468XmlReader::readTransitionList(rapidxml::xml_node<>* transitionListNode)
const
471 rapidxml::xml_node<>* curNode;
473 XmlNodeIterator transitionNI(transitionListNode,
"Transition",
false);
475 while ((curNode = transitionNI.getNext()))
479 QString sourceStateName = readAttribute(curNode,
"from");
480 QString eventName = readAttribute(curNode,
"eventName");
482 if (!hasSubstateByInstanceName(sourceStateName))
485 << loadedState->getStateName().toStdString() <<
"'. SourceState '"
486 << sourceStateName <<
"' of event '" << eventName
487 <<
"' could not be found in the list of substates. State UUID="
488 << loadedState->getUUID()
489 <<
".\nStatechart group information or state path are not available "
490 "at this point. Sorry. Use grep.";
494 transition->sourceState = getSubstateByInstanceName(sourceStateName);
495 transition->destinationState =
496 getSubstateByInstanceName(readAttribute(curNode,
"to",
false));
497 transition->eventName = eventName;
498 transition->transitionUserCode =
499 readAttribute(curNode,
"transitionCodeEnabled",
false) ==
"1";
501 rapidxml::xml_node<>* parameterMappingsNode =
502 XmlNodeIterator(curNode,
"ParameterMappings",
false).getNext();
504 if (parameterMappingsNode)
506 transition->mappingToNextStatesInput = readParameterMappingList(parameterMappingsNode);
509 parameterMappingsNode =
510 XmlNodeIterator(curNode,
"ParameterMappingsToParentsLocal",
false).getNext();
512 if (parameterMappingsNode)
514 transition->mappingToParentStatesLocal =
515 readParameterMappingList(parameterMappingsNode);
518 parameterMappingsNode =
519 XmlNodeIterator(curNode,
"ParameterMappingsToParentsOutput",
false).getNext();
521 if (parameterMappingsNode)
523 transition->mappingToParentStatesOutput =
524 readParameterMappingList(parameterMappingsNode);
527 rapidxml::xml_node<>* supportPointsNode =
528 XmlNodeIterator(curNode,
"SupportPoints",
false).getNext();
530 if (supportPointsNode)
532 rapidxml::xml_node<>* supportPointNode;
533 XmlNodeIterator supportPointNI(supportPointsNode,
"SupportPoint",
false);
535 while ((supportPointNode = supportPointNI.getNext()))
537 QPointF supportPoint(readAttribute(supportPointNode,
"posX").
toFloat(),
538 readAttribute(supportPointNode,
"posY").
toFloat());
540 supportPoints.append(supportPoint);
542 transition->supportPoints.setControlPoints(supportPoints);
545 transitionList.append(transition);
548 return transitionList;
552XmlReader::hasSubstateByInstanceName(
const QString& name)
const
559 return loadedState->getSubstates().contains(name);
563XmlReader::getSubstateByInstanceName(
const QString& name)
const
572 if (!substates.contains(name))
574 std::stringstream ss;
575 ss <<
"Available substates (";
576 ss << substates.size();
579 for (QString s : substates.keys())
581 ss <<
s.toStdString() <<
"; ";
584 throw XmlReaderException(
"Referenced substate \"" + name.toStdString() +
585 "\" not found in State \"" +
586 loadedState->getStateName().toStdString() +
"\"! " + ss.str());
589 return substates[name];
593XmlReader::readAttribute(rapidxml::xml_node<>* node,
594 const QString& attributeName,
597 rapidxml::xml_attribute<>* attribute = node->
first_attribute(attributeName.toUtf8());
603 throw XmlReaderException(
"Attribute \"" + attributeName.toStdString() +
"\" for \"" +
604 node->
name() +
"\" node not found!");
612 return QString::fromUtf8(attribute->
value());
616 const QString& nodeName,
618 parentNode(parentNode),
621 nodeNameUtf8(nodeName.
toUtf8()),
629 if (currentChildNode)
638 currentChildNode = nextChildNode;
642 currentChildNode = parentNode->first_node(nodeNameUtf8.data());
644 if (required && !currentChildNode)
646 throw XmlReaderException(
"Required node \"" + nodeName.toStdString() +
"\" not found!");
650 return currentChildNode;
QString readAttribute(rapidxml::xml_node<> *node, const QString &attributeName, bool required=true)
static SharedPointerType fromName(const std::string &name, XmlParentPair params)
static void RegisterKnownObjectFactoriesWithIce(const Ice::CommunicatorPtr &ic)
Registers all object factories that are known with Ice.
static MappingSource StringToMappingSource(const std::string &mappingSourceString)
static std::string GetRootName()
Iterate over all child nodes with a certain name of a given XML node.
rapidxml::xml_node * getNext()
XmlNodeIterator(rapidxml::xml_node<> *parentNode, const QString &nodeName, bool required)
void parseXml(const QString &xmlString)
Parses the given XML document and builds a State object (that can be retrieved using getRootState()).
XmlReader(Ice::CommunicatorPtr iceCommunicator, VariantInfoPtr info)
Creates a new XmlReader.
static QString StateTypeToString(eStateType type)
const char * what() const noexcept override
Gets human readable description of error.
Ch * value() const
Gets value of node.
Ch * name() const
Gets name of the node.
This class represents root of the DOM hierarchy.
void parse(Ch *text)
Parses zero-terminated XML string according to given flags.
Class representing a node of XML document.
xml_node< Ch > * next_sibling(const Ch *name=nullptr, std::size_t name_size=0, bool case_sensitive=true) const
Gets next sibling node, optionally matching node name.
xml_node< Ch > * first_node(const Ch *name=nullptr, std::size_t name_size=0, bool case_sensitive=true) const
Gets first child node, optionally matching node name.
xml_attribute< Ch > * first_attribute(const Ch *name=nullptr, std::size_t name_size=0, bool case_sensitive=true) const
Gets first attribute of node, optionally matching attribute name.
#define ARMARX_IMPORTANT_S
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
::IceInternal::Handle<::Ice::Communicator > CommunicatorPtr
std::string toUtf8(QString const &qstring)
double s(double t, double s0, double v0, double a0, double j)
std::pair< rapidxml::xml_node<> *, armarx::statechartmodel::StatePtr > XmlParentPair
std::shared_ptr< StateInstanceFactoryBase > StateInstanceFactoryBasePtr
std::shared_ptr< State > StatePtr
QMap< QString, StateParameterPtr > StateParameterMap
std::shared_ptr< StateInstance > StateInstancePtr
std::shared_ptr< StateParameter > StateParameterPtr
QList< ParameterMappingPtr > ParameterMappingList
QList< TransitionPtr > TransitionList
std::shared_ptr< const State > StateCPtr
std::shared_ptr< Event > EventPtr
std::shared_ptr< const Transition > TransitionCPtr
QList< EventPtr > EventList
std::shared_ptr< ParameterMapping > ParameterMappingPtr
QMap< QString, StateInstancePtr > StateInstanceMap
std::shared_ptr< Transition > TransitionPtr
std::shared_ptr< VariantInfo > VariantInfoPtr
IceInternal::Handle< JSONObject > JSONObjectPtr
float toFloat(const std::string &input)
Converts a string to float and uses always dot as seperator.
QList< QPointF > QPointList
const int parse_validate_closing_tags
Parse flag instructing the parser to validate closing tag names.
void setControlPoints(QList< QPointF > list)