diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java index 31e7fa2..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); @@ -76,32 +80,102 @@ // For each resource. for (ResourceNode rn: resources) { boolean f = false; - String resourceName = rn.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase() - + rn.getIdentifierTemplate().getResourceName().substring(1); + String resourceName = getTypeName(rn.getIdentifierTemplate().getResourceName()); TypeDeclaration type = new TypeDeclaration(resourceName); // 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(); - String resName = dstRes.getResourceName().substring(0, 1).toUpperCase() + dstRes.getResourceName().substring(1); + String resName = dstRes.getResourceName(); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // for push data transfer depends.add(dstRes); - fieldInitializer += resName.toLowerCase() + ","; + 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().substring(0, 1).toUpperCase() + srcRes.getResourceName().substring(1); + 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.toLowerCase() + ","; + 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(); @@ -118,22 +192,61 @@ if (!refs.contains(id) && !depends.contains(id)) { refs.add(id); String refResName = id.getResourceName(); - fieldInitializer += refResName.toLowerCase() + ","; + fieldInitializer += refResName + ","; f = true; } } } } + 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); - Block manConstructorBody = mainConstructor.getBody(); - if (manConstructorBody == null) { - manConstructorBody = new Block(); - mainConstructor.setBody(manConstructorBody); + 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. + } - manConstructorBody.addStatement(rn.getIdentifierTemplate().getResourceName() + " = " + fieldInitializer + ";"); // Declare a constructor, fields and update methods in the type of each resource. MethodDeclaration constructor = new MethodDeclaration(resourceName, true); @@ -142,25 +255,25 @@ for (Edge e : rn.getOutEdges()) { ResourceDependency re = (ResourceDependency) e; IdentifierTemplate dstRes = ((ResourceNode) re.getDestination()).getIdentifierTemplate(); - String dstResName = dstRes.getResourceName().substring(0, 1).toUpperCase() + dstRes.getResourceName().substring(1); + String dstResName = getTypeName(dstRes.getResourceName()); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { // Declare a field to refer to the destination resource of push transfer. depends.add(dstRes); type.addField(new FieldDeclaration(new Type(dstResName, dstResName), dstRes.getResourceName())); constructor.addParameter(new VariableDeclaration(new Type(dstResName, dstResName), dstRes.getResourceName())); - block.addStatement("this." + dstResName.toLowerCase() + " = " + dstResName.toLowerCase() + ";"); + block.addStatement("this." + dstRes.getResourceName() + " = " + dstRes.getResourceName() + ";"); } } for (Edge e : rn.getInEdges()) { ResourceDependency re = (ResourceDependency) e; IdentifierTemplate srcRes = ((ResourceNode) re.getSource()).getIdentifierTemplate(); - String srcResName = srcRes.getResourceName().substring(0, 1).toUpperCase() + srcRes.getResourceName().substring(1); + String srcResName = getTypeName(srcRes.getResourceName()); if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { // Declare a field to refer to the source resource of pull transfer. depends.add(srcRes); type.addField(new FieldDeclaration(new Type(srcResName, srcResName), srcRes.getResourceName())); constructor.addParameter(new VariableDeclaration(new Type(srcResName, srcResName), srcRes.getResourceName())); - block.addStatement("this." + srcResName.toLowerCase() + " = " + srcResName.toLowerCase() + ";"); + block.addStatement("this." + srcRes.getResourceName() + " = " + srcRes.getResourceName() + ";"); } else { // Declare an update method in the type of the destination resource. ArrayList vars = new ArrayList<>(); @@ -183,7 +296,7 @@ if (!refs.contains(id) && !depends.contains(id)) { refs.add(id); String refResName = id.getResourceName(); - refResName = refResName.substring(0, 1).toUpperCase() + refResName.substring(1); + refResName = getTypeName(refResName); type.addField(new FieldDeclaration(new Type(refResName, refResName), id.getResourceName())); constructor.addParameter(new VariableDeclaration(new Type(refResName, refResName), id.getResourceName())); block.addStatement("this." + id.getResourceName() + " = " + id.getResourceName() + ";"); @@ -324,6 +437,10 @@ return codes; } + public static String getTypeName(String resourceName) { + return resourceName.substring(0, 1).toUpperCase() + resourceName.substring(1); + } + private static String getInitializer(IdentifierTemplate resId) { Type stateType = resId.getResourceStateType(); String initializer = null;