diff --git a/AlgebraicDataflowArchitectureModel/models/Twitter.model b/AlgebraicDataflowArchitectureModel/models/Twitter.model index 5d5c34b..649abac 100644 --- a/AlgebraicDataflowArchitectureModel/models/Twitter.model +++ b/AlgebraicDataflowArchitectureModel/models/Twitter.model @@ -1,5 +1,9 @@ -channel CIO(myId:Str) { - out accounts.{myId}.tweets(t1:List, tweet(text:Str, time:Long)) == cons(tuple(time, text), t1) +channel CIO1(myId:Str) { + out accounts(ac:List, signup(name:Str)) == cons(tuple(name, nil, nil), t1) +} + +channel CIO2(id:Str) { + out accounts.{id}.tweets(t1:List, tweet(text:Str, time:Long)) == cons(tuple(time, text), t1) } channel C(myId:Str; m:Json) { diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java b/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java index 836227a..6cfd4e7 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java @@ -29,28 +29,33 @@ for (Channel channel: channels) { for (ChannelMember member: ((DataTransferChannel) channel).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).getResource().equals(member.getResource())) { - setStoreAttribute(flag, (ResourceNode) node); + for (Node node : graph.getResourceNodes()) { + if (((ResourceNode) node).getInSideResources().contains(member.getResource())) { + setStoreAttribute((ResourceNode) node, flag); } } } } - for (Node node : graph.getNodes()) { + for (Node node : graph.getResourceNodes()) { HashSet inChannels = new HashSet<>(); for(Edge pre : ((ResourceNode) node).getInEdges()) { - inChannels.add(((DataFlowEdge) pre).getChannel()); + if (pre instanceof DataFlowEdge) { + DataFlowEdge dfEdge = (DataFlowEdge) pre; + if (dfEdge.isChannelToResource()) { + inChannels.add(((ChannelNode) dfEdge.getSource()).getChannel()); + } + } } if ((inChannels.size() > 1)) { - setStoreAttribute(true, (ResourceNode) node); + setStoreAttribute((ResourceNode) node, true); } else if (((ResourceNode) node).getAttribute() == null) { - setStoreAttribute(false, (ResourceNode) node); + setStoreAttribute((ResourceNode) node, false); } } return graph; } - static private void setStoreAttribute(boolean flag, ResourceNode node) { + static private void setStoreAttribute(ResourceNode node, boolean flag) { NodeAttribute attr = node.getAttribute(); StoreAttribute store; if (attr != null && attr instanceof NodeAttribute) { @@ -69,17 +74,17 @@ * @return annotated data flow graph */ static public DataFlowGraph annotateWithSelectableDataTransferAttiribute(DataFlowGraph graph) { - List nodes = new ArrayList<>(graph.getNodes()); + List resNodes = new ArrayList<>(graph.getResourceNodes()); // set push only attributes - for (Node n: graph.getNodes()) { - if (nodes.contains(n) && ((StoreAttribute) ((ResourceNode) n).getAttribute()).isNeeded()) { - nodes.remove(n); - trackEdges(n, nodes); + for (Node resNode: graph.getResourceNodes()) { + if (resNodes.contains(resNode) && ((StoreAttribute) ((ResourceNode) resNode).getAttribute()).isNeeded()) { + resNodes.remove(resNode); + trackEdges(resNode, resNodes); } } // set push/pull attributes to the remaining edges for (Edge e : graph.getEdges()) { - if (((DataFlowEdge) e).getAttribute() == null) { + if (!((DataFlowEdge) e).isChannelToResource() && ((DataFlowEdge) e).getAttribute() == null) { PushPullAttribute ppat = new PushPullAttribute(); ppat.addOption(PushPullValue.PUSHorPULL); ppat.addOption(PushPullValue.PUSH); @@ -90,16 +95,19 @@ return graph; } - static private void trackEdges(Node n, List nodes) { + static private void trackEdges(Node resNode, List resNodes) { // 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); + for (Edge chToRes : ((ResourceNode) resNode).getInEdges()) { + Node chNode = chToRes.getSource(); + for (Edge resToCh : ((ChannelNode) chNode).getInEdges()) { + PushPullAttribute ppat = new PushPullAttribute(); + ppat.addOption(PushPullValue.PUSH); + ((DataFlowEdge) resToCh).setAttribute(ppat); + Node resNode2 = resToCh.getSource(); + if (resNodes.contains(resNode2)) { + resNodes.remove(resNode2); + trackEdges(resNode2, resNodes); + } } } } diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java index d29070d..4479246 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java @@ -22,6 +22,7 @@ import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; import models.dataConstraintModel.StateTransition; import models.dataFlowModel.DataTransferModel; @@ -84,7 +85,7 @@ } static public void infer(DataTransferModel model) { - Map> resources = new HashMap<>(); + Map> resources = new HashMap<>(); Map variables = new HashMap<>(); Map, Type>>> messages = new HashMap<>(); Map consOrSet = new HashMap<>(); @@ -128,24 +129,24 @@ for (Channel c : channels) { for (ChannelMember cm : c.getChannelMembers()) { StateTransition st = cm.getStateTransition(); - ResourcePath id = cm.getResource(); + ResourceHierarchy res = cm.getResource().getResourceHierarchy(); // 1.1 Group expressions by resources. - List sameResource = resources.get(id); + List sameResource = resources.get(res); if (sameResource == null) { sameResource = new ArrayList<>(); - resources.put(id, sameResource); + resources.put(res, sameResource); } sameResource.add(st.getCurStateExpression()); if (st.getNextStateExpression() != null) sameResource.add(st.getNextStateExpression()); expToResource.put(System.identityHashCode(st.getCurStateExpression()), sameResource); if (st.getNextStateExpression() != null) expToResource.put(System.identityHashCode(st.getNextStateExpression()), sameResource); Map updatedExps = getUpdateSet(updateFromResource, sameResource); - Type resType = id.getResourceStateType(); + Type resType = res.getResourceStateType(); Expression exp = st.getCurStateExpression(); Type expType = getExpTypeIfUpdatable(resType, exp); if (expType != null) { - id.setResourceStateType(expType); + res.setResourceStateType(expType); for (Expression resExp : sameResource) { if (resExp != exp) { if (resExp instanceof Variable && compareTypes(((Variable) resExp).getType(), expType)) { @@ -168,12 +169,12 @@ updatedExps.put(System.identityHashCode(exp), exp); } } - resType = id.getResourceStateType(); + resType = res.getResourceStateType(); exp = st.getNextStateExpression(); if (exp != null) { expType = getExpTypeIfUpdatable(resType, exp); if (expType != null) { - id.setResourceStateType(expType); + res.setResourceStateType(expType); for (Expression resExp : sameResource) { if (resExp != exp) { if (resExp instanceof Variable && compareTypes(((Variable) resExp).getType(), expType)) { @@ -1056,16 +1057,16 @@ } } - private static void updateResourceTypes(Expression exp, Map> resources, + private static void updateResourceTypes(Expression exp, Map> resources, Map> expToResource, Map> updateFromResource) { List sameResource = expToResource.get(System.identityHashCode(exp)); if (sameResource == null) return; - for (ResourcePath id : resources.keySet()) { - if (resources.get(id) == sameResource) { - Type resType = id.getResourceStateType(); + for (ResourceHierarchy res : resources.keySet()) { + if (resources.get(res) == sameResource) { + Type resType = res.getResourceStateType(); Type newResType = getExpTypeIfUpdatable(resType, exp); if (newResType != null) { - id.setResourceStateType(newResType); + res.setResourceStateType(newResType); Map updateExps = getUpdateSet(updateFromResource, sameResource); for (Expression resExp : sameResource) { if (resExp != exp) { @@ -1626,8 +1627,7 @@ return type.getInterfaceTypeName(); } - private static > Map getUpdateSet( - Map> updateSets, U keySet) { + private static > Map getUpdateSet(Map> updateSets, U keySet) { Map updatedExps = updateSets.get(System.identityHashCode(keySet)); if (updatedExps == null) { updatedExps = new HashMap<>(); diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java index 83acc69..65d20f0 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java @@ -13,9 +13,11 @@ import algorithms.*; import application.editor.Editor; import code.ast.*; +import generators.CodeGeneratorFromDataFlowGraph; import generators.DataTransferMethodAnalyzer; import generators.JavaCodeGenerator; import generators.JavaMethodBodyGenerator; +import generators.JavaSpecific; import models.dataConstraintModel.ResourcePath; import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.ModelExtension; @@ -57,6 +59,7 @@ JavaCodeGenerator.resetMainTypeName(); // use the default main type's name. } editor.setCodes(JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model))); +// editor.setCodes(new CodeGeneratorFromDataFlowGraph().generateCode(model, graph, new JavaSpecific())); ModelExtension.recoverModel(model); for (CompilationUnit file : editor.getCodes()) { System.out.println(file); diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java index d59f7dc..cce92fa 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -44,6 +44,7 @@ import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.DataTransferChannel; import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.ChannelNode; import models.dataFlowModel.DataFlowEdge; import models.dataFlowModel.DataFlowGraph; import models.dataFlowModel.ResourceNode; @@ -354,17 +355,17 @@ // create channel vertices for (Channel c: model.getChannels()) { - DataTransferChannel channelGen = (DataTransferChannel) 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 + DataTransferChannel channel = (DataTransferChannel) c; + if (channelsIn.get(channel) == null || channelsOut.get(channel) == null) { + Object chCell = graph.insertVertex(parent, null, channel.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); port_in.setVertex(true); - graph.addCell(port_in, channel); // insert the input port of a channel + graph.addCell(port_in, chCell); // insert the input port of a channel 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 - channelsIn.put(channelGen, port_in); - channelsOut.put(channelGen, port_out); + graph.addCell(port_out, chCell); // insert the output port of a channel + channelsIn.put(channel, port_in); + channelsOut.put(channel, port_out); } } @@ -378,29 +379,29 @@ // add input, output and reference edges for (Channel ch: model.getChannels()) { - DataTransferChannel channelGen = (DataTransferChannel) ch; + DataTransferChannel channel = (DataTransferChannel) ch; // input edge - for (ResourcePath srcRes: channelGen.getInputResources()) { - graph.insertEdge(parent, null, new SrcDstAttribute(srcRes, channelGen), resources.get(srcRes), channelsIn.get(channelGen), "movable=false"); + for (ResourcePath srcRes: channel.getInputResources()) { + graph.insertEdge(parent, null, new SrcDstAttribute(srcRes, channel), resources.get(srcRes), channelsIn.get(channel), "movable=false"); } // output edge - for (ResourcePath dstRes: channelGen.getOutputResources()) { - graph.insertEdge(parent, null, new SrcDstAttribute(channelGen, dstRes), channelsOut.get(channelGen), resources.get(dstRes), "movable=false"); + for (ResourcePath dstRes: channel.getOutputResources()) { + graph.insertEdge(parent, null, new SrcDstAttribute(channel, dstRes), channelsOut.get(channel), resources.get(dstRes), "movable=false"); } // reference edges - for (ResourcePath refRes: channelGen.getReferenceResources()) { - graph.insertEdge(parent, null, null, resources.get(refRes), channelsIn.get(channelGen), "dashed=true;movable=false"); + for (ResourcePath refRes: channel.getReferenceResources()) { + graph.insertEdge(parent, null, null, resources.get(refRes), channelsIn.get(channel), "dashed=true;movable=false"); } } - for (Channel ioChannelGen: model.getIOChannels()) { - if (channelsOut.get(ioChannelGen) == null) { - Object channel = graph.insertVertex(parent, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex + for (Channel ioChannel: model.getIOChannels()) { + if (channelsOut.get(ioChannel) == null) { + Object channel = graph.insertVertex(parent, null, ioChannel.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex 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((DataTransferChannel) ioChannelGen, port_out); - for (ResourcePath outRes: ((DataTransferChannel) ioChannelGen).getOutputResources()) { + channelsOut.put((DataTransferChannel) ioChannel, port_out); + for (ResourcePath outRes: ((DataTransferChannel) ioChannel).getOutputResources()) { graph.insertEdge(parent, null, null, port_out, resources.get(outRes), "movable=false"); } } @@ -433,16 +434,18 @@ for (Edge e : dataFlowGraph.getEdges()) { if (e instanceof DataFlowEdge) { DataFlowEdge dataFlow = (DataFlowEdge) e; - DataTransferChannel channelGen = dataFlow.getChannel(); - 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.getResource() && edgeAttr.getDestination() == channelGen) { - edgeCell.setValue(dataFlow.getAttribute()); - break; + if (!dataFlow.isChannelToResource()) { + ResourceNode srcRes = (ResourceNode) dataFlow.getSource(); + DataTransferChannel channel = ((ChannelNode) dataFlow.getDestination()).getChannel(); + // input edge + for (Object edge: graph.getChildEdges(parent)) { + mxCell edgeCell = (mxCell) edge; + if (edgeCell.getValue() instanceof SrcDstAttribute) { + SrcDstAttribute edgeAttr = (SrcDstAttribute) edgeCell.getValue(); + if (srcRes.getOutSideResource().equals(edgeAttr.getSource()) && channel.equals(edgeAttr.getDestination())) { + edgeCell.setValue(dataFlow.getAttribute()); + break; + } } } } @@ -479,7 +482,7 @@ } } - public void addResourcePath(ResourcePath parentPath, String resName) { + public ResourcePath addResourcePath(ResourcePath parentPath, String resName) { ResourcePath resourcePath = null; if (resName.startsWith(Parser.LEFT_CURLY_BRACKET) && resName.endsWith(Parser.RIGHT_CURLY_BRACKET)) { TokenStream stream = new Parser.TokenStream(); @@ -487,13 +490,15 @@ stream.addLine(resName.substring(1, resName.length() - 1)); try { Expression exp = parser.parseTerm(stream, getModel()); - resourcePath = getModel().createResourcePath(parentPath, exp); + resourcePath = new ResourcePath(parentPath, exp); + getModel().addResourcePath(resourcePath); } catch (ExpectedRightBracket e) { e.printStackTrace(); - return; + return null; } } else { - resourcePath = getModel().createResourcePath(parentPath, resName); + resourcePath = new ResourcePath(parentPath, resName); + getModel().addResourcePath(resourcePath); } resetDataFlowGraph(); graph.getModel().beginUpdate(); @@ -504,6 +509,7 @@ } finally { graph.getModel().endUpdate(); } + return resourcePath; } public void addChannel(DataTransferChannel channelGen) { @@ -689,7 +695,7 @@ this.dst = dst; } - public Object getSrouce() { + public Object getSource() { return src; } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java new file mode 100644 index 0000000..9a21a20 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -0,0 +1,360 @@ +package generators; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import code.ast.Block; +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +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.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.ChannelNode; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; + +/** + * Common generator for prototypes + * + * @author Nitta + * + */ +public abstract class CodeGenerator { + public static final String fieldOfResourceState = "value"; + public static final String getterOfResourceState = "getValue"; + public static final String updateMethodName = "update"; + private static String mainTypeName = null; + + public static String getMainTypeName() { + return mainTypeName; + } + + public static void setMainTypeName(String mainTypeName) { + CodeGenerator.mainTypeName = mainTypeName; + } + + public static void resetMainTypeName() { + CodeGenerator.mainTypeName = null; + } + + /** + * Generate source codes in specified language from data-flow/control-flow graph. + * + * @param model architecture model + * @param flowGraph data-flow or control-flow graph + * @param langSpec specified language + * @return source codes + */ + public ArrayList generateCode(DataTransferModel model, DataFlowGraph flowGraph, ILanguageSpecific langSpec) { + ArrayList codes = new ArrayList<>(); + + // Sort the all components. + ArrayList components = determineComponentOrder(flowGraph); + + // Add the main component. + if (mainTypeName == null) { + mainTypeName = langSpec.getMainComponentName(); + } + TypeDeclaration mainComponent = langSpec.newTypeDeclaration(mainTypeName); + MethodDeclaration mainConstructor = mainComponent.createConstructor(); + CompilationUnit mainCU = langSpec.newCompilationUnit(mainComponent); + codes.add(mainCU); + + // Generate the other components. + generateCodeFromFlowGraph(model, flowGraph, components, mainComponent, mainConstructor, codes, langSpec); + + return codes; + } + + public abstract void generateCodeFromFlowGraph(DataTransferModel model, DataFlowGraph flowGraph, ArrayList components, + TypeDeclaration mainComponent, MethodDeclaration mainConstructor, ArrayList codes, ILanguageSpecific langSpec); + + private static ArrayList determineComponentOrder(DataFlowGraph graph) { + ArrayList objects = new ArrayList<>(); + Set visited = new HashSet<>(); + Collection allNodes = graph.getResourceNodes(); + for (ResourceNode resNode: allNodes) { + topologicalSort(allNodes, resNode, visited, objects); + } + return objects; + } + + private static void topologicalSort(Collection allNodes, ResourceNode curResNode, Set visited, List orderedList) { + if (visited.contains(curResNode)) return; + visited.add(curResNode); + // a caller is before the callee + for (Edge chToRes: curResNode.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + if (!(resToCh instanceof DataFlowEdge) || ((PushPullAttribute)((DataFlowEdge) resToCh).getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + topologicalSort(allNodes, (ResourceNode) resToCh.getSource(), visited, orderedList); + } + } + } + if (curResNode instanceof ResourceNode) { + for (Edge resToCh: curResNode.getOutEdges()) { + DataFlowEdge de = (DataFlowEdge) resToCh; + if (((PushPullAttribute) de.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + for (Edge chToRes : resToCh.getDestination().getOutEdges()) { + topologicalSort(allNodes, (ResourceNode) chToRes.getDestination(), visited, orderedList); + } + } + } + } + // For reference resources. + ResourceNode cn = null; + if (curResNode instanceof ResourceNode) { + cn = (ResourceNode) curResNode; + } + if (cn != null) { + for (Node n: allNodes) { + ResourceNode resNode = null; + if (n instanceof ResourceNode) { + resNode = (ResourceNode) n; + } + if (resNode != null) { + for (Edge resToCh: resNode.getOutEdges()) { + ChannelNode chNode = (ChannelNode) resToCh.getDestination(); + for (ChannelMember m: chNode.getChannel().getReferenceChannelMembers()) { + if (m.getResource().equals(curResNode.getOutSideResource())) { + topologicalSort(allNodes, resNode, visited, orderedList); + } + } + } + } + } + } + orderedList.add(0, curResNode); + } + + protected void updateMainComponent(DataTransferModel model, TypeDeclaration mainType, MethodDeclaration mainConstructor, Node componentNode, + final List depends, ILanguageSpecific langSpec) { + // Declare the field to refer to each object in the main type. + ResourceNode resNode = null; + String nodeName = null; + if (componentNode instanceof ResourceNode) { + resNode = (ResourceNode) componentNode; + nodeName = resNode.getResourceName(); + } + String componentName = langSpec.toComponentName(nodeName); + // Declare a field to refer each object. + if (langSpec.declareField()) { + FieldDeclaration refField = langSpec.newFieldDeclaration(new Type(componentName, componentName), nodeName); + mainType.addField(refField); + } + // Add a statement to instantiate each object to the main constructor. + List parameters = new ArrayList<>(); + for (ResourcePath id: depends) { + // For the callee objects (the destination resource of push transfer or the source resource of pull transfer). + parameters.add(id.getResourceName()); + } + // For the refs. + if (resNode != null) { + Set refs = new HashSet<>(); + for (Channel cg : model.getChannels()) { + DataTransferChannel ch = (DataTransferChannel) cg; + if (ch.getInputResources().contains(resNode.getOutSideResource())) { + for (ResourcePath id: ch.getReferenceResources()) { + if (!refs.contains(id) && !depends.contains(id)) { + refs.add(id); + String refResName = id.getResourceName(); + parameters.add(refResName); + } + } + } + } + } + + Block mainConstructorBody = mainConstructor.getBody(); + if (mainConstructorBody == null) { + mainConstructorBody = new Block(); + mainConstructor.setBody(mainConstructorBody); + } + mainConstructorBody.addStatement(langSpec.getFieldAccessor(nodeName) + langSpec.getAssignment() + langSpec.getConstructorInvocation(componentName, parameters) + langSpec.getStatementDelimiter()); + } + + protected void addReference(TypeDeclaration component, MethodDeclaration constructor, Node dstNode, ILanguageSpecific langSpec) { + String dstNodeName = null; + if (dstNode instanceof ResourceNode) { + dstNodeName = ((ResourceNode) dstNode).getResourceName(); + } + String dstComponentName = langSpec.toComponentName(dstNodeName); + if (langSpec.declareField()) { + // Declare a field to refer to another component. + component.addField(langSpec.newFieldDeclaration(new Type(dstComponentName, dstComponentName), dstNodeName)); + } + // Initialize the field to refer to another component. + constructor.addParameter(langSpec.newVariableDeclaration(new Type(dstComponentName, dstComponentName), dstNodeName)); + constructor.getBody().addStatement(langSpec.getFieldAccessor(dstNodeName) + langSpec.getAssignment() + dstNodeName + langSpec.getStatementDelimiter()); + } + + protected void fillGetterMethodToReturnStateField(MethodDeclaration getter, Type resStateType, ILanguageSpecific langSpec) { + // returns the state field when all incoming data-flow edges are PUSH-style. + if (langSpec.isValueType(resStateType)) { + getter.addStatement(langSpec.getReturnStatement(langSpec.getFieldAccessor(fieldOfResourceState)) + langSpec.getStatementDelimiter()); // return value; + } else { + // copy the current state to be returned as a 'value' + String implTypeName = resStateType.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; +// } + List parameters = new ArrayList<>(); + parameters.add(langSpec.getFieldAccessor(fieldOfResourceState)); + getter.addStatement(langSpec.getReturnStatement(langSpec.getConstructorInvocation(implTypeName, parameters)) + langSpec.getStatementDelimiter()); // return new Resource(value); + } + } + + protected void declareAccessorInMainComponent(TypeDeclaration mainComponent, ResourcePath accessRes, MethodDeclaration getter, ILanguageSpecific langSpec) { + List params = new ArrayList<>(); + if (getter.getParameters() != null) { + for (VariableDeclaration var: getter.getParameters()) { + params.add(var.getName()); + } + } + MethodDeclaration accessor = null; + if (params.size() == 0) { + accessor = langSpec.newMethodDeclaration("get" + langSpec.toComponentName(accessRes.getResourceName()), accessRes.getResourceStateType()); + } else { + accessor = langSpec.newMethodDeclaration("get" + langSpec.toComponentName(accessRes.getResourceName()), false, accessRes.getResourceStateType(), getter.getParameters()); + } + Block block = new Block(); + if (params.size() == 0) { + block.addStatement(langSpec.getReturnStatement(langSpec.getMethodInvocation(accessRes.getResourceName(), getter.getName())) + langSpec.getStatementDelimiter()); + } else { + block.addStatement(langSpec.getReturnStatement(langSpec.getMethodInvocation(accessRes.getResourceName(), getter.getName(), params)) + langSpec.getStatementDelimiter()); + } + accessor.setBody(block); + mainComponent.addMethod(accessor); + } + + protected void declareFieldsToReferenceResources(DataTransferModel model, ResourceNode resourceNode, TypeDeclaration component, MethodDeclaration constructor, + final List depends, ILanguageSpecific langSpec) { + Set refs = new HashSet<>(); + for (Channel ch : model.getChannels()) { + DataTransferChannel c = (DataTransferChannel) ch; + if (c.getInputResources().contains(resourceNode.getOutSideResource())) { + for (ResourcePath id: c.getReferenceResources()) { + if (!refs.contains(id) && !depends.contains(id)) { + refs.add(id); + String refResName = langSpec.toComponentName(id.getResourceName()); + component.addField(langSpec.newFieldDeclaration(new Type(refResName, refResName), id.getResourceName())); + constructor.addParameter(langSpec.newVariableDeclaration(new Type(refResName, refResName), id.getResourceName())); + constructor.getBody().addStatement(langSpec.getFieldAccessor(id.getResourceName()) + langSpec.getAssignment() + id.getResourceName() + langSpec.getStatementDelimiter()); + } + } + } + } + } + + protected MethodDeclaration getUpdateMethod(Edge inEdge, TypeDeclaration component, + Map>> dataFlowInform, ILanguageSpecific langSpec) { + List passedResoueces = dataFlowInform.get(inEdge).get(PushPullValue.PUSH); + String methodName = updateMethodName; + for (ResourceNode rn: passedResoueces) { + methodName += langSpec.toComponentName(rn.getResourceName()); + } + return getMethod(component, methodName); + } + + protected MethodDeclaration getInputMethod(ResourceNode resourceNode, DataTransferChannel ch, TypeDeclaration component) { + MethodDeclaration input = null; + for (ChannelMember out : ch.getOutputChannelMembers()) { + if (resourceNode.getInSideResources().contains(out.getResource())) { + Expression message = out.getStateTransition().getMessageExpression(); + if (message instanceof Term) { + input = getMethod(component, ((Term) message).getSymbol().getImplName()); + } else if (message instanceof Variable) { + // Declare an input method in this component. + input = getMethod(component, ((Variable) message).getName()); + } + break; + } + } + return input; + } + + protected MethodDeclaration getMethod(TypeDeclaration component, String methodName) { + for (MethodDeclaration m: component.getMethods()) { + if (m.getName().equals(methodName)) return m; + } + return null; + } + + protected IResourceStateAccessor getPushAccessor() { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { + if (target.equals(from)) { + return new Field(fieldOfResourceState, + 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(ResourcePath target, ResourcePath from) { + return new Parameter(target.getResourceName(), + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + }; + } + + protected IResourceStateAccessor getPullAccessor() { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ResourcePath target, ResourcePath from) { + if (target.equals(from)) { + return new Field(fieldOfResourceState, + target.getResourceStateType() != null ? target.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + return getter; + } + + @Override + public Expression getNextStateAccessorFor(ResourcePath target, ResourcePath from) { + Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(target.getResourceName(), target.getResourceStateType())); + return getter; + } + }; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java new file mode 100644 index 0000000..c766ccb --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -0,0 +1,489 @@ +package generators; + +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.Block; +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +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.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.ChannelNode; +import models.dataFlowModel.StoreAttribute; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; + +public class CodeGeneratorFromDataFlowGraph extends CodeGenerator { + + public void generateCodeFromFlowGraph(DataTransferModel model, DataFlowGraph flowGraph, ArrayList components, + TypeDeclaration mainComponent, MethodDeclaration mainConstructor, ArrayList codes, ILanguageSpecific langSpec) { + // For each of other components. + for (Node componentNode: components) { + // Declare this resource. + ResourceNode resourceNode = (ResourceNode) componentNode; + String resourceName = langSpec.toComponentName(resourceNode.getResourceName()); + TypeDeclaration component = getComponent(resourceName, codes); + List depends = new ArrayList<>(); + if (component == null) { + // Add compilation unit for this component. + component = langSpec.newTypeDeclaration(resourceName); + CompilationUnit cu = langSpec.newCompilationUnit(component); + codes.add(cu); + + // Update the main component for this component. + updateMainComponent(model, mainComponent, mainConstructor, componentNode, depends, langSpec); + } + + // Declare the constructor and the fields to refer to other resources. + MethodDeclaration constructor = declareConstructorAndFieldsToReferToResources(resourceNode, component, depends, langSpec); + + ResourcePath res = resourceNode.getOutSideResource(); + Type resStateType = res.getResourceStateType(); + + // Declare the field in this resource to store the state. + if (((StoreAttribute) resourceNode.getAttribute()).isStored() && resourceNode.getNumberOfParameters() == 0) { + FieldDeclaration stateField = langSpec.newFieldDeclaration(resStateType, fieldOfResourceState, langSpec.getFieldInitializer(resStateType, res.getResourceHierarchy().getInitialValue())); + component.addField(stateField); + } + + // Declare the getter method in this resource to obtain the state. + MethodDeclaration getter = declareGetterMethod(resourceNode, component, resStateType, langSpec); + + // Declare the accessor method in the main component to call the getter method. + declareAccessorInMainComponent(mainComponent, res, getter, langSpec); + + // Declare the fields to refer to reference resources. + declareFieldsToReferenceResources(model, resourceNode, component, constructor, depends, langSpec); + + // Declare cache fields and update methods in this resource. + List updates = declareCacheFieldsAndUpdateMethods(resourceNode, component, langSpec); + + // Declare input methods in this component and the main component. + List inputs = declareInputMethodsInThisAndMainComponents(resourceNode, component, mainComponent, model, langSpec); + + if (constructor.getParameters() == null) { + component.removeMethod(constructor); + } + } + } + + private TypeDeclaration getComponent(String resourceName, ArrayList codes) { + TypeDeclaration component = null; + for (CompilationUnit cu: codes) { + for (TypeDeclaration comp: cu.types()) { + if (resourceName.equals(comp.getTypeName())) { + component = comp; + break; + } + } + if (component != null) break; + } + return component; + } + + private MethodDeclaration declareConstructorAndFieldsToReferToResources(ResourceNode resourceNode, TypeDeclaration component, + List depends, ILanguageSpecific langSpec) { + // Declare a constructor in each component. + MethodDeclaration constructor = component.createConstructor(); + Block block = new Block(); + constructor.setBody(block); + + // Declare fields in each component. (for data-flow graph) + for (Edge resToCh: resourceNode.getOutEdges()) { + if (((PushPullAttribute) ((DataFlowEdge) resToCh).getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + for (Edge chToRes: resToCh.getDestination().getOutEdges()) { + // for PUSH transfer + addReference(component, constructor, chToRes.getDestination(), langSpec); + ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); + if (!depends.contains(dstRes)) depends.add(dstRes); + } + } + } + for (Edge chToRes: resourceNode.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + if (((PushPullAttribute) ((DataFlowEdge) resToCh).getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + // for PULL transfer + addReference(component, constructor, resToCh.getSource(), langSpec); + ResourcePath srcRes = ((ResourceNode) resToCh.getSource()).getOutSideResource(); + if (!depends.contains(srcRes)) depends.add(srcRes); + } + } + } + return constructor; + } + + private MethodDeclaration declareGetterMethod(ResourceNode resourceNode, TypeDeclaration component, Type resStateType, ILanguageSpecific langSpec) { + // Declare the getter method of the resource state. + ArrayList params = new ArrayList<>(); + DataTransferChannel inCh = null; + Edge inEdge = resourceNode.getInEdges().iterator().next(); + if (inEdge != null) { + inCh = ((ChannelNode) inEdge.getSource()).getChannel(); + for (Selector selector: inCh.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + params.add(new VariableDeclaration(var.getType(), var.getName())); + } + } + } + MethodDeclaration getter = null; + if (params.size() > 0) { + getter = langSpec.newMethodDeclaration(getterOfResourceState, false, resStateType, params); + } else { + getter = langSpec.newMethodDeclaration(getterOfResourceState, resStateType); + } + component.addMethod(getter); + + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + if (resourceNode.getNumberOfParameters() == 0) { + fillGetterMethodToReturnStateField(getter, resStateType, langSpec); + } + } else { + // invocations to other getter methods when at least one incoming data-flow edges is PULL-style. + boolean isContainedPush = false; + DataTransferChannel ch = null; + HashMap inputResourceToStateAccessor = new HashMap<>(); + for (Edge chToRes: resourceNode.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + DataFlowEdge dIn = (DataFlowEdge) resToCh; + if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // PUSH transfer + isContainedPush = true; + inputResourceToStateAccessor.put(((ResourceNode) resToCh.getSource()).getOutSideResource(), getPushAccessor()); + } else { + // PULL transfer + inputResourceToStateAccessor.put(((ResourceNode) resToCh.getSource()).getOutSideResource(), getPullAccessor()); + ch = ((ChannelNode) resToCh.getDestination()).getChannel(); + } + } + } + // for reference channel members. + for (ChannelMember c: ch.getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c.getResource(), getPullAccessor()); // by pull data transfer + } + + // generate a return statement. + try { + for (ChannelMember out: ch.getOutputChannelMembers()) { + if (resourceNode.getInSideResources().contains(out.getResource())) { + String[] sideEffects = new String[] {""}; + if (!isContainedPush) { + // All incoming edges are in PULL-style. + String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor()).toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); + } else { + // At least one incoming edge is in PUSH-style. + String curState = ch.deriveUpdateExpressionOf(out, getPullAccessor(), inputResourceToStateAccessor).toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); + } + break; + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + } + + return getter; + } + + private List declareCacheFieldsAndUpdateMethods(ResourceNode resourceNode, TypeDeclaration component, ILanguageSpecific langSpec) { + // Declare cash fields and update methods in the component. + String resComponentName = langSpec.toComponentName(resourceNode.getResourceName()); + List updateMethods = new ArrayList<>(); + for (Edge chToRes: resourceNode.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + DataFlowEdge re = (DataFlowEdge) resToCh; + ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); + String srcResName = srcRes.getResourceName(); + String srcResComponentName = langSpec.toComponentName(srcResName); + if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + // for push data transfer + + // Declare an update method in the type of the destination resource. + ArrayList vars = new ArrayList<>(); + vars.add(langSpec.newVariableDeclaration(srcRes.getResourceStateType(), srcRes.getResourceName())); + // For the refs. + DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); + for (ResourcePath ref: ch.getReferenceResources()) { + if (!resourceNode.getInSideResources().contains(ref)) { + vars.add(langSpec.newVariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); + } + } + MethodDeclaration update = langSpec.newMethodDeclaration(updateMethodName + srcResComponentName, false, null, vars); + component.addMethod(update); + updateMethods.add(update); + + // Add a statement to update the state field + if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { + try { + for (ChannelMember out: ((ChannelNode) resToCh.getDestination()).getChannel().getOutputChannelMembers()) { + if (resourceNode.getInSideResources().contains(out.getResource())) { + Expression updateExp = ((ChannelNode) resToCh.getDestination()).getChannel().deriveUpdateExpressionOf(out, getPushAccessor()); + 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] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + curState + langSpec.getStatementDelimiter(); // this.value = ... + } + if (update.getBody() == null || !update.getBody().getStatements().contains(updateStatement)) { + update.addFirstStatement(updateStatement); + } + break; + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e1) { + e1.printStackTrace(); + } + } + + // Declare the field to cache the state of the source resource in the type of the destination resource. + if (resourceNode.getIndegree() > 1) { + // If incoming edges are multiple + if (langSpec.declareField()) { + // Declare the cache field. + FieldDeclaration cacheField = langSpec.newFieldDeclaration( + srcRes.getResourceStateType(), + srcRes.getResourceName(), + langSpec.getFieldInitializer(srcRes.getResourceStateType(), srcRes.getResourceHierarchy().getInitialValue())); + component.addField(cacheField); + + } + // Update the cache field. + String cashStatement = langSpec.getFieldAccessor(srcResName) + langSpec.getAssignment() + srcResName + langSpec.getStatementDelimiter(); + if (update.getBody() == null || !update.getBody().getStatements().contains(cashStatement)) { + update.addFirstStatement(cashStatement); + } + } + + // Add an invocation to another update method (for a chain of update method invocations). + for (Edge resToCh2: resourceNode.getOutEdges()) { + DataFlowEdge dOut = (DataFlowEdge) resToCh2; + if (((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + for (Edge chToRes2: resToCh2.getDestination().getOutEdges()) { + // PUSH transfer + Map> referredResources = new HashMap<>(); + List params = new ArrayList<>(); + params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + Set referredSet = referredResources.get(update); + for (ChannelMember rc: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + // to get the value of reference member. + ResourcePath ref = rc.getResource(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(update, referredSet); + } + if (!resourceNode.getInSideResources().contains(ref)) { + String refVarName = ref.getResourceName(); + if (!referredSet.contains(ref)) { + referredSet.add(ref); + Expression refGetter = getPullAccessor().getCurrentStateAccessorFor(ref, ((ResourceNode) resToCh2.getSource()).getOutSideResource()); + String[] sideEffects = new String[] {""}; + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); + update.addFirstStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refVarName) + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); + } + params.add(refVarName); + } + } + update.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(((ResourceNode) chToRes2.getDestination()).getResourceName()), + updateMethodName + resComponentName, + params) + langSpec.getStatementDelimiter()); // this.dst.updateSrc(value, refParams); + } + } + } + } + } + } + return updateMethods; + } + + private List declareInputMethodsInThisAndMainComponents(ResourceNode resourceNode, TypeDeclaration component, + TypeDeclaration mainComponent, DataTransferModel model, ILanguageSpecific langSpec) { + // Declare input methods. + String resName = resourceNode.getResourceName(); + String resComponentName = langSpec.toComponentName(resName); + List inputMethods = new ArrayList<>(); + for (Channel ch : model.getIOChannels()) { + for (ChannelMember out : ((DataTransferChannel) ch).getOutputChannelMembers()) { + if (resourceNode.getInSideResources().contains(out.getResource())) { + Expression message = out.getStateTransition().getMessageExpression(); + MethodDeclaration input = null; + MethodDeclaration mainInput = null; + if (message instanceof Term) { + // Declare an input method in this component. + 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(langSpec.newVariableDeclaration(var.getType(), var.getName())); + } + input = langSpec.newMethodDeclaration(((Term) message).getSymbol().getImplName(), false, null, params); + component.addMethod(input); + inputMethods.add(input); + + // Declare the accessor in the main component to call the input method. + String str = ((Term) message).getSymbol().getImplName(); + mainInput = getMethod(mainComponent, str); + if (mainInput == null) { + mainInput = langSpec.newMethodDeclaration(str, false, null, params); + mainComponent.addMethod(mainInput); + } else { + // Add type to a parameter without type. + if (mainInput.getParameters() != null) { + for (VariableDeclaration param: mainInput.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 instanceof Variable) { + // Declare an input method in this component. + 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())); + } + } + if (params.size() == 0) { + input = langSpec.newMethodDeclaration(((Variable) message).getName(), null); + } else { + input = langSpec.newMethodDeclaration(((Variable) message).getName(), false, null, params); + } + component.addMethod(input); + inputMethods.add(input); + String str = ((Variable) message).getName(); + + // Declare the accessor in the main component to call the input method. + mainInput = getMethod(mainComponent, str); + if (mainInput == null) { + if (params.size() == 0) { + mainInput = langSpec.newMethodDeclaration(str, null); + } else { + mainInput = langSpec.newMethodDeclaration(str, false, null, params); + } + mainComponent.addMethod(mainInput); + } + } + + // Add an invocation to the accessor method. + if (mainInput != null) { + List args = new ArrayList<>(); + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable var = (Variable) selector.getExpression(); + args.add(var.getName()); + } + } + if (message instanceof Term) { + for (Variable var: message.getVariables().values()) { + args.add(var.getName()); + } + } + mainInput.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(resName), input.getName(), args) + langSpec.getStatementDelimiter()); + } + + if (input != null) { + // Add a statement to update the state field to the input method. + if (resourceNode.getNumberOfParameters() == 0) { + try { + String[] sideEffects = new String[] {""}; + Expression updateExp; + updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getPullAccessor()); + String newState = updateExp.toImplementation(sideEffects); + String updateStatement; + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + } else { + updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); + } + input.addFirstStatement(updateStatement); + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + } + + // Add an invocation to an update method (for a chain of update method invocations). + for (Edge resToCh: resourceNode.getOutEdges()) { + DataFlowEdge dOut = (DataFlowEdge) resToCh; + if (((PushPullAttribute) dOut.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + for (Edge chToRes: resToCh.getDestination().getOutEdges()) { + // PUSH transfer + Map> referredResources = new HashMap<>(); + List params = new ArrayList<>(); + params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + Set referredSet = referredResources.get(input); + for (ChannelMember rc: ((DataTransferChannel) ch).getReferenceChannelMembers()) { + // to get the value of reference member. + ResourcePath ref = rc.getResource(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(input, referredSet); + } + if (!ref.equals(resourceNode.getOutSideResource())) { + String refVarName = ref.getResourceName(); + if (!referredSet.contains(ref)) { + referredSet.add(ref); + Expression refGetter = getPullAccessor().getCurrentStateAccessorFor(ref, ((ResourceNode) resToCh.getSource()).getOutSideResource()); + String[] sideEffects = new String[] {""}; + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); + input.addFirstStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refVarName) + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); + } + params.add(refVarName); + } + } + input.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(((ResourceNode) chToRes.getDestination()).getResourceName()), + updateMethodName + resComponentName, + params) + langSpec.getStatementDelimiter()); // this.dst.updateSrc(value, refParams); + } + } + } + } + } + } + } + return inputMethods; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/DataTransferMethodAnalyzer.java b/AlgebraicDataflowArchitectureModel/src/generators/DataTransferMethodAnalyzer.java index 8e68103..518ec7f 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/DataTransferMethodAnalyzer.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/DataTransferMethodAnalyzer.java @@ -15,7 +15,7 @@ * */ public class DataTransferMethodAnalyzer { - static private HashSet reachableNodes = new HashSet<>(); + static private HashSet reachableNodes = new HashSet<>(); /** * Determine whether each resource state is stored or not depending on selected data transfer methods. @@ -24,7 +24,7 @@ */ static public void decideToStoreResourceStates(DataFlowGraph graph) { reachableNodes.clear(); - for (Node n : graph.getNodes()) { + for (ResourceNode n: graph.getResourceNodes()) { ResourceNode resource = (ResourceNode) n; trackNode(resource); } @@ -35,11 +35,13 @@ 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; + for (Edge chToRes: resource.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + if (((PushPullAttribute) resToCh.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + // Traverse pull edges only. + trackNode((ResourceNode) resToCh.getSource()); + flag = false; + } } } ((StoreAttribute) resource.getAttribute()).setStored(flag); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java new file mode 100644 index 0000000..8f8da21 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java @@ -0,0 +1,41 @@ +package generators; + +import java.util.ArrayList; +import java.util.List; + +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; +import models.algebra.Expression; +import models.algebra.Type; +import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; + +public interface ILanguageSpecific { + CompilationUnit newCompilationUnit(TypeDeclaration component); + TypeDeclaration newTypeDeclaration(String typeName); + VariableDeclaration newVariableDeclaration(Type type, String varName); + MethodDeclaration newMethodDeclaration(String methodName, Type returnType); + MethodDeclaration newMethodDeclaration(String methodName, boolean isConstructor, Type returnType, List parameters); + FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName); + FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName, String fieldInitializer); + Type newTupleType(List compTypes); + String getVariableDeclaration(String typeName, String varName); + String getFieldInitializer(Type type, Expression initialValue); + boolean declareField(); + String getFieldAccessor(String fieldName); + String getMethodInvocation(String methodName); + String getMethodInvocation(String receivertName, String methodName); + String getMethodInvocation(String receivertName, String methodName, List parameters); + String getConstructorInvocation(String componentName, List parameters); + String getReturnStatement(String returnValue); + String toComponentName(String name); + String getMainComponentName(); + String getTupleGet(String tupleExp, int idx, int length); + String getDecomposedTuple(String tupleExp, VariableDeclaration tupleVar, List vars); + String getAssignment(); + String getStatementDelimiter(); + boolean isValueType(Type type); + boolean isVoidType(Type type); +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index 58d4365..abc6a98 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -33,6 +33,7 @@ import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ChannelNode; import models.dataFlowModel.DataFlowEdge; import models.dataFlowModel.DataFlowGraph; import models.dataFlowModel.ResourceNode; @@ -77,8 +78,8 @@ // 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); + String resourceName = rn.getResourceName().substring(0, 1).toUpperCase() + + rn.getResourceName().substring(1); TypeDeclaration type = null; for (CompilationUnit cu: codes) { for (TypeDeclaration t: cu.types()) { @@ -99,37 +100,41 @@ // 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); + for (Edge resToCh: rn.getOutEdges()) { + DataFlowEdge re = (DataFlowEdge) resToCh; if (((PushPullAttribute) re.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { - depends.add(dstRes); - fieldInitializer += resName.toLowerCase() + ","; - f = true; + for (Edge chToRes: re.getDestination().getOutEdges()) { + ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); + String resName = dstRes.getResourceName().substring(0, 1).toUpperCase() + dstRes.getResourceName().substring(1); + 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))); + for (Edge chToRes : rn.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + DataFlowEdge re = (DataFlowEdge) resToCh; + ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); + 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()).getOutSideResource(); + type.addField(new FieldDeclaration( + cashResId.getResourceStateType(), ((ResourceNode) re.getSource()).getOutSideResource().getResourceName(), getInitializer(cashResId))); + } } } } Set refs = new HashSet<>(); for (Channel ch : model.getChannels()) { DataTransferChannel c = (DataTransferChannel) ch; - if (c.getInputResources().contains(rn.getResource())) { + if (c.getInputResources().contains(rn.getOutSideResource())) { for (ResourcePath res: c.getReferenceResources()) { if (!refs.contains(res) && !depends.contains(res)) { refs.add(res); @@ -142,59 +147,63 @@ } if (f) fieldInitializer = fieldInitializer.substring(0, fieldInitializer.length() - 1); fieldInitializer += ")"; - FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), rn.getResource().getResourceName()); + FieldDeclaration field = new FieldDeclaration(new Type(resourceName, resourceName), rn.getResourceName()); mainType.addField(field); Block mainConstructorBody = mainConstructor.getBody(); if (mainConstructorBody == null) { mainConstructorBody = new Block(); mainConstructor.setBody(mainConstructorBody); } - mainConstructorBody.addStatement(rn.getResource().getResourceName() + " = " + fieldInitializer + ";"); + mainConstructorBody.addStatement(rn.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); + for (Edge resToCh : rn.getOutEdges()) { + DataFlowEdge re = (DataFlowEdge) resToCh; 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 chToRes: re.getDestination().getOutEdges()) { + ResourcePath dstRes = ((ResourceNode) chToRes.getDestination()).getOutSideResource(); + String dstResName = dstRes.getResourceName().substring(0, 1).toUpperCase() + dstRes.getResourceName().substring(1); + 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())); + for (Edge chToRes : rn.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + DataFlowEdge re = (DataFlowEdge) resToCh; + ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); + 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 = ((ChannelNode) resToCh.getDestination()).getChannel(); + for (ResourcePath ref: c.getReferenceResources()) { + if (!ref.equals(rn.getOutSideResource())) { + vars.add(new VariableDeclaration(ref.getResourceStateType(), ref.getResourceName())); + } } + type.addMethod(new MethodDeclaration("update" + srcResName, false, typeVoid, vars)); } - 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())) { + if (c.getInputResources().contains(rn.getOutSideResource())) { for (ResourcePath res: c.getReferenceResources()) { if (!refs.contains(res) && !depends.contains(res)) { refs.add(res); @@ -216,7 +225,7 @@ Channel inCh = null; for (Channel ch : model.getIOChannels()) { for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { - if (cm.getResource().equals(rn.getResource())) { + if (rn.getInSideResources().contains(cm.getResource())) { inCh = ch; Expression message = cm.getStateTransition().getMessageExpression(); if (message instanceof Term) { @@ -292,16 +301,16 @@ } // Declare the field to store the state in the type of each resource. - if (((StoreAttribute) rn.getAttribute()).isStored() && rn.getResource().getNumberOfParameters() == 0) { - ResourcePath resId = rn.getResource(); - type.addField(new FieldDeclaration(resId.getResourceStateType(), "value", getInitializer(resId))); + if (((StoreAttribute) rn.getAttribute()).isStored() && rn.getNumberOfParameters() == 0) { + ResourcePath res = rn.getOutSideResource(); + type.addField(new FieldDeclaration(res.getResourceStateType(), "value", getInitializer(res))); } // 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(); + DataFlowEdge chToRes = (DataFlowEdge) rn.getInEdges().iterator().next(); + if (chToRes != null) { + inCh = ((ChannelNode) chToRes.getSource()).getChannel(); } } if (inCh != null) { @@ -314,23 +323,23 @@ } } if (params.size() > 0) { - type.addMethod(new MethodDeclaration("getValue", false, rn.getResource().getResourceStateType(), params)); + type.addMethod(new MethodDeclaration("getValue", false, rn.getResourceStateType(), params)); } else { - type.addMethod(new MethodDeclaration("getValue", rn.getResource().getResourceStateType())); + type.addMethod(new MethodDeclaration("getValue", rn.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), + getter = new MethodDeclaration("get" + rn.getResourceName().substring(0, 1).toUpperCase() + + rn.getResourceName().substring(1), false, - rn.getResource().getResourceStateType(), + rn.getResourceStateType(), params); } else { - getter = new MethodDeclaration("get" + rn.getResource().getResourceName().substring(0, 1).toUpperCase() - + rn.getResource().getResourceName().substring(1), - rn.getResource().getResourceStateType()); + getter = new MethodDeclaration("get" + rn.getResourceName().substring(0, 1).toUpperCase() + + rn.getResourceName().substring(1), + rn.getResourceStateType()); } getter.setBody(new Block()); if (params.size() > 0) { @@ -340,9 +349,9 @@ sParams += delimiter + var.getName(); delimiter = ", "; } - getter.getBody().addStatement("return " + rn.getResource().getResourceName() + ".getValue(" + sParams + ");"); + getter.getBody().addStatement("return " + rn.getResourceName() + ".getValue(" + sParams + ");"); } else { - getter.getBody().addStatement("return " + rn.getResource().getResourceName() + ".getValue();"); + getter.getBody().addStatement("return " + rn.getResourceName() + ".getValue();"); } mainType.addMethod(getter); } @@ -352,9 +361,9 @@ // Declare the Pair class. boolean isCreatedPair = false; - for(ResourceNode rn : resources) { - if(isCreatedPair) continue; - if(model.getType("Pair").isAncestorOf(rn.getResource().getResourceStateType())) { + for (ResourceNode rn : resources) { + if (isCreatedPair) continue; + if (rn.getResourceStateType() != null && model.getType("Pair").isAncestorOf(rn.getResourceStateType())) { TypeDeclaration type = new TypeDeclaration("Pair"); type.addField(new FieldDeclaration(new Type("Double", "T"), "left")); type.addField(new FieldDeclaration(new Type("Double", "T"), "right")); @@ -402,16 +411,16 @@ return codes; } - private static String getInitializer(ResourcePath resId) { - Type stateType = resId.getResourceStateType(); + private static String getInitializer(ResourcePath res) { + Type stateType = res.getResourceStateType(); String initializer = null; - if (resId.getResourceHierarchy().getInitialValue() != null) { - initializer = resId.getResourceHierarchy().getInitialValue().toImplementation(new String[] {""}); - } else { + if (res.getResourceHierarchy().getInitialValue() != null) { + initializer = res.getResourceHierarchy().getInitialValue().toImplementation(new String[] {""}); + } else if (stateType != null) { if (DataConstraintModel.typeList.isAncestorOf(stateType)) { - initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + initializer = "new " + res.getResourceStateType().getImplementationTypeName() + "()"; } else if (DataConstraintModel.typeMap.isAncestorOf(stateType)) { - initializer = "new " + resId.getResourceStateType().getImplementationTypeName() + "()"; + initializer = "new " + res.getResourceStateType().getImplementationTypeName() + "()"; } } return initializer; @@ -465,40 +474,44 @@ 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); + for (Node n : graph.getResourceNodes()) { + ResourceNode resNode = (ResourceNode) n; + topologicalSort(graph, resNode, 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); + static private void topologicalSort(DataFlowGraph graph, ResourceNode curResNode, Set visited, List orderedList) { + if (visited.contains(curResNode)) return; + visited.add(curResNode); + for (Edge chToRes: curResNode.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + DataFlowEdge re = (DataFlowEdge) resToCh; + 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 (Edge resToCh: curResNode.getOutEdges()) { + DataFlowEdge de = (DataFlowEdge) resToCh; + if (((PushPullAttribute) de.getAttribute()).getOptions().get(0) != PushPullValue.PUSH) { + for (Edge chToRes : resToCh.getDestination().getOutEdges()) { + topologicalSort(graph, (ResourceNode) chToRes.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.getChannel().getReferenceChannelMembers()) { - if (m.getResource().equals(curNode.getResource())) { - topologicalSort(graph, rn, visited, orderedList); + for (Node n: graph.getResourceNodes()) { // for reference resources. + ResourceNode resNode = (ResourceNode) n; + for (Edge resToCh : resNode.getOutEdges()) { + ChannelNode chNode = (ChannelNode) resToCh.getDestination(); + for (ChannelMember m: chNode.getChannel().getReferenceChannelMembers()) { + if (m.getResource().equals(curResNode.getOutSideResource())) { + topologicalSort(graph, resNode, visited, orderedList); } } } } - orderedList.add(0, curNode); + orderedList.add(0, curResNode); } private static MethodDeclaration getMethod(TypeDeclaration type, String methodName, List params) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index 9598f60..3e132e4 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -32,6 +32,7 @@ import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ChannelNode; import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; import models.dataFlowModel.DataFlowEdge; import models.dataFlowModel.DataFlowGraph; @@ -52,167 +53,173 @@ 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.getResource().getResourceName(); - String dstResourceName = dst.getResource().getResourceName(); - TypeDeclaration srcType = typeMap.get(srcResourceName); - TypeDeclaration dstType = typeMap.get(dstResourceName); - for (ChannelMember out: d.getChannel().getOutputChannelMembers()) { - if (out.getResource().equals(dst.getResource())) { - 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.getChannel().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]; + DataFlowEdge resToCh = (DataFlowEdge) e; + if (!resToCh.isChannelToResource()) { + PushPullAttribute pushPull = (PushPullAttribute) resToCh.getAttribute(); + ResourceNode src = (ResourceNode) resToCh.getSource(); + for (Edge chToRes: resToCh.getDestination().getOutEdges()) { + ResourceNode dst = (ResourceNode) chToRes.getDestination(); + String srcResourceName = src.getResourceName(); + String dstResourceName = dst.getResourceName(); + TypeDeclaration srcType = typeMap.get(srcResourceName); + TypeDeclaration dstType = typeMap.get(dstResourceName); + for (ChannelMember out: ((ChannelNode) resToCh.getDestination()).getChannel().getOutputChannelMembers()) { + if (dst.getInSideResources().contains(out.getResource())) { + 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 = ((ChannelNode) resToCh.getDestination()).getChannel().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); + } + } + if (((StoreAttribute) dst.getAttribute()).isStored()) { + if (dst.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.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: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + // to get the value of reference member. + ResourcePath ref = rc.getResource(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(srcUpdate, referredSet); + } + if (!dst.getInSideResources().contains(ref)) { + String refVarName = ref.getResourceName(); + if (!referredSet.contains(ref)) { + referredSet.add(ref); + Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getOutSideResource()); + 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: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + // to get the value of reference member. + ResourcePath ref = rc.getResource(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(srcInput, referredSet); + } + if (!dst.getInSideResources().contains(ref)) { + String refVarName = ref.getResourceName(); + if (!referredSet.contains(ref)) { + referredSet.add(ref); + Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getOutSideResource()); + 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 { - 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); - } - } - if (((StoreAttribute) dst.getAttribute()).isStored()) { - 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);"); - } - } - } - } - // 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.getChannel().getReferenceChannelMembers()) { - // to get the value of reference member. - ResourcePath ref = rc.getResource(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(srcUpdate, referredSet); - } - if (!ref.equals(dst.getResource())) { - String refVarName = ref.getResourceName(); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getResource()); + // for pull (or push/pull) data transfer + if (dst.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 chToRes2: dst.getInEdges()) { + for (Edge resToCh2: chToRes2.getSource().getInEdges()) { + DataFlowEdge dIn = (DataFlowEdge) resToCh2; + if (((PushPullAttribute) dIn.getAttribute()).getOptions().get(0) == PushPullValue.PUSH) { + isContainedPush = true; + inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getOutSideResource(), JavaCodeGenerator.pushAccessor); + } else { + inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getOutSideResource(), JavaCodeGenerator.pullAccessor); + } + } + } + // for reference channel members + for (ChannelMember c: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c.getResource(), JavaCodeGenerator.pullAccessor); // by pull data transfer + } 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.getChannel().getReferenceChannelMembers()) { - // to get the value of reference member. - ResourcePath ref = rc.getResource(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(srcInput, referredSet); - } - if (!ref.equals(dst.getResource())) { - String refVarName = ref.getResourceName(); - if (!referredSet.contains(ref)) { - referredSet.add(ref); - Expression refGetter = JavaCodeGenerator.pullAccessor.getCurrentStateAccessorFor(ref, src.getResource()); - 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 - 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); + // generate a return statement. + if (!isContainedPush) { + // All incoming edges are in PULL style. + String curState = ((ChannelNode) resToCh.getDestination()).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 = ((ChannelNode) resToCh.getDestination()).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 + ";"); - } - } + } } - } + } } } } // 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()) { + for (Node n: graph.getResourceNodes()) { ResourceNode resource = (ResourceNode) n; - String resourceName = resource.getResource().getResourceName(); + String resourceName = resource.getResourceName(); TypeDeclaration type = typeMap.get(resourceName); if (type != null) { // getter method - if (resource.getResource().getNumberOfParameters() == 0) { + if (resource.getNumberOfParameters() == 0) { MethodDeclaration getter = getGetterMethod(type, null); if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { - Type resourceType = resource.getResource().getResourceStateType(); + Type resourceType = resource.getResourceStateType(); if (model.isPrimitiveType(resourceType)) { getter.addStatement("return value;"); } else { @@ -239,7 +246,7 @@ MethodDeclaration input = getInputMethod(type, out); if (input != null) { // In the resource - if (resource.getResource().getNumberOfParameters() == 0) { + if (resource.getNumberOfParameters() == 0) { String[] sideEffects = new String[] {""}; Expression updateExp = entry.getKey().deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor); String newState = updateExp.toImplementation(sideEffects); @@ -331,7 +338,7 @@ DataTransferChannel ch = (DataTransferChannel) c; // I/O channel for (ChannelMember out: ch.getOutputChannelMembers()) { - if (out.getResource().equals(resource.getResource())) { + if (resource.getInSideResources().contains(out.getResource())) { if (out.getStateTransition().getMessageExpression() instanceof Term || out.getStateTransition().getMessageExpression() instanceof Variable) { Set channelMembers = ioChannelsAndMembers.get(ch); if (channelMembers == null) { @@ -352,7 +359,7 @@ DataTransferChannel channel = (DataTransferChannel) c; // I/O channel for (ChannelMember out: channel.getOutputChannelMembers()) { - if (out.getResource().equals(resource.getResource())) { + if (resource.getInSideResources().contains(out.getResource())) { MethodDeclaration input = getInputMethod(type, out); inputs.add(input); } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java new file mode 100644 index 0000000..5fbab32 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java @@ -0,0 +1,255 @@ +package generators; + +import java.util.ArrayList; +import java.util.List; + +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.algebra.Expression; +import models.algebra.Parameter; +import models.algebra.Term; +import models.algebra.Type; +import models.algebra.Variable; +import models.dataConstraintModel.DataConstraintModel; + +public class JavaSpecific implements ILanguageSpecific { + public static final Type typeVoid = new Type("Void", "void"); + public static final String self = "this"; + + @Override + public CompilationUnit newCompilationUnit(TypeDeclaration component) { + CompilationUnit cu = new CompilationUnit(component); + cu.addImport(new ImportDeclaration("java.util.*")); + return cu; + } + + @Override + public TypeDeclaration newTypeDeclaration(String typeName) { + return new TypeDeclaration(typeName); + } + + @Override + public VariableDeclaration newVariableDeclaration(Type type, String varName) { + return new VariableDeclaration(type, varName); + } + + @Override + public MethodDeclaration newMethodDeclaration(String methodName, Type returnType) { + if (returnType == null) { + returnType = typeVoid; + } + return new MethodDeclaration(methodName, returnType); + } + + @Override + public MethodDeclaration newMethodDeclaration(String methodName, boolean isConstructor, Type returnType, List parameters) { + if (returnType == null) { + returnType = typeVoid; + } + return new MethodDeclaration(methodName, isConstructor, returnType, parameters); + } + + @Override + public FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName) { + return new FieldDeclaration(fieldType, fieldName); + } + + @Override + public FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName, String fieldInitializer) { + return new FieldDeclaration(fieldType, fieldName, fieldInitializer); + } + + @Override + public Type newTupleType(List componentTypes) { + String implTypeName = "AbstractMap.SimpleEntry<>"; + String interfaceTypeName = "Map.Entry<$x>"; + if (componentTypes.size() >= 2) { + implTypeName = implTypeName.replace("$x", getImplementationTypeName(componentTypes.get(0)) + "$x"); + interfaceTypeName = interfaceTypeName.replace("$x", getInterfaceTypeName(componentTypes.get(0)) + "$x"); + for (Type argType : componentTypes.subList(1, componentTypes.size() - 1)) { + implTypeName = implTypeName.replace("$x", + ", AbstractMap.SimpleEntry<" + getImplementationTypeName(argType) + "$x>"); + interfaceTypeName = interfaceTypeName.replace("$x", + ", Map.Entry<" + getInterfaceTypeName(argType) + "$x>"); + } + implTypeName = implTypeName.replace("$x", + ", " + getImplementationTypeName(componentTypes.get(componentTypes.size() - 1))); + interfaceTypeName = interfaceTypeName.replace("$x", + ", " + getInterfaceTypeName(componentTypes.get(componentTypes.size() - 1))); + } + Type newTupleType = new Type("Tuple", implTypeName, interfaceTypeName, DataConstraintModel.typeTuple); + return newTupleType; + } + + @Override + public String getVariableDeclaration(String typeName, String varName) { + return typeName + " " + varName; + } + + @Override + public String getFieldInitializer(Type type, Expression initialValue) { + String initializer = null; + if (initialValue != null) { + initializer = initialValue.toImplementation(new String[] {""}); + } else if (type != null) { + if (DataConstraintModel.typeList.isAncestorOf(type)) { + initializer = "new " + type.getImplementationTypeName() + "()"; + } else if (DataConstraintModel.typeMap.isAncestorOf(type)) { + initializer = "new " + type.getImplementationTypeName() + "()"; + } + } + return initializer; + } + + @Override + public boolean declareField() { + return true; + } + + @Override + public String getFieldAccessor(String fieldName) { + return self + "." + fieldName; + } + + @Override + public String getMethodInvocation(String methodName) { + return self + "." + methodName + "()"; + } + + @Override + public String getMethodInvocation(String receiverName, String methodName) { + return receiverName + "." + methodName + "()"; + } + + @Override + public String getMethodInvocation(String receiverName, String methodName, List parameters) { + if (parameters == null) return getMethodInvocation(receiverName, methodName); + String invocation = receiverName + "." + methodName + "("; + if (parameters.size() > 0) { + for (int i = 0; i < parameters.size(); i++) { + if (i < parameters.size() - 1) { + invocation += parameters.get(i) + ", "; + } else { + invocation += parameters.get(i); + } + } + } + invocation += ")"; + return invocation; + } + + @Override + public String getConstructorInvocation(String componentName, List parameters) { + String invocation = "new " + componentName + "("; + if (parameters.size() > 0) { + for (int i = 0; i < parameters.size(); i++) { + if (i < parameters.size() - 1) { + invocation += parameters.get(i) + ", "; + } else { + invocation += parameters.get(i); + } + } + } + invocation += ")"; + return invocation; + } + + @Override + public String getReturnStatement(String returnValue) { + return "return " + returnValue; + } + + @Override + public String toComponentName(String name) { + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + + @Override + public String getMainComponentName() { + return "Main"; + } + + @Override + public String getAssignment() { + return " = "; + } + + @Override + public String getStatementDelimiter() { + return ";"; + } + + @Override + public String getTupleGet(String tupleExp, int idx, int length) { + Expression t = new Variable(tupleExp, DataConstraintModel.typeTuple); + for (int i = 0; i < idx; i++) { + Term next = new Term(DataConstraintModel.snd); + next.addChild(t); + t = next; + } + if (idx < length - 1) { + Term last = new Term(DataConstraintModel.fst); + last.addChild(t); + t = last; + } + return t.toImplementation(new String[]{}); + } + + @Override + public String getDecomposedTuple(String tupleExp, VariableDeclaration tupleVar, List vars) { + String statements = ""; + statements += getVariableDeclaration(tupleVar.getType().getInterfaceTypeName(), tupleVar.getName()) + + getAssignment() + tupleExp + getStatementDelimiter(); + for (int i = 0; i < vars.size(); i++) { + VariableDeclaration var = vars.get(i); + statements += "\n" + getVariableDeclaration(var.getType().getInterfaceTypeName(), var.getName()) + + getAssignment() + + getTupleGet(tupleVar.getName(), i, vars.size()) + + getStatementDelimiter(); + } + return statements; + } + + @Override + public boolean isValueType(Type type) { + if (type == DataConstraintModel.typeInt + || type == DataConstraintModel.typeLong + || type == DataConstraintModel.typeFloat + || type == DataConstraintModel.typeDouble + || type == DataConstraintModel.typeBoolean) { + return true; + } + return false; + } + + + @Override + public boolean isVoidType(Type type) { + if (type == typeVoid) { + return true; + } + return false; + } + + private String getImplementationTypeName(Type type) { + if (type == null) + return "Object"; + String wrapperType = DataConstraintModel.getWrapperType(type); + if (wrapperType != null) + return wrapperType; + return type.getImplementationTypeName(); + } + + private String getInterfaceTypeName(Type type) { + if (type == null) + return "Object"; + String wrapperType = DataConstraintModel.getWrapperType(type); + if (wrapperType != null) + return wrapperType; + return type.getInterfaceTypeName(); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index e908f01..f982fc7 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -1,6 +1,7 @@ package generators; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -34,6 +35,7 @@ import models.dataFlowModel.DataFlowEdge; import models.dataFlowModel.DataFlowGraph; import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.ChannelNode; import models.dataFlowModel.StoreAttribute; /** @@ -63,12 +65,12 @@ static public ArrayList doGenerate(DataFlowGraph graph, DataTransferModel model) { ArrayList codes = new ArrayList<>(); // ArrayList resources = StoreResourceCheck(graph); - Set resources = graph.getNodes(); + Collection resources = graph.getResourceNodes(); for (Node n : resources) { ResourceNode rn = (ResourceNode) n; - String resourceName = rn.getResource().getResourceName().substring(0, 1).toUpperCase() - + rn.getResource().getResourceName().substring(1); + String resourceName = rn.getResourceName().substring(0, 1).toUpperCase() + + rn.getResourceName().substring(1); TypeDeclaration type = null; for (CompilationUnit cu: codes) { @@ -84,7 +86,7 @@ // Add compilation unit for each resource. type = new TypeDeclaration(resourceName); type.addAnnotation(new Annotation("Component")); - type.addAnnotation(new Annotation("Path", "\"/" + rn.getResource().getResourceName() + "\"")); + type.addAnnotation(new Annotation("Path", "\"/" + rn.getResourceName() + "\"")); CompilationUnit cu = new CompilationUnit(type); cu.addImport(new ImportDeclaration("java.util.*")); @@ -99,57 +101,59 @@ // Declare a client field and update methods from other resources. boolean bDeclareClientField = false; - for (Edge e : rn.getOutEdges()) { - DataFlowEdge re = (DataFlowEdge) e; + for (Edge resToCh: rn.getOutEdges()) { + DataFlowEdge re = (DataFlowEdge) resToCh; 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; - 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) { - 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 (ResourcePath refRes: re.getChannel().getReferenceResources()) { - if (!refRes.equals(rn.getResource())) { - param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getResourceName()); - param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getResourceName() + "\"")); - vars.add(param); + for (Edge chToRes : rn.getInEdges()) { + for (Edge resToCh: chToRes.getSource().getInEdges()) { + DataFlowEdge re = (DataFlowEdge) resToCh; + ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(); + 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; } - } - MethodDeclaration update = new MethodDeclaration("update" + srcResName, false, typeVoid, vars); - for (ChannelMember cm: re.getChannel().getOutputChannelMembers()) { - if (cm.getResource().equals(rn.getResource())) { - if (cm.getStateTransition().isRightUnary()) { - update.addAnnotation(new Annotation("PUT")); - } else { - update.addAnnotation(new Annotation("POST")); + } 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 (ResourcePath refRes: ((ChannelNode) re.getDestination()).getChannel().getReferenceResources()) { + if (!refRes.equals(rn.getOutSideResource())) { + 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: ((ChannelNode) re.getDestination()).getChannel().getOutputChannelMembers()) { + if (rn.getInSideResources().contains(cm.getResource())) { + 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. + ResourcePath cashRes = ((ResourceNode) re.getSource()).getOutSideResource(); + type.addField(new FieldDeclaration(cashRes.getResourceStateType(), srcName, getInitializer(cashRes))); + } + type.addMethod(update); } - 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. - ResourcePath cashResId = ((ResourceNode) re.getSource()).getResource(); - type.addField(new FieldDeclaration(cashResId.getResourceStateType(), srcName, getInitializer(cashResId))); - } - type.addMethod(update); } } @@ -175,7 +179,7 @@ Channel inCh = null; for (Channel ch : model.getIOChannels()) { for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { - if (cm.getResource().equals(rn.getResource())) { + if (rn.getInSideResources().contains(cm.getResource())) { inCh = ch; Expression message = cm.getStateTransition().getMessageExpression(); if (message instanceof Term) { @@ -249,16 +253,16 @@ } // Declare the field to store the state in the type of each resource. - if (((StoreAttribute) rn.getAttribute()).isStored() && rn.getResource().getNumberOfParameters() == 0) { - ResourcePath res = rn.getResource(); + if (((StoreAttribute) rn.getAttribute()).isStored() && rn.getNumberOfParameters() == 0) { + ResourcePath res = rn.getOutSideResource(); type.addField(new FieldDeclaration(res.getResourceStateType(), "value", getInitializer(res))); } // Declare the getter method to obtain the state in the type of each resource. if (inCh == null) { - DataFlowEdge e = (DataFlowEdge) rn.getInEdges().iterator().next(); - if (e != null) { - inCh = e.getChannel(); + DataFlowEdge chToRes = (DataFlowEdge) rn.getInEdges().iterator().next(); + if (chToRes != null) { + inCh = ((ChannelNode) chToRes.getSource()).getChannel(); } } if (inCh != null) { @@ -277,9 +281,9 @@ resourcePath += "\""; MethodDeclaration getter = null; if (params.size() > 0) { - getter = new MethodDeclaration("getValue", false, rn.getResource().getResourceStateType(), params); + getter = new MethodDeclaration("getValue", false, rn.getResourceStateType(), params); } else { - getter = new MethodDeclaration("getValue", rn.getResource().getResourceStateType()); + getter = new MethodDeclaration("getValue", rn.getResourceStateType()); } getter.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); getter.addAnnotation(new Annotation("GET")); @@ -295,7 +299,7 @@ for(Node n : resources) { ResourceNode rn = (ResourceNode) n; if(isCreatedPair) continue; - if(model.getType("Pair").isAncestorOf(rn.getResource().getResourceStateType())) { + if(model.getType("Pair").isAncestorOf(rn.getResourceStateType())) { TypeDeclaration type = new TypeDeclaration("Pair"); type.addField(new FieldDeclaration(new Type("Double", "T"), "left")); type.addField(new FieldDeclaration(new Type("Double", "T"), "right")); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 6353287..2fec5d8 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -33,6 +33,7 @@ import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.dataFlowModel.ChannelNode; import models.dataFlowModel.DataFlowEdge; import models.dataFlowModel.DataFlowGraph; import models.dataFlowModel.ResourceNode; @@ -56,254 +57,260 @@ 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.getResource().getResourceName(); - String dstResourceName = dst.getResource().getResourceName(); - TypeDeclaration srcType = typeMap.get(srcResourceName); - TypeDeclaration dstType = typeMap.get(dstResourceName); - for (ChannelMember out: d.getChannel().getOutputChannelMembers()) { - if (out.getResource().equals(dst.getResource())) { - 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.getChannel().getReferenceChannelMembers().size() == 0) { - updateExp = d.getChannel().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); - } else { - // if there exists one or more reference channel member. - HashMap inputResourceToStateAccessor = new HashMap<>(); - for (Edge eIn: dst.getInEdges()) { - DataFlowEdge dIn = (DataFlowEdge) eIn; - inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getResource(), JerseyCodeGenerator.pushAccessor); + DataFlowEdge resToCh = (DataFlowEdge) e; + if (!resToCh.isChannelToResource()) { + PushPullAttribute pushPull = (PushPullAttribute) resToCh.getAttribute(); + ResourceNode src = (ResourceNode) resToCh.getSource(); + for (Edge chToRes: resToCh.getDestination().getOutEdges()) { + ResourceNode dst = (ResourceNode) chToRes.getDestination(); + String srcResourceName = src.getResourceName(); + String dstResourceName = dst.getResourceName(); + TypeDeclaration srcType = typeMap.get(srcResourceName); + TypeDeclaration dstType = typeMap.get(dstResourceName); + for (ChannelMember out: ((ChannelNode) resToCh.getDestination()).getChannel().getOutputChannelMembers()) { + if (dst.getInSideResources().contains(out.getResource())) { + 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 (((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers().size() == 0) { + updateExp = ((ChannelNode) resToCh.getDestination()).getChannel().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); + } else { + // if there exists one or more reference channel member. + HashMap inputResourceToStateAccessor = new HashMap<>(); + for (Edge chToRes2: dst.getInEdges()) { + for (Edge resToCh2: chToRes2.getSource().getInEdges()) { + DataFlowEdge dIn = (DataFlowEdge) resToCh2; + inputResourceToStateAccessor.put(((ResourceNode) dIn.getSource()).getOutSideResource(), JerseyCodeGenerator.pushAccessor); + } + } + for (ChannelMember c: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(c.getResource(), JerseyCodeGenerator.pullAccessor); + } + updateExp = ((ChannelNode) resToCh.getDestination()).getChannel().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputResourceToStateAccessor); + } + 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); + } } - for (ChannelMember c: d.getChannel().getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c.getResource(), JerseyCodeGenerator.pullAccessor); + 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); + } } - updateExp = d.getChannel().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputResourceToStateAccessor); - } - 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. + // 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); } - } 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); - } - if (((StoreAttribute) dst.getAttribute()).isStored()) { - 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;"); + if (((StoreAttribute) dst.getAttribute()).isStored()) { + if (dst.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) - 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.getChannel().getReferenceChannelMembers().size() > 0) { - for (ChannelMember rc: d.getChannel().getReferenceChannelMembers()) { + // 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 (((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers().size() > 0) { + for (ChannelMember rc: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { + // For each reference channel member, get the current state of the reference side resource by pull data transfer. + ResourcePath ref = rc.getResource(); + if (referredSet == null) { + referredSet = new HashSet<>(); + referredResources.put(srcUpdate, referredSet); + } + if (!dst.getInSideResources().contains(ref)) { + 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.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.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: ((ChannelNode) resToCh.getDestination()).getChannel().getReferenceChannelMembers()) { // For each reference channel member, get the current state of the reference side resource by pull data transfer. ResourcePath ref = rc.getResource(); if (referredSet == null) { referredSet = new HashSet<>(); - referredResources.put(srcUpdate, referredSet); + referredResources.put(srcInput, referredSet); } - if (!ref.equals(dst.getResource())) { + if (!dst.getInSideResources().contains(ref)) { String refResourceName = ref.getResourceName(); Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { referredSet.add(ref); - generatePullDataTransfer(srcUpdate, refResourceName, refResourceType); + 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.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.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 + if (dst.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 = ((ChannelNode) resToCh.getDestination()).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: ((ChannelNode) resToCh.getDestination()).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.getResourceStateType(); + generatePullDataTransfer(getter, srcResourceName, srcResourceType); } - 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.getResource().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.getResource().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.getChannel().getReferenceChannelMembers()) { - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - ResourcePath ref = rc.getResource(); - if (referredSet == null) { - referredSet = new HashSet<>(); - referredResources.put(srcInput, referredSet); - } - if (!ref.equals(dst.getResource())) { - 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.getResource().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.getResource().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 - 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); - } - } + } } } } // for source nodes - for (Node n: graph.getNodes()) { + for (Node n: graph.getResourceNodes()) { ResourceNode resource = (ResourceNode) n; - String resourceName = resource.getResource().getResourceName(); + String resourceName = resource.getResourceName(); TypeDeclaration type = typeMap.get(resourceName); if (type != null) { // getter method - if (resource.getResource().getNumberOfParameters() == 0) { + if (resource.getNumberOfParameters() == 0) { MethodDeclaration getter = getGetterMethod(type, null); if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { getter.addStatement("return value;"); @@ -316,7 +323,7 @@ for (ChannelMember out: outs) { MethodDeclaration input = getInputMethod(type, out); if (input != null) { - if (resource.getResource().getNumberOfParameters() == 0) { + if (resource.getNumberOfParameters() == 0) { Expression updateExp = entry.getKey().deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor); String[] sideEffects = new String[] {""}; String newState = updateExp.toImplementation(sideEffects); @@ -566,7 +573,7 @@ DataTransferChannel ch = (DataTransferChannel) c; // I/O channel for (ChannelMember out: ch.getOutputChannelMembers()) { - if (out.getResource().equals(resource.getResource())) { + if (resource.getInSideResources().contains(out.getResource())) { if (out.getStateTransition().getMessageExpression() instanceof Term || out.getStateTransition().getMessageExpression() instanceof Variable) { Set channelMembers = ioChannelsAndMembers.get(ch); if (channelMembers == null) { @@ -587,7 +594,7 @@ DataTransferChannel channel = (DataTransferChannel) c; // I/O channel for (ChannelMember out: channel.getOutputChannelMembers()) { - if (out.getResource().equals(resource.getResource())) { + if (resource.getInSideResources().contains(out.getResource())) { MethodDeclaration input = getInputMethod(type, out); inputs.add(input); } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java index a564792..c7b96ae 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java @@ -8,42 +8,34 @@ import models.algebra.Variable; public class Channel { - protected Channel parent = null; protected String channelName; + protected Channel parent = null; + protected List children = null; protected List selectors = null; protected Set channelMembers = null; protected String sourceText = null; public Channel(String channelName) { - this(null, channelName); - } - - public Channel(String channelName, Variable variable) { - this(null, channelName, variable); - } - - public Channel(String channelName, List variables) { - this(null, channelName, variables); - } - - public Channel(Channel parent, String channelName) { - this.parent = parent; this.channelName = channelName; + this.parent = null; + this.children = new ArrayList<>(); selectors = new ArrayList<>(); channelMembers = new HashSet<>(); } - public Channel(Channel parent, String channelName, Variable variable) { - this.parent = parent; + public Channel(String channelName, Variable variable) { this.channelName = channelName; + this.parent = null; + this.children = new ArrayList<>(); selectors = new ArrayList<>(); selectors.add(new Selector(variable)); channelMembers = new HashSet<>(); } - public Channel(Channel parent, String channelName, List variables) { - this.parent = parent; + public Channel(String channelName, List variables) { this.channelName = channelName; + this.parent = null; + this.children = new ArrayList<>(); selectors = new ArrayList<>(); for (Variable var: variables) { selectors.add(new Selector(var)); @@ -51,16 +43,21 @@ channelMembers = new HashSet<>(); } + public String getChannelName() { + return channelName; + } + public Channel getParent() { return parent; } - - public void setParent(Channel parent) { - this.parent = parent; + + public List getChildren() { + return children; } - public String getChannelName() { - return channelName; + public void addChild(Channel child) { + children.add(child); + child.parent = this; } public List getSelectors() { diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java index a5a5206..b5068fa 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java @@ -14,7 +14,7 @@ import parser.Parser; public class DataConstraintModel { - protected HashMap resourcePaths = null; + protected List resourcePaths = null; protected HashMap resourceHierarchies = null; protected HashMap channels = null; protected HashMap ioChannels = null; @@ -222,7 +222,7 @@ } public DataConstraintModel() { - resourcePaths = new HashMap<>(); + resourcePaths = new ArrayList<>(); resourceHierarchies = new HashMap<>(); channels = new HashMap<>(); ioChannels = new HashMap<>(); @@ -296,64 +296,41 @@ return resourceHierarchies.get(hierarchy); } - public Collection getResourcePaths() { - return resourcePaths.values(); - } - - public ResourcePath getResourcePath(String resourcePath) { - return resourcePaths.get(resourcePath); - } - - public ResourcePath createResourcePath(ResourcePath parent, String resourceName) { - List pathParams = new ArrayList<>(); - ResourceHierarchy hierarchy = null; - if (parent != null) { - pathParams.addAll(parent.getPathParams()); - hierarchy = parent.getResourceHierarchy(); - } - hierarchy = new ResourceHierarchy(hierarchy, resourceName); - return createResourcePath(hierarchy, pathParams); - } - - public ResourcePath createResourcePath(ResourcePath parent, Expression param) { - List pathParams = new ArrayList<>(); - ResourceHierarchy hierarchy = null; - if (parent != null) { - pathParams.addAll(parent.getPathParams()); - hierarchy = parent.getResourceHierarchy(); - } - pathParams.add(param); - hierarchy = new ResourceHierarchy(hierarchy, 1); - return createResourcePath(hierarchy, pathParams); - } - - public ResourcePath createResourcePath(ResourceHierarchy newHierarchy, List pathParams) { - ResourceHierarchy hierarchy = resourceHierarchies.get(newHierarchy.toString()); - if (hierarchy == null) { - resourceHierarchies.put(newHierarchy.toString(), newHierarchy); - hierarchy = newHierarchy; - } - ResourcePath resourcePath = new ResourcePath(hierarchy, pathParams); - resourcePaths.put(resourcePath.toString(), resourcePath); - return resourcePath; + public List getResourcePaths() { + return resourcePaths; } public void addResourcePath(ResourcePath resourcePath) { - resourcePaths.put(resourcePath.toString(), resourcePath); + ResourceHierarchy hierarchy = resourcePath.getResourceHierarchy(); + do { + if (resourceHierarchies.get(hierarchy.toString()) == null) { + resourceHierarchies.put(hierarchy.toString(), hierarchy); + } + hierarchy = hierarchy.getParent(); + } while (hierarchy != null); + resourcePaths.add(resourcePath); } - public void setResourcePaths(HashMap resourcePaths) { + public void setResourcePaths(List resourcePaths) { this.resourcePaths = resourcePaths; } - public void removeResourcePath(String resourcePath) { - ResourcePath res = resourcePaths.get(resourcePath); + public ResourcePath getResourcePath(String path) { + for (ResourcePath resourcePath: resourcePaths) { + if (resourcePath.toString().equals(path)) return resourcePath; + } + return null; + } + + public void removeResourcePath(String path) { + ResourcePath resourcePath = getResourcePath(path); + if (resourcePath == null) return; resourcePaths.remove(resourcePath); for (Channel ch: channels.values()) { - ch.removeChannelMember(res); + ch.removeChannelMember(resourcePath); } for (Channel ch: ioChannels.values()) { - ch.removeChannelMember(res); + ch.removeChannelMember(resourcePath); } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java index 7efeccf..f3a19c6 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ResourcePath.java @@ -11,21 +11,39 @@ import models.algebra.Term; public class ResourcePath extends Symbol { + protected ResourcePath parent = null; protected ResourceHierarchy resourceHierarchy = null; protected List pathParams = null; - public ResourcePath(ResourceHierarchy resourceHierarchy) { - super(resourceHierarchy.toString(), 2); - this.resourceHierarchy = resourceHierarchy; + public ResourcePath(String resourceName) { + super(resourceName); + this.resourceHierarchy = new ResourceHierarchy(null, resourceName); this.pathParams = new ArrayList<>(); } - - public ResourcePath(ResourceHierarchy resourceHierarchy, List pathParams) { - super(resourceHierarchy.toString(pathParams), 2); - this.resourceHierarchy = resourceHierarchy; - this.pathParams = pathParams; + + public ResourcePath(ResourcePath parent, String resourceName) { + super(parent.toString() + "." + resourceName); + this.parent = parent; + this.resourceHierarchy = new ResourceHierarchy(parent.getResourceHierarchy(), resourceName); + this.pathParams = parent.getPathParams(); } + public ResourcePath(ResourcePath parent, Expression exp) { + super(parent.toString() + ".{" + exp + "}"); + this.parent = parent; + this.resourceHierarchy = new ResourceHierarchy(parent.getResourceHierarchy(), 1); + this.pathParams = new ArrayList<>(parent.getPathParams()); + this.pathParams.add(exp); + } + + public ResourcePath(ResourcePath parent, List pathParams) { + super(parent.toString() + ".{" + pathParams.toString() + "}"); + this.resourceHierarchy = new ResourceHierarchy(parent.getResourceHierarchy(), pathParams.size()); + this.pathParams = new ArrayList<>(parent.getPathParams()); + this.pathParams.addAll(pathParams); + } + + public ResourceHierarchy getResourceHierarchy() { return resourceHierarchy; } @@ -59,12 +77,7 @@ } public ResourcePath getParent() { - if (resourceHierarchy.getParent() == null) return null; - if (resourceHierarchy.getNumParameters() > 0) { - return new ResourcePath(resourceHierarchy.getParent(), pathParams.subList(0, pathParams.size() - 1)); - } else { - return new ResourcePath(resourceHierarchy.getParent(), pathParams); - } + return parent; } public ResourcePath getCommonPrefix(ResourcePath another) { diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ChannelNode.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ChannelNode.java new file mode 100644 index 0000000..108bc21 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ChannelNode.java @@ -0,0 +1,39 @@ +package models.dataFlowModel; + +import java.util.HashSet; +import java.util.Set; + +import models.Node; + +public class ChannelNode extends Node { + protected ChannelNode parent = null; + protected Set children = null; + protected DataTransferChannel channel = null; + + public ChannelNode(ChannelNode parent, DataTransferChannel channel) { + this.parent = parent; + this.channel = channel; + this.children = new HashSet<>(); + } + + public ChannelNode getParent() { + return parent; + } + + public Set getChildren() { + return children; + } + + public void addChild(ChannelNode child) { + children.add(child); + child.parent = this; + } + + public DataTransferChannel getChannel() { + return channel; + } + + public void setChannel(DataTransferChannel channel) { + this.channel = channel; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowEdge.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowEdge.java index 9de9359..6b35380 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowEdge.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowEdge.java @@ -3,18 +3,23 @@ import models.*; public class DataFlowEdge extends Edge { - protected DataTransferChannel channel = null; + protected boolean channelToResource = false; - public DataFlowEdge(ResourceNode src, ResourceNode dst, DataTransferChannel channel) { + public DataFlowEdge(ResourceNode src, ChannelNode dst) { super(src, dst); - this.channel = channel; + channelToResource = false; } - - public DataTransferChannel getChannel() { - return channel; + + public DataFlowEdge(ChannelNode src, ResourceNode dst) { + super(src, dst); + channelToResource = true; } - - public String toString() { - return channel.getChannelName(); + + public boolean isChannelToResource() { + return channelToResource; } + +// public String toString() { +// return channel.getChannelName(); +// } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java index ffdcff7..28288c9 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataFlowGraph.java @@ -1,40 +1,107 @@ package models.dataFlowModel; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import models.DirectedGraph; import models.dataConstraintModel.ResourcePath; public class DataFlowGraph extends DirectedGraph { - protected Map nodeMap = null; + protected Set rootResourceNodes = null; + protected Set rootChannelNodes = null; + protected Map channelNodeMap = null; + protected Map resourceNodeMap = null; public DataFlowGraph() { super(); - nodeMap = new HashMap<>(); + rootResourceNodes = new HashSet<>(); + rootChannelNodes = new HashSet<>(); + channelNodeMap = new HashMap<>(); + resourceNodeMap = new HashMap<>(); } - public void addNode(ResourcePath res) { - if (nodeMap.get(res) == null) { - ResourceNode node = new ResourceNode(res); + public ResourceNode addResourceNode(ResourceNode parent, + DataTransferChannel outSideChannel, + ResourcePath outSideResource) { + ResourceNode node = resourceNodeMap.get(outSideResource); + if (node != null) return node; + node = new ResourceNode(parent, outSideChannel, outSideResource); addNode(node); - nodeMap.put(res, node); + if (parent == null) { + rootResourceNodes.add(node); + } else { + parent.addChild(node); } + resourceNodeMap.put(outSideResource, node); + return node; + } + + public ResourceNode addResourceNode(ResourceNode parent, + Map inSide, + Map.Entry outSide) { + ResourceNode node = resourceNodeMap.get(outSide.getValue()); + if (node != null) return node; + node = new ResourceNode(parent, inSide, outSide); + addNode(node); + if (parent == null) { + rootResourceNodes.add(node); + } else { + parent.addChild(node); + } + resourceNodeMap.put(outSide.getValue(), node); + return node; + } + + public ChannelNode addChannelNode(ChannelNode parent, DataTransferChannel ch) { + ChannelNode node = channelNodeMap.get(ch); + if (node != null) return node; + node = new ChannelNode(parent, ch); + addNode(node); + if (parent == null) { + rootChannelNodes.add(node); + } else { + parent.addChild(node); + } + channelNodeMap.put(ch, node); + return node; + } + + public ResourceNode getResourceNode(ResourcePath outSide) { + return resourceNodeMap.get(outSide); + } + + public ChannelNode getChannelNode(DataTransferChannel channel) { + return channelNodeMap.get(channel); + } + + public Collection getResourceNodes() { + return resourceNodeMap.values(); + } + + public Collection getChannelNodes() { + return channelNodeMap.values(); } - public void addEdge(ResourcePath in, ResourcePath out, DataTransferChannel 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)); + public Set getRootResourceNodes() { + return rootResourceNodes; + } + + public Set getRootChannelNodes() { + return rootChannelNodes; + } + + public DataFlowEdge addEdge(ResourceNode srcNode, ChannelNode dstNode) { + DataFlowEdge edge =new DataFlowEdge(srcNode, dstNode); + addEdge(edge); + return edge; + } + + public DataFlowEdge addEdge(ChannelNode srcNode, ResourceNode dstNode) { + DataFlowEdge edge = new DataFlowEdge(srcNode, dstNode); + addEdge(edge); + return edge; } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java index 3f5ca6f..2c906b0 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java @@ -22,33 +22,21 @@ protected Set referenceChannelMembers = null; public DataTransferChannel(String channelName) { - this(null, channelName); + super(channelName); + inputChannelMembers = new HashSet<>(); + outputChannelMembers = new HashSet<>(); + referenceChannelMembers = new HashSet<>(); } public DataTransferChannel(String channelName, Variable variable) { - this(null, channelName, variable); + super(channelName, variable); + inputChannelMembers = new HashSet<>(); + outputChannelMembers = new HashSet<>(); + referenceChannelMembers = new HashSet<>(); } - + public DataTransferChannel(String channelName, List variables) { - this(null, channelName, variables); - } - - public DataTransferChannel(DataTransferChannel parent, String channelName) { - super(parent, channelName); - inputChannelMembers = new HashSet<>(); - outputChannelMembers = new HashSet<>(); - referenceChannelMembers = new HashSet<>(); - } - - public DataTransferChannel(DataTransferChannel parent, String channelName, Variable variable) { - super(parent, channelName, variable); - inputChannelMembers = new HashSet<>(); - outputChannelMembers = new HashSet<>(); - referenceChannelMembers = new HashSet<>(); - } - - public DataTransferChannel(DataTransferChannel parent, String channelName, List variables) { - super(parent, channelName, variables); + super(channelName, variables); inputChannelMembers = new HashSet<>(); outputChannelMembers = new HashSet<>(); referenceChannelMembers = new HashSet<>(); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java index db43b80..c94b787 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java @@ -1,31 +1,85 @@ package models.dataFlowModel; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; import java.util.Set; import models.dataConstraintModel.Channel; import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; public class DataTransferModel extends DataConstraintModel { public DataFlowGraph getDataFlowGraph() { DataFlowGraph dataFlowGraph = new DataFlowGraph(); + Map> resourceMap = new HashMap<>(); for (Channel channel: getChannels()) { - DataTransferChannel dfChannel = (DataTransferChannel)channel; - Set inputResources = dfChannel.getInputResources(); - Set outputResources = dfChannel.getOutputResources(); - for (ResourcePath in: inputResources) { - for (ResourcePath out: outputResources) { - dataFlowGraph.addEdge(in ,out, dfChannel); - } - } + addResourceToChannelEdges(dataFlowGraph, channel, null, resourceMap); + } + for (Channel channel: getChannels()) { + addChannelToResourceEdges(dataFlowGraph, channel, null, resourceMap); } for (Channel channel: getIOChannels()) { - DataTransferChannel dfChannel = (DataTransferChannel)channel; - Set outputResources = dfChannel.getOutputResources(); - for (ResourcePath out: outputResources) { - dataFlowGraph.addNode(out); - } + addChannelToResourceEdges(dataFlowGraph, channel, null, resourceMap); } return dataFlowGraph; } + + private void addResourceToChannelEdges(DataFlowGraph dataFlowGraph, Channel channel, ChannelNode parentNode, + Map> resourceMap) { + DataTransferChannel dfChannel = (DataTransferChannel)channel; + ChannelNode channelNode = dataFlowGraph.addChannelNode(parentNode, dfChannel); + Set inputResources = dfChannel.getInputResources(); + for (ResourcePath inRes: inputResources) { + ResourceNode resNode = addResourceNodes(dataFlowGraph, inRes, dfChannel, resourceMap); + dataFlowGraph.addEdge(resNode, channelNode); + } + for (Channel childChannel: dfChannel.getChildren()) { + addResourceToChannelEdges(dataFlowGraph, childChannel, channelNode, resourceMap); + } + } + + private void addChannelToResourceEdges(DataFlowGraph dataFlowGraph, Channel channel, ChannelNode parentNode, + Map> resourceMap) { + DataTransferChannel dfChannel = (DataTransferChannel)channel; + Set outputResources = dfChannel.getOutputResources(); + ChannelNode channelNode = dataFlowGraph.addChannelNode(parentNode, dfChannel); + for (ResourcePath outRes: outputResources) { + Set resSet = resourceMap.get(outRes.getResourceHierarchy()); + if (resSet == null || resSet.size() == 0) { + ResourceNode resNode = addResourceNodes(dataFlowGraph, outRes, dfChannel, resourceMap); + if (resSet == null) { + resSet = new HashSet<>(); + resourceMap.put(outRes.getResourceHierarchy(), resSet); + } + resSet.add(resNode); + } + for (ResourceNode resNode: resSet) { + resNode.addInSideResource(dfChannel, outRes); + dataFlowGraph.addEdge(channelNode, resNode); + } + } + for (Channel childChannel: dfChannel.getChildren()) { + addChannelToResourceEdges(dataFlowGraph, childChannel, channelNode, resourceMap); + } + } + + private ResourceNode addResourceNodes(DataFlowGraph dataFlowGraph, ResourcePath resPath, DataTransferChannel dfChannel, + Map> resourceMap) { + ResourceNode resNode = null; + if (resPath.getParent() == null) { + resNode = dataFlowGraph.addResourceNode(null, dfChannel, resPath); + } else { + ResourceNode parent = addResourceNodes(dataFlowGraph, resPath.getParent(), null, resourceMap); + resNode = dataFlowGraph.addResourceNode(parent, dfChannel, resPath); + } + Set resSet = resourceMap.get(resPath.getResourceHierarchy()); + if (resSet == null) { + resSet = new HashSet<>(); + resourceMap.put(resPath.getResourceHierarchy(), resSet); + } + resSet.add(resNode); + return resNode; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ReferenceEdge.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ReferenceEdge.java new file mode 100644 index 0000000..c8ff371 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ReferenceEdge.java @@ -0,0 +1,11 @@ +package models.dataFlowModel; + +import models.Edge; + +public class ReferenceEdge extends Edge { + + public ReferenceEdge(ResourceNode src, ResourceNode dst) { + super(src, dst); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java index 5e6d9d7..4d33ec8 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNode.java @@ -1,30 +1,109 @@ package models.dataFlowModel; +import java.util.AbstractMap; +import java.util.AbstractMap.SimpleEntry; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import models.Node; +import models.algebra.Type; +import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; public class ResourceNode extends Node { - protected ResourcePath resourcePath = null; + protected ResourceNode parent = null; + protected Set children = null; + protected ResourceHierarchy resourceHierarchy = null; + protected Map inSide = null; + protected Map.Entry outSide = null; - public ResourceNode(ResourcePath resourcePath) { - this.resourcePath = resourcePath; + public ResourceNode(ResourceNode parent, + DataTransferChannel outSideChannel, + ResourcePath outSideResource) { + this.parent = parent; + this.children = new HashSet<>(); + this.inSide = new HashMap<>(); + this.outSide = new AbstractMap.SimpleEntry<>(outSideChannel, outSideResource); + this.resourceHierarchy = outSideResource.getResourceHierarchy(); } - public ResourcePath getResource() { - return resourcePath; + public ResourceNode(ResourceNode parent, + Map inSide, + Map.Entry outSide) { + this.parent = parent; + this.children = new HashSet<>(); + this.inSide = inSide; + this.outSide = outSide; + this.resourceHierarchy = outSide.getValue().getResourceHierarchy(); } - public boolean equals(Object another) { - if (this == another) return true; - if (!(another instanceof ResourceNode)) return false; - return resourcePath.equals(((ResourceNode)another).resourcePath); + public ResourceHierarchy getResourceHierarchy() { + return resourceHierarchy; } - public int hashCode() { - return resourcePath.hashCode(); + public String getResourceName() { + return resourceHierarchy.getResourceName(); } - public String toString() { - return resourcePath.toString(); + public Type getResourceStateType() { + return resourceHierarchy.getResourceStateType(); } + + public int getNumberOfParameters() { + return resourceHierarchy.getTotalNumParameters(); + } + + public ResourceNode getParent() { + return parent; + } + + public Set getChildren() { + return children; + } + + public void addChild(ResourceNode child) { + children.add(child); + child.parent = this; + } + + public Collection getInSideResources() { + return inSide.values(); + } + + public ResourcePath getInSideResource(DataTransferChannel channel) { + return inSide.get(channel); + } + + public ResourcePath getOutSideResource() { + return outSide.getValue(); + } + + public DataTransferChannel getOutSideChannel() { + return outSide.getKey(); + } + + public void addInSideResource(DataTransferChannel channel, ResourcePath inResource) { + inSide.put(channel, inResource); + } + + public void setOutSideResource(DataTransferChannel channel, ResourcePath outResource) { + outSide = new AbstractMap.SimpleEntry<>(channel, outResource); + } + +// public boolean equals(Object another) { +// if (this == another) return true; +// if (!(another instanceof ResourceNode)) return false; +// return resourcePath.equals(((ResourceNode)another).resourcePath); +// } +// +// public int hashCode() { +// return resourcePath.hashCode(); +// } +// +// public String toString() { +// return resourcePath.toString(); +// } } diff --git a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index e7a52eb..bf8d96d 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -164,7 +164,7 @@ } else if (inOrOutOrRefOrSub.equals(SUB_CHANNEL)) { DataTransferChannel subChannel = parseChannel(model); if (subChannel != null) { - subChannel.setParent(channel); + channel.addChild(subChannel); } } else { throw new ExpectedInOrOutOrRefOrSubKeyword(stream.getLine()); @@ -434,7 +434,7 @@ } public ResourcePath parseResourcePath(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, ExpectedRightCurlyBracket, WrongPathExpression { - ResourceHierarchy hierarchy = null; + ResourcePath path = null; List pathParams = new ArrayList<>(); do { String literalOrLeftCurlyBracket = stream.next(); @@ -444,15 +444,20 @@ pathParams.add(paramTerm); String rightCurlyBracket = stream.next(); if (rightCurlyBracket == null || !rightCurlyBracket.equals(RIGHT_CURLY_BRACKET)) throw new ExpectedRightCurlyBracket(stream.getLine()); - hierarchy = new ResourceHierarchy(hierarchy, 1); + path = new ResourcePath(path, pathParams); } else { // Path literal - hierarchy = new ResourceHierarchy(hierarchy, literalOrLeftCurlyBracket); + if (path == null) { + path = new ResourcePath(literalOrLeftCurlyBracket); + } else { + path = new ResourcePath(path, literalOrLeftCurlyBracket); + } } if (!stream.hasNext()) throw new WrongPathExpression(stream.getLine()); if (stream.checkNext().equals(LEFT_BRACKET)) break; } while (stream.next().equals(DOT)); - return model.createResourcePath(hierarchy, pathParams); + model.addResourcePath(path); + return path; } protected Boolean doesMatchToKeyword(final String token, final String specificTokenName) { diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java index 25f1d61..238df91 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java @@ -14,13 +14,16 @@ // Construct a data constraint architecture model. DataConstraintModel model = new DataConstraintModel(); - ResourcePath customers = model.createResourcePath(null, "customers"); // "customers" - ResourcePath customer = model.createResourcePath(customers, new Variable("uid")); // "customers.{uid}" - ResourcePath customer_off = model.createResourcePath(customer, "off"); // "customers.{uid}.off" - ResourcePath customer_add = model.createResourcePath(customer, "add"); // "customers.{uid}.add" - ResourcePath companies = model.createResourcePath(null, "companies"); // "companies" - ResourcePath company = model.createResourcePath(companies, new Variable("cid")); // "companies.{cid}" - ResourcePath company_add = model.createResourcePath(company, "add"); // "companies.{cid}.add" + ResourcePath customers = new ResourcePath("customers"); // "customers" + ResourcePath customer = new ResourcePath(customers, new Variable("uid")); // "customers.{uid}" + ResourcePath customer_off = new ResourcePath(customer, "off"); // "customers.{uid}.off" + ResourcePath customer_add = new ResourcePath(customer, "add"); // "customers.{uid}.add" + ResourcePath companies = new ResourcePath("companies"); // "companies" + ResourcePath company = new ResourcePath(companies, new Variable("cid")); // "companies.{cid}" + ResourcePath company_add = new ResourcePath(company, "add"); // "companies.{cid}.add" + model.addResourcePath(customer_off); + model.addResourcePath(customer_add); + model.addResourcePath(company_add); Channel cio_setCustomerOff = new Channel("CIO_SetCustomerOff", new Variable("uid")); // set customer's office ChannelMember customer_off_1 = new ChannelMember(customer_off); @@ -48,7 +51,7 @@ model.addChannel(c); // Check the model. - assertEquals(0, model.getResourcePaths().size()); + assertEquals(3, model.getResourcePaths().size()); assertEquals(7, model.getResourceHierarchies().size()); assertEquals(2, model.getIOChannels().size()); assertEquals(1, model.getChannels().size()); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java index 29b9fac..ffbef05 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataFlowModelTest.java @@ -16,14 +16,13 @@ // Construct a data-flow architecture model. DataTransferModel model = new DataTransferModel(); - ResourcePath customers = model.createResourcePath(null, "customers"); // "customers" - ResourcePath customer = model.createResourcePath(customers, new Variable("uid")); // "customers.{uid}" - ResourcePath customer_off = model.createResourcePath(customer, "off"); // "customers.{uid}.off" - ResourcePath customer_add = model.createResourcePath(customer, "add"); // "customers.{uid}.add" - ResourcePath companies = model.createResourcePath(null, "companies"); // "companies" - ResourcePath company = model.createResourcePath(companies, new Variable("cid")); // "companies.{cid}" - ResourcePath company_add = model.createResourcePath(company, "add"); // "companies.{cid}.add" - + ResourcePath customers = new ResourcePath("customers"); // "customers" + ResourcePath customer = new ResourcePath(customers, new Variable("uid")); // "customers.{uid}" + ResourcePath customer_off = new ResourcePath(customer, "off"); // "customers.{uid}.off" + ResourcePath customer_add = new ResourcePath(customer, "add"); // "customers.{uid}.add" + ResourcePath companies = new ResourcePath("companies"); // "companies" + ResourcePath company = new ResourcePath(companies, new Variable("cid")); // "companies.{cid}" + ResourcePath company_add = new ResourcePath(company, "add"); // "companies.{cid}.add" model.addResourcePath(customer_off); model.addResourcePath(customer_add); model.addResourcePath(company_add); @@ -78,8 +77,9 @@ DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph(); // Check the graph. - assertEquals(3, resourceDependencyGraph.getNodes().size()); - assertEquals(2, resourceDependencyGraph.getEdges().size()); + assertEquals(7, resourceDependencyGraph.getResourceNodes().size()); + assertEquals(3, resourceDependencyGraph.getChannelNodes().size()); + assertEquals(5, resourceDependencyGraph.getEdges().size()); for (Edge e: resourceDependencyGraph.getEdges()) { System.out.println(e.getSource() + "-(" + e + ")->" + e.getDestination()); } diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java index 823c006..7326b58 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataStorageDecisionTest.java @@ -36,8 +36,8 @@ DataFlowGraph graph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(graph); DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); - for(Node n:graph.getNodes()) { - System.out.println(((ResourceNode) n).getResource().getResourceName() + ":" + ((StoreAttribute) ((ResourceNode) n).getAttribute()).isStored()); + for(Node resNode: graph.getResourceNodes()) { + System.out.println(((ResourceNode) resNode).getResourceName() + ":" + ((StoreAttribute) ((ResourceNode) resNode).getAttribute()).isStored()); } } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefOrSubKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression diff --git a/AlgebraicDataflowArchitectureModel/src/tests/FormulaChannelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/FormulaChannelTest.java index 6a0bd63..6bf26f4 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/FormulaChannelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/FormulaChannelTest.java @@ -13,9 +13,9 @@ @Test public void test() { - ResourcePath res1 = new ResourcePath(new ResourceHierarchy("r1")); - ResourcePath res2 = new ResourcePath(new ResourceHierarchy("r2")); - ResourcePath res3 = new ResourcePath(new ResourceHierarchy("r3")); + ResourcePath res1 = new ResourcePath("r1"); + ResourcePath res2 = new ResourcePath("r2"); + ResourcePath res3 = new ResourcePath("r3"); FormulaChannel ch1 = new FormulaChannel("ch1", DataConstraintModel.add); System.out.println(ch1.getFormula()); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java index 6dededf..7c30c68 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java @@ -14,10 +14,10 @@ public void test() { // Construct a data-flow architecture model. DataTransferModel model = new DataTransferModel(); - ResourcePath payment = model.createResourcePath(null, "payment"); // a resource to specify the payment resource - ResourcePath points = model.createResourcePath(null, "points"); // a resource to specify the points resource - ResourcePath history = model.createResourcePath(null, "history"); // a resource to specify the payment history resource - ResourcePath total = model.createResourcePath(null, "total"); // a resource to specify the total payment resource + ResourcePath payment = new ResourcePath("payment"); // a resource to specify the payment resource + ResourcePath points = new ResourcePath("points"); // a resource to specify the points resource + ResourcePath history = new ResourcePath("history"); // a resource to specify the payment history resource + ResourcePath total = new ResourcePath("total"); // a resource to specify the total payment resource model.addResourcePath(payment); model.addResourcePath(points); model.addResourcePath(history); @@ -89,8 +89,9 @@ DataFlowGraph resourceDependencyGraph = model.getDataFlowGraph(); // Check the graph. - assertEquals(4, resourceDependencyGraph.getNodes().size()); - assertEquals(3, resourceDependencyGraph.getEdges().size()); + assertEquals(4, resourceDependencyGraph.getResourceNodes().size()); + assertEquals(4, resourceDependencyGraph.getChannelNodes().size()); + assertEquals(6, resourceDependencyGraph.getEdges().size()); for (Edge e: resourceDependencyGraph.getEdges()) { System.out.println(e.getSource() + "-(" + e + ")->" + e.getDestination()); } diff --git a/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java b/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java index 9773fad..bdb21e6 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/UpdateCodeGenerationTest.java @@ -25,10 +25,14 @@ Symbol sum = new Symbol("sum", 1, Symbol.Type.PREFIX, "stream().mapToInt(x->x).sum", Symbol.Type.METHOD); // resources - ResourcePath payment = new ResourcePath(new ResourceHierarchy("payment", DataConstraintModel.typeInt)); // a resource to specify the payment resource - ResourcePath points = new ResourcePath(new ResourceHierarchy("points", DataConstraintModel.typeInt)); // a resource to specify the loyalty resource - ResourcePath history = new ResourcePath(new ResourceHierarchy("history", DataConstraintModel.typeList)); // a resource to specify the payment history resource - ResourcePath total = new ResourcePath(new ResourceHierarchy("total", DataConstraintModel.typeInt)); // a resource to specify the total payment resource + ResourcePath payment = new ResourcePath("payment"); // a resource to specify the payment resource + ResourcePath points = new ResourcePath("points"); // a resource to specify the loyalty resource + ResourcePath history = new ResourcePath("history"); // a resource to specify the payment history resource + ResourcePath total = new ResourcePath("total"); // a resource to specify the total payment resource + payment.setResourceStateType(DataConstraintModel.typeInt); + points.setResourceStateType(DataConstraintModel.typeInt); + history.setResourceStateType(DataConstraintModel.typeInt); + total.setResourceStateType(DataConstraintModel.typeInt); // fields in the Java program final Field fPayment = new Field("payment", DataConstraintModel.typeInt);