diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java index 7eb00dc..a94a45f 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java @@ -11,15 +11,12 @@ import models.dataConstraintModel.ChannelMember; import models.dataFlowModel.*; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; public class ControlFlowGraph extends DirectedGraph implements IFlowGraph { - private DataFlowGraph dataFlowGraph; - private CallGraph pushCallGraph; - private CallGraph pullCallGraph; + private final DataFlowGraph dataFlowGraph; + private final CallGraph pushCallGraph; + private final CallGraph pullCallGraph; public ControlFlowGraph(DataFlowGraph dataFlowGraph, DataTransferModel model) { this.dataFlowGraph = dataFlowGraph; @@ -33,56 +30,58 @@ } } - for (Edge resToCh : dataFlowGraph.getEdges()) { - if (!((DataFlowEdge) resToCh).isChannelToResource()) { - // A resource to channel edge - PushPullAttribute pushPull = ((PushPullAttribute) ((DataFlowEdge) resToCh).getAttribute()); - ResourceNode srcResNode = (ResourceNode) resToCh.getSource(); - ChannelNode chNode = (ChannelNode) resToCh.getDestination(); - for (Edge chToRes : chNode.getOutEdges()) { - ResourceNode dstResNode = (ResourceNode) chToRes.getDestination(); - if (!CodeGenerator.generatesComponent(srcResNode.getResourceHierarchy())) { - srcResNode = srcResNode.getParent(); - } - if (!CodeGenerator.generatesComponent(dstResNode.getResourceHierarchy())) { - dstResNode = dstResNode.getParent(); - } - if (!srcResNode.getResourceHierarchy().equals(dstResNode.getResourceHierarchy())) { - if (pushPull.getOptions().get(0) == PushPullValue.PUSH) { - // same direction as the data flow - pushCallGraph.addEdge(srcResNode, dstResNode, PushPullValue.PUSH); - } else { - // reverse direction to the data flow - pullCallGraph.addEdge(dstResNode, srcResNode, PushPullValue.PULL); - } - } + for (Edge edge : dataFlowGraph.getEdges()) { + if (((DataFlowEdge) edge).isChannelToResource()) { + continue; + } + DataFlowEdge resourceToChannelEdge = (DataFlowEdge) edge; + PushPullAttribute edgeAttribute = ((PushPullAttribute) resourceToChannelEdge.getAttribute()); + ChannelNode middleChannelNode = (ChannelNode) resourceToChannelEdge.getDestination(); + + for (Edge channelToResourceEdge : middleChannelNode.getOutEdges()) { + ResourceNode sourceNode = (ResourceNode) resourceToChannelEdge.getSource(); + ResourceNode destinationNode = (ResourceNode) channelToResourceEdge.getDestination(); + if (!CodeGenerator.generatesComponent(sourceNode.getResourceHierarchy())) { + sourceNode = sourceNode.getParent(); + } + if (!CodeGenerator.generatesComponent(destinationNode.getResourceHierarchy())) { + destinationNode = destinationNode.getParent(); + } + + if (sourceNode.getResourceHierarchy().equals(destinationNode.getResourceHierarchy())) { + continue; + } + + if (edgeAttribute.getOptions().get(0) == PushPullValue.PUSH) { + createEdgeChain(pushCallGraph, sourceNode, destinationNode, PushPullValue.PUSH); + } else { + createEdgeChain(pullCallGraph, destinationNode, sourceNode, PushPullValue.PULL); } } } - for (Channel ch : model.getInputChannels()) { - DataTransferChannel evCh = (DataTransferChannel) ch; - EventChannelObjectNode srcNode = new EventChannelObjectNode(evCh); - for (ChannelMember cm : evCh.getChannelMembers()) { - if (srcNode.getName() == null) { - Expression exp = cm.getStateTransition().getMessageExpression(); + for (Channel channel : model.getInputChannels()) { + DataTransferChannel eventChannel = (DataTransferChannel) channel; + EventChannelObjectNode sourceNode = new EventChannelObjectNode(eventChannel); + + for (ChannelMember member : eventChannel.getChannelMembers()) { + // Set up source node name + if (sourceNode.getName() == null) { + Expression exp = member.getStateTransition().getMessageExpression(); if (exp instanceof Term) { - srcNode.setName(((Term) exp).getSymbol().getName()); + sourceNode.setName(((Term) exp).getSymbol().getName()); } else if (exp instanceof Variable) { - srcNode.setName(((Variable) exp).getName()); + sourceNode.setName(((Variable) exp).getName()); } } - for (ResourceNode dstResNode : dataFlowGraph.getResourceNodes(cm.getResource().getResourceHierarchy())) { - if (!CodeGenerator.generatesComponent(dstResNode.getResourceHierarchy())) { - dstResNode = dstResNode.getParent(); + + for (ResourceNode resourceNode : dataFlowGraph.getResourceNodes(member.getResource().getResourceHierarchy())) { + if (!CodeGenerator.generatesComponent(resourceNode.getResourceHierarchy())) { + resourceNode = resourceNode.getParent(); } - StatefulObjectNode dstNode = pushCallGraph.getStatefulObjectNode(dstResNode); - if (dstNode == null) { - pushCallGraph.addNode(dstResNode); - dstNode = pushCallGraph.getStatefulObjectNode(dstResNode); - } - // from an input event channel to a resource - pushCallGraph.insertEdge(srcNode, dstNode, PushPullValue.PUSH, 0); + StatefulObjectNode destinationNode = pushCallGraph.getStatefulObjectNode(resourceNode); + + createEdgeChain(pushCallGraph, sourceNode, destinationNode, PushPullValue.PUSH); } } } @@ -128,4 +127,46 @@ } return allNodeSets; } + + private void createEdgeChain(CallGraph callGraph, ResourceNode sourceNode, ResourceNode destinationNode, PushPullValue option) { + Deque path = new ArrayDeque<>(); + + ResourceNode currentNode = destinationNode; + while (currentNode != null && currentNode != sourceNode) { + path.push(currentNode); + currentNode = currentNode.getParent(); + } + path.push(sourceNode); + + // path = [destination, parent, ..., root of destination, source] + while (!path.isEmpty()) { + ResourceNode from = path.pop(); + ResourceNode to = path.peek(); + if (to == null) { + continue; + } + callGraph.addEdge(from, to, option); + } + } + + private void createEdgeChain(CallGraph callGraph, EventChannelObjectNode sourceNode, StatefulObjectNode destinationNode, PushPullValue option) { + Deque path = new ArrayDeque<>(); + + StatefulObjectNode currentNode = destinationNode; + while (currentNode != null) { + path.push(currentNode); + currentNode = callGraph.getStatefulObjectNode(currentNode.getResource().getParent()); + } + path.push(sourceNode); + + // path = [destination, parent, ..., root of destination, source] + while (!path.isEmpty()) { + ObjectNode from = path.pop(); + ObjectNode to = path.peek(); + if (to == null) { + continue; + } + callGraph.insertEdge(from, to, option, 0); + } + } }