diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java index 28070d2..90bbd0e 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java @@ -36,6 +36,10 @@ @Override public void actionPerformed(ActionEvent e) { DataFlowGraph graph = editor.getDataFlowGraph(); + if (graph == null) { + editor.changeStage(Editor.STAGE_PUSH_PULL_SELECTION); + graph = editor.getDataFlowGraph(); + } if (graph != null) { DataTransferModel model = editor.getModel(); ModelExtension.extendModel(model); diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/JerseyPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/JerseyPrototypeGenerateAction.java index b74075c..25986ec 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/actions/JerseyPrototypeGenerateAction.java +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/JerseyPrototypeGenerateAction.java @@ -37,6 +37,10 @@ @Override public void actionPerformed(ActionEvent e) { DataFlowGraph graph = editor.getDataFlowGraph(); + if (graph == null) { + editor.changeStage(Editor.STAGE_PUSH_PULL_SELECTION); + graph = editor.getDataFlowGraph(); + } if (graph != null) { DataTransferModel model = editor.getModel(); ModelExtension.extendModel(model); diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/SaveAsAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/SaveAsAction.java index 1a38b08..9542cdb 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/actions/SaveAsAction.java +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/SaveAsAction.java @@ -65,9 +65,7 @@ lastDir = fc.getSelectedFile().getParent(); String fileName = fc.getSelectedFile().getAbsolutePath() + extension; - - // checking file duplicates - if(! (fc.getSelectedFile().exists())) editor.setCurFilePath(fileName); + editor.setCurFilePath(fileName); // overwriting file editor.save(); diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java index 1a02eaa..bcf6326 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -17,11 +17,9 @@ import com.mxgraph.layout.mxCircleLayout; import com.mxgraph.layout.mxCompactTreeLayout; import com.mxgraph.model.mxCell; -import com.mxgraph.model.mxGeometry; import com.mxgraph.model.mxGraphModel; import com.mxgraph.model.mxIGraphModel; import com.mxgraph.util.mxConstants; -import com.mxgraph.util.mxPoint; import com.mxgraph.view.mxCellState; import com.mxgraph.util.mxRectangle; import com.mxgraph.view.mxGraph; @@ -29,13 +27,15 @@ import algorithms.DataTransferModelAnalyzer; import algorithms.Validation; +import application.editor.stages.ControlFlowDelegationStage; +import application.editor.stages.DataFlowModelingStage; +import application.editor.stages.PushPullSelectionStage; import application.layouts.*; import code.ast.CompilationUnit; import models.Edge; import models.EdgeAttribute; import models.Node; import models.dataConstraintModel.ChannelGenerator; -import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.IdentifierTemplate; import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.DataTransferChannelGenerator; @@ -45,7 +45,6 @@ import models.dataFlowModel.ResourceNode; import models.visualModel.FormulaChannelGenerator; import parser.Parser; -import parser.Parser.TokenStream; import parser.exceptions.ExpectedAssignment; import parser.exceptions.ExpectedChannel; import parser.exceptions.ExpectedChannelName; @@ -66,58 +65,63 @@ import parser.ParserDTRAM; public class Editor { - final int PORT_DIAMETER = 8; - final int PORT_RADIUS = PORT_DIAMETER / 2; + public DataTransferModel model = null; + public mxGraph graph = null; + protected Stage curStage = null; + protected List stageQueue = null; + protected String curFileName = null; protected String curFilePath = null; protected ArrayList codes = null; - - protected DataTransferModel model = null; - protected mxGraph graph = null; - - protected DataFlowGraph dataFlowGraph = null; - + + public static DataFlowModelingStage STAGE_DATA_FLOW_MODELING = null; + public static PushPullSelectionStage STAGE_PUSH_PULL_SELECTION = null; + public static ControlFlowDelegationStage STAGE_CONTROL_FLOW_DELEGATION = null; public Editor(mxGraph graph) { this.graph = graph; + stageQueue = new ArrayList<>(); + STAGE_DATA_FLOW_MODELING = new DataFlowModelingStage(graph); + STAGE_PUSH_PULL_SELECTION = new PushPullSelectionStage(graph); + STAGE_CONTROL_FLOW_DELEGATION = new ControlFlowDelegationStage(graph); + stageQueue.add(STAGE_DATA_FLOW_MODELING); + stageQueue.add(STAGE_PUSH_PULL_SELECTION); + stageQueue.add(STAGE_CONTROL_FLOW_DELEGATION); + curStage = STAGE_DATA_FLOW_MODELING; } public mxGraph getGraph() { return graph; } - public void setGraph(mxGraph graph) { - this.graph = graph; - } - public DataTransferModel getModel() { - if (model == null) { - model = new DataTransferModel(); - } + model = curStage.getModel(); return model; } + + public Stage getCurStage() { + return curStage; + } + + public boolean nextStage() { + int curStageNo = stageQueue.indexOf(curStage); + if (curStageNo + 1 >= stageQueue.size()) return false; + return changeStage(stageQueue.get(curStageNo + 1)); + } + + public boolean changeStage(Stage nextStage) { + if (!nextStage.canChangeFrom(curStage)) return false; + nextStage.init(curStage); + curStage = nextStage; + return true; + } public DataFlowGraph getDataFlowGraph() { - if (dataFlowGraph == null) { - analyzeDataTransferModel(getModel()); + if (curStage instanceof PushPullSelectionStage) { + return ((PushPullSelectionStage) curStage).getDataFlowGraph(); } - return dataFlowGraph; - } - - public DataFlowGraph analyzeDataTransferModel(DataTransferModel model) { - DataFlowGraph flowGraph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); - dataFlowGraph = DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(flowGraph); - updateEdgeAttiributes(dataFlowGraph); - return dataFlowGraph; - } - - public void resetDataFlowGraph() { - dataFlowGraph = null; - } - - public void setDataFlowGraph(DataFlowGraph dataFlowGraph) { - this.dataFlowGraph = dataFlowGraph; + return null; } public ArrayList getCodes() { @@ -142,9 +146,13 @@ } public void clear() { + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + model = null; - ((mxGraphModel) graph.getModel()).clear(); - dataFlowGraph = null; + ((DataFlowModelingStage) curStage).clear(); + curFilePath = null; curFileName = null; codes = null; @@ -156,28 +164,39 @@ * @return a constructed DataFlowModel */ public DataTransferModel open(File file) { + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return null; + try { - String extension =""; if(file != null && file.exists()) { - // get a file's name + // get file's name String name = file.getName(); - // get a file's extension + // get file's extension extension = name.substring(name.lastIndexOf(".")); } if(extension.contains(".model")) { openModel(file); } else { + // Parse the .dtram file. ParserDTRAM parserDTRAM = new ParserDTRAM(new BufferedReader(new FileReader(file))); - try { + try { model = parserDTRAM.doParseModel(); - graph = constructGraph(model); + if (!Validation.checkUpdateConflict(model)) return null; + if (curStage instanceof DataFlowModelingStage) { + // Update the mxGraph. + ((DataFlowModelingStage) curStage).setModel(model); + } + // Restore the geometry. parserDTRAM.doParseGeometry(graph); + + // Change to the push/pull selection stage, analyze the data transfer model and construct a data-flow graph. + changeStage(STAGE_PUSH_PULL_SELECTION); + curFilePath = file.getAbsolutePath(); curFileName = file.getName(); - if (!Validation.checkUpdateConflict(model)) return null; - analyzeDataTransferModel(model); return model; } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression @@ -193,17 +212,28 @@ } public DataTransferModel openModel(File file) { + // Force to change to data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return null; + try { - + // Parse the .model file. Parser parser = new Parser(new BufferedReader(new FileReader(file))); - try { model = parser.doParse(); + if (!Validation.checkUpdateConflict(model)) return null; + if (curStage instanceof DataFlowModelingStage) { + // Update the mxGraph. + ((DataFlowModelingStage) curStage).setModel(model); + } + // Set DAG layout. + setDAGLayout(); + + // Change to the push/pull selection stage, analyze the data transfer model and construct a data-flow graph. + changeStage(STAGE_PUSH_PULL_SELECTION); + curFilePath = file.getAbsolutePath(); curFileName = file.getName(); - if (!Validation.checkUpdateConflict(model)) return null; - graph = constructGraph(model); - analyzeDataTransferModel(model); return model; } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression @@ -308,90 +338,6 @@ return fileString; } - /** - * Construct a mxGraph from DataFlowModel and DataFlowModel - * @param model - * @param dataFlowGraph - * @return constructed mxGraph - */ - public mxGraph constructGraph(DataTransferModel model) { - ((mxGraphModel) graph.getModel()).clear(); - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - try { - mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo1.setRelative(true); - - mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo2.setRelative(true); - - Map channelsIn = new HashMap<>(); - Map channelsOut = new HashMap<>(); - Map resources = new HashMap<>(); - - // create channel vertices - for (ChannelGenerator c: model.getChannelGenerators()) { - DataTransferChannelGenerator channelGen = (DataTransferChannelGenerator) c; - if (channelsIn.get(channelGen) == null || channelsOut.get(channelGen) == null) { - Object channel = graph.insertVertex(parent, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex - mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); - port_in.setVertex(true); - graph.addCell(port_in, channel); // insert the input port of a channel - mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); - port_out.setVertex(true); - graph.addCell(port_out, channel); // insert the output port of a channel - channelsIn.put(channelGen, port_in); - channelsOut.put(channelGen, port_out); - } - } - - // create resource vertices - for (IdentifierTemplate res: model.getIdentifierTemplates()) { - Object resource = graph.insertVertex(parent, null, - res.getResourceName(), 20, 20, 80, 30, - "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex - resources.put(res, resource); - } - - // add input, output and reference edges - for (ChannelGenerator ch: model.getChannelGenerators()) { - DataTransferChannelGenerator channelGen = (DataTransferChannelGenerator) ch; - // input edge - for (IdentifierTemplate srcRes: channelGen.getInputIdentifierTemplates()) { - graph.insertEdge(parent, null, new SrcDstAttribute(srcRes, channelGen), resources.get(srcRes), channelsIn.get(channelGen), "movable=false"); - } - // output edge - for (IdentifierTemplate dstRes: channelGen.getOutputIdentifierTemplates()) { - graph.insertEdge(parent, null, new SrcDstAttribute(channelGen, dstRes), channelsOut.get(channelGen), resources.get(dstRes), "movable=false"); - } - // reference edges - for (IdentifierTemplate refRes: channelGen.getReferenceIdentifierTemplates()) { - graph.insertEdge(parent, null, null, resources.get(refRes), channelsIn.get(channelGen), "dashed=true;movable=false"); - } - } - - for (ChannelGenerator ioChannelGen: model.getIOChannelGenerators()) { - if (channelsOut.get(ioChannelGen) == null) { - Object channel = graph.insertVertex(parent, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex - mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); - port_out.setVertex(true); - graph.addCell(port_out, channel); // insert the output port of a channel - channelsOut.put((DataTransferChannelGenerator) ioChannelGen, port_out); - for (IdentifierTemplate outRes: ((DataTransferChannelGenerator) ioChannelGen).getOutputIdentifierTemplates()) { - graph.insertEdge(parent, null, null, port_out, resources.get(outRes), "movable=false"); - } - } - } - } finally { - graph.getModel().endUpdate(); - } - setTreeLayout(); - - return graph; - } - public void setDAGLayout() { Object parent = graph.getDefaultParent(); graph.getModel().beginUpdate(); @@ -403,35 +349,6 @@ } } - public void updateEdgeAttiributes(DataFlowGraph dataFlowGraph) { - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - try { - // add input, output and reference edges - for (Edge e : dataFlowGraph.getEdges()) { - if (e instanceof DataFlowEdge) { - DataFlowEdge dataFlow = (DataFlowEdge) e; - DataTransferChannelGenerator channelGen = dataFlow.getChannelGenerator(); - ResourceNode srcRes = (ResourceNode) dataFlow.getSource(); - // input edge - for (Object edge: graph.getChildEdges(parent)) { - mxCell edgeCell = (mxCell) edge; - if (edgeCell.getValue() instanceof SrcDstAttribute) { - SrcDstAttribute edgeAttr = (SrcDstAttribute) edgeCell.getValue(); - if (edgeAttr.getSrouce() == srcRes.getIdentifierTemplate() && edgeAttr.getDestination() == channelGen) { - edgeCell.setValue(dataFlow.getAttribute()); - break; - } - } - } - } - } - } finally { - graph.getModel().endUpdate(); - } - graph.refresh(); - } - public void setTreeLayout() { Object parent = graph.getDefaultParent(); graph.getModel().beginUpdate(); @@ -458,192 +375,66 @@ } public void addIdentifierTemplate(IdentifierTemplate res) { - getModel().addIdentifierTemplate(res); - resetDataFlowGraph(); - graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); - try { - graph.insertVertex(parent, null, res.getResourceName(), 20, 20, 80, 30, - "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex - } finally { - graph.getModel().endUpdate(); - } + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + + ((DataFlowModelingStage) curStage).addIdentifierTemplate(res); + model = ((DataFlowModelingStage) curStage).getModel(); } public void addChannelGenerator(DataTransferChannelGenerator channelGen) { - getModel().addChannelGenerator(channelGen); - resetDataFlowGraph(); - graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); - try { - mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo1.setRelative(true); - - mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo2.setRelative(true); - - Object channel = graph.insertVertex(parent, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex - mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); - port_in.setVertex(true); - graph.addCell(port_in, channel); // insert the input port of a channel - mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); - port_out.setVertex(true); - graph.addCell(port_out, channel); // insert the output port of a channel - } finally { - graph.getModel().endUpdate(); - } + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + + ((DataFlowModelingStage) curStage).addChannelGenerator(channelGen); + model = ((DataFlowModelingStage) curStage).getModel(); } public void addIOChannelGenerator(DataTransferChannelGenerator ioChannelGen) { - getModel().addIOChannelGenerator(ioChannelGen); - resetDataFlowGraph(); - graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); - try { - mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo2.setRelative(true); - - Object channel = graph.insertVertex(parent, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex - mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); - port_out.setVertex(true); - graph.addCell(port_out, channel); // insert the output port of a channel - } finally { - graph.getModel().endUpdate(); - } + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + + ((DataFlowModelingStage) curStage).addIOChannelGenerator(ioChannelGen); + model = ((DataFlowModelingStage) curStage).getModel(); } public void addFormulaChannelGenerator(FormulaChannelGenerator formulaChannelGen) { - getModel().addChannelGenerator(formulaChannelGen); - resetDataFlowGraph(); - graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); - try { - mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo1.setRelative(true); - - mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); - geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); - geo2.setRelative(true); - - Object channel = graph.insertVertex(parent, null, formulaChannelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex - mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); - port_in.setVertex(true); - graph.addCell(port_in, channel); // insert the input port of a channel - mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); - port_out.setVertex(true); - graph.addCell(port_out, channel); // insert the output port of a channel - } finally { - graph.getModel().endUpdate(); - } + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + + ((DataFlowModelingStage) curStage).addFormulaChannelGenerator(formulaChannelGen); + model = ((DataFlowModelingStage) curStage).getModel(); } public boolean connectEdge(mxCell edge, mxCell src, mxCell dst) { - DataTransferModel model = getModel(); - ChannelGenerator srcCh = model.getChannelGenerator((String) src.getValue()); - if (srcCh == null) { - srcCh = model.getIOChannelGenerator((String) src.getValue()); - if (srcCh == null) { - IdentifierTemplate srcRes = model.getIdentifierTemplate((String) src.getValue()); - ChannelGenerator dstCh = model.getChannelGenerator((String) dst.getValue()); - if (srcRes == null || dstCh == null) return false; - // resource to channel edge - ChannelMember srcCm = new ChannelMember(srcRes); - ((DataTransferChannelGenerator ) dstCh).addChannelMemberAsInput(srcCm); - edge.setValue(new SrcDstAttribute(srcRes, dstCh)); - resetDataFlowGraph(); - return true; - } - } - IdentifierTemplate dstRes = model.getIdentifierTemplate((String) dst.getValue()); - if (dstRes == null) return false; - // channel to resource edge - ChannelMember dstCm = new ChannelMember(dstRes); - ((DataTransferChannelGenerator) srcCh).addChannelMemberAsOutput(dstCm); - edge.setValue(new SrcDstAttribute(srcCh, dstRes)); - resetDataFlowGraph(); - return true; + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return false; + + return ((DataFlowModelingStage) curStage).connectEdge(edge, src, dst); } public void delete() { - for (Object obj: graph.getSelectionCells()) { - mxCell cell = (mxCell) obj; - if (cell.isEdge()) { - String srcName = (String) cell.getSource().getValue(); - String dstName = (String) cell.getTarget().getValue(); - if (model.getIdentifierTemplate(srcName) != null) { - // resource to channel edge - ChannelGenerator ch = model.getChannelGenerator(dstName); - ch.removeChannelMember(model.getIdentifierTemplate(srcName)); - } else if (model.getIdentifierTemplate(dstName) != null) { - // channel to resource edge - ChannelGenerator ch = model.getChannelGenerator(srcName); - if (ch == null) { - ch = model.getIOChannelGenerator(srcName); - } - ch.removeChannelMember(model.getIdentifierTemplate(dstName)); - } - } else if (cell.isVertex()) { - String name = (String) cell.getValue(); - if (model.getChannelGenerator(name) != null) { - model.removeChannelGenerator(name); - } else if (model.getIOChannelGenerator(name) != null) { - model.removeIOChannelGenerator(name); - } else if (model.getIdentifierTemplate(name) != null) { - model.removeIdentifierTemplate(name); - } - } - } - graph.removeCells(graph.getSelectionCells()); - resetDataFlowGraph(); + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; + + ((DataFlowModelingStage) curStage).delete(); } public void setChannelCode(DataTransferChannelGenerator ch, String code) { - ch.setSourceText(code); - TokenStream stream = new Parser.TokenStream(); - Parser parser = new Parser(stream); + // Force to change to the data-flow modeling stage. + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) return; - for (String line: code.split("\n")) { - stream.addLine(line); - } - try { - DataTransferChannelGenerator ch2 = parser.parseChannel(getModel()); - for (ChannelMember chm2: ch2.getInputChannelMembers()) { - for (ChannelMember chm: ch.getInputChannelMembers()) { - if (chm2.getIdentifierTemplate() == chm.getIdentifierTemplate()) { - chm.setStateTransition(chm2.getStateTransition()); - break; - } - } - } - for (ChannelMember chm2: ch2.getOutputChannelMembers()) { - for (ChannelMember chm: ch.getOutputChannelMembers()) { - if (chm2.getIdentifierTemplate() == chm.getIdentifierTemplate()) { - chm.setStateTransition(chm2.getStateTransition()); - break; - } - } - } - for (ChannelMember chm2: ch2.getReferenceChannelMembers()) { - for (ChannelMember chm: ch.getReferenceChannelMembers()) { - if (chm2.getIdentifierTemplate() == chm.getIdentifierTemplate()) { - chm.setStateTransition(chm2.getStateTransition()); - break; - } - } - } - resetDataFlowGraph(); - } catch (ExpectedRightBracket | ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket - | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression - | WrongLHSExpression | WrongRHSExpression | ExpectedAssignment e) { - e.printStackTrace(); - } + ((DataFlowModelingStage) curStage).setChannelCode(ch, code); } - private class SrcDstAttribute extends EdgeAttribute { + public static class SrcDstAttribute extends EdgeAttribute { private Object src; private Object dst; diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java new file mode 100644 index 0000000..46e3b6b --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java @@ -0,0 +1,21 @@ +package application.editor; + +import com.mxgraph.view.mxGraph; + +import models.dataFlowModel.DataTransferModel; + +abstract public class Stage { + protected DataTransferModel model = null; + protected mxGraph graph = null; + + public Stage(mxGraph graph) { + this.graph = graph; + } + + public DataTransferModel getModel() { + return model; + } + + abstract public boolean canChangeFrom(Stage prevStage); + abstract public void init(Stage prevStage); +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java new file mode 100644 index 0000000..d4c0538 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/ControlFlowDelegationStage.java @@ -0,0 +1,29 @@ +package application.editor.stages; + +import com.mxgraph.view.mxGraph; + +import application.editor.Stage; +import models.dataFlowModel.DataFlowGraph; + +public class ControlFlowDelegationStage extends Stage { + private DataFlowGraph dataFlowGraph; + + public ControlFlowDelegationStage(mxGraph graph) { + super(graph); + } + + @Override + public boolean canChangeFrom(Stage prevStage) { + if (prevStage instanceof PushPullSelectionStage) return true; + return false; + } + + @Override + public void init(Stage prevStage) { + if (prevStage instanceof PushPullSelectionStage) { + model = ((PushPullSelectionStage) prevStage).getModel(); + dataFlowGraph = ((PushPullSelectionStage) prevStage).getDataFlowGraph(); + } + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java new file mode 100644 index 0000000..7cb3d55 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java @@ -0,0 +1,330 @@ +package application.editor.stages; + +import java.util.HashMap; +import java.util.Map; + +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGeometry; +import com.mxgraph.model.mxGraphModel; +import com.mxgraph.util.mxPoint; +import com.mxgraph.view.mxGraph; + +import application.editor.Stage; +import application.editor.Editor; +import application.editor.Editor.SrcDstAttribute; +import models.dataConstraintModel.ChannelGenerator; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.IdentifierTemplate; +import models.dataFlowModel.DataTransferChannelGenerator; +import models.dataFlowModel.DataTransferModel; +import models.visualModel.FormulaChannelGenerator; +import parser.Parser; +import parser.Parser.TokenStream; +import parser.exceptions.ExpectedAssignment; +import parser.exceptions.ExpectedChannel; +import parser.exceptions.ExpectedChannelName; +import parser.exceptions.ExpectedEquals; +import parser.exceptions.ExpectedInOrOutOrRefKeyword; +import parser.exceptions.ExpectedLeftCurlyBracket; +import parser.exceptions.ExpectedRHSExpression; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.ExpectedStateTransition; +import parser.exceptions.WrongLHSExpression; +import parser.exceptions.WrongRHSExpression; + +public class DataFlowModelingStage extends Stage { + public int PORT_DIAMETER = 8; + public int PORT_RADIUS = PORT_DIAMETER / 2; + + public DataFlowModelingStage(mxGraph graph) { + super(graph); + } + + @Override + public boolean canChangeFrom(Stage prevStage) { + return true; + } + + @Override + public void init(Stage prevStage) { + } + + public void clear() { + model = null; + ((mxGraphModel) graph.getModel()).clear(); + } + + public DataTransferModel getModel() { + if (model == null) { + setModel(new DataTransferModel()); + } + return model; + } + + public void setModel(DataTransferModel model) { + this.model = model; + // Update the mxGraph. + graph = constructGraph(graph, model); + } + + /** + * Construct a mxGraph from DataFlowModel + * @param model + * @param dataFlowGraph + * @return constructed mxGraph + */ + public mxGraph constructGraph(mxGraph graph, DataTransferModel model) { + ((mxGraphModel) graph.getModel()).clear(); + Object parent = graph.getDefaultParent(); + graph.getModel().beginUpdate(); + try { + mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo1.setRelative(true); + + mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo2.setRelative(true); + + Map channelsIn = new HashMap<>(); + Map channelsOut = new HashMap<>(); + Map resources = new HashMap<>(); + + // create channel vertices + for (ChannelGenerator c: model.getChannelGenerators()) { + DataTransferChannelGenerator channelGen = (DataTransferChannelGenerator) c; + if (channelsIn.get(channelGen) == null || channelsOut.get(channelGen) == null) { + Object channel = graph.insertVertex(parent, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex + mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); + port_in.setVertex(true); + graph.addCell(port_in, channel); // insert the input port of a channel + mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + graph.addCell(port_out, channel); // insert the output port of a channel + channelsIn.put(channelGen, port_in); + channelsOut.put(channelGen, port_out); + } + } + + // create resource vertices + for (IdentifierTemplate res: model.getIdentifierTemplates()) { + Object resource = graph.insertVertex(parent, null, + res.getResourceName(), 20, 20, 80, 30, + "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex + resources.put(res, resource); + } + + // add input, output and reference edges + for (ChannelGenerator ch: model.getChannelGenerators()) { + DataTransferChannelGenerator channelGen = (DataTransferChannelGenerator) ch; + // input edge + for (IdentifierTemplate srcRes: channelGen.getInputIdentifierTemplates()) { + graph.insertEdge(parent, null, new SrcDstAttribute(srcRes, channelGen), resources.get(srcRes), channelsIn.get(channelGen), "movable=false"); + } + // output edge + for (IdentifierTemplate dstRes: channelGen.getOutputIdentifierTemplates()) { + graph.insertEdge(parent, null, new SrcDstAttribute(channelGen, dstRes), channelsOut.get(channelGen), resources.get(dstRes), "movable=false"); + } + // reference edges + for (IdentifierTemplate refRes: channelGen.getReferenceIdentifierTemplates()) { + graph.insertEdge(parent, null, null, resources.get(refRes), channelsIn.get(channelGen), "dashed=true;movable=false"); + } + } + + for (ChannelGenerator ioChannelGen: model.getIOChannelGenerators()) { + if (channelsOut.get(ioChannelGen) == null) { + Object channel = graph.insertVertex(parent, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex + mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + graph.addCell(port_out, channel); // insert the output port of a channel + channelsOut.put((DataTransferChannelGenerator) ioChannelGen, port_out); + for (IdentifierTemplate outRes: ((DataTransferChannelGenerator) ioChannelGen).getOutputIdentifierTemplates()) { + graph.insertEdge(parent, null, null, port_out, resources.get(outRes), "movable=false"); + } + } + } + } finally { + graph.getModel().endUpdate(); + } + + return graph; + } + + public void addIdentifierTemplate(IdentifierTemplate res) { + getModel().addIdentifierTemplate(res); + graph.getModel().beginUpdate(); + Object parent = graph.getDefaultParent(); + try { + graph.insertVertex(parent, null, res.getResourceName(), 20, 20, 80, 30, + "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex + } finally { + graph.getModel().endUpdate(); + } + } + + public void addChannelGenerator(DataTransferChannelGenerator channelGen) { + getModel().addChannelGenerator(channelGen); + graph.getModel().beginUpdate(); + Object parent = graph.getDefaultParent(); + try { + mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo1.setRelative(true); + + mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo2.setRelative(true); + + Object channel = graph.insertVertex(parent, null, channelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex + mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); + port_in.setVertex(true); + graph.addCell(port_in, channel); // insert the input port of a channel + mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + graph.addCell(port_out, channel); // insert the output port of a channel + } finally { + graph.getModel().endUpdate(); + } + } + + public void addIOChannelGenerator(DataTransferChannelGenerator ioChannelGen) { + getModel().addIOChannelGenerator(ioChannelGen); + graph.getModel().beginUpdate(); + Object parent = graph.getDefaultParent(); + try { + mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo2.setRelative(true); + + Object channel = graph.insertVertex(parent, null, ioChannelGen.getChannelName(), 150, 20, 30, 30); // insert an I/O channel as a vertex + mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + graph.addCell(port_out, channel); // insert the output port of a channel + } finally { + graph.getModel().endUpdate(); + } + } + + public void addFormulaChannelGenerator(FormulaChannelGenerator formulaChannelGen) { + getModel().addChannelGenerator(formulaChannelGen); + graph.getModel().beginUpdate(); + Object parent = graph.getDefaultParent(); + try { + mxGeometry geo1 = new mxGeometry(0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo1.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo1.setRelative(true); + + mxGeometry geo2 = new mxGeometry(1.0, 0.5, PORT_DIAMETER, PORT_DIAMETER); + geo2.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS)); + geo2.setRelative(true); + + Object channel = graph.insertVertex(parent, null, formulaChannelGen.getChannelName(), 150, 20, 30, 30); // insert a channel as a vertex + mxCell port_in = new mxCell(null, geo1, "shape=ellipse;perimter=ellipsePerimeter"); + port_in.setVertex(true); + graph.addCell(port_in, channel); // insert the input port of a channel + mxCell port_out = new mxCell(null, geo2, "shape=ellipse;perimter=ellipsePerimeter"); + port_out.setVertex(true); + graph.addCell(port_out, channel); // insert the output port of a channel + } finally { + graph.getModel().endUpdate(); + } + } + + public boolean connectEdge(mxCell edge, mxCell src, mxCell dst) { + DataTransferModel model = getModel(); + ChannelGenerator srcCh = model.getChannelGenerator((String) src.getValue()); + if (srcCh == null) { + srcCh = model.getIOChannelGenerator((String) src.getValue()); + if (srcCh == null) { + IdentifierTemplate srcRes = model.getIdentifierTemplate((String) src.getValue()); + ChannelGenerator dstCh = model.getChannelGenerator((String) dst.getValue()); + if (srcRes == null || dstCh == null) return false; + // resource to channel edge + ChannelMember srcCm = new ChannelMember(srcRes); + ((DataTransferChannelGenerator ) dstCh).addChannelMemberAsInput(srcCm); + edge.setValue(new SrcDstAttribute(srcRes, dstCh)); + return true; + } + } + IdentifierTemplate dstRes = model.getIdentifierTemplate((String) dst.getValue()); + if (dstRes == null) return false; + // channel to resource edge + ChannelMember dstCm = new ChannelMember(dstRes); + ((DataTransferChannelGenerator) srcCh).addChannelMemberAsOutput(dstCm); + edge.setValue(new SrcDstAttribute(srcCh, dstRes)); + return true; + } + + public void delete() { + for (Object obj: graph.getSelectionCells()) { + mxCell cell = (mxCell) obj; + if (cell.isEdge()) { + String srcName = (String) cell.getSource().getValue(); + String dstName = (String) cell.getTarget().getValue(); + if (model.getIdentifierTemplate(srcName) != null) { + // resource to channel edge + ChannelGenerator ch = model.getChannelGenerator(dstName); + ch.removeChannelMember(model.getIdentifierTemplate(srcName)); + } else if (model.getIdentifierTemplate(dstName) != null) { + // channel to resource edge + ChannelGenerator ch = model.getChannelGenerator(srcName); + if (ch == null) { + ch = model.getIOChannelGenerator(srcName); + } + ch.removeChannelMember(model.getIdentifierTemplate(dstName)); + } + } else if (cell.isVertex()) { + String name = (String) cell.getValue(); + if (model.getChannelGenerator(name) != null) { + model.removeChannelGenerator(name); + } else if (model.getIOChannelGenerator(name) != null) { + model.removeIOChannelGenerator(name); + } else if (model.getIdentifierTemplate(name) != null) { + model.removeIdentifierTemplate(name); + } + } + } + graph.removeCells(graph.getSelectionCells()); + } + + public void setChannelCode(DataTransferChannelGenerator ch, String code) { + ch.setSourceText(code); + TokenStream stream = new TokenStream(); + Parser parser = new Parser(stream); + + for (String line: code.split("\n")) { + stream.addLine(line); + } + try { + DataTransferChannelGenerator ch2 = parser.parseChannel(getModel()); + for (ChannelMember chm2: ch2.getInputChannelMembers()) { + for (ChannelMember chm: ch.getInputChannelMembers()) { + if (chm2.getIdentifierTemplate() == chm.getIdentifierTemplate()) { + chm.setStateTransition(chm2.getStateTransition()); + break; + } + } + } + for (ChannelMember chm2: ch2.getOutputChannelMembers()) { + for (ChannelMember chm: ch.getOutputChannelMembers()) { + if (chm2.getIdentifierTemplate() == chm.getIdentifierTemplate()) { + chm.setStateTransition(chm2.getStateTransition()); + break; + } + } + } + for (ChannelMember chm2: ch2.getReferenceChannelMembers()) { + for (ChannelMember chm: ch.getReferenceChannelMembers()) { + if (chm2.getIdentifierTemplate() == chm.getIdentifierTemplate()) { + chm.setStateTransition(chm2.getStateTransition()); + break; + } + } + } + } catch (ExpectedRightBracket | ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket + | ExpectedInOrOutOrRefKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression + | WrongLHSExpression | WrongRHSExpression | ExpectedAssignment e) { + e.printStackTrace(); + } + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java new file mode 100644 index 0000000..540ca4e --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java @@ -0,0 +1,77 @@ +package application.editor.stages; + +import com.mxgraph.model.mxCell; +import com.mxgraph.view.mxGraph; + +import algorithms.DataTransferModelAnalyzer; +import application.editor.Stage; +import application.editor.Editor.SrcDstAttribute; +import models.Edge; +import models.dataFlowModel.DataFlowEdge; +import models.dataFlowModel.DataFlowGraph; +import models.dataFlowModel.DataTransferChannelGenerator; +import models.dataFlowModel.DataTransferModel; +import models.dataFlowModel.ResourceNode; + +public class PushPullSelectionStage extends Stage { + protected DataFlowGraph dataFlowGraph = null; + + public PushPullSelectionStage(mxGraph graph) { + super(graph); + } + + @Override + public boolean canChangeFrom(Stage prevStage) { + if (prevStage instanceof DataFlowModelingStage) return true; + if (((DataFlowModelingStage) prevStage).getModel() == null) return false; + return false; + } + + @Override + public void init(Stage prevStage) { + if (prevStage instanceof DataFlowModelingStage) { + model = ((DataFlowModelingStage) prevStage).getModel(); + dataFlowGraph = analyzeDataTransferModel(graph, model); + } + } + + public DataFlowGraph getDataFlowGraph() { + return dataFlowGraph; + } + + public DataFlowGraph analyzeDataTransferModel(mxGraph graph, DataTransferModel model) { + DataFlowGraph flowGraph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); + DataFlowGraph dataFlowGraph = DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(flowGraph); + updateEdgeAttiributes(graph, dataFlowGraph); + return dataFlowGraph; + } + + private void updateEdgeAttiributes(mxGraph graph, DataFlowGraph dataFlowGraph) { + Object parent = graph.getDefaultParent(); + graph.getModel().beginUpdate(); + try { + // add input, output and reference edges + for (Edge e : dataFlowGraph.getEdges()) { + if (e instanceof DataFlowEdge) { + DataFlowEdge dataFlow = (DataFlowEdge) e; + DataTransferChannelGenerator channelGen = dataFlow.getChannelGenerator(); + ResourceNode srcRes = (ResourceNode) dataFlow.getSource(); + // input edge + for (Object edge: graph.getChildEdges(parent)) { + mxCell edgeCell = (mxCell) edge; + if (edgeCell.getValue() instanceof SrcDstAttribute) { + SrcDstAttribute edgeAttr = (SrcDstAttribute) edgeCell.getValue(); + if (edgeAttr.getSrouce() == srcRes.getIdentifierTemplate() && edgeAttr.getDestination() == channelGen) { + edgeCell.setValue(dataFlow.getAttribute()); + break; + } + } + } + } + } + } finally { + graph.getModel().endUpdate(); + } + graph.refresh(); + } +}