diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java index e37166e..1667970 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java @@ -2,8 +2,10 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; @@ -60,9 +62,11 @@ JavaCodeGenerator.mainTypeName = defaultMainTypeName; } - static public ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model) { + static public ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model, JavaCodeOptions options) { ArrayList codes = new ArrayList<>(); ArrayList resources = determineResourceOrder(graph); + Map channelTypeMap = new HashMap<>(); +// Map channelPullCount = new HashMap<>(); // to create a channel class just after the TypeDeclaration mainType = new TypeDeclaration(mainTypeName); CompilationUnit mainCU = new CompilationUnit(mainType); @@ -82,6 +86,8 @@ // Declare the field to refer to each resource in the main type. String fieldInitializer = "new " + resourceName + "("; Set depends = new HashSet<>(); + Map channelToInitializer = new HashMap<>(); +// DataflowChannelGenerator channelFieldToGenerate = null; for (Edge e : rn.getOutEdges()) { ResourceDependency re = (ResourceDependency) e; IdentifierTemplate dstRes = ((ResourceNode) re.getDestination()).getIdentifierTemplate(); @@ -89,20 +95,87 @@ if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { // for push data transfer depends.add(dstRes); - fieldInitializer += resName + ","; + if (!options.isChannelAsAClass()) { + fieldInitializer += resName + ","; + } else { + fieldInitializer += re.getChannelGenerator().getChannelName() + ","; + } f = true; +// } else if (options.isChannelAsAClass()) { +// // Generate a class for the destination channel +// DataflowChannelGenerator dstCh = re.getChannelGenerator(); +// String chTypeName = getTypeName(dstCh.getChannelName()); +// if (channelTypeMap.get(chTypeName) == null) { +// TypeDeclaration chType = new TypeDeclaration(chTypeName); +// channelTypeMap.put(chTypeName, chType); +// CompilationUnit cu = new CompilationUnit(chType); +// cu.addImport(new ImportDeclaration("java.util.*")); +// codes.add(cu); +// int pullCount = 0; +// for (Edge inE: re.getDestination().getInEdges()) { +// if (((PushPullAttribute) inE.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { +// pullCount++; +// } +// } +// channelPullCount.put(chType, pullCount - 1); // except for this edge +// if (pullCount - 1 == 0) channelFieldToGenerate = dstCh; +// } else { +// TypeDeclaration chType = channelTypeMap.get(chTypeName); +// int pullCount = channelPullCount.get(chType) - 1; +// channelPullCount.put(chType, pullCount); +// if (pullCount == 0) channelFieldToGenerate = dstCh; +// } } } for (Edge e : rn.getInEdges()) { ResourceDependency re = (ResourceDependency) e; IdentifierTemplate srcRes = ((ResourceNode) re.getSource()).getIdentifierTemplate(); String resName = srcRes.getResourceName(); + DataflowChannelGenerator srcCh = re.getChannelGenerator(); + if (options.isChannelAsAClass() && channelTypeMap.get(srcCh.getChannelName()) == null) { + if (channelToInitializer.get(srcCh) == null) { + channelToInitializer.put(srcCh, null); + } + } if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { // for pull data transfer depends.add(srcRes); - fieldInitializer += resName + ","; + if (!options.isChannelAsAClass()) { + fieldInitializer += resName + ","; + } else { + fieldInitializer += srcCh.getChannelName() + ","; + if (channelTypeMap.get(srcCh.getChannelName()) == null) { + String channelFieldInitializer = channelToInitializer.get(srcCh); + if (channelFieldInitializer == null) { + String chTypeName = getTypeName(srcCh.getChannelName()); + channelFieldInitializer = "new " + chTypeName + "("; + } + channelFieldInitializer += resName + ","; + channelToInitializer.put(srcCh, channelFieldInitializer); + } + } f = true; } else { +// if (options.isChannelAsAClass()) { +// // Generate a class for the source channel +// DataflowChannelGenerator srcCh = re.getChannelGenerator(); +// String chTypeName = getTypeName(srcCh.getChannelName()); +// if (channelTypeMap.get(chTypeName) == null) { +// TypeDeclaration chType = new TypeDeclaration(chTypeName); +// channelTypeMap.put(chTypeName, chType); +// CompilationUnit cu = new CompilationUnit(chType); +// cu.addImport(new ImportDeclaration("java.util.*")); +// codes.add(cu); +// int pullCount = 0; +// for (Edge inE: rn.getInEdges()) { +// if (((PushPullAttribute) inE.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { +// pullCount++; +// } +// } +// channelPullCount.put(chType, pullCount); // always zero? +// if (pullCount == 0) channelFieldToGenerate = srcCh; +// } +// } if (rn.getIndegree() > 1) { // Declare a field to cash the state of the source resource in the type of the destination resource. IdentifierTemplate cashResId = ((ResourceNode) re.getSource()).getIdentifierTemplate(); @@ -125,18 +198,56 @@ } } } - // declare and initialize the filed to refer to a resource. - if (f) fieldInitializer = fieldInitializer.substring(0, fieldInitializer.length() - 1); - fieldInitializer += ")"; - FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), rn.getIdentifierTemplate().getResourceName()); - mainType.addField(field); + boolean pullContained = false; + if (options.isChannelAsAClass()) { + // Generate a class for each source channel + for (DataflowChannelGenerator srcCh: channelToInitializer.keySet()) { + String chTypeName = getTypeName(srcCh.getChannelName()); + if (channelTypeMap.get(chTypeName) == null) { + TypeDeclaration chType = new TypeDeclaration(chTypeName); + channelTypeMap.put(chTypeName, chType); + CompilationUnit cu = new CompilationUnit(chType); + cu.addImport(new ImportDeclaration("java.util.*")); + codes.add(cu); + } + if (channelToInitializer.get(srcCh) != null) { + pullContained = true; + } + } + } Block mainConstructorBody = mainConstructor.getBody(); if (mainConstructorBody == null) { mainConstructorBody = new Block(); mainConstructor.setBody(mainConstructorBody); } + + if (options.isChannelAsAClass() && pullContained) { + // declare and initialize the field to refer to a channel BEFORE declaring the field to refer the destination resource because at least one pull transfer is contained. + for (DataflowChannelGenerator srcCh: channelToInitializer.keySet()) { + if (channelToInitializer.get(srcCh) != null) { + // declare and initialize the filed to refer to a channel. + String channelTypeName = getTypeName(srcCh.getChannelName()); + FieldDeclaration channelField = new FieldDeclaration(new Type(channelTypeName, channelTypeName), srcCh.getChannelName()); + mainType.addField(channelField); + String channelFieldInitializer = channelToInitializer.get(srcCh); + channelFieldInitializer = channelFieldInitializer.substring(0, fieldInitializer.length() - 1) + ")"; + mainConstructorBody.addStatement(srcCh.getChannelName() + " = " + channelFieldInitializer + ";"); + } + } + } + + // declare and initialize the filed to refer to a resource. + if (f) fieldInitializer = fieldInitializer.substring(0, fieldInitializer.length() - 1); + fieldInitializer += ")"; + FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), rn.getIdentifierTemplate().getResourceName()); + mainType.addField(field); mainConstructorBody.addStatement(rn.getIdentifierTemplate().getResourceName() + " = " + fieldInitializer + ";"); + if (options.isChannelAsAClass() && !pullContained) { + // declare and initialize the field to refer to a channel AFTER declaring the field to refer the destination resource because no pull transfer is contained. + + } + // Declare a constructor, fields and update methods in the type of each resource. MethodDeclaration constructor = new MethodDeclaration(resourceName, true); Block block = new Block();