package models.dataFlowModel; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import models.dataConstraintModel.Channel; import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; public class DataTransferModel extends DataConstraintModel { public DataFlowGraph getDataFlowGraph() { DataFlowGraph dataFlowGraph = new DataFlowGraph(); Map<ResourceHierarchy, Map<Channel, Set<ResourceNode>>> channelLocalResMap = new HashMap<>(); for (Channel channel: getChannels()) { addResourceToChannelEdges(dataFlowGraph, channel, null, channelLocalResMap); } for (Channel channel: getChannels()) { addChannelToResourceEdges(dataFlowGraph, channel, null, channelLocalResMap); } for (Channel channel: getInputChannels()) { addChannelToResourceEdges(dataFlowGraph, channel, null, channelLocalResMap); } return dataFlowGraph; } private void addResourceToChannelEdges(DataFlowGraph dataFlowGraph, Channel dstChannel, ChannelNode parentChannelNode, Map<ResourceHierarchy, Map<Channel, Set<ResourceNode>>> channelLocalResMap) { DataTransferChannel dstDfChannel = (DataTransferChannel) dstChannel; ChannelNode dstChannelNode = dataFlowGraph.addChannelNode(parentChannelNode, dstDfChannel); for (ResourcePath srcRes: dstDfChannel.getInputResources()) { Map<Channel, Set<ResourceNode>> chLocalResNodes = channelLocalResMap.get(srcRes.getResourceHierarchy()); if (srcRes.getNumberOfParameters() == 0) { // ResourcePath without parameter corresponds to a global ResourceNode. ResourceNode srcResNode = addResourceNodes(dataFlowGraph, srcRes, dstDfChannel, channelLocalResMap, false); dataFlowGraph.addEdge(srcResNode, dstChannelNode); } else { if (chLocalResNodes == null || chLocalResNodes.get(dstChannel) == null) { // There is no channel-local ResourcePath. // Then, create a new channel-local ResourceNode. ResourceNode srcResNode = addResourceNodes(dataFlowGraph, srcRes, dstDfChannel, channelLocalResMap, false); dataFlowGraph.addEdge(srcResNode, dstChannelNode); } else { // There already has been a channel-local ResourceNode. Set<ResourceNode> nodes = chLocalResNodes.get(dstChannel); // channel-local ResourceNodes. boolean bExists = false; for (ResourceNode node: nodes) { ResourcePath r = node.getOutSideResource(dstDfChannel); if (r.toString().equals(srcRes.toString())) { bExists = true; // There exists a textually identical ResourecPath within the same channel. break; } } if (!bExists) { // Create a new channel-local ResourceNode. ResourceNode srcResNode = addResourceNodes(dataFlowGraph, srcRes, dstDfChannel, channelLocalResMap, false); dataFlowGraph.addEdge(srcResNode, dstChannelNode); } } } } for (Channel childChannel: dstDfChannel.getChildren()) { addResourceToChannelEdges(dataFlowGraph, childChannel, dstChannelNode, channelLocalResMap); } } private void addChannelToResourceEdges(DataFlowGraph dataFlowGraph, Channel srcChannel, ChannelNode parentChannelNode, Map<ResourceHierarchy, Map<Channel, Set<ResourceNode>>> channelLocalResMap) { DataTransferChannel srcDfChannel = (DataTransferChannel) srcChannel; ChannelNode srcChannelNode = dataFlowGraph.addChannelNode(parentChannelNode, srcDfChannel); for (ResourcePath dstRes: srcDfChannel.getOutputResources()) { Map<Channel, Set<ResourceNode>> chLocalResNodes = channelLocalResMap.get(dstRes.getResourceHierarchy()); // ResourceNodes that have the same ResourceHierarchy. Set<ResourceNode> dstResSet = new HashSet<>(); if (dstRes.getNumberOfParameters() == 0) { // ResourcePath without parameter corresponds to a global ResourceNode. if (chLocalResNodes == null) { // Create a new global terminal ResourceNode. ResourceNode dstResNode = addResourceNodes(dataFlowGraph, dstRes, srcDfChannel, channelLocalResMap, true); dstResSet.add(dstResNode); } else { // Select all (usually one) global ResourceNodes. for (Set<ResourceNode> resSet: chLocalResNodes.values()) { dstResSet.addAll(resSet); } } } else { if (chLocalResNodes == null) { // There is no corresponding ResourceNode. // Create a new channel-local terminal ResourceNode. ResourceNode dstResNode = addResourceNodes(dataFlowGraph, dstRes, srcDfChannel, channelLocalResMap, true); dstResSet.add(dstResNode); } else { if (chLocalResNodes.get(srcDfChannel) == null) { // Select all non-terminal ResourceNodes. for (Set<ResourceNode> resSet: chLocalResNodes.values()) { dstResSet.addAll(resSet); } } else { // There already has been a channel-local terminal ResourceNode. if (chLocalResNodes.size() > 0) { // There already has been a channel-local ResourceNode. for (Set<ResourceNode> resNodes: chLocalResNodes.values()) { for (ResourceNode localResNode: resNodes) { for (ResourcePath localResPath: localResNode.getInSideResources()) { if (localResPath.toString().equals(dstRes.toString())) { // Channel-local ResourcePath should be identical, and the identical ResourcePath is selected on top priority. dstResSet.add(localResNode); } } } } } // Search a common channel-local ancestor. if (dstResSet.size() == 0) { ResourcePath dstParent = dstRes.getParent(); while (dstParent != null && dstParent.getNumberOfParameters() > 0) { Map<Channel, Set<ResourceNode>> chToLocalDstNodes = channelLocalResMap.get(dstParent.getResourceHierarchy()); if (chToLocalDstNodes != null) { for (Channel dstCh: chToLocalDstNodes.keySet()) { for (ResourceNode localParentNode: chToLocalDstNodes.get(dstCh)) { for (ResourcePath localParentPath: localParentNode.getInSideResources()) { if (localParentPath.toString().equals(dstParent.toString())) { // There already has been a common channel-local ancestor. ResourceNode dstResNode = addResourceNodes(dataFlowGraph, dstRes, (DataTransferChannel)dstCh, channelLocalResMap, false); dstResSet.add(dstResNode); break; } } if (dstResSet.size() > 0) break; } if (dstResSet.size() > 0) break; } if (dstResSet.size() > 0) break; } dstParent = dstParent.getParent(); } } if (dstResSet.size() == 0) { for (Set<ResourceNode> nodes: chLocalResNodes.values()) { // Select all corresponding ResourceNodes. dstResSet.addAll(nodes); } } if (dstResSet.size() == 0) { // Otherwise create a new ResourceNode. ResourceNode dstResNode = addResourceNodes(dataFlowGraph, dstRes, srcDfChannel, channelLocalResMap, false); dstResSet.add(dstResNode); } } } } for (ResourceNode dstResNode: dstResSet) { dstResNode.addInSideResource(srcDfChannel, dstRes); dataFlowGraph.addEdge(srcChannelNode, dstResNode); // Connect to each ResourceNode that has the same ResourceHierarchy. } } for (Channel childChannel: srcDfChannel.getChildren()) { addChannelToResourceEdges(dataFlowGraph, childChannel, srcChannelNode, channelLocalResMap); } } private ResourceNode addResourceNodes(DataFlowGraph dataFlowGraph, ResourcePath resPath, DataTransferChannel dfChannel, Map<ResourceHierarchy, Map<Channel, Set<ResourceNode>>> channelLocalResMap, boolean isTerminal) { ResourceNode resNode = null; if (resPath.getParent() == null) { if (!isTerminal) { resNode = dataFlowGraph.addResourceNode(null, resPath, dfChannel); } else { resNode = dataFlowGraph.addTerminalResourceNode(null, dfChannel, resPath); } } else { // Search an identical parent ResourceNode. ResourceNode parent = null; DataTransferChannel parentDfChannel = dfChannel; if (resPath.getResourceHierarchy().getParent().getNumParameters() == 0) { parentDfChannel = null; } if (channelLocalResMap.get(resPath.getResourceHierarchy().getParent()) != null) { Set<ResourceNode> chLocalNodes = channelLocalResMap.get(resPath.getResourceHierarchy().getParent()).get(parentDfChannel); if (chLocalNodes != null) { for (ResourceNode node: chLocalNodes) { for (ResourcePath r: node.getOutSideResources()) { if (r.toString().equals(resPath.getParent().toString())) { parent = node; break; } } if (parent != null) break; for (ResourcePath r: node.getInSideResources()) { if (r.toString().equals(resPath.getParent().toString())) { parent = node; break; } } if (parent != null) break; } } } if (parent == null) { parent = addResourceNodes(dataFlowGraph, resPath.getParent(), parentDfChannel, channelLocalResMap, false); } if (!isTerminal) { resNode = dataFlowGraph.addResourceNode(parent, resPath, dfChannel); } else { resNode = dataFlowGraph.addTerminalResourceNode(parent, dfChannel, resPath); } } Map<Channel, Set<ResourceNode>> chToLocalNodes = channelLocalResMap.get(resPath.getResourceHierarchy()); if (chToLocalNodes == null) { chToLocalNodes = new HashMap<>(); channelLocalResMap.put(resPath.getResourceHierarchy(), chToLocalNodes); } Set<ResourceNode> chLocalNodes = chToLocalNodes.get(dfChannel); if (chLocalNodes == null) { chLocalNodes = new HashSet<>(); chToLocalNodes.put(dfChannel, chLocalNodes); } chLocalNodes.add(resNode); return resNode; } // private ResourceNode addResourceNodes(DataFlowGraph dataFlowGraph, ResourcePath resPath, DataTransferChannel dfChannel, // Map<ResourceHierarchy, Map<Channel, Set<ResourceNode>>> resourceMap) { // if (resPath.getNumberOfParameters() == 0) { // // ResourcePath without parameter corresponds to a global ResourceNode. // dfChannel = null; // } // if (resourceMap.get(resPath.getResourceHierarchy()) != null && resourceMap.get(resPath.getResourceHierarchy()).get(dfChannel) != null) { // Set<ResourceNode> nodes = resourceMap.get(resPath.getResourceHierarchy()).get(dfChannel); // for (ResourceNode node: nodes) { // if (node.getOutSideResource().toString().equals(resPath.toString())) { // return node; // } // for (ResourcePath res: node.getInSideResources()) { // if (res.toString().toString().equals(resPath.toString())) { // return node; // } // } // } // } // ResourceNode resNode = null; // if (resPath.getParent() == null) { // resNode = dataFlowGraph.addResourceNode(null, dfChannel, resPath); // } else { // ResourceNode parent = addResourceNodes(dataFlowGraph, resPath.getParent(), dfChannel, resourceMap); // resNode = dataFlowGraph.addResourceNode(parent, dfChannel, resPath); // } // Map<Channel, Set<ResourceNode>> chToNodes = resourceMap.get(resPath.getResourceHierarchy()); // if (chToNodes == null) { // chToNodes = new HashMap<>(); // resourceMap.put(resPath.getResourceHierarchy(), chToNodes); // } // Set<ResourceNode> nodes = chToNodes.get(dfChannel); // if (nodes == null) { // nodes = new HashSet<>(); // chToNodes.put(dfChannel, nodes); // } // nodes.add(resNode); // return resNode; // } }