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()) {
addReferenceResources(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 addReferenceResources(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.getReferenceResources()) {
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);
} else {
if (chLocalResNodes == null) {
// There is no channel-local ResourcePath.
// Then, create a new channel-local ResourceNode.
ResourceNode srcResNode = addResourceNodes(dataFlowGraph, srcRes, dstDfChannel, channelLocalResMap, false);
} else {
boolean bExists = false;
for (Channel ch: chLocalResNodes.keySet()) {
Set<ResourceNode> nodes = chLocalResNodes.get(ch);
for (ResourceNode node: nodes) {
ResourcePath r = node.getOutSideResource((DataTransferChannel) ch);
if (r.toString().equals(srcRes.toString())) {
bExists = true; // There exists the same ResourecPath within some channel.
break;
}
}
}
if (!bExists) {
// Create a new channel-local ResourceNode.
ResourceNode srcResNode = addResourceNodes(dataFlowGraph, srcRes, dstDfChannel, channelLocalResMap, false);
}
}
}
}
for (Channel childChannel: dstDfChannel.getChildren()) {
addReferenceResources(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;
// }
}