diff --git a/AlgebraicDataflowArchitectureModel/models/SimpleUI.model b/AlgebraicDataflowArchitectureModel/models/SimpleUI.model index 584d8e3..3b0d023 100644 --- a/AlgebraicDataflowArchitectureModel/models/SimpleUI.model +++ b/AlgebraicDataflowArchitectureModel/models/SimpleUI.model @@ -1,5 +1,5 @@ native channel ScreenUpdate { - in screen(curSc: Json, update(nextSc)) = nextSc + in screen(curSc: Json, update(curSc, nextSc)) = nextSc } native channel SetVisible(wid: Str) { @@ -26,6 +26,6 @@ out screen.widgets(widgets: Map, addLabel(wid: Str, text: Str)) = insert(widgets, wid, {"type": "label", "text": text, "state": 0}) } -channel AddInputText { - out screen.widgets(widgets: Map, addInputText(wid: Str)) = insert(widgets, wid, {"type": "inputText", "state": 0}) -} +channel AddTextInput { + out screen.widgets(widgets: Map, addTextInput(wid: Str)) = insert(widgets, wid, {"type": "textInput", "text": "", "state": 0}) +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java b/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java deleted file mode 100644 index a8b4281..0000000 --- a/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java +++ /dev/null @@ -1,201 +0,0 @@ -package application; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.swing.JFrame; - -import application.editor.SimulationLayout; -import com.mxgraph.model.mxCell; -import com.mxgraph.model.mxGeometry; -import com.mxgraph.model.mxGraphModel; -import com.mxgraph.swing.mxGraphComponent; -import com.mxgraph.swing.handler.mxRubberband; -import com.mxgraph.util.mxEvent; -import com.mxgraph.util.mxEventObject; -import com.mxgraph.util.mxPoint; -import com.mxgraph.util.mxEventSource.mxIEventListener; -import com.mxgraph.view.mxGraph; - -import algorithms.TypeInference; -import application.actions.SimulateAction; -import application.editor.DataTransferModelingCellEditor; -import application.editor.Editor; -import application.editor.InputEventCellEditor; -import application.layouts.DAGLayout; -import generators.JavaCodeGenerator; -import models.Edge; -import models.EdgeAttribute; -import models.algebra.Expression; -import models.algebra.InvalidMessage; -import models.algebra.ParameterizedIdentifierIsFutureWork; -import models.algebra.UnificationFailed; -import models.algebra.ValueUndefined; -import models.dataConstraintModel.Channel; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.ResourcePath; -import models.dataConstraintModel.Selector; -import models.dataFlowModel.ChannelNode; -import models.dataFlowModel.DataFlowEdge; -import models.dataFlowModel.DataFlowGraph; -import models.dataFlowModel.DataTransferChannel; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; -import models.dataFlowModel.ResourceNode; -import parser.Parser; -import parser.ParserDTRAM; -import parser.exceptions.ExpectedColon; -import parser.exceptions.ExpectedRightBracket; -import parser.exceptions.WrongJsonExpression; -import parser.Parser.TokenStream; -import simulator.Event; -import simulator.Resource; -import simulator.ResourceIdentifier; -import simulator.Simulator; - -public class SimulatorWindow extends JFrame{ - - private static final long serialVersionUID = -2425820512017088254L; - public static final String title = "Simulation Tool"; - - final int PORT_DIAMETER = 8; - final int PORT_RADIUS = PORT_DIAMETER / 2; - - private Editor editor = null; - private mxGraph graph = null; - private mxGraphComponent graphComponent = null; - private UIWindow uiWindow; - - private Simulator simulator = null; - - private boolean bReflectingArchitectureModel = false; - private double x = 20; - private double y = 20; - - public SimulatorWindow(Editor editor) { - setTitle(title); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - this.graph = new mxGraph() { - public boolean isPort(Object cell) { - mxGeometry geo = getCellGeometry(cell); - - return (geo != null) ? geo.isRelative() : false; - } - - public boolean isCellFoldable(Object cell, boolean collapse) { - return false; - } - }; - - this.graphComponent = new mxGraphComponent(graph); - this.editor = editor; - - 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); - graph.setCellsDisconnectable(true); - - setTitle(title); - setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - setSize(870,640); - setVisible(true); - - DataTransferModel model = this.editor.getModel(); - TypeInference.infer(model); - simulator = new Simulator(model); - SimulationLayout layout = new SimulationLayout(simulator.getCurState()); - layout.constructSimulateGraph(graph, simulator); - graphComponent.setCellEditor(new InputEventCellEditor(graphComponent, simulator, this.editor, graph)); - - uiWindow = new UIWindow(simulator); - } - - public mxGraph constructSimulateGraph(Set simulateRes, DataTransferModel model, DataFlowGraph dataFlowGraph) { - bReflectingArchitectureModel = true; - ((mxGraphModel) graph.getModel()).clear(); - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - - try { - Map resources = new HashMap<>(); - - // create resource vertices - for (Resource resNode: simulateRes) { - int w = 80; - int h = 30; - ResourcePath res = resNode.getResourceIdentifier(); - Object resource = graph.insertVertex(parent, null, - res.toString(), x, y, w, h, - "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex - resources.put(resNode, resource); - createChildSimulateResourceVerticies(resource, resNode, resources, w, h); - x+=80; - } - - } finally { - graph.getModel().endUpdate(); - } - - bReflectingArchitectureModel = false; - return graph; - } - - - public void createChildSimulateResourceVerticies(Object resource, Resource resNode, Map resources, int w, int h) { //sample - - if(resNode.getChildren() != null) { - for (Resource childNode: resNode.getChildren()) { - ResourcePath childRes = childNode.getResourceIdentifier(); - Object childResource = graph.insertVertex(resource, null, - childRes.toString(), 0, 0, w/2, h/2, - "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex - resources.put(childNode, childResource); - createChildSimulateResourceVerticies(childResource, childNode, resources, w, h); - } - } - if (resNode.getChildren() == null || resNode.getChildren().size() == 0) { - Object state = graph.insertVertex(resource, null, - resNode.getState().getValue().toString(), 0.5, 0.5, 0.25, 0.25, "opacity=0;verticalAlign=down;", true); // insert a state label as a vertex - } - } - - public mxGraphComponent getGraphComponent() { - return graphComponent; - } - - public Editor getEditor() { - return editor; - } - - public void setEditor(Editor editor) { - this.editor = editor; - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/application/UIWindow.java b/AlgebraicDataflowArchitectureModel/src/application/UIWindow.java deleted file mode 100644 index 97ca1e3..0000000 --- a/AlgebraicDataflowArchitectureModel/src/application/UIWindow.java +++ /dev/null @@ -1,26 +0,0 @@ -package application; - -import javax.swing.JFrame; -import javax.swing.JPanel; - -import simulator.Simulator; -import simulator.interfaces.swing.SwingPresenter; - -public class UIWindow extends JFrame { - - private static final long serialVersionUID = 1770206525826167136L; - private SwingPresenter presenter; - private Simulator simulator; - private JPanel mainPanel; - - public UIWindow(Simulator simulator) { - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - this.simulator = simulator; - mainPanel = new JPanel(); - presenter = new SwingPresenter(mainPanel, simulator); - this.add(mainPanel); - - setSize(870,640); - setVisible(true); - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/SimulateAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/SimulateAction.java index 9f0e5a2..26a1779 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/actions/SimulateAction.java +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/SimulateAction.java @@ -10,8 +10,8 @@ import javax.swing.filechooser.FileNameExtensionFilter; import application.ApplicationWindow; -import application.SimulatorWindow; import application.editor.Editor; +import application.simulator.SimulatorWindow; import models.dataFlowModel.DataTransferChannel; public class SimulateAction extends AbstractSystemAction { diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/InputEventCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/InputEventCellEditor.java deleted file mode 100644 index ea39086..0000000 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/InputEventCellEditor.java +++ /dev/null @@ -1,343 +0,0 @@ -package application.editor; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Rectangle; -import java.util.EventObject; -import java.util.HashMap; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.swing.BorderFactory; -import javax.swing.JComboBox; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextArea; -import javax.swing.JTextField; - -import com.mxgraph.model.mxCell; -import com.mxgraph.model.mxGraphModel; -import com.mxgraph.model.mxIGraphModel; -import com.mxgraph.swing.mxGraphComponent; -import com.mxgraph.swing.view.mxICellEditor; -import com.mxgraph.util.mxConstants; -import com.mxgraph.util.mxUtils; -import com.mxgraph.view.mxCellState; -import com.mxgraph.view.mxGraph; -import com.mxgraph.view.mxGraphView; - -import application.SimulatorWindow; -import application.layouts.DAGLayout; -import models.algebra.Expression; -import models.algebra.InvalidMessage; -import models.algebra.ParameterizedIdentifierIsFutureWork; -import models.algebra.Term; -import models.algebra.UnificationFailed; -import models.algebra.ValueUndefined; -import models.algebra.Variable; -import models.dataConstraintModel.Channel; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.ResourceHierarchy; -import models.dataConstraintModel.ResourcePath; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataFlowGraph; -import models.dataFlowModel.DataTransferChannel; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.PushPullValue; -import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; -import models.visualModel.FormulaChannel; -import parser.Parser; -import parser.Parser.TokenStream; -import parser.exceptions.ExpectedColon; -import parser.exceptions.ExpectedRightBracket; -import parser.exceptions.WrongJsonExpression; -import simulator.ChannelState; -import simulator.Resource; -import simulator.ResourceIdentifier; -import simulator.Simulator; -import simulator.Event; -import simulator.SystemState; - -public class InputEventCellEditor implements mxICellEditor { - public int DEFAULT_MIN_WIDTH = 70; - public int DEFAULT_MIN_HEIGHT = 30; - public double DEFAULT_MINIMUM_EDITOR_SCALE = 1; - private double x = 20; - private double y = 20; - - protected double minimumEditorScale = DEFAULT_MINIMUM_EDITOR_SCALE; - protected int minimumWidth = DEFAULT_MIN_WIDTH; - protected int minimumHeight = DEFAULT_MIN_HEIGHT; - - private Object editingCell; - private EventObject trigger; - private JComboBox comboBox; - private mxGraphComponent graphComponent; - private Simulator simulator; - private JComboBox pulldownMenu; - private Editor editor; - private boolean bReflectingArchitectureModel = false; - private mxGraph graph; - - public InputEventCellEditor(mxGraphComponent graphComponent, Simulator simulator, Editor editor, mxGraph graph) { - this.graphComponent = graphComponent; - this.simulator = simulator; - this.editor = editor; - this.graph = graph; - } - - @Override - public Object getEditingCell() { - return editingCell; - } - - @Override - public void startEditing(Object cell, EventObject evt) { - if (editingCell != null) { - stopEditing(true); - } - if (!graphComponent.getGraph().getModel().isEdge(cell)) { - - Resource res = simulator.getCurState().getResource((String) ((mxCell) cell).getValue()); - ResourceIdentifier resId = res.getResourceIdentifier();//resource - ArrayList eventChs = new ArrayList<>();//iOchannelList - ArrayList messages = new ArrayList<>();//ADLmessage - ArrayList eventMessages = new ArrayList<>();//messageList - ResourcePath eventResPath = null; - - for(Channel ch : simulator.getModel().getInputChannels()) {//all channel - if(((DataTransferChannel)ch).getInputResources().size()== 0) {//ioch Or normalch - for(ChannelMember out: ((DataTransferChannel)ch).getOutputChannelMembers()) { - ResourcePath resPath = out.getResource(); - if(resId.isInstanceOf(resPath)) {//account.uid == acounts.123 - eventResPath = resPath; - eventChs.add(((DataTransferChannel)ch)); - String message = null; - Expression mesExp = out.getStateTransition().getMessageExpression();//sync(a,b) - eventMessages.add(mesExp); - if(mesExp instanceof Term) { - message = ((Term) mesExp).getSymbol().toString();//sync - }else if(mesExp instanceof Variable) { - message = ((Variable) mesExp).getName();//x,y,z.. - } - messages.add(message);//pulldown - - } - } - } - } - - if(messages.isEmpty()) { - return; - } - String[] eventList = messages.toArray(new String[messages.size()]); - JComboBox event = new JComboBox(eventList); - - JPanel eventChoice = new JPanel(); - eventChoice.add(event);//FirstEventChoice - - int ret = JOptionPane.showConfirmDialog(null, eventChoice, "Event Choice", JOptionPane.OK_CANCEL_OPTION); - if (ret == JOptionPane.OK_OPTION) { - - JPanel inputEvent = new JPanel(); - int i , eventNum; - i = eventNum = 0; - - for(String eventString : eventList) { - if(eventString.equals(event.getSelectedItem().toString())) { - eventNum = i; - } - i++; - } - - JTextArea textArea = new JTextArea(eventMessages.get(eventNum).toString(), 10, 30);//EventInput - inputEvent.add(textArea); - - int approve = JOptionPane.showConfirmDialog(null, inputEvent, "Event Code", JOptionPane.OK_CANCEL_OPTION); - if (approve == JOptionPane.OK_OPTION) { - try { - - TokenStream stream = new Parser.TokenStream(); - Parser parser = new Parser(stream); - stream.addLine(textArea.getText()); - Expression eventMessage = parser.parseTerm(stream,simulator.getModel()); - - Event newEvent = new Event(eventChs.get(eventNum), eventMessage, eventResPath, simulator.getCurState().getResource(resId)); - simulator.transition(newEvent); - - SimulationLayout layout = new SimulationLayout(simulator.getCurState()); - layout.constructSimulateGraph(graph, simulator); - - graphComponent.setCellEditor(new InputEventCellEditor(graphComponent, simulator, this.editor, graph)); - - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork - | InvalidMessage | UnificationFailed | ValueUndefined | ExpectedRightBracket | WrongJsonExpression | ExpectedColon e) { - e.printStackTrace(); - } - } - } - //resource - return; - } - - mxCellState state = graphComponent.getGraph().getView().getState(cell); - if (state != null && state.getLabel() != null && !state.getLabel().equals("")) { - editingCell = cell; - trigger = evt; - - double scale = Math.max(minimumEditorScale, graphComponent.getGraph().getView().getScale()); - Object value = graphComponent.getGraph().getModel().getValue(cell); - if (value != null && value instanceof PushPullAttribute) { - PushPullAttribute attr = (PushPullAttribute) value; - comboBox = new JComboBox<>(attr.getOptionStrings()); - comboBox.setBorder(BorderFactory.createEmptyBorder()); - comboBox.setOpaque(false); - comboBox.setBounds(getEditorBounds(state, scale)); - comboBox.setVisible(true); - graphComponent.getGraphControl().add(comboBox, 0); - comboBox.updateUI(); - } - } - } - - private mxGraph constructNextSimulateGraph(Set simulateRes, DataTransferModel model,DataFlowGraph dataFlowGraph, mxGraph nextGraph) { - bReflectingArchitectureModel = true; - ((mxGraphModel) nextGraph.getModel()).clear(); - Object parent = nextGraph.getDefaultParent(); - nextGraph.getModel().beginUpdate(); - - try { - Map resources = new HashMap<>(); - - // create resource vertices - for (Resource resNode: simulateRes) { - int w = 400; - int h = 150; - ResourcePath res = resNode.getResourceIdentifier(); - Object resource = nextGraph.insertVertex(parent, null, - res.toString(), x, y, w, h, - "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex - resources.put(resNode, resource); - - createNextChildSimulateResourceVerticies(resource, resNode, resources, w, h); - x+=400; - } - - } finally { - nextGraph.getModel().endUpdate(); - } - - bReflectingArchitectureModel = false; - return nextGraph; - } - - private void createNextChildSimulateResourceVerticies(Object resource, Resource resNode, Map resources, int w, int h) { //sample - - if(resNode.getChildren() != null) { - for (Resource childNode: resNode.getChildren()) { - int i = 1; - ResourcePath childRes = childNode.getResourceIdentifier(); - Object childResource = graph.insertVertex(resource, null, - childRes.toString(), x/i, 0, w/(i+1), h/(i+2), - "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex - resources.put(childNode, childResource); - i++; - createNextChildSimulateResourceVerticies(childResource, childNode, resources, w, h); - } - } - if (resNode.getChildren() == null || resNode.getChildren().size() == 0) { - Object state = graph.insertVertex(resource, null, - resNode.getState().getValue().toString(), 0.5, 0.5, 0.25, 0.25, "opacity=0;verticalAlign=down;", true); // insert a state label as a vertex - } - } - - @Override - public void stopEditing(boolean cancel) { - if (editingCell != null) { - comboBox.transferFocusUpCycle(); - Object cell = editingCell; - editingCell = null; - if (!cancel) { - EventObject trig = trigger; - trigger = null; - Object value = graphComponent.getGraph().getModel().getValue(cell); - if (value != null && value instanceof PushPullAttribute) { - PushPullAttribute attr = (PushPullAttribute) value; - List options = attr.getOptions(); - PushPullValue selected = null; - for (PushPullValue option: options) { - if (option.toString().equals(getCurrentValue())) { - selected = option; - break; - } - } - if (selected != null) { - options.remove(selected); - options.add(0, selected); - } - graphComponent.labelChanged(cell, attr, trig); - } - } else { - mxCellState state = graphComponent.getGraph().getView().getState(cell); - graphComponent.redraw(state); - } - - if (comboBox.getParent() != null) { - comboBox.setVisible(false); - comboBox.getParent().remove(comboBox); - } - - graphComponent.requestFocusInWindow(); - } - } - - public String getCurrentValue() { - return (String) comboBox.getSelectedItem(); - } - - /** - * Returns the bounds to be used for the editor. - */ - public Rectangle getEditorBounds(mxCellState state, double scale) { - mxIGraphModel model = state.getView().getGraph().getModel(); - Rectangle bounds = null; - - bounds = state.getLabelBounds().getRectangle(); - bounds.height += 10; - - // Applies the horizontal and vertical label positions - if (model.isVertex(state.getCell())) { - String horizontal = mxUtils.getString(state.getStyle(), mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER); - - if (horizontal.equals(mxConstants.ALIGN_LEFT)) { - bounds.x -= state.getWidth(); - } else if (horizontal.equals(mxConstants.ALIGN_RIGHT)) { - bounds.x += state.getWidth(); - } - - String vertical = mxUtils.getString(state.getStyle(), - mxConstants.STYLE_VERTICAL_LABEL_POSITION, - mxConstants.ALIGN_MIDDLE); - - if (vertical.equals(mxConstants.ALIGN_TOP)) { - bounds.y -= state.getHeight(); - } else if (vertical.equals(mxConstants.ALIGN_BOTTOM)) { - bounds.y += state.getHeight(); - } - } - - bounds.setSize( - (int) Math.max(bounds.getWidth(), - Math.round(minimumWidth * scale)), - (int) Math.max(bounds.getHeight(), - Math.round(minimumHeight * scale))); - - return bounds; - } - -} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/SimulationLayout.java b/AlgebraicDataflowArchitectureModel/src/application/editor/SimulationLayout.java deleted file mode 100644 index 99bbdff..0000000 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/SimulationLayout.java +++ /dev/null @@ -1,157 +0,0 @@ -package application.editor; - -import com.mxgraph.model.mxGraphModel; -import com.mxgraph.view.mxGraph; -import models.dataConstraintModel.ResourcePath; -import simulator.Resource; -import simulator.ResourceIdentifier; -import simulator.Simulator; -import simulator.SystemState; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class SimulationLayout { - // Hold the division level for each resource - HashMap divisionLevelMap = new HashMap<>(); - // Hold the scaling factor for each resource - HashMap resourceScaleMap = new HashMap<>(); - int maxDivisionLevel = 1; - public final double BASE_WIDTH = 400; - public final double BASE_HEIGHT = BASE_WIDTH/2; - public final double MARGIN_SCALE = 0.92; - SystemState systemState; - public SimulationLayout(SystemState systemState){ - this.systemState = systemState; - // Calculate the division level for each resource - for (Resource res:systemState.getRootResources()) { - setDivisionLevel(divisionLevelMap, res.getResourceIdentifier(), 1); - } - // Calculate the scaling factor for each resource - for (ResourceIdentifier res:divisionLevelMap.keySet()) { - double scale = (double) maxDivisionLevel / divisionLevelMap.get(res); - resourceScaleMap.put(res, scale); - } - } - public double getScale(ResourceIdentifier resource){ - return resourceScaleMap.get(resource); - } - public double getDivision(ResourceIdentifier resource){ - return divisionLevelMap.get(resource); - } - - public int getMaxDivisionLevel() { - return maxDivisionLevel; - } - - public boolean isExistResource(ResourceIdentifier resourceIdentifier){ - return divisionLevelMap.containsKey(resourceIdentifier); - } - private void setDivisionLevel(HashMap resourceSet, ResourceIdentifier resource, int childCount){ - int divisionLevel; - if(resourceSet.get(resource.getParent()) == null){ - divisionLevel = 1; - }else{ - divisionLevel = resourceSet.get(resource.getParent()) * childCount; - } - if (divisionLevel > maxDivisionLevel)maxDivisionLevel = divisionLevel; - resourceSet.put(resource,divisionLevel); - - Collection identifiers = systemState.getResource(resource).getChildren(); - if (identifiers != null) { - for (Resource child:identifiers) { - setDivisionLevel(resourceSet, child.getResourceIdentifier(), identifiers.size()); - } - } - } - /** - * - * Draw an object corresponding to the target resource on the mxGraph. - * @param graph The mxGraph for drawing. - * @param parent The parent object of the target resource. - * @param resourceIdentifier The ID of the target resource. - * @param index The index. - * @param length The number of sibling resources of the target resource. - * @return The drawing object of the target resource. - */ - - private Object setLayout(mxGraph graph,Object parent, ResourceIdentifier resourceIdentifier,double index, double length){ - double width, height, x, y; - double parentWidth = graph.getCellGeometry(parent).getWidth(); - double parentHeight = graph.getCellGeometry(parent).getHeight(); - - width = parentWidth / length * MARGIN_SCALE; - height = width/2; - x = parentWidth * (index - 1)/length + (parentWidth/length)*(1-MARGIN_SCALE)/2; - - // Process to avoid hiding the parent's resource name - if ((int)length == 1) { - y = 20; - height -=20; - } else { - y = parentHeight/2 - height/2; - } - - Object result = graph.insertVertex(parent, null, - resourceIdentifier.toString(), x, y, width, height, - "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); - System.out.println(result); - return result; - } - - public mxGraph constructSimulateGraph(mxGraph graph, Simulator simulator){ - ((mxGraphModel) graph.getModel()).clear(); - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - - try { - Map resources = new HashMap<>(); - int i = 0; - // create resource vertices - for (Resource resNode: simulator.getCurState().getRootResources()) { - double scale = this.getScale(resNode.getResourceIdentifier()); - double maxDiv = this.getMaxDivisionLevel(); - double w = this.BASE_WIDTH * scale /maxDiv; - double h = this.BASE_HEIGHT * scale /maxDiv; - int childCount = simulator.getCurState().getRootResources().size(); - double x = w * (1 + i - childCount / 2.0); - double y = 20 ; - ResourcePath res = resNode.getResourceIdentifier(); - Object resource = graph.insertVertex(parent, null, - res.toString(), x, y, w, h, - "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex - resources.put(resNode, resource); - i++; - createNextChildSimulateResourceVerticies(graph, resource, resNode, resources); - - } - - } finally { - graph.getModel().endUpdate(); - } - - return graph; - } - private void createNextChildSimulateResourceVerticies(mxGraph graph, Object parent, Resource resNode, Map resources) { //sample - Collection children = resNode.getChildren(); - if (children != null) { - //List children = resNode.getChildren(); - double i = 1; - double childCount = children.size(); - for (Resource childNode: children) { - Object childResource = setLayout(graph, parent, childNode.getResourceIdentifier(), i, childCount); - resources.put(childNode, childResource); - i++; - createNextChildSimulateResourceVerticies(graph, childResource, childNode, resources); - - } - } - if (children == null || children.size() == 0) { - Object state = graph.insertVertex(parent, null, - resNode.getState().getValue().toString(), 0.5, 0.5, 0.25, 0.25, "opacity=0;verticalAlign=down;", true); // insert a state label as a vertex - } - } -} diff --git a/AlgebraicDataflowArchitectureModel/src/application/simulator/InputEventCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/simulator/InputEventCellEditor.java new file mode 100644 index 0000000..10e5565 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/simulator/InputEventCellEditor.java @@ -0,0 +1,343 @@ +package application.simulator; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Rectangle; +import java.util.EventObject; +import java.util.HashMap; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.swing.BorderFactory; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGraphModel; +import com.mxgraph.model.mxIGraphModel; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.swing.view.mxICellEditor; +import com.mxgraph.util.mxConstants; +import com.mxgraph.util.mxUtils; +import com.mxgraph.view.mxCellState; +import com.mxgraph.view.mxGraph; +import com.mxgraph.view.mxGraphView; + +import application.editor.Editor; +import application.layouts.DAGLayout; +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.Term; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.algebra.Variable; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourceHierarchy; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.visualModel.FormulaChannel; +import parser.Parser; +import parser.Parser.TokenStream; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.WrongJsonExpression; +import simulator.ChannelState; +import simulator.Resource; +import simulator.ResourceIdentifier; +import simulator.Simulator; +import simulator.Event; +import simulator.SystemState; + +public class InputEventCellEditor implements mxICellEditor { + public int DEFAULT_MIN_WIDTH = 70; + public int DEFAULT_MIN_HEIGHT = 30; + public double DEFAULT_MINIMUM_EDITOR_SCALE = 1; + private double x = 20; + private double y = 20; + + protected double minimumEditorScale = DEFAULT_MINIMUM_EDITOR_SCALE; + protected int minimumWidth = DEFAULT_MIN_WIDTH; + protected int minimumHeight = DEFAULT_MIN_HEIGHT; + + private Object editingCell; + private EventObject trigger; + private JComboBox comboBox; + private mxGraphComponent graphComponent; + private Simulator simulator; + private JComboBox pulldownMenu; + private Editor editor; + private boolean bReflectingArchitectureModel = false; + private mxGraph graph; + + public InputEventCellEditor(mxGraphComponent graphComponent, Simulator simulator, Editor editor, mxGraph graph) { + this.graphComponent = graphComponent; + this.simulator = simulator; + this.editor = editor; + this.graph = graph; + } + + @Override + public Object getEditingCell() { + return editingCell; + } + + @Override + public void startEditing(Object cell, EventObject evt) { + if (editingCell != null) { + stopEditing(true); + } + if (!graphComponent.getGraph().getModel().isEdge(cell)) { + + Resource res = simulator.getCurState().getResource((String) ((mxCell) cell).getValue()); + ResourceIdentifier resId = res.getResourceIdentifier();//resource + ArrayList eventChs = new ArrayList<>();//iOchannelList + ArrayList messages = new ArrayList<>();//ADLmessage + ArrayList eventMessages = new ArrayList<>();//messageList + ResourcePath eventResPath = null; + + for(Channel ch : simulator.getModel().getInputChannels()) {//all channel + if(((DataTransferChannel)ch).getInputResources().size()== 0) {//ioch Or normalch + for(ChannelMember out: ((DataTransferChannel)ch).getOutputChannelMembers()) { + ResourcePath resPath = out.getResource(); + if(resId.isInstanceOf(resPath)) {//account.uid == acounts.123 + eventResPath = resPath; + eventChs.add(((DataTransferChannel)ch)); + String message = null; + Expression mesExp = out.getStateTransition().getMessageExpression();//sync(a,b) + eventMessages.add(mesExp); + if(mesExp instanceof Term) { + message = ((Term) mesExp).getSymbol().toString();//sync + }else if(mesExp instanceof Variable) { + message = ((Variable) mesExp).getName();//x,y,z.. + } + messages.add(message);//pulldown + + } + } + } + } + + if(messages.isEmpty()) { + return; + } + String[] eventList = messages.toArray(new String[messages.size()]); + JComboBox event = new JComboBox(eventList); + + JPanel eventChoice = new JPanel(); + eventChoice.add(event);//FirstEventChoice + + int ret = JOptionPane.showConfirmDialog(null, eventChoice, "Event Choice", JOptionPane.OK_CANCEL_OPTION); + if (ret == JOptionPane.OK_OPTION) { + + JPanel inputEvent = new JPanel(); + int i , eventNum; + i = eventNum = 0; + + for(String eventString : eventList) { + if(eventString.equals(event.getSelectedItem().toString())) { + eventNum = i; + } + i++; + } + + JTextArea textArea = new JTextArea(eventMessages.get(eventNum).toString(), 10, 30);//EventInput + inputEvent.add(textArea); + + int approve = JOptionPane.showConfirmDialog(null, inputEvent, "Event Code", JOptionPane.OK_CANCEL_OPTION); + if (approve == JOptionPane.OK_OPTION) { + try { + + TokenStream stream = new Parser.TokenStream(); + Parser parser = new Parser(stream); + stream.addLine(textArea.getText()); + Expression eventMessage = parser.parseTerm(stream,simulator.getModel()); + + Event newEvent = new Event(eventChs.get(eventNum), eventMessage, eventResPath, simulator.getCurState().getResource(resId)); + simulator.transition(newEvent); + + SimulationLayout layout = new SimulationLayout(simulator.getCurState()); + layout.constructSimulateGraph(graph, simulator); + + graphComponent.setCellEditor(new InputEventCellEditor(graphComponent, simulator, this.editor, graph)); + + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined | ExpectedRightBracket | WrongJsonExpression | ExpectedColon e) { + e.printStackTrace(); + } + } + } + //resource + return; + } + + mxCellState state = graphComponent.getGraph().getView().getState(cell); + if (state != null && state.getLabel() != null && !state.getLabel().equals("")) { + editingCell = cell; + trigger = evt; + + double scale = Math.max(minimumEditorScale, graphComponent.getGraph().getView().getScale()); + Object value = graphComponent.getGraph().getModel().getValue(cell); + if (value != null && value instanceof PushPullAttribute) { + PushPullAttribute attr = (PushPullAttribute) value; + comboBox = new JComboBox<>(attr.getOptionStrings()); + comboBox.setBorder(BorderFactory.createEmptyBorder()); + comboBox.setOpaque(false); + comboBox.setBounds(getEditorBounds(state, scale)); + comboBox.setVisible(true); + graphComponent.getGraphControl().add(comboBox, 0); + comboBox.updateUI(); + } + } + } + + private mxGraph constructNextSimulateGraph(Set simulateRes, DataTransferModel model,DataFlowGraph dataFlowGraph, mxGraph nextGraph) { + bReflectingArchitectureModel = true; + ((mxGraphModel) nextGraph.getModel()).clear(); + Object parent = nextGraph.getDefaultParent(); + nextGraph.getModel().beginUpdate(); + + try { + Map resources = new HashMap<>(); + + // create resource vertices + for (Resource resNode: simulateRes) { + int w = 400; + int h = 150; + ResourcePath res = resNode.getResourceIdentifier(); + Object resource = nextGraph.insertVertex(parent, null, + res.toString(), x, y, w, h, + "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex + resources.put(resNode, resource); + + createNextChildSimulateResourceVerticies(resource, resNode, resources, w, h); + x+=400; + } + + } finally { + nextGraph.getModel().endUpdate(); + } + + bReflectingArchitectureModel = false; + return nextGraph; + } + + private void createNextChildSimulateResourceVerticies(Object resource, Resource resNode, Map resources, int w, int h) { //sample + + if(resNode.getChildren() != null) { + for (Resource childNode: resNode.getChildren()) { + int i = 1; + ResourcePath childRes = childNode.getResourceIdentifier(); + Object childResource = graph.insertVertex(resource, null, + childRes.toString(), x/i, 0, w/(i+1), h/(i+2), + "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex + resources.put(childNode, childResource); + i++; + createNextChildSimulateResourceVerticies(childResource, childNode, resources, w, h); + } + } + if (resNode.getChildren() == null || resNode.getChildren().size() == 0) { + Object state = graph.insertVertex(resource, null, + resNode.getState().getValue().toString(), 0.5, 0.5, 0.25, 0.25, "opacity=0;verticalAlign=down;", true); // insert a state label as a vertex + } + } + + @Override + public void stopEditing(boolean cancel) { + if (editingCell != null) { + comboBox.transferFocusUpCycle(); + Object cell = editingCell; + editingCell = null; + if (!cancel) { + EventObject trig = trigger; + trigger = null; + Object value = graphComponent.getGraph().getModel().getValue(cell); + if (value != null && value instanceof PushPullAttribute) { + PushPullAttribute attr = (PushPullAttribute) value; + List options = attr.getOptions(); + PushPullValue selected = null; + for (PushPullValue option: options) { + if (option.toString().equals(getCurrentValue())) { + selected = option; + break; + } + } + if (selected != null) { + options.remove(selected); + options.add(0, selected); + } + graphComponent.labelChanged(cell, attr, trig); + } + } else { + mxCellState state = graphComponent.getGraph().getView().getState(cell); + graphComponent.redraw(state); + } + + if (comboBox.getParent() != null) { + comboBox.setVisible(false); + comboBox.getParent().remove(comboBox); + } + + graphComponent.requestFocusInWindow(); + } + } + + public String getCurrentValue() { + return (String) comboBox.getSelectedItem(); + } + + /** + * Returns the bounds to be used for the editor. + */ + public Rectangle getEditorBounds(mxCellState state, double scale) { + mxIGraphModel model = state.getView().getGraph().getModel(); + Rectangle bounds = null; + + bounds = state.getLabelBounds().getRectangle(); + bounds.height += 10; + + // Applies the horizontal and vertical label positions + if (model.isVertex(state.getCell())) { + String horizontal = mxUtils.getString(state.getStyle(), mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER); + + if (horizontal.equals(mxConstants.ALIGN_LEFT)) { + bounds.x -= state.getWidth(); + } else if (horizontal.equals(mxConstants.ALIGN_RIGHT)) { + bounds.x += state.getWidth(); + } + + String vertical = mxUtils.getString(state.getStyle(), + mxConstants.STYLE_VERTICAL_LABEL_POSITION, + mxConstants.ALIGN_MIDDLE); + + if (vertical.equals(mxConstants.ALIGN_TOP)) { + bounds.y -= state.getHeight(); + } else if (vertical.equals(mxConstants.ALIGN_BOTTOM)) { + bounds.y += state.getHeight(); + } + } + + bounds.setSize( + (int) Math.max(bounds.getWidth(), + Math.round(minimumWidth * scale)), + (int) Math.max(bounds.getHeight(), + Math.round(minimumHeight * scale))); + + return bounds; + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/simulator/SimulationLayout.java b/AlgebraicDataflowArchitectureModel/src/application/simulator/SimulationLayout.java new file mode 100644 index 0000000..eced48d --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/simulator/SimulationLayout.java @@ -0,0 +1,157 @@ +package application.simulator; + +import com.mxgraph.model.mxGraphModel; +import com.mxgraph.view.mxGraph; +import models.dataConstraintModel.ResourcePath; +import simulator.Resource; +import simulator.ResourceIdentifier; +import simulator.Simulator; +import simulator.SystemState; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class SimulationLayout { + // Hold the division level for each resource + HashMap divisionLevelMap = new HashMap<>(); + // Hold the scaling factor for each resource + HashMap resourceScaleMap = new HashMap<>(); + int maxDivisionLevel = 1; + public final double BASE_WIDTH = 720; + public final double BASE_HEIGHT = BASE_WIDTH/2; + public final double MARGIN_SCALE = 0.92; + SystemState systemState; + public SimulationLayout(SystemState systemState){ + this.systemState = systemState; + // Calculate the division level for each resource + for (Resource res:systemState.getRootResources()) { + setDivisionLevel(divisionLevelMap, res.getResourceIdentifier(), 1); + } + // Calculate the scaling factor for each resource + for (ResourceIdentifier res:divisionLevelMap.keySet()) { + double scale = (double) maxDivisionLevel / divisionLevelMap.get(res); + resourceScaleMap.put(res, scale); + } + } + public double getScale(ResourceIdentifier resource){ + return resourceScaleMap.get(resource); + } + public double getDivision(ResourceIdentifier resource){ + return divisionLevelMap.get(resource); + } + + public int getMaxDivisionLevel() { + return maxDivisionLevel; + } + + public boolean isExistResource(ResourceIdentifier resourceIdentifier){ + return divisionLevelMap.containsKey(resourceIdentifier); + } + private void setDivisionLevel(HashMap resourceSet, ResourceIdentifier resource, int childCount){ + int divisionLevel; + if(resourceSet.get(resource.getParent()) == null){ + divisionLevel = 1; + }else{ + divisionLevel = resourceSet.get(resource.getParent()) * childCount; + } + if (divisionLevel > maxDivisionLevel)maxDivisionLevel = divisionLevel; + resourceSet.put(resource,divisionLevel); + + Collection identifiers = systemState.getResource(resource).getChildren(); + if (identifiers != null) { + for (Resource child:identifiers) { + setDivisionLevel(resourceSet, child.getResourceIdentifier(), identifiers.size()); + } + } + } + /** + * + * Draw an object corresponding to the target resource on the mxGraph. + * @param graph The mxGraph for drawing. + * @param parent The parent object of the target resource. + * @param resourceIdentifier The ID of the target resource. + * @param index The index. + * @param length The number of sibling resources of the target resource. + * @return The drawing object of the target resource. + */ + + private Object setLayout(mxGraph graph,Object parent, ResourceIdentifier resourceIdentifier,double index, double length){ + double width, height, x, y; + double parentWidth = graph.getCellGeometry(parent).getWidth(); + double parentHeight = graph.getCellGeometry(parent).getHeight(); + + width = parentWidth / length * MARGIN_SCALE; + height = width/2; + x = parentWidth * (index - 1)/length + (parentWidth/length)*(1-MARGIN_SCALE)/2; + + // Process to avoid hiding the parent's resource name + if ((int)length == 1) { + y = 20; + height -=20; + } else { + y = parentHeight/2 - height/2; + } + + Object result = graph.insertVertex(parent, null, + resourceIdentifier.toString(), x, y, width, height, + "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); + System.out.println(result); + return result; + } + + public mxGraph constructSimulateGraph(mxGraph graph, Simulator simulator){ + ((mxGraphModel) graph.getModel()).clear(); + Object parent = graph.getDefaultParent(); + graph.getModel().beginUpdate(); + + try { + Map resources = new HashMap<>(); + int i = 0; + int childCount = simulator.getCurState().getRootResources().size(); + // create resource vertices + for (Resource resNode: simulator.getCurState().getRootResources()) { + double scale = this.getScale(resNode.getResourceIdentifier()); + double maxDiv = this.getMaxDivisionLevel(); + double w = this.BASE_WIDTH * scale / maxDiv / childCount; + double h = this.BASE_HEIGHT * scale / maxDiv / childCount; + double x = w * i + 50; + double y = 20 ; + ResourcePath res = resNode.getResourceIdentifier(); + Object resource = graph.insertVertex(parent, null, + res.toString(), x, y, w, h, + "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex + resources.put(resNode, resource); + i++; + createNextChildSimulateResourceVerticies(graph, resource, resNode, resources); + + } + + } finally { + graph.getModel().endUpdate(); + } + + return graph; + } + private void createNextChildSimulateResourceVerticies(mxGraph graph, Object parent, Resource resNode, Map resources) { //sample + Collection children = resNode.getChildren(); + if (children != null) { + //List children = resNode.getChildren(); + double i = 1; + double childCount = children.size(); + for (Resource childNode: children) { + Object childResource = setLayout(graph, parent, childNode.getResourceIdentifier(), i, childCount); + resources.put(childNode, childResource); + i++; + createNextChildSimulateResourceVerticies(graph, childResource, childNode, resources); + + } + } + if (children == null || children.size() == 0) { + Object state = graph.insertVertex(parent, null, + resNode.getState().getValue().toString(), 0.5, 0.5, 0.25, 0.25, "opacity=0;verticalAlign=down;", true); // insert a state label as a vertex + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/simulator/SimulatorMenuBar.java b/AlgebraicDataflowArchitectureModel/src/application/simulator/SimulatorMenuBar.java new file mode 100644 index 0000000..29463f4 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/simulator/SimulatorMenuBar.java @@ -0,0 +1,27 @@ +package application.simulator; + +import javax.swing.JMenu; +import javax.swing.JMenuBar; + +import application.actions.ZoomInAction; +import application.actions.ZoomOutAction; +import application.simulator.actions.ShowUISimulatorAction; + +public class SimulatorMenuBar extends JMenuBar { + private static final long serialVersionUID = 7769410930379012970L; + + private SimulatorWindow simulatorWindow = null; + + public SimulatorMenuBar(SimulatorWindow simulatorWindow) { + this.simulatorWindow = simulatorWindow; + + JMenu menu = null; + menu = add(new JMenu("View")); + menu.add(new ZoomInAction(simulatorWindow.getGraphComponent())); + menu.add(new ZoomOutAction(simulatorWindow.getGraphComponent())); + + menu = add(new JMenu("Show")); + menu.add(new ShowUISimulatorAction(simulatorWindow.getSimulator())); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/simulator/SimulatorWindow.java b/AlgebraicDataflowArchitectureModel/src/application/simulator/SimulatorWindow.java new file mode 100644 index 0000000..07268f3 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/simulator/SimulatorWindow.java @@ -0,0 +1,203 @@ +package application.simulator; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.swing.JFrame; + +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGeometry; +import com.mxgraph.model.mxGraphModel; +import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.swing.handler.mxRubberband; +import com.mxgraph.util.mxEvent; +import com.mxgraph.util.mxEventObject; +import com.mxgraph.util.mxPoint; +import com.mxgraph.util.mxEventSource.mxIEventListener; +import com.mxgraph.view.mxGraph; + +import algorithms.TypeInference; +import application.editor.DataTransferModelingCellEditor; +import application.editor.Editor; +import application.layouts.DAGLayout; +import generators.JavaCodeGenerator; +import models.Edge; +import models.EdgeAttribute; +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; +import models.dataFlowModel.ChannelNode; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import models.dataFlowModel.ResourceNode; +import parser.Parser; +import parser.ParserDTRAM; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.WrongJsonExpression; +import parser.Parser.TokenStream; +import simulator.Event; +import simulator.Resource; +import simulator.ResourceIdentifier; +import simulator.Simulator; + +public class SimulatorWindow extends JFrame{ + + private static final long serialVersionUID = -2425820512017088254L; + public static final String title = "Simulation Tool"; + + final int PORT_DIAMETER = 8; + final int PORT_RADIUS = PORT_DIAMETER / 2; + + private Editor editor = null; + private mxGraph graph = null; + private mxGraphComponent graphComponent = null; + + private Simulator simulator = null; + + private boolean bReflectingArchitectureModel = false; + private double x = 20; + private double y = 20; + private SimulatorMenuBar menuBar; + + public SimulatorWindow(Editor editor) { + setTitle(title); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + + this.graph = new mxGraph() { + public boolean isPort(Object cell) { + mxGeometry geo = getCellGeometry(cell); + + return (geo != null) ? geo.isRelative() : false; + } + + public boolean isCellFoldable(Object cell, boolean collapse) { + return false; + } + }; + + this.graphComponent = new mxGraphComponent(graph); + this.editor = editor; + + 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); + graph.setCellsDisconnectable(true); + + setTitle(title); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setSize(870,640); + setVisible(true); + + DataTransferModel model = this.editor.getModel(); + TypeInference.infer(model); + simulator = new Simulator(model); + SimulationLayout layout = new SimulationLayout(simulator.getCurState()); + layout.constructSimulateGraph(graph, simulator); + graphComponent.setCellEditor(new InputEventCellEditor(graphComponent, simulator, this.editor, graph)); + + menuBar = new SimulatorMenuBar(this); + setJMenuBar(menuBar); + } + + public mxGraph constructSimulateGraph(Set simulateRes, DataTransferModel model, DataFlowGraph dataFlowGraph) { + bReflectingArchitectureModel = true; + ((mxGraphModel) graph.getModel()).clear(); + Object parent = graph.getDefaultParent(); + graph.getModel().beginUpdate(); + + try { + Map resources = new HashMap<>(); + + // create resource vertices + for (Resource resNode: simulateRes) { + int w = 80; + int h = 30; + ResourcePath res = resNode.getResourceIdentifier(); + Object resource = graph.insertVertex(parent, null, + res.toString(), x, y, w, h, + "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex + resources.put(resNode, resource); + createChildSimulateResourceVerticies(resource, resNode, resources, w, h); + x+=80; + } + + } finally { + graph.getModel().endUpdate(); + } + + bReflectingArchitectureModel = false; + return graph; + } + + + public void createChildSimulateResourceVerticies(Object resource, Resource resNode, Map resources, int w, int h) { //sample + + if(resNode.getChildren() != null) { + for (Resource childNode: resNode.getChildren()) { + ResourcePath childRes = childNode.getResourceIdentifier(); + Object childResource = graph.insertVertex(resource, null, + childRes.toString(), 0, 0, w/2, h/2, + "shape=ellipse;perimeter=ellipsePerimeter;verticalAlign=top;"); // insert a resource as a vertex + resources.put(childNode, childResource); + createChildSimulateResourceVerticies(childResource, childNode, resources, w, h); + } + } + if (resNode.getChildren() == null || resNode.getChildren().size() == 0) { + Object state = graph.insertVertex(resource, null, + resNode.getState().getValue().toString(), 0.5, 0.5, 0.25, 0.25, "opacity=0;verticalAlign=down;", true); // insert a state label as a vertex + } + } + + public mxGraphComponent getGraphComponent() { + return graphComponent; + } + + public Editor getEditor() { + return editor; + } + + public void setEditor(Editor editor) { + this.editor = editor; + } + + public Simulator getSimulator() { + return simulator; + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/simulator/UISimulatorWindow.java b/AlgebraicDataflowArchitectureModel/src/application/simulator/UISimulatorWindow.java new file mode 100644 index 0000000..24ac3c0 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/simulator/UISimulatorWindow.java @@ -0,0 +1,26 @@ +package application.simulator; + +import javax.swing.JFrame; +import javax.swing.JPanel; + +import simulator.Simulator; +import simulator.interfaces.swing.SwingPresenter; + +public class UISimulatorWindow extends JFrame { + + private static final long serialVersionUID = 1770206525826167136L; + private SwingPresenter presenter; + private Simulator simulator; + private JPanel mainPanel; + + public UISimulatorWindow(Simulator simulator) { + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + this.simulator = simulator; + mainPanel = new JPanel(); + presenter = new SwingPresenter(mainPanel, simulator); + this.add(mainPanel); + + setSize(870,640); + setVisible(true); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/simulator/actions/ShowUISimulatorAction.java b/AlgebraicDataflowArchitectureModel/src/application/simulator/actions/ShowUISimulatorAction.java new file mode 100644 index 0000000..758d2d9 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/simulator/actions/ShowUISimulatorAction.java @@ -0,0 +1,23 @@ +package application.simulator.actions; + +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; + +import application.simulator.UISimulatorWindow; +import simulator.Simulator; + +public class ShowUISimulatorAction extends AbstractAction { + private Simulator simulator; + + public ShowUISimulatorAction(Simulator simulator) { + super("Show UI Simulator"); + this.simulator = simulator; + } + + @Override + public void actionPerformed(ActionEvent e) { + new UISimulatorWindow(simulator); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java index eb5e29e..2776604 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java @@ -200,6 +200,8 @@ result = (Long.parseLong(sArg0) == Long.parseLong(sArg1)); } else if (arg0.getType().equals(typeInt) || arg1.getType().equals(typeInt)) { result = (Integer.parseInt(sArg0) == Integer.parseInt(sArg1)); + } else if (arg0.getType().equals(typeString) || arg1.getType().equals(typeString)) { + result = (sArg0.toString().equals(sArg1.toString())); } if (result) { return new Constant(true_); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonTerm.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonTerm.java index 6c5d1eb..a5c1973 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonTerm.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonTerm.java @@ -38,6 +38,16 @@ return getChild(keyToIndex.get(key.toString())); } + @Override + public Object clone() { + JsonTerm newTerm = new JsonTerm(); + for (Expression e: children) { + newTerm.addChild((Expression) e.clone()); + } + newTerm.keyToIndex = new HashMap(keyToIndex); + return newTerm; + } + public String toString() { String jsonStr = "{"; String delim = ""; diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ListTerm.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ListTerm.java index d70d476..de5b736 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ListTerm.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ListTerm.java @@ -1,5 +1,7 @@ package models.dataConstraintModel; +import java.util.HashMap; + import models.algebra.Expression; import models.algebra.Symbol; import models.algebra.Term; @@ -19,6 +21,15 @@ return getChild(index); } + @Override + public Object clone() { + ListTerm newTerm = new ListTerm(); + for (Expression e: children) { + newTerm.addChild((Expression) e.clone()); + } + return newTerm; + } + public String toString() { String listStr = "["; String delim = ""; diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/MapTerm.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/MapTerm.java index 34792f6..3646146 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/MapTerm.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/MapTerm.java @@ -38,6 +38,16 @@ return getChild(keyToIndex.get(key.toString())); } + @Override + public Object clone() { + MapTerm newTerm = new MapTerm(); + for (Expression e: children) { + newTerm.addChild((Expression) e.clone()); + } + newTerm.keyToIndex = new HashMap(keyToIndex); + return newTerm; + } + public String toString() { String mapStr = "{"; String delim = ""; diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java index 9fd4993..101bb80 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java @@ -10,7 +10,7 @@ import models.dataConstraintModel.Selector; import models.dataFlowModel.DataTransferChannel; -public class ChannelState { +public class ChannelState implements Cloneable { private DataTransferChannel channel; private ReferenceStructure referenceStructure; @@ -52,7 +52,13 @@ referenceStructure.addDependingParamAndValue(channelValues, dependingVariable, itsValue); } - private static class ReferenceStructure { + public Object clone() { + ChannelState newChannelState = new ChannelState(channel); + newChannelState.referenceStructure = (ReferenceStructure) referenceStructure.clone(); + return newChannelState; + } + + private static class ReferenceStructure implements Cloneable { private Map dependingParamAndValues = null; private Map referenceStructure; @@ -130,5 +136,17 @@ public ReferenceStructure getReferenceStructure(Constant channelParam) { return referenceStructure.get(channelParam); } + + public Object clone() { + ReferenceStructure newReferenceStructure = new ReferenceStructure(); + newReferenceStructure.dependingParamAndValues = new HashMap<>(dependingParamAndValues); + if (referenceStructure != null) { + newReferenceStructure.referenceStructure = new HashMap<>(); + for (Map.Entry refEnt: referenceStructure.entrySet()) { + newReferenceStructure.referenceStructure.put(refEnt.getKey(), (ReferenceStructure) refEnt.getValue().clone()); + } + } + return newReferenceStructure; + } } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java index b0bce8c..643be88 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java @@ -55,7 +55,7 @@ } ancestor = ancestor.getParent(); } - channelSelectorAndValues.add(new AbstractMap.SimpleEntry<>(sel, ancestor.getParameter())); + if (ancestor!= null) channelSelectorAndValues.add(new AbstractMap.SimpleEntry<>(sel, ancestor.getParameter())); } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java index 48dad8f..23254b8 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java @@ -1,16 +1,13 @@ package simulator; -import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import models.algebra.Constant; import models.algebra.Type; import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.ResourceHierarchy; -import models.dataConstraintModel.ResourcePath; import simulator.states.*; public class Resource { @@ -20,6 +17,13 @@ private ResourceState state = null; private Constant parameter = null; + public Resource(Resource resource) { + this.resourceHierarchy = resource.resourceHierarchy; + this.parent = resource.parent; + this.state = (ResourceState) resource.state.clone(); + this.parameter = resource.parameter; + } + public Resource(ResourceHierarchy resourceHierarchy) { this.resourceHierarchy = resourceHierarchy; Type resType = resourceHierarchy.getResourceStateType(); diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java index 2338858..e4fbd12 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java @@ -175,10 +175,10 @@ } else if (channel.isNative()) { // A native output event channel INativeReceiver receiver = nativeChannelReceivers.get(channel); // receiver for the channel - if (receiver != null) receiver.onReceiveFromModel(event); + if (receiver != null) receiver.onReceiveFromModel(event, nextSystemState); if (nativeReceivers.get(channel) != null) { receiver = nativeReceivers.get(channel).get(event.getInputResource()); // receiver for the channel and resource - if (receiver != null) receiver.onReceiveFromModel(event); + if (receiver != null) receiver.onReceiveFromModel(event, nextSystemState); } } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java index 8f5037e..4ae4020 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java @@ -31,8 +31,16 @@ } public SystemState(SystemState prevState) { - rootResources = new HashSet<>(prevState.getRootResources()); - channelStates = new HashMap<>(prevState.getChannelStates()); + for (Resource resource: prevState.getRootResources()) { + rootResources.add(new Resource(resource)); + } + for (Map.Entry channelEnt: prevState.getChannelStates().entrySet()) { + if (channelEnt.getValue() != null) { + channelStates.put(channelEnt.getKey(), (ChannelState) channelEnt.getValue().clone()); + } else { + channelStates.put(channelEnt.getKey(), null); + } + } } public Set getRootResources() { diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/INativeReceiver.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/INativeReceiver.java index 50e651e..296506a 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/INativeReceiver.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/INativeReceiver.java @@ -1,7 +1,8 @@ package simulator.interfaces; import simulator.Event; +import simulator.SystemState; public interface INativeReceiver { - public void onReceiveFromModel(Event event); + public void onReceiveFromModel(Event event, SystemState nextSystemState); } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextReceiver.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextReceiver.java index e110a67..69badc8 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextReceiver.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextReceiver.java @@ -10,6 +10,7 @@ import models.algebra.Expression; import models.algebra.Term; import simulator.Event; +import simulator.SystemState; import simulator.interfaces.INativeReceiver; public class ComponentTextReceiver implements INativeReceiver { @@ -20,7 +21,7 @@ } @Override - public void onReceiveFromModel(Event event) { + public void onReceiveFromModel(Event event, SystemState nextSystemState) { Expression message = event.getMessage(); if (message instanceof Term) { Expression text = ((Term) message).getChild(0); diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextSender.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextSender.java index 4e13f41..c6580fd 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextSender.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextSender.java @@ -1,8 +1,9 @@ package simulator.interfaces.swing; -import java.awt.TextField; -import java.awt.event.InputMethodEvent; -import java.awt.event.InputMethodListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; import models.algebra.Constant; import models.algebra.Expression; @@ -14,23 +15,52 @@ import simulator.Simulator; import simulator.interfaces.NativeSender; -public class ComponentTextSender extends NativeSender implements InputMethodListener { +public class ComponentTextSender extends NativeSender implements DocumentListener { public ComponentTextSender(Simulator simulator, DataTransferChannel channel, ResourcePath resourcePath, Resource resource) { super(simulator, channel, resourcePath, resource); } @Override - public void inputMethodTextChanged(InputMethodEvent event) { - Constant text = new Constant(((TextField) event.getSource()).getText(), DataConstraintModel.typeString); - Expression message = channel.getOutputChannelMembers().iterator().next().getStateTransition().getMessageExpression(); - message = (Term) message.clone(); - ((Term) message).setChild(0, text); - sendToModel(message); + public void insertUpdate(DocumentEvent e) { + Document d = e.getDocument(); + try { + Constant text = new Constant(d.getText(0, d.getLength()), DataConstraintModel.typeString); + Expression message = channel.getOutputChannelMembers().iterator().next().getStateTransition().getMessageExpression(); + message = (Term) message.clone(); + ((Term) message).setChild(0, text); + sendToModel(message); + } catch (BadLocationException e1) { + e1.printStackTrace(); + } } @Override - public void caretPositionChanged(InputMethodEvent event) { + public void removeUpdate(DocumentEvent e) { + Document d = e.getDocument(); + try { + Constant text = new Constant(d.getText(0, d.getLength()), DataConstraintModel.typeString); + Expression message = channel.getOutputChannelMembers().iterator().next().getStateTransition().getMessageExpression(); + message = (Term) message.clone(); + ((Term) message).setChild(0, text); + sendToModel(message); + } catch (BadLocationException e1) { + e1.printStackTrace(); + } + } + + @Override + public void changedUpdate(DocumentEvent e) { + Document d = e.getDocument(); + try { + Constant text = new Constant(d.getText(0, d.getLength()), DataConstraintModel.typeString); + Expression message = channel.getOutputChannelMembers().iterator().next().getStateTransition().getMessageExpression(); + message = (Term) message.clone(); + ((Term) message).setChild(0, text); + sendToModel(message); + } catch (BadLocationException e1) { + e1.printStackTrace(); + } } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentVisibilityReceiver.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentVisibilityReceiver.java index 2527a52..447dae1 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentVisibilityReceiver.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentVisibilityReceiver.java @@ -7,6 +7,7 @@ import models.algebra.Term; import models.dataConstraintModel.DataConstraintModel; import simulator.Event; +import simulator.SystemState; import simulator.interfaces.INativeReceiver; public class ComponentVisibilityReceiver implements INativeReceiver { @@ -17,7 +18,7 @@ } @Override - public void onReceiveFromModel(Event event) { + public void onReceiveFromModel(Event event, SystemState nextSystemState) { Expression message = event.getMessage(); if (message instanceof Term) { Expression visible = ((Term) message).getChild(0); diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java index 68df398..e82372e 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java @@ -22,11 +22,13 @@ import simulator.Event; import simulator.Resource; import simulator.Simulator; +import simulator.SystemState; import simulator.interfaces.INativeReceiver; public class SwingPresenter implements INativeReceiver { public final String screenUpdateChannelName = "ScreenUpdate"; public final String setVisibleChannelName = "SetVisible"; + public final String setTextChannelName = "SetText"; public final String mouseEventChannelName = "MouseEvent"; public final String textEventChannelName = "TextEvent"; @@ -35,9 +37,10 @@ protected Map components; protected DataTransferChannel screenUpdateChannel; protected DataTransferChannel setVisibleChannel; + protected DataTransferChannel setTextChannel; protected DataTransferChannel mouseEventChannel; protected DataTransferChannel textEventChannel; - protected Map> channelAndResourcesForReceiving = new HashMap<>(); + protected Map> channelAndResourcesForReceiving = new HashMap<>(); public SwingPresenter(JPanel mainPanel, Simulator simulator) { this.mainPanel = mainPanel; @@ -45,92 +48,131 @@ components = new HashMap<>(); screenUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(screenUpdateChannelName); setVisibleChannel = (DataTransferChannel) simulator.getModel().getChannel(setVisibleChannelName); + setTextChannel = (DataTransferChannel) simulator.getModel().getChannel(setTextChannelName); mouseEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(mouseEventChannelName); textEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(textEventChannelName); simulator.addNativeReceiver(this, screenUpdateChannel); } @Override - public void onReceiveFromModel(Event event) { + public void onReceiveFromModel(Event event, SystemState nextSystemState) { Expression message = event.getMessage(); - if (message instanceof Term && ((Term) message).getChildren().size() == 1) { - message = ((Term) message).getChild(0); - if (message instanceof JsonTerm) { - // Remove old native receivers. - for (DataTransferChannel channel: channelAndResourcesForReceiving.keySet()) { - for (Resource resource: channelAndResourcesForReceiving.get(channel)) { - simulator.removeNativeReceiver(channel, resource); - } - } - channelAndResourcesForReceiving.clear(); - - // Reconstruct swing components. - JsonTerm screenContent = (JsonTerm) message; - Resource screenResource = simulator.getCurState().getResource(event.getInputResource().getResourceIdentifier()); - Expression widgets = screenContent.get("widgets"); - Resource widgetsResource = screenResource.getChildrenMap().get("widgets"); - if (widgets instanceof MapTerm) { - mainPanel.removeAll(); - for (String key: ((MapTerm) widgets).keySet()) { - Expression value = ((MapTerm) widgets).get(key); - if (value instanceof JsonTerm) { - JsonTerm widget = (JsonTerm) value; - Resource widgetResource = widgetsResource.getChildrenMap().get(key); - Expression type = widget.get("\"type\""); - if (type.toString().equals("\"button\"")) { - // Add a button component. - Expression text = widget.get("\"text\""); - JButton button = new JButton(text.toString().replace("\"", "")); - mainPanel.add(button); - components.put(key, button); - // Connect swing component and model. - ResourcePath resPath = mouseEventChannel.getOutputResources().iterator().next(); - button.addMouseListener(new ComponentMouseSender(simulator, mouseEventChannel, resPath, widgetResource)); // button => widgetResource - ComponentVisibilityReceiver nativeReceiver = new ComponentVisibilityReceiver(button); // widgetResource => button - simulator.addNativeReceiver(nativeReceiver, setVisibleChannel, widgetResource); - Set resources = channelAndResourcesForReceiving.get(setVisibleChannel); - if (resources == null) { - resources = new HashSet<>(); - channelAndResourcesForReceiving.put(setVisibleChannel, resources); + if (message instanceof Term && ((Term) message).getChildren().size() >= 2) { + Expression curScExp = ((Term) message).getChild(0); + Expression nextScExp = ((Term) message).getChild(1); + if (curScExp instanceof JsonTerm && nextScExp instanceof JsonTerm) { + JsonTerm curSc = (JsonTerm) curScExp; + JsonTerm nextSc = (JsonTerm) nextScExp; + Expression oldWidgets = curSc.get("widgets"); + Expression newWidgets = nextSc.get("widgets"); + if (oldWidgets instanceof MapTerm && newWidgets instanceof MapTerm) { + Set oldWidSet = new HashSet<>(((MapTerm) oldWidgets).keySet()); + Set newWidSet = new HashSet<>(((MapTerm) newWidgets).keySet()); + oldWidSet.removeAll(((MapTerm) newWidgets).keySet()); + newWidSet.removeAll(((MapTerm) oldWidgets).keySet()); + if (!oldWidSet.isEmpty() || !newWidSet.isEmpty()) { + // If the set of screen components is changed. + + // Remove old components and their native receivers. + for (String oldWid: oldWidSet) { + mainPanel.remove(components.get(oldWid)); + } + + for (DataTransferChannel channel: channelAndResourcesForReceiving.keySet()) { + Map widToResource = channelAndResourcesForReceiving.get(channel); + for (String oldWid: oldWidSet) { + Resource resource = widToResource.remove(oldWid); + if (resource != null) { + simulator.removeNativeReceiver(channel, resource); } - resources.add(widgetsResource); - } else if (type.toString().equals("\"label\"")) { - // Add a label component. - Expression text = widget.get("\"text\""); - JLabel label = new JLabel(text.toString().replace("\"", "")); - mainPanel.add(label); - components.put(key, label); - // Connect swing component and model. - ComponentVisibilityReceiver nativeReceiver = new ComponentVisibilityReceiver(label); - simulator.addNativeReceiver(nativeReceiver, setVisibleChannel, widgetResource); - Set resources = channelAndResourcesForReceiving.get(setVisibleChannel); - if (resources == null) { - resources = new HashSet<>(); - channelAndResourcesForReceiving.put(setVisibleChannel, resources); - } - resources.add(widgetsResource); - } else if (type.toString().equals("\"inputText\"")) { - // Add a text input component. - JTextField textField = new JTextField(10); - mainPanel.add(textField); - components.put(key, textField); - // Connect swing component and model. - ResourcePath resPath = textEventChannel.getOutputResources().iterator().next(); - textField.addInputMethodListener(new ComponentTextSender(simulator, textEventChannel, resPath, widgetResource)); // textField => widgetResource - ComponentVisibilityReceiver nativeReceiver = new ComponentVisibilityReceiver(textField); // widgetResource => textField - simulator.addNativeReceiver(nativeReceiver, setVisibleChannel, widgetResource); - Set resources = channelAndResourcesForReceiving.get(setVisibleChannel); - if (resources == null) { - resources = new HashSet<>(); - channelAndResourcesForReceiving.put(setVisibleChannel, resources); - } - resources.add(widgetsResource); } } + + // Add new swing components. + Resource screenResource = nextSystemState.getResource(event.getInputResource().getResourceIdentifier()); + Resource widgetsResource = screenResource.getChildrenMap().get("widgets"); + for (String newWid: newWidSet) { + Expression value = ((MapTerm) newWidgets).get(newWid); + if (value instanceof JsonTerm) { + JsonTerm widget = (JsonTerm) value; + Resource widgetResource = widgetsResource.getChildrenMap().get(newWid); + Expression type = widget.get("\"type\""); + if (type.toString().equals("\"button\"")) { + // Add a button component. + Expression text = widget.get("\"text\""); + JButton button = new JButton(text.toString().replace("\"", "")); + mainPanel.add(button); + components.put(newWid, button); + // Connect swing component and model. + ResourcePath resPath = mouseEventChannel.getOutputResources().iterator().next(); + button.addMouseListener(new ComponentMouseSender(simulator, mouseEventChannel, resPath, widgetResource)); // button => widgetResource + + ComponentVisibilityReceiver nativeVisibilityReceiver = new ComponentVisibilityReceiver(button); // widgetResource => button + simulator.addNativeReceiver(nativeVisibilityReceiver, setVisibleChannel, widgetResource); + Map resources = channelAndResourcesForReceiving.get(setVisibleChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setVisibleChannel, resources); + } + resources.put(newWid, widgetsResource); + + ComponentTextReceiver nativeTextReceiver = new ComponentTextReceiver(button); // widgetResource => button + simulator.addNativeReceiver(nativeTextReceiver, setTextChannel, widgetResource); + resources = channelAndResourcesForReceiving.get(setTextChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setTextChannel, resources); + } + resources.put(newWid, widgetsResource); + } else if (type.toString().equals("\"label\"")) { + // Add a label component. + Expression text = widget.get("\"text\""); + JLabel label = new JLabel(text.toString().replace("\"", "")); + mainPanel.add(label); + components.put(newWid, label); + + // Connect swing component and model. + ComponentVisibilityReceiver nativeVisibilityReceiver = new ComponentVisibilityReceiver(label); // widgetResource => label + simulator.addNativeReceiver(nativeVisibilityReceiver, setVisibleChannel, widgetResource); + Map resources = channelAndResourcesForReceiving.get(setVisibleChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setVisibleChannel, resources); + } + resources.put(newWid, widgetsResource); + + ComponentTextReceiver nativeTextReceiver = new ComponentTextReceiver(label); // widgetResource => label + simulator.addNativeReceiver(nativeTextReceiver, setTextChannel, widgetResource); + resources = channelAndResourcesForReceiving.get(setTextChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setTextChannel, resources); + } + resources.put(newWid, widgetsResource); + } else if (type.toString().equals("\"textInput\"")) { + // Add a text input component. + JTextField textField = new JTextField(10); + mainPanel.add(textField); + components.put(newWid, textField); + // Connect swing component and model. + ResourcePath resPath = textEventChannel.getOutputResources().iterator().next(); + textField.getDocument().addDocumentListener(new ComponentTextSender(simulator, textEventChannel, resPath, widgetResource)); // textField => widgetResource + + ComponentVisibilityReceiver nativeReceiver = new ComponentVisibilityReceiver(textField); // widgetResource => textField + simulator.addNativeReceiver(nativeReceiver, setVisibleChannel, widgetResource); + Map resources = channelAndResourcesForReceiving.get(setVisibleChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setVisibleChannel, resources); + } + resources.put(newWid, widgetsResource); + } + } + } + mainPanel.invalidate(); + mainPanel.validate(); + mainPanel.repaint(); } - mainPanel.invalidate(); - mainPanel.validate(); - mainPanel.repaint(); } } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java index cf4ce2b..20909c6 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java @@ -39,4 +39,12 @@ } } } + + public Object clone() { + JsonResourceState newJsonResourceState = new JsonResourceState(); + for (String key: children.keySet()) { + newJsonResourceState.children.put(key, (ResourceState) children.get(key).clone()); + } + return newJsonResourceState; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java index 0e45334..34eff54 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java @@ -45,4 +45,12 @@ } } } + + public Object clone() { + ListResourceState newListResourceState = new ListResourceState(); + for (ResourceState state: children) { + newListResourceState.children.add((ResourceState) state.clone()); + } + return newListResourceState; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java index e03d70e..6071c51 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java @@ -39,4 +39,12 @@ } } } + + public Object clone() { + MapResourceState newMapResourceState = new MapResourceState(); + for (String key: children.keySet()) { + newMapResourceState.children.put(key, (ResourceState) children.get(key).clone()); + } + return newMapResourceState; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/PrimitiveResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/PrimitiveResourceState.java index d5aba63..adfb7f3 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/PrimitiveResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/PrimitiveResourceState.java @@ -24,4 +24,8 @@ boolean hasChildren() { return false; } + + public Object clone() { + return this; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/State.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/State.java index f9286dd..2dfa5c0 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/State.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/State.java @@ -2,6 +2,7 @@ import models.algebra.Expression; -abstract public class State { +abstract public class State implements Cloneable { abstract public Expression getValue(); + abstract public Object clone(); } diff --git a/AlgebraicDataflowArchitectureModel/src/tests/NativeAccessTest.java b/AlgebraicDataflowArchitectureModel/src/tests/NativeAccessTest.java index d9598b8..e014bab 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/NativeAccessTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/NativeAccessTest.java @@ -81,7 +81,7 @@ }; INativeReceiver textReceiver = new INativeReceiver() { // Model to native code @Override - public void onReceiveFromModel(Event event) { // Receive a message from the model + public void onReceiveFromModel(Event event, SystemState nextSystemState) { // Receive a message from the model Expression message = event.getMessage(); System.out.println(message); }