diff --git a/AlgebraicDataflowArchitectureModel/.classpath b/AlgebraicDataflowArchitectureModel/.classpath index 5d3b090..3e99697 100644 --- a/AlgebraicDataflowArchitectureModel/.classpath +++ b/AlgebraicDataflowArchitectureModel/.classpath @@ -1,6 +1,6 @@ - + diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java b/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java new file mode 100644 index 0000000..07afdf1 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java @@ -0,0 +1,106 @@ +package algorithms; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; + +import models.*; +import models.algebra.*; +import models.dataConstraintModel.*; +import models.dataFlowModel.*; + +/** + * Algorithms to analyze data transfer model. + * + * @author Nitta + * + */ +public class DataTransferModelAnalyzer { + /** + * Create data flow graph annotated with node attributes that indicate whether each resource state needs to be stored. + * @param model a data transfer model + * @return annotated data flow graph + */ + static public DataFlowGraph createDataFlowGraphWithStateStoringAttribute(DataTransferModel model) { + DataFlowGraph graph = model.getDataFlowGraph(); + Collection channels = new HashSet<>(model.getIOChannelGenerators()); + channels.addAll(model.getChannelGenerators()); + for (ChannelGenerator generator: channels) { + for (ChannelMember member: ((DataTransferChannelGenerator) generator).getOutputChannelMembers()) { + boolean flag = !member.getStateTransition().isRightUnary(); // The state does not need to be stored if the state transition function is right unary. + for (Node node : graph.getNodes()) { + if (((ResourceNode) node).getIdentifierTemplate().equals(member.getIdentifierTemplate())) { + setStoreAttribute(flag, (ResourceNode) node); + } + } + } + } + for (Node node : graph.getNodes()) { + HashSet inChannels = new HashSet<>(); + for(Edge pre : ((ResourceNode) node).getInEdges()) { + inChannels.add(((DataFlowEdge) pre).getChannelGenerator()); + } + if ((inChannels.size() > 1)) { + setStoreAttribute(true, (ResourceNode) node); + } else if (((ResourceNode) node).getAttribute() == null) { + setStoreAttribute(false, (ResourceNode) node); + } + } + return graph; + } + + static private void setStoreAttribute(boolean flag, ResourceNode node) { + NodeAttribute attr = node.getAttribute(); + StoreAttribute store; + if (attr != null && attr instanceof NodeAttribute) { + store = (StoreAttribute) attr; + store.setNeeded(store.isNeeded() || flag); + } else { + store = new StoreAttribute(); + store.setNeeded(flag); + node.setAttribute(store); + } + } + + /** + * Annotate data flow graph with edge attributes that indicate selectable data transfer methods. + * @param graph a data flow graph + * @return annotated data flow graph + */ + static public DataFlowGraph annotateWithSelectableDataTransferAttiribute(DataFlowGraph graph) { + List nodes = new ArrayList<>(graph.getNodes()); + // set push only attributes + for (Node n: graph.getNodes()) { + if (nodes.contains(n) && ((StoreAttribute) ((ResourceNode) n).getAttribute()).isNeeded()) { + nodes.remove(n); + trackEdges(n, nodes); + } + } + // set push/pull attributes to the remaining edges + for (Edge e : graph.getEdges()) { + if (((DataFlowEdge) e).getAttribute() == null) { + PushPullAttribute ppat = new PushPullAttribute(); + ppat.addOption(PushPullValue.PUSHorPULL); + ppat.addOption(PushPullValue.PUSH); + ppat.addOption(PushPullValue.PULL); + ((DataFlowEdge) e).setAttribute(ppat); + } + } + return graph; + } + + static private void trackEdges(Node n, List nodes) { + // recursively set push only attributes to input side edges + for (Edge e : ((ResourceNode) n).getInEdges()) { + PushPullAttribute ppat = new PushPullAttribute(); + ppat.addOption(PushPullValue.PUSH); + ((DataFlowEdge) e).setAttribute(ppat); + Node n2 = e.getSource(); + if (nodes.contains(n2)) { + nodes.remove(n2); + trackEdges(n2, nodes); + } + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/FinalDecisionOfStoringResourceStates.java b/AlgebraicDataflowArchitectureModel/src/algorithms/FinalDecisionOfStoringResourceStates.java deleted file mode 100644 index b466fd7..0000000 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/FinalDecisionOfStoringResourceStates.java +++ /dev/null @@ -1,36 +0,0 @@ -package algorithms; - -import java.util.HashSet; - -import models.*; -import models.algebra.*; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataFlowModel.*; - -public class FinalDecisionOfStoringResourceStates { - static private HashSet reachableNodes = new HashSet<>(); - - static public void doDecide(ResourceDependencyGraph graph) { - reachableNodes.clear(); - for (Node n : graph.getNodes()) { - ResourceNode resource = (ResourceNode) n; - trackNode(resource); - } - } - - static private void trackNode(ResourceNode resource) { - if (reachableNodes.contains(resource)) - return; - reachableNodes.add(resource); - boolean flag = true; - for (Edge e : resource.getInEdges()) { - if (((PushPullAttribute) e.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { - // Traverse pull edges only. - trackNode((ResourceNode) e.getSource()); - flag = false; - } - } - ((StoreAttribute) resource.getAttribute()).setStored(flag); - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java deleted file mode 100644 index 31e7fa2..0000000 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaCodeGenerator.java +++ /dev/null @@ -1,475 +0,0 @@ -package algorithms; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - - -import code.ast.Block; -import code.ast.CompilationUnit; -import code.ast.FieldDeclaration; -import code.ast.ImportDeclaration; -import code.ast.MethodDeclaration; -import code.ast.TypeDeclaration; -import code.ast.VariableDeclaration; -import models.Edge; -import models.Node; -import models.algebra.Expression; -import models.algebra.Field; -import models.algebra.Parameter; -import models.algebra.Symbol; -import models.algebra.Term; -import models.algebra.Type; -import models.algebra.Variable; -import models.dataConstraintModel.ChannelGenerator; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; -import models.dataFlowModel.DataFlowModel; -import models.dataFlowModel.DataflowChannelGenerator; -import models.dataFlowModel.DataflowChannelGenerator.IResourceStateAccessor; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.PushPullValue; -import models.dataFlowModel.ResourceDependency; -import models.dataFlowModel.ResourceDependencyGraph; -import models.dataFlowModel.ResourceNode; -import models.dataFlowModel.StoreAttribute; - -/** - * Generator for plain Java prototypes - * - * @author Nitta - * - */ -public class JavaCodeGenerator { - public static final Type typeVoid = new Type("Void", "void"); - private static String defaultMainTypeName = "Main"; - static String mainTypeName = defaultMainTypeName; - - public static String getMainTypeName() { - return mainTypeName; - } - - public static void setMainTypeName(String mainTypeName) { - JavaCodeGenerator.mainTypeName = mainTypeName; - } - - public static void resetMainTypeName() { - JavaCodeGenerator.mainTypeName = defaultMainTypeName; - } - - static public ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model) { - ArrayList codes = new ArrayList<>(); - ArrayList resources = determineResourceOrder(graph); - - TypeDeclaration mainType = new TypeDeclaration(mainTypeName); - CompilationUnit mainCU = new CompilationUnit(mainType); - mainCU.addImport(new ImportDeclaration("java.util.*")); - codes.add(mainCU); - - // Declare the constructor of the main type. - MethodDeclaration mainConstructor = new MethodDeclaration(mainTypeName, true); - mainType.addMethod(mainConstructor); - - // For each resource. - for (ResourceNode rn: resources) { - boolean f = false; - String resourceName = rn.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase() - + rn.getIdentifierTemplate().getResourceName().substring(1); - 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<>(); - 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); - if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - depends.add(dstRes); - fieldInitializer += resName.toLowerCase() + ","; - f = true; - } - } - 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); - if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { - depends.add(srcRes); - fieldInitializer += resName.toLowerCase() + ","; - f = true; - } else { - 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(); - type.addField(new FieldDeclaration( - cashResId.getResourceStateType(), ((ResourceNode) re.getSource()).getIdentifierTemplate().getResourceName(), getInitializer(cashResId))); - } - } - } - Set refs = new HashSet<>(); - for (ChannelGenerator cg : model.getChannelGenerators()) { - DataflowChannelGenerator c = (DataflowChannelGenerator) cg; - if (c.getInputIdentifierTemplates().contains(rn.getIdentifierTemplate())) { - for (IdentifierTemplate id: c.getReferenceIdentifierTemplates()) { - if (!refs.contains(id) && !depends.contains(id)) { - refs.add(id); - String refResName = id.getResourceName(); - fieldInitializer += refResName.toLowerCase() + ","; - f = true; - } - } - } - } - 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); - } - 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); - Block block = new Block(); - depends = new HashSet<>(); - 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); - 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() + ";"); - } - } - 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); - 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() + ";"); - } else { - // Declare an update method in the type of the destination resource. - ArrayList vars = new ArrayList<>(); - vars.add(new VariableDeclaration(srcRes.getResourceStateType(), srcRes.getResourceName())); - DataflowChannelGenerator c = (DataflowChannelGenerator) re.getChannelGenerator(); - for (IdentifierTemplate ref: c.getReferenceIdentifierTemplates()) { - if (ref != rn.getIdentifierTemplate()) { - vars.add(new VariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); - } - } - type.addMethod(new MethodDeclaration("update" + srcResName, false, typeVoid, vars)); - } - } - // Declare a field to refer to the reference resource. - refs = new HashSet<>(); - for (ChannelGenerator cg : model.getChannelGenerators()) { - DataflowChannelGenerator c = (DataflowChannelGenerator) cg; - if (c.getInputIdentifierTemplates().contains(rn.getIdentifierTemplate())) { - for (IdentifierTemplate id: c.getReferenceIdentifierTemplates()) { - if (!refs.contains(id) && !depends.contains(id)) { - refs.add(id); - String refResName = id.getResourceName(); - refResName = refResName.substring(0, 1).toUpperCase() + refResName.substring(1); - 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() + ";"); - } - } - } - } - constructor.setBody(block); - if (constructor.getParameters() != null) - type.addMethod(constructor); - - // Declare input methods in resources and the main type. - for (ChannelGenerator cg : model.getIOChannelGenerators()) { - for (ChannelMember cm : ((DataflowChannelGenerator) cg).getOutputChannelMembers()) { - if (cm.getIdentifierTemplate().equals(rn.getIdentifierTemplate())) { - Expression message = cm.getStateTransition().getMessageExpression(); - if (message.getClass() == Term.class) { - ArrayList params = new ArrayList<>(); - for (Variable var: message.getVariables().values()) { - params.add(new VariableDeclaration(var.getType(), var.getName())); - } - MethodDeclaration input = new MethodDeclaration( - ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), - false, typeVoid, params); - type.addMethod(input); - String str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); - input = getMethod(mainType, str); - if (input == null) { - input = new MethodDeclaration(str, false, typeVoid, params); - mainType.addMethod(input); - } else { - // Add type to a parameter without type. - for (VariableDeclaration param: input.getParameters()) { - if (param.getType() == null) { - for (VariableDeclaration p: params) { - if (param.getName().equals(p.getName()) && p.getType() != null) { - param.setType(p.getType()); - } - } - } - } - } - } else if (message.getClass() == Variable.class) { - MethodDeclaration input = new MethodDeclaration( - ((Variable) cm.getStateTransition().getMessageExpression()).getName(), - false, typeVoid, null); - type.addMethod(input); - String str = ((Variable) cm.getStateTransition().getMessageExpression()).getName(); - input = getMethod(mainType, str); - if (input == null) { - input = new MethodDeclaration(str, false, typeVoid, null); - mainType.addMethod(input); - } - } - } - } - } - - // Declare the field to store the state in the type of each resource. - if (((StoreAttribute) rn.getAttribute()).isStored()) { - IdentifierTemplate resId = rn.getIdentifierTemplate(); - type.addField(new FieldDeclaration(resId.getResourceStateType(), "value", getInitializer(resId))); - } - - // Declare the getter method to obtain the state in the type of each resource. - type.addMethod(new MethodDeclaration("getValue", - rn.getIdentifierTemplate().getResourceStateType())); - - // Add compilation unit for each resource. - CompilationUnit cu = new CompilationUnit(type); - cu.addImport(new ImportDeclaration("java.util.*")); - codes.add(cu); - } - - // Declare the Pair class. - boolean isCreatedPair = false; - for(ResourceNode rn : resources) { - if(isCreatedPair) continue; - if(model.getType("Pair").isAncestorOf(rn.getIdentifierTemplate().getResourceStateType())) { - TypeDeclaration type = new TypeDeclaration("Pair"); - type.addField(new FieldDeclaration(new Type("Double", "T"), "left")); - type.addField(new FieldDeclaration(new Type("Double", "T"), "right")); - - MethodDeclaration constructor = new MethodDeclaration("Pair", true); - constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "left")); - constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "right")); - Block block = new Block(); - block.addStatement("this.left = left;"); - block.addStatement("this.right = right;"); - constructor.setBody(block); - type.addMethod(constructor); - - for(FieldDeclaration field : type.getFields()) { - MethodDeclaration getter = new MethodDeclaration( - "get" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1), - new Type("Double","T")); - getter.setBody(new Block()); - getter.getBody().addStatement("return " + field.getName() + ";"); - type.addMethod(getter); - } - - CompilationUnit cu = new CompilationUnit(type); - cu.addImport(new ImportDeclaration("java.util.*")); - codes.add(cu); - - isCreatedPair = true; - } - } - - // Declare getter methods in the main type. - for (Node n : graph.getNodes()) { - ResourceNode rn = (ResourceNode) n; - MethodDeclaration getter = new MethodDeclaration( - "get" + rn.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase() - + rn.getIdentifierTemplate().getResourceName().substring(1), - rn.getIdentifierTemplate().getResourceStateType()); - getter.setBody(new Block()); - getter.getBody().addStatement( - "return " + rn.getIdentifierTemplate().getResourceName() + ".getValue();"); - mainType.addMethod(getter); - } - - - HashSet tmps = new HashSet<>(); - HashSet cont = new HashSet<>(); - for (MethodDeclaration method : mainType.getMethods()) { - if (!tmps.contains(method.getName())) - tmps.add(method.getName()); - else - cont.add(method.getName()); - } - for (MethodDeclaration method : mainType.getMethods()) { - if (cont.contains(method.getName())) { - method.setName(method.getName() + method.getParameters().get(0).getName().substring(0, 1).toUpperCase() - + method.getParameters().get(0).getName().substring(1)); - } - } - return codes; - } - - private static String getInitializer(IdentifierTemplate resId) { - Type stateType = resId.getResourceStateType(); - String initializer = null; - if (resId.getInitialValue() != null) { - initializer = resId.getInitialValue().toImplementation(new String[] {""}); - } else { - if (DataConstraintModel.typeList.isAncestorOf(stateType)) { - initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; - } else if (DataConstraintModel.typeMap.isAncestorOf(stateType)) { - initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; - } - } - return initializer; - } - - static public ArrayList getCodes(ArrayList codeTree) { - ArrayList codes = new ArrayList<>(); - for (TypeDeclaration type : codeTree) { - codes.add("public class " + type.getTypeName() + "{"); - for (FieldDeclaration field : type.getFields()) { - if (type.getTypeName() != mainTypeName) { - String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " - + field.getName(); - if (DataConstraintModel.isListType(field.getType())) - cons += " = new ArrayList<>()"; - cons += ";"; - codes.add(cons); - } else { - String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " - + field.getName() + " = new " + field.getType().getTypeName() + "("; - cons += ");"; - codes.add(cons); - } - } - codes.add(""); - for (MethodDeclaration method : type.getMethods()) { - String varstr = "\t" + "public " + method.getReturnType().getInterfaceTypeName() + " " - + method.getName() + "("; - if (method.getParameters() != null) { - for (VariableDeclaration var : method.getParameters()) { - varstr += var.getType().getInterfaceTypeName() + " " + var.getName() + ","; - } - if (!method.getParameters().isEmpty()) - varstr = varstr.substring(0, varstr.length() - 1); - } - if (method.getBody() != null) { - for (String str : method.getBody().getStatements()) { - codes.add("\t\t" + str + ";"); - } - } - codes.add(varstr + ")" + "{"); - codes.add("\t" + "}"); - codes.add(""); - } - codes.add("}"); - codes.add(""); - } - return codes; - } - - static private ArrayList determineResourceOrder(ResourceDependencyGraph graph) { - ArrayList resources = new ArrayList<>(); - Set visited = new HashSet<>(); - for (Node n : graph.getNodes()) { - ResourceNode rn = (ResourceNode) n; - topologicalSort(graph, rn, visited, resources); - } - return resources; - } - - static private void topologicalSort(ResourceDependencyGraph graph, ResourceNode curNode, Set visited, List orderedList) { - if (visited.contains(curNode)) return; - visited.add(curNode); - for (Edge e : curNode.getInEdges()) { - ResourceDependency re = (ResourceDependency) e; - if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - topologicalSort(graph, (ResourceNode) re.getSource(), visited, orderedList); - } - } - for (Edge e : curNode.getOutEdges()) { - ResourceDependency re = (ResourceDependency) e; - if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { - topologicalSort(graph, (ResourceNode) re.getDestination(), visited, orderedList); - } - } - for (Node n: graph.getNodes()) { // for reference resources. - ResourceNode rn = (ResourceNode) n; - for (Edge e : rn.getOutEdges()) { - ResourceDependency re = (ResourceDependency) e; - for (ChannelMember m: re.getChannelGenerator().getReferenceChannelMembers()) { - if (m.getIdentifierTemplate() == curNode.getIdentifierTemplate()) { - topologicalSort(graph, rn, visited, orderedList); - } - } - } - } - orderedList.add(0, curNode); - } - - private static MethodDeclaration getMethod(TypeDeclaration type, String methodName) { - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().equals(methodName)) return m; - } - return null; - } - - static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - if (target.equals(from)) { - return new Field("value", - target.getResourceStateType() != null ? target.getResourceStateType() - : DataConstraintModel.typeInt); - } - // for reference channel member - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() - : DataConstraintModel.typeInt); - } - }; - static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - if (target.equals(from)) { - return new Field("value", - target.getResourceStateType() != null ? target.getResourceStateType() - : DataConstraintModel.typeInt); - } - // for reference channel member - Term getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); - return getter; - } - - @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - Term getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); - getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); - return getter; - } - }; -} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java deleted file mode 100644 index fa03235..0000000 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JavaMethodBodyGenerator.java +++ /dev/null @@ -1,350 +0,0 @@ -package algorithms; - -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import code.ast.CompilationUnit; -import code.ast.MethodDeclaration; -import code.ast.TypeDeclaration; -import models.Edge; -import models.Node; -import models.algebra.Expression; -import models.algebra.InvalidMessage; -import models.algebra.ParameterizedIdentifierIsFutureWork; -import models.algebra.Term; -import models.algebra.Type; -import models.algebra.UnificationFailed; -import models.algebra.ValueUndefined; -import models.algebra.Variable; -import models.dataConstraintModel.ChannelGenerator; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; -import models.dataFlowModel.DataFlowModel; -import models.dataFlowModel.DataflowChannelGenerator; -import models.dataFlowModel.DataflowChannelGenerator.IResourceStateAccessor; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.PushPullValue; -import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; -import models.dataFlowModel.ResourceDependency; -import models.dataFlowModel.ResourceDependencyGraph; -import models.dataFlowModel.ResourceNode; -import models.dataFlowModel.StoreAttribute; - -public class JavaMethodBodyGenerator { - public static ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model, ArrayList codes) { - // Create a map from type names (lower case) to their types. - Map typeMap = new HashMap<>(); - for (CompilationUnit code: codes) { - for (TypeDeclaration type: code.types()) { - typeMap.put(type.getTypeName().substring(0,1).toLowerCase() + type.getTypeName().substring(1), type); - } - } - - // Generate the body of each update or getter method. - try { - Map> referredResources = new HashMap<>(); - for (Edge e: graph.getEdges()) { - ResourceDependency d = (ResourceDependency) e; - PushPullAttribute pushPull = (PushPullAttribute) d.getAttribute(); - ResourceNode src = (ResourceNode) d.getSource(); - ResourceNode dst = (ResourceNode) d.getDestination(); - String srcResourceName = src.getIdentifierTemplate().getResourceName(); - String dstResourceName = dst.getIdentifierTemplate().getResourceName(); - TypeDeclaration srcType = typeMap.get(srcResourceName); - TypeDeclaration dstType = typeMap.get(dstResourceName); - for (ChannelMember out: d.getChannelGenerator().getOutputChannelMembers()) { - if (out.getIdentifierTemplate() == dst.getIdentifierTemplate()) { - if (pushPull.getOptions().get(0) == PushPullValue.PUSH && srcType != null) { - // for push data transfer - MethodDeclaration update = getUpdateMethod(dstType, srcType); - if (((StoreAttribute) dst.getAttribute()).isStored()) { - // update stored state of dst side resource (when every incoming edge is in push style) - Expression updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); - String[] sideEffects = new String[] {""}; - String curState = updateExp.toImplementation(sideEffects); - String updateStatement; - if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { - updateStatement = sideEffects[0]; - } else { - updateStatement = sideEffects[0] + "value = " + curState + ";"; - } - if (update.getBody() == null || !update.getBody().getStatements().contains(updateStatement)) { - update.addFirstStatement(updateStatement); - } - } - if (dst.getIndegree() > 1) { - // update a cash of src side resource (when incoming edges are multiple) - String cashStatement = "this." + srcResourceName + " = " + srcResourceName + ";"; - if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { - update.addFirstStatement(cashStatement); - } - } - MethodDeclaration getter = getGetterMethod(dstType); - if (((StoreAttribute) dst.getAttribute()).isStored()) { - // returns the current state stored in a field. - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - Type resourceType = dst.getIdentifierTemplate().getResourceStateType(); - if (model.isPrimitiveType(resourceType)) { - getter.addStatement("return value;"); - } else { - // copy the current state to be returned as a 'value' - String implTypeName = resourceType.getImplementationTypeName(); -// String interfaceTypeName = resourceType.getInterfaceTypeName(); -// String concreteTypeName; -// if (interfaceTypeName.contains("<")) { -// String typeName = implTypeName.substring(0, implTypeName.indexOf("<")); -//// String generics = interfaceTypeName.substring(interfaceTypeName.indexOf("<") + 1, interfaceTypeName.lastIndexOf(">")); -// concreteTypeName = typeName + "<>"; -// } else { -// concreteTypeName = implTypeName; -// } - getter.addStatement("return new " + implTypeName + "(value);"); - } - } - } - // src side (for a chain of update method invocations) - for (MethodDeclaration srcUpdate: getUpdateMethods(srcType)) { - String refParams = ""; - Set referredSet = referredResources.get(srcUpdate); - for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { - // to get the value of reference member. - IdentifierTemplate ref = rc.getIdentifierTemplate(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(srcUpdate, referredSet); - } - if (ref != dst.getIdentifierTemplate()) { - String refVarName = ref.getResourceName(); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getIdentifierTemplate()); - String[] sideEffects = new String[] {""}; - String refExp = refGetter.toImplementation(sideEffects); - String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); - srcUpdate.addFirstStatement(sideEffects[0] + refTypeName + " " + refVarName + " = " + refExp + ";"); - } - refParams += ", " + refVarName; - } - } - srcUpdate.addStatement("this." + dstResourceName + ".update" + srcType.getTypeName() + "(value" + refParams + ");"); - } - for (MethodDeclaration srcInput: getInputMethods(srcType, src, model)) { - String refParams = ""; - Set referredSet = referredResources.get(srcInput); - for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { - // to get the value of reference member. - IdentifierTemplate ref = rc.getIdentifierTemplate(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(srcInput, referredSet); - } - if (ref != dst.getIdentifierTemplate()) { - String refVarName = ref.getResourceName(); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getIdentifierTemplate()); - String[] sideEffects = new String[] {""}; - String refExp = refGetter.toImplementation(sideEffects); - String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); - srcInput.addFirstStatement(sideEffects[0] + refTypeName + " " + refVarName + " = " + refExp + ";"); - } - refParams += ", " + refVarName; - } - } - srcInput.addStatement("this." + dstResourceName + ".update" + srcType.getTypeName() + "(value" + refParams + ");"); - } - } else { - // for pull (or push/pull) data transfer - MethodDeclaration getter = getGetterMethod(dstType); - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - boolean isContainedPush = false; - HashMap inputIdentifierToStateAccessor = new HashMap<>(); - for (Edge eIn: dst.getInEdges()) { - ResourceDependency dIn = (ResourceDependency) eIn; - if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - isContainedPush = true; - inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JavaCodeGenerator.pushAccessor); - } else { - inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JavaCodeGenerator.pullAccessor); - } - } - // for reference channel members - for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { - inputIdentifierToStateAccessor.put(c.getIdentifierTemplate(), JavaCodeGenerator.pullAccessor); // by pull data transfer - } - String[] sideEffects = new String[] {""}; - // generate a return statement. - if (!isContainedPush) { - // All incoming edges are in PULL style. - String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor).toImplementation(sideEffects); - getter.addStatement(sideEffects[0] + "return " + curState + ";"); - } else { - // At least one incoming edge is in PUSH style. - String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor, inputIdentifierToStateAccessor).toImplementation(sideEffects); - getter.addStatement(sideEffects[0] + "return " + curState + ";"); - } - } - } - } - } - } - // for source nodes - String mainTypeName = JavaCodeGenerator.mainTypeName.substring(0,1).toLowerCase() + JavaCodeGenerator.mainTypeName.substring(1); - TypeDeclaration mainType = typeMap.get(mainTypeName); - for (Node n: graph.getNodes()) { - ResourceNode resource = (ResourceNode) n; - String resourceName = resource.getIdentifierTemplate().getResourceName(); - TypeDeclaration type = typeMap.get(resourceName); - if (type != null) { - // getter method - MethodDeclaration getter = getGetterMethod(type); - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - Type resourceType = resource.getIdentifierTemplate().getResourceStateType(); - if (model.isPrimitiveType(resourceType)) { - getter.addStatement("return value;"); - } else { - // copy the current state to be returned as a 'value' - String implTypeName = resourceType.getImplementationTypeName(); -// String interfaceTypeName = resourceType.getInterfaceTypeName(); -// String concreteTypeName; -// if (interfaceTypeName.contains("<")) { -// String typeName = implTypeName.substring(0, implTypeName.indexOf("<")); -// String generics = interfaceTypeName.substring(interfaceTypeName.indexOf("<") + 1, interfaceTypeName.lastIndexOf(">")); -// concreteTypeName = typeName + "<" + generics + ">"; -// } else { -// concreteTypeName = implTypeName; -// } - getter.addStatement("return new " + implTypeName + "(value);"); - } - } - // methods for input events - Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); - for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { - Set outs = entry.getValue(); - for (ChannelMember out: outs) { - MethodDeclaration input = getInputMethod(type, out); - if (input != null) { - String[] sideEffects = new String[] {""}; - Expression updateExp = entry.getKey().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); - String newState = updateExp.toImplementation(sideEffects); - String updateStatement; - if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { - updateStatement = sideEffects[0]; - } else { - updateStatement = sideEffects[0] + "this.value = " + newState + ";"; - } - if (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement)) { - input.addFirstStatement(updateStatement); - } - if (mainType != null) { - MethodDeclaration mainInput = getMethod(mainType, input.getName()); - if (mainInput != null) { - String args = ""; - String delimitar = ""; - if (out.getStateTransition().getMessageExpression() instanceof Term) { - Term message = (Term) out.getStateTransition().getMessageExpression(); - for (Variable var: message.getVariables().values()) { - args += delimitar + var.getName(); - delimitar = ", "; - } - } - mainInput.addStatement("this." + resourceName + "." + input.getName() + "(" + args + ");"); - } - } - } - } - } - } - } - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork - | InvalidMessage | UnificationFailed | ValueUndefined e1) { - e1.printStackTrace(); - } - return codes; - } - - private static MethodDeclaration getUpdateMethod(TypeDeclaration type, TypeDeclaration from) { - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().equals("update" + from.getTypeName())) return m; - } - return null; - } - - private static List getUpdateMethods(TypeDeclaration type) { - List updates = new ArrayList<>(); - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().startsWith("update")) { - updates.add(m); - } - } - return updates; - } - - private static MethodDeclaration getGetterMethod(TypeDeclaration type) { - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().startsWith("get")) return m; - } - return null; - } - - private static Map> getIOChannelsAndMembers(ResourceNode resource, DataFlowModel model) { - Map> ioChannelsAndMembers = new HashMap<>(); - for (ChannelGenerator c: model.getIOChannelGenerators()) { - DataflowChannelGenerator ch = (DataflowChannelGenerator) c; - // I/O channel - for (ChannelMember out: ch.getOutputChannelMembers()) { - if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { - if (out.getStateTransition().getMessageExpression() instanceof Term || out.getStateTransition().getMessageExpression() instanceof Variable) { - Set channelMembers = ioChannelsAndMembers.get(ch); - if (channelMembers == null) { - channelMembers = new HashSet<>(); - ioChannelsAndMembers.put(ch, channelMembers); - } - channelMembers.add(out); - } - } - } - } - return ioChannelsAndMembers; - } - - private static List getInputMethods(TypeDeclaration type, ResourceNode resource, DataFlowModel model) { - List inputs = new ArrayList<>(); - for (ChannelGenerator c: model.getIOChannelGenerators()) { - DataflowChannelGenerator channel = (DataflowChannelGenerator) c; - // I/O channel - for (ChannelMember out: channel.getOutputChannelMembers()) { - if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { - MethodDeclaration input = getInputMethod(type, out); - inputs.add(input); - } - } - } - return inputs; - } - - private static MethodDeclaration getInputMethod(TypeDeclaration type, ChannelMember out) { - MethodDeclaration input = null; - if (out.getStateTransition().getMessageExpression() instanceof Term) { - Term message = (Term) out.getStateTransition().getMessageExpression(); - input = getMethod(type, message.getSymbol().getImplName()); - } else if (out.getStateTransition().getMessageExpression() instanceof Variable) { - Variable message = (Variable) out.getStateTransition().getMessageExpression(); - input = getMethod(type, message.getName()); - } - return input; - } - - private static MethodDeclaration getMethod(TypeDeclaration type, String methodName) { - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().equals(methodName)) return m; - } - return null; - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java deleted file mode 100644 index fbdfb7b..0000000 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyCodeGenerator.java +++ /dev/null @@ -1,356 +0,0 @@ -package algorithms; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; - -import code.ast.Annotation; -import code.ast.Block; -import code.ast.CompilationUnit; -import code.ast.FieldDeclaration; -import code.ast.ImportDeclaration; -import code.ast.MethodDeclaration; -import code.ast.TypeDeclaration; -import code.ast.VariableDeclaration; -import models.Edge; -import models.Node; -import models.algebra.Expression; -import models.algebra.Field; -import models.algebra.Parameter; -import models.algebra.Symbol; -import models.algebra.Term; -import models.algebra.Type; -import models.algebra.Variable; -import models.dataConstraintModel.ChannelGenerator; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; -import models.dataFlowModel.DataFlowModel; -import models.dataFlowModel.DataflowChannelGenerator; -import models.dataFlowModel.DataflowChannelGenerator.IResourceStateAccessor; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.PushPullValue; -import models.dataFlowModel.ResourceDependency; -import models.dataFlowModel.ResourceDependencyGraph; -import models.dataFlowModel.ResourceNode; -import models.dataFlowModel.StoreAttribute; - -/** - * Generator for Jersey prototypes - * - * @author Nitta - * - */ -public class JerseyCodeGenerator { - public static final Type typeVoid = new Type("Void", "void"); - public static final Type typeClient = new Type("Client", "Client"); - private static String defaultMainTypeName = "Main"; - static String mainTypeName = defaultMainTypeName; - - public static String getMainTypeName() { - return mainTypeName; - } - - public static void setMainTypeName(String mainTypeName) { - JerseyCodeGenerator.mainTypeName = mainTypeName; - } - - public static void resetMainTypeName() { - JerseyCodeGenerator.mainTypeName = defaultMainTypeName; - } - - static public ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model) { - ArrayList codes = new ArrayList<>(); -// ArrayList resources = StoreResourceCheck(graph); - Set resources = graph.getNodes(); - - for (Node n : resources) { - ResourceNode rn = (ResourceNode) n; - String resourceName = rn.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase() - + rn.getIdentifierTemplate().getResourceName().substring(1); - - // Declare the field to refer each resource in the main type. - TypeDeclaration type = new TypeDeclaration(resourceName); - type.addAnnotation(new Annotation("Component")); - type.addAnnotation(new Annotation("Path", "\"/" + rn.getIdentifierTemplate().getResourceName() + "\"")); - - // Declare a client field and update methods from other resources. - boolean bDeclareClientField = false; - for (Edge e : rn.getOutEdges()) { - ResourceDependency re = (ResourceDependency) e; - if (!bDeclareClientField && ((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - // Declare a client field to connect to the destination resource of push transfer. - type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); - bDeclareClientField = true; - } - } - 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); - if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { - if (!bDeclareClientField) { - // Declare a client field to connect to the source resource of pull transfer. - type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); - bDeclareClientField = true; - } - } else { - // Declare an update method in the type of the destination resource. - ArrayList vars = new ArrayList<>(); - String srcName = srcRes.getResourceName(); - Type srcType = srcRes.getResourceStateType(); - VariableDeclaration param = new VariableDeclaration(srcType, srcName); - param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); - vars.add(param); - for (IdentifierTemplate refRes: re.getChannelGenerator().getReferenceIdentifierTemplates()) { - if (refRes != rn.getIdentifierTemplate()) { - param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getResourceName()); - param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); - vars.add(param); - } - } - MethodDeclaration update = new MethodDeclaration("update" + srcResName, false, typeVoid, vars); - for (ChannelMember cm: re.getChannelGenerator().getOutputChannelMembers()) { - if (cm.getIdentifierTemplate() == rn.getIdentifierTemplate()) { - if (cm.getStateTransition().isRightUnary()) { - update.addAnnotation(new Annotation("PUT")); - } else { - update.addAnnotation(new Annotation("POST")); - } - } - } - if (rn.getInEdges().size() > 1) { - // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. - update.addAnnotation(new Annotation("Path", "\"/" + srcName + "\"")); - // Declare a field to cash the state of the source resource in the type of the destination resource. - IdentifierTemplate cashResId = ((ResourceNode) re.getSource()).getIdentifierTemplate(); - type.addField(new FieldDeclaration(cashResId.getResourceStateType(), srcName, getInitializer(cashResId))); - } - type.addMethod(update); - } - } - -// // Declare a client field to connect to the source resource of reference transfer. -// if (!bDeclareClientField) { -// for (ChannelGenerator cg : model.getChannelGenerators()) { -// DataflowChannelGenerator dcg = ((DataflowChannelGenerator) cg); -// for (ChannelMember cm : dcg.getOutputChannelMembers()) { -// if (cm.getIdentifierTemplate().getResourceName().equals(type.getTypeName().toLowerCase())) { -// if (dcg.getReferenceChannelMembers().size() > 0) { -// // If there exists one or more reference channel member. -// type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); -// bDeclareClientField = true; -// break; -// } -// } -// } -// if (bDeclareClientField) break; -// } -// } - - // Declare input methods in resources. - for (ChannelGenerator cg : model.getIOChannelGenerators()) { - for (ChannelMember cm : ((DataflowChannelGenerator) cg).getOutputChannelMembers()) { - if (cm.getIdentifierTemplate().equals(rn.getIdentifierTemplate())) { - Expression message = cm.getStateTransition().getMessageExpression(); - if (message.getClass() == Term.class) { - ArrayList params = new ArrayList<>(); - for (Variable var: message.getVariables().values()) { - String paramName = var.getName(); - VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); - param.addAnnotation(new Annotation("FormParam", "\"" + paramName + "\"")); - params.add(param); - } - MethodDeclaration input = new MethodDeclaration( - ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), - false, typeVoid, params); - if (cm.getStateTransition().isRightUnary()) { - input.addAnnotation(new Annotation("PUT")); - } else { - input.addAnnotation(new Annotation("POST")); - } - type.addMethod(input); - } else if (message.getClass() == Variable.class) { - MethodDeclaration input = new MethodDeclaration( - ((Variable) cm.getStateTransition().getMessageExpression()).getName(), - false, typeVoid, null); - if (cm.getStateTransition().isRightUnary()) { - input.addAnnotation(new Annotation("PUT")); - } else { - input.addAnnotation(new Annotation("POST")); - } - type.addMethod(input); - } - } - } - } - - // Declare the field to store the state in the type of each resource. - if (((StoreAttribute) rn.getAttribute()).isStored()) { - IdentifierTemplate resId = rn.getIdentifierTemplate(); - type.addField(new FieldDeclaration(resId.getResourceStateType(), "value", getInitializer(resId))); - } - - // Declare the getter method to obtain the state in the type of each resource. - MethodDeclaration getter = new MethodDeclaration("getValue", rn.getIdentifierTemplate().getResourceStateType()); - getter.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); - getter.addAnnotation(new Annotation("GET")); - type.addMethod(getter); - - // Add compilation unit for each resource. - CompilationUnit cu = new CompilationUnit(type); - cu.addImport(new ImportDeclaration("java.util.*")); - cu.addImport(new ImportDeclaration("javax.ws.rs.*")); - cu.addImport(new ImportDeclaration("javax.ws.rs.client.*")); - cu.addImport(new ImportDeclaration("javax.ws.rs.core.*")); - cu.addImport(new ImportDeclaration("org.springframework.stereotype.Component")); - cu.addImport(new ImportDeclaration("com.fasterxml.jackson.databind.ObjectMapper")); - cu.addImport(new ImportDeclaration("com.fasterxml.jackson.core.JsonProcessingException")); - codes.add(cu); - } - - // Declare the Pair class. - boolean isCreatedPair = false; - for(Node n : resources) { - ResourceNode rn = (ResourceNode) n; - if(isCreatedPair) continue; - if(model.getType("Pair").isAncestorOf(rn.getIdentifierTemplate().getResourceStateType())) { - TypeDeclaration type = new TypeDeclaration("Pair"); - type.addField(new FieldDeclaration(new Type("Double", "T"), "left")); - type.addField(new FieldDeclaration(new Type("Double", "T"), "right")); - - MethodDeclaration constructor = new MethodDeclaration("Pair", true); - constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "left")); - constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "right")); - Block block = new Block(); - block.addStatement("this.left = left;"); - block.addStatement("this.right = right;"); - constructor.setBody(block); - type.addMethod(constructor); - - for(FieldDeclaration field : type.getFields()) { - MethodDeclaration getter = new MethodDeclaration( - "get" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1), - new Type("Double","T")); - getter.setBody(new Block()); - getter.getBody().addStatement("return " + field.getName() + ";"); - type.addMethod(getter); - } - -// MethodDeclaration toStr = new MethodDeclaration("toString", false, DataConstraintModel.typeString, null); -// block = new Block(); -// block.addStatement("return \"{\\\"\" + left + \"\\\":\\\"\" + right + \"\\\"}\";"); -// toStr.setBody(block); -// type.addMethod(toStr); - - CompilationUnit cu = new CompilationUnit(type); - cu.addImport(new ImportDeclaration("java.util.*")); - codes.add(cu); - - isCreatedPair = true; - } - } - - return codes; - } - - private static String getInitializer(IdentifierTemplate resId) { - Type stateType = resId.getResourceStateType(); - String initializer = null; - if (resId.getInitialValue() != null) { - initializer = resId.getInitialValue().toImplementation(new String[] {""}); - } else { - if (DataConstraintModel.typeList.isAncestorOf(stateType)) { - initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; - } else if (DataConstraintModel.typeMap.isAncestorOf(stateType)) { - initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; - } - } - return initializer; - } - - static public ArrayList getCodes(ArrayList codeTree) { - ArrayList codes = new ArrayList<>(); - for (TypeDeclaration type : codeTree) { - codes.add("public class " + type.getTypeName() + "{"); - for (FieldDeclaration field : type.getFields()) { - if (type.getTypeName() != mainTypeName) { - String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " - + field.getName(); - if (DataConstraintModel.isListType(field.getType())) - cons += " = new " + field.getType().getImplementationTypeName() + "()"; - cons += ";"; - codes.add(cons); - } else { - String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " - + field.getName() + " = new " + field.getType().getTypeName() + "("; - cons += ");"; - codes.add(cons); - } - } - codes.add(""); - for (MethodDeclaration method : type.getMethods()) { - String varstr = "\t" + "public " + method.getReturnType().getInterfaceTypeName() + " " - + method.getName() + "("; - if (method.getParameters() != null) { - for (VariableDeclaration var : method.getParameters()) { - varstr += var.getType().getInterfaceTypeName() + " " + var.getName() + ","; - } - if (!method.getParameters().isEmpty()) - varstr = varstr.substring(0, varstr.length() - 1); - } - if (method.getBody() != null) { - for (String str : method.getBody().getStatements()) { - codes.add("\t\t" + str + ";"); - } - } - codes.add(varstr + ")" + "{"); - codes.add("\t" + "}"); - codes.add(""); - } - codes.add("}"); - codes.add(""); - } - return codes; - } - - static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - if (target.equals(from)) { - return new Field("value", - target.getResourceStateType() != null ? target.getResourceStateType() - : DataConstraintModel.typeInt); - } - return null; - } - - @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() - : DataConstraintModel.typeInt); - } - }; - static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - if (target.equals(from)) { - return new Field("value", - target.getResourceStateType() != null ? target.getResourceStateType() - : DataConstraintModel.typeInt); - } - // for reference channel member - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - return new Parameter(target.getResourceName(), - target.getResourceStateType() != null ? target.getResourceStateType() - : DataConstraintModel.typeInt); - } - }; -} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyMethodBodyGenerator.java deleted file mode 100644 index 4004486..0000000 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/JerseyMethodBodyGenerator.java +++ /dev/null @@ -1,596 +0,0 @@ -package algorithms; - -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import code.ast.CodeUtil; -import code.ast.CompilationUnit; -import code.ast.MethodDeclaration; -import code.ast.TypeDeclaration; -import code.ast.VariableDeclaration; -import models.Edge; -import models.Node; -import models.algebra.Expression; -import models.algebra.InvalidMessage; -import models.algebra.ParameterizedIdentifierIsFutureWork; -import models.algebra.Term; -import models.algebra.Type; -import models.algebra.UnificationFailed; -import models.algebra.ValueUndefined; -import models.algebra.Variable; -import models.dataConstraintModel.ChannelGenerator; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; -import models.dataFlowModel.DataFlowModel; -import models.dataFlowModel.DataflowChannelGenerator; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.PushPullValue; -import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; -import models.dataFlowModel.ResourceDependency; -import models.dataFlowModel.ResourceDependencyGraph; -import models.dataFlowModel.ResourceNode; -import models.dataFlowModel.StoreAttribute; -import models.dataFlowModel.DataflowChannelGenerator.IResourceStateAccessor; - -public class JerseyMethodBodyGenerator { - private static String baseURL = "http://localhost:8080"; - - public static ArrayList doGenerate(ResourceDependencyGraph graph, DataFlowModel model, ArrayList codes) { - // Create a map from type names (lower case) to their types. - Map typeMap = new HashMap<>(); - for (CompilationUnit code: codes) { - for (TypeDeclaration type: code.types()) { - typeMap.put(type.getTypeName().substring(0,1).toLowerCase() + type.getTypeName().substring(1), type); - } - } - - // Generate the body of each update or getter method. - try { - Set chainedCalls = new HashSet<>(); - Map> referredResources = new HashMap<>(); - for (Edge e: graph.getEdges()) { - ResourceDependency d = (ResourceDependency) e; - PushPullAttribute pushPull = (PushPullAttribute) d.getAttribute(); - ResourceNode src = (ResourceNode) d.getSource(); - ResourceNode dst = (ResourceNode) d.getDestination(); - String srcResourceName = src.getIdentifierTemplate().getResourceName(); - String dstResourceName = dst.getIdentifierTemplate().getResourceName(); - TypeDeclaration srcType = typeMap.get(srcResourceName); - TypeDeclaration dstType = typeMap.get(dstResourceName); - for (ChannelMember out: d.getChannelGenerator().getOutputChannelMembers()) { - if (out.getIdentifierTemplate() == dst.getIdentifierTemplate()) { - if (pushPull.getOptions().get(0) == PushPullValue.PUSH && srcType != null) { - // for push data transfer - MethodDeclaration update = getUpdateMethod(dstType, srcType); - if (((StoreAttribute) dst.getAttribute()).isStored()) { - // update stored state of dst side resource (when every incoming edge is in push style) - Expression updateExp = null; - if (d.getChannelGenerator().getReferenceChannelMembers().size() == 0) { - updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); - } else { - // if there exists one or more reference channel member. - HashMap inputIdentifierToStateAccessor = new HashMap<>(); - for (Edge eIn: dst.getInEdges()) { - ResourceDependency dIn = (ResourceDependency) eIn; - inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JerseyCodeGenerator.pushAccessor); - } - for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { - inputIdentifierToStateAccessor.put(c.getIdentifierTemplate(), JerseyCodeGenerator.pullAccessor); - } - updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputIdentifierToStateAccessor); - } - String[] sideEffects = new String[] {""}; - String curState = updateExp.toImplementation(sideEffects); - String updateStatement; - if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { - updateStatement = sideEffects[0]; - } else { - updateStatement = sideEffects[0] + "this.value = " + curState + ";"; - } - if (update.getBody() == null || !update.getBody().getStatements().contains(updateStatement)) { - // add an update statement of the state of dst side resource. - update.addFirstStatement(updateStatement); - } - } - if (dst.getIndegree() > 1) { - // update a cash of src side resource (when incoming edges are multiple) - String cashStatement = "this." + srcResourceName + " = " + srcResourceName + ";"; - if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { - update.addFirstStatement(cashStatement); - } - } - // to convert a json param to a tuple, pair or map object. - for (VariableDeclaration param: update.getParameters()) { - Type paramType = param.getType(); - String paramName = param.getName(); - String paramConverter = ""; - if (DataConstraintModel.typeList.isAncestorOf(paramType) && paramType != DataConstraintModel.typeList) { - Type compType = TypeInference.getListComponentType(paramType); - if (DataConstraintModel.typeTuple.isAncestorOf(compType)) { - param.setType(DataConstraintModel.typeListStr); - param.setName(paramName + "_json"); - paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = new " + paramType.getImplementationTypeName() + "();\n"; - paramConverter += "for (String str: " + param.getName() + ") {\n"; - String mapTypeName = convertFromEntryToMapType(compType); - paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(str, HashMap.class);\n"; - paramConverter += "\t" + paramName + ".add(" + getCodeForConversionFromMapToTuple(compType, "i") + ");\n"; - paramConverter += "}"; - update.addThrow("JsonProcessingException"); - } else if (DataConstraintModel.typePair.isAncestorOf(compType)) { - param.setType(DataConstraintModel.typeListStr); - param.setName(paramName + "_json"); - paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = new " + paramType.getImplementationTypeName() + "();\n"; - paramConverter += "for (String str: " + param.getName() + ") {\n"; - String mapTypeName = convertFromEntryToMapType(compType); - paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(str, HashMap.class);\n"; - paramConverter += "\t" + paramName + ".add(" + getCodeForConversionFromMapToPair(compType, "i") + ");\n"; - paramConverter += "}"; - update.addThrow("JsonProcessingException"); - } else if (DataConstraintModel.typeMap.isAncestorOf(compType)) { - param.setType(DataConstraintModel.typeListStr); - // To do. - } - } else if (DataConstraintModel.typeTuple.isAncestorOf(paramType)) { - param.setType(DataConstraintModel.typeString); - param.setName(paramName + "_json"); - paramConverter += paramType.getInterfaceTypeName() + " " + paramName + ";\n"; - paramConverter += "{\n"; - String mapTypeName = convertFromEntryToMapType(paramType); - paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; - paramConverter += "\t" + paramName + " = " + getCodeForConversionFromMapToTuple(paramType, "i") + ";\n"; - paramConverter += "}"; - update.addThrow("JsonProcessingException"); - } else if (DataConstraintModel.typePair.isAncestorOf(paramType)) { - param.setType(DataConstraintModel.typeString); - param.setName(paramName + "_json"); - paramConverter += paramType.getInterfaceTypeName() + " " + paramName + ";\n"; - paramConverter += "{\n"; - String mapTypeName = convertFromEntryToMapType(paramType); - paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; - paramConverter += "\t" + paramName + " = " + getCodeForConversionFromMapToPair(paramType, "i") + ";\n"; - paramConverter += "}"; - update.addThrow("JsonProcessingException"); - } else if (DataConstraintModel.typeMap.isAncestorOf(paramType)) { - param.setType(DataConstraintModel.typeString); - param.setName(paramName + "_json"); - paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = " + "new " + paramType.getImplementationTypeName() + "();\n"; - paramConverter += "{\n"; - String mapTypeName = convertFromEntryToMapType(paramType); - paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; - paramConverter += "\t" + getCodeForConversionFromMapToMap(paramType, "i", paramName) + "\n"; - paramConverter += "}"; - update.addThrow("JsonProcessingException"); - } - if (paramConverter.length() > 0) update.addFirstStatement(paramConverter); - } - MethodDeclaration getter = getGetterMethod(dstType); - if (((StoreAttribute) dst.getAttribute()).isStored()) { - // returns the state stored in a field. - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - getter.addStatement("return value;"); - } - } - // src side (for a chain of update method invocations) - String httpMethod = null; - if (out.getStateTransition().isRightUnary()) { - httpMethod = "put"; - } else { - httpMethod = "post"; - } - for (MethodDeclaration srcUpdate: getUpdateMethods(srcType)) { - if (srcUpdate != null) { - List>> params = new ArrayList<>(); - Set referredSet = referredResources.get(srcUpdate); - if (d.getChannelGenerator().getReferenceChannelMembers().size() > 0) { - for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - IdentifierTemplate ref = rc.getIdentifierTemplate(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(srcUpdate, referredSet); - } - if (ref != dst.getIdentifierTemplate()) { - String refResourceName = ref.getResourceName(); - Type refResourceType = ref.getResourceStateType(); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - generatePullDataTransfer(srcUpdate, refResourceName, refResourceType); - } - // Value of a reference side resource. - params.add(new AbstractMap.SimpleEntry<>(refResourceType, new AbstractMap.SimpleEntry<>(refResourceName, refResourceName))); - } - } - } - String srcResName = null; - if (dst.getIndegree() > 1) { - srcResName = srcResourceName; - } - if (!chainedCalls.contains(srcUpdate)) { - // The first call to an update method in this method - // Value of the source side (input side) resource. - params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); - srcUpdate.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, true)); - srcUpdate.addStatement("String result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); - chainedCalls.add(srcUpdate); - } else { - // After the second time of call to update methods in this method - // Value of the source side (input side) resource. - params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); - srcUpdate.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, false)); - srcUpdate.addStatement("result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); - } - srcUpdate.addThrow("JsonProcessingException"); - } - } - for (MethodDeclaration srcInput: getInputMethods(srcType, src, model)) { - List>> params = new ArrayList<>(); - Set referredSet = referredResources.get(srcInput); - for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - IdentifierTemplate ref = rc.getIdentifierTemplate(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(srcInput, referredSet); - } - if (ref != dst.getIdentifierTemplate()) { - String refResourceName = ref.getResourceName(); - Type refResourceType = ref.getResourceStateType(); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - generatePullDataTransfer(srcInput, refResourceName, refResourceType); - } - // Value of a reference side resource. - params.add(new AbstractMap.SimpleEntry<>(refResourceType, new AbstractMap.SimpleEntry<>(refResourceName, refResourceName))); - } - } - String srcResName = null; - if (dst.getIndegree() > 1) { - srcResName = srcResourceName; - } - if (!chainedCalls.contains(srcInput)) { - // First call to an update method in this method - // Value of the source side (input side) resource. - params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); - srcInput.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, true)); - srcInput.addStatement("String result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); - chainedCalls.add(srcInput); - } else { - // After the second time of call to update methods in this method - // Value of the source side (input side) resource. - params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); - srcInput.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, false)); - srcInput.addStatement("result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); - } - srcInput.addThrow("JsonProcessingException"); - } - } else { - // for pull (or push/pull) data transfer - MethodDeclaration getter = getGetterMethod(dstType); - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - // generate a return statement. - String[] sideEffects = new String[] {""}; - String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pullAccessor).toImplementation(sideEffects); // no pull data transfer is included. - getter.addStatement(sideEffects[0] + "return " + curState + ";"); - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { - String refResourceName = c.getIdentifierTemplate().getResourceName(); - Type refResourceType = c.getIdentifierTemplate().getResourceStateType(); - generatePullDataTransfer(getter, refResourceName, refResourceType); - } - } - // get src side resource state by pull data transfer. - Type srcResourceType = src.getIdentifierTemplate().getResourceStateType(); - generatePullDataTransfer(getter, srcResourceName, srcResourceType); - } - } - } - } - // for source nodes - for (Node n: graph.getNodes()) { - ResourceNode resource = (ResourceNode) n; - String resourceName = resource.getIdentifierTemplate().getResourceName(); - TypeDeclaration type = typeMap.get(resourceName); - if (type != null) { - // getter method - MethodDeclaration getter = getGetterMethod(type); - if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - getter.addStatement("return value;"); - } - // methods for input events - Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); - for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { - Set outs = entry.getValue(); - for (ChannelMember out: outs) { - MethodDeclaration input = getInputMethod(type, out); - if (input != null) { - Expression updateExp = entry.getKey().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); - String[] sideEffects = new String[] {""}; - String newState = updateExp.toImplementation(sideEffects); - String updateStatement; - if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { - updateStatement = sideEffects[0]; - } else { - updateStatement = sideEffects[0] + "this.value = " + newState + ";"; - } - if (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement)) { - input.addFirstStatement(updateStatement); - } - } - } - } - } - } - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork - | InvalidMessage | UnificationFailed | ValueUndefined e1) { - e1.printStackTrace(); - } - return codes; - } - - private static void generatePullDataTransfer(MethodDeclaration methodBody, String fromResourceName, Type fromResourceType) { - String varName = new String(fromResourceName); - String respTypeName = fromResourceType.getInterfaceTypeName(); - String respImplTypeName = fromResourceType.getImplementationTypeName(); - String respConverter = ""; - if (DataConstraintModel.typeList.isAncestorOf(fromResourceType) && fromResourceType != DataConstraintModel.typeList) { - Type compType = TypeInference.getListComponentType(fromResourceType); - if (DataConstraintModel.typeTuple.isAncestorOf(compType)) { - varName += "_json"; - String mapTypeName = convertFromEntryToMapType(compType); - respTypeName = "List<" + mapTypeName + ">"; - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = new " + fromResourceType.getImplementationTypeName() + "();\n"; - respConverter += "for (" + mapTypeName + " i: " + varName + ") {\n"; - respConverter += "\t" + fromResourceName + ".add(" + getCodeForConversionFromMapToTuple(compType, "i") + ");\n"; - respConverter += "}"; - methodBody.addThrow("JsonProcessingException"); - } else if (DataConstraintModel.typeMap.isAncestorOf(compType)) { - // To do. - } - } else if (DataConstraintModel.typeTuple.isAncestorOf(fromResourceType)) { - varName += "_json"; - respTypeName = convertFromEntryToMapType(fromResourceType); - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = " + getCodeForConversionFromMapToTuple(fromResourceType, varName) + ";"; - respImplTypeName = "HashMap"; - } else if (DataConstraintModel.typePair.isAncestorOf(fromResourceType)) { - varName += "_json"; - respTypeName = convertFromEntryToMapType(fromResourceType); - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = " + getCodeForConversionFromMapToPair(fromResourceType, varName) + ";"; - respImplTypeName = "HashMap"; - } else if (DataConstraintModel.typeMap.isAncestorOf(fromResourceType)) { - varName += "_json"; - respTypeName = convertFromEntryToMapType(fromResourceType); - respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = new " + fromResourceType.getImplementationTypeName() + "();\n"; - respConverter += getCodeForConversionFromMapToMap(fromResourceType, varName, fromResourceName); - respImplTypeName = "HashMap"; - } - if (respConverter.length() > 0) { - methodBody.addFirstStatement(respConverter); - } - methodBody.addFirstStatement(respTypeName + " " + varName + " = " + getHttpMethodCallStatementWithResponse(baseURL, fromResourceName, "get", respImplTypeName)); - } - - private static String convertFromEntryToMapType(Type type) { - String mapTypeName = null; - if (DataConstraintModel.typePair.isAncestorOf(type)) { - Type compType = TypeInference.getPairComponentType(type); - String wrapperType = DataConstraintModel.getWrapperType(compType); - if (wrapperType != null) { - mapTypeName = "Map"; - } else { - mapTypeName = "Map"; - } - } else if (DataConstraintModel.typeMap.isAncestorOf(type)) { - List compTypes = TypeInference.getMapComponentTypes(type); - String wrapperType = DataConstraintModel.getWrapperType(compTypes.get(1)); - if (wrapperType != null) { - mapTypeName = "Map"; - } else { - mapTypeName = "Map"; - } - } else { - mapTypeName = type.getInterfaceTypeName(); - mapTypeName = mapTypeName.replace("Map.Entry", "Map"); - for (int idx = mapTypeName.indexOf("<", 0); idx >= 0; idx = mapTypeName.indexOf("<", idx + 1)) { - int to = mapTypeName.indexOf(",", idx); - if (to > idx) { - mapTypeName = mapTypeName.substring(0, idx + 1) + "String" + mapTypeName.substring(to); // All elements except for the last one have the string type. - } - } - } - return mapTypeName; - } - - private static String getCodeForConversionFromMapToTuple(Type tupleType, String mapVar) { - String decoded = "$x"; - List elementsTypes = TypeInference.getTupleComponentTypes(tupleType); - String elementBase = mapVar; - for (Type elmType: elementsTypes.subList(0, elementsTypes.size() - 1)) { - elementBase += ".entrySet().iterator().next()"; - if (elmType == DataConstraintModel.typeBoolean - || elmType == DataConstraintModel.typeInt - || elmType == DataConstraintModel.typeLong - || elmType == DataConstraintModel.typeFloat - || elmType == DataConstraintModel.typeDouble) { - String elmVal = CodeUtil.getToValueExp(elmType.getImplementationTypeName(), elementBase + ".getKey()"); - decoded = decoded.replace("$x", "new AbstractMap.SimpleEntry<>(" + elmVal + ", $x)"); - } else if (elmType == DataConstraintModel.typeString) { - decoded = decoded.replace("$x", "new AbstractMap.SimpleEntry<>(" + elementBase + ".getKey(), $x)"); - } else { - // To do. - } - elementBase += ".getValue()"; - } - decoded = decoded.replace("$x", elementBase); - return decoded; - } - - private static String getCodeForConversionFromMapToPair(Type pairType, String mapVar) { - String decoded = "$x"; - decoded = decoded.replace("$x", "new Pair<>(" + mapVar + ".get(\"left\"), $x)"); - decoded = decoded.replace("$x", mapVar + ".get(\"right\")"); - return decoded; - } - - private static String getCodeForConversionFromMapToMap(Type mapType, String mapVal, String mapVar) { - List elementsTypes = TypeInference.getMapComponentTypes(mapType); - Type keyType = elementsTypes.get(0); - Type valType = elementsTypes.get(1); - String keyVal = null; - String decoded = ""; - if (keyType == DataConstraintModel.typeBoolean - || keyType == DataConstraintModel.typeInt - || keyType == DataConstraintModel.typeLong - || keyType == DataConstraintModel.typeFloat - || keyType == DataConstraintModel.typeDouble) { - decoded += "for (String k: " + mapVal + ".keySet()) {\n"; - decoded += "\t" + mapVar + ".put("; - keyVal = CodeUtil.getToValueExp(keyType.getImplementationTypeName(), "k"); - decoded += keyVal + ", " + mapVal + ".get(" + keyVal + ")" + ");\n"; - decoded += "}"; - } else if (keyType == DataConstraintModel.typeString) { - decoded += mapVar + " = " + mapVal + ";"; - } - return decoded; - } - - private static String getHttpMethodParamsStatement(String callerResourceName, List>> params, boolean isFirstCall) { - String statements = ""; - if (isFirstCall) { - statements += "Form "; - } - statements += "form = new Form();\n"; - for (Map.Entry> param: params) { - Type paramType = param.getKey(); - String paramName = param.getValue().getKey(); - String value = param.getValue().getValue(); - if (DataConstraintModel.typeList.isAncestorOf(paramType)) { - Type compType = TypeInference.getListComponentType(paramType); - String wrapperType = DataConstraintModel.getWrapperType(compType); - if (wrapperType == null) { - statements += "for (" + compType.getInterfaceTypeName() + " i: " + value + ") {\n"; - } else { - statements += "for (" + wrapperType + " i: " + value + ") {\n"; - } - if (DataConstraintModel.typeTuple.isAncestorOf(compType) || DataConstraintModel.typePair.isAncestorOf(paramType) || DataConstraintModel.typeList.isAncestorOf(compType) || DataConstraintModel.typeMap.isAncestorOf(paramType)) { - statements += "\tform.param(\"" + paramName + "\", new ObjectMapper().writeValueAsString(i));\n"; // typeTuple: {"1.0":2.0}, typePair: {"left": 1.0, "right":2.0} - } else { - statements += "\tform.param(\"" + paramName + "\", i.toString());\n"; - } - statements += "}\n"; -// return "Entity entity = Entity.entity(" + paramName + ".toString(), MediaType.APPLICATION_JSON);"; - } else if (DataConstraintModel.typeTuple.isAncestorOf(paramType) || DataConstraintModel.typePair.isAncestorOf(paramType) || DataConstraintModel.typeMap.isAncestorOf(paramType)) { - // typeTuple: {"1.0":2.0}, typePair: {"left": 1.0, "right":2.0} - statements += "form.param(\"" + paramName + "\", new ObjectMapper().writeValueAsString(" + value + "));\n"; - } else { - statements += "form.param(\"" + paramName + "\", " + CodeUtil.getToStringExp(paramType.getImplementationTypeName(), value) + ");\n"; - } - } - if (isFirstCall) { - statements += "Entity
"; - } - statements += "entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED);"; - return statements; - } - - private static String getHttpMethodCallStatement(String baseURL, String resourceName, String srcResName, String httpMethod) { - if (srcResName == null) { - return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(entity, String.class);"; - } else { - // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. - return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "/" + srcResName + "\").request()." + httpMethod + "(entity, String.class);"; - } - } - - private static String getHttpMethodCallStatementWithResponse(String baseURL, String resourceName, String httpMethod, String respImplName) { - String responseShortTypeName = respImplName; - if (respImplName.contains("<")) { - responseShortTypeName = respImplName.substring(0, respImplName.indexOf("<")); - } - return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(" + responseShortTypeName + ".class);"; - } - - private static MethodDeclaration getUpdateMethod(TypeDeclaration type, TypeDeclaration from) { - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().equals("update" + from.getTypeName())) return m; - } - return null; - } - - private static List getUpdateMethods(TypeDeclaration type) { - List updates = new ArrayList<>(); - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().startsWith("update")) { - updates.add(m); - } - } - return updates; - } - - private static MethodDeclaration getGetterMethod(TypeDeclaration type) { - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().startsWith("get")) return m; - } - return null; - } - - private static Map> getIOChannelsAndMembers(ResourceNode resource, DataFlowModel model) { - Map> ioChannelsAndMembers = new HashMap<>(); - for (ChannelGenerator c: model.getIOChannelGenerators()) { - DataflowChannelGenerator ch = (DataflowChannelGenerator) c; - // I/O channel - for (ChannelMember out: ch.getOutputChannelMembers()) { - if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { - if (out.getStateTransition().getMessageExpression() instanceof Term || out.getStateTransition().getMessageExpression() instanceof Variable) { - Set channelMembers = ioChannelsAndMembers.get(ch); - if (channelMembers == null) { - channelMembers = new HashSet<>(); - ioChannelsAndMembers.put(ch, channelMembers); - } - channelMembers.add(out); - } - } - } - } - return ioChannelsAndMembers; - } - - private static List getInputMethods(TypeDeclaration type, ResourceNode resource, DataFlowModel model) { - List inputs = new ArrayList<>(); - for (ChannelGenerator c: model.getIOChannelGenerators()) { - DataflowChannelGenerator channel = (DataflowChannelGenerator) c; - // I/O channel - for (ChannelMember out: channel.getOutputChannelMembers()) { - if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { - MethodDeclaration input = getInputMethod(type, out); - inputs.add(input); - } - } - } - return inputs; - } - - private static MethodDeclaration getInputMethod(TypeDeclaration type, ChannelMember out) { - MethodDeclaration input = null; - if (out.getStateTransition().getMessageExpression() instanceof Term) { - Term message = (Term) out.getStateTransition().getMessageExpression(); - input = getMethod(type, message.getSymbol().getImplName()); - } else if (out.getStateTransition().getMessageExpression() instanceof Variable) { - Variable message = (Variable) out.getStateTransition().getMessageExpression(); - input = getMethod(type, message.getName()); - } - return input; - } - - private static MethodDeclaration getMethod(TypeDeclaration type, String methodName) { - for (MethodDeclaration m: type.getMethods()) { - if (m.getName().equals(methodName)) return m; - } - return null; - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/NecessityOfStoringResourceStates.java b/AlgebraicDataflowArchitectureModel/src/algorithms/NecessityOfStoringResourceStates.java deleted file mode 100644 index 9a72711..0000000 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/NecessityOfStoringResourceStates.java +++ /dev/null @@ -1,52 +0,0 @@ -package algorithms; - -import java.util.Collection; -import java.util.HashSet; - -import models.*; -import models.algebra.*; -import models.dataConstraintModel.*; -import models.dataFlowModel.*; - -public class NecessityOfStoringResourceStates { - static public ResourceDependencyGraph doDecide(DataFlowModel model) { - ResourceDependencyGraph graph = model.getResourceDependencyGraph(); - Collection channels = new HashSet<>(model.getIOChannelGenerators()); - channels.addAll(model.getChannelGenerators()); - for (ChannelGenerator generator: channels) { - for (ChannelMember member: ((DataflowChannelGenerator) generator).getOutputChannelMembers()) { - boolean flag = !member.getStateTransition().isRightUnary(); // The state does not need to be stored if the state transition function is right unary. - for (Node node : graph.getNodes()) { - if (((ResourceNode) node).getIdentifierTemplate().equals(member.getIdentifierTemplate())) { - setStoreAttribute(flag, (ResourceNode) node); - } - } - } - } - for (Node node : graph.getNodes()) { - HashSet inChannels = new HashSet<>(); - for(Edge pre : ((ResourceNode) node).getInEdges()) { - inChannels.add(((ResourceDependency) pre).getChannelGenerator()); - } - if ((inChannels.size() > 1)) { - setStoreAttribute(true, (ResourceNode) node); - } else if (((ResourceNode) node).getAttribute() == null) { - setStoreAttribute(false, (ResourceNode) node); - } - } - return graph; - } - - static private void setStoreAttribute(boolean flag, ResourceNode node) { - NodeAttribute attr = node.getAttribute(); - StoreAttribute store; - if (attr != null && attr instanceof NodeAttribute) { - store = (StoreAttribute) attr; - store.setNeeded(store.isNeeded() || flag); - } else { - store = new StoreAttribute(); - store.setNeeded(flag); - node.setAttribute(store); - } - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/SelectableDataTransfers.java b/AlgebraicDataflowArchitectureModel/src/algorithms/SelectableDataTransfers.java deleted file mode 100644 index c59e4f2..0000000 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/SelectableDataTransfers.java +++ /dev/null @@ -1,45 +0,0 @@ -package algorithms; - -import java.util.ArrayList; -import java.util.List; - -import models.*; -import models.dataFlowModel.*; - -public class SelectableDataTransfers { - static public ResourceDependencyGraph init(ResourceDependencyGraph graph) { - List nodes = new ArrayList<>(graph.getNodes()); - // set push only attributes - for (Node n: graph.getNodes()) { - if (nodes.contains(n) && ((StoreAttribute) ((ResourceNode) n).getAttribute()).isNeeded()) { - nodes.remove(n); - trackEdges(n, nodes); - } - } - // set push/pull attributes to the remaining edges - for (Edge e : graph.getEdges()) { - if (((ResourceDependency) e).getAttribute() == null) { - PushPullAttribute ppat = new PushPullAttribute(); - ppat.addOption(PushPullValue.PUSHorPULL); - ppat.addOption(PushPullValue.PUSH); - ppat.addOption(PushPullValue.PULL); - ((ResourceDependency) e).setAttribute(ppat); - } - } - return graph; - } - - static private void trackEdges(Node n, List nodes) { - // recursively set push only attributes to input side edges - for (Edge e : ((ResourceNode) n).getInEdges()) { - PushPullAttribute ppat = new PushPullAttribute(); - ppat.addOption(PushPullValue.PUSH); - ((ResourceDependency) e).setAttribute(ppat); - Node n2 = e.getSource(); - if (nodes.contains(n2)) { - nodes.remove(n2); - trackEdges(n2, nodes); - } - } - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java index a890ad3..fb48b10 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java @@ -24,10 +24,15 @@ import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.IdentifierTemplate; import models.dataConstraintModel.StateTransition; -import models.dataFlowModel.DataFlowModel; -import models.dataFlowModel.ResourceDependencyGraph; +import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.ResourceNode; +/** + * Type inference for data transfer model + * + * @author Nitta + * + */ public class TypeInference { static private Map listTypes = new HashMap<>(); static private Map listComponentTypes = new HashMap<>(); @@ -78,7 +83,7 @@ return mapComponentTypes.get(mapType); } - static public void infer(ResourceDependencyGraph graph, DataFlowModel model) { + static public void infer(DataTransferModel model) { Map> resources = new HashMap<>(); Map variables = new HashMap<>(); Map, Type>>> messages = new HashMap<>(); @@ -94,7 +99,6 @@ Map>> expToPair = new HashMap<>(); Map>> expToMap = new HashMap<>(); - Map idToRes = new HashMap<>(); Map> updateFromResource = new HashMap<>(); Map> updateFromVariable = new HashMap<>(); Map> updateFromMessage = new HashMap<>(); @@ -117,10 +121,6 @@ pairTypes.put(DataConstraintModel.typeDouble, DataConstraintModel.typePairDouble); tupleComponentTypes.put(DataConstraintModel.typeTuple, Arrays.asList(new Type[] { null, null })); mapComponentTypes.put(DataConstraintModel.typeMap, Arrays.asList(new Type[] { null, null })); - for (Node n : graph.getNodes()) { - ResourceNode resource = (ResourceNode) n; - idToRes.put(resource.getIdentifierTemplate(), resource); - } // 1. Collect type information from the architecture model. Collection channels = new HashSet<>(model.getIOChannelGenerators()); diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/UpdateConflictCheck.java b/AlgebraicDataflowArchitectureModel/src/algorithms/UpdateConflictCheck.java deleted file mode 100644 index ad76543..0000000 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/UpdateConflictCheck.java +++ /dev/null @@ -1,74 +0,0 @@ -package algorithms; - -import java.util.*; - -import models.*; -import models.dataFlowModel.*; - -public class UpdateConflictCheck { - private static int index = 0; - private static Deque stack = new ArrayDeque<>(); - private static Set> strong = new HashSet<>(); - private static Map ids = new HashMap<>(); - private static Map lowlink = new HashMap<>(); - private static Map onStack = new HashMap<>(); - - static private void init() { - index = 0; - stack = new ArrayDeque<>(); - strong = new HashSet<>(); - ids = new HashMap<>(); - lowlink = new HashMap<>(); - onStack = new HashMap<>(); - } - - static private void strongconnect(Node node) { - ids.put(node, index); - lowlink.put(node, index); - index++; - stack.push(node); - onStack.put(node, true); - - for (Node n : node.getSuccessors()) { - if (lowlink.containsKey(n)) { - strongconnect(n); - if (lowlink.get(node) > lowlink.get(n)) { - lowlink.replace(node, lowlink.get(n)); - } - } else if (onStack.get(n)) { - if (lowlink.get(node) > lowlink.get(n)) { - lowlink.replace(node, lowlink.get(n)); - } - } - } - if (lowlink.get(node) == ids.get(node)) { - Set tmp = new HashSet<>(); - Node w; - do { - w = stack.pop(); - onStack.replace(node, false); - tmp.add(w); - } while (node != w); - strong.add(tmp); - } - } - - static public boolean run(DataFlowModel model) { - init(); - boolean check = true; - for (Node node : model.getResourceDependencyGraph().getNodes()) { - if (ids.containsKey(node)) { - strongconnect(node); - } - } -// System.out.println(strong.size() + " " + model.getResourceDependencyGraph().getNodes().size()); - /* - * for(ChannelGenerator cg:model.getChannelGenerators()) { - * DataflowChannelGenerator data = (DataflowChannelGenerator)cg; - * for(ChannelMember channel:data.getChannelMembers()) { for(ChannelMember - * another:data.getChannelMembers()) { if(!channel.equals(another)) { check = - * channel.getIdentifierTemplate() != another.getIdentifierTemplate(); } } } } - */ - return strong.size() == 0 && check; - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/Validation.java b/AlgebraicDataflowArchitectureModel/src/algorithms/Validation.java new file mode 100644 index 0000000..1744af5 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/Validation.java @@ -0,0 +1,72 @@ +package algorithms; + +import java.util.*; + +import models.*; +import models.dataFlowModel.*; + +/** + * Validation checker for data transfer model + * + * @author Nitta + * + */ +public class Validation { + private static int index = 0; + private static Deque stack = new ArrayDeque<>(); + private static Set> strong = new HashSet<>(); + private static Map ids = new HashMap<>(); + private static Map lowlink = new HashMap<>(); + private static Map onStack = new HashMap<>(); + + static public boolean checkUpdateConflict(DataTransferModel model) { + init(); + boolean check = true; + for (Node node : model.getDataFlowGraph().getNodes()) { + if (ids.containsKey(node)) { + traverseStronglyConnectedComponents(node); + } + } + return strong.size() == 0 && check; + } + + static private void init() { + index = 0; + stack = new ArrayDeque<>(); + strong = new HashSet<>(); + ids = new HashMap<>(); + lowlink = new HashMap<>(); + onStack = new HashMap<>(); + } + + static private void traverseStronglyConnectedComponents(Node node) { + ids.put(node, index); + lowlink.put(node, index); + index++; + stack.push(node); + onStack.put(node, true); + + for (Node n : node.getSuccessors()) { + if (lowlink.containsKey(n)) { + traverseStronglyConnectedComponents(n); + if (lowlink.get(node) > lowlink.get(n)) { + lowlink.replace(node, lowlink.get(n)); + } + } else if (onStack.get(n)) { + if (lowlink.get(node) > lowlink.get(n)) { + lowlink.replace(node, lowlink.get(n)); + } + } + } + if (lowlink.get(node) == ids.get(node)) { + Set tmp = new HashSet<>(); + Node w; + do { + w = stack.pop(); + onStack.replace(node, false); + tmp.add(w); + } while (node != w); + strong.add(tmp); + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/DataTransferMethodAnalyzer.java b/AlgebraicDataflowArchitectureModel/src/generators/DataTransferMethodAnalyzer.java new file mode 100644 index 0000000..8e68103 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/DataTransferMethodAnalyzer.java @@ -0,0 +1,47 @@ +package generators; + +import java.util.HashSet; + +import models.*; +import models.algebra.*; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.DataConstraintModel; +import models.dataFlowModel.*; + +/** + * Algorithm to analyze data transfer methods selected by a user + * + * @author Nitta + * + */ +public class DataTransferMethodAnalyzer { + static private HashSet reachableNodes = new HashSet<>(); + + /** + * Determine whether each resource state is stored or not depending on selected data transfer methods. + * + * @param graph a data flow graph (in/out) + */ + static public void decideToStoreResourceStates(DataFlowGraph graph) { + reachableNodes.clear(); + for (Node n : graph.getNodes()) { + ResourceNode resource = (ResourceNode) n; + trackNode(resource); + } + } + + static private void trackNode(ResourceNode resource) { + if (reachableNodes.contains(resource)) + return; + reachableNodes.add(resource); + boolean flag = true; + for (Edge e : resource.getInEdges()) { + if (((PushPullAttribute) e.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + // Traverse pull edges only. + trackNode((ResourceNode) e.getSource()); + flag = false; + } + } + ((StoreAttribute) resource.getAttribute()).setStored(flag); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java new file mode 100644 index 0000000..74ed6a8 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -0,0 +1,475 @@ +package generators; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +import code.ast.Block; +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +import code.ast.ImportDeclaration; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; +import models.Edge; +import models.Node; +import models.algebra.Expression; +import models.algebra.Field; +import models.algebra.Parameter; +import models.algebra.Symbol; +import models.algebra.Term; +import models.algebra.Type; +import models.algebra.Variable; +import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.IdentifierTemplate; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataTransferChannelGenerator; +import models.dataFlowModel.DataTransferChannelGenerator.IResourceStateAccessor; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.StoreAttribute; + +/** + * Generator for plain Java prototypes + * + * @author Nitta + * + */ +public class JavaCodeGenerator { + public static final Type typeVoid = new Type("Void", "void"); + private static String defaultMainTypeName = "Main"; + static String mainTypeName = defaultMainTypeName; + + public static String getMainTypeName() { + return mainTypeName; + } + + public static void setMainTypeName(String mainTypeName) { + JavaCodeGenerator.mainTypeName = mainTypeName; + } + + public static void resetMainTypeName() { + JavaCodeGenerator.mainTypeName = defaultMainTypeName; + } + + static public ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model) { + ArrayList codes = new ArrayList<>(); + ArrayList resources = determineResourceOrder(graph); + + TypeDeclaration mainType = new TypeDeclaration(mainTypeName); + CompilationUnit mainCU = new CompilationUnit(mainType); + mainCU.addImport(new ImportDeclaration("java.util.*")); + codes.add(mainCU); + + // Declare the constructor of the main type. + MethodDeclaration mainConstructor = new MethodDeclaration(mainTypeName, true); + mainType.addMethod(mainConstructor); + + // For each resource. + for (ResourceNode rn: resources) { + boolean f = false; + String resourceName = rn.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase() + + rn.getIdentifierTemplate().getResourceName().substring(1); + 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<>(); + for (Edge e : rn.getOutEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + IdentifierTemplate dstRes = ((ResourceNode) re.getDestination()).getIdentifierTemplate(); + String resName = dstRes.getResourceName().substring(0, 1).toUpperCase() + dstRes.getResourceName().substring(1); + if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + depends.add(dstRes); + fieldInitializer += resName.toLowerCase() + ","; + f = true; + } + } + for (Edge e : rn.getInEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + IdentifierTemplate srcRes = ((ResourceNode) re.getSource()).getIdentifierTemplate(); + String resName = srcRes.getResourceName().substring(0, 1).toUpperCase() + srcRes.getResourceName().substring(1); + if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + depends.add(srcRes); + fieldInitializer += resName.toLowerCase() + ","; + f = true; + } else { + 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(); + type.addField(new FieldDeclaration( + cashResId.getResourceStateType(), ((ResourceNode) re.getSource()).getIdentifierTemplate().getResourceName(), getInitializer(cashResId))); + } + } + } + Set refs = new HashSet<>(); + for (ChannelGenerator cg : model.getChannelGenerators()) { + DataTransferChannelGenerator c = (DataTransferChannelGenerator) cg; + if (c.getInputIdentifierTemplates().contains(rn.getIdentifierTemplate())) { + for (IdentifierTemplate id: c.getReferenceIdentifierTemplates()) { + if (!refs.contains(id) && !depends.contains(id)) { + refs.add(id); + String refResName = id.getResourceName(); + fieldInitializer += refResName.toLowerCase() + ","; + f = true; + } + } + } + } + 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); + } + 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); + Block block = new Block(); + depends = new HashSet<>(); + for (Edge e : rn.getOutEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + IdentifierTemplate dstRes = ((ResourceNode) re.getDestination()).getIdentifierTemplate(); + String dstResName = dstRes.getResourceName().substring(0, 1).toUpperCase() + dstRes.getResourceName().substring(1); + 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() + ";"); + } + } + for (Edge e : rn.getInEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + IdentifierTemplate srcRes = ((ResourceNode) re.getSource()).getIdentifierTemplate(); + String srcResName = srcRes.getResourceName().substring(0, 1).toUpperCase() + srcRes.getResourceName().substring(1); + 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() + ";"); + } else { + // Declare an update method in the type of the destination resource. + ArrayList vars = new ArrayList<>(); + vars.add(new VariableDeclaration(srcRes.getResourceStateType(), srcRes.getResourceName())); + DataTransferChannelGenerator c = (DataTransferChannelGenerator) re.getChannelGenerator(); + for (IdentifierTemplate ref: c.getReferenceIdentifierTemplates()) { + if (ref != rn.getIdentifierTemplate()) { + vars.add(new VariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); + } + } + type.addMethod(new MethodDeclaration("update" + srcResName, false, typeVoid, vars)); + } + } + // Declare a field to refer to the reference resource. + refs = new HashSet<>(); + for (ChannelGenerator cg : model.getChannelGenerators()) { + DataTransferChannelGenerator c = (DataTransferChannelGenerator) cg; + if (c.getInputIdentifierTemplates().contains(rn.getIdentifierTemplate())) { + for (IdentifierTemplate id: c.getReferenceIdentifierTemplates()) { + if (!refs.contains(id) && !depends.contains(id)) { + refs.add(id); + String refResName = id.getResourceName(); + refResName = refResName.substring(0, 1).toUpperCase() + refResName.substring(1); + 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() + ";"); + } + } + } + } + constructor.setBody(block); + if (constructor.getParameters() != null) + type.addMethod(constructor); + + // Declare input methods in resources and the main type. + for (ChannelGenerator cg : model.getIOChannelGenerators()) { + for (ChannelMember cm : ((DataTransferChannelGenerator) cg).getOutputChannelMembers()) { + if (cm.getIdentifierTemplate().equals(rn.getIdentifierTemplate())) { + Expression message = cm.getStateTransition().getMessageExpression(); + if (message.getClass() == Term.class) { + ArrayList params = new ArrayList<>(); + for (Variable var: message.getVariables().values()) { + params.add(new VariableDeclaration(var.getType(), var.getName())); + } + MethodDeclaration input = new MethodDeclaration( + ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), + false, typeVoid, params); + type.addMethod(input); + String str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); + input = getMethod(mainType, str); + if (input == null) { + input = new MethodDeclaration(str, false, typeVoid, params); + mainType.addMethod(input); + } else { + // Add type to a parameter without type. + for (VariableDeclaration param: input.getParameters()) { + if (param.getType() == null) { + for (VariableDeclaration p: params) { + if (param.getName().equals(p.getName()) && p.getType() != null) { + param.setType(p.getType()); + } + } + } + } + } + } else if (message.getClass() == Variable.class) { + MethodDeclaration input = new MethodDeclaration( + ((Variable) cm.getStateTransition().getMessageExpression()).getName(), + false, typeVoid, null); + type.addMethod(input); + String str = ((Variable) cm.getStateTransition().getMessageExpression()).getName(); + input = getMethod(mainType, str); + if (input == null) { + input = new MethodDeclaration(str, false, typeVoid, null); + mainType.addMethod(input); + } + } + } + } + } + + // Declare the field to store the state in the type of each resource. + if (((StoreAttribute) rn.getAttribute()).isStored()) { + IdentifierTemplate resId = rn.getIdentifierTemplate(); + type.addField(new FieldDeclaration(resId.getResourceStateType(), "value", getInitializer(resId))); + } + + // Declare the getter method to obtain the state in the type of each resource. + type.addMethod(new MethodDeclaration("getValue", + rn.getIdentifierTemplate().getResourceStateType())); + + // Add compilation unit for each resource. + CompilationUnit cu = new CompilationUnit(type); + cu.addImport(new ImportDeclaration("java.util.*")); + codes.add(cu); + } + + // Declare the Pair class. + boolean isCreatedPair = false; + for(ResourceNode rn : resources) { + if(isCreatedPair) continue; + if(model.getType("Pair").isAncestorOf(rn.getIdentifierTemplate().getResourceStateType())) { + TypeDeclaration type = new TypeDeclaration("Pair"); + type.addField(new FieldDeclaration(new Type("Double", "T"), "left")); + type.addField(new FieldDeclaration(new Type("Double", "T"), "right")); + + MethodDeclaration constructor = new MethodDeclaration("Pair", true); + constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "left")); + constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "right")); + Block block = new Block(); + block.addStatement("this.left = left;"); + block.addStatement("this.right = right;"); + constructor.setBody(block); + type.addMethod(constructor); + + for(FieldDeclaration field : type.getFields()) { + MethodDeclaration getter = new MethodDeclaration( + "get" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1), + new Type("Double","T")); + getter.setBody(new Block()); + getter.getBody().addStatement("return " + field.getName() + ";"); + type.addMethod(getter); + } + + CompilationUnit cu = new CompilationUnit(type); + cu.addImport(new ImportDeclaration("java.util.*")); + codes.add(cu); + + isCreatedPair = true; + } + } + + // Declare getter methods in the main type. + for (Node n : graph.getNodes()) { + ResourceNode rn = (ResourceNode) n; + MethodDeclaration getter = new MethodDeclaration( + "get" + rn.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase() + + rn.getIdentifierTemplate().getResourceName().substring(1), + rn.getIdentifierTemplate().getResourceStateType()); + getter.setBody(new Block()); + getter.getBody().addStatement( + "return " + rn.getIdentifierTemplate().getResourceName() + ".getValue();"); + mainType.addMethod(getter); + } + + + HashSet tmps = new HashSet<>(); + HashSet cont = new HashSet<>(); + for (MethodDeclaration method : mainType.getMethods()) { + if (!tmps.contains(method.getName())) + tmps.add(method.getName()); + else + cont.add(method.getName()); + } + for (MethodDeclaration method : mainType.getMethods()) { + if (cont.contains(method.getName())) { + method.setName(method.getName() + method.getParameters().get(0).getName().substring(0, 1).toUpperCase() + + method.getParameters().get(0).getName().substring(1)); + } + } + return codes; + } + + private static String getInitializer(IdentifierTemplate resId) { + Type stateType = resId.getResourceStateType(); + String initializer = null; + if (resId.getInitialValue() != null) { + initializer = resId.getInitialValue().toImplementation(new String[] {""}); + } else { + if (DataConstraintModel.typeList.isAncestorOf(stateType)) { + initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + } else if (DataConstraintModel.typeMap.isAncestorOf(stateType)) { + initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + } + } + return initializer; + } + + static public ArrayList getCodes(ArrayList codeTree) { + ArrayList codes = new ArrayList<>(); + for (TypeDeclaration type : codeTree) { + codes.add("public class " + type.getTypeName() + "{"); + for (FieldDeclaration field : type.getFields()) { + if (type.getTypeName() != mainTypeName) { + String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " + + field.getName(); + if (DataConstraintModel.isListType(field.getType())) + cons += " = new ArrayList<>()"; + cons += ";"; + codes.add(cons); + } else { + String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " + + field.getName() + " = new " + field.getType().getTypeName() + "("; + cons += ");"; + codes.add(cons); + } + } + codes.add(""); + for (MethodDeclaration method : type.getMethods()) { + String varstr = "\t" + "public " + method.getReturnType().getInterfaceTypeName() + " " + + method.getName() + "("; + if (method.getParameters() != null) { + for (VariableDeclaration var : method.getParameters()) { + varstr += var.getType().getInterfaceTypeName() + " " + var.getName() + ","; + } + if (!method.getParameters().isEmpty()) + varstr = varstr.substring(0, varstr.length() - 1); + } + if (method.getBody() != null) { + for (String str : method.getBody().getStatements()) { + codes.add("\t\t" + str + ";"); + } + } + codes.add(varstr + ")" + "{"); + codes.add("\t" + "}"); + codes.add(""); + } + codes.add("}"); + codes.add(""); + } + return codes; + } + + static private ArrayList determineResourceOrder(DataFlowGraph graph) { + ArrayList resources = new ArrayList<>(); + Set visited = new HashSet<>(); + for (Node n : graph.getNodes()) { + ResourceNode rn = (ResourceNode) n; + topologicalSort(graph, rn, visited, resources); + } + return resources; + } + + static private void topologicalSort(DataFlowGraph graph, ResourceNode curNode, Set visited, List orderedList) { + if (visited.contains(curNode)) return; + visited.add(curNode); + for (Edge e : curNode.getInEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + topologicalSort(graph, (ResourceNode) re.getSource(), visited, orderedList); + } + } + for (Edge e : curNode.getOutEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + topologicalSort(graph, (ResourceNode) re.getDestination(), visited, orderedList); + } + } + for (Node n: graph.getNodes()) { // for reference resources. + ResourceNode rn = (ResourceNode) n; + for (Edge e : rn.getOutEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + for (ChannelMember m: re.getChannelGenerator().getReferenceChannelMembers()) { + if (m.getIdentifierTemplate() == curNode.getIdentifierTemplate()) { + topologicalSort(graph, rn, visited, orderedList); + } + } + } + } + orderedList.add(0, curNode); + } + + private static MethodDeclaration getMethod(TypeDeclaration type, String methodName) { + for (MethodDeclaration m: type.getMethods()) { + if (m.getName().equals(methodName)) return m; + } + return null; + } + + static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + if (target.equals(from)) { + return new Field("value", + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + return new Parameter(target.getResourceName(), + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + return new Parameter(target.getResourceName(), + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + }; + static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + if (target.equals(from)) { + return new Field("value", + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + Term getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); + getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + return getter; + } + + @Override + public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + Term getter = new Term(new Symbol("getValue", 1, Symbol.Type.METHOD)); + getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + return getter; + } + }; +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java new file mode 100644 index 0000000..ec17706 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -0,0 +1,350 @@ +package generators; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import code.ast.CompilationUnit; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import models.Edge; +import models.Node; +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.Term; +import models.algebra.Type; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.algebra.Variable; +import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.IdentifierTemplate; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataTransferChannelGenerator; +import models.dataFlowModel.DataTransferChannelGenerator.IResourceStateAccessor; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.StoreAttribute; + +public class JavaMethodBodyGenerator { + public static ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model, ArrayList codes) { + // Create a map from type names (lower case) to their types. + Map typeMap = new HashMap<>(); + for (CompilationUnit code: codes) { + for (TypeDeclaration type: code.types()) { + typeMap.put(type.getTypeName().substring(0,1).toLowerCase() + type.getTypeName().substring(1), type); + } + } + + // Generate the body of each update or getter method. + try { + Map> referredResources = new HashMap<>(); + for (Edge e: graph.getEdges()) { + DataFlowEdge d = (DataFlowEdge) e; + PushPullAttribute pushPull = (PushPullAttribute) d.getAttribute(); + ResourceNode src = (ResourceNode) d.getSource(); + ResourceNode dst = (ResourceNode) d.getDestination(); + String srcResourceName = src.getIdentifierTemplate().getResourceName(); + String dstResourceName = dst.getIdentifierTemplate().getResourceName(); + TypeDeclaration srcType = typeMap.get(srcResourceName); + TypeDeclaration dstType = typeMap.get(dstResourceName); + for (ChannelMember out: d.getChannelGenerator().getOutputChannelMembers()) { + if (out.getIdentifierTemplate() == dst.getIdentifierTemplate()) { + if (pushPull.getOptions().get(0) == PushPullValue.PUSH && srcType != null) { + // for push data transfer + MethodDeclaration update = getUpdateMethod(dstType, srcType); + if (((StoreAttribute) dst.getAttribute()).isStored()) { + // update stored state of dst side resource (when every incoming edge is in push style) + Expression updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); + String[] sideEffects = new String[] {""}; + String curState = updateExp.toImplementation(sideEffects); + String updateStatement; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + } else { + updateStatement = sideEffects[0] + "value = " + curState + ";"; + } + if (update.getBody() == null || !update.getBody().getStatements().contains(updateStatement)) { + update.addFirstStatement(updateStatement); + } + } + if (dst.getIndegree() > 1) { + // update a cash of src side resource (when incoming edges are multiple) + String cashStatement = "this." + srcResourceName + " = " + srcResourceName + ";"; + if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { + update.addFirstStatement(cashStatement); + } + } + MethodDeclaration getter = getGetterMethod(dstType); + if (((StoreAttribute) dst.getAttribute()).isStored()) { + // returns the current state stored in a field. + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + Type resourceType = dst.getIdentifierTemplate().getResourceStateType(); + if (model.isPrimitiveType(resourceType)) { + getter.addStatement("return value;"); + } else { + // copy the current state to be returned as a 'value' + String implTypeName = resourceType.getImplementationTypeName(); +// String interfaceTypeName = resourceType.getInterfaceTypeName(); +// String concreteTypeName; +// if (interfaceTypeName.contains("<")) { +// String typeName = implTypeName.substring(0, implTypeName.indexOf("<")); +//// String generics = interfaceTypeName.substring(interfaceTypeName.indexOf("<") + 1, interfaceTypeName.lastIndexOf(">")); +// concreteTypeName = typeName + "<>"; +// } else { +// concreteTypeName = implTypeName; +// } + getter.addStatement("return new " + implTypeName + "(value);"); + } + } + } + // src side (for a chain of update method invocations) + for (MethodDeclaration srcUpdate: getUpdateMethods(srcType)) { + String refParams = ""; + Set referredSet = referredResources.get(srcUpdate); + for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { + // to get the value of reference member. + IdentifierTemplate ref = rc.getIdentifierTemplate(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(srcUpdate, referredSet); + } + if (ref != dst.getIdentifierTemplate()) { + String refVarName = ref.getResourceName(); + if (!referredSet.contains(ref)) { + referredSet.add(ref); + Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getIdentifierTemplate()); + String[] sideEffects = new String[] {""}; + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); + srcUpdate.addFirstStatement(sideEffects[0] + refTypeName + " " + refVarName + " = " + refExp + ";"); + } + refParams += ", " + refVarName; + } + } + srcUpdate.addStatement("this." + dstResourceName + ".update" + srcType.getTypeName() + "(value" + refParams + ");"); + } + for (MethodDeclaration srcInput: getInputMethods(srcType, src, model)) { + String refParams = ""; + Set referredSet = referredResources.get(srcInput); + for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { + // to get the value of reference member. + IdentifierTemplate ref = rc.getIdentifierTemplate(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(srcInput, referredSet); + } + if (ref != dst.getIdentifierTemplate()) { + String refVarName = ref.getResourceName(); + if (!referredSet.contains(ref)) { + referredSet.add(ref); + Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getIdentifierTemplate()); + String[] sideEffects = new String[] {""}; + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); + srcInput.addFirstStatement(sideEffects[0] + refTypeName + " " + refVarName + " = " + refExp + ";"); + } + refParams += ", " + refVarName; + } + } + srcInput.addStatement("this." + dstResourceName + ".update" + srcType.getTypeName() + "(value" + refParams + ");"); + } + } else { + // for pull (or push/pull) data transfer + MethodDeclaration getter = getGetterMethod(dstType); + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + boolean isContainedPush = false; + HashMap inputIdentifierToStateAccessor = new HashMap<>(); + for (Edge eIn: dst.getInEdges()) { + DataFlowEdge dIn = (DataFlowEdge) eIn; + if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + isContainedPush = true; + inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JavaCodeGenerator.pushAccessor); + } else { + inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JavaCodeGenerator.pullAccessor); + } + } + // for reference channel members + for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { + inputIdentifierToStateAccessor.put(c.getIdentifierTemplate(), JavaCodeGenerator.pullAccessor); // by pull data transfer + } + String[] sideEffects = new String[] {""}; + // generate a return statement. + if (!isContainedPush) { + // All incoming edges are in PULL style. + String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor).toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + "return " + curState + ";"); + } else { + // At least one incoming edge is in PUSH style. + String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor, inputIdentifierToStateAccessor).toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + "return " + curState + ";"); + } + } + } + } + } + } + // for source nodes + String mainTypeName = JavaCodeGenerator.mainTypeName.substring(0,1).toLowerCase() + JavaCodeGenerator.mainTypeName.substring(1); + TypeDeclaration mainType = typeMap.get(mainTypeName); + for (Node n: graph.getNodes()) { + ResourceNode resource = (ResourceNode) n; + String resourceName = resource.getIdentifierTemplate().getResourceName(); + TypeDeclaration type = typeMap.get(resourceName); + if (type != null) { + // getter method + MethodDeclaration getter = getGetterMethod(type); + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + Type resourceType = resource.getIdentifierTemplate().getResourceStateType(); + if (model.isPrimitiveType(resourceType)) { + getter.addStatement("return value;"); + } else { + // copy the current state to be returned as a 'value' + String implTypeName = resourceType.getImplementationTypeName(); +// String interfaceTypeName = resourceType.getInterfaceTypeName(); +// String concreteTypeName; +// if (interfaceTypeName.contains("<")) { +// String typeName = implTypeName.substring(0, implTypeName.indexOf("<")); +// String generics = interfaceTypeName.substring(interfaceTypeName.indexOf("<") + 1, interfaceTypeName.lastIndexOf(">")); +// concreteTypeName = typeName + "<" + generics + ">"; +// } else { +// concreteTypeName = implTypeName; +// } + getter.addStatement("return new " + implTypeName + "(value);"); + } + } + // methods for input events + Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); + for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { + Set outs = entry.getValue(); + for (ChannelMember out: outs) { + MethodDeclaration input = getInputMethod(type, out); + if (input != null) { + String[] sideEffects = new String[] {""}; + Expression updateExp = entry.getKey().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); + String newState = updateExp.toImplementation(sideEffects); + String updateStatement; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + } else { + updateStatement = sideEffects[0] + "this.value = " + newState + ";"; + } + if (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement)) { + input.addFirstStatement(updateStatement); + } + if (mainType != null) { + MethodDeclaration mainInput = getMethod(mainType, input.getName()); + if (mainInput != null) { + String args = ""; + String delimitar = ""; + if (out.getStateTransition().getMessageExpression() instanceof Term) { + Term message = (Term) out.getStateTransition().getMessageExpression(); + for (Variable var: message.getVariables().values()) { + args += delimitar + var.getName(); + delimitar = ", "; + } + } + mainInput.addStatement("this." + resourceName + "." + input.getName() + "(" + args + ");"); + } + } + } + } + } + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e1) { + e1.printStackTrace(); + } + return codes; + } + + private static MethodDeclaration getUpdateMethod(TypeDeclaration type, TypeDeclaration from) { + for (MethodDeclaration m: type.getMethods()) { + if (m.getName().equals("update" + from.getTypeName())) return m; + } + return null; + } + + private static List getUpdateMethods(TypeDeclaration type) { + List updates = new ArrayList<>(); + for (MethodDeclaration m: type.getMethods()) { + if (m.getName().startsWith("update")) { + updates.add(m); + } + } + return updates; + } + + private static MethodDeclaration getGetterMethod(TypeDeclaration type) { + for (MethodDeclaration m: type.getMethods()) { + if (m.getName().startsWith("get")) return m; + } + return null; + } + + private static Map> getIOChannelsAndMembers(ResourceNode resource, DataTransferModel model) { + Map> ioChannelsAndMembers = new HashMap<>(); + for (ChannelGenerator c: model.getIOChannelGenerators()) { + DataTransferChannelGenerator ch = (DataTransferChannelGenerator) c; + // I/O channel + for (ChannelMember out: ch.getOutputChannelMembers()) { + if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { + if (out.getStateTransition().getMessageExpression() instanceof Term || out.getStateTransition().getMessageExpression() instanceof Variable) { + Set channelMembers = ioChannelsAndMembers.get(ch); + if (channelMembers == null) { + channelMembers = new HashSet<>(); + ioChannelsAndMembers.put(ch, channelMembers); + } + channelMembers.add(out); + } + } + } + } + return ioChannelsAndMembers; + } + + private static List getInputMethods(TypeDeclaration type, ResourceNode resource, DataTransferModel model) { + List inputs = new ArrayList<>(); + for (ChannelGenerator c: model.getIOChannelGenerators()) { + DataTransferChannelGenerator channel = (DataTransferChannelGenerator) c; + // I/O channel + for (ChannelMember out: channel.getOutputChannelMembers()) { + if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { + MethodDeclaration input = getInputMethod(type, out); + inputs.add(input); + } + } + } + return inputs; + } + + private static MethodDeclaration getInputMethod(TypeDeclaration type, ChannelMember out) { + MethodDeclaration input = null; + if (out.getStateTransition().getMessageExpression() instanceof Term) { + Term message = (Term) out.getStateTransition().getMessageExpression(); + input = getMethod(type, message.getSymbol().getImplName()); + } else if (out.getStateTransition().getMessageExpression() instanceof Variable) { + Variable message = (Variable) out.getStateTransition().getMessageExpression(); + input = getMethod(type, message.getName()); + } + return input; + } + + private static MethodDeclaration getMethod(TypeDeclaration type, String methodName) { + for (MethodDeclaration m: type.getMethods()) { + if (m.getName().equals(methodName)) return m; + } + return null; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java new file mode 100644 index 0000000..dcbd48f --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -0,0 +1,356 @@ +package generators; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import code.ast.Annotation; +import code.ast.Block; +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +import code.ast.ImportDeclaration; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; +import models.Edge; +import models.Node; +import models.algebra.Expression; +import models.algebra.Field; +import models.algebra.Parameter; +import models.algebra.Symbol; +import models.algebra.Term; +import models.algebra.Type; +import models.algebra.Variable; +import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.IdentifierTemplate; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataTransferChannelGenerator; +import models.dataFlowModel.DataTransferChannelGenerator.IResourceStateAccessor; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.StoreAttribute; + +/** + * Generator for Jersey prototypes + * + * @author Nitta + * + */ +public class JerseyCodeGenerator { + public static final Type typeVoid = new Type("Void", "void"); + public static final Type typeClient = new Type("Client", "Client"); + private static String defaultMainTypeName = "Main"; + static String mainTypeName = defaultMainTypeName; + + public static String getMainTypeName() { + return mainTypeName; + } + + public static void setMainTypeName(String mainTypeName) { + JerseyCodeGenerator.mainTypeName = mainTypeName; + } + + public static void resetMainTypeName() { + JerseyCodeGenerator.mainTypeName = defaultMainTypeName; + } + + static public ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model) { + ArrayList codes = new ArrayList<>(); +// ArrayList resources = StoreResourceCheck(graph); + Set resources = graph.getNodes(); + + for (Node n : resources) { + ResourceNode rn = (ResourceNode) n; + String resourceName = rn.getIdentifierTemplate().getResourceName().substring(0, 1).toUpperCase() + + rn.getIdentifierTemplate().getResourceName().substring(1); + + // Declare the field to refer each resource in the main type. + TypeDeclaration type = new TypeDeclaration(resourceName); + type.addAnnotation(new Annotation("Component")); + type.addAnnotation(new Annotation("Path", "\"/" + rn.getIdentifierTemplate().getResourceName() + "\"")); + + // Declare a client field and update methods from other resources. + boolean bDeclareClientField = false; + for (Edge e : rn.getOutEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + if (!bDeclareClientField && ((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // Declare a client field to connect to the destination resource of push transfer. + type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); + bDeclareClientField = true; + } + } + for (Edge e : rn.getInEdges()) { + DataFlowEdge re = (DataFlowEdge) e; + IdentifierTemplate srcRes = ((ResourceNode) re.getSource()).getIdentifierTemplate(); + String srcResName = srcRes.getResourceName().substring(0, 1).toUpperCase() + srcRes.getResourceName().substring(1); + if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + if (!bDeclareClientField) { + // Declare a client field to connect to the source resource of pull transfer. + type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); + bDeclareClientField = true; + } + } else { + // Declare an update method in the type of the destination resource. + ArrayList vars = new ArrayList<>(); + String srcName = srcRes.getResourceName(); + Type srcType = srcRes.getResourceStateType(); + VariableDeclaration param = new VariableDeclaration(srcType, srcName); + param.addAnnotation(new Annotation("FormParam", "\"" + srcName + "\"")); + vars.add(param); + for (IdentifierTemplate refRes: re.getChannelGenerator().getReferenceIdentifierTemplates()) { + if (refRes != rn.getIdentifierTemplate()) { + param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getResourceName()); + param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); + vars.add(param); + } + } + MethodDeclaration update = new MethodDeclaration("update" + srcResName, false, typeVoid, vars); + for (ChannelMember cm: re.getChannelGenerator().getOutputChannelMembers()) { + if (cm.getIdentifierTemplate() == rn.getIdentifierTemplate()) { + if (cm.getStateTransition().isRightUnary()) { + update.addAnnotation(new Annotation("PUT")); + } else { + update.addAnnotation(new Annotation("POST")); + } + } + } + if (rn.getInEdges().size() > 1) { + // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. + update.addAnnotation(new Annotation("Path", "\"/" + srcName + "\"")); + // Declare a field to cash the state of the source resource in the type of the destination resource. + IdentifierTemplate cashResId = ((ResourceNode) re.getSource()).getIdentifierTemplate(); + type.addField(new FieldDeclaration(cashResId.getResourceStateType(), srcName, getInitializer(cashResId))); + } + type.addMethod(update); + } + } + +// // Declare a client field to connect to the source resource of reference transfer. +// if (!bDeclareClientField) { +// for (ChannelGenerator cg : model.getChannelGenerators()) { +// DataflowChannelGenerator dcg = ((DataflowChannelGenerator) cg); +// for (ChannelMember cm : dcg.getOutputChannelMembers()) { +// if (cm.getIdentifierTemplate().getResourceName().equals(type.getTypeName().toLowerCase())) { +// if (dcg.getReferenceChannelMembers().size() > 0) { +// // If there exists one or more reference channel member. +// type.addField(new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()")); +// bDeclareClientField = true; +// break; +// } +// } +// } +// if (bDeclareClientField) break; +// } +// } + + // Declare input methods in resources. + for (ChannelGenerator cg : model.getIOChannelGenerators()) { + for (ChannelMember cm : ((DataTransferChannelGenerator) cg).getOutputChannelMembers()) { + if (cm.getIdentifierTemplate().equals(rn.getIdentifierTemplate())) { + Expression message = cm.getStateTransition().getMessageExpression(); + if (message.getClass() == Term.class) { + ArrayList params = new ArrayList<>(); + for (Variable var: message.getVariables().values()) { + String paramName = var.getName(); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("FormParam", "\"" + paramName + "\"")); + params.add(param); + } + MethodDeclaration input = new MethodDeclaration( + ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), + false, typeVoid, params); + if (cm.getStateTransition().isRightUnary()) { + input.addAnnotation(new Annotation("PUT")); + } else { + input.addAnnotation(new Annotation("POST")); + } + type.addMethod(input); + } else if (message.getClass() == Variable.class) { + MethodDeclaration input = new MethodDeclaration( + ((Variable) cm.getStateTransition().getMessageExpression()).getName(), + false, typeVoid, null); + if (cm.getStateTransition().isRightUnary()) { + input.addAnnotation(new Annotation("PUT")); + } else { + input.addAnnotation(new Annotation("POST")); + } + type.addMethod(input); + } + } + } + } + + // Declare the field to store the state in the type of each resource. + if (((StoreAttribute) rn.getAttribute()).isStored()) { + IdentifierTemplate resId = rn.getIdentifierTemplate(); + type.addField(new FieldDeclaration(resId.getResourceStateType(), "value", getInitializer(resId))); + } + + // Declare the getter method to obtain the state in the type of each resource. + MethodDeclaration getter = new MethodDeclaration("getValue", rn.getIdentifierTemplate().getResourceStateType()); + getter.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); + getter.addAnnotation(new Annotation("GET")); + type.addMethod(getter); + + // Add compilation unit for each resource. + CompilationUnit cu = new CompilationUnit(type); + cu.addImport(new ImportDeclaration("java.util.*")); + cu.addImport(new ImportDeclaration("javax.ws.rs.*")); + cu.addImport(new ImportDeclaration("javax.ws.rs.client.*")); + cu.addImport(new ImportDeclaration("javax.ws.rs.core.*")); + cu.addImport(new ImportDeclaration("org.springframework.stereotype.Component")); + cu.addImport(new ImportDeclaration("com.fasterxml.jackson.databind.ObjectMapper")); + cu.addImport(new ImportDeclaration("com.fasterxml.jackson.core.JsonProcessingException")); + codes.add(cu); + } + + // Declare the Pair class. + boolean isCreatedPair = false; + for(Node n : resources) { + ResourceNode rn = (ResourceNode) n; + if(isCreatedPair) continue; + if(model.getType("Pair").isAncestorOf(rn.getIdentifierTemplate().getResourceStateType())) { + TypeDeclaration type = new TypeDeclaration("Pair"); + type.addField(new FieldDeclaration(new Type("Double", "T"), "left")); + type.addField(new FieldDeclaration(new Type("Double", "T"), "right")); + + MethodDeclaration constructor = new MethodDeclaration("Pair", true); + constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "left")); + constructor.addParameter(new VariableDeclaration(new Type("Double", "T"), "right")); + Block block = new Block(); + block.addStatement("this.left = left;"); + block.addStatement("this.right = right;"); + constructor.setBody(block); + type.addMethod(constructor); + + for(FieldDeclaration field : type.getFields()) { + MethodDeclaration getter = new MethodDeclaration( + "get" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1), + new Type("Double","T")); + getter.setBody(new Block()); + getter.getBody().addStatement("return " + field.getName() + ";"); + type.addMethod(getter); + } + +// MethodDeclaration toStr = new MethodDeclaration("toString", false, DataConstraintModel.typeString, null); +// block = new Block(); +// block.addStatement("return \"{\\\"\" + left + \"\\\":\\\"\" + right + \"\\\"}\";"); +// toStr.setBody(block); +// type.addMethod(toStr); + + CompilationUnit cu = new CompilationUnit(type); + cu.addImport(new ImportDeclaration("java.util.*")); + codes.add(cu); + + isCreatedPair = true; + } + } + + return codes; + } + + private static String getInitializer(IdentifierTemplate resId) { + Type stateType = resId.getResourceStateType(); + String initializer = null; + if (resId.getInitialValue() != null) { + initializer = resId.getInitialValue().toImplementation(new String[] {""}); + } else { + if (DataConstraintModel.typeList.isAncestorOf(stateType)) { + initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + } else if (DataConstraintModel.typeMap.isAncestorOf(stateType)) { + initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + } + } + return initializer; + } + + static public ArrayList getCodes(ArrayList codeTree) { + ArrayList codes = new ArrayList<>(); + for (TypeDeclaration type : codeTree) { + codes.add("public class " + type.getTypeName() + "{"); + for (FieldDeclaration field : type.getFields()) { + if (type.getTypeName() != mainTypeName) { + String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " + + field.getName(); + if (DataConstraintModel.isListType(field.getType())) + cons += " = new " + field.getType().getImplementationTypeName() + "()"; + cons += ";"; + codes.add(cons); + } else { + String cons = "\t" + "private " + field.getType().getInterfaceTypeName() + " " + + field.getName() + " = new " + field.getType().getTypeName() + "("; + cons += ");"; + codes.add(cons); + } + } + codes.add(""); + for (MethodDeclaration method : type.getMethods()) { + String varstr = "\t" + "public " + method.getReturnType().getInterfaceTypeName() + " " + + method.getName() + "("; + if (method.getParameters() != null) { + for (VariableDeclaration var : method.getParameters()) { + varstr += var.getType().getInterfaceTypeName() + " " + var.getName() + ","; + } + if (!method.getParameters().isEmpty()) + varstr = varstr.substring(0, varstr.length() - 1); + } + if (method.getBody() != null) { + for (String str : method.getBody().getStatements()) { + codes.add("\t\t" + str + ";"); + } + } + codes.add(varstr + ")" + "{"); + codes.add("\t" + "}"); + codes.add(""); + } + codes.add("}"); + codes.add(""); + } + return codes; + } + + static public IResourceStateAccessor pushAccessor = new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + if (target.equals(from)) { + return new Field("value", + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + return null; + } + + @Override + public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + return new Parameter(target.getResourceName(), + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + }; + static public IResourceStateAccessor pullAccessor = new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + if (target.equals(from)) { + return new Field("value", + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + return new Parameter(target.getResourceName(), + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + return new Parameter(target.getResourceName(), + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + }; +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java new file mode 100644 index 0000000..6fe0efd --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -0,0 +1,597 @@ +package generators; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import algorithms.TypeInference; +import code.ast.CodeUtil; +import code.ast.CompilationUnit; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; +import models.Edge; +import models.Node; +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.Term; +import models.algebra.Type; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.algebra.Variable; +import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.IdentifierTemplate; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataTransferChannelGenerator; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.StoreAttribute; +import models.dataFlowModel.DataTransferChannelGenerator.IResourceStateAccessor; + +public class JerseyMethodBodyGenerator { + private static String baseURL = "http://localhost:8080"; + + public static ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model, ArrayList codes) { + // Create a map from type names (lower case) to their types. + Map typeMap = new HashMap<>(); + for (CompilationUnit code: codes) { + for (TypeDeclaration type: code.types()) { + typeMap.put(type.getTypeName().substring(0,1).toLowerCase() + type.getTypeName().substring(1), type); + } + } + + // Generate the body of each update or getter method. + try { + Set chainedCalls = new HashSet<>(); + Map> referredResources = new HashMap<>(); + for (Edge e: graph.getEdges()) { + DataFlowEdge d = (DataFlowEdge) e; + PushPullAttribute pushPull = (PushPullAttribute) d.getAttribute(); + ResourceNode src = (ResourceNode) d.getSource(); + ResourceNode dst = (ResourceNode) d.getDestination(); + String srcResourceName = src.getIdentifierTemplate().getResourceName(); + String dstResourceName = dst.getIdentifierTemplate().getResourceName(); + TypeDeclaration srcType = typeMap.get(srcResourceName); + TypeDeclaration dstType = typeMap.get(dstResourceName); + for (ChannelMember out: d.getChannelGenerator().getOutputChannelMembers()) { + if (out.getIdentifierTemplate() == dst.getIdentifierTemplate()) { + if (pushPull.getOptions().get(0) == PushPullValue.PUSH && srcType != null) { + // for push data transfer + MethodDeclaration update = getUpdateMethod(dstType, srcType); + if (((StoreAttribute) dst.getAttribute()).isStored()) { + // update stored state of dst side resource (when every incoming edge is in push style) + Expression updateExp = null; + if (d.getChannelGenerator().getReferenceChannelMembers().size() == 0) { + updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); + } else { + // if there exists one or more reference channel member. + HashMap inputIdentifierToStateAccessor = new HashMap<>(); + for (Edge eIn: dst.getInEdges()) { + DataFlowEdge dIn = (DataFlowEdge) eIn; + inputIdentifierToStateAccessor.put(((ResourceNode) dIn.getSource()).getIdentifierTemplate(), JerseyCodeGenerator.pushAccessor); + } + for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { + inputIdentifierToStateAccessor.put(c.getIdentifierTemplate(), JerseyCodeGenerator.pullAccessor); + } + updateExp = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputIdentifierToStateAccessor); + } + String[] sideEffects = new String[] {""}; + String curState = updateExp.toImplementation(sideEffects); + String updateStatement; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + } else { + updateStatement = sideEffects[0] + "this.value = " + curState + ";"; + } + if (update.getBody() == null || !update.getBody().getStatements().contains(updateStatement)) { + // add an update statement of the state of dst side resource. + update.addFirstStatement(updateStatement); + } + } + if (dst.getIndegree() > 1) { + // update a cash of src side resource (when incoming edges are multiple) + String cashStatement = "this." + srcResourceName + " = " + srcResourceName + ";"; + if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { + update.addFirstStatement(cashStatement); + } + } + // to convert a json param to a tuple, pair or map object. + for (VariableDeclaration param: update.getParameters()) { + Type paramType = param.getType(); + String paramName = param.getName(); + String paramConverter = ""; + if (DataConstraintModel.typeList.isAncestorOf(paramType) && paramType != DataConstraintModel.typeList) { + Type compType = TypeInference.getListComponentType(paramType); + if (DataConstraintModel.typeTuple.isAncestorOf(compType)) { + param.setType(DataConstraintModel.typeListStr); + param.setName(paramName + "_json"); + paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = new " + paramType.getImplementationTypeName() + "();\n"; + paramConverter += "for (String str: " + param.getName() + ") {\n"; + String mapTypeName = convertFromEntryToMapType(compType); + paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(str, HashMap.class);\n"; + paramConverter += "\t" + paramName + ".add(" + getCodeForConversionFromMapToTuple(compType, "i") + ");\n"; + paramConverter += "}"; + update.addThrow("JsonProcessingException"); + } else if (DataConstraintModel.typePair.isAncestorOf(compType)) { + param.setType(DataConstraintModel.typeListStr); + param.setName(paramName + "_json"); + paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = new " + paramType.getImplementationTypeName() + "();\n"; + paramConverter += "for (String str: " + param.getName() + ") {\n"; + String mapTypeName = convertFromEntryToMapType(compType); + paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(str, HashMap.class);\n"; + paramConverter += "\t" + paramName + ".add(" + getCodeForConversionFromMapToPair(compType, "i") + ");\n"; + paramConverter += "}"; + update.addThrow("JsonProcessingException"); + } else if (DataConstraintModel.typeMap.isAncestorOf(compType)) { + param.setType(DataConstraintModel.typeListStr); + // To do. + } + } else if (DataConstraintModel.typeTuple.isAncestorOf(paramType)) { + param.setType(DataConstraintModel.typeString); + param.setName(paramName + "_json"); + paramConverter += paramType.getInterfaceTypeName() + " " + paramName + ";\n"; + paramConverter += "{\n"; + String mapTypeName = convertFromEntryToMapType(paramType); + paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; + paramConverter += "\t" + paramName + " = " + getCodeForConversionFromMapToTuple(paramType, "i") + ";\n"; + paramConverter += "}"; + update.addThrow("JsonProcessingException"); + } else if (DataConstraintModel.typePair.isAncestorOf(paramType)) { + param.setType(DataConstraintModel.typeString); + param.setName(paramName + "_json"); + paramConverter += paramType.getInterfaceTypeName() + " " + paramName + ";\n"; + paramConverter += "{\n"; + String mapTypeName = convertFromEntryToMapType(paramType); + paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; + paramConverter += "\t" + paramName + " = " + getCodeForConversionFromMapToPair(paramType, "i") + ";\n"; + paramConverter += "}"; + update.addThrow("JsonProcessingException"); + } else if (DataConstraintModel.typeMap.isAncestorOf(paramType)) { + param.setType(DataConstraintModel.typeString); + param.setName(paramName + "_json"); + paramConverter += paramType.getInterfaceTypeName() + " " + paramName + " = " + "new " + paramType.getImplementationTypeName() + "();\n"; + paramConverter += "{\n"; + String mapTypeName = convertFromEntryToMapType(paramType); + paramConverter += "\t" + mapTypeName + " i = new ObjectMapper().readValue(" + paramName + "_json" + ", HashMap.class);\n"; + paramConverter += "\t" + getCodeForConversionFromMapToMap(paramType, "i", paramName) + "\n"; + paramConverter += "}"; + update.addThrow("JsonProcessingException"); + } + if (paramConverter.length() > 0) update.addFirstStatement(paramConverter); + } + MethodDeclaration getter = getGetterMethod(dstType); + if (((StoreAttribute) dst.getAttribute()).isStored()) { + // returns the state stored in a field. + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + getter.addStatement("return value;"); + } + } + // src side (for a chain of update method invocations) + String httpMethod = null; + if (out.getStateTransition().isRightUnary()) { + httpMethod = "put"; + } else { + httpMethod = "post"; + } + for (MethodDeclaration srcUpdate: getUpdateMethods(srcType)) { + if (srcUpdate != null) { + List>> params = new ArrayList<>(); + Set referredSet = referredResources.get(srcUpdate); + if (d.getChannelGenerator().getReferenceChannelMembers().size() > 0) { + for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { + // For each reference channel member, get the current state of the reference side resource by pull data transfer. + IdentifierTemplate ref = rc.getIdentifierTemplate(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(srcUpdate, referredSet); + } + if (ref != dst.getIdentifierTemplate()) { + String refResourceName = ref.getResourceName(); + Type refResourceType = ref.getResourceStateType(); + if (!referredSet.contains(ref)) { + referredSet.add(ref); + generatePullDataTransfer(srcUpdate, refResourceName, refResourceType); + } + // Value of a reference side resource. + params.add(new AbstractMap.SimpleEntry<>(refResourceType, new AbstractMap.SimpleEntry<>(refResourceName, refResourceName))); + } + } + } + String srcResName = null; + if (dst.getIndegree() > 1) { + srcResName = srcResourceName; + } + if (!chainedCalls.contains(srcUpdate)) { + // The first call to an update method in this method + // Value of the source side (input side) resource. + params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); + srcUpdate.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, true)); + srcUpdate.addStatement("String result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); + chainedCalls.add(srcUpdate); + } else { + // After the second time of call to update methods in this method + // Value of the source side (input side) resource. + params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); + srcUpdate.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, false)); + srcUpdate.addStatement("result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); + } + srcUpdate.addThrow("JsonProcessingException"); + } + } + for (MethodDeclaration srcInput: getInputMethods(srcType, src, model)) { + List>> params = new ArrayList<>(); + Set referredSet = referredResources.get(srcInput); + for (ChannelMember rc: d.getChannelGenerator().getReferenceChannelMembers()) { + // For each reference channel member, get the current state of the reference side resource by pull data transfer. + IdentifierTemplate ref = rc.getIdentifierTemplate(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(srcInput, referredSet); + } + if (ref != dst.getIdentifierTemplate()) { + String refResourceName = ref.getResourceName(); + Type refResourceType = ref.getResourceStateType(); + if (!referredSet.contains(ref)) { + referredSet.add(ref); + generatePullDataTransfer(srcInput, refResourceName, refResourceType); + } + // Value of a reference side resource. + params.add(new AbstractMap.SimpleEntry<>(refResourceType, new AbstractMap.SimpleEntry<>(refResourceName, refResourceName))); + } + } + String srcResName = null; + if (dst.getIndegree() > 1) { + srcResName = srcResourceName; + } + if (!chainedCalls.contains(srcInput)) { + // First call to an update method in this method + // Value of the source side (input side) resource. + params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); + srcInput.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, true)); + srcInput.addStatement("String result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); + chainedCalls.add(srcInput); + } else { + // After the second time of call to update methods in this method + // Value of the source side (input side) resource. + params.add(0, new AbstractMap.SimpleEntry<>(src.getIdentifierTemplate().getResourceStateType(), new AbstractMap.SimpleEntry<>(srcResourceName, "this.value"))); + srcInput.addStatement(getHttpMethodParamsStatement(srcType.getTypeName(), params, false)); + srcInput.addStatement("result = " + getHttpMethodCallStatement(baseURL, dstResourceName, srcResName, httpMethod)); + } + srcInput.addThrow("JsonProcessingException"); + } + } else { + // for pull (or push/pull) data transfer + MethodDeclaration getter = getGetterMethod(dstType); + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + // generate a return statement. + String[] sideEffects = new String[] {""}; + String curState = d.getChannelGenerator().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pullAccessor).toImplementation(sideEffects); // no pull data transfer is included. + getter.addStatement(sideEffects[0] + "return " + curState + ";"); + // For each reference channel member, get the current state of the reference side resource by pull data transfer. + for (ChannelMember c: d.getChannelGenerator().getReferenceChannelMembers()) { + String refResourceName = c.getIdentifierTemplate().getResourceName(); + Type refResourceType = c.getIdentifierTemplate().getResourceStateType(); + generatePullDataTransfer(getter, refResourceName, refResourceType); + } + } + // get src side resource state by pull data transfer. + Type srcResourceType = src.getIdentifierTemplate().getResourceStateType(); + generatePullDataTransfer(getter, srcResourceName, srcResourceType); + } + } + } + } + // for source nodes + for (Node n: graph.getNodes()) { + ResourceNode resource = (ResourceNode) n; + String resourceName = resource.getIdentifierTemplate().getResourceName(); + TypeDeclaration type = typeMap.get(resourceName); + if (type != null) { + // getter method + MethodDeclaration getter = getGetterMethod(type); + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + getter.addStatement("return value;"); + } + // methods for input events + Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); + for (Map.Entry> entry: ioChannelsAndMembers.entrySet()) { + Set outs = entry.getValue(); + for (ChannelMember out: outs) { + MethodDeclaration input = getInputMethod(type, out); + if (input != null) { + Expression updateExp = entry.getKey().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); + String[] sideEffects = new String[] {""}; + String newState = updateExp.toImplementation(sideEffects); + String updateStatement; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + } else { + updateStatement = sideEffects[0] + "this.value = " + newState + ";"; + } + if (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement)) { + input.addFirstStatement(updateStatement); + } + } + } + } + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e1) { + e1.printStackTrace(); + } + return codes; + } + + private static void generatePullDataTransfer(MethodDeclaration methodBody, String fromResourceName, Type fromResourceType) { + String varName = new String(fromResourceName); + String respTypeName = fromResourceType.getInterfaceTypeName(); + String respImplTypeName = fromResourceType.getImplementationTypeName(); + String respConverter = ""; + if (DataConstraintModel.typeList.isAncestorOf(fromResourceType) && fromResourceType != DataConstraintModel.typeList) { + Type compType = TypeInference.getListComponentType(fromResourceType); + if (DataConstraintModel.typeTuple.isAncestorOf(compType)) { + varName += "_json"; + String mapTypeName = convertFromEntryToMapType(compType); + respTypeName = "List<" + mapTypeName + ">"; + respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = new " + fromResourceType.getImplementationTypeName() + "();\n"; + respConverter += "for (" + mapTypeName + " i: " + varName + ") {\n"; + respConverter += "\t" + fromResourceName + ".add(" + getCodeForConversionFromMapToTuple(compType, "i") + ");\n"; + respConverter += "}"; + methodBody.addThrow("JsonProcessingException"); + } else if (DataConstraintModel.typeMap.isAncestorOf(compType)) { + // To do. + } + } else if (DataConstraintModel.typeTuple.isAncestorOf(fromResourceType)) { + varName += "_json"; + respTypeName = convertFromEntryToMapType(fromResourceType); + respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = " + getCodeForConversionFromMapToTuple(fromResourceType, varName) + ";"; + respImplTypeName = "HashMap"; + } else if (DataConstraintModel.typePair.isAncestorOf(fromResourceType)) { + varName += "_json"; + respTypeName = convertFromEntryToMapType(fromResourceType); + respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = " + getCodeForConversionFromMapToPair(fromResourceType, varName) + ";"; + respImplTypeName = "HashMap"; + } else if (DataConstraintModel.typeMap.isAncestorOf(fromResourceType)) { + varName += "_json"; + respTypeName = convertFromEntryToMapType(fromResourceType); + respConverter += fromResourceType.getInterfaceTypeName() + " " + fromResourceName + " = new " + fromResourceType.getImplementationTypeName() + "();\n"; + respConverter += getCodeForConversionFromMapToMap(fromResourceType, varName, fromResourceName); + respImplTypeName = "HashMap"; + } + if (respConverter.length() > 0) { + methodBody.addFirstStatement(respConverter); + } + methodBody.addFirstStatement(respTypeName + " " + varName + " = " + getHttpMethodCallStatementWithResponse(baseURL, fromResourceName, "get", respImplTypeName)); + } + + private static String convertFromEntryToMapType(Type type) { + String mapTypeName = null; + if (DataConstraintModel.typePair.isAncestorOf(type)) { + Type compType = TypeInference.getPairComponentType(type); + String wrapperType = DataConstraintModel.getWrapperType(compType); + if (wrapperType != null) { + mapTypeName = "Map"; + } else { + mapTypeName = "Map"; + } + } else if (DataConstraintModel.typeMap.isAncestorOf(type)) { + List compTypes = TypeInference.getMapComponentTypes(type); + String wrapperType = DataConstraintModel.getWrapperType(compTypes.get(1)); + if (wrapperType != null) { + mapTypeName = "Map"; + } else { + mapTypeName = "Map"; + } + } else { + mapTypeName = type.getInterfaceTypeName(); + mapTypeName = mapTypeName.replace("Map.Entry", "Map"); + for (int idx = mapTypeName.indexOf("<", 0); idx >= 0; idx = mapTypeName.indexOf("<", idx + 1)) { + int to = mapTypeName.indexOf(",", idx); + if (to > idx) { + mapTypeName = mapTypeName.substring(0, idx + 1) + "String" + mapTypeName.substring(to); // All elements except for the last one have the string type. + } + } + } + return mapTypeName; + } + + private static String getCodeForConversionFromMapToTuple(Type tupleType, String mapVar) { + String decoded = "$x"; + List elementsTypes = TypeInference.getTupleComponentTypes(tupleType); + String elementBase = mapVar; + for (Type elmType: elementsTypes.subList(0, elementsTypes.size() - 1)) { + elementBase += ".entrySet().iterator().next()"; + if (elmType == DataConstraintModel.typeBoolean + || elmType == DataConstraintModel.typeInt + || elmType == DataConstraintModel.typeLong + || elmType == DataConstraintModel.typeFloat + || elmType == DataConstraintModel.typeDouble) { + String elmVal = CodeUtil.getToValueExp(elmType.getImplementationTypeName(), elementBase + ".getKey()"); + decoded = decoded.replace("$x", "new AbstractMap.SimpleEntry<>(" + elmVal + ", $x)"); + } else if (elmType == DataConstraintModel.typeString) { + decoded = decoded.replace("$x", "new AbstractMap.SimpleEntry<>(" + elementBase + ".getKey(), $x)"); + } else { + // To do. + } + elementBase += ".getValue()"; + } + decoded = decoded.replace("$x", elementBase); + return decoded; + } + + private static String getCodeForConversionFromMapToPair(Type pairType, String mapVar) { + String decoded = "$x"; + decoded = decoded.replace("$x", "new Pair<>(" + mapVar + ".get(\"left\"), $x)"); + decoded = decoded.replace("$x", mapVar + ".get(\"right\")"); + return decoded; + } + + private static String getCodeForConversionFromMapToMap(Type mapType, String mapVal, String mapVar) { + List elementsTypes = TypeInference.getMapComponentTypes(mapType); + Type keyType = elementsTypes.get(0); + Type valType = elementsTypes.get(1); + String keyVal = null; + String decoded = ""; + if (keyType == DataConstraintModel.typeBoolean + || keyType == DataConstraintModel.typeInt + || keyType == DataConstraintModel.typeLong + || keyType == DataConstraintModel.typeFloat + || keyType == DataConstraintModel.typeDouble) { + decoded += "for (String k: " + mapVal + ".keySet()) {\n"; + decoded += "\t" + mapVar + ".put("; + keyVal = CodeUtil.getToValueExp(keyType.getImplementationTypeName(), "k"); + decoded += keyVal + ", " + mapVal + ".get(" + keyVal + ")" + ");\n"; + decoded += "}"; + } else if (keyType == DataConstraintModel.typeString) { + decoded += mapVar + " = " + mapVal + ";"; + } + return decoded; + } + + private static String getHttpMethodParamsStatement(String callerResourceName, List>> params, boolean isFirstCall) { + String statements = ""; + if (isFirstCall) { + statements += "Form "; + } + statements += "form = new Form();\n"; + for (Map.Entry> param: params) { + Type paramType = param.getKey(); + String paramName = param.getValue().getKey(); + String value = param.getValue().getValue(); + if (DataConstraintModel.typeList.isAncestorOf(paramType)) { + Type compType = TypeInference.getListComponentType(paramType); + String wrapperType = DataConstraintModel.getWrapperType(compType); + if (wrapperType == null) { + statements += "for (" + compType.getInterfaceTypeName() + " i: " + value + ") {\n"; + } else { + statements += "for (" + wrapperType + " i: " + value + ") {\n"; + } + if (DataConstraintModel.typeTuple.isAncestorOf(compType) || DataConstraintModel.typePair.isAncestorOf(paramType) || DataConstraintModel.typeList.isAncestorOf(compType) || DataConstraintModel.typeMap.isAncestorOf(paramType)) { + statements += "\tform.param(\"" + paramName + "\", new ObjectMapper().writeValueAsString(i));\n"; // typeTuple: {"1.0":2.0}, typePair: {"left": 1.0, "right":2.0} + } else { + statements += "\tform.param(\"" + paramName + "\", i.toString());\n"; + } + statements += "}\n"; +// return "Entity entity = Entity.entity(" + paramName + ".toString(), MediaType.APPLICATION_JSON);"; + } else if (DataConstraintModel.typeTuple.isAncestorOf(paramType) || DataConstraintModel.typePair.isAncestorOf(paramType) || DataConstraintModel.typeMap.isAncestorOf(paramType)) { + // typeTuple: {"1.0":2.0}, typePair: {"left": 1.0, "right":2.0} + statements += "form.param(\"" + paramName + "\", new ObjectMapper().writeValueAsString(" + value + "));\n"; + } else { + statements += "form.param(\"" + paramName + "\", " + CodeUtil.getToStringExp(paramType.getImplementationTypeName(), value) + ");\n"; + } + } + if (isFirstCall) { + statements += "Entity "; + } + statements += "entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED);"; + return statements; + } + + private static String getHttpMethodCallStatement(String baseURL, String resourceName, String srcResName, String httpMethod) { + if (srcResName == null) { + return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(entity, String.class);"; + } else { + // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. + return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "/" + srcResName + "\").request()." + httpMethod + "(entity, String.class);"; + } + } + + private static String getHttpMethodCallStatementWithResponse(String baseURL, String resourceName, String httpMethod, String respImplName) { + String responseShortTypeName = respImplName; + if (respImplName.contains("<")) { + responseShortTypeName = respImplName.substring(0, respImplName.indexOf("<")); + } + return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(" + responseShortTypeName + ".class);"; + } + + private static MethodDeclaration getUpdateMethod(TypeDeclaration type, TypeDeclaration from) { + for (MethodDeclaration m: type.getMethods()) { + if (m.getName().equals("update" + from.getTypeName())) return m; + } + return null; + } + + private static List getUpdateMethods(TypeDeclaration type) { + List updates = new ArrayList<>(); + for (MethodDeclaration m: type.getMethods()) { + if (m.getName().startsWith("update")) { + updates.add(m); + } + } + return updates; + } + + private static MethodDeclaration getGetterMethod(TypeDeclaration type) { + for (MethodDeclaration m: type.getMethods()) { + if (m.getName().startsWith("get")) return m; + } + return null; + } + + private static Map> getIOChannelsAndMembers(ResourceNode resource, DataTransferModel model) { + Map> ioChannelsAndMembers = new HashMap<>(); + for (ChannelGenerator c: model.getIOChannelGenerators()) { + DataTransferChannelGenerator ch = (DataTransferChannelGenerator) c; + // I/O channel + for (ChannelMember out: ch.getOutputChannelMembers()) { + if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { + if (out.getStateTransition().getMessageExpression() instanceof Term || out.getStateTransition().getMessageExpression() instanceof Variable) { + Set channelMembers = ioChannelsAndMembers.get(ch); + if (channelMembers == null) { + channelMembers = new HashSet<>(); + ioChannelsAndMembers.put(ch, channelMembers); + } + channelMembers.add(out); + } + } + } + } + return ioChannelsAndMembers; + } + + private static List getInputMethods(TypeDeclaration type, ResourceNode resource, DataTransferModel model) { + List inputs = new ArrayList<>(); + for (ChannelGenerator c: model.getIOChannelGenerators()) { + DataTransferChannelGenerator channel = (DataTransferChannelGenerator) c; + // I/O channel + for (ChannelMember out: channel.getOutputChannelMembers()) { + if (out.getIdentifierTemplate().equals(resource.getIdentifierTemplate())) { + MethodDeclaration input = getInputMethod(type, out); + inputs.add(input); + } + } + } + return inputs; + } + + private static MethodDeclaration getInputMethod(TypeDeclaration type, ChannelMember out) { + MethodDeclaration input = null; + if (out.getStateTransition().getMessageExpression() instanceof Term) { + Term message = (Term) out.getStateTransition().getMessageExpression(); + input = getMethod(type, message.getSymbol().getImplName()); + } else if (out.getStateTransition().getMessageExpression() instanceof Variable) { + Variable message = (Variable) out.getStateTransition().getMessageExpression(); + input = getMethod(type, message.getName()); + } + return input; + } + + private static MethodDeclaration getMethod(TypeDeclaration type, String methodName) { + for (MethodDeclaration m: type.getMethods()) { + if (m.getName().equals(methodName)) return m; + } + return null; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JavaPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JavaPrototypeGenerateAction.java index 53939bd..60ca2f1 100644 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JavaPrototypeGenerateAction.java +++ b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JavaPrototypeGenerateAction.java @@ -12,11 +12,14 @@ import algorithms.*; import code.ast.*; +import generators.DataTransferMethodAnalyzer; +import generators.JavaCodeGenerator; +import generators.JavaMethodBodyGenerator; import graphicalrefactor.editor.Editor; import models.dataConstraintModel.IdentifierTemplate; -import models.dataFlowModel.DataFlowModel; +import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.ModelExtension; -import models.dataFlowModel.ResourceDependencyGraph; +import models.dataFlowModel.DataFlowGraph; public class JavaPrototypeGenerateAction extends AbstractEditorAction { /** @@ -32,12 +35,12 @@ @Override public void actionPerformed(ActionEvent e) { - ResourceDependencyGraph graph = editor.getResourceDependencyGraph(); + DataFlowGraph graph = editor.getDataFlowGraph(); if (graph != null) { - DataFlowModel model = editor.getModel(); - FinalDecisionOfStoringResourceStates.doDecide(graph); + DataTransferModel model = editor.getModel(); ModelExtension.extendModel(model); - TypeInference.infer(graph, model); + TypeInference.infer(model); + DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); String fileName = editor.getCurFileName(); if (fileName == null) fileName = "Main"; String mainTypeName = fileName.split("\\.")[0]; diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JerseyPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JerseyPrototypeGenerateAction.java index dfa7a57..083c690 100644 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JerseyPrototypeGenerateAction.java +++ b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/JerseyPrototypeGenerateAction.java @@ -12,12 +12,15 @@ import algorithms.*; import code.ast.*; +import generators.DataTransferMethodAnalyzer; +import generators.JerseyCodeGenerator; +import generators.JerseyMethodBodyGenerator; import graphicalrefactor.editor.Editor; import models.algebra.Type; import models.dataConstraintModel.IdentifierTemplate; -import models.dataFlowModel.DataFlowModel; +import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.ModelExtension; -import models.dataFlowModel.ResourceDependencyGraph; +import models.dataFlowModel.DataFlowGraph; public class JerseyPrototypeGenerateAction extends AbstractEditorAction { /** @@ -33,12 +36,12 @@ @Override public void actionPerformed(ActionEvent e) { - ResourceDependencyGraph graph = editor.getResourceDependencyGraph(); + DataFlowGraph graph = editor.getDataFlowGraph(); if (graph != null) { - DataFlowModel model = editor.getModel(); - FinalDecisionOfStoringResourceStates.doDecide(graph); + DataTransferModel model = editor.getModel(); ModelExtension.extendModel(model); - TypeInference.infer(graph, model); + TypeInference.infer(model); + DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); String fileName = editor.getCurFileName(); if (fileName == null) fileName = "Main"; String mainTypeName = fileName.split("\\.")[0]; diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewChannelAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewChannelAction.java index 9d8f747..9328f5f 100644 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewChannelAction.java +++ b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewChannelAction.java @@ -5,7 +5,7 @@ import javax.swing.JOptionPane; import graphicalrefactor.editor.Editor; -import models.dataFlowModel.DataflowChannelGenerator; +import models.dataFlowModel.DataTransferChannelGenerator; public class NewChannelAction extends AbstractEditorAction { @@ -22,7 +22,7 @@ public void actionPerformed(ActionEvent e) { String channelName = JOptionPane.showInputDialog("Channel Name:"); if (channelName == null) return; - editor.addChannelGenerator(new DataflowChannelGenerator(channelName)); + editor.addChannelGenerator(new DataTransferChannelGenerator(channelName)); } } diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewIOChannelAction.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewIOChannelAction.java index 7e2c884..6b3bf66 100644 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewIOChannelAction.java +++ b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/actions/NewIOChannelAction.java @@ -6,7 +6,7 @@ import graphicalrefactor.editor.Editor; -import models.dataFlowModel.DataflowChannelGenerator; +import models.dataFlowModel.DataTransferChannelGenerator; public class NewIOChannelAction extends AbstractEditorAction { @@ -23,7 +23,7 @@ public void actionPerformed(ActionEvent e) { String channelName = JOptionPane.showInputDialog("I/O Channel Name:"); if (channelName == null) return; - editor.addIOChannelGenerator(new DataflowChannelGenerator(channelName)); + editor.addIOChannelGenerator(new DataTransferChannelGenerator(channelName)); } } diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/editor/Editor.java index b8e8984..bc27ce5 100644 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/editor/Editor.java @@ -27,9 +27,8 @@ import com.mxgraph.view.mxGraph; import com.mxgraph.view.mxGraphView; -import algorithms.NecessityOfStoringResourceStates; -import algorithms.SelectableDataTransfers; -import algorithms.UpdateConflictCheck; +import algorithms.DataTransferModelAnalyzer; +import algorithms.Validation; import code.ast.CompilationUnit; import graphicalrefactor.layouts.*; import models.Edge; @@ -38,11 +37,11 @@ import models.dataConstraintModel.ChannelGenerator; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.IdentifierTemplate; -import models.dataFlowModel.DataFlowModel; -import models.dataFlowModel.DataflowChannelGenerator; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataTransferChannelGenerator; import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.ResourceDependency; -import models.dataFlowModel.ResourceDependencyGraph; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; import models.dataFlowModel.ResourceNode; import models.visualModel.FormulaChannelGenerator; import parser.Parser; @@ -74,10 +73,10 @@ protected String curFilePath = null; protected ArrayList codes = null; - protected DataFlowModel model = null; + protected DataTransferModel model = null; protected mxGraph graph = null; - protected ResourceDependencyGraph resourceDependencyGraph = null; + protected DataFlowGraph dataFlowGraph = null; public Editor(mxGraph graph) { @@ -92,33 +91,33 @@ this.graph = graph; } - public DataFlowModel getModel() { + public DataTransferModel getModel() { if (model == null) { - model = new DataFlowModel(); + model = new DataTransferModel(); } return model; } - public ResourceDependencyGraph getResourceDependencyGraph() { - if (resourceDependencyGraph == null) { - updateResourceDependencyGraph(getModel()); + public DataFlowGraph getDataFlowGraph() { + if (dataFlowGraph == null) { + analyzeDataTransferModel(getModel()); } - return resourceDependencyGraph; + return dataFlowGraph; } - public ResourceDependencyGraph updateResourceDependencyGraph(DataFlowModel model) { - ResourceDependencyGraph resourceGraph = NecessityOfStoringResourceStates.doDecide(model); - resourceDependencyGraph = SelectableDataTransfers.init(resourceGraph); - updateEdgeAttiributes(resourceDependencyGraph); - return resourceDependencyGraph; + public DataFlowGraph analyzeDataTransferModel(DataTransferModel model) { + DataFlowGraph flowGraph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); + dataFlowGraph = DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(flowGraph); + updateEdgeAttiributes(dataFlowGraph); + return dataFlowGraph; } - public void resetResourceDependencyGraph() { - resourceDependencyGraph = null; + public void resetDataFlowGraph() { + dataFlowGraph = null; } - public void setResourceDependencyGraph(ResourceDependencyGraph resourceDependencyGraph) { - this.resourceDependencyGraph = resourceDependencyGraph; + public void setDataFlowGraph(DataFlowGraph dataFlowGraph) { + this.dataFlowGraph = dataFlowGraph; } public ArrayList getCodes() { @@ -145,7 +144,7 @@ public void clear() { model = null; ((mxGraphModel) graph.getModel()).clear(); - resourceDependencyGraph = null; + dataFlowGraph = null; curFilePath = null; curFileName = null; codes = null; @@ -156,7 +155,7 @@ * @param file given file * @return a constructed DataFlowModel */ - public DataFlowModel open(File file) { + public DataTransferModel open(File file) { try { String extension =""; @@ -177,8 +176,8 @@ parserDTRAM.doParseGeometry(graph); curFilePath = file.getAbsolutePath(); curFileName = file.getName(); - if (!UpdateConflictCheck.run(model)) return null; - updateResourceDependencyGraph(model); + if (!Validation.checkUpdateConflict(model)) return null; + analyzeDataTransferModel(model); return model; } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression @@ -193,7 +192,7 @@ return null; } - public DataFlowModel openModel(File file) { + public DataTransferModel openModel(File file) { try { Parser parser = new Parser(new BufferedReader(new FileReader(file))); @@ -202,9 +201,9 @@ model = parser.doParse(); curFilePath = file.getAbsolutePath(); curFileName = file.getName(); - if (!UpdateConflictCheck.run(model)) return null; + if (!Validation.checkUpdateConflict(model)) return null; graph = constructGraph(model); - updateResourceDependencyGraph(model); + analyzeDataTransferModel(model); return model; } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression @@ -312,10 +311,10 @@ /** * Construct a mxGraph from DataFlowModel and DataFlowModel * @param model - * @param resourceDependencyGraph + * @param dataFlowGraph * @return constructed mxGraph */ - public mxGraph constructGraph(DataFlowModel model) { + public mxGraph constructGraph(DataTransferModel model) { ((mxGraphModel) graph.getModel()).clear(); Object parent = graph.getDefaultParent(); graph.getModel().beginUpdate(); @@ -328,13 +327,13 @@ geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); geo2.setRelative(true); - Map channelsIn = new HashMap<>(); - Map channelsOut = new HashMap<>(); + Map channelsIn = new HashMap<>(); + Map channelsOut = new HashMap<>(); Map resources = new HashMap<>(); // create channel vertices for (ChannelGenerator c: model.getChannelGenerators()) { - DataflowChannelGenerator channelGen = (DataflowChannelGenerator) c; + DataTransferChannelGenerator channelGen = (DataTransferChannelGenerator) c; if (channelsIn.get(channelGen) == null || channelsOut.get(channelGen) == null) { Object channel = graph.insertVertex(parent, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); @@ -358,7 +357,7 @@ // add input, output and reference edges for (ChannelGenerator ch: model.getChannelGenerators()) { - DataflowChannelGenerator channelGen = (DataflowChannelGenerator) ch; + DataTransferChannelGenerator channelGen = (DataTransferChannelGenerator) ch; // input edge for (IdentifierTemplate srcRes: channelGen.getInputIdentifierTemplates()) { graph.insertEdge(parent, null, new SrcDstAttribute(srcRes, channelGen), resources.get(srcRes), channelsIn.get(channelGen), "movable=false"); @@ -379,8 +378,8 @@ mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); port_out.setVertex(true); graph.addCell(port_out, channel); // insert the output port of a channel - channelsOut.put((DataflowChannelGenerator) ioChannelGen, port_out); - for (IdentifierTemplate outRes: ((DataflowChannelGenerator) ioChannelGen).getOutputIdentifierTemplates()) { + channelsOut.put((DataTransferChannelGenerator) ioChannelGen, port_out); + for (IdentifierTemplate outRes: ((DataTransferChannelGenerator) ioChannelGen).getOutputIdentifierTemplates()) { graph.insertEdge(parent, null, null, port_out, resources.get(outRes), "movable=false"); } } @@ -404,23 +403,23 @@ } } - public void updateEdgeAttiributes(ResourceDependencyGraph resourceDependencyGraph) { + public void updateEdgeAttiributes(DataFlowGraph dataFlowGraph) { Object parent = graph.getDefaultParent(); graph.getModel().beginUpdate(); try { // add input, output and reference edges - for (Edge e : resourceDependencyGraph.getEdges()) { - if (e instanceof ResourceDependency) { - ResourceDependency dependency = (ResourceDependency) e; - DataflowChannelGenerator channelGen = dependency.getChannelGenerator(); - ResourceNode srcRes = (ResourceNode) dependency.getSource(); + for (Edge e : dataFlowGraph.getEdges()) { + if (e instanceof DataFlowEdge) { + DataFlowEdge dataFlow = (DataFlowEdge) e; + DataTransferChannelGenerator channelGen = dataFlow.getChannelGenerator(); + ResourceNode srcRes = (ResourceNode) dataFlow.getSource(); // input edge for (Object edge: graph.getChildEdges(parent)) { mxCell edgeCell = (mxCell) edge; if (edgeCell.getValue() instanceof SrcDstAttribute) { SrcDstAttribute edgeAttr = (SrcDstAttribute) edgeCell.getValue(); if (edgeAttr.getSrouce() == srcRes.getIdentifierTemplate() && edgeAttr.getDestination() == channelGen) { - edgeCell.setValue(dependency.getAttribute()); + edgeCell.setValue(dataFlow.getAttribute()); break; } } @@ -460,7 +459,7 @@ public void addIdentifierTemplate(IdentifierTemplate res) { getModel().addIdentifierTemplate(res); - resetResourceDependencyGraph(); + resetDataFlowGraph(); graph.getModel().beginUpdate(); Object parent = graph.getDefaultParent(); try { @@ -471,9 +470,9 @@ } } - public void addChannelGenerator(DataflowChannelGenerator channelGen) { + public void addChannelGenerator(DataTransferChannelGenerator channelGen) { getModel().addChannelGenerator(channelGen); - resetResourceDependencyGraph(); + resetDataFlowGraph(); graph.getModel().beginUpdate(); Object parent = graph.getDefaultParent(); try { @@ -497,9 +496,9 @@ } } - public void addIOChannelGenerator(DataflowChannelGenerator ioChannelGen) { + public void addIOChannelGenerator(DataTransferChannelGenerator ioChannelGen) { getModel().addIOChannelGenerator(ioChannelGen); - resetResourceDependencyGraph(); + resetDataFlowGraph(); graph.getModel().beginUpdate(); Object parent = graph.getDefaultParent(); try { @@ -518,7 +517,7 @@ public void addFormulaChannelGenerator(FormulaChannelGenerator formulaChannelGen) { getModel().addChannelGenerator(formulaChannelGen); - resetResourceDependencyGraph(); + resetDataFlowGraph(); graph.getModel().beginUpdate(); Object parent = graph.getDefaultParent(); try { @@ -543,7 +542,7 @@ } public boolean connectEdge(mxCell edge, mxCell src, mxCell dst) { - DataFlowModel model = getModel(); + DataTransferModel model = getModel(); ChannelGenerator srcCh = model.getChannelGenerator((String) src.getValue()); if (srcCh == null) { srcCh = model.getIOChannelGenerator((String) src.getValue()); @@ -553,9 +552,9 @@ if (srcRes == null || dstCh == null) return false; // resource to channel edge ChannelMember srcCm = new ChannelMember(srcRes); - ((DataflowChannelGenerator ) dstCh).addChannelMemberAsInput(srcCm); + ((DataTransferChannelGenerator ) dstCh).addChannelMemberAsInput(srcCm); edge.setValue(new SrcDstAttribute(srcRes, dstCh)); - resetResourceDependencyGraph(); + resetDataFlowGraph(); return true; } } @@ -563,9 +562,9 @@ if (dstRes == null) return false; // channel to resource edge ChannelMember dstCm = new ChannelMember(dstRes); - ((DataflowChannelGenerator) srcCh).addChannelMemberAsOutput(dstCm); + ((DataTransferChannelGenerator) srcCh).addChannelMemberAsOutput(dstCm); edge.setValue(new SrcDstAttribute(srcCh, dstRes)); - resetResourceDependencyGraph(); + resetDataFlowGraph(); return true; } @@ -599,10 +598,10 @@ } } graph.removeCells(graph.getSelectionCells()); - resetResourceDependencyGraph(); + resetDataFlowGraph(); } - public void setChannelCode(DataflowChannelGenerator ch, String code) { + public void setChannelCode(DataTransferChannelGenerator ch, String code) { ch.setSourceText(code); TokenStream stream = new Parser.TokenStream(); Parser parser = new Parser(stream); @@ -611,7 +610,7 @@ stream.addLine(line); } try { - DataflowChannelGenerator ch2 = parser.parseChannel(getModel()); + DataTransferChannelGenerator ch2 = parser.parseChannel(getModel()); for (ChannelMember chm2: ch2.getInputChannelMembers()) { for (ChannelMember chm: ch.getInputChannelMembers()) { if (chm2.getIdentifierTemplate() == chm.getIdentifierTemplate()) { @@ -636,7 +635,7 @@ } } } - resetResourceDependencyGraph(); + resetDataFlowGraph(); } catch (ExpectedRightBracket | ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression | WrongRHSExpression | ExpectedAssignment e) { diff --git a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactorCellEditor.java b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactorCellEditor.java index a4d1d06..606c7e4 100644 --- a/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactorCellEditor.java +++ b/AlgebraicDataflowArchitectureModel/src/graphicalrefactor/views/GraphicalRefactorCellEditor.java @@ -24,8 +24,8 @@ import graphicalrefactor.editor.Editor; import models.algebra.Expression; -import models.dataFlowModel.DataFlowModel; -import models.dataFlowModel.DataflowChannelGenerator; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataTransferChannelGenerator; import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; import models.visualModel.FormulaChannelGenerator; @@ -65,10 +65,10 @@ } if (!graphComponent.getGraph().getModel().isEdge(cell)) { - DataFlowModel model = editor.getModel(); - DataflowChannelGenerator ch = (DataflowChannelGenerator) model.getChannelGenerator((String) ((mxCell) cell).getValue()); + DataTransferModel model = editor.getModel(); + DataTransferChannelGenerator ch = (DataTransferChannelGenerator) model.getChannelGenerator((String) ((mxCell) cell).getValue()); if (ch == null) { - ch = (DataflowChannelGenerator) model.getIOChannelGenerator((String) ((mxCell) cell).getValue()); + ch = (DataTransferChannelGenerator) model.getIOChannelGenerator((String) ((mxCell) cell).getValue()); if(ch == null) { //resource return; diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowEdge.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowEdge.java new file mode 100644 index 0000000..3c3b25f --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowEdge.java @@ -0,0 +1,20 @@ +package models.dataFlowModel; + +import models.*; + +public class DataFlowEdge extends Edge { + protected DataTransferChannelGenerator channelGenerator = null; + + public DataFlowEdge(ResourceNode src, ResourceNode dst, DataTransferChannelGenerator channelGenerator) { + super(src, dst); + this.channelGenerator = channelGenerator; + } + + public DataTransferChannelGenerator getChannelGenerator() { + return channelGenerator; + } + + public String toString() { + return channelGenerator.getChannelName(); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java new file mode 100644 index 0000000..5df4229 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java @@ -0,0 +1,40 @@ +package models.dataFlowModel; + +import java.util.HashMap; +import java.util.Map; + +import models.DirectedGraph; +import models.dataConstraintModel.IdentifierTemplate; + +public class DataFlowGraph extends DirectedGraph { + protected Map nodeMap = null; + + public DataFlowGraph() { + super(); + nodeMap = new HashMap<>(); + } + + public void addNode(IdentifierTemplate id) { + if (nodeMap.get(id) == null) { + ResourceNode node = new ResourceNode(id); + addNode(node); + nodeMap.put(id, node); + } + } + + public void addEdge(IdentifierTemplate in, IdentifierTemplate out, DataTransferChannelGenerator dfChannelGen) { + ResourceNode srcNode = nodeMap.get(in); + if (srcNode == null) { + srcNode = new ResourceNode(in); + addNode(srcNode); + nodeMap.put(in, srcNode); + } + ResourceNode dstNode = nodeMap.get(out); + if (dstNode == null) { + dstNode = new ResourceNode(out); + addNode(dstNode); + nodeMap.put(out, dstNode); + } + addEdge(new DataFlowEdge(srcNode, dstNode, dfChannelGen)); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowModel.java deleted file mode 100644 index ae21ae2..0000000 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowModel.java +++ /dev/null @@ -1,31 +0,0 @@ -package models.dataFlowModel; - -import java.util.Set; - -import models.dataConstraintModel.ChannelGenerator; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.IdentifierTemplate; - -public class DataFlowModel extends DataConstraintModel { - public ResourceDependencyGraph getResourceDependencyGraph() { - ResourceDependencyGraph resourceDependencyGraph = new ResourceDependencyGraph(); - for (ChannelGenerator channelGen: getChannelGenerators()) { - DataflowChannelGenerator dfChannelGen = (DataflowChannelGenerator)channelGen; - Set inputResources = dfChannelGen.getInputIdentifierTemplates(); - Set outputResources = dfChannelGen.getOutputIdentifierTemplates(); - for (IdentifierTemplate in: inputResources) { - for (IdentifierTemplate out: outputResources) { - resourceDependencyGraph.addEdge(in ,out, dfChannelGen); - } - } - } - for (ChannelGenerator channelGen: getIOChannelGenerators()) { - DataflowChannelGenerator dfChannelGen = (DataflowChannelGenerator)channelGen; - Set outputResources = dfChannelGen.getOutputIdentifierTemplates(); - for (IdentifierTemplate out: outputResources) { - resourceDependencyGraph.addNode(out); - } - } - return resourceDependencyGraph; - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannelGenerator.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannelGenerator.java new file mode 100644 index 0000000..1426ac7 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannelGenerator.java @@ -0,0 +1,273 @@ +package models.dataFlowModel; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.Parameter; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.Position; +import models.algebra.Term; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.algebra.Variable; +import models.dataConstraintModel.*; + +public class DataTransferChannelGenerator extends ChannelGenerator { + protected Set inputChannelMembers = null; + protected Set outputChannelMembers = null; + protected Set referenceChannelMembers = null; + + public DataTransferChannelGenerator(String channelName) { + super(channelName); + inputChannelMembers = new HashSet<>(); + outputChannelMembers = new HashSet<>(); + referenceChannelMembers = new HashSet<>(); + } + + public Set getInputChannelMembers() { + return inputChannelMembers; + } + + public void setInputChannelMembers(Set inputChannelMembers) { + this.inputChannelMembers = inputChannelMembers; + } + + public void addInputChannelMember(ChannelMember inputChannelMember) { + inputChannelMembers.add(inputChannelMember); + } + + public Set getOutputChannelMembers() { + return outputChannelMembers; + } + + public void setOutputChannelMembers(Set outputChannelMembers) { + this.outputChannelMembers = outputChannelMembers; + } + + public void addOutputChannelMember(ChannelMember outputChannelMember) { + outputChannelMembers.add(outputChannelMember); + } + + public Set getReferenceChannelMembers() { + return referenceChannelMembers; + } + + public void setReferenceChannelMembers(Set referenceChannelMembers) { + this.referenceChannelMembers = referenceChannelMembers; + } + + public void addReferenceChannelMember(ChannelMember referenceChannelMember) { + referenceChannelMembers.add(referenceChannelMember); + } + + public void addChannelMemberAsInput(ChannelMember groupDependentResource) { + addChannelMember(groupDependentResource); + addInputChannelMember(groupDependentResource); + } + + public void addChannelMemberAsOutput(ChannelMember groupDependentResource) { + addChannelMember(groupDependentResource); + addOutputChannelMember(groupDependentResource); + } + + public void addChannelMemberAsReference(ChannelMember groupDependentResource) { + addChannelMember(groupDependentResource); + addReferenceChannelMember(groupDependentResource); + } + + public void removeChannelMember(IdentifierTemplate id) { + for (ChannelMember cm: inputChannelMembers) { + if (cm.getIdentifierTemplate() == id) { + inputChannelMembers.remove(cm); + super.removeChannelMember(id); + return; + } + } + for (ChannelMember cm: outputChannelMembers) { + if (cm.getIdentifierTemplate() == id) { + outputChannelMembers.remove(cm); + super.removeChannelMember(id); + return; + } + } + for (ChannelMember cm: referenceChannelMembers) { + if (cm.getIdentifierTemplate() == id) { + referenceChannelMembers.remove(cm); + super.removeChannelMember(id); + return; + } + } + } + + public Set getInputIdentifierTemplates() { + Set inputIdentifierTemplates = new HashSet<>(); + for (ChannelMember member: inputChannelMembers) { + inputIdentifierTemplates.add(member.getIdentifierTemplate()); + } + return inputIdentifierTemplates; + } + + public Set getOutputIdentifierTemplates() { + Set outputIdentifierTemplates = new HashSet<>(); + for (ChannelMember member: outputChannelMembers) { + outputIdentifierTemplates.add(member.getIdentifierTemplate()); + } + return outputIdentifierTemplates; + } + + public Set getReferenceIdentifierTemplates() { + Set referenceIdentifierTemplates = new HashSet<>(); + for (ChannelMember member: referenceChannelMembers) { + referenceIdentifierTemplates.add(member.getIdentifierTemplate()); + } + return referenceIdentifierTemplates; + } + + /** + * Derive the update expression of the state of the target channel member. + * @param targetMember a channel member whose state is to be updated + * @return the derived update expression + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ + public Expression deriveUpdateExpressionOf(ChannelMember targetMember) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + IResourceStateAccessor defaultStateAccessor = new IResourceStateAccessor() { + HashMap curStateParams = new HashMap<>(); + HashMap nextStateParams = new HashMap<>(); + + @Override + public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + String resource = target.getResourceName(); + Parameter curStateParam = curStateParams.get(resource); + if (curStateParam == null) { + curStateParam = new Parameter("cur" + resource); + curStateParams.put(resource, curStateParam); + } + return curStateParam; + } + + @Override + public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { + String resource = target.getResourceName(); + Parameter nextStateParam = nextStateParams.get(resource); + if (nextStateParam == null) { + nextStateParam = new Parameter("next" + resource); + nextStateParams.put(resource, nextStateParam); + } + return nextStateParam; + } + }; + return deriveUpdateExpressionOf(targetMember, defaultStateAccessor); + } + + /** + * Derive the update expression of the state of the target channel member with a given resource state accessor. + * @param targetMember a channel member whose state is to be updated + * @param stateAccessor a resource state accessor + * @return the derived update expression + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ + public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + return deriveUpdateExpressionOf(targetMember, stateAccessor, null); + } + + public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor, HashMap inputIdentifierToStateAccessor) + throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { + if (!getOutputChannelMembers().contains(targetMember)) return null; + HashSet messageConstraints = new HashSet<>(); + + // Calculate message constraints from input state transitions + for (ChannelMember inputMember: getInputChannelMembers()) { + IdentifierTemplate inputIdentifier = inputMember.getIdentifierTemplate(); + if (inputIdentifier.getNumberOfParameters() > 0) { + throw new ParameterizedIdentifierIsFutureWork(); + } + Expression curInputStateAccessor = null; + Expression nextInputStateAccessor = null; + if (inputIdentifierToStateAccessor == null) { + curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); + nextInputStateAccessor = stateAccessor.getNextStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); + } else { + curInputStateAccessor = inputIdentifierToStateAccessor.get(inputIdentifier).getCurrentStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); + nextInputStateAccessor = inputIdentifierToStateAccessor.get(inputIdentifier).getNextStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); + } + Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor); + messageConstraints.add((Term) messageConstraintByInput); + } + + // Calculate message constraints from reference state transitions + for (ChannelMember referenceMember: getReferenceChannelMembers()) { + IdentifierTemplate referenceIdentifier = referenceMember.getIdentifierTemplate(); + if (referenceIdentifier.getNumberOfParameters() > 0) { + throw new ParameterizedIdentifierIsFutureWork(); + } + Expression curInputStateAccessor = null; + if (inputIdentifierToStateAccessor == null) { + curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(referenceIdentifier, targetMember.getIdentifierTemplate()); + } else { + curInputStateAccessor = inputIdentifierToStateAccessor.get(referenceIdentifier).getCurrentStateAccessorFor(referenceIdentifier, targetMember.getIdentifierTemplate()); + } + Expression messageConstraintByReference = referenceMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor); + messageConstraints.add((Term) messageConstraintByReference); + } + + // Unify message constraints + Term unifiedMessage = null; + for (Term messageContraint: messageConstraints) { + if (unifiedMessage == null) { + unifiedMessage = messageContraint; + } else { + unifiedMessage = (Term) unifiedMessage.unify(messageContraint); + if (unifiedMessage == null) { + throw new UnificationFailed(); + } + } + } + + // Calculate the next state of target resource from the unified message and the current resource state + IdentifierTemplate targetIdentifier = targetMember.getIdentifierTemplate(); + if (targetIdentifier.getNumberOfParameters() > 0) { + throw new ParameterizedIdentifierIsFutureWork(); + } + Expression curOutputStateAccessor = stateAccessor.getCurrentStateAccessorFor(targetIdentifier, targetIdentifier); + if (unifiedMessage == null) { + // for IOChannel + if (targetMember.getStateTransition().getMessageExpression() instanceof Term) { + unifiedMessage = (Term) targetMember.getStateTransition().getMessageExpression(); + } + } + return targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, unifiedMessage); + } + + @Override + public String toString() { + String channelSource = "channel " + getChannelName() + " {\n"; + for (ChannelMember inputMember: inputChannelMembers) { + channelSource += "\t in " + inputMember + "\n"; + } + for (ChannelMember refMember: referenceChannelMembers) { + channelSource += "\t ref " + refMember + "\n"; + } + for (ChannelMember outputMember: outputChannelMembers) { + channelSource += "\t out " + outputMember + "\n"; + } + channelSource += "}\n"; + return channelSource; + } + + public interface IResourceStateAccessor { + Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from); + Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java new file mode 100644 index 0000000..364a646 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java @@ -0,0 +1,31 @@ +package models.dataFlowModel; + +import java.util.Set; + +import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.IdentifierTemplate; + +public class DataTransferModel extends DataConstraintModel { + public DataFlowGraph getDataFlowGraph() { + DataFlowGraph dataFlowGraph = new DataFlowGraph(); + for (ChannelGenerator channelGen: getChannelGenerators()) { + DataTransferChannelGenerator dfChannelGen = (DataTransferChannelGenerator)channelGen; + Set inputResources = dfChannelGen.getInputIdentifierTemplates(); + Set outputResources = dfChannelGen.getOutputIdentifierTemplates(); + for (IdentifierTemplate in: inputResources) { + for (IdentifierTemplate out: outputResources) { + dataFlowGraph.addEdge(in ,out, dfChannelGen); + } + } + } + for (ChannelGenerator channelGen: getIOChannelGenerators()) { + DataTransferChannelGenerator dfChannelGen = (DataTransferChannelGenerator)channelGen; + Set outputResources = dfChannelGen.getOutputIdentifierTemplates(); + for (IdentifierTemplate out: outputResources) { + dataFlowGraph.addNode(out); + } + } + return dataFlowGraph; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java deleted file mode 100644 index 62870b3..0000000 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataflowChannelGenerator.java +++ /dev/null @@ -1,273 +0,0 @@ -package models.dataFlowModel; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; - -import models.algebra.Expression; -import models.algebra.InvalidMessage; -import models.algebra.Parameter; -import models.algebra.ParameterizedIdentifierIsFutureWork; -import models.algebra.Position; -import models.algebra.Term; -import models.algebra.UnificationFailed; -import models.algebra.ValueUndefined; -import models.algebra.Variable; -import models.dataConstraintModel.*; - -public class DataflowChannelGenerator extends ChannelGenerator { - protected Set inputChannelMembers = null; - protected Set outputChannelMembers = null; - protected Set referenceChannelMembers = null; - - public DataflowChannelGenerator(String channelName) { - super(channelName); - inputChannelMembers = new HashSet<>(); - outputChannelMembers = new HashSet<>(); - referenceChannelMembers = new HashSet<>(); - } - - public Set getInputChannelMembers() { - return inputChannelMembers; - } - - public void setInputChannelMembers(Set inputChannelMembers) { - this.inputChannelMembers = inputChannelMembers; - } - - public void addInputChannelMember(ChannelMember inputChannelMember) { - inputChannelMembers.add(inputChannelMember); - } - - public Set getOutputChannelMembers() { - return outputChannelMembers; - } - - public void setOutputChannelMembers(Set outputChannelMembers) { - this.outputChannelMembers = outputChannelMembers; - } - - public void addOutputChannelMember(ChannelMember outputChannelMember) { - outputChannelMembers.add(outputChannelMember); - } - - public Set getReferenceChannelMembers() { - return referenceChannelMembers; - } - - public void setReferenceChannelMembers(Set referenceChannelMembers) { - this.referenceChannelMembers = referenceChannelMembers; - } - - public void addReferenceChannelMember(ChannelMember referenceChannelMember) { - referenceChannelMembers.add(referenceChannelMember); - } - - public void addChannelMemberAsInput(ChannelMember groupDependentResource) { - addChannelMember(groupDependentResource); - addInputChannelMember(groupDependentResource); - } - - public void addChannelMemberAsOutput(ChannelMember groupDependentResource) { - addChannelMember(groupDependentResource); - addOutputChannelMember(groupDependentResource); - } - - public void addChannelMemberAsReference(ChannelMember groupDependentResource) { - addChannelMember(groupDependentResource); - addReferenceChannelMember(groupDependentResource); - } - - public void removeChannelMember(IdentifierTemplate id) { - for (ChannelMember cm: inputChannelMembers) { - if (cm.getIdentifierTemplate() == id) { - inputChannelMembers.remove(cm); - super.removeChannelMember(id); - return; - } - } - for (ChannelMember cm: outputChannelMembers) { - if (cm.getIdentifierTemplate() == id) { - outputChannelMembers.remove(cm); - super.removeChannelMember(id); - return; - } - } - for (ChannelMember cm: referenceChannelMembers) { - if (cm.getIdentifierTemplate() == id) { - referenceChannelMembers.remove(cm); - super.removeChannelMember(id); - return; - } - } - } - - public Set getInputIdentifierTemplates() { - Set inputIdentifierTemplates = new HashSet<>(); - for (ChannelMember member: inputChannelMembers) { - inputIdentifierTemplates.add(member.getIdentifierTemplate()); - } - return inputIdentifierTemplates; - } - - public Set getOutputIdentifierTemplates() { - Set outputIdentifierTemplates = new HashSet<>(); - for (ChannelMember member: outputChannelMembers) { - outputIdentifierTemplates.add(member.getIdentifierTemplate()); - } - return outputIdentifierTemplates; - } - - public Set getReferenceIdentifierTemplates() { - Set referenceIdentifierTemplates = new HashSet<>(); - for (ChannelMember member: referenceChannelMembers) { - referenceIdentifierTemplates.add(member.getIdentifierTemplate()); - } - return referenceIdentifierTemplates; - } - - /** - * Derive the update expression of the state of the target channel member. - * @param targetMember a channel member whose state is to be updated - * @return the derived update expression - * @throws ParameterizedIdentifierIsFutureWork - * @throws ResolvingMultipleDefinitionIsFutureWork - * @throws InvalidMessage - * @throws UnificationFailed - * @throws ValueUndefined - */ - public Expression deriveUpdateExpressionOf(ChannelMember targetMember) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { - IResourceStateAccessor defaultStateAccessor = new IResourceStateAccessor() { - HashMap curStateParams = new HashMap<>(); - HashMap nextStateParams = new HashMap<>(); - - @Override - public Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - String resource = target.getResourceName(); - Parameter curStateParam = curStateParams.get(resource); - if (curStateParam == null) { - curStateParam = new Parameter("cur" + resource); - curStateParams.put(resource, curStateParam); - } - return curStateParam; - } - - @Override - public Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from) { - String resource = target.getResourceName(); - Parameter nextStateParam = nextStateParams.get(resource); - if (nextStateParam == null) { - nextStateParam = new Parameter("next" + resource); - nextStateParams.put(resource, nextStateParam); - } - return nextStateParam; - } - }; - return deriveUpdateExpressionOf(targetMember, defaultStateAccessor); - } - - /** - * Derive the update expression of the state of the target channel member with a given resource state accessor. - * @param targetMember a channel member whose state is to be updated - * @param stateAccessor a resource state accessor - * @return the derived update expression - * @throws ParameterizedIdentifierIsFutureWork - * @throws ResolvingMultipleDefinitionIsFutureWork - * @throws InvalidMessage - * @throws UnificationFailed - * @throws ValueUndefined - */ - public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor) - throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { - return deriveUpdateExpressionOf(targetMember, stateAccessor, null); - } - - public Expression deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor, HashMap inputIdentifierToStateAccessor) - throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { - if (!getOutputChannelMembers().contains(targetMember)) return null; - HashSet messageConstraints = new HashSet<>(); - - // Calculate message constraints from input state transitions - for (ChannelMember inputMember: getInputChannelMembers()) { - IdentifierTemplate inputIdentifier = inputMember.getIdentifierTemplate(); - if (inputIdentifier.getNumberOfParameters() > 0) { - throw new ParameterizedIdentifierIsFutureWork(); - } - Expression curInputStateAccessor = null; - Expression nextInputStateAccessor = null; - if (inputIdentifierToStateAccessor == null) { - curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); - nextInputStateAccessor = stateAccessor.getNextStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); - } else { - curInputStateAccessor = inputIdentifierToStateAccessor.get(inputIdentifier).getCurrentStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); - nextInputStateAccessor = inputIdentifierToStateAccessor.get(inputIdentifier).getNextStateAccessorFor(inputIdentifier, targetMember.getIdentifierTemplate()); - } - Expression messageConstraintByInput = inputMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor, nextInputStateAccessor); - messageConstraints.add((Term) messageConstraintByInput); - } - - // Calculate message constraints from reference state transitions - for (ChannelMember referenceMember: getReferenceChannelMembers()) { - IdentifierTemplate referenceIdentifier = referenceMember.getIdentifierTemplate(); - if (referenceIdentifier.getNumberOfParameters() > 0) { - throw new ParameterizedIdentifierIsFutureWork(); - } - Expression curInputStateAccessor = null; - if (inputIdentifierToStateAccessor == null) { - curInputStateAccessor = stateAccessor.getCurrentStateAccessorFor(referenceIdentifier, targetMember.getIdentifierTemplate()); - } else { - curInputStateAccessor = inputIdentifierToStateAccessor.get(referenceIdentifier).getCurrentStateAccessorFor(referenceIdentifier, targetMember.getIdentifierTemplate()); - } - Expression messageConstraintByReference = referenceMember.getStateTransition().deriveMessageConstraintFor(curInputStateAccessor); - messageConstraints.add((Term) messageConstraintByReference); - } - - // Unify message constraints - Term unifiedMessage = null; - for (Term messageContraint: messageConstraints) { - if (unifiedMessage == null) { - unifiedMessage = messageContraint; - } else { - unifiedMessage = (Term) unifiedMessage.unify(messageContraint); - if (unifiedMessage == null) { - throw new UnificationFailed(); - } - } - } - - // Calculate the next state of target resource from the unified message and the current resource state - IdentifierTemplate targetIdentifier = targetMember.getIdentifierTemplate(); - if (targetIdentifier.getNumberOfParameters() > 0) { - throw new ParameterizedIdentifierIsFutureWork(); - } - Expression curOutputStateAccessor = stateAccessor.getCurrentStateAccessorFor(targetIdentifier, targetIdentifier); - if (unifiedMessage == null) { - // for IOChannel - if (targetMember.getStateTransition().getMessageExpression() instanceof Term) { - unifiedMessage = (Term) targetMember.getStateTransition().getMessageExpression(); - } - } - return targetMember.getStateTransition().deriveNextStateExpressionFor(curOutputStateAccessor, unifiedMessage); - } - - @Override - public String toString() { - String channelSource = "channel " + getChannelName() + " {\n"; - for (ChannelMember inputMember: inputChannelMembers) { - channelSource += "\t in " + inputMember + "\n"; - } - for (ChannelMember refMember: referenceChannelMembers) { - channelSource += "\t ref " + refMember + "\n"; - } - for (ChannelMember outputMember: outputChannelMembers) { - channelSource += "\t out " + outputMember + "\n"; - } - channelSource += "}\n"; - return channelSource; - } - - public interface IResourceStateAccessor { - Expression getCurrentStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from); - Expression getNextStateAccessorFor(IdentifierTemplate target, IdentifierTemplate from); - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java index 06468f0..d8aa4af 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ModelExtension.java @@ -11,7 +11,7 @@ private static Symbol.Memento extractFaceDownMem; private static Symbol.Memento sortByKeyMem; - public static void extendModel(DataFlowModel model) { + public static void extendModel(DataTransferModel model) { Symbol floor = model.getSymbol("floor"); floorMem = null; if (floor != null) { @@ -150,7 +150,7 @@ } } - public static void recoverModel(DataFlowModel model) { + public static void recoverModel(DataTransferModel model) { Symbol floor = model.getSymbol("floor"); if (floor != null) floor.setMemento(floorMem); Symbol sum = model.getSymbol("sum"); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceDependency.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceDependency.java deleted file mode 100644 index 8a3bed5..0000000 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceDependency.java +++ /dev/null @@ -1,20 +0,0 @@ -package models.dataFlowModel; - -import models.*; - -public class ResourceDependency extends Edge { - protected DataflowChannelGenerator channelGenerator = null; - - public ResourceDependency(ResourceNode src, ResourceNode dst, DataflowChannelGenerator channelGenerator) { - super(src, dst); - this.channelGenerator = channelGenerator; - } - - public DataflowChannelGenerator getChannelGenerator() { - return channelGenerator; - } - - public String toString() { - return channelGenerator.getChannelName(); - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceDependencyGraph.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceDependencyGraph.java deleted file mode 100644 index f196835..0000000 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceDependencyGraph.java +++ /dev/null @@ -1,40 +0,0 @@ -package models.dataFlowModel; - -import java.util.HashMap; -import java.util.Map; - -import models.DirectedGraph; -import models.dataConstraintModel.IdentifierTemplate; - -public class ResourceDependencyGraph extends DirectedGraph { - protected Map nodeMap = null; - - public ResourceDependencyGraph() { - super(); - nodeMap = new HashMap<>(); - } - - public void addNode(IdentifierTemplate id) { - if (nodeMap.get(id) == null) { - ResourceNode node = new ResourceNode(id); - addNode(node); - nodeMap.put(id, node); - } - } - - public void addEdge(IdentifierTemplate in, IdentifierTemplate out, DataflowChannelGenerator dfChannelGen) { - ResourceNode srcNode = nodeMap.get(in); - if (srcNode == null) { - srcNode = new ResourceNode(in); - addNode(srcNode); - nodeMap.put(in, srcNode); - } - ResourceNode dstNode = nodeMap.get(out); - if (dstNode == null) { - dstNode = new ResourceNode(out); - addNode(dstNode); - nodeMap.put(out, dstNode); - } - addEdge(new ResourceDependency(srcNode, dstNode, dfChannelGen)); - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannelGenerator.java b/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannelGenerator.java index d5192a0..4bbfe7e 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannelGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/models/visualModel/FormulaChannelGenerator.java @@ -13,9 +13,9 @@ import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.IdentifierTemplate; import models.dataConstraintModel.StateTransition; -import models.dataFlowModel.DataflowChannelGenerator; +import models.dataFlowModel.DataTransferChannelGenerator; -public class FormulaChannelGenerator extends DataflowChannelGenerator { +public class FormulaChannelGenerator extends DataTransferChannelGenerator { private Symbol defaultOperator = null; private String formula = null; private Expression formulaRhs = null; diff --git a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index 96eac7b..ed9aaf9 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -16,8 +16,8 @@ import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.IdentifierTemplate; import models.dataConstraintModel.StateTransition; -import models.dataFlowModel.DataFlowModel; -import models.dataFlowModel.DataflowChannelGenerator; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataTransferChannelGenerator; import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; import parser.exceptions.ExpectedChannelName; @@ -78,15 +78,15 @@ } } - public DataFlowModel doParse() + public DataTransferModel doParse() throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment { return parseDataFlowModel(); } - public DataFlowModel parseDataFlowModel() + public DataTransferModel parseDataFlowModel() throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment { - DataFlowModel model = new DataFlowModel(); - DataflowChannelGenerator channel; + DataTransferModel model = new DataTransferModel(); + DataTransferChannelGenerator channel; while ((channel = parseChannel(model)) != null) { if (channel.getInputChannelMembers().size() == 0) { model.addIOChannelGenerator(channel); @@ -97,7 +97,7 @@ return model; } - public DataflowChannelGenerator parseChannel(DataFlowModel model) + public DataTransferChannelGenerator parseChannel(DataTransferModel model) throws ExpectedLeftCurlyBracket, ExpectedRightBracket, ExpectedAssignment, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, @@ -119,7 +119,7 @@ if (channelName.equals(LEFT_CURLY_BRACKET)) throw new ExpectedChannelName(stream.getLine()); int fromLine = stream.getLine(); - DataflowChannelGenerator channel = new DataflowChannelGenerator(channelName); + DataTransferChannelGenerator channel = new DataTransferChannelGenerator(channelName); String leftBracket = stream.next(); if (!leftBracket.equals(LEFT_CURLY_BRACKET)) throw new ExpectedLeftCurlyBracket(stream.getLine()); @@ -150,7 +150,7 @@ return channel; } - public void parseInit(DataFlowModel model) + public void parseInit(DataTransferModel model) throws ExpectedLeftCurlyBracket, ExpectedAssignment, ExpectedRHSExpression, WrongRHSExpression, ExpectedRightBracket { @@ -183,7 +183,7 @@ } } - public ChannelMember parseChannelMember(DataFlowModel model, final String inOrOutOrRef) + public ChannelMember parseChannelMember(DataTransferModel model, final String inOrOutOrRef) throws ExpectedRightBracket, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression @@ -239,7 +239,7 @@ return channelMember; } - public Expression parseTerm(TokenStream stream, DataFlowModel model) + public Expression parseTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket { ArrayList expressions = new ArrayList<>(); @@ -256,7 +256,7 @@ Symbol minus = null; String symbolName = null; if (leftBracketOrMinus.equals(MINUS)) { - minus = DataFlowModel.minus; // not sub + minus = DataTransferModel.minus; // not sub symbolName = stream.next(); } else { symbolName = leftBracketOrMinus; @@ -291,9 +291,9 @@ } else { Double d = Double.parseDouble(symbolName); if (symbolName.contains(".")) { - exp = new Constant(symbolName, DataFlowModel.typeDouble); + exp = new Constant(symbolName, DataTransferModel.typeDouble); } else { - exp = new Constant(symbolName, DataFlowModel.typeInt); + exp = new Constant(symbolName, DataTransferModel.typeInt); } } } catch (NumberFormatException e) { @@ -323,13 +323,13 @@ if (operator == null) { break; } else if (operator.equals(ADD)) { - operators.add(DataFlowModel.add); + operators.add(DataTransferModel.add); } else if (operator.equals(MUL)) { - operators.add(DataFlowModel.mul); + operators.add(DataTransferModel.mul); } else if (operator.equals(SUB)) { - operators.add(DataFlowModel.sub); // not minus + operators.add(DataTransferModel.sub); // not minus } else if (operator.equals(DIV)) { - operators.add(DataFlowModel.div); + operators.add(DataTransferModel.div); } else { break; } diff --git a/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java b/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java index c2ab83b..830bd5f 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/ParserDTRAM.java @@ -10,7 +10,7 @@ import com.mxgraph.view.mxGraph; import com.mxgraph.view.mxGraphView; -import models.dataFlowModel.DataFlowModel; +import models.dataFlowModel.DataTransferModel; import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; import parser.exceptions.ExpectedChannelName; @@ -62,9 +62,9 @@ * * @param reader */ - public DataFlowModel doParseModel() + public DataTransferModel doParseModel() throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, ExpectedModel, ExpectedGeometry { - DataFlowModel model = getParsedModel(); + DataTransferModel model = getParsedModel(); return model; } @@ -84,7 +84,7 @@ * * @param stream */ - private DataFlowModel getParsedModel() + private DataTransferModel getParsedModel() throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedInOrOutOrRefKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, ExpectedModel, ExpectedGeometry { if (!stream.hasNext()) throw new NullPointerException(); @@ -96,7 +96,7 @@ String leftBracket = stream.next(); if (!leftBracket.equals(LEFT_CURLY_BRACKET)) throw new ExpectedLeftCurlyBracket(stream.getLine()); - DataFlowModel model = parseDataFlowModel(); + DataTransferModel model = parseDataFlowModel(); String rightBracket = stream.next(); if(!rightBracket.equals(RIGHT_CURLY_BRACKET))throw new ExpectedRightBracket(stream.getLine()); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java b/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java index 6791346..a89ea3c 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/CodeGeneratorTest.java @@ -9,6 +9,9 @@ import algorithms.*; import code.ast.CompilationUnit; import code.ast.TypeDeclaration; +import generators.DataTransferMethodAnalyzer; +import generators.JavaCodeGenerator; +import generators.JavaMethodBodyGenerator; import models.dataFlowModel.*; import parser.*; import parser.exceptions.ExpectedAssignment; @@ -28,12 +31,12 @@ File file = new File("models/POS.model"); try { Parser parser = new Parser(new BufferedReader(new FileReader(file))); - DataFlowModel model; + DataTransferModel model; try { model = parser.doParse(); - ResourceDependencyGraph graph = NecessityOfStoringResourceStates.doDecide(model); - SelectableDataTransfers.init(graph); - FinalDecisionOfStoringResourceStates.doDecide(graph); + DataFlowGraph graph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); + DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(graph); + DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); ArrayList codetree = JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model)); System.out.println(codetree); } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java index b83e99a..6065992 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java @@ -13,7 +13,7 @@ @Test public void test() { // Construct a data-flow architecture model. - DataFlowModel model = new DataFlowModel(); + DataTransferModel model = new DataTransferModel(); IdentifierTemplate customer_off = new IdentifierTemplate("customers.{x1}.off", 1); // an identifier template to specify a customer's office resource IdentifierTemplate company_add = new IdentifierTemplate("companies.{x2}.add", 1); // an identifier template to specify a companie's address resource IdentifierTemplate customer_add = new IdentifierTemplate("customers.{x1}.add", 1); // an identifier template to specify a customer's address resource @@ -23,7 +23,7 @@ // customers.{x1}.off(c, set(x)) == x // customers.{x1}.off(c, e) == c // - DataflowChannelGenerator gin_1 = new DataflowChannelGenerator("gin_1"); // set customer's office (an input channel) + DataTransferChannelGenerator gin_1 = new DataTransferChannelGenerator("gin_1"); // set customer's office (an input channel) GroupSelector x1 = new GroupSelector(); ChannelMember customer_off_1 = new ChannelMember(customer_off); customer_off_1.addSelector(x1); // x1 is determined by the path parameter in customer's office template, and serves as a group selector in this channel @@ -35,7 +35,7 @@ // companies.{x2}.add(a, set(y)) == y // companies.{x2}.add(a, e) == a // - DataflowChannelGenerator gin_2 = new DataflowChannelGenerator("gin_2"); // set companie's address (an input channel) + DataTransferChannelGenerator gin_2 = new DataTransferChannelGenerator("gin_2"); // set companie's address (an input channel) GroupSelector x2 = new GroupSelector(); ChannelMember company_add_1 = new ChannelMember(company_add); company_add_1.addSelector(x2); // x2 is determined by the path parameter in companie's address template, and serves as a group selector in this channel @@ -48,7 +48,7 @@ // companies.{y}.add( a1, update(y, z)) == z // customers.{x3}.add(a2, update(y, z)) == z // - DataflowChannelGenerator g = new DataflowChannelGenerator("g"); // update customer's address + DataTransferChannelGenerator g = new DataTransferChannelGenerator("g"); // update customer's address GroupSelector x3 = new GroupSelector(); ChannelSelector y = new ChannelSelector(); ChannelMember customer_off_2 = new ChannelMember(customer_off); @@ -75,7 +75,7 @@ assertEquals(1, model.getChannelGenerators().size()); // Extract the resource dependency graph. - ResourceDependencyGraph resourceDependencyGraph = model.getResourceDependencyGraph(); + DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph(); // Check the graph. assertEquals(3, resourceDependencyGraph.getNodes().size()); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java index 8bb75ca..67a1a2a 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java @@ -6,6 +6,7 @@ import java.io.FileReader; import algorithms.*; +import generators.DataTransferMethodAnalyzer; import models.Node; import models.dataFlowModel.*; import parser.*; @@ -26,13 +27,13 @@ File file = new File("models/POS2.model"); try { Parser parser = new Parser(new BufferedReader(new FileReader(file))); - DataFlowModel model = null; + DataTransferModel model = null; try { model = parser.doParse(); System.out.println(model); - ResourceDependencyGraph graph = NecessityOfStoringResourceStates.doDecide(model); - SelectableDataTransfers.init(graph); - FinalDecisionOfStoringResourceStates.doDecide(graph); + DataFlowGraph graph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); + DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(graph); + DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); for(Node n:graph.getNodes()) { System.out.println(((ResourceNode) n).getIdentifierTemplate().getResourceName() + ":" + ((StoreAttribute) ((ResourceNode) n).getAttribute()).isStored()); } diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java index feed8ab..9a7c300 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageNecessityTest.java @@ -5,7 +5,7 @@ import java.io.FileNotFoundException; import java.io.FileReader; -import algorithms.NecessityOfStoringResourceStates; +import algorithms.DataTransferModelAnalyzer; import models.Node; import models.dataFlowModel.*; import parser.Parser; @@ -26,11 +26,11 @@ File file = new File("models/POS2.model"); try { Parser parser = new Parser(new BufferedReader(new FileReader(file))); - DataFlowModel model; + DataTransferModel model; try { model = parser.doParse(); System.out.println(model); - ResourceDependencyGraph graph = NecessityOfStoringResourceStates.doDecide(model); + DataFlowGraph graph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); for (Node n:graph.getNodes()) { ResourceNode resource = (ResourceNode)n; if((StoreAttribute)resource.getAttribute() != null) { diff --git a/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java b/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java index f4d9077..847fb6f 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/EdgeTransitionSelectableTest.java @@ -26,14 +26,14 @@ File file = new File("models/POS2.model"); try { Parser parser = new Parser(new BufferedReader(new FileReader(file))); - DataFlowModel model; + DataTransferModel model; try { model = parser.doParse(); System.out.println(model); - ResourceDependencyGraph graph = NecessityOfStoringResourceStates.doDecide(model); - SelectableDataTransfers.init(graph); + DataFlowGraph graph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); + DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(graph); for(Edge e:graph.getEdges()) { - ResourceDependency re = (ResourceDependency) e; + DataFlowEdge re = (DataFlowEdge) e; System.out.println(re.getSource() + "-" + re.getDestination() + ":" + ((PushPullAttribute)(re.getAttribute())).getOptions()); } } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword diff --git a/AlgebraicDataflowArchitectureModel/src/tests/InverseTest.java b/AlgebraicDataflowArchitectureModel/src/tests/InverseTest.java index 277948d..bfa8957 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/InverseTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/InverseTest.java @@ -15,7 +15,7 @@ import models.algebra.Expression; import models.algebra.Position; import models.algebra.Variable; -import models.dataFlowModel.DataFlowModel; +import models.dataFlowModel.DataTransferModel; import parser.Parser; import parser.Parser.TokenStream; import parser.exceptions.ExpectedRightBracket; @@ -24,7 +24,7 @@ @Test public void test() { String lhs = "y"; - DataFlowModel model = new DataFlowModel(); + DataTransferModel model = new DataTransferModel(); try { String rhs = "(a * x + b) * c"; diff --git a/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java index e16163b..ff262b2 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java @@ -13,7 +13,7 @@ @Test public void test() { // Construct a data-flow architecture model. - DataFlowModel model = new DataFlowModel(); + DataTransferModel model = new DataTransferModel(); IdentifierTemplate payment = new IdentifierTemplate("payment", 0); // an identifier template to specify the payment resource IdentifierTemplate loyalty = new IdentifierTemplate("loyalty", 0); // an identifier template to specify the loyalty resource IdentifierTemplate history = new IdentifierTemplate("history", 0); // an identifier template to specify the payment history resource @@ -23,7 +23,7 @@ // // payment(p1, purchase(x)) == x // - DataflowChannelGenerator cin = new DataflowChannelGenerator("cin"); + DataTransferChannelGenerator cin = new DataTransferChannelGenerator("cin"); ChannelMember cin_payment = new ChannelMember(payment); cin.addChannelMember(cin_payment); assertEquals(cin.getChannelMembers().size(), 1); @@ -33,7 +33,7 @@ // payment(p1, update1(y)) == y // loyalty(l, update1(y)) == floor(y * 0.05) // - DataflowChannelGenerator c1 = new DataflowChannelGenerator("c1"); + DataTransferChannelGenerator c1 = new DataTransferChannelGenerator("c1"); ChannelMember c1_payment = new ChannelMember(payment); ChannelMember c1_loyalty = new ChannelMember(loyalty); c1.addChannelMemberAsInput(c1_payment); @@ -47,7 +47,7 @@ // payment(p1, update2(z)) == z // history(h, update2(z)) == cons(z, h) // - DataflowChannelGenerator c2 = new DataflowChannelGenerator("c2"); + DataTransferChannelGenerator c2 = new DataTransferChannelGenerator("c2"); ChannelMember c2_payment = new ChannelMember(payment); ChannelMember c2_history = new ChannelMember(history); c2.addChannelMemberAsInput(c2_payment); @@ -61,7 +61,7 @@ // history(h, update3(u)) == u // total(t, update3(u)) == sum(u) // - DataflowChannelGenerator c3 = new DataflowChannelGenerator("c3"); + DataTransferChannelGenerator c3 = new DataTransferChannelGenerator("c3"); ChannelMember c3_history = new ChannelMember(history); ChannelMember c3_total = new ChannelMember(total); c3.addChannelMemberAsInput(c3_history); @@ -82,7 +82,7 @@ assertEquals(3, model.getChannelGenerators().size()); // Extract the resource dependency graph. - ResourceDependencyGraph resourceDependencyGraph = model.getResourceDependencyGraph(); + DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph(); // Check the graph. assertEquals(4, resourceDependencyGraph.getNodes().size()); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java b/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java index 7d9d901..cfd510c 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java @@ -12,9 +12,9 @@ import models.algebra.ValueUndefined; import models.algebra.Variable; import models.dataConstraintModel.*; -import models.dataFlowModel.DataFlowModel; -import models.dataFlowModel.DataflowChannelGenerator; -import models.dataFlowModel.DataflowChannelGenerator.IResourceStateAccessor; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataTransferChannelGenerator; +import models.dataFlowModel.DataTransferChannelGenerator.IResourceStateAccessor; import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; public class UpdateCodeGenerationTest { @@ -108,7 +108,7 @@ // payment(p1, update1(y)) == y // loyalty(l, update1(y)) == floor(y * 0.05) // - DataflowChannelGenerator c1 = new DataflowChannelGenerator("c1"); + DataTransferChannelGenerator c1 = new DataTransferChannelGenerator("c1"); ChannelMember c1_payment = new ChannelMember(payment); ChannelMember c1_loyalty = new ChannelMember(loyalty); c1.addChannelMemberAsInput(c1_payment); @@ -175,7 +175,7 @@ // payment(p1, update2(z)) == z // history(h, update2(z)) == cons(z, h) // - DataflowChannelGenerator c2 = new DataflowChannelGenerator("c2"); + DataTransferChannelGenerator c2 = new DataTransferChannelGenerator("c2"); ChannelMember c2_payment = new ChannelMember(payment); ChannelMember c2_history = new ChannelMember(history); c2.addChannelMemberAsInput(c2_payment); @@ -186,7 +186,7 @@ Symbol update2 = new Symbol("update2", 1); Term c2_message = new Term(update2); // update2(z) c2_message.addChild(z); - Term nextHistory = new Term(DataFlowModel.cons); // cons(z, h) + Term nextHistory = new Term(DataTransferModel.cons); // cons(z, h) nextHistory.addChild(z); nextHistory.addChild(h); @@ -238,7 +238,7 @@ // history(h, update3(u)) = u // total(t, update3(u)) = sum(u) // - DataflowChannelGenerator c3 = new DataflowChannelGenerator("c3"); + DataTransferChannelGenerator c3 = new DataTransferChannelGenerator("c3"); ChannelMember c3_history = new ChannelMember(history); ChannelMember c3_total = new ChannelMember(total); c3.addChannelMemberAsInput(c3_history); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java b/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java index 30c985c..5f51af7 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/UpdateConflictCheckTest.java @@ -6,7 +6,7 @@ import java.io.FileReader; import algorithms.*; -import models.dataFlowModel.DataFlowModel; +import models.dataFlowModel.DataTransferModel; import parser.Parser; import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; @@ -26,8 +26,8 @@ try { Parser parser = new Parser(new BufferedReader(new FileReader(file))); try { - DataFlowModel model = parser.doParse(); - System.out.println(UpdateConflictCheck.run(model)); + DataTransferModel model = parser.doParse(); + System.out.println(Validation.checkUpdateConflict(model)); } catch (ExpectedRightBracket e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java b/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java index f7d923b..008d004 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/parser/ParseTest.java @@ -32,21 +32,21 @@ File file = new File("models/POS.model"); try { Parser parser = new Parser(new BufferedReader(new FileReader(file))); - DataFlowModel model; + DataTransferModel model; try { model = parser.doParse(); System.out.println(model); for (ChannelGenerator c: model.getChannelGenerators()) { - for (ChannelMember out: ((DataflowChannelGenerator) c).getOutputChannelMembers()) { + for (ChannelMember out: ((DataTransferChannelGenerator) c).getOutputChannelMembers()) { String[] sideEffects = new String[] {""}; - System.out.println("next" + out.getIdentifierTemplate().getResourceName() + " = " + ((DataflowChannelGenerator) c).deriveUpdateExpressionOf(out).toImplementation(sideEffects)); + System.out.println("next" + out.getIdentifierTemplate().getResourceName() + " = " + ((DataTransferChannelGenerator) c).deriveUpdateExpressionOf(out).toImplementation(sideEffects)); } } System.out.println(); - ResourceDependencyGraph resourceDependencyGraph = model.getResourceDependencyGraph(); + DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph(); for (Edge e: resourceDependencyGraph.getEdges()) { System.out.println(e.getSource() + "-(" + e + ")->" + e.getDestination()); }