summaryrefslogtreecommitdiffstats
path: root/src/uscxml/debug/SCXMLDotWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml/debug/SCXMLDotWriter.cpp')
-rw-r--r--src/uscxml/debug/SCXMLDotWriter.cpp888
1 files changed, 0 insertions, 888 deletions
diff --git a/src/uscxml/debug/SCXMLDotWriter.cpp b/src/uscxml/debug/SCXMLDotWriter.cpp
deleted file mode 100644
index 56de37a..0000000
--- a/src/uscxml/debug/SCXMLDotWriter.cpp
+++ /dev/null
@@ -1,888 +0,0 @@
-/**
- * @file
- * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
- * @copyright Simplified BSD
- *
- * @cond
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the FreeBSD license as published by the FreeBSD
- * project.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the FreeBSD license along with this
- * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
- * @endcond
- */
-
-#include "uscxml/Common.h"
-#include "uscxml/UUID.h"
-#include "SCXMLDotWriter.h"
-#include "../transform/FlatStateIdentifier.h"
-#include "uscxml/dom/DOMUtils.h"
-#include <boost/algorithm/string.hpp> // replace_all
-#include <iomanip>
-
-namespace uscxml {
-
-using namespace Arabica::DOM;
-using namespace Arabica::XPath;
-
-SCXMLDotWriter::SCXMLDotWriter() {
- _iteration = 0;
- _indentation = 0;
-}
-
-SCXMLDotWriter::SCXMLDotWriter(Interpreter interpreter,
- const std::list<SCXMLDotWriter::StateAnchor>& stateAnchors,
- const Element<std::string>& transition) {
- _interpreter = interpreter;
- _xmlNSPrefix = _interpreter.getNameSpaceInfo().xmlNSPrefix;
- _transition = transition;
- _anchors = stateAnchors;
-
- NodeList<std::string > scxmlElems = interpreter.getDocument().getElementsByTagName("scxml");
- _scxml = (Element<std::string>)scxmlElems.item(0);
- _isFlat = HAS_ATTR(_scxml, "flat") && stringIsTrue(ATTR(_scxml, "flat"));
-
- if (_anchors.size() == 0) {
- StateAnchor anchor;
- anchor.element = _scxml;
- _anchors.push_back(anchor);
- }
-
- for (std::list<StateAnchor>::iterator anchIter = _anchors.begin(); anchIter != _anchors.end(); anchIter++) {
- if (!anchIter->element)
- anchIter->element = _scxml;
- if (anchIter->childDepth >= 0 && anchIter->transDepth == -1)
- anchIter->transDepth = anchIter->childDepth;
-
- _portType = anchIter->type;
- assembleGraph(anchIter->element, anchIter->childDepth, anchIter->transDepth + 1);
- }
-
- _iteration = 0;
- _indentation = 0;
-}
-
-SCXMLDotWriter::~SCXMLDotWriter() {
-
-}
-
-void SCXMLDotWriter::onStableConfiguration(Interpreter interpreter) {
- std::ostringstream fileSS;
- fileSS << interpreter.getName() << "." << std::setw(6) << std::setfill('0') << _iteration++ << ".dot";
- toDot(fileSS.str(), interpreter);
-}
-
-void SCXMLDotWriter::afterCompletion(Interpreter interpreter) {
- std::ostringstream fileSS;
- fileSS << interpreter.getName() << "." << std::setw(6) << std::setfill('0') << _iteration++ << ".dot";
- toDot(fileSS.str(), interpreter);
-}
-
-void SCXMLDotWriter::beforeMicroStep(Interpreter interpreter) {
-// std::ostringstream fileSS;
-// fileSS << interpreter.getName() << "." << std::setw(6) << std::setfill('0') << _iteration++ << ".dot";
-// toDot(fileSS.str(), interpreter);
-}
-
-void SCXMLDotWriter::beforeTakingTransition(Interpreter interpreter,
- const Element<std::string>& transition,
- bool moreComing) {
- std::ostringstream fileSS;
- fileSS << interpreter.getName() << "." << std::setw(6) << std::setfill('0') << _iteration++ << ".dot";
- toDot(fileSS.str(), interpreter, transition);
-}
-
-std::string SCXMLDotWriter::getPrefix() {
- std::string prefix = "";
- for (size_t i = 0; i < _indentation; i++)
- prefix += " ";
- return prefix;
-}
-
-void SCXMLDotWriter::writeTo(std::ostream& os) {
- os << "digraph {" << std::endl;
- os << " rankdir=LR;" << std::endl;
- os << " fontsize=10;" << std::endl;
- // outfile << " splines=ortho;" << std::endl;
- // outfile << " splines=false;" << std::endl;
- // outfile << " nodesep=1.0;" << std::endl;
-
- _indentation++;
- writeStateElement(os, _scxml);
-
- // write edges at end of file
- for(std::set<DotEdge>::iterator edgeIter = _edges.begin(); edgeIter != _edges.end(); edgeIter++) {
- if (edgeIter->from == edgeIter->to)
- continue;
- if (_histories.find(edgeIter->to) != _histories.end()) {
- if (_histories.find(edgeIter->to)->second.from == _histories.find(edgeIter->to)->second.to)
- continue;
- }
-
- os << getPrefix() << "\"" << portEscape(edgeIter->from) << "\"";
- if (edgeIter->fromPort.size() > 0) {
- os << std::string(":\"") + portEscape(edgeIter->fromPort) + "\":e";
- } else {
- os << ":__name";
- }
- os << " -> ";
-
- if (_histories.find(edgeIter->to) != _histories.end()) {
- os << getPrefix() << "\"" << portEscape(_histories.find(edgeIter->to)->second.to) << "\"";
- if (_histories.find(edgeIter->to)->second.toPort.size() > 0) {
- os << std::string(":\"") + portEscape(_histories.find(edgeIter->to)->second.toPort) + "\"";
- } else {
- os << ":__name";
- }
-
- } else {
- os << getPrefix() << "\"" << portEscape(edgeIter->to) << "\"";
- if (edgeIter->toPort.size() > 0) {
- os << std::string(":\"") + portEscape(edgeIter->toPort) + "\"";
- } else {
- os << ":__name";
- }
- }
-
- if (edgeIter->type == EDGE_INITAL) {
- os << ":nw [style=\"dashed\", color=\"black\"]";
- } else {
- os << " [color=\"black\"]";
- }
- os << std::endl;
-
- }
-
- _indentation--;
-
- os << "}" << std::endl;
-
-}
-
-void SCXMLDotWriter::toDot(const std::string& filename,
- Interpreter interpreter,
- const std::list<SCXMLDotWriter::StateAnchor>& stateAnchors,
- const Element<std::string>& transition) {
-
- std::ofstream outfile(filename.c_str());
- SCXMLDotWriter writer(interpreter, stateAnchors, transition);
- writer.writeTo(outfile);
-
-}
-
-/**
- * Walk the subset of the graph that is reachable and remember the nodes
- */
-void SCXMLDotWriter::assembleGraph(const Element<std::string>& state, int32_t childDepth, int32_t transDepth) {
- std::string nodeId = idForNode(state);
-
- // this node is neither included per child, nor per transition
- if (childDepth <= 0 && transDepth <= 0) {
- return;
- }
-
- // been here
- if (_graph.find(nodeId) != _graph.end())
- return;
-
- _graph[nodeId].node = state;
- _graph[nodeId].portType = _portType;
-
-
- if (childDepth == 0 && transDepth == 0) {
- _graph[nodeId].isBorder = true;
- }
-
-
- NodeSet<std::string> childElems = DOMUtils::filterChildType(Node_base::ELEMENT_NODE, state);
- for (size_t i = 0; i < childElems.size(); i++) {
- Element<std::string> childElem(childElems[i]);
-
- // remember histories we passed
- if (iequals(TAGNAME(childElem), "history")) {
- _histories[ATTR(childElem, "id")].to = ATTR(state, "id");
- _histories[ATTR(childElem, "id")].toPort = ATTR(childElem, "id");
- }
-
- // follow transitions
- if (iequals(TAGNAME(childElem), "transition")) {
- _graph[nodeId].transitions.push_back(childElem);
- NodeSet<std::string> targetStates = _interpreter.getImpl()->getTargetStates(childElem);
- for (size_t j = 0; j < targetStates.size(); j++) {
- std::string remoteNodeId = idForNode(targetStates[j]);
- _graph[nodeId].targets.insert(std::make_pair(remoteNodeId, childElem));
-
- // recurse along the transition targets, no weight from child depth
- assembleGraph((Element<std::string>)targetStates[j], 0, transDepth - 1);
- }
- if (targetStates.size() == 0)
- _graph[nodeId].targets.insert(std::make_pair(nodeId, childElem));
-
- std::list<std::string> eventNames;
- if (HAS_ATTR(childElem, "event"))
- eventNames = tokenize(ATTR(childElem, "event"));
- if (eventNames.size() == 0)
- _graph[nodeId].events.insert(std::make_pair("", childElem));
- for (std::list<std::string>::iterator evIter = eventNames.begin(); evIter != eventNames.end(); evIter++) {
- _graph[nodeId].events.insert(std::make_pair(*evIter, childElem));
- }
- }
-
- // follow childs
- if (InterpreterImpl::isState(Element<std::string>(childElem))) {
- if (_interpreter.getImpl()->isInitial(Element<std::string>(childElem))) {
- // add to initial states if it is initial
- _graph[nodeId].initialchilds.insert(idForNode(childElem));
- } else if (_interpreter.getImpl()->isParallel(Element<std::string>(state))) {
- // add to initial states if we are parallel
- _graph[nodeId].initialchilds.insert(idForNode(childElem));
- }
- // in any case, it is a child state
- _graph[nodeId].childs.insert(idForNode(childElem));
-
- // recurse (do we really need to?)
- assembleGraph(childElem, childDepth - 1, transDepth);
- }
-
- }
-}
-
-
-/**
- * Walk the complete graph and draw reachable subset
- */
-void SCXMLDotWriter::writeStateElement(std::ostream& os, const Element<std::string>& stateElem) {
- std::string stateId = idForNode(stateElem);
-
- if (_knownIds.find(stateId) != _knownIds.end())
- return;
- _knownIds.insert(stateId);
-
- std::list<Node<std::string> > invisParents;
- bool isVisible = (_graph.find(stateId) != _graph.end());
-
- bool subgraph = InterpreterImpl::isCompound(stateElem) || InterpreterImpl::isParallel(stateElem);
- bool fatherIsParallel = (stateElem.getParentNode() &&
- stateElem.getParentNode().getNodeType() == Node_base::ELEMENT_NODE &&
- InterpreterImpl::isParallel(Element<std::string>(stateElem.getParentNode())));
-
- if (subgraph) {
- _indentation++;
- os << std::endl;
- os << getPrefix() << "subgraph \"cluster_" << portEscape(stateId) << "\" {" << std::endl;
- _indentation++;
- os << getPrefix() << "fontsize=14" << std::endl;
- os << getPrefix() << "label=<" << nameForNode(stateElem) << ">" << std::endl;
- // os << getPrefix() << "rank=\"same\"" << std::endl;
- os << getPrefix() << "labeljust=l" << std::endl;
-
- os << getPrefix() << (fatherIsParallel ? "style=dashed" : "style=solid") << std::endl;
-
- // os << getPrefix() << "ranksep=\"equally\"" << std::endl;
-
- }
-
- if (isVisible) {
- // this state is visible!
- const DotState& dotState = _graph.find(stateId)->second;
-
- // is this a subgraph?
-
- os << std::endl;
- os << getPrefix() << "\"" << portEscape(stateId) << "\" [" << std::endl;
- _indentation++;
-
- os << getPrefix() << "fontsize=10," << std::endl;
- os << getPrefix() << "shape=plaintext," << std::endl;
- os << getPrefix() << (fatherIsParallel ? "style=dashed," : "style=solid,") << std::endl;
-
- // is the current state in the basic configuration?
- if (InterpreterImpl::isMember(stateElem, _interpreter.getBasicConfiguration()))
- os << getPrefix() << "color=red, penwidth=3," << std::endl;
-
- // is the current state in the basic configuration?
- if (dotState.isBorder)
- os << getPrefix() << "color=blue," << std::endl;
-
- // is this state final?
- if (_interpreter.getImpl()->isFinal(stateElem)) {
- os << getPrefix() << "shape=doublecircle," << std::endl;
- os << getPrefix() << "color=black," << std::endl;
- os << getPrefix() << "penwidth=2," << std::endl;
- os << getPrefix() << "label=< <table cellborder=\"0\" border=\"0\"><tr><td balign=\"left\">" << nameForNode(stateElem) << "</td></tr></table>>" << std::endl;
- _indentation--;
- os << getPrefix() << "];" << std::endl;
-
- return;
- }
-
- // is the state initial?
- bool isInitial = _interpreter.getImpl()->isInitial(stateElem);
- // if (isInitial)
- // os << getPrefix() << "style=filled, fillcolor=lightgrey, " << std::endl;
-
- DotState::mmap_s_e_t::const_iterator destIterF, destIterB;
- //std::list<std::string> outPorts; // count unique keys
-
- int nrOutPorts = 0;
-
- switch (dotState.portType) {
- case PORT_TARGET: // outports are per target
- for(DotState::mmap_s_e_t::const_iterator it = dotState.targets.begin(), end = dotState.targets.end();
- it != end;
- it = dotState.targets.upper_bound(it->first)) {
- nrOutPorts++;
- }
- break;
- case PORT_EVENT: // outports are per event
- for(DotState::mmap_s_e_t::const_iterator it = dotState.events.begin(), end = dotState.events.end();
- it != end;
- it = dotState.events.upper_bound(it->first)) {
- nrOutPorts++;
- }
- break;
- case PORT_TRANSITION:
- nrOutPorts = dotState.transitions.size();
-// for (size_t i = 0; i < dotState.transitions.size(); i++) {
-// outPorts.push_back(idForNode(dotState.transitions[i]));
-// }
- break;
- }
-
- os << getPrefix() << "label = < " << std::endl;
-
- /*
- <table cellborder="1" border="0" cellspacing="0" cellpadding="2" style="rounded">
- <tr><td port="name" rowspan="4"><b>step</b></td></tr>
- <tr><td port="foo.error.port" align="right">foo.error.port</td></tr>
- <tr><td port="bar" align="right">bar</td></tr>
- <tr><td port="baz" align="right">baz</td></tr>
- </table>
- */
-
- std::string details = getDetailedLabel(stateElem);
- std::string stateLabel = nameForNode(stateElem);
- int stateLines = 0;
-
- std::string::size_type start = 0;
- while ((start = stateLabel.find("<br", start)) != std::string::npos) {
- ++stateLines;
- start += 3;
- }
-
- os << "<table " << (isInitial ? "bgcolor=\"orange\" " : "") << "valign=\"top\" align=\"left\" cellborder=\"1\" border=\"0\" cellspacing=\"0\" cellpadding=\"5\" >" << std::endl;
- os << " <tr><td port=\"__name\" balign=\"left\" valign=\"top\" align=\"left\" rowspan=\"" << nrOutPorts + 1 << "\">" << stateLabel << "</td></tr>" << std::endl;
-
- switch (dotState.portType) {
- case PORT_TARGET: // outports are per target
- writePerTargetPorts(os, dotState, stateLines);
- break;
- case PORT_EVENT: // outports are per event
- writePerEventPorts(os, dotState, stateLines);
- break;
- case PORT_TRANSITION:
- writePerTransitionPorts(os, dotState, stateLines);
- break;
- }
-
-
- // write details of the state
- if (details.size() > 0) {
- os << " <tr><td balign=\"left\" colspan=\"" << (nrOutPorts == 0 ? 1 : 2) << "\">" << std::endl;
- os << details << std::endl;
- os << " </td></tr>" << std::endl;
- }
-
- // write history states
- NodeSet<std::string> histories = DOMUtils::filterChildElements(_xmlNSPrefix + "history", stateElem);
- for (size_t i = 0; i < histories.size(); i++) {
- os << " <tr><td port=\"" << portEscape(ATTR_CAST(histories[i], "id")) << "\" balign=\"left\" colspan=\"" << (nrOutPorts == 0 ? 1 : 2) << "\"><b>history: </b>" << ATTR_CAST(histories[i], "id") << "</td></tr>" << std::endl;
-
- }
-
- os << "</table>" << std::endl << getPrefix() << ">" << std::endl;
-
- _indentation--;
- os << getPrefix() << "];" << std::endl;
-
- for (std::set<std::string>::iterator initIter = dotState.initialchilds.begin(); initIter != dotState.initialchilds.end(); initIter++) {
- std::string destId = *initIter;
- DotEdge edge(stateId, destId);
- edge.type = EDGE_INITAL;
- if (_graph.find(destId) != _graph.end())
- _edges.insert(edge);
- }
-
- }
-
- // recurse into children and search others to draw
- NodeSet<std::string> childElems = DOMUtils::filterChildType(Node_base::ELEMENT_NODE, stateElem);
- for (size_t i = 0; i < childElems.size(); i++) {
- Element<std::string> childElem(childElems[i]);
- if (InterpreterImpl::isState(Element<std::string>(childElem))) {
- writeStateElement(os, childElem);
- }
- }
-
- if (subgraph) {
- _indentation--;
- os << getPrefix() << "} #" << stateId << std::endl;
- _indentation--;
- }
-}
-
-void SCXMLDotWriter::writePerTransitionPorts(std::ostream& os, const DotState& dotState, int stateLines) {
- // TODO: Not implemented
-}
-
-void SCXMLDotWriter::writePerEventPorts(std::ostream& os, const DotState& dotState, int stateLines) {
- // std::multimap<std::string, Arabica::DOM::Element<std::string> > events; // key is event name, value is transitions that react
-
- std::string stateId = idForNode(dotState.node);
- DotState::mmap_s_e_t::const_iterator destIterF, destIterB;
-
- for(DotState::mmap_s_e_t::const_iterator it = dotState.events.begin(), end = dotState.events.end();
- it != end;
- it = dotState.events.upper_bound(it->first)) {
- os << " <tr><td port=\"" << portEscape(it->first) << "\" align=\"right\">" << it->first << "</td></tr>" << std::endl;
- }
-
-}
-
-std::string SCXMLDotWriter::htmlLabelForId(const std::string& stateId, int minRows) {
- FlatStateIdentifier flatId(stateId);
-
- std::list<std::string>::const_iterator listIter;
- std::stringstream labelSS;
- std::string seperator;
-
- labelSS << "<b>active: </b>";
- labelSS << "{";
- for (listIter = flatId.getActive().begin(); listIter != flatId.getActive().end(); listIter++) {
- labelSS << seperator << *listIter;
- seperator = ", ";
- }
- labelSS << "}";
-
- if (flatId.getVisited().size() > 0) {
- minRows--;
-
- labelSS << "<br /><b>init: </b>";
-
- labelSS << "{";
- seperator = "";
- for (listIter = flatId.getVisited().begin(); listIter != flatId.getVisited().end(); listIter++) {
- labelSS << seperator << *listIter;
- seperator = ", ";
- }
- labelSS << "}";
- }
-
- if (flatId.getHistory().size() > 0) {
- minRows--;
-
- seperator = "";
- std::string histSeperator = "<br /> ";
-
- labelSS << "<br /><b>history: </b>";
-
- std::map<std::string, std::list<std::string> >::const_iterator histIter;
- for (histIter = flatId.getHistory().begin(); histIter != flatId.getHistory().end(); histIter++) {
- labelSS << histSeperator << histIter->first << ": {";
-
- for (listIter = histIter->second.begin(); listIter != histIter->second.end(); listIter++) {
- labelSS << seperator << *listIter;
- seperator = ", ";
- }
- labelSS << "}";
- seperator = "";
- }
- }
- return labelSS.str();
-}
-
-
-void SCXMLDotWriter::writePerTargetPorts(std::ostream& os, const DotState& dotState, int stateLines) {
- // std::multimap<std::string, Arabica::DOM::Element<std::string> > targets; // key is remote node, transition is element
-
- int nrOutports = 0;
- std::string stateId = idForNode(dotState.node);
-
- typedef DotState::mmap_s_e_t iter_t;
-
- // we need to count outports first for vertical padding
- for(iter_t::const_iterator targetIter = dotState.targets.begin(), end = dotState.targets.end();
- targetIter != end;
- targetIter = dotState.targets.upper_bound(targetIter->first)) {
- nrOutports++;
- }
-
- for(iter_t::const_iterator targetIter = dotState.targets.begin(), end = dotState.targets.end();
- targetIter != end;
- targetIter = dotState.targets.upper_bound(targetIter->first)) {
-
- // gather all events that activate the transition
- std::string targetId = targetIter->first;
-
- std::set<std::string> eventNames;
-
- DotEdge edge(stateId, targetId);
- edge.fromPort = targetId;
-
- std::pair <iter_t::const_iterator, iter_t::const_iterator> targetKeyRange = dotState.targets.equal_range(targetId);
- for (iter_t::const_iterator transIter = targetKeyRange.first; transIter != targetKeyRange.second; ++transIter) {
- const Element<std::string>& transElem = transIter->second;
-
- std::list<std::string> events = tokenize(ATTR(transElem, "event"));
- eventNames.insert(events.begin(), events.end());
-
- if (events.size() == 0) {
- // spontaneous transition
- eventNames.insert("&#35;");
- edge.type = EDGE_SPONTANEOUS;
- }
- }
-
- if (_graph.find(targetId) != _graph.end())
- _edges.insert(edge);
-
- std::stringstream outPortSS;
- outPortSS << (_isFlat ? htmlLabelForId(targetId) : "<b>" + targetId + "</b>" );
-
- if (_isFlat) {
- outPortSS << "<br /><b>events: </b>{";
- } else {
- outPortSS << "<br />{";
- }
-
- std::string seperator;
- for (std::set<std::string>::const_iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
- outPortSS << seperator << *eventIter << std::endl;
- seperator = ", ";
- }
- outPortSS << "}";
-
- if (nrOutports == 1) {
- int missing = stateLines - nrOutports;
- while (_isFlat && missing-- >= 1) {
- outPortSS << "<br /> ";
- }
- }
-
- os << " <tr><td port=\"" << portEscape(targetId) << "\" balign=\"left\" align=\"left\">" << outPortSS.str() << "</td></tr>" << std::endl;
-
- }
-}
-
-std::string SCXMLDotWriter::getDetailedLabel(const Element<std::string>& elem, int indentation) {
-
- /*
- <table>
- <tr>
- <td colspan="2">onEntry</td>
- </tr>
- <tr>
- <td>Details</td>
- <td bgcolor="#eee">
- Nested Content
- </td>
- </tr>
- </table>
- */
-
- std::list<struct ElemDetails> content;
-
- NodeList<std::string > childElems = elem.getChildNodes();
- for (size_t i = 0; i < childElems.getLength(); i++) {
- if (childElems.item(i).getNodeType() != Node_base::ELEMENT_NODE)
- continue;
- Element<std::string> elem = Element<std::string>(childElems.item(i));
-
- if (InterpreterImpl::isState(elem) ||
- iequals(TAGNAME(elem), "transition") ||
- iequals(TAGNAME(elem), "initial") ||
- false)
- continue;
-
- struct ElemDetails details;
- details.name = "<b>" + TAGNAME(elem) + ":</b>";
-
- if (iequals(TAGNAME(elem), "history")) {
- continue;
- }
-
- // provide details for special elements here
-
- // param ---------
- if (iequals(TAGNAME(elem), "param")) {
- if (HAS_ATTR(elem, "name"))
- details.name += " " + ATTR(elem, "name") + " = ";
- if (HAS_ATTR(elem, "expr"))
- details.name += ATTR(elem, "expr");
- if (HAS_ATTR(elem, "location"))
- details.name += ATTR(elem, "location");
- }
-
- // data ---------
- if (iequals(TAGNAME(elem), "data")) {
- if (HAS_ATTR(elem, "id"))
- details.name += " " + ATTR(elem, "id");
- if (HAS_ATTR(elem, "src"))
- details.name += ATTR(elem, "src");
- if (HAS_ATTR(elem, "expr"))
- details.name += " = " + ATTR(elem, "expr");
- NodeList<std::string > grandChildElems = elem.getChildNodes();
- for (size_t j = 0; j < grandChildElems.getLength(); j++) {
- if (grandChildElems.item(j).getNodeType() == Node_base::TEXT_NODE) {
- details.name += dotEscape(grandChildElems.item(j).getNodeValue());
- }
- }
- }
-
- // invoke ---------
- if (iequals(TAGNAME(elem), "invoke")) {
- if (HAS_ATTR(elem, "type"))
- details.name += "<br />type = " + ATTR(elem, "type");
- if (HAS_ATTR(elem, "typeexpr"))
- details.name += "<br />type = " + ATTR(elem, "typeexpr");
- if (HAS_ATTR(elem, "src"))
- details.name += "<br />src = " + ATTR(elem, "src");
- if (HAS_ATTR(elem, "srcexpr"))
- details.name += "<br />src = " + ATTR(elem, "srcexpr");
- if (HAS_ATTR(elem, "id"))
- details.name += "<br />id = " + ATTR(elem, "id");
- if (HAS_ATTR(elem, "idlocation"))
- details.name += "<br />id = " + ATTR(elem, "idlocation");
- }
-
- // send ---------
- if (iequals(TAGNAME(elem), "raise")) {
- if (HAS_ATTR(elem, "event "))
- details.name += "<br />event = " + ATTR(elem, "event");
- }
-
- // send ---------
- if (iequals(TAGNAME(elem), "send")) {
- if (HAS_ATTR(elem, "id"))
- details.name += "<br />id = " + ATTR(elem, "id");
- if (HAS_ATTR(elem, "type"))
- details.name += "<br />type = " + ATTR(elem, "type");
- if (HAS_ATTR(elem, "typeexpr"))
- details.name += "<br />type = " + ATTR(elem, "typeexpr");
- if (HAS_ATTR(elem, "event"))
- details.name += "<br />event = " + ATTR(elem, "event");
- if (HAS_ATTR(elem, "eventexpr"))
- details.name += "<br />event = " + ATTR(elem, "eventexpr");
- if (HAS_ATTR(elem, "target"))
- details.name += "<br />target = " + ATTR(elem, "target");
- if (HAS_ATTR(elem, "targetexpr"))
- details.name += "<br />target = " + ATTR(elem, "targetexpr");
- if (HAS_ATTR(elem, "delay"))
- details.name += "<br />delay = " + ATTR(elem, "delay");
- if (HAS_ATTR(elem, "delayexpr"))
- details.name += "<br />delay = " + ATTR(elem, "delayexpr");
- }
-
- // cancel ---------
- if (iequals(TAGNAME(elem), "cancel")) {
- if (HAS_ATTR(elem, "sendid"))
- details.name += " " + ATTR(elem, "sendid");
- }
-
- // script ---------
- if (iequals(TAGNAME(elem), "script")) {
- details.name += " ";
- if (HAS_ATTR(elem, "src"))
- details.name += ATTR(elem, "src");
- NodeList<std::string > grandChildElems = childElems.item(i).getChildNodes();
- for (size_t j = 0; j < grandChildElems.getLength(); j++) {
- if (grandChildElems.item(j).getNodeType() == Node_base::TEXT_NODE) {
- details.name += dotEscape(grandChildElems.item(j).getNodeValue());
- }
- }
- }
-
- // if ---------
- if (iequals(TAGNAME(elem), "if")) {
- if (HAS_ATTR(elem, "cond"))
- details.name += " cond = " + dotEscape(ATTR(elem, "cond"));
- }
-
- // elseif ---------
- if (iequals(TAGNAME(elem), "elseif")) {
- if (HAS_ATTR(elem, "cond"))
- details.name += " cond = " + dotEscape(ATTR(elem, "cond"));
- }
-
- // log ---------
- if (iequals(TAGNAME(elem), "log")) {
- details.name += " ";
- if (HAS_ATTR(elem, "label"))
- details.name += ATTR(elem, "label") + " = ";
- if (HAS_ATTR(elem, "expr"))
- details.name += ATTR(elem, "expr");
- }
-
- // foreach ---------
- if (iequals(TAGNAME(elem), "foreach")) {
- if (HAS_ATTR(elem, "item"))
- details.name += "<br />&nbsp;&nbsp;item = " + ATTR(elem, "item");
- if (HAS_ATTR(elem, "array"))
- details.name += "<br />&nbsp;&nbsp;array = " + ATTR(elem, "array");
- if (HAS_ATTR(elem, "index"))
- details.name += "<br />&nbsp;&nbsp;index = " + ATTR(elem, "index");
- }
-
- // recurse
- details.content = getDetailedLabel((Element<std::string>)childElems.item(i), indentation + 1);
- content.push_back(details);
- }
-
- std::stringstream ssContent;
-
- if (content.size() > 0) {
- ssContent << "<table cellspacing=\"2\" cellpadding=\"0\" border=\"0\" bgcolor=\"#" << colorForIndent(indentation + 1) << "\">";
-
- std::list<struct ElemDetails>::iterator contentIter = content.begin();
- while(contentIter != content.end()) {
- ssContent << "<tr>";
-// ssContent << "<td align=\"left\" colspan=\"2\">" << contentIter->name << "</td>";
- ssContent << "<td balign=\"left\" align=\"left\">" << contentIter->name << "</td>";
- ssContent << "</tr>";
-
- if (contentIter->content.size() > 0) {
- ssContent << "<tr>";
-// ssContent << "<td>" << contentIter->details << "</td>";
- ssContent << "<td bgcolor=\"#" << colorForIndent(indentation + 1) << "\">" << contentIter->content << "</td>";
- ssContent << "</tr>";
- }
- contentIter++;
-
- }
- ssContent << "</table>";
- }
- return ssContent.str();
-}
-
-std::string SCXMLDotWriter::portEscape(const std::string& text) {
- std::string escaped(text);
- boost::replace_all(escaped, ".", "-");
- boost::replace_all(escaped, "{", "-");
- boost::replace_all(escaped, "}", "-");
- boost::replace_all(escaped, ":", "-");
- return escaped;
-}
-
-std::string SCXMLDotWriter::dotEscape(const std::string& text) {
- std::string escaped(text);
- boost::replace_all(escaped, " ", "&nbsp;");
- boost::replace_all(escaped, "\t", "&nbsp;&nbsp;&nbsp;");
- boost::replace_all(escaped, "<", "&lt;");
- boost::replace_all(escaped, ">", "&gt;");
- boost::replace_all(escaped, "\"", "&quot;");
- boost::replace_all(escaped, "\n", "<br />");
-
- return escaped;
-}
-
-std::string SCXMLDotWriter::colorForIndent(int indent) {
- int color = 255 - (16 * indent);
- std::stringstream ss;
- ss << std::hex << color;
- ss << std::hex << color;
- ss << std::hex << color;
- return ss.str();
-}
-
-std::string SCXMLDotWriter::nameForNode(const Node<std::string>& node) {
- std::string elemName;
- if (node.getNodeType() == Node_base::ELEMENT_NODE) {
- Element<std::string> elem = (Element<std::string>)node;
-
- if (InterpreterImpl::isFinal(elem) && _isFlat) {
- // ignore visited and history with final elements
- FlatStateIdentifier flatId(elem.getAttribute("id"));
- return "<b>" + flatId.getActive().front() + "</b>";
- }
-
- if (elem.hasAttribute("id") && _isFlat) {
- elemName = htmlLabelForId(elem.getAttribute("id"));
- if (elemName.size() > 0)
- return elemName;
- } else if (elem.getTagName() == "scxml") {
- if (elem.hasAttribute("name") && !UUID::isUUID(elem.getAttribute("name"))) {
- elemName += elem.getAttribute("name");
- } else if (elem.hasAttribute("id") && !UUID::isUUID(elem.getAttribute("id"))) {
- elemName += elem.getAttribute("id");
- }
- } else if (InterpreterImpl::isCompound(elem)) {
- elemName = "<i>Compound: </i>" + elem.getAttribute("id");
- } else if (InterpreterImpl::isParallel(elem)) {
- elemName = "<i>Parallel: </i>" + elem.getAttribute("id");
- } else if (elem.hasAttribute("id")) {
- elemName += elem.getAttribute("id");
- }
- }
-
- if (elemName.size() == 0)
- elemName = boost::lexical_cast<std::string>(node.getLocalName());
-
- return "<b>" + elemName + "</b>";
-
-}
-
-std::string SCXMLDotWriter::idForNode(const Node<std::string>& node) {
- std::string elemId;
-
- // try to get the id as the name or id attribute
- if (node.getNodeType() == Node_base::ELEMENT_NODE) {
- Element<std::string> elem = (Element<std::string>)node;
-
-// if (InterpreterImpl::isFinal(elem) && _isFlat) {
-// // ignore visited and history with final elements
-// FlatStateIdentifier flatId(elem.getAttribute("id"));
-//
-// std::stringstream activeSS;
-// activeSS << "active-";
-// for (std::list<std::string>::const_iterator activeIter = flatId.getActive().begin(); activeIter != flatId.getActive().end(); activeIter++) {
-// activeSS << *activeIter << "-";
-// }
-// return activeSS.str();
-// }
-
- if (elem.hasAttribute("name")) {
- elemId = elem.getAttribute("name");
- } else if (elem.hasAttribute("id")) {
- elemId = elem.getAttribute("id");
- }
- }
-
- // no luck, create id from position in tree
- if (elemId.size() == 0) {
- Node<std::string> tmpParent = node;
- Node<std::string> tmpIndex;
- do {
- if (tmpParent.getNodeType() != Node_base::ELEMENT_NODE)
- continue;
-
- tmpIndex = tmpParent;
- int index = 0;
-
- while((tmpIndex = tmpIndex.getPreviousSibling()))
- index++;
-
- std::stringstream ssElemId;
- ssElemId << TAGNAME_CAST(tmpParent) << index << ".";
- elemId = ssElemId.str() + elemId;
- } while ((tmpParent = tmpParent.getParentNode()));
-// elemId = ssElemId.str();
- }
- return elemId;
-}
-
-} \ No newline at end of file