diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index f5aeb56..72f2358 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -132,8 +132,11 @@ CodeGenerator.langSpec = langSpec; ArrayList codes = new ArrayList<>(); + // Get the dependency among root nodes. + Map> dependedRootComponentGraph = getDependedRootComponentGraph(model); + // Sort the all components. - ArrayList components = determineComponentOrder(flowGraph); + ArrayList components = determineComponentOrder(flowGraph, dependedRootComponentGraph); // Add the main component. if (mainTypeName == null) { @@ -145,46 +148,89 @@ codes.add(mainCU); // Generate the other components. - generateCodeFromFlowGraph(model, flowGraph, components, mainComponent, mainConstructor, codes, langSpec); + generateCodeFromFlowGraph(model, flowGraph, components, dependedRootComponentGraph, mainComponent, mainConstructor, codes, langSpec); return codes; } - public abstract void generateCodeFromFlowGraph(DataTransferModel model, DataFlowGraph flowGraph, ArrayList components, + public abstract void generateCodeFromFlowGraph(DataTransferModel model, DataFlowGraph flowGraph, ArrayList components, Map> dependedRootComponentGraph, TypeDeclaration mainComponent, MethodDeclaration mainConstructor, ArrayList codes, ILanguageSpecific langSpec); - private static ArrayList determineComponentOrder(DataFlowGraph graph) { + private static Map> getDependedRootComponentGraph(DataTransferModel model) { + Map> dependedComponentGraph = new HashMap<>(); + for (Channel ch: model.getChannels()) { + DataTransferChannel dtCh = (DataTransferChannel) ch; + Set inRes = new HashSet<>(); + Set outRes = new HashSet<>(); + for (ChannelMember cm: dtCh.getChannelMembers()) { + if (cm.isOutside()) { + outRes.add(cm.getResource().getResourceHierarchy()); + } else { + inRes.add(cm.getResource().getResourceHierarchy()); + } + } + if (outRes.size() > 0 && inRes.size() > 0) { + for (ResourceHierarchy out: outRes) { + for (ResourceHierarchy in: inRes) { + Set dependings = dependedComponentGraph.get(out.getRoot()); + if (dependings == null) { + dependings = new HashSet<>(); + dependedComponentGraph.put(out.getRoot(), dependings); + } + dependings.add(in.getRoot()); + } + } + } + } + return dependedComponentGraph; + } + + private static ArrayList determineComponentOrder(DataFlowGraph graph, Map> dependedRootComponentGraph) { ArrayList objects = new ArrayList<>(); Set visited = new HashSet<>(); Collection allNodes = graph.getResourceNodes(); for (ResourceNode resNode: allNodes) { - topologicalSort(allNodes, resNode, visited, objects); + topologicalSort(resNode, allNodes, dependedRootComponentGraph, visited, objects); } return objects; } - private static void topologicalSort(Collection allNodes, ResourceNode curResNode, Set visited, List orderedList) { + private static void topologicalSort(ResourceNode curResNode, Collection allNodes, Map> dependedRootComponentGraph, Set visited, List orderedList) { if (visited.contains(curResNode)) return; visited.add(curResNode); - // a caller is before the callee + // A caller is before the callee + + // For each incoming PUSH transfer. for (Edge chToRes: curResNode.getInEdges()) { for (Edge resToCh: chToRes.getSource().getInEdges()) { if (!(resToCh instanceof DataFlowEdge) || ((PushPullAttribute)((DataFlowEdge) resToCh).getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - topologicalSort(allNodes, (ResourceNode) resToCh.getSource(), visited, orderedList); + topologicalSort((ResourceNode) resToCh.getSource(), allNodes, dependedRootComponentGraph, visited, orderedList); } } } + // For each outgoing PULL transfer. if (curResNode instanceof ResourceNode) { for (Edge resToCh: curResNode.getOutEdges()) { DataFlowEdge de = (DataFlowEdge) resToCh; if (((PushPullAttribute) de.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { for (Edge chToRes : resToCh.getDestination().getOutEdges()) { - topologicalSort(allNodes, (ResourceNode) chToRes.getDestination(), visited, orderedList); + topologicalSort((ResourceNode) chToRes.getDestination(), allNodes, dependedRootComponentGraph, visited, orderedList); } } } } - // For reference resources. + // For each depending root node. + if (curResNode instanceof ResourceNode && dependedRootComponentGraph.get(curResNode.getResourceHierarchy()) != null) { + for (ResourceHierarchy dependingRes: dependedRootComponentGraph.get(curResNode.getResourceHierarchy())) { + for (ResourceNode rootNode: allNodes) { + ResourceHierarchy rootRes = rootNode.getResourceHierarchy(); + if (rootRes.getParent() == null && rootRes.equals(dependingRes)) { + topologicalSort(rootNode, allNodes, dependedRootComponentGraph, visited, orderedList); + } + } + } + } + // For each reference resource. ResourceNode cn = null; if (curResNode instanceof ResourceNode) { cn = (ResourceNode) curResNode; @@ -200,7 +246,7 @@ ChannelNode chNode = (ChannelNode) resToCh.getDestination(); for (ChannelMember m: chNode.getChannel().getReferenceChannelMembers()) { if (m.getResource().equals(curResNode.getOutSideResource())) { - topologicalSort(allNodes, resNode, visited, orderedList); + topologicalSort(resNode, allNodes, dependedRootComponentGraph, visited, orderedList); } } } @@ -211,7 +257,7 @@ } protected void updateMainComponent(DataTransferModel model, TypeDeclaration mainType, MethodDeclaration mainConstructor, Node componentNode, - final List depends, ILanguageSpecific langSpec) { + final List depends, ILanguageSpecific langSpec) { // Declare the field to refer to each object in the main type. ResourceNode resNode = null; String nodeName = null; @@ -227,7 +273,7 @@ } // Add a statement to instantiate each object to the main constructor. List parameters = new ArrayList<>(); - for (ResourcePath res: depends) { + for (ResourceHierarchy res: depends) { // For the callee objects (the destination resource of push transfer or the source resource of pull transfer). parameters.add(res.getResourceName()); } @@ -237,10 +283,10 @@ for (Channel cg : model.getChannels()) { DataTransferChannel ch = (DataTransferChannel) cg; if (ch.getInputResources().contains(resNode.getOutSideResource())) { - for (ResourcePath id: ch.getReferenceResources()) { - if (!refs.contains(id) && !depends.contains(id)) { - refs.add(id); - String refResName = id.getResourceName(); + for (ResourcePath resPath: ch.getReferenceResources()) { + if (!refs.contains(resPath) && !depends.contains(resPath.getResourceHierarchy())) { + refs.add(resPath); + String refResName = resPath.getResourceName(); parameters.add(refResName); } } @@ -256,11 +302,11 @@ mainConstructorBody.addStatement(langSpec.getFieldAccessor(nodeName) + langSpec.getAssignment() + langSpec.getConstructorInvocation(componentName, parameters) + langSpec.getStatementDelimiter()); } - protected ResourcePath addReference(TypeDeclaration component, MethodDeclaration constructor, ResourcePath dstRes, ILanguageSpecific langSpec) { - if (!generatesComponent(dstRes.getResourceHierarchy())) { + protected ResourceHierarchy addReference(TypeDeclaration component, MethodDeclaration constructor, ResourceHierarchy dstRes, ILanguageSpecific langSpec) { + if (!generatesComponent(dstRes)) { dstRes = dstRes.getParent(); } - String dstComponentName = getComponentName(dstRes.getResourceHierarchy(), langSpec); + String dstComponentName = getComponentName(dstRes, langSpec); if (dstComponentName != null) { String dstNodeName = langSpec.toVariableName(dstComponentName); if (langSpec.declareField()) { @@ -392,13 +438,13 @@ } protected void declareFieldsToReferenceResources(DataTransferModel model, ResourceNode resourceNode, TypeDeclaration component, MethodDeclaration constructor, - final List depends, ILanguageSpecific langSpec) { + final List depends, ILanguageSpecific langSpec) { Set refs = new HashSet<>(); for (Channel ch : model.getChannels()) { DataTransferChannel c = (DataTransferChannel) ch; if (c.getInputResources().contains(resourceNode.getOutSideResource())) { for (ResourcePath res: c.getReferenceResources()) { - if (!refs.contains(res) && !depends.contains(res)) { + if (!refs.contains(res) && !depends.contains(res.getResourceHierarchy())) { refs.add(res); String refResName = langSpec.toComponentName(res.getResourceName()); component.addField(langSpec.newFieldDeclaration(new Type(refResName, refResName), res.getResourceName()));