| 494 | } |
| 495 | |
| 496 | string GraphElement::asStringDot() const |
| 497 | { |
| 498 | string dot = "digraph {\n"; |
| 499 | |
| 500 | // Create a unique name for each child element. |
| 501 | ElementVec children = topologicalSort(); |
| 502 | StringMap nameMap; |
| 503 | StringSet nameSet; |
| 504 | for (ElementPtr elem : children) |
| 505 | { |
| 506 | string uniqueName = elem->getCategory(); |
| 507 | while (nameSet.count(uniqueName)) |
| 508 | { |
| 509 | uniqueName = incrementName(uniqueName); |
| 510 | } |
| 511 | nameMap[elem->getName()] = uniqueName; |
| 512 | nameSet.insert(uniqueName); |
| 513 | } |
| 514 | |
| 515 | // Write out all nodes. |
| 516 | for (ElementPtr elem : children) |
| 517 | { |
| 518 | NodePtr node = elem->asA<Node>(); |
| 519 | if (node) |
| 520 | { |
| 521 | dot += " \"" + nameMap[node->getName()] + "\" "; |
| 522 | NodeDefPtr nodeDef = node->getNodeDef(); |
| 523 | const string& nodeGroup = nodeDef ? nodeDef->getNodeGroup() : EMPTY_STRING; |
| 524 | if (nodeGroup == NodeDef::CONDITIONAL_NODE_GROUP) |
| 525 | { |
| 526 | dot += "[shape=diamond];\n"; |
| 527 | } |
| 528 | else |
| 529 | { |
| 530 | dot += "[shape=box];\n"; |
| 531 | } |
| 532 | } |
| 533 | } |
| 534 | |
| 535 | // Write out all connections. |
| 536 | std::set<Edge> processedEdges; |
| 537 | StringSet processedInterfaces; |
| 538 | for (OutputPtr output : getOutputs()) |
| 539 | { |
| 540 | for (Edge edge : output->traverseGraph()) |
| 541 | { |
| 542 | if (!processedEdges.count(edge)) |
| 543 | { |
| 544 | ElementPtr upstreamElem = edge.getUpstreamElement(); |
| 545 | ElementPtr downstreamElem = edge.getDownstreamElement(); |
| 546 | ElementPtr connectingElem = edge.getConnectingElement(); |
| 547 | |
| 548 | dot += " \"" + nameMap[upstreamElem->getName()]; |
| 549 | dot += "\" -> \"" + nameMap[downstreamElem->getName()]; |
| 550 | dot += "\" [label=\""; |
| 551 | dot += connectingElem ? connectingElem->getName() : EMPTY_STRING; |
| 552 | dot += "\"];\n"; |
| 553 |
no test coverage detected