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(); diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeOptions.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeOptions.java new file mode 100644 index 0000000..13d65d5 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeOptions.java @@ -0,0 +1,22 @@ +package algorithms; + +public class JavaCodeOptions { + private String mainTypeName = null; + private boolean bChannelAsAClass = false; + + public String getMainTypeName() { + return mainTypeName; + } + + public void setMainTypeName(String mainTypeName) { + this.mainTypeName = mainTypeName; + } + + public boolean isChannelAsAClass() { + return bChannelAsAClass; + } + + public void setChannelAsAClass(boolean bChannelAsAClass) { + this.bChannelAsAClass = bChannelAsAClass; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java index fa03235..6ef0cd5 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java @@ -37,7 +37,7 @@ import models.dataFlowModel.StoreAttribute; public class JavaMethodBodyGenerator { - public static ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model, ArrayList codes) { + public static ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model, ArrayList codes, JavaCodeOptions options) { // Create a map from type names (lower case) to their types. Map typeMap = new HashMap<>(); for (CompilationUnit code: codes) { diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java index fbdfb7b..1d9eaff 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java @@ -59,7 +59,7 @@ JerseyCodeGenerator.mainTypeName = defaultMainTypeName; } - static public ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model) { + static public ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model, JerseyCodeOptions options) { ArrayList codes = new ArrayList<>(); // ArrayList resources = StoreResourceCheck(graph); Set resources = graph.getNodes(); diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeOptions.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeOptions.java new file mode 100644 index 0000000..fc58a0a --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeOptions.java @@ -0,0 +1,13 @@ +package algorithms; + +public class JerseyCodeOptions { + private String baseURI = null; + + public String getBaseURI() { + return baseURI; + } + + public void setBaseURI(String baseURI) { + this.baseURI = baseURI; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyMethodBodyGenerator.java index 4004486..834786a 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyMethodBodyGenerator.java @@ -41,7 +41,7 @@ public class JerseyMethodBodyGenerator { private static String baseURL = "http://localhost:8080"; - public static ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model, ArrayList codes) { + public static ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model, ArrayList codes, JerseyCodeOptions options) { // Create a map from type names (lower case) to their types. Map typeMap = new HashMap<>(); for (CompilationUnit code: codes) { diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JavaPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JavaPrototypeGenerateAction.java index 78a39ac..d512b09 100644 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JavaPrototypeGenerateAction.java +++ b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JavaPrototypeGenerateAction.java @@ -52,7 +52,9 @@ } else { JavaCodeGenerator.resetMainTypeName(); // use the default main type's name. } - editor.setCodes(JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model))); + JavaCodeOptions options = new JavaCodeOptions(); + options.setChannelAsAClass(true); + editor.setCodes(JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model, options), options)); ModelExtension.recoverModel(model); for (CompilationUnit file : editor.getCodes()) { System.out.println(file); diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JerseyPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JerseyPrototypeGenerateAction.java index 0236d5d..16c5642 100644 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JerseyPrototypeGenerateAction.java +++ b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JerseyPrototypeGenerateAction.java @@ -53,7 +53,8 @@ } else { JerseyCodeGenerator.resetMainTypeName(); // use the default main type's name. } - editor.setCodes(JerseyMethodBodyGenerator.doGenerate(graph, model, JerseyCodeGenerator.doGenerate(graph, model))); + JerseyCodeOptions options = new JerseyCodeOptions(); + editor.setCodes(JerseyMethodBodyGenerator.doGenerate(graph, model, JerseyCodeGenerator.doGenerate(graph, model, options), options)); ModelExtension.recoverModel(model); for (CompilationUnit file : editor.getCodes()) { System.out.println(file); diff --git a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index c41a255..211bbd7 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -85,11 +85,11 @@ public static DataflowChannelGenerator parseChannel(TokenStream stream, DataFlowModel model) throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment { if (!stream.hasNext()) return null; - String channelOtInitKeyword = stream.next(); - if (!channelOtInitKeyword.equals(CHANNEL)) { - if (!channelOtInitKeyword.equals(INIT)) throw new ExpectedChannel(stream.getLine()); + String channelOrInitKeyword = stream.next(); + if (!channelOrInitKeyword.equals(CHANNEL)) { + if (!channelOrInitKeyword.equals(INIT)) throw new ExpectedChannel(stream.getLine()); parseInit(stream, model); - channelOtInitKeyword = stream.next(); + channelOrInitKeyword = stream.next(); } if (!stream.hasNext()) throw new ExpectedChannelName(stream.getLine()); String channelName = stream.next(); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java b/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java index bd733d1..3e52b48 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java @@ -23,7 +23,7 @@ ResourceDependencyGraph graph = NecessityOfStoringResourceStates.doDecide(model); SelectableDataTransfers.init(graph); FinalDecisionOfStoringResourceStates.doDecide(graph); - ArrayList codetree = JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model)); + ArrayList codetree = JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model, new JavaCodeOptions()), new JavaCodeOptions()); System.out.println(codetree); } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression