diff --git a/AlgebraicDataflowArchitectureModel/models/Clock.dtram b/AlgebraicDataflowArchitectureModel/models/Clock.dtram new file mode 100644 index 0000000..380ceca --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/Clock.dtram @@ -0,0 +1,27 @@ +model { +channel CIO1 { + out min(m, tick) == mod(m + 1, 60) +} +channel HourUpdate { + in hour(h, update(h')) == h' + out hour_hand(h_ang, update(h')) == h' / 6 * PI +} +channel MinUpdate { + in min(m, update(m')) == m' + out min_hand(m_ang, update(m')) == m' / 30 * PI +} +channel Clock { + in min(m, update(m')) == m' + out hour(h, update(m')) == if(eq(m', 0), mod(h + 1, 24), h) +} +} +geometry { + node c HourUpdate:520,340,30,30 + node c MinUpdate:520,100,30,30 + node c Clock:280,220,30,30 + node r min_hand:670,100,80,30 + node r min:250,100,80,30 + node r hour:270,340,80,30 + node r hour_hand:680,340,80,30 + node ioc CIO1:100,100,30,30 +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/ApplicationMenuBar.java b/AlgebraicDataflowArchitectureModel/src/application/ApplicationMenuBar.java index 0385b05..c837ba4 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/ApplicationMenuBar.java +++ b/AlgebraicDataflowArchitectureModel/src/application/ApplicationMenuBar.java @@ -18,15 +18,19 @@ import application.actions.SaveAction; import application.actions.SaveAsAction; import application.actions.ShowNavigationAction; +import application.actions.ShowSwitchLayerWindowAction; import application.actions.TreeLayoutAction; import application.actions.ZoomInAction; import application.actions.ZoomOutAction; import application.editor.Editor; public class ApplicationMenuBar extends JMenuBar { - private static final long serialVersionUID = 4811536194182272888L; + private static final long serialVersionUID = 4811536194182272888L; + + private Editor editor = null; private ApplicationWindow applicationWindow = null; + private NewResourceAction newResourceAction = null; private NewChannelAction newChannelAction = null; private NewIOChannelAction newIOChannelAction = null; @@ -37,9 +41,10 @@ private DAGLayoutAction dagLayoutAction = null; private TreeLayoutAction treeLayoutAction = null; private CircleLayoutAction circleLayoutAction = null; - + public ApplicationMenuBar(ApplicationWindow applicationWindow) { this.applicationWindow = applicationWindow; + this.editor = editor; JMenu newMenu = new JMenu("New"); newMenu.add(new NewModelAction(applicationWindow)); @@ -78,6 +83,7 @@ menu = add(new JMenu("Window")); menu.add(new ShowNavigationAction(applicationWindow)); + menu.add(new ShowSwitchLayerWindowAction(applicationWindow)); } public Editor getEditor() { diff --git a/AlgebraicDataflowArchitectureModel/src/application/ApplicationWindow.java b/AlgebraicDataflowArchitectureModel/src/application/ApplicationWindow.java index 2651c23..4630830 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/ApplicationWindow.java +++ b/AlgebraicDataflowArchitectureModel/src/application/ApplicationWindow.java @@ -19,17 +19,19 @@ import application.editor.Editor; import application.editor.stages.DataFlowCellEditor; import application.views.NavigationWindow; +import application.views.controlFlowDelegation.ShowFlowWindow; public class ApplicationWindow extends JFrame { private static final long serialVersionUID = -8690140317781055614L; public static final String title = "Visual Modeling Tool"; - private Editor editor; - private mxGraph graph; - private mxGraphComponent graphComponent; + private Editor editor = null; + private mxGraph graph = null; + private mxGraphComponent graphComponent = null; - private ApplicationMenuBar menuBar; - private NavigationWindow navigationWindow; + private ApplicationMenuBar menuBar = null; + private NavigationWindow navigationWindow = null; + private ShowFlowWindow FlowLayerWindow = null; public ApplicationWindow() { setTitle(title); @@ -51,25 +53,6 @@ this.editor = new Editor(graphComponent); - graph.getModel().addListener(mxEvent.CHANGE, new mxIEventListener() { - public void invoke(Object sender, mxEventObject evt) { - List terminals = new ArrayList<>(); - mxCell cell = null; - for (Object change: ((List) evt.getProperties().get("changes"))) { - if (change instanceof mxGraphModel.mxTerminalChange) { - mxGraphModel.mxTerminalChange terminalChange = (mxGraphModel.mxTerminalChange) change; - cell = (mxCell) terminalChange.getCell(); - mxCell terminal = (mxCell) terminalChange.getTerminal(); - terminals.add(terminal); - } - } - if (terminals.size() == 2) { - if (!editor.connectEdge(cell, terminals.get(0), terminals.get(1))) { - graph.removeCells(new mxCell[] {cell}); - } - } - } - }); getContentPane().add(graphComponent); new mxRubberband(graphComponent); graph.setAllowDanglingEdges(false); @@ -81,7 +64,12 @@ navigationWindow = new NavigationWindow(this, editor); navigationWindow.setVisible(true); + + FlowLayerWindow = new ShowFlowWindow(this); + FlowLayerWindow.setVisible(false); + editor.addStageChangeListener(navigationWindow); + editor.addStageChangeListener(FlowLayerWindow); } public mxGraph getGraph() { @@ -103,5 +91,9 @@ public void showNavigationWindow() { navigationWindow.setVisible(true); } + + public void showSwitchLayerWindow() { + FlowLayerWindow.setVisible(true); + } } diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/ShowSwitchLayerWindowAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/ShowSwitchLayerWindowAction.java new file mode 100644 index 0000000..b137463 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/ShowSwitchLayerWindowAction.java @@ -0,0 +1,16 @@ +package application.actions; + +import java.awt.event.ActionEvent; + +import application.ApplicationWindow; + +public class ShowSwitchLayerWindowAction extends AbstractSystemAction { + public ShowSwitchLayerWindowAction(ApplicationWindow frame) { + super("Show Flow", frame); + } + + @Override + public void actionPerformed(ActionEvent e) { + frame.showSwitchLayerWindow(); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java index 115c5fb..63702cd 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -13,6 +13,8 @@ import com.mxgraph.layout.mxCompactTreeLayout; import com.mxgraph.model.mxCell; import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.util.mxEvent; +import com.mxgraph.util.mxEventSource.mxIEventListener; import com.mxgraph.view.mxCellState; import com.mxgraph.view.mxGraph; import com.mxgraph.view.mxGraphView; @@ -53,11 +55,12 @@ public DataTransferModel model = null; public mxGraph graph = null; private mxGraphComponent graphComponent = null; + private mxIEventListener curChangeEventListener = null; protected Stage curStage = null; protected List stageQueue = null; private List stageChangeListeners = null; - + protected String curFileName = null; protected String curFilePath = null; protected ArrayList codes = null; @@ -116,7 +119,15 @@ if (!nextStage.canChangeFrom(curStage)) return false; nextStage.init(curStage); graphComponent.setCellEditor(nextStage.createCellEditor(graphComponent)); + if (curChangeEventListener != null) { + graph.getModel().removeListener(curChangeEventListener); + } + curChangeEventListener = nextStage.createChangeEventListener(this); + if (curChangeEventListener != null) { + graph.getModel().addListener(mxEvent.CHANGE, curChangeEventListener); + } curStage = nextStage; + // notifyStageChangeListeners(); // <- roop? return true; } @@ -260,9 +271,9 @@ return null; } - /**-------------------------------------------------------------------------------- - * save - /**-------------------------------------------------------------------------------- + /************************************************************* + * [save] + /************************************************************* * */ public void save() { @@ -372,6 +383,9 @@ try { DAGLayout ctl = new DAGLayout(graph); ctl.execute(dataFlowLayer); +// for(int i = 0; i < root.getChildCount(); i++) { +// ctl.execute(root.getChildAt(i)); +// } } finally { graph.getModel().endUpdate(); } @@ -379,14 +393,15 @@ public void setTreeLayout() { mxCell root = (mxCell) graph.getDefaultParent(); - mxCell dataFlowLayer = (mxCell) root.getChildAt(Stage.DATA_FLOW_LAYER); graph.getModel().beginUpdate(); try { mxCompactTreeLayout ctl = new mxCompactTreeLayout(graph); ctl.setLevelDistance(100); // ctl.setHorizontal(false); ctl.setEdgeRouting(false); - ctl.execute(dataFlowLayer); + for(int i = 0; i < root.getChildCount(); i++) { + ctl.execute(root.getChildAt(i)); + } } finally { graph.getModel().endUpdate(); } @@ -394,11 +409,12 @@ public void setCircleLayout() { mxCell root = (mxCell) graph.getDefaultParent(); - mxCell dataFlowLayer = (mxCell) root.getChildAt(Stage.DATA_FLOW_LAYER); graph.getModel().beginUpdate(); try { mxCircleLayout ctl = new mxCircleLayout(graph); - ctl.execute(dataFlowLayer); + for(int i = 0; i < root.getChildCount(); i++) { + ctl.execute(root.getChildAt(i)); + } } finally { graph.getModel().endUpdate(); } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java index 7eadbbf..c3873bc 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java @@ -3,6 +3,7 @@ import com.mxgraph.model.mxCell; import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.swing.view.mxICellEditor; +import com.mxgraph.util.mxEventSource.mxIEventListener; import com.mxgraph.view.mxGraph; import models.dataFlowModel.DataTransferModel; @@ -12,9 +13,8 @@ protected mxGraph graph = null; public static final int NODE_LAYER = 0; public static final int DATA_FLOW_LAYER = 0; - public static final int CONTROL_FLOW_LAYER = 1; - public static final int PUSH_FLOW_LAYER = 2; - public static final int PULL_FLOW_LAYER = 3; + public static final int PUSH_FLOW_LAYER = 1; + public static final int PULL_FLOW_LAYER = 2; /************************************************************* * [ *constructor] @@ -37,18 +37,31 @@ abstract public boolean canChangeFrom(Stage prevStage); abstract public void init(Stage prevStage); abstract public mxICellEditor createCellEditor(mxGraphComponent graphComponent); + abstract public mxIEventListener createChangeEventListener(Editor editor); /************************************************************* - * [ *protected ] + * [ *public ] + /************************************************************* + * + */ + public void setEnabledForLayer(final int layerNo, final boolean isEnable) { + mxCell rootCell = (mxCell) graph.getDefaultParent(); + if(rootCell== null) return; + if(rootCell.getChildCount() <= 0) return; + + graph.getModel().setVisible(rootCell.getChildAt(layerNo), isEnable); + graph.refresh(); + } + /************************************************************* * Showing layers are specified number of layers. * @param you want to show numbers of layers. */ - protected void showOnlyLayer(mxGraph graph, final int... argsOfLayers) { + public void showOnlyLayer(final int... argsOfLayers) { mxCell rootCell = (mxCell) graph.getDefaultParent(); if(rootCell== null) return; - if(rootCell.getChildCount() <= 0) return; - + if(rootCell.getChildCount() <= 0) return; + for(int i = 0; i < rootCell.getChildCount(); i++) { graph.getModel().setVisible(rootCell.getChildAt(i), false); } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationCellEditor.java index 455299b..dcd8786 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationCellEditor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationCellEditor.java @@ -1,12 +1,30 @@ package application.editor.stages; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; import java.util.EventObject; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +import com.mxgraph.model.mxCell; import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.swing.mxGraphComponent.mxGraphControl; +import com.mxgraph.view.mxCellState; import application.editor.FlowCellEditor; +import application.editor.Stage; +import models.controlFlowModel.CallEdgeAttribute; +import models.controlFlowModel.ObjectNodeAttribute; +import models.dataFlowModel.PushPullValue; +/************************************************************* + * + */ public class ControlFlowDelegationCellEditor extends FlowCellEditor { + private ControlFlowDelegationStageStatus curState = null; + private mxCell targetEdgeCell = null; /************************************************************* * [ *constructor ] @@ -16,6 +34,18 @@ */ public ControlFlowDelegationCellEditor(ControlFlowDelegationStage stage, mxGraphComponent graphComponent) { super(stage, graphComponent); + curState = ControlFlowDelegationStageStatus.SELECTING_AN_EDGE; + + // If required handlers have already resistered, + // then remove them before each add. + mxGraphControl graphControl = graphComponent.getGraphControl(); + for(MouseListener listener : graphControl.getMouseListeners()) { + if(listener instanceof InsertObjectNodeAction) + graphControl.removeMouseListener(listener); + } + + // Adding handlers + graphControl.addMouseListener(new InsertObjectNodeAction()); } /************************************************************* @@ -27,10 +57,48 @@ public void startEditing(Object cellObj, EventObject eventObj) { if( editingCell != null) stopEditing(true); - if( graphComponent.getGraph().getModel().isEdge(cellObj) ) { - System.out.println("Edge: " + cellObj.toString()); - } + System.out.println("state:" + curState.name()); + switch(curState) { + case SELECTING_AN_EDGE: + + // Branching based on the edge click event. + // | double clicked > Showing delegatable nodes. + // | right clicked > Inserting a stateless node. + // (added listener -> InsertObjectNodeAction) + if( graphComponent.getGraph().getModel().isEdge(cellObj)) { + // cache a target edge of cell; + targetEdgeCell = (mxCell)cellObj; + + showDelegatableNodesBySelectedEdge(cellObj); + curState = ControlFlowDelegationStageStatus.SHOWING_DELEGATABLE_NODES; + + // If the label of the edge is clicked, + // then inputing a call order you want. + mxCellState state = graphComponent.getGraph().getView().getState(cellObj); + if(state == null || state.getLabel() == null || state.getLabel().equals("")) return; + + changeCallOrderOfCallEdge(cellObj); + } + break; + + case SHOWING_DELEGATABLE_NODES: + if( graphComponent.getGraph().getModel().isVertex(cellObj) ) { + // invocating delegation method + if(!(cellObj instanceof mxCell)) throw new ClassCastException(); + + ((ControlFlowDelegationStage)stage) + .showDelegatedGraph(graphComponent.getGraph(), targetEdgeCell, (mxCell)cellObj); + + curState = ControlFlowDelegationStageStatus.SELECTING_AN_EDGE; + } + else { + System.out.println("cancel showing state."); + ((ControlFlowDelegationStage)stage). resetAllStyleOfCells(); + curState = ControlFlowDelegationStageStatus.SELECTING_AN_EDGE; + } + break; + } } /************************************************************* @@ -40,4 +108,138 @@ public void stopEditing(boolean cancel) { } + + + /************************************************************* + * [ *private ] + /************************************************************* + * [ view ] + /************************************************************* + * + * Todo: support to PUSH/PULL each layer + */ + private void showDelegatableNodesBySelectedEdge(Object cellObj) { + CallEdgeAttribute callEdgeAttr = (CallEdgeAttribute)graphComponent.getGraph().getModel().getValue(cellObj); + if(callEdgeAttr == null) return; + + ((ControlFlowDelegationStage)stage) + .showDelegatableNodes(graphComponent.getGraph(), callEdgeAttr); + } + + /************************************************************* + * + */ + private void changeCallOrderOfCallEdge(final Object cellObj) { + String input = ""; + int inputOrder = 0; + + CallEdgeAttribute callEdgeAttr = (CallEdgeAttribute)graphComponent.getGraph().getModel().getValue(cellObj); + if(callEdgeAttr == null) return; + + input = JOptionPane.showInputDialog("Call order"); + if( input == null) return; + if( !isNumeric(input) ) { + JOptionPane.showMessageDialog(graphComponent, "Input value must type of number."); + return; + } + + inputOrder = Integer.parseInt(input); + + final int endOfOrderOfSrc = callEdgeAttr.getSourceObjectNode().getOutdegree(); + + if(inputOrder <= 0 || endOfOrderOfSrc < inputOrder) { + JOptionPane.showMessageDialog(graphComponent, "Input order must be between 1 and " + endOfOrderOfSrc + "."); + return; + } + + int curOrder = callEdgeAttr.getSourceObjectNode().getOutEdgeCallOrder(callEdgeAttr.getCallEdge()); + callEdgeAttr.getSourceObjectNode().sortOutEdgesByCallOrder(curOrder, inputOrder); + graphComponent.refresh(); + } + + + /************************************************************* + * + */ + private boolean isNumeric(final String str) { + if(str == null) return false; + return str.matches("[0-9.]+"); + } + + /************************************************************* + * + */ + private boolean isDuplicatedName(final String name) { + mxCell root = (mxCell)graphComponent.getGraph().getDefaultParent(); + + for(int i = 0; i < root.getChildCount(); i++) { + mxCell layerCell = (mxCell)root.getChildAt(i); + for(int j = 0; j < layerCell.getChildCount(); j++) { + mxCell cell = (mxCell)layerCell.getChildAt(i); + + ObjectNodeAttribute attr = null; + if(cell.getValue() instanceof ObjectNodeAttribute) + attr = (ObjectNodeAttribute)cell.getValue(); + else continue; + + if( !(attr.getObjectNode().getName().equals(name))) continue; + return true; + } + } + return false; + } + + /************************************************************* + * [ *inner class ] + /************************************************************* + * [ action ] + * Inserting an intermediation object type of . + */ + private class InsertObjectNodeAction extends MouseAdapter { + @Override + public void mouseReleased(MouseEvent e) { + // if the right mouse button was clicked, + // then pop up the dialog name to insert a mediator-object. + if( !curState.equals(ControlFlowDelegationStageStatus.SELECTING_AN_EDGE)) return; + if( !SwingUtilities.isRightMouseButton(e) )return; + + Object cellObj = graphComponent.getCellAt(e.getX(), e.getY()); + insertObjectNode(cellObj); + } + + /*************************************************************/ + private void insertObjectNode(final Object cellObj) { + if(cellObj == null) return; + + mxCell edgeCell = null; + if(cellObj instanceof mxCell) edgeCell = (mxCell)cellObj; + else return; + + curState = ControlFlowDelegationStageStatus.SELECTING_AN_EDGE; + + // Inputing name to the dialog. + String objName = JOptionPane.showInputDialog("Object Name:"); + if(objName == null) return; + + if( objName.isEmpty()) { + JOptionPane.showMessageDialog(graphComponent, "You must input a name. \nIt mustn't be empty."); + return; + } + + CallEdgeAttribute callEdgeAttr = null; + if(edgeCell.getValue() instanceof CallEdgeAttribute) { + callEdgeAttr = (CallEdgeAttribute)edgeCell.getValue(); + } + else throw new ClassCastException(); + + if( isDuplicatedName(objName) ) { + JOptionPane.showMessageDialog(graphComponent, "The named object has already existed."); + return; + } + + ((ControlFlowDelegationStage)stage) + .insertObjectNodeCellInControlFlowLayer(graphComponent.getGraph(), edgeCell, objName); + } + + } } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java index 2171a54..15497b4 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java @@ -1,32 +1,44 @@ package application.editor.stages; import java.util.HashMap; +import java.util.List; import java.util.Map; import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGeometry; import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.util.mxEventSource.mxIEventListener; +import com.mxgraph.util.mxPoint; import com.mxgraph.view.mxGraph; +import application.editor.Editor; import application.editor.FlowCellEditor; -import application.editor.InEdgeAttribute; -import application.editor.OutEdgeAttribute; import application.editor.Stage; import models.Edge; +import models.Node; import models.controlFlowModel.CallEdge; import models.controlFlowModel.CallEdgeAttribute; import models.controlFlowModel.CallGraph; +import models.controlFlowModel.ControlFlowDelegator; import models.controlFlowModel.ControlFlowGraph; +import models.controlFlowModel.EntryPointObjectNode; +import models.controlFlowModel.ObjectNode; +import models.controlFlowModel.ObjectNodeAttribute; import models.controlFlowModel.StatefulObjectNode; -import models.dataConstraintModel.IdentifierTemplate; import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.PushPullValue; import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.ResourceNodeAttribute; +/************************************************************* + * + */ public class ControlFlowDelegationStage extends Stage { public final int PORT_DIAMETER = 8; public final int PORT_RADIUS = PORT_DIAMETER / 2; private ControlFlowGraph controlFlowGraph = null; - + /************************************************************* * [ *constructor ] /************************************************************* @@ -41,8 +53,6 @@ * [ *public ] /************************************************************* * - * @param prevStage - * @return */ @Override public boolean canChangeFrom(Stage prevStage) { @@ -52,7 +62,6 @@ /************************************************************* * - * @param prevStage */ @Override public void init(Stage prevStage) { @@ -60,52 +69,280 @@ model = ((PushPullSelectionStage) prevStage).getModel(); DataFlowGraph dataFlowGraph = ((PushPullSelectionStage) prevStage).getDataFlowGraph(); - controlFlowGraph = new ControlFlowGraph(dataFlowGraph); - + + controlFlowGraph = new ControlFlowGraph(dataFlowGraph, model); + graph = clearControlFlowGraphCells(graph); graph = constructGraph(graph, controlFlowGraph); - - // First, a mouse-event is "Showing delegatable Objects". } } /************************************************************* * - * @return */ @Override public FlowCellEditor createCellEditor(mxGraphComponent graphComponent) { return new ControlFlowDelegationCellEditor(this, graphComponent); } + + @Override + public mxIEventListener createChangeEventListener(Editor editor) { + return null; + } + + /************************************************************* + * + */ + public void showDelegatableNodes(mxGraph graph, final CallEdgeAttribute callEdgeAttr){ + mxCell root = (mxCell)graph.getDefaultParent(); + mxCell layerCell = null; + switch(callEdgeAttr.getSelectedOption()) { + case PUSH: + layerCell = (mxCell)root.getChildAt(Stage.PUSH_FLOW_LAYER); + break; + + case PULL: + case PUSHorPULL: + layerCell = (mxCell)root.getChildAt(Stage.PULL_FLOW_LAYER); + } + + graph.getModel().beginUpdate(); + try { + ObjectNode delegatingNode = callEdgeAttr.getDestinationObjectNode(); + + for(Object node : graph.getChildVertices(layerCell)) { + if( !(node instanceof mxCell) ) continue; + mxCell cell = (mxCell)node; + + ObjectNodeAttribute objNodeAttr = (ObjectNodeAttribute)cell.getValue(); + if(objNodeAttr == null) return; + + ObjectNode objNode = objNodeAttr.getObjectNode(); + ControlFlowDelegator delegator = new ControlFlowDelegator(controlFlowGraph); + List delegatableNodes = delegator.searchDelegatableNodes(callEdgeAttr.getCallEdge()); + + if(delegatableNodes.contains(objNode)) // enable + graph.getModel().setStyle(cell, objNodeAttr.getEnableStyle()); + else // disable + graph.getModel().setStyle(cell, objNodeAttr.getDisableStyle()); + + + // base-Node + if(delegatingNode.equals(objNodeAttr.getObjectNode())) + graph.getModel().setStyle(cell, objNodeAttr.getDelegatingStyle()); + } + } + finally { + graph.getModel().endUpdate(); + graph.refresh(); + } + } + + /************************************************************* + * Showing the delegated graph. + */ + public void showDelegatedGraph(mxGraph graph, mxCell targetEdgeCell, final mxCell dstObjNodeCell) { + ObjectNode dstObjNode = ((ObjectNodeAttribute)dstObjNodeCell.getValue()).getObjectNode(); + if(dstObjNode == null) throw new ClassCastException(); + + CallEdgeAttribute targetEdgeAttr = (CallEdgeAttribute)targetEdgeCell.getValue(); + if(targetEdgeAttr == null) throw new ClassCastException(); + + ControlFlowDelegator delegator = new ControlFlowDelegator(controlFlowGraph); + delegator.delegateCallEdge(targetEdgeAttr.getCallEdge(), dstObjNode); + + mxCell root = (mxCell)graph.getDefaultParent(); + mxCell layerCell = null; + switch(targetEdgeAttr.getSelectedOption()) { + case PUSH: + layerCell = (mxCell)root.getChildAt(Stage.PUSH_FLOW_LAYER); + break; + + case PULL: + case PUSHorPULL: + layerCell = (mxCell)root.getChildAt(Stage.PULL_FLOW_LAYER); + } + + try { + mxCell dstNodeCell = targetEdgeAttr.getDestinationCell(); + + // Removing the target edge from graph model. + if(graph.getModel().getValue(targetEdgeCell) != null) { + graph.getModel().remove(targetEdgeCell); + } + + // Insert an edge + CallEdgeAttribute newAttr = new CallEdgeAttribute(targetEdgeAttr.getCallEdge(), targetEdgeAttr.getOriginalSourceObjectNode(),dstObjNodeCell, dstNodeCell); + graph.insertEdge(layerCell, "", newAttr, dstObjNodeCell, dstNodeCell, "movable=false;"); + + resetAllStyleOfCells(); + } + finally { + graph.getModel().endUpdate(); + } + } + + /************************************************************* + * + */ + public void resetAllStyleOfCells() { + mxCell root = (mxCell)graph.getDefaultParent(); + + graph.getModel().beginUpdate(); + try { + for(int i = Stage.PUSH_FLOW_LAYER; i <= Stage.PULL_FLOW_LAYER; i++) { + mxCell layerCell = (mxCell)root.getChildAt(i); + for(Object node : graph.getChildVertices(layerCell)) { + mxCell cell = null; + if(node instanceof mxCell) cell = (mxCell)node; + else continue; + + ObjectNodeAttribute objNodeAttr = (ObjectNodeAttribute)(cell.getValue()); + if(objNodeAttr == null) throw new NullPointerException(""); + + graph.getModel().setStyle(cell, objNodeAttr.getDefaultStyle()); + } + } + } + finally { + graph.getModel().endUpdate(); + graph.refresh(); + } + } + + /************************************************************* + * Inserting an intermediation object type of . + * todo: support to PUSH/PULL-layer + */ + public void insertObjectNodeCellInControlFlowLayer(mxGraph graph, mxCell targetEdge, final String insertObjName) { + CallEdgeAttribute callEdgeAttr = (CallEdgeAttribute)targetEdge.getValue(); + if(callEdgeAttr == null) throw new NullPointerException(); + + mxCell root = (mxCell)graph.getDefaultParent(); + mxCell layerCell = null; + switch(callEdgeAttr.getSelectedOption()) { + case PUSH: + layerCell = (mxCell)root.getChildAt(Stage.PUSH_FLOW_LAYER); + break; + + case PULL: + case PUSHorPULL: + layerCell = (mxCell)root.getChildAt(Stage.PULL_FLOW_LAYER); + } + + graph.getModel().beginUpdate(); + + try { + // Inserting the node type of to the graph. + ObjectNode insertObjNode = new ObjectNode(insertObjName); + ObjectNodeAttribute objNodeAttr = new ObjectNodeAttribute(insertObjNode); + + mxPoint srcPoint = new mxPoint(callEdgeAttr.getSourceCell().getGeometry().getX(), callEdgeAttr.getSourceCell().getGeometry().getY()); + mxPoint dstPoint = new mxPoint(callEdgeAttr.getDestinationCell().getGeometry().getX(), callEdgeAttr.getDestinationCell().getGeometry().getY()); + mxPoint insertPoint = new mxPoint( + (srcPoint.getX() + dstPoint.getX())/2, + (srcPoint.getY() + dstPoint.getY())/2); + + mxCell insertObjNodeCell = + (mxCell)graph.insertVertex(layerCell, null, objNodeAttr, + /* coordinate*/ insertPoint.getX(), insertPoint.getY(), + /* scale */ 40, 40, + objNodeAttr.getDefaultStyle()); + insertObjNodeCell.setValue(objNodeAttr); + + addObjectNodeToCallGraphl(insertObjNode, callEdgeAttr.getSelectedOption()); + + // Reconnecting each edges of the node. + ObjectNode srcObjNode = callEdgeAttr.getSourceObjectNode(); + ObjectNode dstObjNode = callEdgeAttr.getDestinationObjectNode(); + if(srcObjNode == null || dstObjNode == null) throw new NullPointerException(); + if(!(srcObjNode instanceof ObjectNode && dstObjNode instanceof ObjectNode)) throw new ClassCastException(); + + // Connecting I/O Edges to the insert object. + CallEdge srcToInsertEdge = callEdgeAttr.getCallEdge(); + CallEdge insertToDstEdge = new CallEdge(insertObjNode, dstObjNode, callEdgeAttr.getSelectedOption()); + if(srcToInsertEdge == null || insertToDstEdge == null) throw new NullPointerException(); + + // Remove the destination edge of the object node. + // After add the "srcToInsertEdge" to the destination object node. + dstObjNode.removeInEdge(srcToInsertEdge); + dstObjNode.addInEdge(insertToDstEdge); + + srcToInsertEdge.setDestination(insertObjNode); // changing the out of edge of the sourceObjectNode + + insertObjNode.addInEdge(srcToInsertEdge); + insertObjNode.addOutEdge(insertToDstEdge); + + // Update the cell of the graph. + for(int i =0; i < layerCell.getChildCount(); i++) { + mxCell nodeCell = (mxCell)layerCell.getChildAt(i); + if( !nodeCell.isVertex()) continue; + + // Checking "nodeCell" has an instance of + ObjectNodeAttribute cellObjNodeAttr = (ObjectNodeAttribute)nodeCell.getValue(); + if(cellObjNodeAttr == null) throw new ClassCastException("dosen't have the value of "); + + // Is "nodeCell" the same as the source cell of the call edge? + if(nodeCell.equals(callEdgeAttr.getSourceCell())){ + mxCell srcNodeCell = callEdgeAttr.getSourceCell(); + CallEdgeAttribute newInEdgeAttr = new CallEdgeAttribute(srcToInsertEdge, srcNodeCell, insertObjNodeCell); + + // If the target call edge hasn't removed yet. + // then it removes from mxGraphModel. + if(graph.getModel().getValue(targetEdge) != null) + graph.getModel().remove(targetEdge); + + mxCell outPortCell = (mxCell)srcNodeCell.getChildAt(0); + if(outPortCell != null) { + graph.insertEdge(layerCell, null, newInEdgeAttr, outPortCell, insertObjNodeCell, "movable=false;"); + } + else { + graph.insertEdge(layerCell, null, newInEdgeAttr, srcNodeCell, insertObjNodeCell, "movable=false;"); + } + continue; + } + // Is "nodeCell" the same as the destination cell of the call edge? + else if(nodeCell.equals(callEdgeAttr.getDestinationCell())) { + mxCell dstNodeCell = callEdgeAttr.getDestinationCell(); + CallEdgeAttribute newOutEdgeAttr = new CallEdgeAttribute(insertToDstEdge, insertObjNodeCell, dstNodeCell); + + // If the target + if(graph.getModel().getValue(targetEdge) != null) + graph.getModel().remove(targetEdge); + + graph.insertEdge(layerCell, null, newOutEdgeAttr, insertObjNodeCell, dstNodeCell, "movable=false;"); + + continue; + } + } + } + finally { + graph.getModel().endUpdate(); + } + } + /************************************************************* * [ *private ] /************************************************************* - * [ views ] - /************************************************************* * - * @param graph - * @param dataFlowGraph */ - private mxGraph constructGraph(mxGraph graph, ControlFlowGraph controlFlowGraph) { - mxCell root = (mxCell) graph.getDefaultParent(); - - showOnlyLayer(graph, CONTROL_FLOW_LAYER); - - // Creating Control-Flow and separeted Push/Pull which types of - Map controlFlowNodeCells = createCellsOfResourceMap(graph, CONTROL_FLOW_LAYER, controlFlowGraph); - Map pushResNodeCells = createCellsOfResourceMap(graph, PUSH_FLOW_LAYER, controlFlowGraph); - Map pullResNodeCells = createCellsOfResourceMap(graph, PULL_FLOW_LAYER, controlFlowGraph); - + private mxGraph constructGraph(mxGraph graph, ControlFlowGraph controlFlowGraph) { + showOnlyLayer(PUSH_FLOW_LAYER, PULL_FLOW_LAYER); + graph.getModel().beginUpdate(); try { - // Inserting edges of both Push and Pull transfer - graph = insertControlFlowEdges(graph, CONTROL_FLOW_LAYER, controlFlowGraph.getPushCallGraph(),controlFlowNodeCells); - graph = insertControlFlowEdges(graph, CONTROL_FLOW_LAYER, controlFlowGraph.getPullCallGraph(),controlFlowNodeCells); + // Creating Control-Flow and separeted Push/Pull which types of + Map pushResNodeCells = createCellsOfResourceMap(graph, PUSH_FLOW_LAYER, controlFlowGraph); + Map pullResNodeCells = createCellsOfResourceMap(graph, PULL_FLOW_LAYER, controlFlowGraph); + // Creating Entry-Point Object + Map pushFlowEntryNodeCells = createCellsOfInputChannel(graph, PUSH_FLOW_LAYER, controlFlowGraph, pushResNodeCells); + // Inserting edges of each transfer - graph = insertControlFlowEdges(graph, PUSH_FLOW_LAYER, controlFlowGraph.getPushCallGraph(), pushResNodeCells); - graph = insertControlFlowEdges(graph, PULL_FLOW_LAYER, controlFlowGraph.getPullCallGraph(), pullResNodeCells); + graph = insertControlFlowEdges(graph, PUSH_FLOW_LAYER, controlFlowGraph.getPushCallGraph(), pushResNodeCells, pushFlowEntryNodeCells); + graph = insertControlFlowEdges(graph, PULL_FLOW_LAYER, controlFlowGraph.getPullCallGraph(), pullResNodeCells, null); + } finally { graph.getModel().endUpdate(); } @@ -114,7 +351,6 @@ /************************************************************* * When changed from previous stage, it will be called in initializing. - * @return */ private mxGraph clearControlFlowGraphCells(mxGraph graph) { mxCell root = (mxCell)graph.getDefaultParent(); @@ -124,12 +360,9 @@ // removing child from end of a root cell root.remove(root.getChildAt(PULL_FLOW_LAYER)); root.remove(root.getChildAt(PUSH_FLOW_LAYER)); - root.remove(root.getChildAt(CONTROL_FLOW_LAYER)); root.insert(new mxCell()); - root.insert(new mxCell()); - root.insert(new mxCell()); - + root.insert(new mxCell()); } finally { graph.getModel().endUpdate(); } @@ -141,37 +374,106 @@ /************************************************************* * Creating a map of to and Creating 's vertices - * @param model - * @param dataFlowGraph - * @return constructed mxGraph + * @return constructed the view of the graph */ - private Map createCellsOfResourceMap(mxGraph graph, final int layerNumber, final ControlFlowGraph controlFlowGraph) { - Map resNodeCells = new HashMap<>(); + private Map createCellsOfResourceMap(mxGraph graph, final int layerNumber, final ControlFlowGraph controlFlowGraph) { + Map resNodeCells = new HashMap<>(); mxCell root = (mxCell)graph.getDefaultParent(); + mxCell nodeLayerCell = (mxCell)root.getChildAt(NODE_LAYER); mxCell layerCell = (mxCell)root.getChildAt(layerNumber); // create resource vertices for (ResourceNode resNode : controlFlowGraph.getDataFlowGraph().getResouceNodes()) { - IdentifierTemplate id = resNode.getIdentifierTemplate(); - Object resNodeObj = graph.insertVertex(layerCell, null, - id.getResourceName(), 20, 20, 80, 30, - "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex - resNodeCells.put(resNode, resNodeObj); + + ObjectNode objNode = null; + switch(layerNumber) { + case PUSH_FLOW_LAYER: + if(controlFlowGraph.getPushCallGraph().getStatefulObjectNode(resNode) != null) + objNode = controlFlowGraph.getPushCallGraph().getStatefulObjectNode(resNode); + break; + + case PULL_FLOW_LAYER: + if(controlFlowGraph.getPullCallGraph().getStatefulObjectNode(resNode) != null) + objNode = controlFlowGraph.getPullCallGraph().getStatefulObjectNode(resNode); + break; + } + + if(objNode == null) continue; + + for(int i =0; i < nodeLayerCell.getChildCount(); i++) { + mxCell nodeCell = (mxCell)nodeLayerCell.getChildAt(i); + if( nodeCell.getValue() instanceof ResourceNodeAttribute ) { + nodeCell = (mxCell)nodeLayerCell.getChildAt(i); + } + else continue; + + // Checking if the "node" has a cell of the data-flow-layer is the same as "resNode". + ResourceNodeAttribute resNodeAttr = (ResourceNodeAttribute)nodeCell.getValue(); + if( !resNodeAttr.getResourceNode().equals(resNode) )continue; + + // Getting information from the cell in the data-flow-layer, + // After that, insert a resource as a vertex + ObjectNodeAttribute objNodeAttr = new ObjectNodeAttribute(objNode); + mxCell resNodeObjCell = (mxCell)graph.insertVertex(layerCell, null, objNodeAttr, + /* scale */nodeCell.getGeometry().getX(), nodeCell.getGeometry().getY(), + /*coordinate*/nodeCell.getGeometry().getWidth(), nodeCell.getGeometry().getHeight(), + objNodeAttr.getDefaultStyle()); + + resNodeCells.put(resNode, resNodeObjCell); + } } return resNodeCells; } /************************************************************* - * - * @param graph - * @param layerNumber - * @param callGraph - * @param resNodeCells - * @return + * Createing an input channel object */ - private mxGraph insertControlFlowEdges(mxGraph graph, final int layerNumber, final CallGraph callGraph ,final Map resNodeCells) { + private Map createCellsOfInputChannel(mxGraph graph, final int layerNumber, final ControlFlowGraph controlGraph, final Map resNodeCell){ + if(layerNumber == PULL_FLOW_LAYER) return null; + + mxCell root = (mxCell)graph.getDefaultParent(); + mxCell layerCell = (mxCell)root.getChildAt(layerNumber); + + Map ioChannelCells = new HashMap<>(); + + graph.getModel().beginUpdate(); + try { + mxGeometry outPortGeometry = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + outPortGeometry.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + outPortGeometry.setRelative(true); + + CallGraph callGraph = controlFlowGraph.getPushCallGraph(); + + // insert an I/O channel as a vertex + for (Node node : callGraph.getNodes()) { + EntryPointObjectNode entryPointObjNode = null; + if(node instanceof EntryPointObjectNode) + entryPointObjNode = (EntryPointObjectNode)node; + else continue; + + ObjectNodeAttribute entryObjAttr = new ObjectNodeAttribute(entryPointObjNode); + + mxCell channel = (mxCell)graph.insertVertex(layerCell, null, entryObjAttr, 150, 20, 30, 30); + mxCell port_out = new mxCell(null, outPortGeometry, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + + graph.addCell(port_out, channel); // insert the output port of a channel + ioChannelCells.put(entryPointObjNode, channel); + } + } + finally { + graph.getModel().endUpdate(); + } + + return ioChannelCells; + } + + /************************************************************* + * When changed from previous stage, it will be called in initializing. + */ + private mxGraph insertControlFlowEdges(mxGraph graph, final int layerNumber, final CallGraph callGraph ,final Map resNodeCells, final Map entryNodeCells) { mxCell root = (mxCell)graph.getDefaultParent(); mxCell layerCell = (mxCell)root.getChildAt(layerNumber); @@ -180,17 +482,61 @@ CallEdge callEdge = (CallEdge) callGraphEdge; // Is checking node connecting a resource? - if(callEdge.getSource() == null) continue; - if(callEdge.getDestination() == null) continue; + if(callEdge.getSource() == null || callEdge.getDestination() == null) continue; - ResourceNode srcResNode = ((StatefulObjectNode)callEdge.getSource()).getResource(); + Node srcResNode = null; ResourceNode dstResNode = ((StatefulObjectNode)callEdge.getDestination()).getResource(); - Object srcNodeCell =resNodeCells.get(srcResNode); - Object dstNodeCell = resNodeCells.get(dstResNode); - - graph.insertEdge(layerCell, null, null/*callEdgeAttribute*/,srcNodeCell, dstNodeCell, "movable=false"); + mxCell srcNodeCell =null; + mxCell srcOutPortCell = null; + mxCell dstNodeCell = resNodeCells.get(dstResNode); + + if(callEdge.getSource() instanceof StatefulObjectNode) { + srcResNode = ((StatefulObjectNode)callEdge.getSource()).getResource(); + srcNodeCell =resNodeCells.get(srcResNode); + } + else if (callEdge.getSource() instanceof EntryPointObjectNode) { + srcResNode = (EntryPointObjectNode)callEdge.getSource(); + srcNodeCell = entryNodeCells.get(srcResNode); + srcOutPortCell = (mxCell)srcNodeCell.getChildAt(0); + } + else continue; + + if(srcNodeCell == null || dstNodeCell == null) continue; + + CallEdgeAttribute callEdgeAttr = new CallEdgeAttribute(callEdge, (ObjectNode)callEdge.getSource(), srcNodeCell, dstNodeCell); + + // If "srcResNode" types of "EntryPointObjectNode" (= channel) + // then parameter references to geometry of "outPort". + if(srcResNode instanceof ResourceNode) { + graph.insertEdge(layerCell, null, callEdgeAttr, srcNodeCell, dstNodeCell, "movable=false;"); + } + else if(srcResNode instanceof EntryPointObjectNode) { + graph.insertEdge(layerCell, null, callEdgeAttr, srcOutPortCell, dstNodeCell, "movable=false;"); + } + } return graph; } + + /************************************************************* + * + */ + private void addObjectNodeToCallGraphl(final ObjectNode insertObjNode, final PushPullValue selectedOption) { + switch(selectedOption) { + case PUSH: + if(controlFlowGraph.getPushCallGraph().getNodes().contains(insertObjNode))return; + controlFlowGraph.getPushCallGraph().addNode(insertObjNode); + + break; + + case PULL: + case PUSHorPULL: + if(controlFlowGraph.getPullCallGraph().getNodes().contains(insertObjNode))return; + controlFlowGraph.getPullCallGraph().addNode(insertObjNode); + + break; + } + } + } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStageStatus.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStageStatus.java new file mode 100644 index 0000000..9cf8f99 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStageStatus.java @@ -0,0 +1,10 @@ +package application.editor.stages; + +/************************************************************* + * + * @author k-fujii + */ +public enum ControlFlowDelegationStageStatus { + SELECTING_AN_EDGE, + SHOWING_DELEGATABLE_NODES, +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java index 30f7156..f05c14c 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java @@ -38,6 +38,7 @@ * */ public class DataFlowCellEditor extends FlowCellEditor { + /************************************************************* * [ *constructor ] /************************************************************* diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java index 76176e5..100de3d 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java @@ -1,16 +1,21 @@ package application.editor.stages; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; 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.mxEventObject; import com.mxgraph.util.mxPoint; import com.mxgraph.view.mxGraph; import algorithms.Validation; +import application.editor.Editor; import application.editor.Editor.SrcDstAttribute; import application.editor.FlowCellEditor; import application.editor.Stage; @@ -19,6 +24,7 @@ import models.dataConstraintModel.IdentifierTemplate; import models.dataFlowModel.DataTransferChannelGenerator; import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ResourceNodeAttribute; import models.visualModel.FormulaChannelGenerator; import parser.Parser; import parser.Parser.TokenStream; @@ -34,29 +40,75 @@ import parser.exceptions.WrongLHSExpression; import parser.exceptions.WrongRHSExpression; +/************************************************************* + * + * @author n-nitta, k-fujii + */ public class DataFlowModelingStage extends Stage { public int PORT_DIAMETER = 8; public int PORT_RADIUS = PORT_DIAMETER / 2; + /************************************************************* + * [ *constructor] + /************************************************************* + * + */ public DataFlowModelingStage(mxGraph graph) { super(graph); } + /************************************************************* + * [ *public ] + /************************************************************* + * + */ @Override public boolean canChangeFrom(Stage prevStage) { return true; } + /************************************************************* + * + */ @Override public void init(Stage prevStage) { - showOnlyLayer(graph, NODE_LAYER, DATA_FLOW_LAYER); + showOnlyLayer(DATA_FLOW_LAYER); } + /************************************************************* + * + */ @Override public FlowCellEditor createCellEditor(mxGraphComponent graphComponent) { return new DataFlowCellEditor(this, graphComponent); } + + @Override + public mxIEventListener createChangeEventListener(Editor editor) { + return new mxIEventListener() { + public void invoke(Object sender, mxEventObject evt) { + List terminals = new ArrayList<>(); + mxCell cell = null; + for (Object change: ((List) evt.getProperties().get("changes"))) { + if (change instanceof mxGraphModel.mxTerminalChange) { + mxGraphModel.mxTerminalChange terminalChange = (mxGraphModel.mxTerminalChange) change; + cell = (mxCell) terminalChange.getCell(); + mxCell terminal = (mxCell) terminalChange.getTerminal(); + terminals.add(terminal); + } + } + if (terminals.size() == 2) { + if (!editor.connectEdge(cell, terminals.get(0), terminals.get(1))) { + graph.removeCells(new mxCell[] {cell}); + } + } + } + }; + } + /************************************************************* + * + */ public void clear() { model = null; ((mxGraphModel) graph.getModel()).clear(); @@ -69,13 +121,18 @@ root.insert(new mxCell()); // CONTROL_FLOW_LAYER root.insert(new mxCell()); // PUSH_FLOW_LAYER root.insert(new mxCell()); // PULL_FLOW_LAYER - showOnlyLayer(graph, NODE_LAYER, DATA_FLOW_LAYER); - } finally { + + showOnlyLayer(NODE_LAYER, DATA_FLOW_LAYER); + } + finally { graph.getModel().endUpdate(); } graph.refresh(); } + /************************************************************* + * + */ public DataTransferModel getModel() { if (model == null) { setModel(new DataTransferModel()); @@ -83,6 +140,9 @@ return model; } + /************************************************************* + * + */ public void setModel(DataTransferModel model) { clear(); // Set the model. @@ -91,14 +151,17 @@ // Update the mxGraph. graph = constructGraph(graph, model); } - + + /************************************************************* + * + */ public boolean isValid() { if (model == null) return false; if (!Validation.checkUpdateConflict(model)) return false; return true; } - /** + /************************************************************* * Construct a mxGraph from DataFlowModel * @param model * @param dataFlowGraph @@ -141,9 +204,13 @@ // create resource vertices for (IdentifierTemplate res: model.getIdentifierTemplates()) { - Object resource = graph.insertVertex(dataFlowLayer, null, - res.getResourceName(), 20, 20, 80, 30, - "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex + // insert a resource as a vertex + ResourceNodeAttribute resNodeAttr = new ResourceNodeAttribute(model.getDataFlowGraph().getResouceNode(res)); + Object resource = graph.insertVertex( + dataFlowLayer, null, resNodeAttr, + /*coordinate*/20, 20, + /* scale */80, 30, + resNodeAttr.getDefaultStyle()); resources.put(res, resource); } @@ -171,9 +238,11 @@ port_out.setVertex(true); graph.addCell(port_out, channel); // insert the output port of a channel channelsOut.put((DataTransferChannelGenerator) ioChannelGen, port_out); + for (IdentifierTemplate outRes: ((DataTransferChannelGenerator) ioChannelGen).getOutputIdentifierTemplates()) { graph.insertEdge(dataFlowLayer, null, null, port_out, resources.get(outRes), "movable=false;strokeColor=#FF0000"); } + } } } finally { @@ -183,6 +252,9 @@ return graph; } + /************************************************************* + * + */ public void addIdentifierTemplate(IdentifierTemplate res) { getModel().addIdentifierTemplate(res); graph.getModel().beginUpdate(); @@ -196,6 +268,9 @@ } } + /************************************************************* + * + */ public void addChannelGenerator(DataTransferChannelGenerator channelGen) { getModel().addChannelGenerator(channelGen); graph.getModel().beginUpdate(); @@ -221,7 +296,10 @@ graph.getModel().endUpdate(); } } - + + /************************************************************* + * + */ public void addIOChannelGenerator(DataTransferChannelGenerator ioChannelGen) { getModel().addIOChannelGenerator(ioChannelGen); graph.getModel().beginUpdate(); @@ -292,6 +370,9 @@ return true; } + /************************************************************* + * + */ public void delete() { for (Object obj: graph.getSelectionCells()) { mxCell cell = (mxCell) obj; @@ -324,6 +405,9 @@ graph.removeCells(graph.getSelectionCells()); } + /************************************************************* + * + */ public void setChannelCode(DataTransferChannelGenerator ch, String code) { ch.setSourceText(code); TokenStream stream = new TokenStream(); diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java index f4f27da..49325a3 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java @@ -119,7 +119,6 @@ } } - public String getCurrentValue() { return (String) comboBox.getSelectedItem(); } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java index d3b3318..dedf31d 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java @@ -1,11 +1,18 @@ package application.editor.stages; +import java.util.ArrayList; +import java.util.List; + import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGraphModel; import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.util.mxEventObject; +import com.mxgraph.util.mxEventSource.mxIEventListener; import com.mxgraph.view.mxGraph; import algorithms.DataTransferModelAnalyzer; import application.editor.Editor.SrcDstAttribute; +import application.editor.Editor; import application.editor.FlowCellEditor; import application.editor.InEdgeAttribute; import application.editor.OutEdgeAttribute; @@ -40,10 +47,11 @@ if (prevStage instanceof DataFlowModelingStage) { model = ((DataFlowModelingStage) prevStage).getModel(); dataFlowGraph = analyzeDataTransferModel(graph, model); + showOnlyLayer(DATA_FLOW_LAYER); } if(prevStage instanceof ControlFlowDelegationStage) { - showOnlyLayer(graph, NODE_LAYER, DATA_FLOW_LAYER); + showOnlyLayer(DATA_FLOW_LAYER); } } @@ -52,6 +60,28 @@ return new PushPullSelectionCellEditor(this, graphComponent); } + @Override + public mxIEventListener createChangeEventListener(Editor editor) { + return new mxIEventListener() { + public void invoke(Object sender, mxEventObject evt) { + List terminals = new ArrayList<>(); + mxCell cell = null; + for (Object change: ((List) evt.getProperties().get("changes"))) { + if (change instanceof mxGraphModel.mxTerminalChange) { + mxGraphModel.mxTerminalChange terminalChange = (mxGraphModel.mxTerminalChange) change; + cell = (mxCell) terminalChange.getCell(); + mxCell terminal = (mxCell) terminalChange.getTerminal(); + terminals.add(terminal); + } + } + if (terminals.size() == 2) { + // cancel connect + graph.removeCells(new mxCell[] {cell}); + } + } + }; + } + public DataFlowGraph getDataFlowGraph() { return dataFlowGraph; } diff --git a/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java b/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java index 0a1a204..0389845 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java +++ b/AlgebraicDataflowArchitectureModel/src/application/layouts/DAGLayout.java @@ -15,15 +15,32 @@ import com.mxgraph.view.mxGraph; import com.mxgraph.view.mxGraphView; +import models.controlFlowModel.ObjectNodeAttribute; import models.dataConstraintModel.ChannelGenerator; import models.dataConstraintModel.IdentifierTemplate; +import models.dataFlowModel.ResourceNodeAttribute; +/************************************************************* + * DAG-Layout sorting algorithm. + */ public class DAGLayout extends mxGraphLayout { - public DAGLayout(mxGraph arg0) { - super(arg0); + /************************************************************* + * [ *constructor] + /************************************************************* + * + * @param cell + */ + public DAGLayout(mxGraph cell) { + super(cell); } - + + /************************************************************* + * [ *public ] + /************************************************************* + * Executing a layout sorting algorithm. + */ + @Override public void execute(Object parent) { mxIGraphModel model = graph.getModel(); @@ -60,6 +77,8 @@ for (int j = 0; j < map.get(i).size(); j++) { mxGeometry geom = (mxGeometry) map.get(i).get(j).getGeometry().clone(); mxCellState state = view.getState(map.get(i).get(j)); + + if (checkmoved(moved, map.get(i).get(j))) { if ("ellipse".equals(state.getStyle().get("shape"))){ geom.setX(50 + j*200); diff --git a/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/FlowLayerValue.java b/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/FlowLayerValue.java new file mode 100644 index 0000000..0c9317c --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/FlowLayerValue.java @@ -0,0 +1,10 @@ +package application.views.controlFlowDelegation; + +/************************************************************* + * + */ +public enum FlowLayerValue { + DATA_FLOW, + PUSH_FLOW, + PULL_FLOW +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/ShowFlowWindow.java b/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/ShowFlowWindow.java new file mode 100644 index 0000000..34c1d6a --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/views/controlFlowDelegation/ShowFlowWindow.java @@ -0,0 +1,111 @@ +package application.views.controlFlowDelegation; + +import java.awt.Container; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.ButtonGroup; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JRadioButton; + +import application.ApplicationWindow; +import application.editor.Editor; +import application.editor.IStageChangeListener; +import application.editor.Stage; +import application.editor.stages.ControlFlowDelegationStage; + +/************************************************************* + * the window has a button group for swichting layers in the control-flow-modeling. + */ +public class ShowFlowWindow extends JDialog implements IStageChangeListener { + private String title = "ShowFlowWindow"; + private JCheckBox dataFlowCheckBox = null; + private JCheckBox pushFlowCheckBox = null; + private JCheckBox pullFlowCheckBox = null; + + private ControlFlowDelegationStage stage = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public ShowFlowWindow(final ApplicationWindow owner) { + super(owner); + + setTitle(title); + setDefaultCloseOperation(HIDE_ON_CLOSE); + + stage = Editor.STAGE_CONTROL_FLOW_DELEGATION; + + // initialize buttons + dataFlowCheckBox = new JCheckBox("Data-Flow", false); + pushFlowCheckBox = new JCheckBox("Push-Flow", true); + pullFlowCheckBox = new JCheckBox("Pull-Flow", true); + + // each add handler + dataFlowCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + stage.setEnabledForLayer(Stage.DATA_FLOW_LAYER, dataFlowCheckBox.isSelected()); + }}); + + pushFlowCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + stage.setEnabledForLayer(Stage.PUSH_FLOW_LAYER, pushFlowCheckBox.isSelected()); + }}); + + pullFlowCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + stage.setEnabledForLayer(Stage.PULL_FLOW_LAYER, pullFlowCheckBox.isSelected()); + }}); + + dataFlowCheckBox.setEnabled(false); + pushFlowCheckBox.setEnabled(false); + pullFlowCheckBox.setEnabled(false); + + // initialize panel + Container panel = getContentPane(); + panel.setLayout(new GridLayout(/*low*/3, /*col*/1)); + panel.add(dataFlowCheckBox); + panel.add(pushFlowCheckBox); + panel.add(pullFlowCheckBox); + + pack(); + setResizable(false); + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + @Override + public void stageChanged(Stage newStage) { + if((newStage instanceof ControlFlowDelegationStage)) { + + dataFlowCheckBox.setEnabled(true); + pushFlowCheckBox.setEnabled(true); + pullFlowCheckBox.setEnabled(true); + + newStage.setEnabledForLayer(Stage.PUSH_FLOW_LAYER, pushFlowCheckBox.isSelected()); + newStage.setEnabledForLayer(Stage.PULL_FLOW_LAYER, pullFlowCheckBox.isSelected()); + } + else { + dataFlowCheckBox.setEnabled(false); + pushFlowCheckBox.setEnabled(false); + pullFlowCheckBox.setEnabled(false); + + newStage.setEnabledForLayer(Stage.PUSH_FLOW_LAYER, false); + newStage.setEnabledForLayer(Stage.PULL_FLOW_LAYER, false); + } + } +} + diff --git a/AlgebraicDataflowArchitectureModel/src/models/Edge.java b/AlgebraicDataflowArchitectureModel/src/models/Edge.java index 9ea2037..71ab977 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/Edge.java +++ b/AlgebraicDataflowArchitectureModel/src/models/Edge.java @@ -1,6 +1,8 @@ package models; -public class Edge { +import java.io.Serializable; + +public class Edge implements Serializable { protected Node source; protected Node destination; private EdgeAttribute attribute; diff --git a/AlgebraicDataflowArchitectureModel/src/models/Node.java b/AlgebraicDataflowArchitectureModel/src/models/Node.java index f2537f6..589cc4f 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/Node.java +++ b/AlgebraicDataflowArchitectureModel/src/models/Node.java @@ -1,11 +1,12 @@ package models; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Set; -public class Node implements Cloneable { +public class Node implements Cloneable, Serializable { protected Collection inEdges = null; protected Collection outEdges = null; private NodeAttribute attribute; diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdge.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdge.java index cfe1c83..e19986e 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdge.java +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdge.java @@ -1,11 +1,17 @@ package models.controlFlowModel; import models.Edge; +import models.dataFlowModel.PushPullValue; public class CallEdge extends Edge { - - public CallEdge(ObjectNode src, ObjectNode dst) { + private PushPullValue selectedOption = PushPullValue.PUSHorPULL; + + public CallEdge(ObjectNode src, ObjectNode dst, PushPullValue selectedOption) { super(src, dst); + this.selectedOption = selectedOption; } - + + public PushPullValue getSelectedOption() { + return this.selectedOption; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdgeAttribute.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdgeAttribute.java index 9164d5c..2658597 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdgeAttribute.java +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallEdgeAttribute.java @@ -1,39 +1,98 @@ package models.controlFlowModel; +import com.mxgraph.model.mxCell; + import models.EdgeAttribute; import models.dataFlowModel.PushPullValue; +/************************************************************* + * Information of connection status of the call edge among nodes type of "Object-Node". + */ public class CallEdgeAttribute extends EdgeAttribute { - private PushPullValue selectedOption; - private ObjectNode srcObjNode; - private ObjectNode dstObjNode; + private CallEdge callEdge = null; + private ObjectNode orginalSrcObjNode = null; + private mxCell srcCell = null; + private mxCell dstCell = null; /************************************************************* * [ *constructor ] /************************************************************* * */ - public CallEdgeAttribute(PushPullValue selectedOption, ObjectNode srcObjNode, ObjectNode dstObjNode) { - this.selectedOption = selectedOption; - this.srcObjNode = srcObjNode; - this.dstObjNode = dstObjNode; + public CallEdgeAttribute(CallEdge callEdge, ObjectNode originalSrcObjNode, final mxCell srcCell, final mxCell dstCell) { + this.callEdge = callEdge; + this.callEdge.setAttribute(this); + + this.orginalSrcObjNode = originalSrcObjNode; + + this.srcCell = srcCell; + this.dstCell = dstCell; } + + /************************************************************* + * + */ + public CallEdgeAttribute(CallEdge callEdge, final mxCell srcCell, final mxCell dstCell) { + this.callEdge = callEdge; + this.callEdge.setAttribute(this); + + this.srcCell = srcCell; + this.dstCell = dstCell; + } + /************************************************************* * [ *public ] /************************************************************* - * [ getter ] + * [ getter ] /*************************************************************/ - public PushPullValue getSelectedOption() { - return selectedOption; + public CallEdge getCallEdge() { + return callEdge; } + public ObjectNode getOriginalSourceObjectNode() { + return orginalSrcObjNode; + } + + public PushPullValue getSelectedOption() { + return callEdge.getSelectedOption(); + } + public ObjectNode getSourceObjectNode() { - return srcObjNode; + if( !(callEdge.getSource() instanceof ObjectNode) ) throw new ClassCastException("sourceNode isn't type of "); + return (ObjectNode)callEdge.getSource(); } public ObjectNode getDestinationObjectNode() { - return dstObjNode; + if( !(callEdge.getDestination() instanceof ObjectNode) ) throw new ClassCastException("destinationNode isn't type of "); + return (ObjectNode)callEdge.getDestination(); } + public mxCell getSourceCell() { + return srcCell; + } + + public mxCell getDestinationCell() { + return dstCell; + } + + public void setDestinationCell(final mxCell dstCell) { + this.dstCell = dstCell; + } + + /************************************************************* + * + */ + @Override + public String toString() { + String value = ""; + + if(2 <= callEdge.getSource().getOutEdges( ).size()) { + int order = (((ObjectNode)callEdge.getSource()).getOutEdgeCallOrder(callEdge)+ 1); + value += "[" + order + "]"; + } + + return value; + } + } diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallGraph.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallGraph.java index c533f09..fbd3356 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/CallGraph.java @@ -5,6 +5,7 @@ import models.DirectedGraph; import models.Node; +import models.dataFlowModel.PushPullValue; import models.dataFlowModel.ResourceNode; public class CallGraph extends DirectedGraph { @@ -31,14 +32,14 @@ } } - public void addEdge(ResourceNode srcResNode, ResourceNode dstResNode) { + public void addEdge(ResourceNode srcResNode, ResourceNode dstResNode, PushPullValue selectedOption) { addNode(srcResNode); addNode(dstResNode); - addEdge(new CallEdge(getStatefulObjectNode(srcResNode), getStatefulObjectNode(dstResNode))); + addEdge(new CallEdge(getStatefulObjectNode(srcResNode), getStatefulObjectNode(dstResNode), selectedOption)); } - public void insertEdge(ObjectNode srcObjNode, ObjectNode dstObjNode, int n) { - CallEdge edge = new CallEdge(srcObjNode, dstObjNode); + public void insertEdge(ObjectNode srcObjNode, ObjectNode dstObjNode, PushPullValue selectedOption, int n) { + CallEdge edge = new CallEdge(srcObjNode, dstObjNode, selectedOption); simpleAddEdge(edge); addNode(srcObjNode); addNode(dstObjNode); diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowDelegator.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowDelegator.java index 5aca969..2d0b5de 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowDelegator.java +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowDelegator.java @@ -1,41 +1,173 @@ package models.controlFlowModel; import java.util.ArrayList; +import java.util.List; -import models.Node; -import models.dataFlowModel.PushPullAttribute; +import models.Edge; -/**-------------------------------------------------------------------------------- +/************************************************************* * it has Delegation of Control-Flow algorithm. */ public class ControlFlowDelegator { - /**-------------------------------------------------------------------------------- - * [ *public ] - /**-------------------------------------------------------------------------------- + private ControlFlowGraph controlFlowGraph = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* * - * Todo: - * 1. object-nodeとmxCellを対応付ける - * 2. mxGraphを再構築? - * 3. mxGraphModelから委譲可能なmxCellのリストと */ - public void changeControlFlowGraph() {} + public ControlFlowDelegator(final ControlFlowGraph controlFlowGraph) { + this.controlFlowGraph = controlFlowGraph; + } - /**-------------------------------------------------------------------------------- + /************************************************************* + * [ *public ] + /************************************************************* * *@param callEdge */ - public ArrayList searchDelegatableNodes(final CallEdge callEdge){ - ArrayList nodes = new ArrayList<>(); + public List searchDelegatableNodes(final CallEdge callEdge){ + List nodes = new ArrayList<>(); - Node parentNode = callEdge.getSource(); - if(parentNode == null) return null; + // 1. adding parentNode + ObjectNode delegatingNode = (ObjectNode) callEdge.getDestination(); + ObjectNode parentNode = (ObjectNode) callEdge.getSource(); + + if(parentNode == null || delegatingNode == null) + throw new NullPointerException("parentNode is null."); + if( !(parentNode instanceof ObjectNode && delegatingNode instanceof ObjectNode)) + throw new ClassCastException("callEdge.getSource() is not ObjectNode"); - PushPullAttribute pushPullAttribute = (PushPullAttribute)callEdge.getAttribute(); - if( pushPullAttribute == null) return null; - if( !(pushPullAttribute instanceof PushPullAttribute) ) return null; + // if the relation of "delegatingNode" to "parentNode" is 1 : 1 ? + // then return an empty list. + if( isRootNode(parentNode) && ! hasChildrenNode(parentNode) ) return nodes; + + // 2. collecting for each transfer method has nodes in the common area. + collectCommonTransferNodes(nodes, parentNode, delegatingNode); + + // 3. if the transfer method is PUSH-style, + // then serach delegatable area. + collectParentNodesInPushTransfer(nodes, delegatingNode, parentNode); // switch objects by transfer type - return null; + return nodes; + } + + /************************************************************* + * + */ + public void delegateCallEdge(CallEdge delegatingEdge, final ObjectNode dstObjNode) { + ObjectNode srcObjNode = (ObjectNode)delegatingEdge.getDestination(); + if(srcObjNode == null) throw new ClassCastException(); + + delegatingEdge.getSource().removeOutEdge(delegatingEdge); + srcObjNode.removeInEdge(delegatingEdge); + + // Reconnecting the edge to the new source object. + delegatingEdge.setDestination(srcObjNode); + delegatingEdge.setSource(dstObjNode); + + srcObjNode.addInEdge(delegatingEdge); + dstObjNode.addOutEdge(delegatingEdge); + } + + /************************************************************* + * [* private ] + /************************************************************* + * [ search ] + /************************************************************* + * Collecting nodes in the "nodes" parameter for each transfer method has nodes in the common area. + * @param nodes + * @param curObjNode + * @param delegatingObjNode + * @param selectedOption + */ + private void collectCommonTransferNodes(List nodes, ObjectNode curObjNode, final ObjectNode delegatingObjNode){ + if( !hasChildrenNode(curObjNode)) return; + + for(Edge e : curObjNode.getOutEdges()) { + ObjectNode foundNode = (ObjectNode)e.getDestination(); + + if( foundNode.equals(delegatingObjNode)) continue; + + nodes.add(foundNode); + collectCommonTransferNodes(nodes, foundNode, delegatingObjNode); + } + } + + /************************************************************* + * Collecting nodes in the "nodes" parameter for node of the area of PUSH-style transfer method. + * @param result in "nodes" parameter. + * @param curObjNode + */ + private void collectParentNodesInPushTransfer(List nodes, ObjectNode curObjNode, final ObjectNode parentDelegatingNode) { + if( isRootNode(curObjNode) ) return; + if( isInEdgesConversingToNode(curObjNode) ) return; + + ObjectNode parentObjNode = (ObjectNode)curObjNode.getInEdge(0).getSource(); + if(parentObjNode == null) return; + + if( !parentDelegatingNode.equals(parentObjNode) ) + nodes.add(parentObjNode); + + int inEdgeCallOrder = parentObjNode.getOutEdgeCallOrder(curObjNode.getInEdge(0)); + for(Edge edge : parentObjNode.getOutEdges()) { + if( !(edge instanceof CallEdge)) continue; + + int callOrder = parentObjNode.getOutEdgeCallOrder((CallEdge)edge); + if(inEdgeCallOrder < callOrder) collectChildNodesInPushTransfer(nodes, (CallEdge)edge); + } + + collectParentNodesInPushTransfer(nodes, parentObjNode, parentDelegatingNode); + } + + /************************************************************* + * + * @param node + */ + private void collectChildNodesInPushTransfer(List nodes, CallEdge callEdge) { + ObjectNode dstObjNode = (ObjectNode)callEdge.getDestination(); + if(dstObjNode == null) return; + + nodes.add(dstObjNode); + + if(!hasChildrenNode(dstObjNode)) return; + + for(Edge e : dstObjNode.getOutEdges()) { + CallEdge edge = (CallEdge)e; + if(edge == null) continue; + + ObjectNode foundNode = (ObjectNode)e.getDestination(); + if(foundNode == null) continue; + if(nodes.contains(foundNode))continue; + + collectChildNodesInPushTransfer(nodes, edge); + } + } + + /************************************************************* + * + * @param node + */ + private boolean isRootNode(final ObjectNode node) { + return node.getInEdges().isEmpty(); + } + + /************************************************************* + * + * @param node + */ + private boolean hasChildrenNode(final ObjectNode node) { + if(node.getOutEdges().size() < 1) return false; + return true; + } + + /************************************************************* + * + * @param node + */ + private boolean isInEdgesConversingToNode(final ObjectNode node) { + return ( 1 < node.getInEdges().size() ); } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java index 23012bf..0ebaaa2 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ControlFlowGraph.java @@ -1,8 +1,15 @@ package models.controlFlowModel; import models.Edge; +import models.algebra.Expression; +import models.algebra.Term; +import models.algebra.Variable; +import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.ChannelMember; import models.dataFlowModel.DataFlowEdge; import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.DataTransferChannelGenerator; +import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.PushPullAttribute; import models.dataFlowModel.PushPullValue; import models.dataFlowModel.ResourceNode; @@ -12,7 +19,7 @@ private CallGraph pushCallGraph; private CallGraph pullCallGraph; - public ControlFlowGraph(DataFlowGraph dataFlowGraph) { + public ControlFlowGraph(DataFlowGraph dataFlowGraph, DataTransferModel model) { this.dataFlowGraph = dataFlowGraph; this.pushCallGraph = new CallGraph(); this.pullCallGraph = new CallGraph(); @@ -22,10 +29,32 @@ ResourceNode dstNode = (ResourceNode) e.getDestination(); if (pushPull.getOptions().get(0) == PushPullValue.PUSH) { // same direction as the data flow - pushCallGraph.addEdge(srcNode, dstNode); + pushCallGraph.addEdge(srcNode, dstNode, PushPullValue.PUSH); } else { // reverse direction to the data flow - pullCallGraph.addEdge(dstNode, srcNode); + pullCallGraph.addEdge(dstNode, srcNode, PushPullValue.PULL); + } + } + for (ChannelGenerator ch: model.getIOChannelGenerators()) { + DataTransferChannelGenerator cio = (DataTransferChannelGenerator) ch; + EntryPointObjectNode srcNode = new EntryPointObjectNode(cio); + for (ChannelMember cm: cio.getChannelMembers()) { + if (srcNode.getName() == null) { + Expression exp = cm.getStateTransition().getMessageExpression(); + if (exp instanceof Term) { + srcNode.setName(((Term) exp).getSymbol().getName()); + } else if (exp instanceof Variable) { + srcNode.setName(((Variable) exp).getName()); + } + } + ResourceNode dstResNode = dataFlowGraph.getResouceNode(cm.getIdentifierTemplate()); + StatefulObjectNode dstNode = pushCallGraph.getStatefulObjectNode(dstResNode); + if (dstNode == null) { + pushCallGraph.addNode(dstResNode); + dstNode = pushCallGraph.getStatefulObjectNode(dstResNode); + } + // from an I/O channel to a resource + pushCallGraph.insertEdge(srcNode, dstNode, PushPullValue.PUSH, 0); } } } @@ -40,7 +69,7 @@ ResourceNode srcNode = (ResourceNode) e.getSource(); ResourceNode dstNode = (ResourceNode) e.getDestination(); // same direction as the data flow - pushCallGraph.addEdge(srcNode, dstNode); + pushCallGraph.addEdge(srcNode, dstNode, PushPullValue.PUSH); } } else { // pull-first @@ -51,11 +80,11 @@ if (pushPull.getOptions().contains(PushPullValue.PULL)) { // Pull style is selectable // reverse direction to the data flow - pullCallGraph.addEdge(dstNode, srcNode); + pullCallGraph.addEdge(dstNode, srcNode, PushPullValue.PULL); } else { // Pull style is not selectable // same direction as the data flow - pushCallGraph.addEdge(srcNode, dstNode); + pushCallGraph.addEdge(srcNode, dstNode, PushPullValue.PUSH); } } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/EntryPointObjectNode.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/EntryPointObjectNode.java new file mode 100644 index 0000000..f200312 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/EntryPointObjectNode.java @@ -0,0 +1,40 @@ +package models.controlFlowModel; + +import models.dataFlowModel.DataTransferChannelGenerator; + +/************************************************************* + * An object is mapped to I/O channel. + * ToDo: Fecthing name from in Data-Flow-Graph + */ +public class EntryPointObjectNode extends ObjectNode { + DataTransferChannelGenerator ioChannelGenerator = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public EntryPointObjectNode(DataTransferChannelGenerator ioChannelGenerator) { + super(null); + this.ioChannelGenerator = ioChannelGenerator; + } + + public EntryPointObjectNode(String name, DataTransferChannelGenerator ioChannelGenerator) { + super(name); + this.ioChannelGenerator = ioChannelGenerator; + } + + /************************************************************* + * [ *public ] + /************************************************************* + * + */ + public DataTransferChannelGenerator getIoChannelGenerator() { + return ioChannelGenerator; + } + + public void setIoChannelGenerator(DataTransferChannelGenerator ioChannelGenerator) { + this.ioChannelGenerator = ioChannelGenerator; + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNode.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNode.java index 3fa5ca6..53d7459 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNode.java +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNode.java @@ -6,14 +6,28 @@ import models.Edge; import models.Node; -public class ObjectNode extends Node { - private String name; +/************************************************************* +* +*/ +public class ObjectNode extends Node{ + protected String name = ""; + /************************************************************* + * [ *constructor] + /************************************************************* + */ public ObjectNode(String name) { inEdges = new ArrayList<>(); outEdges = new ArrayList<>(); + + this.name = name; } + /************************************************************* + * [ *public ] + /************************************************************* + * + */ public String getName() { return name; } @@ -21,20 +35,56 @@ public void setName(String name) { this.name = name; } + + public CallEdge getInEdge(int i) { + return (CallEdge) ((List) inEdges).get(i); + } public CallEdge getOutEdge(int i) { return (CallEdge) ((List) outEdges).get(i); } + + public CallEdge findEdgeInInEdges(final CallEdge edge) { + for(Edge e : inEdges) { + if( e instanceof CallEdge) return (CallEdge)e; + } + return null; + } public void insertOutEdge(CallEdge edge, int n) { ((List) outEdges).add(n, edge); } + public CallEdge findEdgeInOutEdges(final CallEdge edge) { + for(Edge e : outEdges) { + if( e instanceof CallEdge) return (CallEdge)e; + } + return null; + } + public int getChildrenNum() { return outEdges.size(); } + + public int getOutEdgeCallOrder(final CallEdge callEdge) { + for(int i = 0; i < outEdges.size(); i++) { + if(callEdge.equals(getOutEdge(i))) return i; + } + return -1; + } public ObjectNode getChildren(int i) { return (ObjectNode) ((List) outEdges).get(i).getDestination(); } + + /************************************************************* + * + */ + public void sortOutEdgesByCallOrder(final int curOrder, final int callOrder) { + ArrayList edges = ((ArrayList)outEdges); + Edge edge = ((List)outEdges).get(curOrder); + + edges.remove(curOrder); + edges.add(callOrder-1, edge); + } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNodeAttribute.java b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNodeAttribute.java new file mode 100644 index 0000000..0a5efa9 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/controlFlowModel/ObjectNodeAttribute.java @@ -0,0 +1,112 @@ +package models.controlFlowModel; + +import models.NodeAttribute; + +/************************************************************* + * + * @author k-fujii + * + */ +public class ObjectNodeAttribute extends NodeAttribute{ + private ObjectNode objectNode = null; + private String shapeStyle = ""; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public ObjectNodeAttribute(final ObjectNode objectNode) { + this.objectNode = objectNode; + this.objectNode.setAttribute(this); + + // Setting a shape style of cell + if(objectNode instanceof StatefulObjectNode) { + shapeStyle = "shape=ellipse;perimeter=ellipsePerimeter;"; + } + else if(objectNode instanceof EntryPointObjectNode) { + shapeStyle = "shape=rectangle;perimeter=rectanglePerimeter;"; + } + else { + shapeStyle = "shape=hexagon;perimeter=hexagonPerimeter;"; + } + + // Setting a name of cell + if(objectNode.name != null) return; + if(objectNode.name.isEmpty()) return; + + if( objectNode instanceof StatefulObjectNode ) { + objectNode.name = objectNode.getName(); + } + else if(objectNode instanceof EntryPointObjectNode){ + objectNode.name = "entryPoint"; + } + } + + /************************************************************* + * [ *public ] + /************************************************************* + * [ getter ] + /************************************************************* + * + * @return + */ + public ObjectNode getObjectNode() { + return objectNode; + } + + /************************************************************* + * + */ + public String getDefaultStyle() { + String style = ";"; + + return objectNode instanceof StatefulObjectNode + ? shapeStyle + style + : shapeStyle + style; + } + + /************************************************************* + * + */ + public String getEnableStyle() { + String style = "fillColor=#7fffd4;"; + style += "strokeColor=#66cdaa;"; + style += "strokeWidth=2;"; + + return objectNode instanceof StatefulObjectNode + ? shapeStyle + style + : shapeStyle + style; + } + + /************************************************************* + * + */ + public String getDisableStyle() { + String style = "fillColor=#999999"; + + return objectNode instanceof StatefulObjectNode + ? shapeStyle + style + : shapeStyle + style; + } + + /************************************************************* + * + */ + public String getDelegatingStyle() { + String style = "strokeWidth=4;"; + style += "strokeColor=#4169e;"; + + return shapeStyle + style; + } + + /************************************************************* + * showing label of mxCell + */ + @Override + public String toString() { + return objectNode instanceof StatefulObjectNode + ? ((StatefulObjectNode) objectNode).getResource().getIdentifierTemplate().getResourceName() + : objectNode.getName(); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNodeAttribute.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNodeAttribute.java new file mode 100644 index 0000000..d03c305 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/ResourceNodeAttribute.java @@ -0,0 +1,63 @@ +package models.dataFlowModel; + +import models.NodeAttribute; + +/************************************************************* + * + * @author k-fujii + * + */ +public class ResourceNodeAttribute extends NodeAttribute { + private ResourceNode resourceNode = null; + + /************************************************************* + * [ *constructor ] + /************************************************************* + * + */ + public ResourceNodeAttribute(ResourceNode resNode) { + this.resourceNode = resNode; + this.resourceNode.setAttribute(this); + } + + /************************************************************* + * [ *public ] + /************************************************************* + * [ getter ] + /************************************************************* + * + * @return + */ + public ResourceNode getResourceNode() { + return resourceNode; + } + + /************************************************************* + * + */ + public String getResourceName() { + return resourceNode.getIdentifierTemplate().getResourceName(); + } + + /************************************************************* + * + * @return + */ + public String getDefaultStyle() { + String style =""; + style += "shape=ellipse;"; + style += "perimeter=ellipsePerimeter"; + + return style; + } + + + /************************************************************* + * + * @return + */ + @Override + public String toString() { + return resourceNode.getIdentifierTemplate().getResourceName(); + } +}