#include "data/graph/Graph.h" #include "data/graph/token_component/TokenComponentSignature.h" #include "utility/logging/logging.h" #include "utility/utilityString.h" Graph::Graph() { } Graph::~Graph() { m_edges.clear(); m_nodes.clear(); } Node* Graph::getNode(const std::string& fullName) const { std::deque names = utility::split>(fullName, DELIMITER); Node* node = getLastValidNode(&names); if (node && !names.size()) { return node; } return nullptr; } Edge* Graph::getEdge(Edge::EdgeType type, Node* from, Node* to) const { return from->findEdgeOfType(type, [to](Edge* e) { return e->getTo() == to; } ); } 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; } Token* Graph::getTokenById(Id id) const { Token* token = getNodeById(id); if (!token) { token = getEdgeById(id); } return token; } Node* Graph::createNodeHierarchy(const std::string& fullName) { return createNodeHierarchy(Node::NODE_UNDEFINED, fullName); } Node* Graph::createNodeHierarchy(Node::NodeType type, const std::string& fullName) { std::deque names = utility::split>(fullName, DELIMITER); Node* node = getLastValidNode(&names); if (node && !names.size()) { if (type != Node::NODE_UNDEFINED) { node->setType(type); } return node; } return insertNodeHierarchy(type, names, node); } Node* Graph::createNodeHierarchyWithDistinctSignature(const std::string& fullName, const std::string& signature) { return createNodeHierarchyWithDistinctSignature(Node::NODE_UNDEFINED, fullName, signature); } Node* Graph::createNodeHierarchyWithDistinctSignature( Node::NodeType type, const std::string& fullName, const std::string& signature ){ std::deque names = utility::split>(fullName, DELIMITER); Node* node = getLastValidNode(&names); if (node && !names.size()) { TokenComponentSignature* sigComponent = node->getComponent(); if (sigComponent && sigComponent->getSignature() == signature) { if (type != Node::NODE_UNDEFINED) { node->setType(type); } return node; } Node* parentNode = node->getParentNode(); const std::string& name = node->getName(); std::function findSignature = [&name, &signature](Node* n) { TokenComponentSignature* c = n->getComponent(); return n->getName() == name && c && c->getSignature() == signature; }; if (parentNode) { node = parentNode->findChildNode(findSignature); } else { node = findNode(findSignature); } if (node) { return node; } node = insertNode(type, name, parentNode); } else { node = insertNodeHierarchy(type, names, node); } node->addComponentSignature(std::make_shared(signature)); return node; } Edge* Graph::createEdge(Edge::EdgeType type, Node* from, Node* to) { Edge* edge = getEdge(type, from, to); if (edge) { return edge; } return insertEdge(type, from, to); } 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 has still 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; } 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); } void Graph::clear() { m_edges.clear(); m_nodes.clear(); } const std::map >& Graph::getNodes() const { return m_nodes; } const std::map >& Graph::getEdges() const { return m_edges; } 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(); } const std::string Graph::DELIMITER = "::"; Node* Graph::getLastValidNode(std::deque* names) const { const std::string& name = names->front(); Node* node = findNode( [&name](Node* n) { return n->getName() == name && n->getParentNode() == nullptr; } ); if (!node) { return nullptr; } names->pop_front(); while (names->size()) { const std::string& name = names->front(); Node* childNode = node->findChildNode( [&name](Node* n) { return n->getName() == name; } ); if (!childNode) { break; } node = childNode; names->pop_front(); } return node; } Node* Graph::insertNodeHierarchy(Node::NodeType type, std::deque names, Node* parentNode) { while (names.size()) { parentNode = insertNode(names.size() == 1 ? type : Node::NODE_UNDEFINED, names.front(), parentNode); names.pop_front(); } return parentNode; } Node* Graph::insertNode(Node::NodeType type, const std::string& name, Node* parentNode) { std::shared_ptr nodePtr = std::make_shared(type, name); m_nodes.emplace(nodePtr->getId(), nodePtr); Node* node = nodePtr.get(); if (parentNode) { createEdge(Edge::EDGE_MEMBER, parentNode, node); } return node; } Edge* Graph::insertEdge(Edge::EdgeType type, Node* from, Node* to) { std::shared_ptr edgePtr = std::make_shared(type, from, to); m_edges.emplace(edgePtr->getId(), edgePtr); return edgePtr.get(); } 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) { ostream << "Graph:\n"; ostream << "nodes (" << graph.getNodes().size() << ")\n"; graph.forEachNode( [&ostream](Node* n) { ostream << *n << '\n'; } ); ostream << "edges (" << graph.getEdges().size() << ")\n"; graph.forEachEdge( [&ostream](Edge* e) { ostream << *e << '\n'; } ); return ostream; }