logic: refactored GraphAccess and GraphController to use single call that returns Graph
This change refactors the GraphController to use the GraphAccess only with a single call that returns a Graph. The Graph contains all information for visually representing the active Token with all parent and child nodes and edges. This reduces coupling of the data and logic tiers.
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
#include "component/controller/GraphController.h"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <set>
|
||||
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
#include "component/view/graphElements/GraphEdge.h"
|
||||
#include "component/view/graphElements/GraphNode.h"
|
||||
#include "component/view/GraphView.h"
|
||||
#include "data/access/GraphAccess.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
GraphController::GraphController(GraphAccess* graphAccess)
|
||||
: m_graphAccess(graphAccess)
|
||||
@@ -19,12 +20,12 @@ GraphController::~GraphController()
|
||||
|
||||
void GraphController::handleMessage(MessageActivateToken* message)
|
||||
{
|
||||
createDummyGraph(message->tokenId, &GraphLayouter::layoutSimpleRing);
|
||||
createDummyGraphForTokenId(message->tokenId, &GraphLayouter::layoutSimpleRing);
|
||||
}
|
||||
|
||||
void GraphController::handleMessage(MessageActivateTokens* message)
|
||||
{
|
||||
createDummyGraph(message->tokenIds[0], &GraphLayouter::layoutSimpleRing);
|
||||
createDummyGraphForTokenId(message->tokenIds[0], &GraphLayouter::layoutSimpleRing);
|
||||
}
|
||||
|
||||
GraphView* GraphController::getView()
|
||||
@@ -32,250 +33,76 @@ GraphView* GraphController::getView()
|
||||
return Controller::getView<GraphView>();
|
||||
}
|
||||
|
||||
void GraphController::createDummyGraph(const Id activeId, const LayoutFunction layoutFunction)
|
||||
void GraphController::createDummyGraphForTokenId(Id tokenId, const GraphLayouter::LayoutFunction layoutFunction)
|
||||
{
|
||||
GraphView* view = getView();
|
||||
if (view != NULL)
|
||||
if (!view)
|
||||
{
|
||||
std::vector<DummyNode> nodes;
|
||||
LOG_ERROR("GraphController has no associated GraphView");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_graphAccess->checkTokenIsNode(activeId))
|
||||
std::vector<Id> activeTokenIds;
|
||||
activeTokenIds.push_back(tokenId);
|
||||
std::shared_ptr<Graph> graph = m_graphAccess->getGraphForActiveTokenIds(activeTokenIds);
|
||||
|
||||
std::vector<DummyNode> dummyNodes;
|
||||
std::vector<DummyEdge> dummyEdges;
|
||||
std::set<Id> addedNodes;
|
||||
|
||||
graph->forEachNode(
|
||||
[&dummyNodes, &dummyEdges, &addedNodes, this](Node* node)
|
||||
{
|
||||
nodes.push_back(createDummyNode(activeId));
|
||||
std::vector<DummyNode> neighbours = createNeighbourNodes(nodes[0]);
|
||||
nodes.insert(nodes.end(), neighbours.begin(), neighbours.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::pair<Id, Id> nodeIds = m_graphAccess->getNodesOfEdge(activeId);
|
||||
nodes.push_back(createDummyNode(nodeIds.first));
|
||||
nodes.push_back(createDummyNode(nodeIds.second));
|
||||
}
|
||||
|
||||
layoutFunction(nodes);
|
||||
|
||||
std::vector<DummyEdge> edges;
|
||||
edges = createEdges(nodes);
|
||||
|
||||
view->rebuildGraph(nodes, edges);
|
||||
}
|
||||
}
|
||||
|
||||
DummyNode GraphController::createDummyNode(const Id nodeId)
|
||||
{
|
||||
DummyNode result("invalid", 0, Vec2i());
|
||||
|
||||
Id topLevelId = findTopLevelNode(nodeId);
|
||||
|
||||
result = buildNodeTopDown(topLevelId);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Id GraphController::findTopLevelNode(const Id nodeId)
|
||||
{
|
||||
std::vector<std::tuple<Id, Id, Id>> memberEdges = m_graphAccess->getMemberEdgesOfNode(nodeId);
|
||||
|
||||
for (unsigned int i = 0; i < memberEdges.size(); i++)
|
||||
{
|
||||
if (std::get<0>(memberEdges[i]) != nodeId)
|
||||
{
|
||||
return findTopLevelNode(std::get<0>(memberEdges[i]));
|
||||
}
|
||||
}
|
||||
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
DummyNode GraphController::buildNodeTopDown(const Id nodeId)
|
||||
{
|
||||
DummyNode result("invalid", 0, Vec2i());
|
||||
|
||||
result.name = m_graphAccess->getNameForNodeWithId(nodeId);
|
||||
result.tokenId = nodeId;
|
||||
|
||||
std::vector<std::tuple<Id, Id, Id>> memberEdges = m_graphAccess->getMemberEdgesOfNode(nodeId);
|
||||
for (unsigned int i = 0; i < memberEdges.size(); i++)
|
||||
{
|
||||
if (std::get<1>(memberEdges[i]) != nodeId)
|
||||
{
|
||||
result.subNodes.push_back(buildNodeTopDown(std::get<1>(memberEdges[i])));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<DummyNode> GraphController::createNeighbourNodes(const Id nodeId)
|
||||
{
|
||||
std::vector<DummyNode> result;
|
||||
|
||||
std::vector<std::tuple<Id, Id, Id>> edges;
|
||||
std::vector<std::tuple<Id, Id, Id>> callEdges = m_graphAccess->getCallEdgesOfNode(nodeId);
|
||||
std::vector<std::tuple<Id, Id, Id>> usageEdges = m_graphAccess->getUsageEdgesOfNode(nodeId);
|
||||
std::vector<std::tuple<Id, Id, Id>> typeOfEdges = m_graphAccess->getTypeOfEdgesOfNode(nodeId);
|
||||
std::vector<std::tuple<Id, Id, Id>> returnTypeEdges = m_graphAccess->getReturnTypeOfEdgesOfNode(nodeId);
|
||||
std::vector<std::tuple<Id, Id, Id>> parameterEdges = m_graphAccess->getParameterOfEdgesOfNode(nodeId);
|
||||
std::vector<std::tuple<Id, Id, Id>> inheritanceEdges = m_graphAccess->getInheritanceEdgesOfNode(nodeId);
|
||||
|
||||
if (callEdges.size() > 0)
|
||||
{
|
||||
edges.insert(edges.end(), callEdges.begin(), callEdges.end());
|
||||
}
|
||||
if (usageEdges.size() > 0)
|
||||
{
|
||||
edges.insert(edges.end(), usageEdges.begin(), usageEdges.end());
|
||||
}
|
||||
if (typeOfEdges.size() > 0)
|
||||
{
|
||||
edges.insert(edges.end(), typeOfEdges.begin(), typeOfEdges.end());
|
||||
}
|
||||
if (returnTypeEdges.size() > 0)
|
||||
{
|
||||
edges.insert(edges.end(), returnTypeEdges.begin(), returnTypeEdges.end());
|
||||
}
|
||||
if (parameterEdges.size() > 0)
|
||||
{
|
||||
edges.insert(edges.end(), parameterEdges.begin(), parameterEdges.end());
|
||||
}
|
||||
if (inheritanceEdges.size() > 0)
|
||||
{
|
||||
edges.insert(edges.end(), inheritanceEdges.begin(), inheritanceEdges.end());
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < edges.size(); i++)
|
||||
{
|
||||
if (std::get<0>(edges[i]) == nodeId)
|
||||
{
|
||||
result.push_back(createDummyNode(std::get<1>(edges[i])));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.push_back(createDummyNode(std::get<0>(edges[i])));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<DummyNode> GraphController::createNeighbourNodes(const DummyNode& node)
|
||||
{
|
||||
std::vector<DummyNode> result;
|
||||
|
||||
std::set<DummyNode> tmpNodes; // to make it easier to keep the nodes unique
|
||||
|
||||
result = createNeighbourNodes(node.tokenId);
|
||||
for (unsigned int i = 0; i < result.size(); i++)
|
||||
{
|
||||
tmpNodes.insert(result[i]);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < node.subNodes.size(); i++)
|
||||
{
|
||||
std::vector<DummyNode> tmpNeighbours = createNeighbourNodes(node.subNodes[i].tokenId);
|
||||
for (unsigned int j = 0; j < tmpNeighbours.size(); j++)
|
||||
{
|
||||
tmpNodes.insert(tmpNeighbours[j]);
|
||||
}
|
||||
}
|
||||
|
||||
result.clear();
|
||||
|
||||
for (std::set<DummyNode>::iterator it = tmpNodes.begin(); it != tmpNodes.end(); it++)
|
||||
{
|
||||
result.push_back(*it);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<DummyEdge> GraphController::createEdges(const std::vector<DummyNode>& nodes)
|
||||
{
|
||||
std::vector<DummyEdge> result;
|
||||
|
||||
std::unordered_set<Id> nodeIds; // to help discard edges that point to non-existing nodes in the sub-graph
|
||||
std::queue<DummyNode> nodeQueue;
|
||||
for (unsigned int i = 0; i < nodes.size(); i++)
|
||||
{
|
||||
nodeQueue.push(nodes[i]);
|
||||
}
|
||||
|
||||
while (nodeQueue.size() > 0)
|
||||
{
|
||||
DummyNode n = nodeQueue.front();
|
||||
nodeQueue.pop();
|
||||
|
||||
for (unsigned int i = 0; i < n.subNodes.size(); i++)
|
||||
{
|
||||
nodeQueue.push(n.subNodes[i]);
|
||||
}
|
||||
|
||||
nodeIds.insert(n.tokenId);
|
||||
}
|
||||
|
||||
std::set<DummyEdge> tmpEdges; // to make it easier to keep the edges unique
|
||||
for (unsigned int i = 0; i < nodes.size(); i++)
|
||||
{
|
||||
std::set<DummyEdge> tmp = getNeighbourEdgesOfNode(nodes[i]);
|
||||
|
||||
for (std::set<DummyEdge>::iterator it = tmp.begin(); it != tmp.end(); it++)
|
||||
{
|
||||
if (nodeIds.find(it->ownerId) != nodeIds.end() && nodeIds.find(it->targetId) != nodeIds.end())
|
||||
Node* parent = node->getLastParentNode();
|
||||
Id id = parent->getId();
|
||||
if (addedNodes.find(id) != addedNodes.end())
|
||||
{
|
||||
tmpEdges.insert(tmp.begin(), tmp.end());
|
||||
return;
|
||||
}
|
||||
addedNodes.insert(id);
|
||||
|
||||
dummyNodes.push_back(createDummyNodeTopDown(parent, &dummyEdges));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
for (std::set<DummyEdge>::iterator it = tmpEdges.begin(); it != tmpEdges.end(); it++)
|
||||
{
|
||||
result.push_back(*it);
|
||||
}
|
||||
|
||||
return result;
|
||||
layoutFunction(dummyNodes);
|
||||
view->rebuildGraph(dummyNodes, dummyEdges);
|
||||
}
|
||||
|
||||
std::set<DummyEdge> GraphController::getNeighbourEdgesOfNode(const DummyNode& node)
|
||||
DummyNode GraphController::createDummyNodeTopDown(Node* node, std::vector<DummyEdge>* dummyEdges) const
|
||||
{
|
||||
std::set<DummyEdge> result;
|
||||
DummyNode result("invalid", 0, Vec2i());
|
||||
|
||||
std::vector<std::tuple<Id, Id, Id>> callEdges = m_graphAccess->getCallEdgesOfNode(node.tokenId);
|
||||
std::vector<std::tuple<Id, Id, Id>> usageEdges = m_graphAccess->getUsageEdgesOfNode(node.tokenId);
|
||||
std::vector<std::tuple<Id, Id, Id>> typeOfEdges = m_graphAccess->getTypeOfEdgesOfNode(node.tokenId);
|
||||
std::vector<std::tuple<Id, Id, Id>> returnTypeEdges = m_graphAccess->getReturnTypeOfEdgesOfNode(node.tokenId);
|
||||
std::vector<std::tuple<Id, Id, Id>> parameterEdges = m_graphAccess->getParameterOfEdgesOfNode(node.tokenId);
|
||||
std::vector<std::tuple<Id, Id, Id>> inheritanceEdges = m_graphAccess->getInheritanceEdgesOfNode(node.tokenId);
|
||||
result.name = node->getName();
|
||||
result.tokenId = node->getId();
|
||||
|
||||
for (unsigned int i = 0; i < callEdges.size(); i++)
|
||||
{
|
||||
result.insert(DummyEdge(std::get<0>(callEdges[i]), std::get<1>(callEdges[i]), std::get<2>(callEdges[i]), Edge::EDGE_CALL));
|
||||
}
|
||||
for (unsigned int i = 0; i < usageEdges.size(); i++)
|
||||
{
|
||||
result.insert(DummyEdge(std::get<0>(usageEdges[i]), std::get<1>(usageEdges[i]), std::get<2>(usageEdges[i]), Edge::EDGE_USAGE));
|
||||
}
|
||||
for (unsigned int i = 0; i < typeOfEdges.size(); i++)
|
||||
{
|
||||
result.insert(DummyEdge(std::get<0>(typeOfEdges[i]), std::get<1>(typeOfEdges[i]), std::get<2>(typeOfEdges[i]), Edge::EDGE_TYPE_OF));
|
||||
}
|
||||
for (unsigned int i = 0; i < returnTypeEdges.size(); i++)
|
||||
{
|
||||
result.insert(DummyEdge(std::get<0>(returnTypeEdges[i]), std::get<1>(returnTypeEdges[i]), std::get<2>(returnTypeEdges[i]), Edge::EDGE_RETURN_TYPE_OF));
|
||||
}
|
||||
for (unsigned int i = 0; i < parameterEdges.size(); i++)
|
||||
{
|
||||
result.insert(DummyEdge(std::get<0>(parameterEdges[i]), std::get<1>(parameterEdges[i]), std::get<2>(parameterEdges[i]), Edge::EDGE_PARAMETER_TYPE_OF));
|
||||
}
|
||||
for (unsigned int i = 0; i < inheritanceEdges.size(); i++)
|
||||
{
|
||||
result.insert(DummyEdge(std::get<0>(inheritanceEdges[i]), std::get<1>(inheritanceEdges[i]), std::get<2>(inheritanceEdges[i]), Edge::EDGE_INHERITANCE));
|
||||
}
|
||||
node->forEachChildNode(
|
||||
[&result, dummyEdges, this](Node* child)
|
||||
{
|
||||
result.subNodes.push_back(createDummyNodeTopDown(child, dummyEdges));
|
||||
}
|
||||
);
|
||||
|
||||
for (unsigned int i = 0; i < node.subNodes.size(); i++)
|
||||
{
|
||||
std::set<DummyEdge> tmpNeighbours = getNeighbourEdgesOfNode(node.subNodes[i]);
|
||||
result.insert(tmpNeighbours.begin(), tmpNeighbours.end());
|
||||
}
|
||||
node->forEachEdge(
|
||||
[&result, node, dummyEdges](Edge* edge)
|
||||
{
|
||||
if (edge->isType(Edge::EDGE_MEMBER))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (const DummyEdge& dummy : *dummyEdges)
|
||||
{
|
||||
if (dummy.tokenId == edge->getId())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
dummyEdges->push_back(
|
||||
DummyEdge(edge->getFrom()->getId(), edge->getTo()->getId(), edge->getId(), edge->getType()));
|
||||
}
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
#ifndef GRAPH_CONTROLLER_H
|
||||
#define GRAPH_CONTROLLER_H
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "component/controller/Controller.h"
|
||||
#include "component/controller/GraphLayouter.h"
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
#include "utility/messaging/type/MessageActivateToken.h"
|
||||
#include "utility/messaging/type/MessageActivateTokens.h"
|
||||
|
||||
#include "component/controller/Controller.h"
|
||||
#include "component/controller/GraphLayouter.h"
|
||||
|
||||
struct DummyNode;
|
||||
struct DummyEdge;
|
||||
class GraphView;
|
||||
class GraphAccess;
|
||||
class Node;
|
||||
|
||||
class GraphController
|
||||
: public Controller
|
||||
@@ -29,17 +30,9 @@ private:
|
||||
virtual void handleMessage(MessageActivateTokens* message);
|
||||
|
||||
GraphView* getView();
|
||||
void createDummyGraph(const Id activeId, const LayoutFunction layoutFunction);
|
||||
|
||||
DummyNode createDummyNode(const Id nodeId);
|
||||
Id findTopLevelNode(const Id nodeId);
|
||||
DummyNode buildNodeTopDown(const Id nodeId);
|
||||
|
||||
std::vector<DummyNode> createNeighbourNodes(const Id nodeId);
|
||||
std::vector<DummyNode> createNeighbourNodes(const DummyNode& node);
|
||||
|
||||
std::vector<DummyEdge> createEdges(const std::vector<DummyNode>& nodes);
|
||||
std::set<DummyEdge> getNeighbourEdgesOfNode(const DummyNode& node);
|
||||
void createDummyGraphForTokenId(Id tokenId, const GraphLayouter::LayoutFunction layoutFunction);
|
||||
DummyNode createDummyNodeTopDown(Node* node, std::vector<DummyEdge>* dummyEdges) const;
|
||||
|
||||
GraphAccess* m_graphAccess;
|
||||
};
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
struct DummyNode;
|
||||
|
||||
typedef void (*LayoutFunction)(std::vector<DummyNode>&);
|
||||
|
||||
class GraphLayouter
|
||||
{
|
||||
public:
|
||||
typedef void (*LayoutFunction)(std::vector<DummyNode>&);
|
||||
|
||||
static void layoutSimpleRaster(std::vector<DummyNode>& nodes);
|
||||
static void layoutSimpleRing(std::vector<DummyNode>& nodes);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user