diff --git a/AlgebraicDataflowArchitectureModel/models/Accounts.model b/AlgebraicDataflowArchitectureModel/models/Accounts.model index dba68ba..24710ee 100644 --- a/AlgebraicDataflowArchitectureModel/models/Accounts.model +++ b/AlgebraicDataflowArchitectureModel/models/Accounts.model @@ -1,5 +1,5 @@ channel CIO1 { - out accounts(l:Map, signup(id:Int, name:Str)) = append(l, {"name": name}) + out accounts(l:List, signup(name:Str)) = append(l, {"name": name}) } channel CIO2(uid:Int) { diff --git a/AlgebraicDataflowArchitectureModel/models/SimpleUI.model b/AlgebraicDataflowArchitectureModel/models/SimpleUI.model index f393c9d..9b54346 100644 --- a/AlgebraicDataflowArchitectureModel/models/SimpleUI.model +++ b/AlgebraicDataflowArchitectureModel/models/SimpleUI.model @@ -1,5 +1,15 @@ +init { + screen := {"widgets": {"001": {"type": "button", "text": "OK", "state": 0}, + "002": {"type": "textInput", "text": "", "state": 0}}, + "layout": true} +} + native channel ScreenUpdate { - in screen(curSc: Json, update(nextSc)) = nextSc + in screen(curSc: Json, update(curSc, nextSc)) = nextSc +} + +native channel SetLayout { + in screen.layout(curLayout: Bool, setLayout(nextLayout)) = nextLayout } native channel SetVisible(wid: Str) { @@ -10,6 +20,22 @@ in screen.widgets.{wid}.text(curText: Str, setText(nextText)) = nextText } +native channel SetX(wid: Str) { + in screen.widgets.{wid}.x(curX: Int, setX(nextX)) = nextX +} + +native channel SetY(wid: Str) { + in screen.widgets.{wid}.y(curY: Int, setY(nextY)) = nextY +} + +native channel SetWidth(wid: Str) { + in screen.widgets.{wid}.width(curWidth: Int, setWidth(nextWidth)) = nextWidth +} + +native channel SetHeight(wid: Str) { + in screen.widgets.{wid}.height(curHeight: Int, setHeight(nextHeight)) = nextHeight +} + native channel MouseEvent(wid: Str) { out screen.widgets.{wid}.state(curState: Int, mouseEvent(nextState)) = nextState } @@ -17,3 +43,39 @@ native channel TextEvent(wid: Str) { out screen.widgets.{wid}.text(curText: Str, textEvent(nextText)) = nextText } + +channel ChangeLayout { + out screen.layout(curLayout: Bool, changeLayout(layout)) = layout +} + +channel ChangeX(wid: Str) { + out screen.widgets.{wid}.x(curX: Int, changeX(x)) = x +} + +channel ChangeY(wid: Str) { + out screen.widgets.{wid}.y(curY: Int, changeY(y)) = y +} + +channel AddButton { + out screen.widgets(widgets: Map, addButton(wid: Str, text: Str)) = insert(widgets, wid, {"type": "button", "text": text, "state": 0}) +} + +channel AddLabel { + out screen.widgets(widgets: Map, addLabel(wid: Str, text: Str)) = insert(widgets, wid, {"type": "label", "text": text, "state": 0}) +} + +channel AddTextInput { + out screen.widgets(widgets: Map, addTextInput(wid: Str)) = insert(widgets, wid, {"type": "textInput", "text": "", "state": 0}) +} + +channel AddMovableButton { + out screen.widgets(widgets: Map, addMovableButton(wid: Str, text: Str, x: Int, y: Int, width: Int, height: Int)) = insert(widgets, wid, {"type": "button", "text": text, "x": x, "y": y, "width": width, "height": height, "state": 0}) +} + +channel AddMovableLabel { + out screen.widgets(widgets: Map, addMovableLabel(wid: Str, text: Str, x: Int, y: Int, width: Int, height: Int)) = insert(widgets, wid, {"type": "label", "text": text, "x": x, "y": y, "width": width, "height": height, "state": 0}) +} + +channel AddMovableTextInput { + out screen.widgets(widgets: Map, addMovableTextInput(wid: Str, x: Int, y: Int, width: Int, height: Int)) = insert(widgets, wid, {"type": "textInput", "text": "", "x": x, "y": y, "width": width, "height": height, "state": 0}) +} diff --git a/AlgebraicDataflowArchitectureModel/models/Timer.model b/AlgebraicDataflowArchitectureModel/models/Timer.model new file mode 100644 index 0000000..83a66d5 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/Timer.model @@ -0,0 +1,15 @@ +native channel TimersUpdated { + in timers(curTimers: Map, update(curTimers, nextTimers)) = nextTimers +} + +native channel TimerEvent(tid: Str) { + out timers.{tid}.count(count: Long, tick()) = count + 1 +} + +channel StartTimer { + out timers(timers: Map, startTimer(tid: Str, interval: Long)) = insert(timers, tid, {"interval": interval, "count": 0}) +} + +channel ClearTimer { + out timers(timers: Map, clearTimer(tid: Str)) = delete(timers, tid) +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java b/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java deleted file mode 100644 index 6a0684b..0000000 --- a/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java +++ /dev/null @@ -1,198 +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 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 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); - constructSimulateGraph(simulator.getCurState().getRootResources(), this.editor.getModel(),this.editor.getDataFlowGraph()); - graphComponent.setCellEditor(new InputEventCellEditor(graphComponent, simulator, this.editor, graph)); - } - - - 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/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 e945773..0000000 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/InputEventCellEditor.java +++ /dev/null @@ -1,341 +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); - - constructNextSimulateGraph(simulator.getCurState().getRootResources(), simulator.getModel(),simulator.getModel().getDataFlowGraph(), graph); - 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, y, 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/InputEventCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/simulator/InputEventCellEditor.java new file mode 100644 index 0000000..8d219c5 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/simulator/InputEventCellEditor.java @@ -0,0 +1,341 @@ +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; + + public InputEventCellEditor(mxGraphComponent graphComponent, Simulator simulator, Editor editor) { + this.graphComponent = graphComponent; + this.simulator = simulator; + this.editor = editor; + } + + @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)); + + } 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..6dfb078 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/simulator/SimulatorWindow.java @@ -0,0 +1,213 @@ +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; +import simulator.SystemState; +import simulator.interfaces.INativeReceiver; + +public class SimulatorWindow extends JFrame implements INativeReceiver { + + 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)); + simulator.addSystemReceiver(this); + + menuBar = new SimulatorMenuBar(this); + setJMenuBar(menuBar); + } + + + @Override + public void onReceiveFromModel(Event event, SystemState nextSystemState) { + SimulationLayout layout = new SimulationLayout(nextSystemState); + layout.constructSimulateGraph(graph, 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; + } + + 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..1c246b9 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/simulator/UISimulatorWindow.java @@ -0,0 +1,29 @@ +package application.simulator; + +import javax.swing.JFrame; +import javax.swing.JPanel; + +import simulator.Simulator; +import simulator.interfaces.swing.SwingPresenter; +import simulator.interfaces.timers.TimerService; + +public class UISimulatorWindow extends JFrame { + + private static final long serialVersionUID = 1770206525826167136L; + private SwingPresenter presenter; + private Simulator simulator; + private JPanel mainPanel; + private TimerService timerService; + + public UISimulatorWindow(Simulator simulator) { + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + this.simulator = simulator; + mainPanel = new JPanel(); + presenter = new SwingPresenter(mainPanel, simulator); + this.add(mainPanel); + timerService = new TimerService(simulator); + + 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/algebra/Term.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java index 1b5a6ac..3398f18 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java @@ -172,8 +172,11 @@ boolean bReduced = false; for (Expression child: children) { if (child instanceof Term && !(child instanceof Constant)) { - child = ((Term) (child)).reduce(); - bReduced = true; + Expression newChild = ((Term) (child)).reduce(); + if (newChild != child) { + bReduced = true; + child = newChild; + } } newChildren.add(child); } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java index eb5e29e..0962ce2 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_); @@ -781,6 +783,15 @@ return resourceHierarchies.get(hierarchy); } + public ResourceHierarchy getOrPutResourceHierarchy(ResourceHierarchy resourceHierarchy) { + String hierarchy = resourceHierarchy.toString(); + if (resourceHierarchies.get(hierarchy) != null) { + return resourceHierarchies.get(hierarchy); + } + resourceHierarchies.put(hierarchy, resourceHierarchy); + return resourceHierarchy; + } + public List getResourcePaths() { return resourcePaths; } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonTerm.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonTerm.java index 6c5d1eb..dd213a8 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonTerm.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonTerm.java @@ -31,13 +31,25 @@ } public Expression get(String key) { + if (keyToIndex.get(key) == null) return null; return getChild(keyToIndex.get(key)); } public Expression get(Constant key) { + if (keyToIndex.get(key.toString()) == null) return null; 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..91dd47d 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,19 @@ return getChild(index); } + public int size() { + return children.size(); + } + + @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/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index a137bf7..a1184ad 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -15,6 +15,7 @@ import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.JsonAccessor; +import models.dataConstraintModel.JsonTerm; import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; import models.dataConstraintModel.StateTransition; @@ -135,16 +136,21 @@ if (stream.checkNext().equals(RIGHT_CURLY_BRACKET)) return null; boolean isNative = false; - String channelOrInitKeyword = stream.next(); - if (channelOrInitKeyword.equals(NATIVE)) { + String channelOrInitOrNativeKeyword = stream.next(); + if (channelOrInitOrNativeKeyword.equals(NATIVE)) { // A native channel isNative = true; - channelOrInitKeyword = stream.next(); + channelOrInitOrNativeKeyword = stream.next(); } - if (!channelOrInitKeyword.equals(CHANNEL) && !channelOrInitKeyword.equals(SUB_CHANNEL)) { - if (!channelOrInitKeyword.equals(INIT)) throw new ExpectedChannel(stream.getLine()); + if (!channelOrInitOrNativeKeyword.equals(CHANNEL) && !channelOrInitOrNativeKeyword.equals(SUB_CHANNEL)) { + if (!channelOrInitOrNativeKeyword.equals(INIT)) throw new ExpectedChannel(stream.getLine()); parseInit(model); - channelOrInitKeyword = stream.next(); + channelOrInitOrNativeKeyword = stream.next(); + if (channelOrInitOrNativeKeyword.equals(NATIVE)) { + // A native channel + isNative = true; + channelOrInitOrNativeKeyword = stream.next(); + } } if (!stream.hasNext()) throw new ExpectedChannelName(stream.getLine()); @@ -326,6 +332,7 @@ int arity = 0; do { stream.next(); // LEFT_BRACKET or COMMA + if (stream.checkNext().equals(RIGHT_BRACKET)) break; arity++; Expression subTerm = parseTerm(stream, model); term.addChild(subTerm, true); @@ -522,21 +529,35 @@ } } +// private Expression parseJsonTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { +// Term jsonTerm = new Constant(DataConstraintModel.nil); +// jsonTerm.setType(DataConstraintModel.typeJson); +// while (stream.checkNext() != null && !stream.checkNext().equals(RIGHT_CURLY_BRACKET)) { +// String key = stream.next(); +// Constant keyExp = new Constant(key); +// keyExp.setType(DataConstraintModel.typeString); +// if (stream.checkNext() == null || !stream.checkNext().equals(COLON)) throw new ExpectedColon(stream.getLine()); +// String colon = stream.next(); +// Expression value = parseTerm(stream, model); +// Term nextTerm = new Term(DataConstraintModel.addMember); +// nextTerm.addChild(jsonTerm); +// nextTerm.addChild(keyExp); +// nextTerm.addChild(value); +// jsonTerm = nextTerm; +// if (stream.checkNext() == null || !stream.checkNext().equals(COMMA)) break; +// String comma = stream.next(); +// } +// return jsonTerm; +// } + private Expression parseJsonTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { - Term jsonTerm = new Constant(DataConstraintModel.nil); - jsonTerm.setType(DataConstraintModel.typeJson); + JsonTerm jsonTerm = new JsonTerm(); while (stream.checkNext() != null && !stream.checkNext().equals(RIGHT_CURLY_BRACKET)) { String key = stream.next(); - Constant keyExp = new Constant(key); - keyExp.setType(DataConstraintModel.typeString); if (stream.checkNext() == null || !stream.checkNext().equals(COLON)) throw new ExpectedColon(stream.getLine()); String colon = stream.next(); Expression value = parseTerm(stream, model); - Term nextTerm = new Term(DataConstraintModel.addMember); - nextTerm.addChild(jsonTerm); - nextTerm.addChild(keyExp); - nextTerm.addChild(value); - jsonTerm = nextTerm; + jsonTerm.addMember(key, value); if (stream.checkNext() == null || !stream.checkNext().equals(COMMA)) break; String comma = stream.next(); } @@ -611,6 +632,7 @@ if (stream.checkNext().equals(LEFT_BRACKET)) break; if (stream.checkNext().equals(COLON)) break; } while (stream.next().equals(DOT)); + hierarchy = model.getOrPutResourceHierarchy(hierarchy); return hierarchy; } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java b/AlgebraicDataflowArchitectureModel/src/simulator/ChannelState.java index 9fd4993..ce4424e 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,19 @@ public ReferenceStructure getReferenceStructure(Constant channelParam) { return referenceStructure.get(channelParam); } + + public Object clone() { + ReferenceStructure newReferenceStructure = new ReferenceStructure(); + if (dependingParamAndValues != null) { + 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..14e30bb 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java @@ -1,16 +1,14 @@ 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.Expression; import models.algebra.Type; import models.dataConstraintModel.DataConstraintModel; import models.dataConstraintModel.ResourceHierarchy; -import models.dataConstraintModel.ResourcePath; import simulator.states.*; public class Resource { @@ -20,6 +18,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(); @@ -44,7 +49,12 @@ } } } else { - state = new PrimitiveResourceState((Constant) resourceHierarchy.getInitialValue()); + Expression initValue = resourceHierarchy.getInitialValue(); + if (initValue != null && initValue instanceof Constant) { + state = new PrimitiveResourceState((Constant) resourceHierarchy.getInitialValue()); + } else { + state = new PrimitiveResourceState(null); + } } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java index 2338858..bb90111 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java @@ -31,7 +31,8 @@ public class Simulator { private DataTransferModel model; private SystemState curState; - private Map> nativeReceivers = new HashMap<>(); + private List systemReceivers = new ArrayList<>(); + private Map> nativeReceivers = new HashMap<>(); private Map nativeChannelReceivers = new HashMap<>(); public Simulator(DataTransferModel model) { @@ -48,7 +49,15 @@ for (ResourceHierarchy res: model.getResourceHierarchies()) { if (res.getParent() == null) { // root resource - curState.addResource(new Resource(res)); + Resource resource = new Resource(res); + curState.addResource(resource); + Expression initilValue = res.getInitialValue(); + if (initilValue != null) { + if (initilValue instanceof Term) { + initilValue = ((Term) initilValue).reduce(); + } + curState.updateResourceState(resource.getResourceIdentifier(), initilValue); + } } } for (Channel channel: model.getChannels()) { @@ -80,20 +89,31 @@ fireEvent(inputEvent, curState, nextSystemState); curState = nextSystemState; + for (INativeReceiver receiver: systemReceivers) { + receiver.onReceiveFromModel(inputEvent, nextSystemState); + } return nextSystemState; } + public void addSystemReceiver(INativeReceiver receiver) { + systemReceivers.add(receiver); + } + public void addNativeReceiver(INativeReceiver receiver, DataTransferChannel channel) { nativeChannelReceivers.put(channel, receiver); } public void addNativeReceiver(INativeReceiver receiver, DataTransferChannel channel, Resource resource) { - Map receivers = nativeReceivers.get(channel); + Map receivers = nativeReceivers.get(channel); if (receivers == null) { receivers = new HashMap<>(); nativeReceivers.put(channel, receivers); } - receivers.put(resource, receiver); + receivers.put(resource.getResourceIdentifier(), receiver); + } + + public void removeSystemReceiver(INativeReceiver receiver) { + systemReceivers.remove(receiver); } public void removeNativeReceiver(DataTransferChannel channel) { @@ -101,9 +121,9 @@ } public void removeNativeReceiver(DataTransferChannel channel, Resource resource) { - Map receivers = nativeReceivers.get(channel); + Map receivers = nativeReceivers.get(channel); if (receivers != null) { - receivers.remove(resource); + receivers.remove(resource.getResourceIdentifier()); if (receivers.size() == 0) { nativeReceivers.remove(channel); } @@ -175,10 +195,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); + receiver = nativeReceivers.get(channel).get(event.getInputResource().getResourceIdentifier()); // receiver for the channel and resource + if (receiver != null) receiver.onReceiveFromModel(event, nextSystemState); } } } @@ -189,11 +209,13 @@ IResourceStateValueProvider resourceStateValueProvider = new IResourceStateValueProvider() { @Override public Expression getCurrentStateValueOf(ResourceIdentifier resId) { + if (curSystemState.getResource(resId) == null) return null; return curSystemState.getResource(resId).getState().getValue(); } @Override public Expression getNextStateValueOf(ResourceIdentifier resId) { + if (nextSystemState.getResource(resId).getState() == null) return null; return nextSystemState.getResource(resId).getState().getValue(); } }; diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java index 8f5037e..5f25bdb 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java @@ -13,6 +13,9 @@ import models.algebra.Term; import models.algebra.Type; import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.JsonTerm; +import models.dataConstraintModel.ListTerm; +import models.dataConstraintModel.MapTerm; import models.dataConstraintModel.ResourceHierarchy; import models.dataFlowModel.DataTransferChannel; import simulator.states.CompositeResourceState; @@ -31,8 +34,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() { @@ -70,6 +81,21 @@ Type resType = resourceIdentifier.getResourceStateType(); if (resType != null && DataConstraintModel.typeList.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof ListTerm) { + ListTerm listValue = (ListTerm) resStateValue; + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + ResourceIdentifier createdResource = null; + for (int i = 0; i < listValue.size(); i++) { + Expression childExp = new Constant(Integer.toString(i), DataConstraintModel.typeInt); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.get(i)); + ((ListResourceState) state).addChildState(childInfo.getKey()); + createdResource = childInfo.getValue(); + } + return createdResource; } else if (resStateValue instanceof Term) { Term listValue = (Term) resStateValue; if (listValue.getSymbol().equals(DataConstraintModel.append)) { @@ -77,10 +103,10 @@ ResourceState state = res.getState(); Expression childExp = null; if (state instanceof ListResourceState) { - childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size())); + childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size()), DataConstraintModel.typeInt); } else if (state instanceof PrimitiveResourceState && ((PrimitiveResourceState) state).getValue().getSymbol().equals(DataConstraintModel.nil)) { // If the value of state is nil. - childExp = new Constant("0"); + childExp = new Constant("0", DataConstraintModel.typeInt); ResourceState parentState = res.getParent().getState(); ResourceState newState = new ListResourceState(); if (parentState instanceof CompositeResourceState) { @@ -103,6 +129,36 @@ } } else if (resType != null && DataConstraintModel.typeMap.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof JsonTerm) { + JsonTerm mapValue = (JsonTerm) resStateValue; + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + ResourceIdentifier createdResource = null; + for (String key: mapValue.keySet()) { + Expression childExp = new Constant(key, DataConstraintModel.typeString); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + ((MapResourceState) state).addChildState(key, childInfo.getKey()); + createdResource = childInfo.getValue(); + } + return createdResource; + } else if (resStateValue instanceof MapTerm) { + MapTerm mapValue = (MapTerm) resStateValue; + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + ResourceIdentifier createdResource = null; + for (String key: mapValue.keySet()) { + Expression childExp = new Constant(key, DataConstraintModel.typeString); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + ((MapResourceState) state).addChildState(key, childInfo.getKey()); + createdResource = childInfo.getValue(); + } + return createdResource; } else if (resStateValue instanceof Term) { Term mapValue = (Term) resStateValue; if (mapValue.getSymbol().equals(DataConstraintModel.insert)) { @@ -136,6 +192,33 @@ } } else if (resType != null && DataConstraintModel.typeJson.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof JsonTerm) { + JsonTerm jsonValue = (JsonTerm) resStateValue; + Resource res = getResource(resourceIdentifier); + ResourceState state = res.getState(); + ResourceIdentifier createdResource = null; + for (String key: jsonValue.keySet()) { + String memberName = key.replace("\"", ""); + ResourceHierarchy childResourceHierarchy = null; + for (ResourceHierarchy childRes: resourceIdentifier.getResourceHierarchy().getChildren()) { + if (childRes.getResourceName().equals(memberName)) { + childResourceHierarchy = childRes; + break; + } + } + if (childResourceHierarchy == null) { + childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), memberName); + } + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, memberName, childResourceHierarchy); + Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.get(key)); + ResourceState childState = childInfo.getKey(); + if (res.getChildrenMap() != null && res.getChildrenMap().get(memberName) != null) { + res.getChildrenMap().get(memberName).changeState(childState); + } + ((JsonResourceState) state).addChildState(memberName, childState); + createdResource = childInfo.getValue(); + } + return createdResource; } else if (resStateValue instanceof Term) { Term jsonValue = (Term) resStateValue; Resource res = getResource(resourceIdentifier); @@ -192,19 +275,34 @@ } public Map.Entry createResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { - Type resType = null; - if (resStateValue instanceof Term) { - resType = ((Term) resStateValue).getType(); - resStateValue = ((Term) resStateValue).reduce(); - } +// Type resType = null; +// if (resStateValue instanceof Term) { +// resType = ((Term) resStateValue).getType(); +// resStateValue = ((Term) resStateValue).reduce(); +// } + Type resType = resourceIdentifier.getResourceStateType(); if (resType != null) { if (DataConstraintModel.typeList.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof ListTerm) { + ListTerm listValue = (ListTerm) resStateValue; + ListResourceState state = new ListResourceState(); + Map.Entry createInfo = null; + for (int i = 0; i < listValue.size(); i++) { + Expression childExp = new Constant(Integer.toString(i), DataConstraintModel.typeInt); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, listValue.get(i)); + state.addChildState(childInfo.getKey()); + createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + return createInfo; } else if (resStateValue instanceof Term) { Term listValue = (Term) resStateValue; if (listValue.getSymbol().equals(DataConstraintModel.append)) { ListResourceState state = new ListResourceState(); - Expression childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size())); + Expression childExp = new Constant(Integer.toString(((ListResourceState) state).getChildStates().size()), DataConstraintModel.typeInt); ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, childExp, resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); @@ -215,6 +313,34 @@ } } else if (DataConstraintModel.typeMap.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof JsonTerm) { + JsonTerm mapValue = (JsonTerm) resStateValue; + MapResourceState state = new MapResourceState(); + Map.Entry createInfo = null; + for (String key: mapValue.keySet()) { + Expression childExp = new Constant(key, DataConstraintModel.typeString); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + state.addChildState(key, childInfo.getKey()); + createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + return createInfo; + } else if (resStateValue instanceof MapTerm) { + MapTerm mapValue = (MapTerm) resStateValue; + MapResourceState state = new MapResourceState(); + Map.Entry createInfo = null; + for (String key: mapValue.keySet()) { + Expression childExp = new Constant(key, DataConstraintModel.typeString); + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, + childExp, + resourceIdentifier.getResourceHierarchy().getChildren().iterator().next()); + Map.Entry childInfo = createResourceState(childResourceIdentifier, mapValue.get(key)); + state.addChildState(key, childInfo.getKey()); + createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + return createInfo; } else if (resStateValue instanceof Term) { Term mapValue = (Term) resStateValue; if (mapValue.getSymbol().equals(DataConstraintModel.insert)) { @@ -233,6 +359,33 @@ } } else if (DataConstraintModel.typeJson.isAncestorOf(resType)) { if (resStateValue instanceof Constant) { + } else if (resStateValue instanceof JsonTerm) { + JsonTerm jsonValue = (JsonTerm) resStateValue; + MapResourceState state = new MapResourceState(); + Map.Entry createInfo = null; + for (String key: jsonValue.keySet()) { + String memberName = key.replace("\"", ""); + ResourceHierarchy childResourceHierarchy = null; + for (ResourceHierarchy childRes: resourceIdentifier.getResourceHierarchy().getChildren()) { + if (childRes.getResourceName().equals(memberName)) { + childResourceHierarchy = childRes; + break; + } + } + if (childResourceHierarchy == null) { + childResourceHierarchy = new ResourceHierarchy(resourceIdentifier.getResourceHierarchy(), memberName); + } + ResourceIdentifier childResourceIdentifier = new ResourceIdentifier(resourceIdentifier, memberName, childResourceHierarchy); + Map.Entry childInfo = createResourceState(childResourceIdentifier, jsonValue.get(key)); + ResourceState childState = childInfo.getKey(); + Resource res = getResource(resourceIdentifier); + if (res != null && res.getChildrenMap() != null && res.getChildrenMap().get(memberName) != null) { + res.getChildrenMap().get(memberName).changeState(childState); + } + state.addChildState(memberName, childState); + createInfo = new AbstractMap.SimpleEntry<>(state, childInfo.getValue()); + } + return createInfo; } else if (resStateValue instanceof Term) { Term jsonValue = (Term) resStateValue; JsonResourceState state = new JsonResourceState(); 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/ComponentHeightReceiver.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentHeightReceiver.java new file mode 100644 index 0000000..9d6aad1 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentHeightReceiver.java @@ -0,0 +1,35 @@ +package simulator.interfaces.swing; + +import java.awt.Component; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.text.JTextComponent; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import simulator.Event; +import simulator.SystemState; +import simulator.interfaces.INativeReceiver; + +public class ComponentHeightReceiver implements INativeReceiver { + protected Component component; + + public ComponentHeightReceiver(Component component) { + this.component = component; + } + + @Override + public void onReceiveFromModel(Event event, SystemState nextSystemState) { + Expression message = event.getMessage(); + if (message instanceof Term) { + Expression height = ((Term) message).getChild(0); + if (height instanceof Constant) { + int curWidth = component.getSize().width; + component.setSize(curWidth, Integer.parseInt(height.toString())); + } + } + } + +} 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/ComponentWidthReceiver.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentWidthReceiver.java new file mode 100644 index 0000000..76c0dda --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentWidthReceiver.java @@ -0,0 +1,35 @@ +package simulator.interfaces.swing; + +import java.awt.Component; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.text.JTextComponent; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import simulator.Event; +import simulator.SystemState; +import simulator.interfaces.INativeReceiver; + +public class ComponentWidthReceiver implements INativeReceiver { + protected Component component; + + public ComponentWidthReceiver(Component component) { + this.component = component; + } + + @Override + public void onReceiveFromModel(Event event, SystemState nextSystemState) { + Expression message = event.getMessage(); + if (message instanceof Term) { + Expression width = ((Term) message).getChild(0); + if (width instanceof Constant) { + int curHeight = component.getSize().height; + component.setSize(Integer.parseInt(width.toString()), curHeight); + } + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentXReceiver.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentXReceiver.java new file mode 100644 index 0000000..2867e97 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentXReceiver.java @@ -0,0 +1,35 @@ +package simulator.interfaces.swing; + +import java.awt.Component; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.text.JTextComponent; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import simulator.Event; +import simulator.SystemState; +import simulator.interfaces.INativeReceiver; + +public class ComponentXReceiver implements INativeReceiver { + protected Component component; + + public ComponentXReceiver(Component component) { + this.component = component; + } + + @Override + public void onReceiveFromModel(Event event, SystemState nextSystemState) { + Expression message = event.getMessage(); + if (message instanceof Term) { + Expression x = ((Term) message).getChild(0); + if (x instanceof Constant) { + int curY = component.getLocation().y; + component.setLocation(Integer.parseInt(x.toString()), curY); + } + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentYReceiver.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentYReceiver.java new file mode 100644 index 0000000..a964f6b --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentYReceiver.java @@ -0,0 +1,35 @@ +package simulator.interfaces.swing; + +import java.awt.Component; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.text.JTextComponent; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import simulator.Event; +import simulator.SystemState; +import simulator.interfaces.INativeReceiver; + +public class ComponentYReceiver implements INativeReceiver { + protected Component component; + + public ComponentYReceiver(Component component) { + this.component = component; + } + + @Override + public void onReceiveFromModel(Event event, SystemState nextSystemState) { + Expression message = event.getMessage(); + if (message instanceof Term) { + Expression y = ((Term) message).getChild(0); + if (y instanceof Constant) { + int curX = component.getLocation().x; + component.setLocation(curX, Integer.parseInt(y.toString())); + } + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java index f8b3b2e..e935244 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java @@ -1,6 +1,7 @@ package simulator.interfaces.swing; import java.awt.Component; +import java.awt.FlowLayout; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -11,7 +12,9 @@ import javax.swing.JPanel; import javax.swing.JTextField; +import models.algebra.Constant; import models.algebra.Expression; +import models.algebra.Term; import models.dataConstraintModel.JsonTerm; import models.dataConstraintModel.MapTerm; import models.dataConstraintModel.ResourcePath; @@ -19,110 +22,381 @@ import simulator.Event; import simulator.Resource; import simulator.Simulator; +import simulator.SystemState; import simulator.interfaces.INativeReceiver; public class SwingPresenter implements INativeReceiver { + // Native channel names. public final String screenUpdateChannelName = "ScreenUpdate"; + public final String setLayoutChannelName = "SetLayout"; public final String setVisibleChannelName = "SetVisible"; + public final String setTextChannelName = "SetText"; + public final String setXChannelName = "SetX"; + public final String setYChannelName = "SetY"; + public final String setWidthChannelName = "SetWidth"; + public final String setHeightChannelName = "SetHeight"; public final String mouseEventChannelName = "MouseEvent"; public final String textEventChannelName = "TextEvent"; protected JPanel mainPanel; protected Simulator simulator; protected Map components; + + // Native channels. protected DataTransferChannel screenUpdateChannel; + protected DataTransferChannel setLayoutChannel; protected DataTransferChannel setVisibleChannel; + protected DataTransferChannel setTextChannel; + protected DataTransferChannel setXChannel; + protected DataTransferChannel setYChannel; + protected DataTransferChannel setWidthChannel; + protected DataTransferChannel setHeightChannel; 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; this.simulator = simulator; + components = new HashMap<>(); screenUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(screenUpdateChannelName); + setLayoutChannel = (DataTransferChannel) simulator.getModel().getChannel(setLayoutChannelName); setVisibleChannel = (DataTransferChannel) simulator.getModel().getChannel(setVisibleChannelName); - mouseEventChannel = (DataTransferChannel) simulator.getModel().getChannel(mouseEventChannelName); - textEventChannel = (DataTransferChannel) simulator.getModel().getChannel(textEventChannelName); + setTextChannel = (DataTransferChannel) simulator.getModel().getChannel(setTextChannelName); + setXChannel = (DataTransferChannel) simulator.getModel().getChannel(setXChannelName); + setYChannel = (DataTransferChannel) simulator.getModel().getChannel(setYChannelName); + setWidthChannel = (DataTransferChannel) simulator.getModel().getChannel(setWidthChannelName); + setHeightChannel = (DataTransferChannel) simulator.getModel().getChannel(setHeightChannelName); + mouseEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(mouseEventChannelName); + textEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(textEventChannelName); simulator.addNativeReceiver(this, screenUpdateChannel); + simulator.addNativeReceiver(new SwingLayout(), setLayoutChannel); } @Override - public void onReceiveFromModel(Event event) { + public void onReceiveFromModel(Event event, SystemState nextSystemState) { Expression message = event.getMessage(); - if (message instanceof JsonTerm) { - // Remove old native receivers. - for (DataTransferChannel channel: channelAndResourcesForReceiving.keySet()) { - for (Resource resource: channelAndResourcesForReceiving.get(channel)) { - simulator.removeNativeReceiver(channel, resource); + 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 newLayout = nextSc.get("layout"); + if (newLayout != null) { + if (newLayout.toString().equals("true")) { + mainPanel.setLayout(new FlowLayout()); + } else if (newLayout.toString().equals("false")) { + mainPanel.setLayout(null); + } } - } - 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) { - 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().toString()); - 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); - } - resources.add(widgetsResource); - } else if (type.toString().equals("label")) { - // Add a label component. - Expression text = widget.get("\"text\""); - JLabel label = new JLabel(text.toString().toString()); - 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(); - 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); + 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); + } + } + } + + // 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\""); + Expression x = widget.get("\"x\""); + Expression y = widget.get("\"y\""); + Expression width = widget.get("\"width\""); + Expression height = widget.get("\"height\""); + JButton button = new JButton(text.toString().replace("\"", "")); + if (x != null && y != null) { + button.setLocation(Integer.parseInt(x.toString()), Integer.parseInt(y.toString())); + } + if (width != null && height != null) { + button.setSize(Integer.parseInt(width.toString()), Integer.parseInt(height.toString())); + } + 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, widgetResource); + + 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, widgetResource); + + Resource widgetXResource = widgetResource.getChildrenMap().get("\"x\""); + if (widgetXResource != null) { + ComponentXReceiver nativeXReceiver = new ComponentXReceiver(button); // widgetResource => button + simulator.addNativeReceiver(nativeXReceiver, setXChannel, widgetXResource); + resources = channelAndResourcesForReceiving.get(setXChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setXChannel, resources); + } + resources.put(newWid, widgetXResource); + } + + Resource widgetYResource = widgetResource.getChildrenMap().get("\"y\""); + if (widgetYResource != null) { + ComponentYReceiver nativeYReceiver = new ComponentYReceiver(button); // widgetResource => button + simulator.addNativeReceiver(nativeYReceiver, setYChannel, widgetYResource); + resources = channelAndResourcesForReceiving.get(setYChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setYChannel, resources); + } + resources.put(newWid, widgetYResource); + } + + Resource widgetWidthResource = widgetResource.getChildrenMap().get("\"width\""); + if (widgetWidthResource != null) { + ComponentWidthReceiver nativeWidthReceiver = new ComponentWidthReceiver(button); // widgetResource => button + simulator.addNativeReceiver(nativeWidthReceiver, setWidthChannel, widgetWidthResource); + resources = channelAndResourcesForReceiving.get(setWidthChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setWidthChannel, resources); + } + resources.put(newWid, widgetWidthResource); + } + + Resource widgetHeightResource = widgetResource.getChildrenMap().get("\"height\""); + if (widgetHeightResource != null) { + ComponentHeightReceiver nativeHeightReceiver = new ComponentHeightReceiver(button); // widgetResource => button + simulator.addNativeReceiver(nativeHeightReceiver, setHeightChannel, widgetHeightResource); + resources = channelAndResourcesForReceiving.get(setHeightChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setHeightChannel, resources); + } + resources.put(newWid, widgetHeightResource); + } + } else if (type.toString().equals("\"label\"")) { + // Add a label component. + Expression text = widget.get("\"text\""); + Expression x = widget.get("\"x\""); + Expression y = widget.get("\"y\""); + Expression width = widget.get("\"width\""); + Expression height = widget.get("\"height\""); + JLabel label = new JLabel(text.toString().replace("\"", "")); + if (x != null && y != null) { + label.setLocation(Integer.parseInt(x.toString()), Integer.parseInt(y.toString())); + } + if (width != null && height != null) { + label.setSize(Integer.parseInt(width.toString()), Integer.parseInt(height.toString())); + } + 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, widgetResource); + + 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, widgetResource); + + Resource widgetXResource = widgetResource.getChildrenMap().get("x"); + if (widgetXResource != null) { + ComponentXReceiver nativeXReceiver = new ComponentXReceiver(label); // widgetResource => label + simulator.addNativeReceiver(nativeXReceiver, setXChannel, widgetXResource); + resources = channelAndResourcesForReceiving.get(setXChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setXChannel, resources); + } + resources.put(newWid, widgetXResource); + } + + Resource widgetYResource = widgetResource.getChildrenMap().get("y"); + if (widgetYResource != null) { + ComponentYReceiver nativeYReceiver = new ComponentYReceiver(label); // widgetResource => label + simulator.addNativeReceiver(nativeYReceiver, setYChannel, widgetYResource); + resources = channelAndResourcesForReceiving.get(setYChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setYChannel, resources); + } + resources.put(newWid, widgetYResource); + } + + Resource widgetWidthResource = widgetResource.getChildrenMap().get("width"); + if (widgetWidthResource != null) { + ComponentWidthReceiver nativeWidthReceiver = new ComponentWidthReceiver(label); // widgetResource => label + simulator.addNativeReceiver(nativeWidthReceiver, setWidthChannel, widgetWidthResource); + resources = channelAndResourcesForReceiving.get(setWidthChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setWidthChannel, resources); + } + resources.put(newWid, widgetWidthResource); + } + + Resource widgetHeightResource = widgetResource.getChildrenMap().get("height"); + if (widgetHeightResource != null) { + ComponentHeightReceiver nativeHeightReceiver = new ComponentHeightReceiver(label); // widgetResource => label + simulator.addNativeReceiver(nativeHeightReceiver, setHeightChannel, widgetHeightResource); + resources = channelAndResourcesForReceiving.get(setHeightChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setHeightChannel, resources); + } + resources.put(newWid, widgetHeightResource); + } + } else if (type.toString().equals("\"textInput\"")) { + // Add a text input component. + Expression x = widget.get("\"x\""); + Expression y = widget.get("\"y\""); + Expression width = widget.get("\"width\""); + Expression height = widget.get("\"height\""); + JTextField textField = new JTextField(10); + if (x != null && y != null) { + textField.setLocation(Integer.parseInt(x.toString()), Integer.parseInt(y.toString())); + } + if (width != null && height != null) { + textField.setSize(Integer.parseInt(width.toString()), Integer.parseInt(height.toString())); + } + 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, widgetResource); + + Resource widgetXResource = widgetResource.getChildrenMap().get("x"); + if (widgetXResource != null) { + ComponentXReceiver nativeXReceiver = new ComponentXReceiver(textField); // widgetResource => textField + simulator.addNativeReceiver(nativeXReceiver, setXChannel, widgetXResource); + resources = channelAndResourcesForReceiving.get(setXChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setXChannel, resources); + } + resources.put(newWid, widgetXResource); + } + + Resource widgetYResource = widgetResource.getChildrenMap().get("y"); + if (widgetYResource != null) { + ComponentYReceiver nativeYReceiver = new ComponentYReceiver(textField); // widgetResource => textField + simulator.addNativeReceiver(nativeYReceiver, setYChannel, widgetYResource); + resources = channelAndResourcesForReceiving.get(setYChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setYChannel, resources); + } + resources.put(newWid, widgetYResource); + } + + Resource widgetWidthResource = widgetResource.getChildrenMap().get("width"); + if (widgetWidthResource != null) { + ComponentWidthReceiver nativeWidthReceiver = new ComponentWidthReceiver(textField); // widgetResource => textField + simulator.addNativeReceiver(nativeWidthReceiver, setWidthChannel, widgetWidthResource); + resources = channelAndResourcesForReceiving.get(setWidthChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setWidthChannel, resources); + } + resources.put(newWid, widgetWidthResource); + } + + Resource widgetHeightResource = widgetResource.getChildrenMap().get("height"); + if (widgetHeightResource != null) { + ComponentHeightReceiver nativeHeightReceiver = new ComponentHeightReceiver(textField); // widgetResource => textField + simulator.addNativeReceiver(nativeHeightReceiver, setHeightChannel, widgetHeightResource); + resources = channelAndResourcesForReceiving.get(setHeightChannel); + if (resources == null) { + resources = new HashMap<>(); + channelAndResourcesForReceiving.put(setHeightChannel, resources); + } + resources.put(newWid, widgetHeightResource); + } + } + } + } + mainPanel.invalidate(); + mainPanel.validate(); + mainPanel.repaint(); } } } } } + + public class SwingLayout implements INativeReceiver { + + @Override + public void onReceiveFromModel(Event event, SystemState nextSystemState) { + Expression message = event.getMessage(); + if (message instanceof Term && ((Term) message).getChildren().size() >= 1) { + Expression newLayout = ((Term) message).getChild(0); + if (newLayout instanceof Constant) { + if (newLayout.toString().equals("true")) { + mainPanel.setLayout(new FlowLayout()); + } else if (newLayout.toString().equals("false")) { + mainPanel.setLayout(null); + } + } + } + } + + } } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/timers/TimerEventSender.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/timers/TimerEventSender.java new file mode 100644 index 0000000..1dce61c --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/timers/TimerEventSender.java @@ -0,0 +1,24 @@ +package simulator.interfaces.timers; + +import models.algebra.Expression; +import models.algebra.Term; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferChannel; +import simulator.Resource; +import simulator.Simulator; +import simulator.interfaces.NativeSender; + +public class TimerEventSender extends NativeSender implements Runnable { + + public TimerEventSender(Simulator simulator, DataTransferChannel channel, ResourcePath resourcePath, Resource resource) { + super(simulator, channel, resourcePath, resource); + } + + @Override + public void run() { + Expression message = channel.getOutputChannelMembers().iterator().next().getStateTransition().getMessageExpression(); + message = (Expression) message.clone(); + sendToModel(message); + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/timers/TimerService.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/timers/TimerService.java new file mode 100644 index 0000000..70d6b51 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/timers/TimerService.java @@ -0,0 +1,139 @@ +package simulator.interfaces.timers; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.ScheduledThreadPoolExecutor; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import models.dataConstraintModel.JsonTerm; +import models.dataConstraintModel.MapTerm; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferChannel; +import simulator.Event; +import simulator.Resource; +import simulator.Simulator; +import simulator.SystemState; +import simulator.interfaces.INativeReceiver; + +public class TimerService implements INativeReceiver { + public final String timersUpdatedChannelName = "TimersUpdated"; + public final String timerEventChannelName = "TimerEvent"; + + protected final Simulator simulator; + protected final Map timers; + protected DataTransferChannel timersUpdatedChannel; + protected DataTransferChannel timerEventChannel; + + public TimerService(Simulator simulator) { + this.simulator = simulator; + timers = new HashMap<>(); + timersUpdatedChannel = (DataTransferChannel) simulator.getModel().getChannel(timersUpdatedChannelName); + timerEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(timerEventChannelName); + simulator.addNativeReceiver(this, timersUpdatedChannel); + } + + @Override + public void onReceiveFromModel(Event event, SystemState nextSystemState) { + Expression message = event.getMessage(); + if (message instanceof Term && ((Term) message).getChildren().size() >= 2) { + Expression curTimersExp = ((Term) message).getChild(0); + Expression nextTimersExp = ((Term) message).getChild(1); + if (curTimersExp instanceof MapTerm && nextTimersExp instanceof MapTerm) { + MapTerm curTimers = (MapTerm) curTimersExp; + MapTerm nextTimers = (MapTerm) nextTimersExp; + Set oldTidSet = new HashSet<>(curTimers.keySet()); + Set newTidSet = new HashSet<>(nextTimers.keySet()); + oldTidSet.removeAll(nextTimers.keySet()); + newTidSet.removeAll(curTimers.keySet()); + if (!oldTidSet.isEmpty() || !newTidSet.isEmpty()) { + // If the set of timers is changed. + + // Remove old timers and their native receivers. + for (String tid: oldTidSet) { + ScheduledThreadPoolExecutor timer = timers.get(tid); + timer.shutdown(); + timers.remove(tid); + } + + // Add new timers. + Resource timersResource = nextSystemState.getResource(event.getInputResource().getResourceIdentifier()); + for (String tid: newTidSet) { + Expression value = nextTimers.get(tid); + if (value instanceof JsonTerm) { + JsonTerm timerValue = (JsonTerm) value; + Resource timerResource = timersResource.getChildrenMap().get(tid); + // Add a timer. + Expression intervalExp = timerValue.get("\"interval\""); + long interval = Long.parseLong(((Constant) intervalExp).toString()); + ScheduledThreadPoolExecutor timer = new ScheduledThreadPoolExecutor(0); + timers.put(tid, timer); + + // Connect Java timer and model. + ResourcePath resPath = timerEventChannel.getOutputResources().iterator().next(); + TimerEventSender sender = new TimerEventSender(simulator, timerEventChannel, resPath, timerResource); // timer => timerResource + timer.scheduleAtFixedRate(sender, 0, interval, TimeUnit.MILLISECONDS); + } + } + } + } + } + } + + public class TimerStart implements INativeReceiver { + public final String timerStartChannelName = "TimerStart"; + protected DataTransferChannel timerStartChannel; + protected DataTransferChannel timerEventChannel; + + public TimerStart() { + timerStartChannel = (DataTransferChannel) simulator.getModel().getChannel(timerStartChannelName); + timerEventChannel = (DataTransferChannel) simulator.getModel().getInputChannel(timerEventChannelName); + simulator.addNativeReceiver(this, timerStartChannel); + } + + @Override + public void onReceiveFromModel(Event event, SystemState nextSystemState) { + Expression message = event.getMessage(); + if (message instanceof Term && ((Term) message).getChildren().size() >= 1) { + Expression tidExp = event.getInputResource().getResourceIdentifier().getLastParam(); + Expression intervalExp = ((Term) message).getChild(0); + if (tidExp instanceof Constant && intervalExp instanceof Constant) { + String tid = ((Constant) tidExp).toString(); + long interval = Long.parseLong(((Constant) intervalExp).toString()); + ScheduledThreadPoolExecutor timer = timers.get(tid); + TimerEventSender sender = new TimerEventSender(simulator, timerEventChannel, event.getInputResourcePath(), event.getInputResource()); + timer.scheduleAtFixedRate(sender, 0, interval, TimeUnit.MILLISECONDS); + } + } + } + } + + public class TimerClear implements INativeReceiver { + public final String timerClearChannelName = "TimerClear"; + protected DataTransferChannel timerClearChannel; + + public TimerClear() { + timerClearChannel = (DataTransferChannel) simulator.getModel().getChannel(timerClearChannelName); + simulator.addNativeReceiver(this, timerClearChannel); + } + + @Override + public void onReceiveFromModel(Event event, SystemState nextSystemState) { + Expression message = event.getMessage(); + if (message instanceof Term && ((Term) message).getChildren().size() >= 1) { + Expression tidExp = event.getInputResource().getResourceIdentifier().getLastParam(); + if (tidExp instanceof Constant) { + String tid = ((Constant) tidExp).toString(); + ScheduledThreadPoolExecutor timer = timers.get(tid); + timer.shutdown(); + timers.remove(tid); + } + } + } + + } +} 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 022a32f..34eff54 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java @@ -9,19 +9,16 @@ import models.algebra.Expression; import models.algebra.Term; import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ListTerm; public class ListResourceState extends CompositeResourceState { private List children = new ArrayList<>(); @Override public Expression getValue() { - Term value = new Constant(DataConstraintModel.nil); - value.setType(DataConstraintModel.typeList); + ListTerm value = new ListTerm(); for (ResourceState child: children) { - Term newTerm = new Term(DataConstraintModel.append); - newTerm.addChild(value); - newTerm.addChild(child.getValue()); - value = newTerm; + value.append(child.getValue()); } return value; } @@ -48,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 5bd2fc7..6071c51 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/MapResourceState.java @@ -7,20 +7,17 @@ import models.algebra.Expression; import models.algebra.Term; import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.MapTerm; public class MapResourceState extends CompositeResourceState { private Map children = new HashMap<>(); @Override public Expression getValue() { - Term value = new Constant(DataConstraintModel.nil); + MapTerm value = new MapTerm(); value.setType(DataConstraintModel.typeMap); for (Map.Entry childEnt: children.entrySet()) { - Term newTerm = new Term(DataConstraintModel.insert); - newTerm.addChild(value); - newTerm.addChild(new Constant(childEnt.getKey(), DataConstraintModel.typeString)); - newTerm.addChild(childEnt.getValue().getValue()); - value = newTerm; + value.insert(childEnt.getKey(), childEnt.getValue().getValue()); } return value; } @@ -42,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); }