diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java index cccd863..c5c58c3 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java @@ -11,29 +11,33 @@ import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.util.mxEventSource.mxIEventListener; import com.mxgraph.util.mxPoint; -import models.algebra.Expression; +import com.mxgraph.view.mxGraph; +import generators.JavaCodeGenerator; +import models.Edge; +import models.algebra.*; import models.dataConstraintModel.Channel; import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.ResourcePath; -import models.dataFlowModel.DataTransferChannel; -import models.dataFlowModel.DataTransferModel; +import models.dataConstraintModel.Selector; +import models.dataFlowModel.*; import models.visualModel.FormulaChannel; import parser.Parser; import parser.exceptions.*; import java.awt.event.MouseListener; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class DataFlowModelingStage extends Stage { + private boolean bReflectingArchitectureModel = false; + public DataFlowModelingStage(mxGraphComponent graphComponent) { super(graphComponent); } @Override public void init(Stage prevStage) { - // showOnlyLayers(DATA_FLOW_LAYER); + showOnlyLayer(DATA_FLOW_LAYER); } @Override @@ -74,8 +78,23 @@ } public void clear() { - ((mxGraphModel) graph.getModel()).clear(); model = null; + ((mxGraphModel) graph.getModel()).clear(); + + // 空のレイヤーを新規作成 + mxCell root = (mxCell) graph.getDefaultParent(); + + graph.getModel().beginUpdate(); + try { + root.insert(new mxCell()); // NODE_LAYER, DATA_FLOW_LAYER + root.insert(new mxCell()); // PUSH_FLOW_LAYER + root.insert(new mxCell()); // PULL_FLOW_LAYER + + showOnlyLayer(NODE_LAYER, DATA_FLOW_LAYER); + } finally { + graph.getModel().endUpdate(); + } + graph.refresh(); } public DataTransferModel getModel() { @@ -91,14 +110,183 @@ this.model = model; - if (!isValid()) { - System.err.println("Model is not valid!"); - clear(); - return; + // Update the mxGraph + constructGraph(graph, model); + } + + /** + * Construct a mxGraph from DataFlowModel + * + * @param graph mxGraph + * @param model DataTransferModel + */ + private void constructGraph(mxGraph graph, DataTransferModel model) { + bReflectingArchitectureModel = true; + ((mxGraphModel) graph.getModel()).clear(); + + mxCell parent = (mxCell) graph.getDefaultParent(); + mxCell nodeLayer = (mxCell) parent.getChildAt(Stage.NODE_LAYER); + mxCell dataFlowLayer = (mxCell) parent.getChildAt(Stage.DATA_FLOW_LAYER); + DataFlowGraph dataFlowGraph = model.getDataFlowGraph(); + + graph.getModel().beginUpdate(); + try { + mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo1.setRelative(true); + + mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo2.setRelative(true); + + Map channelsIn = new HashMap<>(); + Map channelsOut = new HashMap<>(); + Map resources = new HashMap<>(); + + // create resource vertices + for (ResourceNode resNode : dataFlowGraph.getRootResourceNodes()) { + int w = 80; + int h = 30; + ResourcePath res = resNode.getPrimaryResourcePath(); + Object resource = graph.insertVertex(dataFlowLayer, null, res.getLeafResourceName(), 20, 20, w, h, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex + resources.put(resNode, resource); + createChildResourceVertices(graph, resource, resNode, resources, w, h); + } + + // create channel vertices + for (ChannelNode c : dataFlowGraph.getRootChannelNodes()) { + DataTransferChannel channel = c.getChannel(); + if (!channel.getInputResources().isEmpty()) { + // Normal channel + if (channelsIn.get(channel) == null || channelsOut.get(channel) == null) { + if (channel.getSelectors().toString() == "[]") { + Object chCell = graph.insertVertex(dataFlowLayer, 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, 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, chCell); // insert the output port of a channel + channelsIn.put(channel, port_in); + channelsOut.put(channel, port_out); + } else { + for (Selector s : channel.getSelectors()) { + Expression exp = s.getExpression(); + String selName = exp.toString(); + String cName = channel.getChannelName(); + String channelName = cName + " (" + selName + ")"; + Object chCell = graph.insertVertex(dataFlowLayer, null, channelName, 150, 20, 60, 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, 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, chCell); // insert the output port of a channel + channelsIn.put(channel, port_in); + channelsOut.put(channel, port_out); + } + } + } + } else { + // I/O channel + if (channelsOut.get(channel) == null) { + if (channel.getSelectors().toString() == "[]") { + Object chCell = graph.insertVertex(nodeLayer, 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, 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, chCell); // insert the output port of a channel + channelsIn.put(channel, port_in); + channelsOut.put(channel, port_out); + } else { + for (Selector s : channel.getSelectors()) { + Expression exp = s.getExpression(); + String selName = exp.toString(); + String cName = channel.getChannelName(); + String channelName = cName + " (" + selName + ")"; + Object chCell = graph.insertVertex(dataFlowLayer, null, channelName, 150, 20, 60, 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, 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, chCell); // insert the output port of a channel + channelsIn.put(channel, port_in); + channelsOut.put(channel, port_out); + } + } + } + } + } + + // add input, output and reference edges + for (Edge edge : dataFlowGraph.getEdges()) { + DataFlowEdge dfEdge = (DataFlowEdge) edge; + if (dfEdge.isChannelToResource()) { + // output edge + DataTransferChannel channel = ((ChannelNode) dfEdge.getSource()).getChannel(); + ResourcePath dstRes = ((ResourceNode) dfEdge.getDestination()).getInSideResource(channel); + graph.insertEdge(dataFlowLayer, null, new Editor.SrcDstAttribute(channel, dstRes), channelsOut.get(channel), resources.get((ResourceNode) dfEdge.getDestination()), "movable=false"); + } else { + // input edge + DataTransferChannel channel = ((ChannelNode) dfEdge.getDestination()).getChannel(); + ResourcePath srcRes = ((ResourceNode) dfEdge.getSource()).getOutSideResource(channel); + Set> toRes = getResourceDependencyForChannel(channel, model, dataFlowGraph); + for (Map.Entry RtoR : toRes) { + graph.insertEdge(dataFlowLayer, null, null, resources.get(RtoR.getValue()), resources.get(RtoR.getKey()), "dashed=true;movable=false"); + } + graph.insertEdge(dataFlowLayer, null, new Editor.SrcDstAttribute(srcRes, channel), resources.get((ResourceNode) dfEdge.getSource()), channelsIn.get(channel), "movable=false"); + } + } + + for (Channel ch : model.getChannels()) { + // reference edges + DataTransferChannel channel = (DataTransferChannel) ch; + for (ResourcePath refRes : channel.getReferenceResources()) { + graph.insertEdge(dataFlowLayer, null, null, resources.get(dataFlowGraph.getResourceNode(refRes)), channelsIn.get(channel), "dashed=true;movable=false"); + } + } + } finally { + graph.getModel().endUpdate(); } - // Update the mxGraph -// this.graph = constructGraph(this.graph, model); + bReflectingArchitectureModel = false; + } + + private void createChildResourceVertices(mxGraph graph, Object resource, ResourceNode resNode, Map resources, int w, int h) { + for (ResourceNode childNode : resNode.getChildren()) { + ResourcePath childRes = childNode.getPrimaryResourcePath(); + Object childResource = graph.insertVertex(resource, null, childRes.getName(), 0, 0, w, h, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex + resources.put(childNode, childResource); + createChildResourceVertices(graph, childResource, childNode, resources, w, h); + } + } + + private Set> getResourceDependencyForChannel(DataTransferChannel ch, DataTransferModel model, DataFlowGraph dataFlowGraph) { + Set> resourceDependency = new HashSet<>(); + if (!ch.getOutputChannelMembers().isEmpty()) { + try { + Map>> dependency = ch.fillOutsideResourcePaths(ch.getOutputChannelMembers().iterator().next(), JavaCodeGenerator.pullAccessor); + for (ChannelMember srcMem : dependency.keySet()) { + ResourceNode srcNode = dataFlowGraph.getResourceNode(srcMem.getResource()); + if (srcNode != null) { + for (ChannelMember dstMem : dependency.get(srcMem).getValue()) { + ResourceNode dstNode = dataFlowGraph.getResourceNode(dstMem.getResource()); + while (srcNode.getResourceHierarchy().getNumParameters() == 0 && srcNode.getParent() != null) { + srcNode = srcNode.getParent(); + } + resourceDependency.add(new AbstractMap.SimpleEntry<>(srcNode, dstNode)); + } + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | + UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + } + return resourceDependency; } public boolean isValid() { @@ -130,11 +318,12 @@ getModel().addResourcePath(resourcePath); } } -// resetDataFlowGraph(); + graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell nodeLayer = (mxCell) root.getChildAt(NODE_LAYER); try { - graph.insertVertex(parent, null, resName, 20, 20, 80, 30, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex + graph.insertVertex(nodeLayer, null, resName, 20, 20, 80, 30, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex } finally { graph.getModel().endUpdate(); } @@ -142,9 +331,10 @@ public void addChannel(DataTransferChannel channelGen) { getModel().addChannel(channelGen); -// resetDataFlowGraph(); + graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell dataFlowLayer = (mxCell) root.getChildAt(DATA_FLOW_LAYER); try { mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); @@ -154,7 +344,7 @@ geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); geo2.setRelative(true); - Object channel = graph.insertVertex(parent, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex + Object channel = graph.insertVertex(dataFlowLayer, null, channelGen.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 @@ -168,15 +358,16 @@ public void addIOChannel(DataTransferChannel ioChannelGen) { getModel().addInputChannel(ioChannelGen); -// resetDataFlowGraph(); + graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell nodeLayer = (mxCell) root.getChildAt(NODE_LAYER); try { mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); geo2.setRelative(true); - Object channel = graph.insertVertex(parent, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex + Object channel = graph.insertVertex(nodeLayer, null, ioChannelGen.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 @@ -187,9 +378,10 @@ public void addFormulaChannel(FormulaChannel formulaChannelGen) { getModel().addChannel(formulaChannelGen); -// resetDataFlowGraph(); + graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell dataFlowLayer = (mxCell) root.getChildAt(DATA_FLOW_LAYER); try { mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); @@ -199,7 +391,7 @@ geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); geo2.setRelative(true); - Object channel = graph.insertVertex(parent, null, formulaChannelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex + Object channel = graph.insertVertex(dataFlowLayer, null, formulaChannelGen.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 @@ -212,7 +404,9 @@ } public boolean connectEdge(mxCell edge, mxCell src, mxCell dst) { -// if (bReflectingArchitectureModel) return false; + if (bReflectingArchitectureModel) { + return false; + } DataTransferModel model = getModel(); Channel srcCh = model.getChannel((String) src.getValue()); if (srcCh == null) { @@ -220,22 +414,24 @@ if (srcCh == null) { ResourcePath srcRes = model.getResourcePath((String) src.getValue()); Channel dstCh = model.getChannel((String) dst.getValue()); - if (srcRes == null || dstCh == null) return false; + if (srcRes == null || dstCh == null) { + return false; + } // resource to channel edge ChannelMember srcCm = new ChannelMember(srcRes); ((DataTransferChannel) dstCh).addChannelMemberAsInput(srcCm); edge.setValue(new Editor.SrcDstAttribute(srcRes, dstCh)); -// resetDataFlowGraph(); return true; } } ResourcePath dstRes = model.getResourcePath((String) dst.getValue()); - if (dstRes == null) return false; + if (dstRes == null) { + return false; + } // channel to resource edge ChannelMember dstCm = new ChannelMember(dstRes); ((DataTransferChannel) srcCh).addChannelMemberAsOutput(dstCm); edge.setValue(new Editor.SrcDstAttribute(srcCh, dstRes)); -// resetDataFlowGraph(); return true; } @@ -269,7 +465,6 @@ } } graph.removeCells(graph.getSelectionCells()); -// resetDataFlowGraph(); } public void setChannelCode(DataTransferChannel ch, String code) { @@ -306,7 +501,6 @@ } } } -// resetDataFlowGraph(); } catch (ExpectedRightBracket | ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefOrSubKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression | WrongRHSExpression | ExpectedAssignment | ExpectedRightCurlyBracket |