diff --git a/AlgebraicDataflowArchitectureModel/models/Accounts.model b/AlgebraicDataflowArchitectureModel/models/Accounts.model new file mode 100644 index 0000000..81093de --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/Accounts.model @@ -0,0 +1,7 @@ +channel CIO1 { + out accounts(l:List, signup(name:Str)) == cons(name, l) +} + +channel CIO2(uid:Int) { + out accounts.{uid}(n:Str, changeName(name)) == name +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java index 5832f46..d59f7dc 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -84,6 +84,8 @@ protected String curFileName = null; protected String curFilePath = null; protected ArrayList codes = null; + + private boolean bReflectingArchitectureModel = false; public Editor(mxGraphComponent graphComponent) { this.graphComponent = graphComponent; @@ -333,6 +335,7 @@ * @return constructed mxGraph */ public mxGraph constructGraph(DataTransferModel model) { + bReflectingArchitectureModel = true; ((mxGraphModel) graph.getModel()).clear(); Object parent = graph.getDefaultParent(); graph.getModel().beginUpdate(); @@ -406,7 +409,8 @@ graph.getModel().endUpdate(); } setTreeLayout(); - + + bReflectingArchitectureModel = false; return graph; } @@ -574,6 +578,7 @@ } public boolean connectEdge(mxCell edge, mxCell src, mxCell dst) { + if (bReflectingArchitectureModel) return false; DataTransferModel model = getModel(); Channel srcCh = model.getChannel((String) src.getValue()); if (srcCh == null) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index d4f5547..58d4365 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -27,6 +27,7 @@ import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.DataTransferChannel; import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; @@ -73,135 +74,160 @@ MethodDeclaration mainConstructor = new MethodDeclaration(mainTypeName, true); mainType.addMethod(mainConstructor); - // For each resource. + // For each resource path. for (ResourceNode rn: resources) { boolean f = false; String resourceName = rn.getResource().getResourceName().substring(0, 1).toUpperCase() + rn.getResource().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; - ResourcePath dstRes = ((ResourceNode) re.getDestination()).getResource(); - 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; - ResourcePath srcRes = ((ResourceNode) re.getSource()).getResource(); - 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. - ResourcePath cashResId = ((ResourceNode) re.getSource()).getResource(); - type.addField(new FieldDeclaration( - cashResId.getResourceStateType(), ((ResourceNode) re.getSource()).getResource().getResourceName(), getInitializer(cashResId))); + TypeDeclaration type = null; + for (CompilationUnit cu: codes) { + for (TypeDeclaration t: cu.types()) { + if (resourceName.equals(t.getTypeName())) { + type = t; + break; } } + if (type != null) break; } - Set refs = new HashSet<>(); - for (Channel cg : model.getChannels()) { - DataTransferChannel c = (DataTransferChannel) cg; - if (c.getInputResources().contains(rn.getResource())) { - for (ResourcePath id: c.getReferenceResources()) { - if (!refs.contains(id) && !depends.contains(id)) { - refs.add(id); - String refResName = id.getResourceName(); - fieldInitializer += refResName.toLowerCase() + ","; - f = true; + if (type == null) { + // Add compilation unit for each resource. + type = new TypeDeclaration(resourceName); + CompilationUnit cu = new CompilationUnit(type); + cu.addImport(new ImportDeclaration("java.util.*")); + codes.add(cu); + + // 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; + ResourcePath dstRes = ((ResourceNode) re.getDestination()).getResource(); + 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; + ResourcePath srcRes = ((ResourceNode) re.getSource()).getResource(); + 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. + ResourcePath cashResId = ((ResourceNode) re.getSource()).getResource(); + type.addField(new FieldDeclaration( + cashResId.getResourceStateType(), ((ResourceNode) re.getSource()).getResource().getResourceName(), getInitializer(cashResId))); } } } - } - if (f) fieldInitializer = fieldInitializer.substring(0, fieldInitializer.length() - 1); - fieldInitializer += ")"; - FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), rn.getResource().getResourceName()); - mainType.addField(field); - Block manConstructorBody = mainConstructor.getBody(); - if (manConstructorBody == null) { - manConstructorBody = new Block(); - mainConstructor.setBody(manConstructorBody); - } - manConstructorBody.addStatement(rn.getResource().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; - ResourcePath dstRes = ((ResourceNode) re.getDestination()).getResource(); - 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; - ResourcePath srcRes = ((ResourceNode) re.getSource()).getResource(); - 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())); - DataTransferChannel c = (DataTransferChannel) re.getChannel(); - for (ResourcePath ref: c.getReferenceResources()) { - if (!ref.equals(rn.getResource())) { - 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 (Channel cg : model.getChannels()) { - DataTransferChannel c = (DataTransferChannel) cg; - if (c.getInputResources().contains(rn.getResource())) { - for (ResourcePath id: c.getReferenceResources()) { - 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() + ";"); + Set refs = new HashSet<>(); + for (Channel ch : model.getChannels()) { + DataTransferChannel c = (DataTransferChannel) ch; + if (c.getInputResources().contains(rn.getResource())) { + for (ResourcePath res: c.getReferenceResources()) { + if (!refs.contains(res) && !depends.contains(res)) { + refs.add(res); + String refResName = res.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.getResource().getResourceName()); + mainType.addField(field); + Block mainConstructorBody = mainConstructor.getBody(); + if (mainConstructorBody == null) { + mainConstructorBody = new Block(); + mainConstructor.setBody(mainConstructorBody); + } + mainConstructorBody.addStatement(rn.getResource().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; + ResourcePath dstRes = ((ResourceNode) re.getDestination()).getResource(); + 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; + ResourcePath srcRes = ((ResourceNode) re.getSource()).getResource(); + 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())); + DataTransferChannel c = (DataTransferChannel) re.getChannel(); + for (ResourcePath ref: c.getReferenceResources()) { + if (!ref.equals(rn.getResource())) { + 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 (Channel ch : model.getChannels()) { + DataTransferChannel c = (DataTransferChannel) ch; + if (c.getInputResources().contains(rn.getResource())) { + for (ResourcePath res: c.getReferenceResources()) { + if (!refs.contains(res) && !depends.contains(res)) { + refs.add(res); + String refResName = res.getResourceName(); + refResName = refResName.substring(0, 1).toUpperCase() + refResName.substring(1); + type.addField(new FieldDeclaration(new Type(refResName, refResName), res.getResourceName())); + constructor.addParameter(new VariableDeclaration(new Type(refResName, refResName), res.getResourceName())); + block.addStatement("this." + res.getResourceName() + " = " + res.getResourceName() + ";"); + } + } + } + } + constructor.setBody(block); + if (constructor.getParameters() != null) + type.addMethod(constructor); } - constructor.setBody(block); - if (constructor.getParameters() != null) - type.addMethod(constructor); // Declare input methods in resources and the main type. - for (Channel cg : model.getIOChannels()) { - for (ChannelMember cm : ((DataTransferChannel) cg).getOutputChannelMembers()) { + Channel inCh = null; + for (Channel ch : model.getIOChannels()) { + for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { if (cm.getResource().equals(rn.getResource())) { + inCh = ch; Expression message = cm.getStateTransition().getMessageExpression(); - if (message.getClass() == Term.class) { + if (message instanceof Term) { + // In the resource. ArrayList params = new ArrayList<>(); + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + params.add(new VariableDeclaration(var.getType(), var.getName())); + } + } for (Variable var: message.getVariables().values()) { params.add(new VariableDeclaration(var.getType(), var.getName())); } @@ -209,8 +235,10 @@ ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(), false, typeVoid, params); type.addMethod(input); + + // In the main type. String str = ((Term) cm.getStateTransition().getMessageExpression()).getSymbol().getImplName(); - input = getMethod(mainType, str); + input = getMethod(mainType, str, params); if (input == null) { input = new MethodDeclaration(str, false, typeVoid, params); mainType.addMethod(input); @@ -226,37 +254,101 @@ } } } - } else if (message.getClass() == Variable.class) { - MethodDeclaration input = new MethodDeclaration( - ((Variable) cm.getStateTransition().getMessageExpression()).getName(), - false, typeVoid, null); + } else if (message instanceof Variable) { + // In the resource. + ArrayList params = new ArrayList<>(); + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + params.add(new VariableDeclaration(var.getType(), var.getName())); + } + } + MethodDeclaration input = null; + if (params.size() > 0) { + input = new MethodDeclaration( + ((Variable) cm.getStateTransition().getMessageExpression()).getName(), + false, typeVoid, params); + } else { + input = new MethodDeclaration( + ((Variable) cm.getStateTransition().getMessageExpression()).getName(), + false, typeVoid, null); + } type.addMethod(input); + + // In the main type. String str = ((Variable) cm.getStateTransition().getMessageExpression()).getName(); - input = getMethod(mainType, str); + input = getMethod(mainType, str, params); if (input == null) { - input = new MethodDeclaration(str, false, typeVoid, null); + if (params.size() > 0) { + input = new MethodDeclaration(str, false, typeVoid, params); + } else { + 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()) { + if (((StoreAttribute) rn.getAttribute()).isStored() && rn.getResource().getNumberOfParameters() == 0) { ResourcePath resId = rn.getResource(); 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.getResource().getResourceStateType())); - - // Add compilation unit for each resource. - CompilationUnit cu = new CompilationUnit(type); - cu.addImport(new ImportDeclaration("java.util.*")); - codes.add(cu); + // Declare the getter methods to obtain the state in the resource and the main type. + if (inCh == null) { + DataFlowEdge e = (DataFlowEdge) rn.getInEdges().iterator().next(); + if (e != null) { + inCh = e.getChannel(); + } + } + if (inCh != null) { + // In the resource. + ArrayList params = new ArrayList<>(); + for (Selector selector: inCh.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + params.add(new VariableDeclaration(var.getType(), var.getName())); + } + } + if (params.size() > 0) { + type.addMethod(new MethodDeclaration("getValue", false, rn.getResource().getResourceStateType(), params)); + } else { + type.addMethod(new MethodDeclaration("getValue", rn.getResource().getResourceStateType())); + } + + // In the main type. + MethodDeclaration getter = null; + if (params.size() > 0) { + getter = new MethodDeclaration("get" + rn.getResource().getResourceName().substring(0, 1).toUpperCase() + + rn.getResource().getResourceName().substring(1), + false, + rn.getResource().getResourceStateType(), + params); + } else { + getter = new MethodDeclaration("get" + rn.getResource().getResourceName().substring(0, 1).toUpperCase() + + rn.getResource().getResourceName().substring(1), + rn.getResource().getResourceStateType()); + } + getter.setBody(new Block()); + if (params.size() > 0) { + String sParams = ""; + String delimiter = ""; + for (VariableDeclaration var: params) { + sParams += delimiter + var.getName(); + delimiter = ", "; + } + getter.getBody().addStatement("return " + rn.getResource().getResourceName() + ".getValue(" + sParams + ");"); + } else { + getter.getBody().addStatement("return " + rn.getResource().getResourceName() + ".getValue();"); + } + mainType.addMethod(getter); + } } + + // Declare the Pair class. boolean isCreatedPair = false; @@ -293,34 +385,20 @@ } } - // Declare getter methods in the main type. - for (Node n : graph.getNodes()) { - ResourceNode rn = (ResourceNode) n; - MethodDeclaration getter = new MethodDeclaration( - "get" + rn.getResource().getResourceName().substring(0, 1).toUpperCase() - + rn.getResource().getResourceName().substring(1), - rn.getResource().getResourceStateType()); - getter.setBody(new Block()); - getter.getBody().addStatement( - "return " + rn.getResource().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)); - } - } +// 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; } @@ -423,9 +501,21 @@ orderedList.add(0, curNode); } - private static MethodDeclaration getMethod(TypeDeclaration type, String methodName) { + private static MethodDeclaration getMethod(TypeDeclaration type, String methodName, List params) { for (MethodDeclaration m: type.getMethods()) { - if (m.getName().equals(methodName)) return m; + if (m.getName().equals(methodName)) { + if (m.getParameters() == null && (params == null || params.size() == 0)) return m; + if (m.getParameters() != null && params != null && m.getParameters().size() == params.size()) { + boolean matchParams = true; + for (int i = 0; i < m.getParameters().size(); i++) { + if (!m.getParameters().get(i).getType().equals(params.get(i).getType())) { + matchParams = false; + break; + } + } + if (matchParams) return m; + } + } } return null; } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index 1e8aec5..9598f60 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -11,6 +11,7 @@ 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; @@ -25,6 +26,7 @@ import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.DataTransferChannel; import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; @@ -85,26 +87,28 @@ 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.getResource().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);"); + if (dst.getResource().getNumberOfParameters() == 0) { + // returns the current state stored in a field. + MethodDeclaration getter = getGetterMethod(dstType, null); + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + Type resourceType = dst.getResource().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);"); + } } } } @@ -161,33 +165,35 @@ } } 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 inputResourceToStateAccessor = new HashMap<>(); - for (Edge eIn: dst.getInEdges()) { - DataFlowEdge dIn = (DataFlowEdge) eIn; - if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - isContainedPush = true; - inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getResource(), JavaCodeGenerator.pushAccessor); - } else { - inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getResource(), JavaCodeGenerator.pullAccessor); + if (dst.getResource().getNumberOfParameters() == 0) { + MethodDeclaration getter = getGetterMethod(dstType, null); + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + boolean isContainedPush = false; + HashMap inputResourceToStateAccessor = new HashMap<>(); + for (Edge eIn: dst.getInEdges()) { + DataFlowEdge dIn = (DataFlowEdge) eIn; + if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + isContainedPush = true; + inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getResource(), JavaCodeGenerator.pushAccessor); + } else { + inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getResource(), JavaCodeGenerator.pullAccessor); + } } - } - // for reference channel members - for (ChannelMember c: d.getChannel().getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c.getResource(), 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.getChannel().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.getChannel().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor, inputResourceToStateAccessor).toImplementation(sideEffects); - getter.addStatement(sideEffects[0] + "return " + curState + ";"); + // for reference channel members + for (ChannelMember c: d.getChannel().getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c.getResource(), 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.getChannel().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.getChannel().deriveUpdateExpressionOf(out, JavaCodeGenerator.pullAccessor, inputResourceToStateAccessor).toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + "return " + curState + ";"); + } } } } @@ -203,24 +209,26 @@ 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.getResource().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);"); + if (resource.getResource().getNumberOfParameters() == 0) { + MethodDeclaration getter = getGetterMethod(type, null); + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + Type resourceType = resource.getResource().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 @@ -230,28 +238,40 @@ 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 + ";"; + // In the resource + if (resource.getResource().getNumberOfParameters() == 0) { + 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 (input.getBody() == null || !input.getBody().getStatements().contains(updateStatement)) { - input.addFirstStatement(updateStatement); - } + + // In the main type if (mainType != null) { MethodDeclaration mainInput = getMethod(mainType, input.getName()); if (mainInput != null) { String args = ""; - String delimitar = ""; + String delimiter = ""; + for (Selector selector: entry.getKey().getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + args += delimiter + var.getName(); + delimiter = ", "; + } + } if (out.getStateTransition().getMessageExpression() instanceof Term) { Term message = (Term) out.getStateTransition().getMessageExpression(); for (Variable var: message.getVariables().values()) { - args += delimitar + var.getName(); - delimitar = ", "; + args += delimiter + var.getName(); + delimiter = ", "; } } mainInput.addStatement("this." + resourceName + "." + input.getName() + "(" + args + ");"); @@ -286,9 +306,21 @@ return updates; } - private static MethodDeclaration getGetterMethod(TypeDeclaration type) { + private static MethodDeclaration getGetterMethod(TypeDeclaration type, List params) { for (MethodDeclaration m: type.getMethods()) { - if (m.getName().startsWith("get")) return m; + if (m.getName().startsWith("get")) { + if (m.getParameters() == null && (params == null || params.size() == 0)) return m; + if (m.getParameters() != null && params != null && m.getParameters().size() == params.size()) { + boolean matchParams = true; + for (int i = 0; i < m.getParameters().size(); i++) { + if (!m.getParameters().get(i).getType().equals(params.get(i).getType())) { + matchParams = false; + break; + } + } + if (matchParams) return m; + } + } } return null; } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index 7a77fae..e908f01 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -25,6 +25,7 @@ import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.DataTransferChannel; import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; @@ -69,10 +70,32 @@ String resourceName = rn.getResource().getResourceName().substring(0, 1).toUpperCase() + rn.getResource().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.getResource().getResourceName() + "\"")); + TypeDeclaration type = null; + for (CompilationUnit cu: codes) { + for (TypeDeclaration t: cu.types()) { + if (resourceName.equals(t.getTypeName())) { + type = t; + break; + } + } + if (type != null) break; + } + if (type == null) { + // Add compilation unit for each resource. + type = new TypeDeclaration(resourceName); + type.addAnnotation(new Annotation("Component")); + type.addAnnotation(new Annotation("Path", "\"/" + rn.getResource().getResourceName() + "\"")); + + 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 a client field and update methods from other resources. boolean bDeclareClientField = false; @@ -149,12 +172,26 @@ // } // Declare input methods in resources. - for (Channel cg : model.getIOChannels()) { - for (ChannelMember cm : ((DataTransferChannel) cg).getOutputChannelMembers()) { + Channel inCh = null; + for (Channel ch : model.getIOChannels()) { + for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { if (cm.getResource().equals(rn.getResource())) { + inCh = ch; Expression message = cm.getStateTransition().getMessageExpression(); - if (message.getClass() == Term.class) { + if (message instanceof Term) { ArrayList params = new ArrayList<>(); + String resourcePath = "\""; + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + String paramName = var.getName(); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + params.add(param); + resourcePath += "/{" + paramName + "}"; + } + } + resourcePath += "\""; for (Variable var: message.getVariables().values()) { String paramName = var.getName(); VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); @@ -169,16 +206,42 @@ } else { input.addAnnotation(new Annotation("POST")); } + if (ch.getAllSelectors().size() > 0) { + input.addAnnotation(new Annotation("Path", resourcePath)); + } type.addMethod(input); - } else if (message.getClass() == Variable.class) { - MethodDeclaration input = new MethodDeclaration( - ((Variable) cm.getStateTransition().getMessageExpression()).getName(), - false, typeVoid, null); + } else if (message instanceof Variable) { + ArrayList params = new ArrayList<>(); + String resourcePath = "\""; + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + String paramName = var.getName(); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + params.add(param); + resourcePath += "/{" + paramName + "}"; + } + } + resourcePath += "\""; + MethodDeclaration input = null; + if (params.size() > 0) { + input = new MethodDeclaration( + ((Variable) cm.getStateTransition().getMessageExpression()).getName(), + false, typeVoid, params); + } else { + 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")); } + if (ch.getAllSelectors().size() > 0) { + input.addAnnotation(new Annotation("Path", resourcePath)); + } type.addMethod(input); } } @@ -186,27 +249,45 @@ } // Declare the field to store the state in the type of each resource. - if (((StoreAttribute) rn.getAttribute()).isStored()) { - ResourcePath resId = rn.getResource(); - type.addField(new FieldDeclaration(resId.getResourceStateType(), "value", getInitializer(resId))); + if (((StoreAttribute) rn.getAttribute()).isStored() && rn.getResource().getNumberOfParameters() == 0) { + ResourcePath res = rn.getResource(); + type.addField(new FieldDeclaration(res.getResourceStateType(), "value", getInitializer(res))); } // Declare the getter method to obtain the state in the type of each resource. - MethodDeclaration getter = new MethodDeclaration("getValue", rn.getResource().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); + if (inCh == null) { + DataFlowEdge e = (DataFlowEdge) rn.getInEdges().iterator().next(); + if (e != null) { + inCh = e.getChannel(); + } + } + if (inCh != null) { + ArrayList params = new ArrayList<>(); + String resourcePath = "\""; + for (Selector selector: inCh.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + String paramName = var.getName(); + VariableDeclaration param = new VariableDeclaration(var.getType(), paramName); + param.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + params.add(param); + resourcePath += "/{" + paramName + "}"; + } + } + resourcePath += "\""; + MethodDeclaration getter = null; + if (params.size() > 0) { + getter = new MethodDeclaration("getValue", false, rn.getResource().getResourceStateType(), params); + } else { + getter = new MethodDeclaration("getValue", rn.getResource().getResourceStateType()); + } + getter.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); + getter.addAnnotation(new Annotation("GET")); + if (inCh.getAllSelectors().size() > 0) { + getter.addAnnotation(new Annotation("Path", resourcePath)); + } + type.addMethod(getter); + } } // Declare the Pair class. diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 9ad2995..6353287 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -170,11 +170,13 @@ } 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;"); + if (dst.getResource().getNumberOfParameters() == 0) { + // returns the state stored in a field. + MethodDeclaration getter = getGetterMethod(dstType, null); + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + getter.addStatement("return value;"); + } } } // src side (for a chain of update method invocations) @@ -272,22 +274,24 @@ } } 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.getChannel().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.getChannel().getReferenceChannelMembers()) { - String refResourceName = c.getResource().getResourceName(); - Type refResourceType = c.getResource().getResourceStateType(); - generatePullDataTransfer(getter, refResourceName, refResourceType); + if (dst.getResource().getNumberOfParameters() == 0) { + MethodDeclaration getter = getGetterMethod(dstType, null); + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + // generate a return statement. + String[] sideEffects = new String[] {""}; + String curState = d.getChannel().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.getChannel().getReferenceChannelMembers()) { + String refResourceName = c.getResource().getResourceName(); + Type refResourceType = c.getResource().getResourceStateType(); + generatePullDataTransfer(getter, refResourceName, refResourceType); + } } + // get src side resource state by pull data transfer. + Type srcResourceType = src.getResource().getResourceStateType(); + generatePullDataTransfer(getter, srcResourceName, srcResourceType); } - // get src side resource state by pull data transfer. - Type srcResourceType = src.getResource().getResourceStateType(); - generatePullDataTransfer(getter, srcResourceName, srcResourceType); } } } @@ -299,9 +303,11 @@ 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;"); + if (resource.getResource().getNumberOfParameters() == 0) { + MethodDeclaration getter = getGetterMethod(type, null); + if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { + getter.addStatement("return value;"); + } } // methods for input events Map> ioChannelsAndMembers = getIOChannelsAndMembers(resource, model); @@ -310,17 +316,19 @@ 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); + if (resource.getResource().getNumberOfParameters() == 0) { + 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); + } } } } @@ -533,9 +541,21 @@ return updates; } - private static MethodDeclaration getGetterMethod(TypeDeclaration type) { + private static MethodDeclaration getGetterMethod(TypeDeclaration type, List params) { for (MethodDeclaration m: type.getMethods()) { - if (m.getName().startsWith("get")) return m; + if (m.getName().startsWith("get")) { + if (m.getParameters() == null && (params == null || params.size() == 0)) return m; + if (m.getParameters() != null && params != null && m.getParameters().size() == params.size()) { + boolean matchParams = true; + for (int i = 0; i < m.getParameters().size(); i++) { + if (!m.getParameters().get(i).getType().equals(params.get(i).getType())) { + matchParams = false; + break; + } + } + if (matchParams) return m; + } + } } return null; } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java index 4a35051..a564792 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java @@ -1,6 +1,8 @@ package models.dataConstraintModel; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; import models.algebra.Variable; @@ -8,7 +10,7 @@ public class Channel { protected Channel parent = null; protected String channelName; - protected Set selectors = null; + protected List selectors = null; protected Set channelMembers = null; protected String sourceText = null; @@ -20,29 +22,29 @@ this(null, channelName, variable); } - public Channel(String channelName, Set variables) { + public Channel(String channelName, List variables) { this(null, channelName, variables); } public Channel(Channel parent, String channelName) { this.parent = parent; this.channelName = channelName; - selectors = new HashSet<>(); + selectors = new ArrayList<>(); channelMembers = new HashSet<>(); } public Channel(Channel parent, String channelName, Variable variable) { this.parent = parent; this.channelName = channelName; - selectors = new HashSet<>(); + selectors = new ArrayList<>(); selectors.add(new Selector(variable)); channelMembers = new HashSet<>(); } - public Channel(Channel parent, String channelName, Set variables) { + public Channel(Channel parent, String channelName, List variables) { this.parent = parent; this.channelName = channelName; - selectors = new HashSet<>(); + selectors = new ArrayList<>(); for (Variable var: variables) { selectors.add(new Selector(var)); } @@ -61,11 +63,18 @@ return channelName; } - public Set getChannelSelectors() { + public List getSelectors() { return selectors; } - public void setChannelSelectors(Set selectors) { + public List getAllSelectors() { + List allSelectors = new ArrayList<>(); + if (parent != null) allSelectors.addAll(parent.getAllSelectors()); + allSelectors.addAll(selectors); + return allSelectors; + } + + public void setSelectors(List selectors) { this.selectors = selectors; } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java index 10c8657..3f5ca6f 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java @@ -2,6 +2,7 @@ import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Set; import models.algebra.Expression; @@ -28,7 +29,7 @@ this(null, channelName, variable); } - public DataTransferChannel(String channelName, Set variables) { + public DataTransferChannel(String channelName, List variables) { this(null, channelName, variables); } @@ -46,7 +47,7 @@ referenceChannelMembers = new HashSet<>(); } - public DataTransferChannel(DataTransferChannel parent, String channelName, Set variables) { + public DataTransferChannel(DataTransferChannel parent, String channelName, List variables) { super(parent, channelName, variables); inputChannelMembers = new HashSet<>(); outputChannelMembers = new HashSet<>(); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java index 98f1962..25f1d61 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java @@ -25,12 +25,12 @@ Channel cio_setCustomerOff = new Channel("CIO_SetCustomerOff", new Variable("uid")); // set customer's office ChannelMember customer_off_1 = new ChannelMember(customer_off); cio_setCustomerOff.addChannelMember(customer_off_1); - assertEquals(customer_off.getPathParams().get(0), cio_setCustomerOff.getChannelSelectors().iterator().next().getExpression()); + assertEquals(customer_off.getPathParams().get(0), cio_setCustomerOff.getSelectors().iterator().next().getExpression()); Channel cio_setCompanyAdd = new Channel("CIO_SetCompanyAdd", new Variable("cid")); // set companie's address ChannelMember company_add_1 = new ChannelMember(company_add); cio_setCompanyAdd.addChannelMember(company_add_1); - assertEquals(company_add.getPathParams().get(0), cio_setCompanyAdd.getChannelSelectors().iterator().next().getExpression()); + assertEquals(company_add.getPathParams().get(0), cio_setCompanyAdd.getSelectors().iterator().next().getExpression()); Channel c = new Channel("c", new Variable("uid")); // update customer's address ChannelMember customer_off_2 = new ChannelMember(customer_off); @@ -39,8 +39,8 @@ c.addChannelMember(customer_off_2); c.addChannelMember(company_add_2); c.addChannelMember(customer_add_2); - assertEquals(customer_off.getPathParams().get(0), c.getChannelSelectors().iterator().next().getExpression()); - assertEquals(customer_add.getPathParams().get(0), c.getChannelSelectors().iterator().next().getExpression()); + assertEquals(customer_off.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); + assertEquals(customer_add.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); assertEquals(company_add.getPathParams().get(0), new Variable("cid")); model.addIOChannel(cio_setCustomerOff); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java index 939a9f1..29b9fac 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java @@ -35,7 +35,7 @@ DataTransferChannel cio_setCustomerOff = new DataTransferChannel("CIO_SetCustomerOff", new Variable("uid")); // set customer's office (an input channel) ChannelMember customer_off_1 = new ChannelMember(customer_off); cio_setCustomerOff.addChannelMemberAsOutput(customer_off_1); - assertEquals(customer_off.getPathParams().get(0), cio_setCustomerOff.getChannelSelectors().iterator().next().getExpression()); + assertEquals(customer_off.getPathParams().get(0), cio_setCustomerOff.getSelectors().iterator().next().getExpression()); // === cio_setCompanyAdd(cid) === // @@ -44,7 +44,7 @@ DataTransferChannel cio_setCompanyAdd = new DataTransferChannel("CIO_SetCompanyAdd", new Variable("cid")); // set companie's address (an input channel) ChannelMember company_add_1 = new ChannelMember(company_add); cio_setCompanyAdd.addChannelMemberAsOutput(company_add_1); - assertEquals(company_add.getPathParams().get(0), cio_setCompanyAdd.getChannelSelectors().iterator().next().getExpression()); + assertEquals(company_add.getPathParams().get(0), cio_setCompanyAdd.getSelectors().iterator().next().getExpression()); // === c === // @@ -59,8 +59,8 @@ c.addChannelMemberAsInput(customer_off_2); c.addChannelMemberAsInput(company_add_2); c.addChannelMemberAsOutput(customer_add_2); - assertEquals(customer_off.getPathParams().get(0), c.getChannelSelectors().iterator().next().getExpression()); - assertEquals(customer_add.getPathParams().get(0), c.getChannelSelectors().iterator().next().getExpression()); + assertEquals(customer_off.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); + assertEquals(customer_add.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); assertEquals(company_add.getPathParams().get(0), new Variable("cid")); // Construct a data-flow architecture model.