Newer
Older
AlgebraicDataflowArchitectureModel / AlgebraicDataflowArchitectureModel / src / models / controlFlowModel / CallGraph.java
package models.controlFlowModel;

import models.DirectedGraph;
import models.Node;
import models.dataFlowModel.PushPullValue;
import models.dataFlowModel.ResourceNode;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * {@link CallGraph} is a directed graph that represents the control flow between resources
 */
public class CallGraph extends DirectedGraph {
	protected Map<ResourceNode, StatefulObjectNode> statefulObjMap;
	
	public CallGraph() {
		statefulObjMap = new HashMap<>();
	}
	
	/**
	 * Add a node to the graph.
	 *
	 * @param node The node to be added.
	 */
	public void addNode(Node node) {
		if (node instanceof ResourceNode) {
			ResourceNode resNode = (ResourceNode) node;
			StatefulObjectNode objNode = statefulObjMap.get(resNode);
			if (objNode == null) {
				objNode = new StatefulObjectNode(resNode);
				statefulObjMap.put(resNode, objNode);
				super.addNode(objNode);
			}
		} else if (node instanceof StatefulObjectNode) {
			StatefulObjectNode objNode = (StatefulObjectNode) node;
			if (statefulObjMap.get(objNode.getResource()) == null) {
				statefulObjMap.put(objNode.getResource(), objNode);
				super.addNode(objNode);
			}
		} else {
			super.addNode(node);
		}
	}
	
	/**
	 * Add new call edge from {@code srcResNode} to {@code dstResNode} with PUSH / PULL selection.
	 *
	 * @param srcResNode     The resource node the edge starts from.
	 * @param dstResNode     The resource node the edge ends at.
	 * @param selectedOption PUSH / PULL
	 */
	public void addEdge(ResourceNode srcResNode, ResourceNode dstResNode, PushPullValue selectedOption) {
		addNode(srcResNode);
		addNode(dstResNode);
		addEdge(new CallEdge(getStatefulObjectNode(srcResNode), getStatefulObjectNode(dstResNode), selectedOption));
	}
	
	/**
	 * Insert an edge into the graph.
	 *
	 * @param srcObjNode     The source node of the edge to be inserted
	 * @param dstObjNode     The destination node of the edge to be inserted
	 * @param selectedOption PUSH or PULL
	 * @param n              The calling order of the edge
	 */
	public void insertEdge(ObjectNode srcObjNode, ObjectNode dstObjNode, PushPullValue selectedOption, int n) {
		CallEdge edge = new CallEdge(srcObjNode, dstObjNode, selectedOption);
		simpleAddEdge(edge);
		addNode(srcObjNode);
		addNode(dstObjNode);
		srcObjNode.insertOutEdge(edge, n);
		dstObjNode.addInEdge(edge);
	}
	
	public StatefulObjectNode getStatefulObjectNode(ResourceNode resNode) {
		return statefulObjMap.get(resNode);
	}
	
	public Set<Node> getRootNodes() {
		Set<Node> roots = new HashSet<>();
		for (Node node : getNodes()) {
			if (node instanceof StatefulObjectNode) {
				StatefulObjectNode statefulObjectNode = (StatefulObjectNode) node;
				if (statefulObjectNode.getResource().getResourceHierarchy().getParent() == null) {
					roots.add(node);
				}
			} else {
				if (node.getIndegree() == 0) {
					roots.add(node);
				}
			}
		}
		return roots;
	}
}