diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java index 29c0dda..3ea8a48 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -375,18 +375,18 @@ Map channelsIn = new HashMap<>(); Map channelsOut = new HashMap<>(); - Map resources = new HashMap<>(); + Map resources = new HashMap<>(); // create resource vertices for (ResourceNode resNode: dataFlowGraph.getRootResourceNodes()) { int w = 80; int h = 30; - ResourcePath res = resNode.getOutSideResource(); + ResourcePath res = resNode.getPrimaryResourcePath(); Object resource = graph.insertVertex(parent, null, res.getResourceName(), 20, 20, w, h, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex - resources.put(System.identityHashCode(res), resource); - getChildResource(resource, resNode, resources, w, h); + resources.put(resNode, resource); + createChildResourceVerticies(resource, resNode, resources, w, h); } // create channel vertices @@ -395,7 +395,7 @@ if (channel.getInputResources().size() > 0) { // Normal channel if (channelsIn.get(channel) == null || channelsOut.get(channel) == null) { - if(channel.getSelectors().toString() == "[]") { + if (channel.getSelectors().toString() == "[]") { Object chCell = graph.insertVertex(parent, null, channel.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); port_in.setVertex(true); @@ -405,8 +405,7 @@ graph.addCell(port_out, chCell); // insert the output port of a channel channelsIn.put(channel, port_in); channelsOut.put(channel, port_out); - }else { - + } else { for (Selector s: channel.getSelectors()) { Expression exp = s.getExpression(); String selName = exp.toString(); @@ -427,7 +426,7 @@ } else { // I/O channel if (channelsOut.get(channel) == null) { - if(channel.getSelectors().toString() == "[]") { + if (channel.getSelectors().toString() == "[]") { Object chCell = graph.insertVertex(parent, null, channel.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); port_in.setVertex(true); @@ -437,8 +436,7 @@ graph.addCell(port_out, chCell); // insert the output port of a channel channelsIn.put(channel, port_in); channelsOut.put(channel, port_out); - }else { - + } else { for (Selector s: channel.getSelectors()) { Expression exp = s.getExpression(); String selName = exp.toString(); @@ -465,20 +463,20 @@ if (dfEdge.isChannelToResource()) { // output edge DataTransferChannel channel = ((ChannelNode) dfEdge.getSource()).getChannel(); - ResourcePath dstRes = ((ResourceNode) dfEdge.getDestination()).getOutSideResource(); - graph.insertEdge(parent, null, new SrcDstAttribute(channel, dstRes), channelsOut.get(channel), resources.get(System.identityHashCode(dstRes)), "movable=false"); + ResourcePath dstRes = ((ResourceNode) dfEdge.getDestination()).getInSideResource(channel); + graph.insertEdge(parent, null, new SrcDstAttribute(channel, dstRes), channelsOut.get(channel), resources.get((ResourceNode) dfEdge.getDestination()), "movable=false"); } else { // input edge - ResourcePath srcRes = ((ResourceNode) dfEdge.getSource()).getOutSideResource(); DataTransferChannel channel = ((ChannelNode) dfEdge.getDestination()).getChannel(); + ResourcePath srcRes = ((ResourceNode) dfEdge.getSource()).getOutSideResource(channel); Set> toRes = getResourceDependencyForChannel(channel, model, dataFlowGraph); - for(Map.Entry RtoR : toRes) { + for(Map.Entry RtoR: toRes) { graph.insertEdge(parent, null, null, - resources.get(System.identityHashCode(RtoR.getValue().getOutSideResource())), - resources.get(System.identityHashCode(RtoR.getKey().getOutSideResource())), "dashed=true;movable=false"); + resources.get(RtoR.getValue()), + resources.get(RtoR.getKey()), "dashed=true;movable=false"); } - graph.insertEdge(parent, null, new SrcDstAttribute(srcRes, channel), resources.get(System.identityHashCode(srcRes)), channelsIn.get(channel), "movable=false"); + graph.insertEdge(parent, null, new SrcDstAttribute(srcRes, channel), resources.get((ResourceNode) dfEdge.getSource()), channelsIn.get(channel), "movable=false"); } } @@ -486,7 +484,7 @@ // reference edges DataTransferChannel channel = (DataTransferChannel) ch; for (ResourcePath refRes: channel.getReferenceResources()) { - graph.insertEdge(parent, null, null, resources.get(System.identityHashCode(refRes)), channelsIn.get(channel), "dashed=true;movable=false"); + graph.insertEdge(parent, null, null, resources.get(dataFlowGraph.getResourceNode(refRes)), channelsIn.get(channel), "dashed=true;movable=false"); } } } finally { @@ -498,15 +496,15 @@ return graph; } - public void getChildResource(Object resource, ResourceNode resNode, Map resources, int w, int h) { + public void createChildResourceVerticies(Object resource, ResourceNode resNode, Map resources, int w, int h) { - for (ResourceNode c: resNode.getChildren()) { - ResourcePath chRes = c.getOutSideResource(); - Object chResource = graph.insertVertex(resource, null, - chRes.getName(), 0, 0, w, h, + for (ResourceNode childNode: resNode.getChildren()) { + ResourcePath childRes = childNode.getPrimaryResourcePath(); + Object childResource = graph.insertVertex(resource, null, + childRes.getName(), 0, 0, w, h, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex - resources.put(System.identityHashCode(chRes), chResource); - getChildResource(chResource, c, resources, w, h); + resources.put(childNode, childResource); + createChildResourceVerticies(childResource, childNode, resources, w, h); } } @@ -537,7 +535,7 @@ mxCell edgeCell = (mxCell) edge; if (edgeCell.getValue() instanceof SrcDstAttribute) { SrcDstAttribute edgeAttr = (SrcDstAttribute) edgeCell.getValue(); - if (srcRes.getOutSideResource().equals(edgeAttr.getSource()) && channel.equals(edgeAttr.getDestination())) { + if (srcRes.getPrimaryResourcePath().equals(edgeAttr.getSource()) && channel.equals(edgeAttr.getDestination())) { edgeCell.setValue(dataFlow.getAttribute()); break; } @@ -795,6 +793,9 @@ if (srcNode != null) { for (ChannelMember dstMem: dependency.get(srcMem).getValue()) { ResourceNode dstNode = dataFlowGraph.getResourceNode(dstMem.getResource()); + while (srcNode.getResourceHierarchy().getNumParameters() == 0 && srcNode.getParent() != null) { + srcNode = srcNode.getParent(); + } resourceDpendency.add(new AbstractMap.SimpleEntry<>(srcNode, dstNode)); } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index 13c6394..acfbf44 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -247,7 +247,7 @@ for (Edge resToCh: resNode.getOutEdges()) { ChannelNode chNode = (ChannelNode) resToCh.getDestination(); for (ChannelMember m: chNode.getChannel().getReferenceChannelMembers()) { - if (m.getResource().equals(curResNode.getOutSideResource())) { + if (curResNode.getOutSideResources().contains(m.getResource())) { topologicalSort(resNode, allNodes, dependedRootComponentGraph, visited, orderedList); } } @@ -259,7 +259,7 @@ } protected void updateMainComponent(TypeDeclaration mainType, MethodDeclaration mainConstructor, Node componentNode, - MethodDeclaration constructor, ILanguageSpecific langSpec) { + MethodDeclaration constructor, final List depends, ILanguageSpecific langSpec) { // Declare the field to refer to each object in the main type. ResourceNode resNode = null; String nodeName = null; @@ -275,6 +275,9 @@ } // Add a statement to instantiate each object to the main constructor. List parameters = new ArrayList<>(); + for (ResourceHierarchy res: depends) { + parameters.add(res.getResourceName()); + } if (constructor.getParameters() != null) { for (VariableDeclaration var: constructor.getParameters()) { parameters.add(var.getName()); @@ -392,7 +395,7 @@ protected void declareAccessorInMainComponent(TypeDeclaration mainComponent, ResourceNode accessRes, MethodDeclaration stateGetter, ILanguageSpecific langSpec) { List mainGetterParams = new ArrayList<>(); int v = 1; - for (Expression param: accessRes.getOutSideResource().getPathParams()) { + for (Expression param: accessRes.getPrimaryResourcePath().getPathParams()) { if (param instanceof Variable) { Variable var = (Variable) param; mainGetterParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); @@ -409,7 +412,7 @@ accessor = langSpec.newMethodDeclaration(getterPrefix + getComponentName(accessRes.getResourceHierarchy(), langSpec), false, getImplStateType(accessRes.getResourceHierarchy(), langSpec), mainGetterParams); } Block block = new Block(); - Expression getState = getPullAccessor().getDirectStateAccessorFor(accessRes.getOutSideResource(), null); + Expression getState = getPullAccessor().getDirectStateAccessorFor(accessRes.getPrimaryResourcePath(), null); block.addStatement(langSpec.getReturnStatement(getState.toImplementation(new String[] {null})) + langSpec.getStatementDelimiter()); // if (stateGetter.getParameters() == null || stateGetter.getParameters().size() == 0) { // block.addStatement(langSpec.getReturnStatement(langSpec.getMethodInvocation(accessRes.getResourceName(), stateGetter.getName())) + langSpec.getStatementDelimiter()); @@ -429,7 +432,7 @@ Set refs = new HashSet<>(); for (Channel ch : model.getChannels()) { DataTransferChannel c = (DataTransferChannel) ch; - if (c.getInputResources().contains(resourceNode.getOutSideResource())) { + if (resourceNode.getOutSideResource(c) != null) { for (ResourcePath res: c.getReferenceResources()) { if (!refs.contains(res) && !depends.contains(res.getResourceHierarchy())) { refs.add(res); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index e2bb32d..d562e39 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -83,7 +83,7 @@ if (resourceNode.getResourceHierarchy().getParent() == null) { // For each root resource // Update the main component for this component. - updateMainComponent(mainComponent, mainConstructor, componentNode, constructor, langSpec); + updateMainComponent(mainComponent, mainConstructor, componentNode, constructor, depends, langSpec); } // Declare the fields to refer to reference resources. @@ -289,14 +289,14 @@ // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().equals(resourceNode.getOutSideResource()) && cm.isOutside()) { + if (resourceNode.getOutSideResources().contains(cm.getResource()) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } for (Edge chToRes: resToCh.getDestination().getOutEdges()) { if (chToRes.getDestination() instanceof ResourceNode) { - ResourceHierarchy dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource().getResourceHierarchy(); + ResourceHierarchy dstRes = ((ResourceNode) chToRes.getDestination()).getResourceHierarchy(); // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = false; for (ChannelMember cm: ch.getOutputChannelMembers()) { @@ -324,12 +324,12 @@ } for (Edge chToRes: resourceNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { - ResourceHierarchy srcRes = ((ResourceNode) resToCh.getSource()).getOutSideResource().getResourceHierarchy(); + ResourceHierarchy srcRes = ((ResourceNode) resToCh.getSource()).getResourceHierarchy(); DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().equals(((ResourceNode) resToCh.getSource()).getOutSideResource()) && cm.isOutside()) { + if (((ResourceNode) resToCh.getSource()).getOutSideResources().contains(cm.getResource()) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } @@ -379,7 +379,6 @@ // leaf resource. FieldDeclaration stateField = langSpec.newFieldDeclaration(resStateType, fieldOfResourceState, langSpec.getFieldInitializer(resStateType, resourceNode.getResourceHierarchy().getInitialValue())); component.addField(stateField); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), langSpec.newVariableDeclaration(resStateType, langSpec.toVariableName(resourceName)))); } else { ResourceHierarchy child = children.iterator().next(); if (children.size() == 1 && child.getNumParameters() > 0) { @@ -412,14 +411,14 @@ // Check if the source resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().equals(resourceNode.getOutSideResource()) && cm.isOutside()) { + if (resourceNode.getOutSideResources().contains(cm.getResource()) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } for (Edge chToRes: re.getDestination().getOutEdges()) { if (chToRes.getDestination() instanceof ResourceNode) { - ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); + ResourceHierarchy dstRes = ((ResourceNode) chToRes.getDestination()).getResourceHierarchy(); // Check if the destination resource is outside of the channel scope. boolean outsideOutputResource = false; for (ChannelMember cm: ch.getOutputChannelMembers()) { @@ -430,15 +429,15 @@ } if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { // Declare a field in the parent component to refer to the destination resource of push transfer. - if (!generatesComponent(dstRes.getResourceHierarchy())) { + if (!generatesComponent(dstRes)) { dstRes = dstRes.getParent(); } - String dstResName = getComponentName(dstRes.getResourceHierarchy(), langSpec); + String dstResName = getComponentName(dstRes, langSpec); FieldDeclaration refFieldForPush = langSpec.newFieldDeclaration(new Type(dstResName, dstResName), langSpec.toVariableName(dstResName)); VariableDeclaration refVarForPush = langSpec.newVariableDeclaration(new Type(dstResName, dstResName), langSpec.toVariableName(dstResName)); if (component != null) { // A component is created for this resource. - if (resourceNode.getResourceHierarchy() != dstRes.getResourceHierarchy()) { + if (resourceNode.getResourceHierarchy() != dstRes) { component.addField(refFieldForPush); if (!outsideOutputResource) { constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refVarForPush)); @@ -446,7 +445,7 @@ } } else { // No component is created for this resource. - if (resourceNode.getParent().getResourceHierarchy() != dstRes.getResourceHierarchy()) { + if (resourceNode.getParent().getResourceHierarchy() != dstRes) { parentComponent.addField(refFieldForPush); if (!outsideOutputResource) { constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refVarForPush)); @@ -457,7 +456,7 @@ // When the reference to the destination resource can vary. if (dstRes.getParent() != null) { // Reference to its root resource. - String dstRootResName = getComponentName(dstRes.getRoot().getResourceHierarchy(), langSpec); + String dstRootResName = getComponentName(dstRes.getRoot(), langSpec); Type dstRootResType = new Type(dstRootResName, dstRootResName); dstRootResName = langSpec.toVariableName(dstRootResName); FieldDeclaration refRootFieldForPush = langSpec.newFieldDeclaration(dstRootResType, dstRootResName); @@ -499,8 +498,8 @@ for (Edge chToRes : resourceNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; - ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); + ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(ch); // Check if the source resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { @@ -586,7 +585,7 @@ } // Declare the state field in the parent component. if (component == null) { - ResourceHierarchy res = resourceNode.getOutSideResource().getResourceHierarchy(); + ResourceHierarchy res = resourceNode.getResourceHierarchy(); if (((StoreAttribute) resourceNode.getAttribute()).isStored() && noPullTransfer && res.getNumParameters() == 0) { String resName = langSpec.toVariableName(getComponentName(res, langSpec)); boolean existsField = false; @@ -671,7 +670,7 @@ DataFlowEdge dIn = (DataFlowEdge) resToCh; ChannelMember in = null; for (ChannelMember cm: ch2.getInputChannelMembers()) { - if (cm.getResource().equals(((ResourceNode) dIn.getSource()).getOutSideResource())) { + if (((ResourceNode) dIn.getSource()).getOutSideResources().contains(cm.getResource())) { in = cm; break; } @@ -760,7 +759,7 @@ for (Edge resToCh: chToRes.getSource().getInEdges()) { DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); DataFlowEdge re = (DataFlowEdge) resToCh; - ResourcePath srcResPath = ((ResourceNode) re.getSource()).getOutSideResource(); + ResourcePath srcResPath = ((ResourceNode) re.getSource()).getOutSideResource(ch); String srcResComponentName = getComponentName(srcResPath.getResourceHierarchy(), langSpec); String srcResName = langSpec.toVariableName(srcResComponentName); // Check if the input resource is outside of the channel scope. @@ -1045,7 +1044,7 @@ ChannelMember in = null; Set outsideInputMembers2 = new HashSet<>(); for (ChannelMember cm: ch2.getInputChannelMembers()) { - if (cm.getResource().equals(resourceNode.getOutSideResource())) { + if (resourceNode.getOutSideResources().contains(cm.getResource())) { if (cm.isOutside()) { outsideInputResource2 = true; // Regarded as pull transfer. } @@ -1144,7 +1143,7 @@ if (outsideInputMembers2.size() > 0) { if (!generatesComponent(resourceNode.getResourceHierarchy())) { // srcRes2 does not have a component. - ResourcePath srcRes2 = resourceNode.getOutSideResource(); + ResourcePath srcRes2 = resourceNode.getOutSideResource(ch2); for (ChannelMember out: ch2.getOutputChannelMembers()) { if (!generatesComponent(out.getResource().getResourceHierarchy())) { // Also dstRes2 does not have a component. @@ -1442,7 +1441,9 @@ for (Selector selector: ch.getAllSelectors()) { if (selector.getExpression() instanceof Variable) { Variable selVar = (Variable) selector.getExpression(); - args.add(selVar.getName()); + if (!args.contains(selVar.getName())) { + args.add(selVar.getName()); + } } } // Values of message parameters. @@ -1457,9 +1458,11 @@ } } if (refVarName != null) { - args.add(refVarName); + if (!args.contains(refVarName)) { + args.add(refVarName); + } } else { - args.add(varEnt.getValue().getName()); + if (!args.contains(varEnt.getValue().getName())) args.add(varEnt.getValue().getName()); } } } @@ -1539,7 +1542,7 @@ ChannelMember in = null; Set outsideInputMembers2 = new HashSet<>(); for (ChannelMember cm: ch2.getInputChannelMembers()) { - if (cm.getResource().equals(resourceNode.getOutSideResource())) { + if (resourceNode.getOutSideResources().contains(cm.getResource())) { if (cm.isOutside()) { outsideInputResource2 = true; // Regarded as pull transfer. } @@ -1597,7 +1600,7 @@ referredSet = new HashSet<>(); referredResources.put(input, referredSet); } - if (!ref.equals(resourceNode.getOutSideResource())) { + if (!resourceNode.getOutSideResources().contains(ref)) { String refVarName = ref.getResourceName(); if (!referredSet.contains(ref)) { referredSet.add(ref); @@ -1637,7 +1640,7 @@ } if (outsideInputMembers2.size() > 0) { if (!generatesComponent(resourceNode.getResourceHierarchy())) { - ResourcePath srcRes2 = resourceNode.getOutSideResource(); + ResourcePath srcRes2 = resourceNode.getOutSideResource(ch2); for (ChannelMember out2: ch2.getOutputChannelMembers()) { if (!generatesComponent(out2.getResource().getResourceHierarchy())) { ResourcePath dstRes2 = out2.getResource(); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index afef24a..f0b2bc0 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -172,9 +172,9 @@ DataFlowEdge re = (DataFlowEdge) resToCh; if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { for (Edge chToRes: re.getDestination().getOutEdges()) { - ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); - String resName = getComponentName(dstRes.getResourceHierarchy()); - depends.add(dstRes.getResourceHierarchy()); + ResourceHierarchy dstRes = ((ResourceNode) chToRes.getDestination()).getResourceHierarchy(); + String resName = getComponentName(dstRes); + depends.add(dstRes); fieldInitializer += toVariableName(resName) + ","; f = true; } @@ -183,10 +183,10 @@ for (Edge chToRes : resourceNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; - ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); - String resName = getComponentName(srcRes.getResourceHierarchy()); + ResourceHierarchy srcRes = ((ResourceNode) re.getSource()).getResourceHierarchy(); + String resName = getComponentName(srcRes); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { - depends.add(srcRes.getResourceHierarchy()); + depends.add(srcRes); fieldInitializer += toVariableName(resName) + ","; f = true; } else { @@ -194,9 +194,9 @@ if (cn.getIndegree() > 1 || (cn.getIndegree() == 1 && cn.getChannel().getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { // Declare a field to cache the state of the source resource in the type of the destination resource. - ResourcePath cacheRes = ((ResourceNode) re.getSource()).getOutSideResource(); + ResourceHierarchy cacheRes = ((ResourceNode) re.getSource()).getResourceHierarchy(); component.addField(new FieldDeclaration( - cacheRes.getResourceStateType(), ((ResourceNode) re.getSource()).getOutSideResource().getResourceName(), getInitializer(cacheRes))); + cacheRes.getResourceStateType(), cacheRes.getResourceName(), getInitializer(cacheRes))); } } } @@ -214,7 +214,7 @@ } for (Channel ch : model.getChannels()) { DataTransferChannel c = (DataTransferChannel) ch; - if (c.getInputResources().contains(resourceNode.getOutSideResource())) { + if (resourceNode.getOutSideResource(c) != null) { for (ResourcePath res: c.getReferenceResources()) { if (!refs.contains(res) && !depends.contains(res.getResourceHierarchy())) { refs.add(res); @@ -239,18 +239,17 @@ // Declare the field to store the state in the type of each resource. if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { - ResourcePath res = resourceNode.getOutSideResource(); - Set children = resourceNode.getResourceHierarchy().getChildren(); + ResourceHierarchy res = resourceNode.getResourceHierarchy(); + Set children = res.getChildren(); if (children == null || children.size() == 0) { // leaf resource. - Type fieldType = getImplStateType(res.getResourceHierarchy()); + Type fieldType = getImplStateType(res); component.addField(new FieldDeclaration(fieldType, "value", getInitializer(res))); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), new VariableDeclaration(fieldType, toVariableName(resourceName)))); } else { ResourceHierarchy child = children.iterator().next(); if (children.size() == 1 && child.getNumParameters() > 0) { // map or list. - component.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); + component.addField(new FieldDeclaration(getImplStateType(res), "value", getInitializer(res))); } else { // class for (ResourceHierarchy c: children) { @@ -315,8 +314,8 @@ for (Edge chToRes : resourceNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; - ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); + ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(ch); // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { @@ -339,7 +338,7 @@ } } // Declare the state field in the parent component. - ResourceHierarchy res = resourceNode.getOutSideResource().getResourceHierarchy(); + ResourceHierarchy res = resourceNode.getResourceHierarchy(); if (((StoreAttribute) resourceNode.getAttribute()).isStored() && noPullTransfer && res.getNumParameters() == 0) { String resName = getComponentName(res); FieldDeclaration stateField = new FieldDeclaration(res.getResourceStateType(), toVariableName(resName)); @@ -393,13 +392,13 @@ // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().equals(resourceNode.getOutSideResource()) && cm.isOutside()) { + if (resourceNode.getOutSideResources().contains(cm.getResource()) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } } for (Edge chToRes: re.getDestination().getOutEdges()) { - ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); + ResourceHierarchy dstRes = ((ResourceNode) chToRes.getDestination()).getResourceHierarchy(); // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = false; for (ChannelMember cm: ch.getOutputChannelMembers()) { @@ -410,16 +409,16 @@ } if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { // Declare a field to refer to the destination resource of push transfer. - if (!generatesComponent(dstRes.getResourceHierarchy())) { + if (!generatesComponent(dstRes)) { dstRes = dstRes.getParent(); } - String dstResName = getComponentName(dstRes.getResourceHierarchy()); - depends.add(dstRes.getResourceHierarchy()); + String dstResName = getComponentName(dstRes); + depends.add(dstRes); FieldDeclaration dstRefField = new FieldDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); VariableDeclaration dstRefVar = new VariableDeclaration(new Type(dstResName, dstResName), toVariableName(dstResName)); if (component != null) { // A component is created for this resource. - if (resourceNode.getResourceHierarchy() != dstRes.getResourceHierarchy()) { + if (resourceNode.getResourceHierarchy() != dstRes) { component.addField(dstRefField); if (!outsideOutputResource) { constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), dstRefVar)); @@ -427,7 +426,7 @@ } } else { // No component is created for this resource. - if (resourceNode.getParent().getResourceHierarchy() != dstRes.getResourceHierarchy()) { + if (resourceNode.getParent().getResourceHierarchy() != dstRes) { fields.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRefField)); if (!outsideOutputResource) { constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), dstRefVar)); @@ -438,8 +437,8 @@ // When the reference to the destination resource can vary. if (dstRes.getParent() != null) { // Reference to root resource. - ResourcePath dstRootRes = dstRes.getRoot(); - String dstRootResName = getComponentName(dstRootRes.getResourceHierarchy()); + ResourceHierarchy dstRootRes = dstRes.getRoot(); + String dstRootResName = getComponentName(dstRootRes); FieldDeclaration dstRootRefField = new FieldDeclaration(new Type(dstRootResName, dstRootResName), toVariableName(dstRootResName)); VariableDeclaration dstRootRefVar = new VariableDeclaration(new Type(dstRootResName, dstRootResName), toVariableName(dstRootResName)); if (component != null) { @@ -460,8 +459,8 @@ for (Edge chToRes : resourceNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; - ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); + ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(ch); // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { @@ -553,7 +552,7 @@ } params.add(new VariableDeclaration(srcRes.getResourceStateType(), srcRes.getResourceName())); // The state of the source resource to carry the data-flow. for (ResourcePath ref: ch.getReferenceResources()) { - if (!ref.equals(resourceNode.getOutSideResource())) { + if (!ref.equals(resourceNode.getInSideResource(ch))) { params.add(new VariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); } } @@ -605,7 +604,7 @@ // Declare a field to refer to the reference resource. for (Channel ch : model.getChannels()) { DataTransferChannel c = (DataTransferChannel) ch; - if (c.getInputResources().contains(resourceNode.getOutSideResource())) { + if (resourceNode.getOutSideResource(c) != null) { for (ResourcePath res: c.getReferenceResources()) { if (!refs.contains(res) && !depends.contains(res.getResourceHierarchy())) { refs.add(res); @@ -971,7 +970,7 @@ for (Edge resToCh : resNode.getOutEdges()) { ChannelNode chNode = (ChannelNode) resToCh.getDestination(); for (ChannelMember m: chNode.getChannel().getReferenceChannelMembers()) { - if (m.getResource().equals(curResNode.getOutSideResource())) { + if (curResNode.getOutSideResources().contains(m.getResource())) { topologicalSort(resNode, graph, dependedRootComponentGraph, visited, orderedList); } } @@ -984,7 +983,7 @@ MethodDeclaration getterAccessor = null; List mainGetterParams = new ArrayList<>(); int v = 1; - for (Expression param: resourceNode.getOutSideResource().getPathParams()) { + for (Expression param: resourceNode.getPrimaryResourcePath().getPathParams()) { if (param instanceof Variable) { Variable var = (Variable) param; mainGetterParams.add(new VariableDeclaration(var.getType(), var.getName())); @@ -1004,7 +1003,7 @@ getImplStateType(resourceNode.getResourceHierarchy())); } getterAccessor.setBody(new Block()); - Expression getState = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(resourceNode.getOutSideResource(), null); + Expression getState = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(resourceNode.getPrimaryResourcePath(), null); getterAccessor.getBody().addStatement("return " + getState.toImplementation(new String[] {null}) + ";"); mainComponent.addMethod(getterAccessor); } @@ -1056,11 +1055,11 @@ return params; } - private static String getInitializer(ResourcePath res) { + private static String getInitializer(ResourceHierarchy res) { Type stateType = res.getResourceStateType(); String initializer = null; - if (res.getResourceHierarchy().getInitialValue() != null) { - initializer = res.getResourceHierarchy().getInitialValue().toImplementation(new String[] {""}); + if (res.getInitialValue() != null) { + initializer = res.getInitialValue().toImplementation(new String[] {""}); } else if (stateType != null) { if (DataConstraintModel.typeList.isAncestorOf(stateType)) { initializer = "new " + res.getResourceStateType().getImplementationTypeName() + "()"; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index f4e9710..aef4145 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -77,7 +77,7 @@ // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().equals(src.getOutSideResource()) && cm.isOutside()) { + if (src.getOutSideResources().contains(cm.getResource()) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } @@ -262,7 +262,7 @@ // src side (for a chain of update method invocations) ChannelMember in = null; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().equals(src.getOutSideResource())) { + if (src.getOutSideResources().contains(cm.getResource())) { in = cm; break; } @@ -419,7 +419,7 @@ DataFlowEdge dIn = (DataFlowEdge) resToCh2; ChannelMember in = null; for (ChannelMember cm: ch2.getInputChannelMembers()) { - if (cm.getResource().equals(((ResourceNode) dIn.getSource()).getOutSideResource())) { + if (((ResourceNode) dIn.getSource()).getOutSideResources().contains(cm.getResource())) { in = cm; break; } @@ -465,7 +465,7 @@ ResourceNode dependingNode = null; PushPullAttribute pushPull2 = null; for (Edge resToCh2: resToCh.getDestination().getInEdges()) { - if (((ResourceNode) resToCh2.getSource()).getOutSideResource().equals(dependingRes)) { + if (((ResourceNode) resToCh2.getSource()).getOutSideResources().contains(dependingRes)) { dependingNode = (ResourceNode) resToCh2.getSource(); pushPull2 = (PushPullAttribute) resToCh.getAttribute(); } @@ -766,13 +766,11 @@ } } Expression resExp = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(out.getResource(), null); - String args = ""; - String delimiter = ""; + List args = new ArrayList<>(); if (resExp instanceof Term) { // to access the parent if (((Term) resExp).getChildren().size() > 1 && ((Term) resExp).getChild(1) instanceof Variable) { - args += delimiter + ((Variable)((Term) resExp).getChild(1)).getName(); - delimiter = ", "; + args.add(((Variable)((Term) resExp).getChild(1)).getName()); } resExp = ((Term) resExp).getChild(0); } @@ -781,8 +779,9 @@ for (Selector selector: ch.getAllSelectors()) { if (selector.getExpression() instanceof Variable) { Variable selVar = (Variable) selector.getExpression(); - args += delimiter + selVar.getName(); - delimiter = ", "; + if (!args.contains(selVar.getName())) { + args.add(selVar.getName()); + } } } // Values of message parameters. @@ -797,14 +796,23 @@ } } if (refVarName != null) { - args += delimiter + refVarName; + if (!args.contains(refVarName)) { + args.add(refVarName); + } } else { - args += delimiter + varEnt.getValue().getName(); + if (!args.contains(varEnt.getValue().getName())) { + args.add(varEnt.getValue().getName()); + } } - delimiter = ", "; } } - inputAccessor.addStatement(resourceAccess + "." + input.getName() + "(" + args + ");"); + String argsStr = ""; + String delimiter = ""; + for (String arg: args) { + argsStr += delimiter + arg; + delimiter = ", "; + } + inputAccessor.addStatement(resourceAccess + "." + input.getName() + "(" + argsStr + ");"); } } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index 0063336..14c631a 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -174,13 +174,13 @@ // Declare the field to store the state in the type of each resource. if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { - ResourcePath res = resourceNode.getOutSideResource(); - Set children = resourceNode.getResourceHierarchy().getChildren(); + ResourceHierarchy res = resourceNode.getResourceHierarchy(); + Set children = res.getChildren(); if (children == null || children.size() == 0) { // leaf resource. - Type fieldType = getImplStateType(res.getResourceHierarchy()); + Type fieldType = getImplStateType(res); component.addField(new FieldDeclaration(fieldType, "value", getInitializer(res))); - Map nameToParam = constructorParams.get(resourceNode.getResourceHierarchy()); + Map nameToParam = constructorParams.get(res); if (nameToParam == null) { nameToParam = new HashMap<>(); constructorParams.put(resourceNode.getResourceHierarchy(), nameToParam); @@ -193,7 +193,7 @@ ResourceHierarchy child = children.iterator().next(); if (children.size() == 1 && child.getNumParameters() > 0) { // map or list. - component.addField(new FieldDeclaration(getImplStateType(res.getResourceHierarchy()), "value", getInitializer(res))); + component.addField(new FieldDeclaration(getImplStateType(res), "value", getInitializer(res))); } else { // class for (ResourceHierarchy c: children) { @@ -228,7 +228,7 @@ children.add(child.getResourceHierarchy()); List pathParams = new ArrayList<>(); int v = 1; - for (Expression pathParam: child.getOutSideResource().getPathParams()) { + for (Expression pathParam: child.getPrimaryResourcePath().getPathParams()) { if (pathParam instanceof Variable) { Variable var = (Variable) pathParam; pathParams.add(new VariableDeclaration(var.getType(), var.getName())); @@ -280,7 +280,7 @@ DataFlowEdge re = (DataFlowEdge) resToCh; DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); for (Edge chToRes: re.getDestination().getOutEdges()) { - ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); + ResourceHierarchy dstRes = ((ResourceNode) chToRes.getDestination()).getResourceHierarchy(); // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = false; for (ChannelMember cm: ch.getOutputChannelMembers()) { @@ -291,10 +291,10 @@ } if (outsideOutputResource) { // Declare a field in the parent component to refer to the destination resource of push transfer. - if (!generatesComponent(dstRes.getResourceHierarchy())) { + if (!generatesComponent(dstRes)) { dstRes = dstRes.getParent(); } - String dstResName = getComponentName(dstRes.getResourceHierarchy()); + String dstResName = getComponentName(dstRes); // if (resourceNode.getOutSideResource().getCommonPrefix(dstRes) == null && differentTreesAsDifferentServices) { // Inter-service if (!bDeclareClientField) { @@ -317,8 +317,8 @@ for (Edge chToRes : resourceNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; - ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); + ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(ch); // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { @@ -354,7 +354,7 @@ } } // Declare the state field in the parent component. - ResourceHierarchy res = resourceNode.getOutSideResource().getResourceHierarchy(); + ResourceHierarchy res = resourceNode.getResourceHierarchy(); if (((StoreAttribute) resourceNode.getAttribute()).isStored() && noPullTransfer && res.getNumParameters() == 0) { String resName = getComponentName(res); FieldDeclaration stateField = new FieldDeclaration(res.getResourceStateType(), toVariableName(resName)); @@ -413,7 +413,7 @@ // For a non-root resource MethodDeclaration getterAccessor = null; List mainGetterParams = new ArrayList<>(); - String resourcePath = getGetterResourcePathAndPathParams(resourceNode.getOutSideResource(), mainGetterParams); + String resourcePath = getGetterResourcePathAndPathParams(resourceNode.getPrimaryResourcePath(), mainGetterParams); if (resourcePath.indexOf('/') > 0) { resourcePath = resourcePath.substring(resourcePath.indexOf('/')); } else { @@ -429,7 +429,8 @@ getImplStateType(resourceNode.getResourceHierarchy())); } getterAccessor.setBody(new Block()); - Expression getState = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(resourceNode.getOutSideResource(), resourceNode.getOutSideResource().getRoot()); + ResourcePath resPath = resourceNode.getPrimaryResourcePath(); + Expression getState = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(resPath, resPath.getRoot()); getterAccessor.getBody().addStatement("return " + getState.toImplementation(new String[] {null}) + ";"); getterAccessor.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); @@ -447,7 +448,7 @@ // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().equals(resourceNode.getOutSideResource()) && cm.isOutside()) { + if (cm.getResource().equals(resourceNode.getOutSideResource(ch)) && cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. break; } @@ -462,7 +463,7 @@ dstRes = dstRes.getParent(); } String dstResName = getComponentName(dstRes.getResourceHierarchy()); - if (outsideOutputResource || (resourceNode.getOutSideResource().getCommonPrefix(dstRes) == null && differentTreesAsDifferentServices)) { + if (outsideOutputResource || (resourceNode.getOutSideResource(ch).getCommonPrefix(dstRes) == null && differentTreesAsDifferentServices)) { // Inter-service if (!bDeclareClientField) { // Declare a client field to connect to the destination resource of push transfer. @@ -498,8 +499,8 @@ for (Edge chToRes : resourceNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { DataFlowEdge re = (DataFlowEdge) resToCh; - ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); + ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(ch); // Check if the input resource is outside of the channel scope. boolean outsideInputResource = false; for (ChannelMember cm: ch.getInputChannelMembers()) { @@ -527,7 +528,7 @@ } if ((((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { // For pull transfer. - if (outsideInputResource || (resourceNode.getOutSideResource().getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices)) { + if (outsideInputResource || (resourceNode.getInSideResource(ch).getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices)) { // Inter-service if (!bDeclareClientField) { // Declare a client field to connect to the source resource of pull transfer. @@ -561,7 +562,7 @@ // For push transfer. boolean hasRestAPI = false; boolean isRestAPI = false; - if (outsideOutputResource || (resourceNode.getOutSideResource().getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices)) { + if (outsideOutputResource || (resourceNode.getInSideResource(ch).getCommonPrefix(srcRes) == null && differentTreesAsDifferentServices)) { // Inter-service hasRestAPI = true; if (resourceNode.getParent() == null) { @@ -585,7 +586,7 @@ if (isRestAPI) param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); params.add(param); // The state of the source resource to carry the data-flow. for (ResourcePath refRes: ch.getReferenceResources()) { - if (!refRes.equals(resourceNode.getOutSideResource())) { + if (!refRes.equals(resourceNode.getInSideResource(ch))) { param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getResourceName()); if (isRestAPI) param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); params.add(param); @@ -632,7 +633,7 @@ if (inDegree > 1 || (inDegree == 1 && ch.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { // Declare a field to cache the state of the source resource in the type of the destination resource. - ResourcePath cacheRes = ((ResourceNode) re.getSource()).getOutSideResource(); + ResourceHierarchy cacheRes = ((ResourceNode) re.getSource()).getResourceHierarchy(); FieldDeclaration cacheField = new FieldDeclaration(cacheRes.getResourceStateType(), srcName, getInitializer(cacheRes)); if (component != null) { // A component is created for this resource. @@ -678,7 +679,7 @@ param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); params.add(param); // The state of the source resource to carry the data-flow. for (ResourcePath refRes: ch.getReferenceResources()) { - if (!refRes.equals(resourceNode.getOutSideResource())) { + if (!refRes.equals(resourceNode.getInSideResource(ch))) { param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getResourceName()); param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); params.add(param); @@ -1132,16 +1133,16 @@ return resPath.getResourceHierarchy().toResourcePath(params); } - private static String getInitializer(ResourcePath resId) { - Type stateType = resId.getResourceStateType(); + private static String getInitializer(ResourceHierarchy res) { + Type stateType = res.getResourceStateType(); String initializer = null; - if (resId.getResourceHierarchy().getInitialValue() != null) { - initializer = resId.getResourceHierarchy().getInitialValue().toImplementation(new String[] {""}); + if (res.getInitialValue() != null) { + initializer = res.getInitialValue().toImplementation(new String[] {""}); } else { if (DataConstraintModel.typeList.isAncestorOf(stateType)) { - initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + initializer = "new " + res.getResourceStateType().getImplementationTypeName() + "()"; } else if (DataConstraintModel.typeMap.isAncestorOf(stateType)) { - initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + initializer = "new " + res.getResourceStateType().getImplementationTypeName() + "()"; } } return initializer; diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 35e6717..7bde0c7 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -83,7 +83,7 @@ boolean outsideInputResource = false; ChannelMember in = null; for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.getResource().equals(src.getOutSideResource())) { + if (src.getOutSideResources().contains(cm.getResource())) { in = cm; if (cm.isOutside()) { outsideInputResource = true; // Regarded as pull transfer. @@ -117,7 +117,7 @@ DataFlowEdge dIn = (DataFlowEdge) resToCh2; ChannelMember in2 = null; for (ChannelMember cm: ch2.getInputChannelMembers()) { - if (cm.getResource().equals(((ResourceNode) dIn.getSource()).getOutSideResource())) { + if (((ResourceNode) dIn.getSource()).getOutSideResources().contains(cm.getResource())) { in2 = cm; break; } @@ -666,7 +666,7 @@ ChannelMember cm = pathEnt.getKey(); ResourcePath src2 = pathEnt.getValue().getKey(); // get outside src resource state by pull data transfer. - if (cm.isOutside() || src2.getCommonPrefix(dst.getOutSideResource()) == null) { + if (cm.isOutside() || src2.getCommonPrefix(dst.getInSideResource(ch)) == null) { Type srcResourceType = src2.getResourceStateType(); List pathParams = new ArrayList<>(); for (Expression pathExp: src2.getPathParams()) { @@ -677,7 +677,7 @@ } } // get src resource state by pull data transfer. - if (src.getNumberOfParameters() == 0 && src.getOutSideResource().getCommonPrefix(dst.getOutSideResource()) == null) { + if (src.getNumberOfParameters() == 0 && src.getOutSideResource(ch).getCommonPrefix(dst.getInSideResource(ch)) == null) { Type srcResourceType = src.getResourceStateType(); List pathParams = new ArrayList<>(); generatePullDataTransfer(getter, src.getResourceName(), src.getResourceHierarchy().toResourcePath(pathParams), srcResourceType); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java index 53ea105..a86dc97 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java @@ -26,11 +26,25 @@ } public ResourceNode addResourceNode(ResourceNode parent, - DataTransferChannel outSideChannel, - ResourcePath outSideResource) { - ResourceNode node = resourceNodeMap.get(System.identityHashCode(outSideResource)); + ResourcePath outSideResource, + DataTransferChannel outSideChannel) { + ResourceNode node = null; + if (outSideResource.getNumberOfParameters() == 0) { + // a global (possibly non-root) resource node + Collection nodes = getResourceNodes(outSideResource.getResourceHierarchy()); + if (nodes.size() > 0) { + node = nodes.iterator().next(); + if (outSideChannel != null) { + // not a terminal node + node.addOutSideResource(outSideChannel, outSideResource); + } + } + } else { + // a channel local resource node + node = resourceNodeMap.get(System.identityHashCode(outSideResource)); + } if (node != null) return node; - node = new ResourceNode(parent, outSideChannel, outSideResource); + node = new ResourceNode(parent, outSideResource, outSideChannel); addNode(node); if (parent == null) { rootResourceNodes.add(node); @@ -41,11 +55,44 @@ return node; } + public ResourceNode addTerminalResourceNode(ResourceNode parent, + DataTransferChannel inSideChannel, + ResourcePath inSideResource) { + ResourceNode node = null; + if (inSideResource.getNumberOfParameters() == 0) { + // a global (possibly non-root) terminal resource node + Collection nodes = getResourceNodes(inSideResource.getResourceHierarchy()); + if (nodes.size() > 0) { + node = nodes.iterator().next(); + } + } else { + // a channel local terminal resource node + node = resourceNodeMap.get(System.identityHashCode(inSideResource)); + } + if (node != null) return node; + node = new ResourceNode(parent, inSideResource, inSideChannel, true); + addNode(node); + if (parent == null) { + rootResourceNodes.add(node); + } else { + parent.addChild(node); + } + resourceNodeMap.put(System.identityHashCode(inSideResource), node); + return node; + } + public ResourceNode addResourceNode(ResourceNode parent, Map inSide, - Map.Entry outSide) { - ResourceNode node = resourceNodeMap.get(System.identityHashCode(outSide.getValue())); - if (node != null) return node; + Map outSide) { + ResourceNode node = null; + for (ResourcePath outRes: outSide.values()) { + node = resourceNodeMap.get(System.identityHashCode(outRes)); + if (node != null) return node; + } + for (ResourcePath inRes: inSide.values()) { + node = resourceNodeMap.get(System.identityHashCode(inRes)); + if (node != null) return node; + } node = new ResourceNode(parent, inSide, outSide); addNode(node); if (parent == null) { @@ -53,7 +100,12 @@ } else { parent.addChild(node); } - resourceNodeMap.put(System.identityHashCode(outSide.getValue()), node); + for (ResourcePath outRes: outSide.values()) { + resourceNodeMap.put(System.identityHashCode(outRes), node); + } + for (ResourcePath inRes: inSide.values()) { + resourceNodeMap.put(System.identityHashCode(inRes), node); + } return node; } @@ -71,8 +123,8 @@ return node; } - public ResourceNode getResourceNode(ResourcePath outSide) { - return resourceNodeMap.get(System.identityHashCode(outSide)); + public ResourceNode getResourceNode(ResourcePath resPath) { + return resourceNodeMap.get(System.identityHashCode(resPath)); } public ChannelNode getChannelNode(DataTransferChannel channel) { @@ -80,7 +132,8 @@ } public Collection getResourceNodes() { - return resourceNodeMap.values(); + HashSet result = new HashSet<>(resourceNodeMap.values()); + return result; } public Collection getResourceNodes(ResourceHierarchy resourceHierarchy) { diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java index 3bf7c9e..e851d06 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java @@ -13,131 +13,141 @@ public class DataTransferModel extends DataConstraintModel { public DataFlowGraph getDataFlowGraph() { DataFlowGraph dataFlowGraph = new DataFlowGraph(); - Map>> resourceMap = new HashMap<>(); + Map>> channelLocalResMap = new HashMap<>(); for (Channel channel: getChannels()) { - addResourceToChannelEdges(dataFlowGraph, channel, null, resourceMap); + addResourceToChannelEdges(dataFlowGraph, channel, null, channelLocalResMap); } for (Channel channel: getChannels()) { - addChannelToResourceEdges(dataFlowGraph, channel, null, resourceMap); + addChannelToResourceEdges(dataFlowGraph, channel, null, channelLocalResMap); } for (Channel channel: getIOChannels()) { - addChannelToResourceEdges(dataFlowGraph, channel, null, resourceMap); + addChannelToResourceEdges(dataFlowGraph, channel, null, channelLocalResMap); } return dataFlowGraph; } private void addResourceToChannelEdges(DataFlowGraph dataFlowGraph, Channel dstChannel, ChannelNode parentChannelNode, - Map>> resourceMap) { + Map>> channelLocalResMap) { DataTransferChannel dstDfChannel = (DataTransferChannel) dstChannel; ChannelNode dstChannelNode = dataFlowGraph.addChannelNode(parentChannelNode, dstDfChannel); for (ResourcePath srcRes: dstDfChannel.getInputResources()) { - Map> chToNodes = resourceMap.get(srcRes.getResourceHierarchy()); + Map> chLocalResNodes = channelLocalResMap.get(srcRes.getResourceHierarchy()); if (srcRes.getNumberOfParameters() == 0) { - if (chToNodes == null || chToNodes.get(null) == null) { - // ResourcePath without parameter corresponds to a global ResourceNode. - ResourceNode srcResNode = addResourceNodes(dataFlowGraph, srcRes, null, resourceMap); - dataFlowGraph.addEdge(srcResNode, dstChannelNode); - } + // ResourcePath without parameter corresponds to a global ResourceNode. + ResourceNode srcResNode = addResourceNodes(dataFlowGraph, srcRes, dstDfChannel, channelLocalResMap, false); + dataFlowGraph.addEdge(srcResNode, dstChannelNode); } else { - if (chToNodes == null || chToNodes.get(dstChannel) == null) { + if (chLocalResNodes == null || chLocalResNodes.get(dstChannel) == null) { // There is no channel-local ResourcePath. - ResourceNode srcResNode = addResourceNodes(dataFlowGraph, srcRes, dstDfChannel, resourceMap); + // 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 nodes = chToNodes.get(dstChannel); // channel-local ResourceNodes. + Set nodes = chLocalResNodes.get(dstChannel); // channel-local ResourceNodes. boolean bExists = false; for (ResourceNode node: nodes) { - if (node.getOutSideResource().toString().equals(srcRes.toString())) { - bExists = true; + 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) { - ResourceNode srcResNode = addResourceNodes(dataFlowGraph, srcRes, dstDfChannel, resourceMap); + // 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, resourceMap); + addResourceToChannelEdges(dataFlowGraph, childChannel, dstChannelNode, channelLocalResMap); } } private void addChannelToResourceEdges(DataFlowGraph dataFlowGraph, Channel srcChannel, ChannelNode parentChannelNode, - Map>> resourceMap) { + Map>> channelLocalResMap) { DataTransferChannel srcDfChannel = (DataTransferChannel) srcChannel; ChannelNode srcChannelNode = dataFlowGraph.addChannelNode(parentChannelNode, srcDfChannel); for (ResourcePath dstRes: srcDfChannel.getOutputResources()) { - Map> chToNodes = resourceMap.get(dstRes.getResourceHierarchy()); // ResourceNodes that have the same ResourceHierarchy. + Map> chLocalResNodes = channelLocalResMap.get(dstRes.getResourceHierarchy()); // ResourceNodes that have the same ResourceHierarchy. Set dstResSet = new HashSet<>(); if (dstRes.getNumberOfParameters() == 0) { // ResourcePath without parameter corresponds to a global ResourceNode. - if (chToNodes == null) { - // Create a new global ResourceNode. - ResourceNode dstResNode = addResourceNodes(dataFlowGraph, dstRes, null, resourceMap); + if (chLocalResNodes == null) { + // Create a new global terminal ResourceNode. + ResourceNode dstResNode = addResourceNodes(dataFlowGraph, dstRes, srcDfChannel, channelLocalResMap, true); dstResSet.add(dstResNode); } else { - // Select global ResourceNodes. - dstResSet.addAll(chToNodes.get(null)); + // Select all (usually one) global ResourceNodes. + for (Set resSet: chLocalResNodes.values()) { + dstResSet.addAll(resSet); + } } } else { - if (chToNodes == null) { + if (chLocalResNodes == null) { // There is no corresponding ResourceNode. - // Create new ResourceNode. - ResourceNode dstResNode = addResourceNodes(dataFlowGraph, dstRes, srcDfChannel, resourceMap); + // Create a new channel-local terminal ResourceNode. + ResourceNode dstResNode = addResourceNodes(dataFlowGraph, dstRes, srcDfChannel, channelLocalResMap, true); dstResSet.add(dstResNode); } else { - // There already has been a ResourceNode. - if (chToNodes.get(srcDfChannel) != null && chToNodes.get(srcDfChannel).size() > 0) { - // There already has been a channel-local ResourceNode. - for (ResourceNode localResNode: chToNodes.get(srcDfChannel)) { - 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); + if (chLocalResNodes.get(srcDfChannel) == null) { + // Select all non-terminal ResourceNodes. + for (Set 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 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) { - if (resourceMap.get(dstParent.getResourceHierarchy()) != null && resourceMap.get(dstParent.getResourceHierarchy()).get(srcDfChannel) != null) { - for (ResourceNode localParentNode: resourceMap.get(dstParent.getResourceHierarchy()).get(srcDfChannel)) { - if (localParentNode.getOutSideResource().toString().equals(dstParent.toString())) { - // There already has been a common channel-local ancestor. - ResourceNode dstResNode = addResourceNodes(dataFlowGraph, dstRes, srcDfChannel, resourceMap); - dstResSet.add(dstResNode); - break; - } - 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, srcDfChannel, resourceMap); - dstResSet.add(dstResNode); - break; + // Search a common channel-local ancestor. + if (dstResSet.size() == 0) { + ResourcePath dstParent = dstRes.getParent(); + while (dstParent != null && dstParent.getNumberOfParameters() > 0) { + Map> 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; } - if (dstResSet.size() > 0) break; + dstParent = dstParent.getParent(); } - dstParent = dstParent.getParent(); } - } - if (dstResSet.size() == 0) { - for (Set nodes: chToNodes.values()) { - // Select all corresponding ResourceNodes. - dstResSet.addAll(nodes); + if (dstResSet.size() == 0) { + for (Set 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, resourceMap); - dstResSet.add(dstResNode); + if (dstResSet.size() == 0) { + // Otherwise create a new ResourceNode. + ResourceNode dstResNode = addResourceNodes(dataFlowGraph, dstRes, srcDfChannel, channelLocalResMap, false); + dstResSet.add(dstResNode); + } } } } @@ -147,33 +157,37 @@ } } for (Channel childChannel: srcDfChannel.getChildren()) { - addChannelToResourceEdges(dataFlowGraph, childChannel, srcChannelNode, resourceMap); + addChannelToResourceEdges(dataFlowGraph, childChannel, srcChannelNode, channelLocalResMap); } } private ResourceNode addResourceNodes(DataFlowGraph dataFlowGraph, ResourcePath resPath, DataTransferChannel dfChannel, - Map>> resourceMap) { + Map>> channelLocalResMap, boolean isTerminal) { ResourceNode resNode = null; - if (resPath.getNumberOfParameters() == 0) { - dfChannel = null; - } if (resPath.getParent() == null) { - resNode = dataFlowGraph.addResourceNode(null, dfChannel, resPath); + 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.getParent().getNumberOfParameters() == 0) { + if (resPath.getResourceHierarchy().getParent().getNumParameters() == 0) { parentDfChannel = null; } - if (resourceMap.get(resPath.getResourceHierarchy().getParent()) != null) { - Set nodes = resourceMap.get(resPath.getResourceHierarchy().getParent()).get(parentDfChannel); - if (nodes != null) { - for (ResourceNode node: nodes) { - if (node.getOutSideResource().toString().equals(resPath.getParent().toString())) { - parent = node; - break; + if (channelLocalResMap.get(resPath.getResourceHierarchy().getParent()) != null) { + Set 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; @@ -185,21 +199,25 @@ } } if (parent == null) { - parent = addResourceNodes(dataFlowGraph, resPath.getParent(), parentDfChannel, resourceMap); + parent = addResourceNodes(dataFlowGraph, resPath.getParent(), parentDfChannel, channelLocalResMap, false); } - resNode = dataFlowGraph.addResourceNode(parent, dfChannel, resPath); + if (!isTerminal) { + resNode = dataFlowGraph.addResourceNode(parent, resPath, dfChannel); + } else { + resNode = dataFlowGraph.addTerminalResourceNode(parent, dfChannel, resPath); + } } - Map> chToNodes = resourceMap.get(resPath.getResourceHierarchy()); - if (chToNodes == null) { - chToNodes = new HashMap<>(); - resourceMap.put(resPath.getResourceHierarchy(), chToNodes); + Map> chToLocalNodes = channelLocalResMap.get(resPath.getResourceHierarchy()); + if (chToLocalNodes == null) { + chToLocalNodes = new HashMap<>(); + channelLocalResMap.put(resPath.getResourceHierarchy(), chToLocalNodes); } - Set nodes = chToNodes.get(dfChannel); - if (nodes == null) { - nodes = new HashSet<>(); - chToNodes.put(dfChannel, nodes); + Set chLocalNodes = chToLocalNodes.get(dfChannel); + if (chLocalNodes == null) { + chLocalNodes = new HashSet<>(); + chToLocalNodes.put(dfChannel, chLocalNodes); } - nodes.add(resNode); + chLocalNodes.add(resNode); return resNode; } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java index 438a8c1..6c2073c 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java @@ -22,16 +22,17 @@ protected Set children = null; protected ResourceHierarchy resourceHierarchy = null; protected Map inSide = null; - protected Map.Entry outSide = null; + protected Map outSide = null; protected List selectors = null; public ResourceNode(ResourceNode parent, - DataTransferChannel outSideChannel, - ResourcePath outSideResource) { + ResourcePath outSideResource, + DataTransferChannel outSideChannel) { this.parent = parent; this.children = new HashSet<>(); this.inSide = new HashMap<>(); - this.outSide = new AbstractMap.SimpleEntry<>(outSideChannel, outSideResource); + this.outSide = new HashMap<>(); + this.outSide.put(outSideChannel, outSideResource); this.resourceHierarchy = outSideResource.getResourceHierarchy(); this.selectors = new ArrayList<>(); if (resourceHierarchy.getNumParameters() > 0) { @@ -43,24 +44,52 @@ } } } + + public ResourceNode(ResourceNode parent, + ResourcePath resource, + DataTransferChannel channel, boolean isInside) { + this.parent = parent; + this.children = new HashSet<>(); + this.inSide = new HashMap<>(); + this.outSide = new HashMap<>(); + if (isInside) { + this.inSide.put(channel, resource); + } else { + this.outSide.put(channel, resource); + } + this.resourceHierarchy = resource.getResourceHierarchy(); + this.selectors = new ArrayList<>(); + if (resourceHierarchy.getNumParameters() > 0) { + if (channel != null) { + selectors.addAll(channel.getSelectors()); + } else { + List pathParams = resource.getPathParams(); + selectors.add(new Selector(pathParams.get(pathParams.size() - 1))); + } + } + } public ResourceNode(ResourceNode parent, - Map inSide, - Map.Entry outSide) { + Map outSide, + Map inSide) { this.parent = parent; this.children = new HashSet<>(); this.inSide = inSide; this.outSide = outSide; - this.resourceHierarchy = outSide.getValue().getResourceHierarchy(); this.selectors = new ArrayList<>(); - DataTransferChannel outSideChannel = outSide.getKey(); - ResourcePath outSideResource = outSide.getValue(); - if (resourceHierarchy.getNumParameters() > 0) { - if (outSideChannel != null) { - selectors.addAll(outSideChannel.getSelectors()); - } else { - List pathParams = outSideResource.getPathParams(); - selectors.add(new Selector(pathParams.get(pathParams.size() - 1))); + for (Map.Entry outsideEnt: outSide.entrySet()) { + DataTransferChannel outSideChannel = outsideEnt.getKey(); + ResourcePath outSideResource = outsideEnt.getValue(); + if (this.resourceHierarchy == null) { + this.resourceHierarchy = outSideResource.getResourceHierarchy(); + } + if (resourceHierarchy.getNumParameters() > 0) { + if (outSideChannel != null) { + selectors.addAll(outSideChannel.getSelectors()); + } else { + List pathParams = outSideResource.getPathParams(); + selectors.add(new Selector(pathParams.get(pathParams.size() - 1))); + } } } } @@ -93,6 +122,11 @@ children.add(child); child.parent = this; } + + public ResourcePath getPrimaryResourcePath() { + if (outSide.size() > 0) return outSide.values().iterator().next(); + return inSide.values().iterator().next(); + } public Collection getInSideResources() { return inSide.values(); @@ -102,20 +136,24 @@ return inSide.get(channel); } - public ResourcePath getOutSideResource() { - return outSide.getValue(); + public Collection getOutSideResources() { + return outSide.values(); } - public DataTransferChannel getOutSideChannel() { - return outSide.getKey(); + public ResourcePath getOutSideResource(DataTransferChannel channel) { + return outSide.get(channel); + } + + public Set getOutSideChannel() { + return outSide.keySet(); } public void addInSideResource(DataTransferChannel channel, ResourcePath inResource) { inSide.put(channel, inResource); } - public void setOutSideResource(DataTransferChannel channel, ResourcePath outResource) { - outSide = new AbstractMap.SimpleEntry<>(channel, outResource); + public void addOutSideResource(DataTransferChannel channel, ResourcePath outResource) { + outSide.put(channel, outResource); } public List getSelectors() {