diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java index 8eb198e..664f8db 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java @@ -23,6 +23,7 @@ public static final int DATA_FLOW_LAYER = 0; public static final int PUSH_FLOW_LAYER = 1; public static final int PULL_FLOW_LAYER = 2; + public static final int DEPENDENCY_LAYER = 3; public Stage(mxGraphComponent graphComponent) { this.graphComponent = graphComponent; @@ -52,12 +53,14 @@ mxCell nodeAndDataFlowLayer = new mxCell(); // 0 mxCell pushFlowLayer = new mxCell(); // 1 mxCell pullFlowLayer = new mxCell(); // 2 + mxCell dependencyLayer = new mxCell(); //3 graph.getModel().beginUpdate(); try { graph.addCell(nodeAndDataFlowLayer, root); graph.addCell(pushFlowLayer, root); graph.addCell(pullFlowLayer, root); + graph.addCell(dependencyLayer, root); } finally { graph.getModel().endUpdate(); } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DependencyModelingStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DependencyModelingStage.java index e9cc6e3..12e3efe 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DependencyModelingStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DependencyModelingStage.java @@ -3,14 +3,23 @@ import application.editor.Editor; import application.editor.FlowCellEditor; import application.editor.Stage; +import application.layouts.DAGLayout; import com.mxgraph.model.mxCell; import com.mxgraph.model.mxGeometry; import com.mxgraph.model.mxGraphModel; import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.util.mxEventSource.mxIEventListener; +import com.mxgraph.util.mxPoint; import com.mxgraph.view.mxGraph; -import com.mxgraph.view.mxStylesheet; -import models.controlFlowModel.ControlFlowGraph; +import generators.JavaCodeGenerator; +import models.Edge; +import models.Node; +import models.algebra.*; +import models.controlFlowModel.*; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; import models.dataFlowModel.*; import models.dependencyModel.DependencyGraph; @@ -28,6 +37,10 @@ private List nodes = new ArrayList<>(); + private HashMap resNodeToCell; + private HashMap eventChannelToCell; + + //-------------------------------------------------- // コンストラクタ //-------------------------------------------------- @@ -63,8 +76,8 @@ model = prevStage.getModel(); DataFlowGraph dataFlowGraph = ((PushPullSelectionStage) prevStage).getDataFlowGraph(); - ControlFlowGraph controlFlowGraph = new ControlFlowGraph(dataFlowGraph, model); - dependencyGraph = new DependencyGraph(controlFlowGraph, model); + //ControlFlowGraph controlFlowGraph = new ControlFlowGraph(dataFlowGraph, model); + dependencyGraph = new DependencyGraph(dataFlowGraph, model); graph = constructGraph(graph, dependencyGraph); } @@ -144,17 +157,210 @@ } private mxGraph constructGraph(mxGraph graph, DependencyGraph dependencyGraph) { + showOnlyLayer(DEPENDENCY_LAYER); graph.getModel().beginUpdate(); try { + Map dependencyResNodeCells = createCellsOfResourceMap(); + Map dependencyEventNodeCells = createEventChannelCells(); + + graph = insertControlFlowEdges(dependencyResNodeCells, dependencyEventNodeCells); } finally { graph.getModel().endUpdate(); } return graph; } + private Map createCellsOfResourceMap() { + Map resNodeCells = new HashMap<>(); + + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell nodeLayerCell = (mxCell) root.getChildAt(NODE_LAYER); + mxCell dependencyLayerCell = (mxCell) root.getChildAt(DEPENDENCY_LAYER); + + for (ResourceNode resourceNode : dependencyGraph.getDataFlowGraph().getRootResourceNodes()) { + int w = 80; + int h = 30; + + ResourcePath resourcePath = resourceNode.getPrimaryResourcePath(); + mxCell resNodeCell = (mxCell) graph.insertVertex(dependencyLayerCell, null, resourcePath.getLeafResourceName(), + 20, 20, w, h, "strokeColor=green;fillColor=#BBFFBB;shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top"); // insert a resource as a vertex + resNodeCells.put(resourceNode, resNodeCell); + + createCellsOfChildResourceMap(resNodeCells, resNodeCell, resourceNode, w, h); + } + return resNodeCells; + } + + private void createCellsOfChildResourceMap( Map resNodeCells , mxCell parentCell, ResourceNode parentResNode, double w, double h){ + for (ResourceNode resNode: parentResNode.getChildren()) { + ResourcePath resPath = resNode.getPrimaryResourcePath(); + mxCell resNodeCell = (mxCell) graph.insertVertex(parentCell, null, resPath.getName(), 0, 0, w, h,"strokeColor=green;fillColor=#BBFFBB;shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top"); // insert a resource as a vertex + resNodeCells.put(resNode, resNodeCell); + createCellsOfChildResourceMap(resNodeCells, resNodeCell, resNode, w, h); + } + } + + private Map createEventChannelCells(){ + + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell dependencyLayerCell = (mxCell) root.getChildAt(DEPENDENCY_LAYER); + + Map eventChannelCells = new HashMap<>(); + Map channelOutToCell = new HashMap<>(); + + graph.getModel().beginUpdate(); + try { + mxGeometry geoPortIn = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geoPortIn.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geoPortIn.setRelative(true); + + mxGeometry geoPortOut = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geoPortOut.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geoPortOut.setRelative(true); + + for (ChannelNode channelNode : dependencyGraph.getDataFlowGraph().getRootChannelNodes()) { + DataTransferChannel channel = channelNode.getChannel(); + if (channel.getInputResources().isEmpty()) { + + if (eventChannelCells.get(channel) == null) { + String channelName = channel.getChannelName(); + if (channel.getSelectors().size() > 0) { + channelName += "("; + String delimiter = ""; + for (Selector s : channel.getSelectors()) { + Expression exp = s.getExpression(); + String selectorName = exp.toString(); + channelName += delimiter + selectorName; + delimiter = ", "; + } + channelName += ")"; + } + int w = 40; + int h = 30; + if (channelNode.getChildren().size() > 0) { + w *= 2; + h *= 2; + } + mxCell channelCell = (mxCell) graph.insertVertex(dependencyLayerCell, null, channelName, 150, 20, w, h, "strokeColor=green;fillColor=#BBFFBB;verticalAlign=top"); // insert a channel as a vertex + eventChannelCells.put(channel, channelCell); + + mxCell portOut = new mxCell(null, geoPortOut, "strokeColor=green;fillColor=#BBFFBB;shape=ellipse;perimter=ellipsePerimeter"); + portOut.setVertex(true); + graph.addCell(portOut, channelCell); // insert the output port of a channel + eventChannelCells.put(channel, portOut); + createChildEventChannelVertices(eventChannelCells, channelCell, channelNode, channelOutToCell, geoPortOut, w, h); + } + } + } + } + finally { + graph.getModel().endUpdate(); + } + + return eventChannelCells; + } + + private void createChildEventChannelVertices(Map eventChannelCells, mxCell parentCell, ChannelNode parentChannelNode, + Map channelOutToCell, mxGeometry geoPortOut, int w, int h) { + for (ChannelNode channelNode: parentChannelNode.getChildren()) { + DataTransferChannel channel = channelNode.getChannel(); + + + if (channel.getInputResources().isEmpty()) { + + if (channelOutToCell.get(channel) == null) { + String channelName = channel.getChannelName(); + if (channel.getSelectors().size() > 0) { + channelName += "("; + String delimiter = ""; + for (Selector s : channel.getSelectors()) { + Expression exp = s.getExpression(); + String selectorName = exp.toString(); + channelName += delimiter + selectorName; + delimiter = ", "; + } + channelName += ")"; + } + mxCell channelCell = (mxCell) graph.insertVertex(parentCell, null, channelName, w / 4, h / 4, w / 2, h / 2, "strokeColor=green;fillColor=#BBFFBB;verticalAlign=top"); // insert a channel as a vertex + eventChannelCells.put(channel, channelCell); + + mxCell portOut = new mxCell(null, geoPortOut, "strokeColor=green;fillColor=#BBFFBB;shape=ellipse;perimter=ellipsePerimeter"); + portOut.setVertex(true); + graph.addCell(portOut, channelCell); // insert the output port of a channel + channelOutToCell.put(channel, portOut); + createChildEventChannelVertices(eventChannelCells, channelCell, channelNode, channelOutToCell, geoPortOut, w / 2, h / 2); + } + } + } + } + + private mxGraph insertControlFlowEdges(final Map resNodeCells, final Map eventChNodeCells) { + mxCell root = (mxCell) graph.getDefaultParent(); + mxCell dependencyLayerCell = (mxCell) root.getChildAt(DEPENDENCY_LAYER); + + graph.getModel().beginUpdate(); + try { + for (Edge edge : dependencyGraph.getDataFlowGraph().getEdges()) { + DataFlowEdge dataFlowEdge = (DataFlowEdge) edge; + if (dataFlowEdge.isChannelToResource()) { + // output edge + DataTransferChannel channel = ((ChannelNode) dataFlowEdge.getSource()).getChannel(); + ResourcePath dstRes = ((ResourceNode) dataFlowEdge.getDestination()).getInSideResource(channel); + graph.insertEdge(dependencyLayerCell, null, new Editor.SrcDstAttribute(channel, dstRes), eventChNodeCells.get(channel), resNodeCells.get((ResourceNode) dataFlowEdge.getDestination()), "strokeColor=green;movable=false"); + } else { + // input edge + DataTransferChannel channel = ((ChannelNode) dataFlowEdge.getDestination()).getChannel(); + ResourcePath srcRes = ((ResourceNode) dataFlowEdge.getSource()).getOutSideResource(channel); + Set> toRes = getResourceDependencyForChannel(channel, dependencyGraph.getDataFlowGraph()); + for (Map.Entry RtoR : toRes) { + graph.insertEdge(dependencyLayerCell, null, null, resNodeCells.get(RtoR.getValue()), resNodeCells.get(RtoR.getKey()), "strokeColor=green;dashed=true;movable=false"); + } + + graph.insertEdge(dependencyLayerCell, null, new Editor.SrcDstAttribute(srcRes, channel), resNodeCells.get((ResourceNode) dataFlowEdge.getSource()), eventChNodeCells.get(channel), "strokeColor=green;movable=false"); + } + } + + for (Channel ch : model.getChannels()) { + // reference edges + DataTransferChannel channel = (DataTransferChannel) ch; + for (ResourcePath refRes : channel.getReferenceResources()) { + graph.insertEdge(dependencyLayerCell, null, null, resNodeCells.get(dependencyGraph.getDataFlowGraph().getResourceNode(refRes)), eventChNodeCells.get(channel), "strokeColor=green;dashed=true;movable=false"); + } + } + } finally { + graph.getModel().endUpdate(); + } + return graph; + } + + private Set> getResourceDependencyForChannel(DataTransferChannel ch, 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; + } + } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java index 9ba5b43..79382c5 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java @@ -27,6 +27,7 @@ private DataFlowGraph dataFlowGraph = null; private HashMap resNodeToCell; private HashMap channelToCell; + private HashMap eventChannelToCell; public PushPullSelectionStage(mxGraphComponent graphComponent) { super(graphComponent); @@ -140,6 +141,7 @@ Map channelInToCell = new HashMap<>(); Map channelOutToCell = new HashMap<>(); channelToCell = new HashMap<>(); + eventChannelToCell = new HashMap<>(); resNodeToCell = new HashMap<>(); mxGeometry geoPortIn = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); @@ -222,7 +224,8 @@ } mxCell channelCell = (mxCell) graph.insertVertex(layer, null, channelName, 150, 20, w, h, "verticalAlign=top"); // insert a channel as a vertex channelToCell.put(channel, channelCell); - + eventChannelToCell.put(channel, channelCell); + mxCell portOut = new mxCell(null, geoPortOut, "shape=ellipse;perimter=ellipsePerimeter"); portOut.setVertex(true); graph.addCell(portOut, channelCell); // insert the output port of a channel @@ -273,8 +276,8 @@ createChildResourceVertices(resourceCell, resNode, w, h); } } - - private void createChildChannelVertices(mxCell parentCell, ChannelNode parentChannelNode, + + private void createChildChannelVertices(mxCell parentCell, ChannelNode parentChannelNode, Map channelInToCell, Map channelOutToCell, mxGeometry geoPortIn, mxGeometry geoPortOut, int w, int h) { for (ChannelNode channelNode: parentChannelNode.getChildren()) { DataTransferChannel channel = channelNode.getChannel(); @@ -324,7 +327,8 @@ } mxCell channelCell = (mxCell) graph.insertVertex(parentCell, null, channelName, w / 4, h / 4, w / 2, h / 2, "verticalAlign=top"); // insert a channel as a vertex channelToCell.put(channel, channelCell); - + eventChannelToCell.put(channel, channelCell); + mxCell portOut = new mxCell(null, geoPortOut, "shape=ellipse;perimter=ellipsePerimeter"); portOut.setVertex(true); graph.addCell(portOut, channelCell); // insert the output port of a channel @@ -363,12 +367,16 @@ public DataFlowGraph getDataFlowGraph() { return dataFlowGraph; } - + public HashMap getResNodeToCell() { return resNodeToCell; } - + public HashMap getChannelToCell() { return channelToCell; } + + public HashMap getEventChannelToCell(){ + return eventChannelToCell; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/application/views/FlowLayerWindow.java b/AlgebraicDataflowArchitectureModel/src/application/views/FlowLayerWindow.java index ae2749a..e9d1b06 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/views/FlowLayerWindow.java +++ b/AlgebraicDataflowArchitectureModel/src/application/views/FlowLayerWindow.java @@ -4,6 +4,9 @@ import application.editor.Editor; import application.editor.IStageChangeListener; import application.editor.Stage; +import application.editor.stages.DataFlowModelingStage; +import application.editor.stages.DependencyModelingStage; +import application.editor.stages.PushPullSelectionStage; import javax.swing.*; import java.awt.*; @@ -15,6 +18,7 @@ private JCheckBox dataFlowCheckBox = null; private JCheckBox pushFlowCheckBox = null; private JCheckBox pullFlowCheckBox = null; + private JCheckBox dependencyCheckBox = null; private Stage stage = null; @@ -30,6 +34,7 @@ dataFlowCheckBox = new JCheckBox("Data-Flow", false); pushFlowCheckBox = new JCheckBox("Push-Flow", true); pullFlowCheckBox = new JCheckBox("Pull-Flow", true); + dependencyCheckBox = new JCheckBox("Dependency", false); // 各Viewにイベントハンドラを追加 dataFlowCheckBox.addActionListener(new ActionListener() { @@ -50,9 +55,16 @@ stage.setEnabledForLayer(Stage.PULL_FLOW_LAYER, pullFlowCheckBox.isSelected()); }}); + dependencyCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + stage.setEnabledForLayer(Stage.DEPENDENCY_LAYER, dependencyCheckBox.isSelected()); + }}); + dataFlowCheckBox.setEnabled(false); pushFlowCheckBox.setEnabled(false); pullFlowCheckBox.setEnabled(false); + dependencyCheckBox.setEnabled(false); // レイヤーのパネルレイアウトの初期化. Container panel = getContentPane(); @@ -60,6 +72,7 @@ panel.add(dataFlowCheckBox); panel.add(pushFlowCheckBox); panel.add(pullFlowCheckBox); + panel.add(dependencyCheckBox); Point location = new Point(owner.getX() + (owner.getWidth() / 2) - (this.getWidth() / 2), owner.getY() + (owner.getHeight() / 2) - (this.getHeight() / 2)); setLocation(location); @@ -72,11 +85,62 @@ */ @Override public void stageChanged(Stage newStage) { - dataFlowCheckBox.setEnabled(false); - pushFlowCheckBox.setEnabled(false); - pullFlowCheckBox.setEnabled(false); + if (newStage instanceof DependencyModelingStage) { + // DependencyStageでは全て操作可能 + dataFlowCheckBox.setEnabled(true); + pushFlowCheckBox.setEnabled(true); + pullFlowCheckBox.setEnabled(true); + dependencyCheckBox.setEnabled(true); - newStage.setEnabledForLayer(Stage.PUSH_FLOW_LAYER, false); - newStage.setEnabledForLayer(Stage.PULL_FLOW_LAYER, false); + // Dependencyチェックを自動でON + dependencyCheckBox.setSelected(true); + newStage.setEnabledForLayer(Stage.DEPENDENCY_LAYER, true); + + } else if (newStage instanceof PushPullSelectionStage) { + // PushPullStage:Data,Push,Pullを表示(操作不可) + setAllCheckBoxesEnabled(false); + dataFlowCheckBox.setSelected(true); + pushFlowCheckBox.setSelected(true); + pullFlowCheckBox.setSelected(true); + dependencyCheckBox.setSelected(false); + + newStage.setEnabledForLayer(Stage.DATA_FLOW_LAYER, true); + newStage.setEnabledForLayer(Stage.PUSH_FLOW_LAYER, true); + newStage.setEnabledForLayer(Stage.PULL_FLOW_LAYER, true); + newStage.setEnabledForLayer(Stage.DEPENDENCY_LAYER, false); + + } else if (newStage instanceof DataFlowModelingStage) { + // DataFlowStage:Dataのみ表示(操作不可) + setAllCheckBoxesEnabled(false); + dataFlowCheckBox.setSelected(true); + pushFlowCheckBox.setSelected(false); + pullFlowCheckBox.setSelected(false); + dependencyCheckBox.setSelected(false); + + newStage.setEnabledForLayer(Stage.DATA_FLOW_LAYER, true); + newStage.setEnabledForLayer(Stage.PUSH_FLOW_LAYER, false); + newStage.setEnabledForLayer(Stage.PULL_FLOW_LAYER, false); + newStage.setEnabledForLayer(Stage.DEPENDENCY_LAYER, false); + } else { + // その他ステージではすべて非活性 + setAllCheckBoxesEnabled(false); + dataFlowCheckBox.setSelected(false); + pushFlowCheckBox.setSelected(false); + pullFlowCheckBox.setSelected(false); + dependencyCheckBox.setSelected(false); + + newStage.setEnabledForLayer(Stage.DATA_FLOW_LAYER, false); + newStage.setEnabledForLayer(Stage.PUSH_FLOW_LAYER, false); + newStage.setEnabledForLayer(Stage.PULL_FLOW_LAYER, false); + newStage.setEnabledForLayer(Stage.DEPENDENCY_LAYER, false); + } + + } + + private void setAllCheckBoxesEnabled(boolean enabled) { + dataFlowCheckBox.setEnabled(enabled); + pushFlowCheckBox.setEnabled(enabled); + pullFlowCheckBox.setEnabled(enabled); + dependencyCheckBox.setEnabled(enabled); } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dependencyModel/DependencyGraph.java b/AlgebraicDataflowArchitectureModel/src/models/dependencyModel/DependencyGraph.java index 15dc07e..d8cf154 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dependencyModel/DependencyGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dependencyModel/DependencyGraph.java @@ -37,7 +37,8 @@ } public DataFlowGraph getDataFlowGraph(){ - return controlFlowGraph.getDataFlowGraph(); + // return controlFlowGraph.getDataFlowGraph(); + return dataFlowGraph; } @Override