29 #include <boost/format.hpp>
31 #include <SimoxUtility/algorithm/string/string_tools.h>
46 std::set<std::string> usedProfiles;
49 stateNode.
nodes(
"InputParameters",
"Parameter",
"DefaultValue"))
51 usedProfiles.insert(defaultNode.attribute_value_or_default(
"profile",
"Root"));
55 stateNode.
nodes(
"OutputParameters",
"Parameter",
"DefaultValue"))
57 usedProfiles.insert(defaultNode.attribute_value_or_default(
"profile",
"Root"));
61 stateNode.
nodes(
"LocalParameters",
"Parameter",
"DefaultValue"))
63 usedProfiles.insert(defaultNode.attribute_value_or_default(
"profile",
"Root"));
70 StatechartGroupDocGenerator::unescapeString(std::string
str)
const
73 std::string::const_iterator it =
str.begin();
75 while (it !=
str.end())
79 if (
c ==
'\\' && it !=
str.end())
113 StatechartGroupDocGenerator::nToBr(std::string
str)
const
115 return simox::alg::replace_all(
str,
"\n",
"<br />\n");
119 StatechartGroupDocGenerator::buildParameterTable(RapidXmlReaderNode parametersNode)
const
121 std::set<std::string> usedProfiles;
123 for (RapidXmlReaderNode defaultNode : parametersNode.nodes(
"Parameter",
"DefaultValue"))
125 usedProfiles.insert(defaultNode.attribute_value_or_default(
"profile",
"Root"));
128 std::vector<std::string> header;
130 header.push_back(
"Name");
131 header.push_back(
"Type");
132 header.push_back(
"Description");
133 std::copy(usedProfiles.begin(), usedProfiles.end(), std::back_inserter(header));
136 for (RapidXmlReaderNode parameterNode : parametersNode.nodes(
"Parameter"))
138 std::vector<std::string> row(header.size());
139 row.at(0) = parameterNode.attribute_value(
"name");
140 row.at(1) = parameterNode.has_attribute(
"docType")
141 ? parameterNode.attribute_value(
"docType")
142 : parameterNode.attribute_value(
"type");
143 row.at(2) = nToBr(parameterNode.first_node_value_or_default(
"Description",
""));
145 for (RapidXmlReaderNode defaultNode : parameterNode.nodes(
"DefaultValue"))
147 int index = std::find(header.begin(),
149 defaultNode.attribute_value_or_default(
"profile",
"Root")) -
151 std::string defaultValue = defaultNode.has_attribute(
"docValue")
152 ? defaultNode.attribute_value(
"docValue")
153 : defaultNode.attribute_value(
"value");
154 row.at(
index) = nToBr(unescapeString(defaultValue));
164 StatechartGroupDocGenerator::addParameterTable(
const DoxDocPtr& doc,
165 const RapidXmlReaderNode& stateNode,
167 const char* nodeName)
const
169 DoxTablePtr table = buildParameterTable(stateNode.first_node(nodeName));
171 if (table->rows() == 0)
173 doc->addLine(
"No " + name +
".<br />");
177 doc->addLine(name +
":");
178 doc->addEntry(table);
183 StatechartGroupDocGenerator::getNodeAttrsFromStateType(
const std::string& nodeType)
const
185 if (nodeType ==
"EndState")
187 return "shape=box,style=filled,fillcolor=\"#FFFF96\"";
190 if (nodeType ==
"RemoteState")
192 return "shape=box,style=filled,fillcolor=\"#96FFFA\"";
195 if (nodeType ==
"DynamicRemoteState")
197 return "shape=box,style=filled,fillcolor=\"#B147EA\"";
200 return "shape=box,style=filled,fillcolor=\"#B3D7FF\"";
207 std::string packageName = reader->getPackageName();
208 std::string groupName = reader->getGroupName();
209 doc->addLine(fmt(
"@defgroup %s-%s %s", packageName, groupName, groupName));
210 doc->addLine(fmt(
"@ingroup Statecharts %s-Statecharts", packageName));
211 doc->addLine(nToBr(reader->getDescription()));
214 bool anyPrivateStateFound =
false;
216 for (std::string statefile : reader->getStateFilepaths())
220 anyPrivateStateFound =
true;
224 if (anyPrivateStateFound)
227 doc->addLine(fmt(
"@defgroup %s-%s-PrivateStates %s Private States",
231 doc->addLine(fmt(
"@ingroup %s-%s", packageName, groupName));
234 for (std::string statefile : reader->getStateFilepaths())
243 doc->addLine(fmt(
"@defgroup State-%s %s", stateUuid, stateName));
245 fmt(
"@ingroup %s-%s%s",
250 :
"-PrivateStates"));
252 "Description",
"This state has no description."));
255 addParameterTable(doc, stateNode,
"\\b Input \\b Parameters",
"InputParameters");
256 addParameterTable(doc, stateNode,
"\\b Local \\b Parameters",
"LocalParameters");
257 addParameterTable(doc, stateNode,
"\\b Output \\b Parameters",
"OutputParameters");
259 doc->addLine(
"<br/>\\b State \\b used by:<br />");
263 std::set<std::string> users =
usageMap.find(stateUuid)->second;
265 for (std::string uuid : users)
267 doc->addLine(fmt(
"@ref State-%s <br />", uuid));
271 doc->addLine(
"<br/>\\b Substates:<br />");
275 if (substateNode.name() ==
"LocalState" || substateNode.name() ==
"RemoteState" ||
276 substateNode.name() ==
"DynamicRemoteState")
278 std::string name = substateNode.attribute_value(
"name");
279 std::string refuuid = substateNode.attribute_value(
"refuuid");
280 std::map<std::string, StateInfo>::const_iterator it =
286 fmt(
"@ref State-%s \"%s (External Package)\"<br />", refuuid, name));
290 StateInfo stateInfo = it->second;
292 if (stateInfo.group == groupName && stateInfo.state == name)
294 doc->addLine(fmt(
"@ref State-%s<br />", refuuid));
296 else if (stateInfo.group == groupName)
298 doc->addLine(fmt(
"%s -> @ref State-%s \"%s\"<br />",
305 doc->addLine(fmt(
"%s -> @ref State-%s \"%s-%s\"<br />",
315 doc->addLine(
"<br/>\\b Statechart \\b layout:");
317 graph->addNode(
"",
"shape=point");
322 graph->addTransition(
"", startStateNode.
attribute_value(
"substateName"),
"");
327 std::string shape = getNodeAttrsFromStateType(substateNode.name());
328 graph->addNode(substateNode.attribute_value(
"name"), shape);
333 if (transition.has_attribute(
"from") && transition.has_attribute(
"to") &&
334 transition.has_attribute(
"eventName"))
336 std::string from = transition.attribute_value_or_default(
"from",
"");
337 std::string to = transition.attribute_value_or_default(
"to",
"");
338 std::string eventName = transition.attribute_value_or_default(
"eventName",
"");
340 graph->addTransition(from, to, eventName);
344 if (graph->transitionCount() > 0)
346 doc->addEntry(graph);
377 doc->writeDoc(writer);
378 return writer->getString();
382 StatechartGroupDocGenerator::fmt(
const std::string& fmt,
const std::string& arg1)
const
388 StatechartGroupDocGenerator::fmt(
const std::string& fmt,
389 const std::string& arg1,
390 const std::string& arg2)
const
392 return boost::str(boost::format(fmt) % arg1 % arg2);
396 StatechartGroupDocGenerator::fmt(
const std::string& fmt,
397 const std::string& arg1,
398 const std::string& arg2,
399 const std::string& arg3)
const
401 return boost::str(boost::format(fmt) % arg1 % arg2 % arg3);
405 StatechartGroupDocGenerator::fmt(
const std::string& fmt,
406 const std::string& arg1,
407 const std::string& arg2,
408 const std::string& arg3,
409 const std::string& arg4)
const
411 return boost::str(boost::format(fmt) % arg1 % arg2 % arg3 % arg4);
418 reader->readXml(std::filesystem::path(groupDefinitionFilePath));
421 std::filesystem::path doxyFile = finder.
getBuildDir();
428 if (!doxyFile.string().empty())
430 doxyFile /=
"doxygen";
437 doxyFile /= reader->getGroupName() +
".dox";
440 file.open(doxyFile.string().c_str());
450 ARMARX_INFO_S <<
"wrote " << docstr.size() <<
" bytes to " << doxyFile.string();
456 for (std::string groupDefinitionFilePath : groups)
460 reader->readXml(std::filesystem::path(groupDefinitionFilePath));
462 for (std::string statefile : reader->getStateFilepaths())
470 StateInfo(reader->getPackageName(), reader->getGroupName(), stateName)));
474 if (substateNode.name() ==
"LocalState" ||
475 substateNode.name() ==
"RemoteState" ||
476 substateNode.name() ==
"DynamicRemoteState")
479 std::string refuuid = substateNode.attribute_value(
"refuuid");
483 usageMap.insert(std::make_pair(refuuid, std::set<std::string>()));
486 usageMap[refuuid].insert(stateUuid);
496 for (std::string groupDefinitionFilePath : groups)
508 std::vector<std::string>
510 const std::filesystem::path& path)
512 std::vector<std::string> result;
518 for (std::filesystem::recursive_directory_iterator end, dir(path); dir != end;
521 if (dir->path().extension() ==
".scgxml" &&
522 dir->path().string().find(
"deprecated") == std::string::npos)
524 result.push_back(dir->path().c_str());
529 ARMARX_INFO_S <<
"Scanning file " << i <<
": " << dir->path().c_str();
533 catch (std::exception& e)
544 auto itFinders =
finders.find(reader->getPackageName());
546 if (itFinders ==
finders.end())
549 .insert(std::make_pair(reader->getPackageName(),
554 return itFinders->second;