diff --git a/AlgebraicDataflowArchitectureModel/models/SimpleUI.model b/AlgebraicDataflowArchitectureModel/models/SimpleUI.model new file mode 100644 index 0000000..f393c9d --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/models/SimpleUI.model @@ -0,0 +1,19 @@ +native channel ScreenUpdate { + in screen(curSc: Json, update(nextSc)) = nextSc +} + +native channel SetVisible(wid: Str) { + in screen.widgets.{wid}.visible(curVisible: Bool, setVisible(nextVisible)) = nextVisible +} + +native channel SetText(wid: Str) { + in screen.widgets.{wid}.text(curText: Str, setText(nextText)) = nextText +} + +native channel MouseEvent(wid: Str) { + out screen.widgets.{wid}.state(curState: Int, mouseEvent(nextState)) = nextState +} + +native channel TextEvent(wid: Str) { + out screen.widgets.{wid}.text(curText: Str, textEvent(nextText)) = nextText +} diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java b/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java index 69fe530..f54aea4 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/DataTransferModelAnalyzer.java @@ -24,7 +24,7 @@ */ static public DataFlowGraph createDataFlowGraphWithStateStoringAttribute(DataTransferModel model) { DataFlowGraph graph = model.getDataFlowGraph(); - Collection channels = new HashSet<>(model.getIOChannels()); + Collection channels = new HashSet<>(model.getInputChannels()); channels.addAll(model.getChannels()); for (Channel channel: channels) { for (ChannelMember member: ((DataTransferChannel) channel).getOutputChannelMembers()) { diff --git a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java index 5f63542..1be6a1d 100644 --- a/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java +++ b/AlgebraicDataflowArchitectureModel/src/algorithms/TypeInference.java @@ -146,7 +146,7 @@ mapComponentTypes.put(DataConstraintModel.typeMap, Arrays.asList(new Type[] { null, null })); // 1. Collect type information from the architecture model. - Collection channels = new HashSet<>(model.getIOChannels()); + Collection channels = new HashSet<>(model.getInputChannels()); channels.addAll(model.getChannels()); for (Channel c : channels) { for (ChannelMember cm : c.getChannelMembers()) { diff --git a/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java b/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java index 37aeefe..6a0684b 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java +++ b/AlgebraicDataflowArchitectureModel/src/application/SimulatorWindow.java @@ -23,6 +23,7 @@ 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; @@ -125,7 +126,9 @@ setSize(870,640); setVisible(true); - simulator = new Simulator(this.editor.getModel()); + 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)); } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/DataTransferModelingCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/DataTransferModelingCellEditor.java index 7ded3d9..fa88e8d 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/DataTransferModelingCellEditor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/DataTransferModelingCellEditor.java @@ -69,7 +69,7 @@ DataTransferModel model = editor.getModel(); DataTransferChannel ch = (DataTransferChannel) model.getChannel((String) ((mxCell) cell).getValue()); if (ch == null) { - ch = (DataTransferChannel) model.getIOChannel((String) ((mxCell) cell).getValue()); + ch = (DataTransferChannel) model.getInputChannel((String) ((mxCell) cell).getValue()); if(ch == null) { //resource return; diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java index 18960d8..6fe7965 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -341,7 +341,7 @@ fileString += "\tnode r " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; } - for (Channel ioC: model.getIOChannels()) { + for (Channel ioC: model.getInputChannels()) { if(ioC instanceof Channel && state.getLabel().equals(ioC.getChannelName())) { fileString += "\tnode ioc " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; } @@ -637,7 +637,7 @@ } public void addIOChannel(DataTransferChannel ioChannelGen) { - getModel().addIOChannel(ioChannelGen); + getModel().addInputChannel(ioChannelGen); resetDataFlowGraph(); graph.getModel().beginUpdate(); Object parent = graph.getDefaultParent(); @@ -686,7 +686,7 @@ DataTransferModel model = getModel(); Channel srcCh = model.getChannel((String) src.getValue()); if (srcCh == null) { - srcCh = model.getIOChannel((String) src.getValue()); + srcCh = model.getInputChannel((String) src.getValue()); if (srcCh == null) { ResourcePath srcRes = model.getResourcePath((String) src.getValue()); Channel dstCh = model.getChannel((String) dst.getValue()); @@ -723,7 +723,7 @@ // channel to resource edge Channel ch = model.getChannel(srcName); if (ch == null) { - ch = model.getIOChannel(srcName); + ch = model.getInputChannel(srcName); } ch.removeChannelMember(model.getResourcePath(dstName)); } @@ -731,8 +731,8 @@ String name = (String) cell.getValue(); if (model.getChannel(name) != null) { model.removeChannel(name); - } else if (model.getIOChannel(name) != null) { - model.removeIOChannel(name); + } else if (model.getInputChannel(name) != null) { + model.removeInputChannel(name); } else if (model.getResourcePath(name) != null) { model.removeResourcePath(name); } @@ -786,23 +786,25 @@ public Set> getResourceDependencyForChannel(DataTransferChannel ch, DataTransferModel model, DataFlowGraph dataFlowGraph) { Set> resourceDpendency = new HashSet<>(); - try { - Map>> dependency = ch.fillOutsideResourcePaths(ch.getOutputChannelMembers().iterator().next(), JavaCodeGenerator.pullAccessor); - for (ChannelMember srcMem: dependency.keySet()) { - ResourceNode srcNode = dataFlowGraph.getResourceNode(srcMem.getResource()); - if (srcNode != null) { - for (ChannelMember dstMem: dependency.get(srcMem).getValue()) { - ResourceNode dstNode = dataFlowGraph.getResourceNode(dstMem.getResource()); - while (srcNode.getResourceHierarchy().getNumParameters() == 0 && srcNode.getParent() != null) { - srcNode = srcNode.getParent(); + if (ch.getOutputChannelMembers().size() > 0) { + try { + Map>> dependency = ch.fillOutsideResourcePaths(ch.getOutputChannelMembers().iterator().next(), JavaCodeGenerator.pullAccessor); + for (ChannelMember srcMem: dependency.keySet()) { + ResourceNode srcNode = dataFlowGraph.getResourceNode(srcMem.getResource()); + if (srcNode != null) { + for (ChannelMember dstMem: dependency.get(srcMem).getValue()) { + ResourceNode dstNode = dataFlowGraph.getResourceNode(dstMem.getResource()); + while (srcNode.getResourceHierarchy().getNumParameters() == 0 && srcNode.getParent() != null) { + srcNode = srcNode.getParent(); + } + resourceDpendency.add(new AbstractMap.SimpleEntry<>(srcNode, dstNode)); } - resourceDpendency.add(new AbstractMap.SimpleEntry<>(srcNode, dstNode)); } } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage + | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); } - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage - | UnificationFailed | ValueUndefined e) { - e.printStackTrace(); } return resourceDpendency; } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/InputEventCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/InputEventCellEditor.java index e21a902..e945773 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/InputEventCellEditor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/InputEventCellEditor.java @@ -110,7 +110,7 @@ ArrayList eventMessages = new ArrayList<>();//messageList ResourcePath eventResPath = null; - for(Channel ch : simulator.getModel().getIOChannels()) {//all channel + 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(); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index d086ffb..ab82982 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -1212,7 +1212,7 @@ String resComponentName = langSpec.toComponentName(resName); List constructorStatements = new ArrayList<>(); Map> inputStatements = new HashMap<>(); - for (Channel ch : model.getIOChannels()) { + for (Channel ch : model.getInputChannels()) { for (ChannelMember out : ((DataTransferChannel) ch).getOutputChannelMembers()) { if (resourceNode.getInSideResources().contains(out.getResource())) { Expression message = out.getStateTransition().getMessageExpression(); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index 1a57882..e86cc63 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -626,7 +626,7 @@ } // Declare the input method in this component and the main component. - for (Channel ch : model.getIOChannels()) { + for (Channel ch : model.getInputChannels()) { for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { if (resourceNode.getInSideResources().contains(cm.getResource())) { Expression message = cm.getStateTransition().getMessageExpression(); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index 9dfadd7..08bc6ec 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -908,7 +908,7 @@ private static Map> getIOChannelsAndMembers(ResourceHierarchy resource, DataTransferModel model) { Map> ioChannelsAndMembers = new HashMap<>(); - for (Channel c: model.getIOChannels()) { + for (Channel c: model.getInputChannels()) { DataTransferChannel ch = (DataTransferChannel) c; // I/O channel for (ChannelMember out: ch.getOutputChannelMembers()) { @@ -929,7 +929,7 @@ private static List getInputMethods(TypeDeclaration component, ResourceNode resource, DataTransferModel model) { List inputs = new ArrayList<>(); - for (Channel c: model.getIOChannels()) { + for (Channel c: model.getInputChannels()) { DataTransferChannel channel = (DataTransferChannel) c; // I/O channel for (ChannelMember out: channel.getOutputChannelMembers()) { @@ -944,7 +944,7 @@ private static List getInputMethods(TypeDeclaration component, ResourceHierarchy resource, DataTransferModel model) { List inputs = new ArrayList<>(); - for (Channel c: model.getIOChannels()) { + for (Channel c: model.getInputChannels()) { DataTransferChannel channel = (DataTransferChannel) c; // I/O channel for (ChannelMember out: channel.getOutputChannelMembers()) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index 512ac90..78a04d2 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -710,7 +710,7 @@ } // Declare the input method in each resource and the root resource. - for (Channel ch : model.getIOChannels()) { + for (Channel ch : model.getInputChannels()) { for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { if (!cm.isOutside()) { if (priorMemberForInputChannel.get(ch) == null) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index e20b7ff..4efb2dd 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -1210,7 +1210,7 @@ private static Map> getIOChannelsAndMembers(ResourceHierarchy resource, DataTransferModel model) { Map> ioChannelsAndMembers = new HashMap<>(); - for (Channel c: model.getIOChannels()) { + for (Channel c: model.getInputChannels()) { DataTransferChannel ch = (DataTransferChannel) c; // I/O channel for (ChannelMember out: ch.getOutputChannelMembers()) { @@ -1231,7 +1231,7 @@ private static List getInputMethods(TypeDeclaration component, ResourceNode resource, DataTransferModel model) { List inputs = new ArrayList<>(); - for (Channel c: model.getIOChannels()) { + for (Channel c: model.getInputChannels()) { DataTransferChannel channel = (DataTransferChannel) c; // I/O channel for (ChannelMember out: channel.getOutputChannelMembers()) { diff --git a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java index 7f69a35..1b5a6ac 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java +++ b/AlgebraicDataflowArchitectureModel/src/models/algebra/Term.java @@ -53,6 +53,12 @@ children.add(child); return true; } + + public boolean setChild(int n, Expression child) { + if (getArity() != -1 && n >= getArity()) return false; + children.set(n, child); + return true; + } public void addChild(Expression child, boolean bForced) { if (!bForced && getArity() != -1 && children.size() >= getArity()) return; diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java index f27e54c..4e71af2 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/Channel.java @@ -15,6 +15,7 @@ protected List selectors = null; protected Set channelMembers = null; protected String sourceText = null; + protected boolean isNative = false; public Channel(String channelName) { this.channelName = channelName; @@ -142,4 +143,12 @@ } return sourceText; } + + public boolean isNative() { + return isNative; + } + + public void setNative(boolean isNative) { + this.isNative = isNative; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java index c169b2a..eb5e29e 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/DataConstraintModel.java @@ -18,7 +18,7 @@ protected List resourcePaths = null; protected HashMap resourceHierarchies = null; protected HashMap channels = null; - protected HashMap ioChannels = null; + protected HashMap inputChannels = null; protected HashMap types = null; protected HashMap symbols = null; public static final Type typeInt = new Type("Int", "int"); @@ -463,6 +463,14 @@ } term = (Term) term.getChild(0); } + if (term instanceof ListTerm) { + for (Expression element: term.getChildren()) { + if (element.equals(args.get(1))) { + return new Constant(true_); + } + } + return new Constant(false_); + } } else if (typeMap.isAncestorOf(type)) { while (term.getSymbol().equals(DataConstraintModel.insert)) { if (term.getChild(1).equals(args.get(1))) { @@ -473,6 +481,12 @@ } term = (Term) term.getChild(0); } + if (term instanceof MapTerm) { + if (((MapTerm) term).keySet().contains(args.get(1).toString())) { + return new Constant(true_); + } + return new Constant(false_); + } } else if (typeJson.isAncestorOf(type)) { while (term.getSymbol().equals(DataConstraintModel.addMember)) { if (term.getChild(1).equals(args.get(1))) { @@ -483,6 +497,12 @@ } term = (Term) term.getChild(0); } + if (term instanceof JsonTerm) { + if (((JsonTerm) term).keySet().contains(args.get(1).toString())) { + return new Constant(true_); + } + return new Constant(false_); + } } } return new Constant(false_); @@ -683,7 +703,7 @@ resourcePaths = new ArrayList<>(); resourceHierarchies = new HashMap<>(); channels = new HashMap<>(); - ioChannels = new HashMap<>(); + inputChannels = new HashMap<>(); types = new HashMap<>(); addType(typeInt); addType(typeLong); @@ -803,7 +823,7 @@ for (Channel ch: channels.values()) { ch.removeChannelMember(resourcePath); } - for (Channel ch: ioChannels.values()) { + for (Channel ch: inputChannels.values()) { ch.removeChannelMember(resourcePath); } } @@ -828,24 +848,24 @@ channels.remove(channelName); } - public Collection getIOChannels() { - return ioChannels.values(); + public Collection getInputChannels() { + return inputChannels.values(); } - public Channel getIOChannel(String channelName) { - return ioChannels.get(channelName); + public Channel getInputChannel(String channelName) { + return inputChannels.get(channelName); } - public void setIOChannels(HashMap ioChannels) { - this.ioChannels = ioChannels; + public void setInputChannels(HashMap inputChannels) { + this.inputChannels = inputChannels; } - public void addIOChannel(Channel ioChannel) { - ioChannels.put(ioChannel.getChannelName(), ioChannel); + public void addInputChannel(Channel inputChannel) { + inputChannels.put(inputChannel.getChannelName(), inputChannel); } - public void removeIOChannel(String ioChannelName) { - ioChannels.remove(ioChannelName); + public void removeInputChannel(String inputChannelName) { + inputChannels.remove(inputChannelName); } public void addType(Type type) { @@ -914,7 +934,7 @@ @Override public String toString() { String out = ""; - for (Channel channel: ioChannels.values()) { + for (Channel channel: inputChannels.values()) { out += channel.toString(); } for (Channel channel: channels.values()) { @@ -935,7 +955,7 @@ if (init.length() > 0) { out += "init {\n" + init + "}\n"; } - for (Channel channel: ioChannels.values()) { + for (Channel channel: inputChannels.values()) { out += channel.getSourceText(); } for (Channel channel: channels.values()) { diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonAccessor.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonAccessor.java index c84207e..85994f2 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonAccessor.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonAccessor.java @@ -51,6 +51,9 @@ } private Expression getValue(Term json, Constant key) { + if (json instanceof JsonTerm) { + return ((JsonTerm) json).get(key); + } if (!json.getSymbol().equals(DataConstraintModel.addMember)) return null; if (json.getChild(1).equals(key)) { return json.getChild(2); diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonTerm.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonTerm.java new file mode 100644 index 0000000..6c5d1eb --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/JsonTerm.java @@ -0,0 +1,50 @@ +package models.dataConstraintModel; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Term; + +public class JsonTerm extends Term { + private Map keyToIndex = new HashMap<>(); + + public JsonTerm() { + super(new Symbol("json", -1)); + setType(DataConstraintModel.typeJson); + } + + public void addMember(String key, Expression value) { + if (keyToIndex.containsKey(key)) { + setChild(keyToIndex.get(key), value); + } else { + keyToIndex.put(key, getChildren().size()); + addChild(value); + } + } + + public Set keySet() { + return keyToIndex.keySet(); + } + + public Expression get(String key) { + return getChild(keyToIndex.get(key)); + } + + public Expression get(Constant key) { + return getChild(keyToIndex.get(key.toString())); + } + + public String toString() { + String jsonStr = "{"; + String delim = ""; + for (String key: keyToIndex.keySet()) { + jsonStr += delim + key + ": " + getChild(keyToIndex.get(key)).toString(); + delim = ", "; + } + return jsonStr + "}"; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ListTerm.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ListTerm.java new file mode 100644 index 0000000..d70d476 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/ListTerm.java @@ -0,0 +1,31 @@ +package models.dataConstraintModel; + +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Term; + +public class ListTerm extends Term { + + public ListTerm() { + super(new Symbol("list", -1)); + setType(DataConstraintModel.typeList); + } + + public void append(Expression value) { + addChild(value); + } + + public Expression get(int index) { + return getChild(index); + } + + public String toString() { + String listStr = "["; + String delim = ""; + for (Expression child: getChildren()) { + listStr += delim + child.toString(); + delim = ", "; + } + return listStr + "]"; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/MapTerm.java b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/MapTerm.java new file mode 100644 index 0000000..34792f6 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/models/dataConstraintModel/MapTerm.java @@ -0,0 +1,50 @@ +package models.dataConstraintModel; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Symbol; +import models.algebra.Term; + +public class MapTerm extends Term { + private Map keyToIndex = new HashMap<>(); + + public MapTerm() { + super(new Symbol("map", -1)); + setType(DataConstraintModel.typeMap); + } + + public void insert(String key, Expression value) { + if (keyToIndex.containsKey(key)) { + setChild(keyToIndex.get(key), value); + } else { + keyToIndex.put(key, getChildren().size()); + addChild(value); + } + } + + public Set keySet() { + return keyToIndex.keySet(); + } + + public Expression get(String key) { + return getChild(keyToIndex.get(key)); + } + + public Expression get(Constant key) { + return getChild(keyToIndex.get(key.toString())); + } + + public String toString() { + String mapStr = "{"; + String delim = ""; + for (String key: keyToIndex.keySet()) { + mapStr += delim + key + ": " + getChild(keyToIndex.get(key)).toString(); + delim = ", "; + } + return mapStr + "}"; + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java index e851d06..b27156b 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferModel.java @@ -20,7 +20,7 @@ for (Channel channel: getChannels()) { addChannelToResourceEdges(dataFlowGraph, channel, null, channelLocalResMap); } - for (Channel channel: getIOChannels()) { + for (Channel channel: getInputChannels()) { addChannelToResourceEdges(dataFlowGraph, channel, null, channelLocalResMap); } return dataFlowGraph; diff --git a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index 9f9ea4a..a137bf7 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -46,6 +46,7 @@ public static final String OUT = "out"; public static final String REF = "ref"; public static final String SUB_CHANNEL = "sub"; + public static final String NATIVE = "native"; public static final String LEFT_CURLY_BRACKET = "{"; public static final String RIGHT_CURLY_BRACKET = "}"; public static final String LEFT_CURLY_BRACKET_REGX = "\\{"; @@ -117,7 +118,7 @@ DataTransferChannel channel; while ((channel = parseChannel(model)) != null) { if (channel.getInputChannelMembers().size() == 0) { - model.addIOChannel(channel); + model.addInputChannel(channel); } else { model.addChannel(channel); } @@ -133,7 +134,13 @@ if (!stream.hasNext()) return null; if (stream.checkNext().equals(RIGHT_CURLY_BRACKET)) return null; + boolean isNative = false; String channelOrInitKeyword = stream.next(); + if (channelOrInitKeyword.equals(NATIVE)) { + // A native channel + isNative = true; + channelOrInitKeyword = stream.next(); + } if (!channelOrInitKeyword.equals(CHANNEL) && !channelOrInitKeyword.equals(SUB_CHANNEL)) { if (!channelOrInitKeyword.equals(INIT)) throw new ExpectedChannel(stream.getLine()); parseInit(model); @@ -146,6 +153,9 @@ int fromLine = stream.getLine(); DataTransferChannel channel = new DataTransferChannel(channelName); + if (isNative) { + channel.setNative(true); + } String leftBracket = stream.next(); if (leftBracket.equals(LEFT_BRACKET)) { // has a selector diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java index 13df0a0..b0bce8c 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Event.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Event.java @@ -26,10 +26,10 @@ private Expression message; private boolean isInput = false; private ResourcePath inputResourcePath = null; + private Resource inputResource = null; private List> channelSelectorAndValues = new ArrayList<>(); private Map dependingParameters = new HashMap<>(); - private Set inputResources = new HashSet<>(); private Set outputResources = new HashSet<>(); private Set succEvents = new HashSet<>(); private Map> channelSelectorToInputResourcePathParam = new HashMap<>(); @@ -63,7 +63,7 @@ this.channel = channel; this.isInput = false; this.inputResourcePath = inputResPath; - this.inputResources.add(inputResource); + this.inputResource = inputResource; connectChannelSelectorAndPathParameters(); // Extract channel parameters from the input resource. @@ -91,7 +91,7 @@ this.channel = channel; this.isInput = false; this.inputResourcePath = inputResPath; - this.inputResources.add(inputResource); + this.inputResource = inputResource; connectChannelSelectorAndPathParameters(); // Extract channel parameters from the input resource. @@ -198,6 +198,35 @@ // Calculate message constraints from leaf channel members on the channel member dependency graph. Map> dependency = channel.getMemberDependency(); + if (dependency.size() == 0) { + // No channel member dependency. + Expression messageConstraint = null; + for (ChannelMember channelMember: channel.getInputChannelMembers()) { + // Calculate message constraint from an input state transition + messageConstraint = channel.calcMessageConstraintForInputMember(channelMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + if (unifiedMessage == null) { + unifiedMessage = (Term) messageConstraint; + } else { + unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); + if (unifiedMessage == null) { + throw new UnificationFailed(); + } + } + } + for (ChannelMember channelMember: channel.getReferenceChannelMembers()) { + // Calculate message constraint from a reference state transition + messageConstraint = channel.calcMessageConstraintForReferenceMember(channelMember, null, resouceStateAccessor, null, substitutedPositionsInMessageFromChannels); + if (unifiedMessage == null) { + unifiedMessage = (Term) messageConstraint; + } else { + unifiedMessage = (Term) unifiedMessage.unify(messageConstraint); + if (unifiedMessage == null) { + throw new UnificationFailed(); + } + } + } + return unifiedMessage; + } Set toResolve = new HashSet<>(); Set resolved = new HashSet<>(); for (Set depended: dependency.values()) { @@ -293,8 +322,8 @@ return inputResourcePath; } - public Set getInputResources() { - return inputResources; + public Resource getInputResource() { + return inputResource; } public Set getOutputResources() { diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java index 83b5eb6..c88b684 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Resource.java @@ -1,6 +1,8 @@ package simulator; import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -13,7 +15,7 @@ public class Resource { private Resource parent = null; - private List children = null; + private Map children = null; private ResourceHierarchy resourceHierarchy = null; private ResourceState state = null; private Constant parameter = null; @@ -34,11 +36,11 @@ } else { // Json resource state = new JsonResourceState(); - children = new ArrayList<>(); + children = new LinkedHashMap<>(); for (ResourceHierarchy child: resourceHierarchy.getChildren()) { Resource cRes = new Resource(child, this); ((JsonResourceState) state).addChildState(child.getResourceName(), cRes.getState()); - children.add(cRes); + children.put(child.getResourceName(), cRes); } } } else { @@ -102,11 +104,15 @@ public Constant getParameter() { return parameter; } + + public Collection getChildren() { + return getChildrenMap().values(); + } - public List getChildren() { - List children = null; + public Map getChildrenMap() { + Map children = null; if (resourceHierarchy.getChildren().size() > 0) { - children = new ArrayList<>(); + children = new LinkedHashMap<>(); ResourceHierarchy childRes = resourceHierarchy.getChildren().iterator().next(); if (childRes.getNumParameters() > 0) { // List or Map type. @@ -118,9 +124,9 @@ ResourceState childState = childEnt.getValue(); Type thisType = resourceHierarchy.getResourceStateType(); if (DataConstraintModel.typeList.isAncestorOf(thisType)) { - children.add(new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeInt), childState)); + children.put(childParam, new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeInt), childState)); } else if (DataConstraintModel.typeMap.isAncestorOf(thisType)) { - children.add(new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeString), childState)); + children.put(childParam, new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeString), childState)); } } } @@ -139,7 +145,7 @@ } } if (DataConstraintModel.typeJson.isAncestorOf(thisType)) { - children.add(new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeString), childState)); + children.put(childParam, new Resource(childRes, this, new Constant(childParam, DataConstraintModel.typeString), childState)); } } this.children = children; diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java index 7d902c5..2338858 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/Simulator.java @@ -26,10 +26,13 @@ import models.dataFlowModel.DataTransferChannel; import models.dataFlowModel.DataTransferChannel.IResourceStateAccessor; import simulator.Event.IResourceStateValueProvider; +import simulator.interfaces.INativeReceiver; public class Simulator { private DataTransferModel model; private SystemState curState; + private Map> nativeReceivers = new HashMap<>(); + private Map nativeChannelReceivers = new HashMap<>(); public Simulator(DataTransferModel model) { this.model = model; @@ -79,6 +82,33 @@ curState = nextSystemState; return nextSystemState; } + + 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); + if (receivers == null) { + receivers = new HashMap<>(); + nativeReceivers.put(channel, receivers); + } + receivers.put(resource, receiver); + } + + public void removeNativeReceiver(DataTransferChannel channel) { + nativeChannelReceivers.remove(channel); + } + + public void removeNativeReceiver(DataTransferChannel channel, Resource resource) { + Map receivers = nativeReceivers.get(channel); + if (receivers != null) { + receivers.remove(resource); + if (receivers.size() == 0) { + nativeReceivers.remove(channel); + } + } + } /** * Fire an given event and construct the next system state from the current system state. @@ -142,6 +172,14 @@ updatedOutResId = (ResourceIdentifier) updatedOutResId.getParent(); } } + } 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 (nativeReceivers.get(channel) != null) { + receiver = nativeReceivers.get(channel).get(event.getInputResource()); // receiver for the channel and resource + if (receiver != null) receiver.onReceiveFromModel(event); + } } } @@ -180,7 +218,7 @@ for (ChannelMember dependedMem: invDependency.keySet()) { if (inResPath == dependedMem.getResource()) { // If some depending resources are to be updated by the update of an depended input resource. - final Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId)); + Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId)); nextEvent.updateDependingParameters(resourceStateValueProvider); if (nextChState == null) { nextChState = new ChannelState(channel); @@ -193,6 +231,11 @@ nextEvents.add(nextEvent); } } + if (invDependency.size() == 0) { + Event nextEvent = new Event(channel, inResPath, nextSystemState.getResource(inResId)); + nextEvent.setMessage(nextEvent.updateDependingParameters(resourceStateValueProvider)); + nextEvents.add(nextEvent); + } if (nextChState != null) { for (ChannelMember dependingMem: dependency.keySet()) { if (inResPath == dependingMem.getResource()) { diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java index 2221b0e..8f5037e 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/SystemState.java @@ -59,6 +59,13 @@ return null; } + /** + * update the state of a specified resource + * + * @param resourceIdentifier a resource identifier to identify the resource + * @param resStateValue a new state of the resource + * @return + */ public ResourceIdentifier updateResourceState(ResourceIdentifier resourceIdentifier, Expression resStateValue) { Type resType = resourceIdentifier.getResourceStateType(); if (resType != null && DataConstraintModel.typeList.isAncestorOf(resType)) { diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/INativeReceiver.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/INativeReceiver.java new file mode 100644 index 0000000..50e651e --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/INativeReceiver.java @@ -0,0 +1,7 @@ +package simulator.interfaces; + +import simulator.Event; + +public interface INativeReceiver { + public void onReceiveFromModel(Event event); +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/NativeSender.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/NativeSender.java new file mode 100644 index 0000000..a286401 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/NativeSender.java @@ -0,0 +1,40 @@ +package simulator.interfaces; + +import java.util.HashSet; +import java.util.Set; + +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.ResourcePath; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import simulator.Event; +import simulator.Resource; +import simulator.Simulator; + +abstract public class NativeSender { + protected Simulator simulator; + protected DataTransferChannel channel; + protected ResourcePath resourcePath; + protected Resource resource; + + public NativeSender(Simulator simulator, DataTransferChannel channel, ResourcePath resourcePath, Resource resource) { + this.simulator = simulator; + this.channel = channel; + this.resourcePath = resourcePath; + this.resource = resource; + } + + public void sendToModel(Expression message) { + try { + Event event = new Event(channel, message, resourcePath, resource); + simulator.transition(event); + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentMouseSender.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentMouseSender.java new file mode 100644 index 0000000..f90d46b --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentMouseSender.java @@ -0,0 +1,47 @@ +package simulator.interfaces.swing; + +import java.awt.Component; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferChannel; +import simulator.Resource; +import simulator.Simulator; +import simulator.interfaces.NativeSender; + +public class ComponentMouseSender extends NativeSender implements MouseListener { + + public ComponentMouseSender(Simulator simulator, DataTransferChannel channel, ResourcePath resourcePath, Resource resource) { + super(simulator, channel, resourcePath, resource); + } + + public void mouseClicked(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + Constant one = new Constant("1", DataConstraintModel.typeInt); + Expression message = channel.getOutputChannelMembers().iterator().next().getStateTransition().getMessageExpression(); + message = (Term) message.clone(); + ((Term) message).setChild(0, one); + sendToModel(message); + } + + public void mouseReleased(MouseEvent e) { + Constant zero = new Constant("0", DataConstraintModel.typeInt); + Expression message = channel.getOutputChannelMembers().iterator().next().getStateTransition().getMessageExpression(); + message = (Term) message.clone(); + ((Term) message).setChild(0, zero); + sendToModel(message); + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextReceiver.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextReceiver.java new file mode 100644 index 0000000..e110a67 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextReceiver.java @@ -0,0 +1,39 @@ +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.interfaces.INativeReceiver; + +public class ComponentTextReceiver implements INativeReceiver { + protected Component component; + + public ComponentTextReceiver(Component component) { + this.component = component; + } + + @Override + public void onReceiveFromModel(Event event) { + Expression message = event.getMessage(); + if (message instanceof Term) { + Expression text = ((Term) message).getChild(0); + if (text instanceof Constant) { + if (component instanceof JTextComponent) { + ((JTextComponent) component).setText(((Constant) text).getSymbol().getName()); + } else if (component instanceof JLabel) { + ((JLabel) component).setText(((Constant) text).getSymbol().getName()); + } else if (component instanceof JButton) { + ((JButton) component).setText(((Constant) text).getSymbol().getName()); + } + } + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextSender.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextSender.java new file mode 100644 index 0000000..4e13f41 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentTextSender.java @@ -0,0 +1,36 @@ +package simulator.interfaces.swing; + +import java.awt.TextField; +import java.awt.event.InputMethodEvent; +import java.awt.event.InputMethodListener; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferChannel; +import simulator.Resource; +import simulator.Simulator; +import simulator.interfaces.NativeSender; + +public class ComponentTextSender extends NativeSender implements InputMethodListener { + + 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); + } + + @Override + public void caretPositionChanged(InputMethodEvent event) { + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentVisibilityReceiver.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentVisibilityReceiver.java new file mode 100644 index 0000000..2527a52 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/ComponentVisibilityReceiver.java @@ -0,0 +1,34 @@ +package simulator.interfaces.swing; + +import java.awt.Component; + +import models.algebra.Constant; +import models.algebra.Expression; +import models.algebra.Term; +import models.dataConstraintModel.DataConstraintModel; +import simulator.Event; +import simulator.interfaces.INativeReceiver; + +public class ComponentVisibilityReceiver implements INativeReceiver { + protected Component component; + + public ComponentVisibilityReceiver(Component component) { + this.component = component; + } + + @Override + public void onReceiveFromModel(Event event) { + Expression message = event.getMessage(); + if (message instanceof Term) { + Expression visible = ((Term) message).getChild(0); + if (visible instanceof Constant) { + if (((Constant) visible).getSymbol() == DataConstraintModel.true_) { + component.setVisible(true); + } else { + component.setVisible(false); + } + } + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java new file mode 100644 index 0000000..f8b3b2e --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/simulator/interfaces/swing/SwingPresenter.java @@ -0,0 +1,128 @@ +package simulator.interfaces.swing; + +import java.awt.Component; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import models.algebra.Expression; +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.interfaces.INativeReceiver; + +public class SwingPresenter implements INativeReceiver { + public final String screenUpdateChannelName = "ScreenUpdate"; + public final String setVisibleChannelName = "SetVisible"; + public final String mouseEventChannelName = "MouseEvent"; + public final String textEventChannelName = "TextEvent"; + + protected JPanel mainPanel; + protected Simulator simulator; + protected Map components; + protected DataTransferChannel screenUpdateChannel; + protected DataTransferChannel setVisibleChannel; + protected DataTransferChannel mouseEventChannel; + protected DataTransferChannel textEventChannel; + protected Map> channelAndResourcesForReceiving = new HashMap<>(); + + public SwingPresenter(JPanel mainPanel, Simulator simulator) { + this.mainPanel = mainPanel; + this.simulator = simulator; + screenUpdateChannel = (DataTransferChannel) simulator.getModel().getChannel(screenUpdateChannelName); + setVisibleChannel = (DataTransferChannel) simulator.getModel().getChannel(setVisibleChannelName); + mouseEventChannel = (DataTransferChannel) simulator.getModel().getChannel(mouseEventChannelName); + textEventChannel = (DataTransferChannel) simulator.getModel().getChannel(textEventChannelName); + simulator.addNativeReceiver(this, screenUpdateChannel); + } + + @Override + public void onReceiveFromModel(Event event) { + 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); + } + } + 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); + } + } + } + } + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java index afd1c20..cf4ce2b 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/JsonResourceState.java @@ -7,20 +7,17 @@ import models.algebra.Expression; import models.algebra.Term; import models.dataConstraintModel.DataConstraintModel; +import models.dataConstraintModel.JsonTerm; public class JsonResourceState extends CompositeResourceState { private Map children = new HashMap<>(); @Override public Expression getValue() { - Term value = new Constant(DataConstraintModel.nil); + JsonTerm value = new JsonTerm(); value.setType(DataConstraintModel.typeJson); for (Map.Entry childEnt: children.entrySet()) { - Term newTerm = new Term(DataConstraintModel.addMember); - newTerm.addChild(value); - newTerm.addChild(new Constant(childEnt.getKey(), DataConstraintModel.typeString)); - newTerm.addChild(childEnt.getValue().getValue()); - value = newTerm; + value.addMember(childEnt.getKey(), childEnt.getValue().getValue()); } return value; } diff --git a/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java b/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java index 83367e0..022a32f 100644 --- a/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java +++ b/AlgebraicDataflowArchitectureModel/src/simulator/states/ListResourceState.java @@ -1,9 +1,9 @@ package simulator.states; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; import models.algebra.Constant; import models.algebra.Expression; @@ -28,7 +28,7 @@ @Override public Map getChildStates() { - Map childParams = new HashMap<>(); + Map childParams = new TreeMap<>(); for (int i = 0; i < children.size(); i++) { childParams.put(Integer.toString(i), children.get(i)); } diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java index 238df91..b84e563 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataConstraintModelTest.java @@ -46,14 +46,14 @@ assertEquals(customer_add.getPathParams().get(0), c.getSelectors().iterator().next().getExpression()); assertEquals(company_add.getPathParams().get(0), new Variable("cid")); - model.addIOChannel(cio_setCustomerOff); - model.addIOChannel(cio_setCompanyAdd); + model.addInputChannel(cio_setCustomerOff); + model.addInputChannel(cio_setCompanyAdd); model.addChannel(c); // Check the model. assertEquals(3, model.getResourcePaths().size()); assertEquals(7, model.getResourceHierarchies().size()); - assertEquals(2, model.getIOChannels().size()); + assertEquals(2, model.getInputChannels().size()); assertEquals(1, model.getChannels().size()); } diff --git a/AlgebraicDataflowArchitectureModel/src/tests/DataTransferModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/DataTransferModelTest.java index 5f1b3c3..0f4575b 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/DataTransferModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/DataTransferModelTest.java @@ -63,14 +63,14 @@ assertEquals(company_add.getPathParams().get(0), new Variable("cid")); // Construct a data-flow architecture model. - model.addIOChannel(cio_setCustomerOff); - model.addIOChannel(cio_setCompanyAdd); + model.addInputChannel(cio_setCustomerOff); + model.addInputChannel(cio_setCompanyAdd); model.addChannel(c); // Check the model. assertEquals(3, model.getResourcePaths().size()); assertEquals(7, model.getResourceHierarchies().size()); - assertEquals(2, model.getIOChannels().size()); + assertEquals(2, model.getInputChannels().size()); assertEquals(1, model.getChannels().size()); // Extract the resource dependency graph. diff --git a/AlgebraicDataflowArchitectureModel/src/tests/NativeAccessTest.java b/AlgebraicDataflowArchitectureModel/src/tests/NativeAccessTest.java new file mode 100644 index 0000000..d9598b8 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/tests/NativeAccessTest.java @@ -0,0 +1,101 @@ +package tests; + +import org.junit.Test; + +import algorithms.TypeInference; +import models.algebra.Expression; +import models.algebra.InvalidMessage; +import models.algebra.ParameterizedIdentifierIsFutureWork; +import models.algebra.UnificationFailed; +import models.algebra.ValueUndefined; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourcePath; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; +import parser.Parser; +import parser.Parser.TokenStream; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.WrongJsonExpression; +import simulator.Event; +import simulator.Resource; +import simulator.Simulator; +import simulator.SystemState; +import simulator.interfaces.INativeReceiver; +import simulator.interfaces.NativeSender; + +public class NativeAccessTest { + + @Test + public void test() { + try { + TokenStream stream = new Parser.TokenStream(); + Parser parser = new Parser(stream); + + // Construct a data transfer architecture model. + DataTransferModel model = new DataTransferModel(); + ResourcePath sampleText = new ResourcePath("sampleText"); + model.addResourcePath(sampleText); + + DataTransferChannel nativeInputEventChannel = new DataTransferChannel("NativeInput"); + nativeInputEventChannel.setNative(true); + ChannelMember textIn = new ChannelMember(sampleText); + stream.addLine("curText:Str"); + Expression curStateIn = parser.parseTerm(stream, model); + stream.addLine("input(nextText)"); + Expression messageIn = parser.parseTerm(stream, model); + stream.addLine("nextText"); + Expression nextStateIn = parser.parseTerm(stream, model); + textIn.getStateTransition().setCurStateExpression(curStateIn); + textIn.getStateTransition().setMessageExpression(messageIn); + textIn.getStateTransition().setNextStateExpression(nextStateIn); + nativeInputEventChannel.addChannelMemberAsOutput(textIn); + model.addInputChannel(nativeInputEventChannel); + + DataTransferChannel nativeOutputEventChannel = new DataTransferChannel("NativeOutput"); + nativeOutputEventChannel.setNative(true); + ChannelMember textOut = new ChannelMember(sampleText); + stream.addLine("curText:Str"); + Expression curStateOut = parser.parseTerm(stream, model); + stream.addLine("output(nextText)"); + Expression messageOut = parser.parseTerm(stream, model); + stream.addLine("nextText"); + Expression nextStateOut = parser.parseTerm(stream, model); + textOut.getStateTransition().setCurStateExpression(curStateOut); + textOut.getStateTransition().setMessageExpression(messageOut); + textOut.getStateTransition().setNextStateExpression(nextStateOut); + nativeOutputEventChannel.addChannelMemberAsInput(textOut); + model.addChannel(nativeOutputEventChannel); + TypeInference.infer(model); + + // Create simulator + Simulator simulator = new Simulator(model); + + // Initial state + SystemState initialState = simulator.init(); + Resource ioResource = initialState.getResource("sampleText"); + + // Connect the simulator and native code + NativeSender textSender = new NativeSender(simulator, nativeInputEventChannel, sampleText, ioResource) { // Native code => model + }; + INativeReceiver textReceiver = new INativeReceiver() { // Model to native code + @Override + public void onReceiveFromModel(Event event) { // Receive a message from the model + Expression message = event.getMessage(); + System.out.println(message); + } + }; + simulator.addNativeReceiver(textReceiver, nativeOutputEventChannel); + + stream.addLine("input(\"HelloWorld\")"); + Expression sendMessage = parser.parseTerm(stream, model); + textSender.sendToModel(sendMessage); // Send a message to the model + + } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon e) { + e.printStackTrace(); + } + + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java b/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java index 7c30c68..099c6a6 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/SimplifiedDataFlowModelTest.java @@ -75,14 +75,14 @@ assertEquals(c3.getOutputChannelMembers().size(), 1); // Construct a data-flow architecture model. - model.addIOChannel(cin); + model.addInputChannel(cin); model.addChannel(c1); model.addChannel(c2); model.addChannel(c3); // Check the model. assertEquals(4, model.getResourcePaths().size()); - assertEquals(1, model.getIOChannels().size()); + assertEquals(1, model.getInputChannels().size()); assertEquals(3, model.getChannels().size()); // Extract the resource dependency graph. diff --git a/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java b/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java index cbac9dc..ca760bb 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/SimulatorTest.java @@ -156,8 +156,8 @@ customer_add_2.getStateTransition().setNextStateExpression(nextStateExp6); c.addChannelMemberAsOutput(customer_add_2); - model.addIOChannel(cio_setCustomerOff); - model.addIOChannel(cio_setCompanyAdd); + model.addInputChannel(cio_setCustomerOff); + model.addInputChannel(cio_setCompanyAdd); model.addChannel(c); Simulator simulator = new Simulator(model);