#include "data/graph/Graph.h" #include "utility/logging/logging.h" Graph::Graph() { } Graph::~Graph() { m_edges.clear(); m_nodes.clear(); } void Graph::clear() { m_edges.clear(); m_nodes.clear(); } void Graph::forEachNode(std::function func) const { for (const std::pair>& node : m_nodes) { func(node.second.get()); } } void Graph::forEachEdge(std::function func) const { for (const std::pair>& edge : m_edges) { func(edge.second.get()); } } void Graph::forEachToken(std::function func) const { forEachNode(func); forEachEdge(func); } Node* Graph::createNode(Id id, Node::NodeType type, NameHierarchy nameHierarchy, bool defined) { Node* n = getNodeById(id); if (n) { return n; } std::shared_ptr node = std::make_shared(id, type, nameHierarchy, defined); m_nodes.emplace(node->getId(), node); return node.get(); } Edge* Graph::createEdge(Id id, Edge::EdgeType type, Node* from, Node* to) { Edge* e = getEdgeById(id); if (e) { return e; } if (!getNodeById(from->getId()) || !getNodeById(to->getId())) { LOG_ERROR("Can't add edge, without adding the nodes first."); return nullptr; } std::shared_ptr edge = std::make_shared(id, type, from, to); m_edges.emplace(edge->getId(), edge); return edge.get(); } size_t Graph::getNodeCount() const { return m_nodes.size(); } size_t Graph::getEdgeCount() const { return m_edges.size(); } Node* Graph::getNodeById(Id id) const { std::map>::const_iterator it = m_nodes.find(id); if (it != m_nodes.end()) { return it->second.get(); } return nullptr; } Edge* Graph::getEdgeById(Id id) const { std::map>::const_iterator it = m_edges.find(id); if (it != m_edges.end()) { return it->second.get(); } return nullptr; } const std::map>& Graph::getNodes() const { return m_nodes; } const std::map>& Graph::getEdges() const { return m_edges; } void Graph::removeNode(Node* node) { std::map>::const_iterator it = m_nodes.find(node->getId()); if (it == m_nodes.end()) { LOG_WARNING("Node was not found in the graph."); return; } node->forEachEdgeOfType( Edge::EDGE_MEMBER, [this, node](Edge* e) { if (node == e->getFrom()) { this->removeNode(e->getTo()); } } ); node->forEachEdge( [this](Edge* e) { this->removeEdgeInternal(e); } ); if (node->getEdges().size()) { LOG_ERROR("Node still has edges."); } m_nodes.erase(it); } void Graph::removeEdge(Edge* edge) { std::map>::const_iterator it = m_edges.find(edge->getId()); if (it == m_edges.end()) { LOG_WARNING("Edge was not found in the graph."); } if (edge->getType() == Edge::EDGE_MEMBER) { LOG_ERROR("Can't remove member edge, without removing the child node."); return; } m_edges.erase(it); } Node* Graph::findNode(std::function func) const { std::map>::const_iterator it = find_if(m_nodes.begin(), m_nodes.end(), [&func](const std::pair>& n) { return func(n.second.get()); } ); if (it != m_nodes.end()) { return it->second.get(); } return nullptr; } Edge* Graph::findEdge(std::function func) const { std::map>::const_iterator it = find_if(m_edges.begin(), m_edges.end(), [func](const std::pair>& e) { return func(e.second.get()); } ); if (it != m_edges.end()) { return it->second.get(); } return nullptr; } Token* Graph::findToken(std::function func) const { Node* node = findNode(func); if (node) { return node; } Edge* edge = findEdge(func); if (edge) { return edge; } return nullptr; } Node* Graph::addNodeAsPlainCopy(Node* node) { Node* n = getNodeById(node->getId()); if (n) { return n; } std::shared_ptr copy = std::make_shared(*node); m_nodes.emplace(copy->getId(), copy); return copy.get(); } Edge* Graph::addEdgeAsPlainCopy(Edge* edge) { Edge* e = getEdgeById(edge->getId()); if (e) { return e; } Node* from = addNodeAsPlainCopy(edge->getFrom()); Node* to = addNodeAsPlainCopy(edge->getTo()); std::shared_ptr copy = std::make_shared(*edge, from, to); m_edges.emplace(copy->getId(), copy); return copy.get(); } Node* Graph::addNodeAndAllChildrenAsPlainCopy(Node* node) { Node* n = addNodeAsPlainCopy(node); node->forEachEdgeOfType(Edge::EDGE_MEMBER, [node, this](Edge* edge) { if (edge->getFrom() == node) { addEdgeAsPlainCopy(edge); addNodeAndAllChildrenAsPlainCopy(edge->getTo()); } } ); return n; } Edge* Graph::addEdgeAndAllChildrenAsPlainCopy(Edge* edge) { addNodeAndAllChildrenAsPlainCopy(edge->getFrom()->getLastParentNode()); addNodeAndAllChildrenAsPlainCopy(edge->getTo()->getLastParentNode()); return addEdgeAsPlainCopy(edge); } size_t Graph::size() const { return getNodeCount() + getEdgeCount(); } Token* Graph::getTokenById(Id id) const { Token* token = getNodeById(id); if (!token) { token = getEdgeById(id); } return token; } void Graph::print(std::ostream& ostream) const { ostream << "Graph:\n"; ostream << "nodes (" << getNodeCount() << ")\n"; forEachNode( [&ostream](Node* n) { ostream << *n << '\n'; } ); ostream << "edges (" << getEdgeCount() << ")\n"; forEachEdge( [&ostream](Edge* e) { ostream << *e << '\n'; } ); } void Graph::printBasic(std::ostream& ostream) const { ostream << getNodeCount() << " nodes:"; forEachNode( [&ostream](Node* n) { ostream << ' ' << n->getReadableTypeString() << ':' << n->getFullName(); } ); ostream << '\n'; ostream << getEdgeCount() << " edges:"; forEachEdge( [&ostream](Edge* e) { ostream << ' ' << e->getName(); } ); ostream << '\n'; } void Graph::removeEdgeInternal(Edge* edge) { std::map >::const_iterator it = m_edges.find(edge->getId()); if (it != m_edges.end() && it->second.get() == edge) { m_edges.erase(it); return; } } std::ostream& operator<<(std::ostream& ostream, const Graph& graph) { graph.print(ostream); return ostream; }