diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java index 69047fa..3f29dc0 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Editor.java @@ -1,145 +1,80 @@ package application.editor; -import java.awt.event.MouseListener; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.AbstractMap; -import java.util.AbstractMap.SimpleEntry; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - import application.editor.stages.DataFlowModelingStage; import application.editor.stages.PushPullSelectionStage; +import application.layouts.DAGLayout; +import code.ast.CompilationUnit; 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.mxICell; -import com.mxgraph.model.mxIGraphModel; import com.mxgraph.swing.mxGraphComponent; -import com.mxgraph.util.*; +import com.mxgraph.util.mxEvent; +import com.mxgraph.util.mxEventSource.mxIEventListener; import com.mxgraph.view.mxCellState; import com.mxgraph.view.mxGraph; import com.mxgraph.view.mxGraphView; - -import algorithms.DataTransferModelAnalyzer; -import algorithms.Validation; -import application.layouts.*; -import code.ast.CompilationUnit; -import generators.JavaCodeGenerator; -import models.Edge; import models.EdgeAttribute; -import models.Node; -import models.algebra.Expression; -import models.algebra.InvalidMessage; -import models.algebra.ParameterizedIdentifierIsFutureWork; -import models.algebra.UnificationFailed; -import models.algebra.ValueUndefined; import models.dataConstraintModel.Channel; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; -import models.dataConstraintModel.Selector; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannel; -import models.dataFlowModel.PushPullAttribute; -import models.dataFlowModel.ResolvingMultipleDefinitionIsFutureWork; -import models.dataFlowModel.ChannelNode; -import models.dataFlowModel.DataFlowEdge; import models.dataFlowModel.DataFlowGraph; -import models.dataFlowModel.ResourceNode; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; import models.visualModel.FormulaChannel; import parser.Parser; -import parser.Parser.TokenStream; -import parser.exceptions.ExpectedAssignment; -import parser.exceptions.ExpectedChannel; -import parser.exceptions.ExpectedChannelName; -import parser.exceptions.ExpectedColon; -import parser.exceptions.ExpectedEquals; -import parser.exceptions.ExpectedFormulaChannel; -import parser.exceptions.ExpectedGeometry; -import parser.exceptions.ExpectedInOrOutOrRefOrSubKeyword; -import parser.exceptions.ExpectedIoChannel; -import parser.exceptions.ExpectedLeftCurlyBracket; -import parser.exceptions.ExpectedModel; -import parser.exceptions.ExpectedNode; -import parser.exceptions.ExpectedRHSExpression; -import parser.exceptions.ExpectedResource; -import parser.exceptions.ExpectedRightBracket; -import parser.exceptions.ExpectedStateTransition; -import parser.exceptions.WrongJsonExpression; -import parser.exceptions.WrongLHSExpression; -import parser.exceptions.WrongRHSExpression; -import parser.exceptions.ExpectedRightCurlyBracket; -import parser.exceptions.WrongPathExpression; import parser.ParserDTRAM; +import parser.exceptions.*; + +import java.awt.event.MouseListener; +import java.io.*; +import java.util.ArrayList; +import java.util.List; public class Editor { - final int PORT_DIAMETER = 8; - final int PORT_RADIUS = PORT_DIAMETER / 2; - protected DataTransferModel model = null; - protected mxGraph graph = null; - private mxGraphComponent graphComponent = null; + protected DataTransferModel model = null; + protected mxGraph graph; + private final mxGraphComponent graphComponent; - protected DataFlowGraph dataFlowGraph = null; + protected Stage curStage; + private final List stageChangeListeners; - protected Stage curStage = null; - private List stageChangeListeners = null; - - private mxEventSource.mxIEventListener curChangeEventListener = null; + private mxIEventListener curChangeEventListener = null; private MouseListener curMouseEventListener = null; - protected String curFileName = null; - protected String curFilePath = null; - protected ArrayList codes = null; + protected String curFileName = null; + protected String curFilePath = null; + protected ArrayList codes = null; - public static DataFlowModelingStage STAGE_DATA_FLOW_MODELING = null; - public static PushPullSelectionStage STAGE_PUSH_PULL_SELECTION = null; + // FIXME These variables should be named by camel-case because they are not constant. + public static DataFlowModelingStage STAGE_DATA_FLOW_MODELING = null; + public static PushPullSelectionStage STAGE_PUSH_PULL_SELECTION = null; - private boolean bReflectingArchitectureModel = false; + public Editor(mxGraphComponent graphComponent) { + this.graphComponent = graphComponent; + this.graph = graphComponent.getGraph(); - public Editor(mxGraphComponent graphComponent) { - this.graphComponent = graphComponent; - this.graph = graphComponent.getGraph(); + STAGE_DATA_FLOW_MODELING = new DataFlowModelingStage(graphComponent); + STAGE_PUSH_PULL_SELECTION = new PushPullSelectionStage(graphComponent); - STAGE_DATA_FLOW_MODELING = new DataFlowModelingStage(graphComponent); - STAGE_PUSH_PULL_SELECTION = new PushPullSelectionStage(graphComponent); + graphComponent.setCellEditor(STAGE_DATA_FLOW_MODELING.createCellEditor(graphComponent)); - graphComponent.setCellEditor(STAGE_DATA_FLOW_MODELING.createCellEditor(graphComponent)); + curStage = STAGE_DATA_FLOW_MODELING; - curStage = STAGE_DATA_FLOW_MODELING; + stageChangeListeners = new ArrayList<>(); + } - stageChangeListeners = new ArrayList<>(); - } + public mxGraph getGraph() { + return graph; + } - public mxGraph getGraph() { - return graph; - } + public mxGraphComponent getGraphComponent() { + return this.graphComponent; + } - public mxGraphComponent getGraphComponent() { - return this.graphComponent; - } - - public DataTransferModel getModel() { - if (model == null) { - model = new DataTransferModel(); - } - return model; - } + public DataTransferModel getModel() { + model = curStage.getModel(); + return model; + } public Stage getCurStage() { return curStage; @@ -165,15 +100,17 @@ } // A handler of a mouse event. - if(curMouseEventListener != null) { + if (curMouseEventListener != null) { graphComponent.getGraphControl().removeMouseListener(curMouseEventListener); } curMouseEventListener = nextStage.createMouseEventListener(this); - if(curMouseEventListener != null) { + if (curMouseEventListener != null) { graphComponent.getGraphControl().addMouseListener(curMouseEventListener); } curStage = nextStage; notifyStageChangeListeners(); + + setDAGLayout(); // FIXME Not correct workaround return true; } @@ -182,715 +119,343 @@ } private void notifyStageChangeListeners() { - for (IStageChangeListener l: stageChangeListeners) { + for (IStageChangeListener l : stageChangeListeners) { l.stageChanged(curStage); } } - public DataFlowGraph getDataFlowGraph() { - if (dataFlowGraph == null) { - analyzeDataTransferModel(getModel()); - updateEdgeAttiributes(dataFlowGraph); - } - return dataFlowGraph; - } + public DataFlowGraph getDataFlowGraph() { + if (curStage instanceof PushPullSelectionStage) { + return ((PushPullSelectionStage) curStage).getDataFlowGraph(); + } + return null; + } - public DataFlowGraph analyzeDataTransferModel(DataTransferModel model) { - DataFlowGraph flowGraph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); - dataFlowGraph = DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(flowGraph); - return dataFlowGraph; - } + public ArrayList getCodes() { + return codes; + } - public void resetDataFlowGraph() { - dataFlowGraph = null; - } + public void setCodes(ArrayList codes) { + this.codes = codes; + } - public void setDataFlowGraph(DataFlowGraph dataFlowGraph) { - this.dataFlowGraph = dataFlowGraph; - } + public String getCurFileName() { + return curFileName; + } - public ArrayList getCodes() { - return codes; - } + public String getCurFilePath() { + return curFilePath; + } - public void setCodes(ArrayList codes) { - this.codes = codes; - } + public void setCurFilePath(String curFilePath) { + this.curFilePath = curFilePath; + this.curFileName = new File(curFilePath).getName(); + } - public String getCurFileName() { - return curFileName; - } + public void clear() { + // Force to change to the data-flow modeling stage + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) { + return; + } + ((DataFlowModelingStage) curStage).clear(); - public String getCurFilePath() { - return curFilePath; - } + model = null; + curFilePath = null; + curFileName = null; + codes = null; + // resetDataFlowGraph + } - public void setCurFilePath(String curFilePath) { - this.curFilePath = curFilePath; - this.curFileName = new File(curFilePath).getName(); - } + /** + * Open a given file, parse the file, construct a DataFlowModel and a mxGraph + * + * @param file given file + */ + public void open(File file) { + // Force to change to data-modeling stage + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) { + return; + } + if (file == null || !file.exists()) { + return; + } + // get a file's extension + String extension = file.getName().substring(file.getName().lastIndexOf(".")); + if (extension.contains(".model")) { + openModel(file); + } + if (extension.contains(".dtram")) { + openDTRAM(file); + } + } - public void clear() { - model = null; - ((mxGraphModel) graph.getModel()).clear(); - dataFlowGraph = null; - curFilePath = null; - curFileName = null; - codes = null; - } + private void openModel(File file) { + try { + Parser parser = new Parser(new BufferedReader(new FileReader(file))); + try { + // Parse the .model file. + model = parser.doParse(); - /** - * Open a given file, parse the file, construct a DataFlowModel and a mxGraph - * @param file given file - * @return a constructed DataFlowModel - */ - public DataTransferModel open(File file) { - try { + // Update stage's model to new parsed one + if (curStage instanceof DataFlowModelingStage) { + DataFlowModelingStage stage = (DataFlowModelingStage) curStage; + stage.setModel(model); + } - String extension =""; - if(file != null && file.exists()) { - // get a file's name - String name = file.getName(); + // Force to change PushPullSelectionStage to construct mxGraph + changeStage(STAGE_PUSH_PULL_SELECTION); - // get a file's extension - extension = name.substring(name.lastIndexOf(".")); - } - if(extension.contains(".model")) { - openModel(file); - } else { - ParserDTRAM parserDTRAM = new ParserDTRAM(new BufferedReader(new FileReader(file))); - try { - // Parse the .dtram file. - model = parserDTRAM.doParseModel(); + // Update current file info + curFilePath = file.getAbsolutePath(); + curFileName = file.getName(); + } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | + ExpectedInOrOutOrRefOrSubKeyword | ExpectedStateTransition | ExpectedEquals | + ExpectedRHSExpression | WrongLHSExpression | WrongRHSExpression | ExpectedRightBracket | + ExpectedAssignment | ExpectedRightCurlyBracket | WrongPathExpression | WrongJsonExpression | + ExpectedColon e) { + e.printStackTrace(); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } - // Analyze the model. - if (!Validation.checkUpdateConflict(model)) return null; - DataFlowGraph dataFlowGraph = analyzeDataTransferModel(model); + private void openDTRAM(File file) { + try { + ParserDTRAM parser = new ParserDTRAM(new BufferedReader(new FileReader(file))); + try { + // Parse the .dtram file. + model = parser.doParseModel(); - // Visualize the model. - graph = constructGraph(model, dataFlowGraph); - parserDTRAM.doParseGeometry(graph); - updateEdgeAttiributes(dataFlowGraph); + // Update stage's model to new parsed one + if (curStage instanceof DataFlowModelingStage) { + DataFlowModelingStage stage = (DataFlowModelingStage) curStage; + stage.setModel(model); + } - curFilePath = file.getAbsolutePath(); - curFileName = file.getName(); - return model; - } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefOrSubKeyword - | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression - | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment | ExpectedModel - | ExpectedGeometry | ExpectedNode | ExpectedResource | ExpectedFormulaChannel | ExpectedIoChannel - | ExpectedRightCurlyBracket | WrongPathExpression | WrongJsonExpression | ExpectedColon e) { - e.printStackTrace(); - } - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } + // Parse Geometry + parser.doParseGeometry(graph); - return null; - } + // Force to change PushPullSelectionStage to construct mxGraph + changeStage(STAGE_PUSH_PULL_SELECTION); - public DataTransferModel openModel(File file) { - try { + // Update current file info + curFilePath = file.getAbsolutePath(); + curFileName = file.getName(); + } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | + ExpectedInOrOutOrRefOrSubKeyword | ExpectedStateTransition | ExpectedEquals | + ExpectedRHSExpression | WrongLHSExpression | WrongRHSExpression | ExpectedRightBracket | + ExpectedAssignment | ExpectedModel | ExpectedGeometry | ExpectedNode | ExpectedResource | + ExpectedFormulaChannel | ExpectedIoChannel | ExpectedRightCurlyBracket | WrongPathExpression | + WrongJsonExpression | ExpectedColon e) { + e.printStackTrace(); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } - Parser parser = new Parser(new BufferedReader(new FileReader(file))); + public void save() { + if (curFilePath == null) { + return; + } + File file = new File(curFilePath); + if (!file.exists()) { + return; + } + // get a file's extension + String extension = file.getName().substring(file.getName().lastIndexOf(".")); + if (extension.contains(".model")) { + saveModel(file); + } + if (extension.contains(".dtram")) { + saveDTRAM(file); + } + } - try { - // Parse the .model file. - model = parser.doParse(); + private void saveModel(File file) { + try { + FileWriter filewriter = new FileWriter(file); + filewriter.write(model.getSourceText()); + filewriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } - // Analyze the model. - if (!Validation.checkUpdateConflict(model)) return null; - DataFlowGraph dataFlowGraph = analyzeDataTransferModel(model); + private void saveDTRAM(File file) { + try { + FileWriter filewriter = new FileWriter(file); + filewriter.write(toOutputString()); + filewriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } - // Visualize the model. - graph = constructGraph(model, dataFlowGraph); - updateEdgeAttiributes(dataFlowGraph); + /** + * get writing texts "dtram" file information is written. + * + * @return formatted "dtram" info texts. + */ + private String toOutputString() { + StringBuilder fileString = new StringBuilder(); - // Set DAG layout. -// setDAGLayout(); + fileString.append("model {\n"); + fileString.append(this.model.getSourceText()); + fileString.append("}\n"); - curFilePath = file.getAbsolutePath(); - curFileName = file.getName(); - return model; - } catch (ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefOrSubKeyword - | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression - | WrongRHSExpression | ExpectedRightBracket | ExpectedAssignment | ExpectedRightCurlyBracket | WrongPathExpression | WrongJsonExpression | ExpectedColon e) { - e.printStackTrace(); - } - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - return null; - } + fileString.append("geometry {\n"); - /**-------------------------------------------------------------------------------- - * save - /**-------------------------------------------------------------------------------- - * - */ - public void save() { - if (curFilePath != null) { - try { - File file = new File(curFilePath); - String extension = ""; - if(file != null && file.exists()) { - // get a file's name - String name = file.getName(); + Object root = graph.getDefaultParent(); + for (int i = 0; i < graph.getModel().getChildCount(root); i++) { + Object cell = graph.getModel().getChildAt(root, i); + if (graph.getModel().isVertex(cell)) { + mxGraphView view = graph.getView(); + mxCellState state = view.getState(cell); + int x = (int) state.getX(); + int y = (int) state.getY(); + int w = (int) state.getWidth(); + int h = (int) state.getHeight(); - // get a file's extension - extension = name.substring(name.lastIndexOf(".")); - } - if(extension.contains(".model")) { - saveModel(file); - } else { - FileWriter filewriter = new FileWriter(file); - filewriter.write(toOutputString()); - filewriter.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - } + for (Channel ch : model.getChannels()) { + if (ch instanceof FormulaChannel && state.getLabel().equals(ch.getChannelName())) { + fileString.append("\tnode fc ").append(state.getLabel()).append(":").append(x).append(",").append(y).append(",").append(w).append(",").append(h).append("\n"); + } else if (ch != null && state.getLabel().equals(ch.getChannelName())) { + fileString.append("\tnode c ").append(state.getLabel()).append(":").append(x).append(",").append(y).append(",").append(w).append(",").append(h).append("\n"); + } + } - public void saveModel(File file) { - if (curFilePath != null) { - try { - FileWriter filewriter = new FileWriter(file); - filewriter.write(model.getSourceText()); - filewriter.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } + for (ResourcePath res : model.getResourcePaths()) { + if (res != null && state.getLabel().equals(res.getLeafResourceName())) + fileString.append("\tnode r ").append(state.getLabel()).append(":").append(x).append(",").append(y).append(",").append(w).append(",").append(h).append("\n"); + } - /**-------------------------------------------------------------------------------- - * get writing texts "dtram" file information is written. - * - * @return formatted "dtram" info texts. - */ - protected String toOutputString() { - String fileString = ""; + for (Channel ioC : model.getInputChannels()) { + if (ioC != null && state.getLabel().equals(ioC.getChannelName())) { + fileString.append("\tnode ioc ").append(state.getLabel()).append(":").append(x).append(",").append(y).append(",").append(w).append(",").append(h).append("\n"); + } + } + } + } + fileString.append("}\n"); - fileString += "model {\n"; - fileString += this.model.getSourceText(); - fileString += "}\n"; + return fileString.toString(); + } - fileString += "geometry {\n"; + public void delete() { + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) { + return; + } + ((DataFlowModelingStage) curStage).delete(); + } - Object root = graph.getDefaultParent(); - for (int i = 0; i < graph.getModel().getChildCount(root); i++) { - Object cell = graph.getModel().getChildAt(root, i); - if (graph.getModel().isVertex(cell)) { - mxGraphView view = graph.getView(); - mxCellState state = view.getState(cell); - int x = (int) state.getX(); - int y = (int) state.getY(); - int w = (int) state.getWidth(); - int h = (int) state.getHeight(); + public void setDAGLayout() { + Object parent = graph.getDefaultParent(); + graph.getModel().beginUpdate(); + try { + DAGLayout ctl = new DAGLayout(graph); + ctl.execute(parent); + } finally { + graph.getModel().endUpdate(); + } + } - for(Channel ch: model.getChannels()) { - if(ch instanceof FormulaChannel && state.getLabel().equals(ch.getChannelName())) { - fileString += "\tnode fc " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h+"\n"; - } else if(ch instanceof Channel && state.getLabel().equals(ch.getChannelName())) { - fileString +="\tnode c " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h+"\n"; - } - } + public void setTreeLayout() { + Object parent = graph.getDefaultParent(); + graph.getModel().beginUpdate(); + try { + mxCompactTreeLayout ctl = new mxCompactTreeLayout(graph); + ctl.setLevelDistance(100); + // ctl.setHorizontal(false); + ctl.setEdgeRouting(false); + ctl.execute(parent); + } finally { + graph.getModel().endUpdate(); + } + } - for (ResourcePath res: model.getResourcePaths()){ - if(res instanceof ResourcePath && state.getLabel().equals(res.getLeafResourceName())) - fileString += "\tnode r " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; - } + public void setCircleLayout() { + Object parent = graph.getDefaultParent(); + graph.getModel().beginUpdate(); + try { + mxCircleLayout ctl = new mxCircleLayout(graph); + ctl.execute(parent); + } finally { + graph.getModel().endUpdate(); + } + } - for (Channel ioC: model.getInputChannels()) { - if(ioC instanceof Channel && state.getLabel().equals(ioC.getChannelName())) { - fileString += "\tnode ioc " + state.getLabel() + ":" + x + "," + y + "," + w + "," + h + "\n"; - } - } - } - } - fileString += "}\n"; + public void addResourcePath(ResourcePath parentPath, String resName) { + // Force to change to data-flow modeling stage + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (stageChanged) { + return; + } + ((DataFlowModelingStage) curStage).addResourcePath(parentPath, resName); + model = curStage.getModel(); + } - return fileString; - } + public void addChannel(DataTransferChannel channelGen) { + // Force to change to data-flow modeling stage + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (stageChanged) { + return; + } + ((DataFlowModelingStage) curStage).addChannel(channelGen); + model = curStage.getModel(); + } - /** - * Construct a mxGraph from DataFlowModel and DataFlowModel - * @param model - * @param dataFlowGraph - * @return constructed mxGraph - */ - public mxGraph constructGraph(DataTransferModel model, DataFlowGraph dataFlowGraph) { - bReflectingArchitectureModel = true; - ((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); + public void addIOChannel(DataTransferChannel ioChannelGen) { + // Force to change to data-flow modeling stage + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (stageChanged) { + return; + } + ((DataFlowModelingStage) curStage).addIOChannel(ioChannelGen); + model = curStage.getModel(); + } - 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 resource vertices - for (ResourceNode resNode: dataFlowGraph.getRootResourceNodes()) { - int w = 80; - int h = 30; - ResourcePath res = resNode.getPrimaryResourcePath(); - Object resource = graph.insertVertex(parent, null, - res.getLeafResourceName(), 20, 20, w, h, - "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex - resources.put(resNode, resource); - createChildResourceVerticies(resource, resNode, resources, w, h); - } - - // create channel vertices - for (ChannelNode c: dataFlowGraph.getRootChannelNodes()) { - DataTransferChannel channel = (DataTransferChannel) c.getChannel(); - if (channel.getInputResources().size() > 0) { - // Normal channel - if (channelsIn.get(channel) == null || channelsOut.get(channel) == null) { - if (channel.getSelectors().toString() == "[]") { - Object chCell = graph.insertVertex(parent, null, channel.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, chCell); // 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, chCell); // insert the output port of a channel - channelsIn.put(channel, port_in); - channelsOut.put(channel, port_out); - } else { - for (Selector s: channel.getSelectors()) { - Expression exp = s.getExpression(); - String selName = exp.toString(); - String cName = channel.getChannelName(); - String channelName = cName + " (" + selName + ")"; - Object chCell = graph.insertVertex(parent, null, channelName, 150, 20, 60, 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, chCell); // 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, chCell); // insert the output port of a channel - channelsIn.put(channel, port_in); - channelsOut.put(channel, port_out); - } - } - } - } else { - // I/O channel - if (channelsOut.get(channel) == null) { - if (channel.getSelectors().toString() == "[]") { - Object chCell = graph.insertVertex(parent, null, channel.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, chCell); // 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, chCell); // insert the output port of a channel - channelsIn.put(channel, port_in); - channelsOut.put(channel, port_out); - } else { - for (Selector s: channel.getSelectors()) { - Expression exp = s.getExpression(); - String selName = exp.toString(); - String cName = channel.getChannelName(); - String channelName = cName + " (" + selName + ")"; - Object chCell = graph.insertVertex(parent, null, channelName, 150, 20, 60, 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, chCell); // 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, chCell); // insert the output port of a channel - channelsIn.put(channel, port_in); - channelsOut.put(channel, port_out); - } - } - } - } - } - - // add input, output and reference edges - for (Edge edge: dataFlowGraph.getEdges()) { - DataFlowEdge dfEdge = (DataFlowEdge) edge; - if (dfEdge.isChannelToResource()) { - // output edge - DataTransferChannel channel = ((ChannelNode) dfEdge.getSource()).getChannel(); - ResourcePath dstRes = ((ResourceNode) dfEdge.getDestination()).getInSideResource(channel); - graph.insertEdge(parent, null, new SrcDstAttribute(channel, dstRes), channelsOut.get(channel), resources.get((ResourceNode) dfEdge.getDestination()), "movable=false"); - } else { - // input edge - DataTransferChannel channel = ((ChannelNode) dfEdge.getDestination()).getChannel(); - ResourcePath srcRes = ((ResourceNode) dfEdge.getSource()).getOutSideResource(channel); - Set> toRes = getResourceDependencyForChannel(channel, model, dataFlowGraph); - for(Map.Entry RtoR: toRes) { - graph.insertEdge(parent, null, null, - resources.get(RtoR.getValue()), - resources.get(RtoR.getKey()), "dashed=true;movable=false"); - } - - graph.insertEdge(parent, null, new SrcDstAttribute(srcRes, channel), resources.get((ResourceNode) dfEdge.getSource()), channelsIn.get(channel), "movable=false"); - } - } - - for (Channel ch: model.getChannels()) { - // reference edges - DataTransferChannel channel = (DataTransferChannel) ch; - for (ResourcePath refRes: channel.getReferenceResources()) { - graph.insertEdge(parent, null, null, resources.get(dataFlowGraph.getResourceNode(refRes)), channelsIn.get(channel), "dashed=true;movable=false"); - } - } - } finally { - graph.getModel().endUpdate(); - } - setDAGLayout(); - - bReflectingArchitectureModel = false; - return graph; - } - - public void createChildResourceVerticies(Object resource, ResourceNode resNode, Map resources, int w, int h) { - - for (ResourceNode childNode: resNode.getChildren()) { - ResourcePath childRes = childNode.getPrimaryResourcePath(); - Object childResource = graph.insertVertex(resource, null, - childRes.getName(), 0, 0, w, h, - "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex - resources.put(childNode, childResource); - createChildResourceVerticies(childResource, childNode, resources, w, h); - } - } - - public void setDAGLayout() { - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - try { - DAGLayout ctl = new DAGLayout(graph); - ctl.execute(parent); - } finally { - graph.getModel().endUpdate(); - } - } - - 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; - if (!dataFlow.isChannelToResource()) { - ResourceNode srcRes = (ResourceNode) dataFlow.getSource(); - DataTransferChannel channel = ((ChannelNode) dataFlow.getDestination()).getChannel(); - // input edge - for (Object edge: graph.getChildEdges(parent)) { - mxCell edgeCell = (mxCell) edge; - if (edgeCell.getValue() instanceof SrcDstAttribute) { - SrcDstAttribute edgeAttr = (SrcDstAttribute) edgeCell.getValue(); - if (srcRes.getPrimaryResourcePath().equals(edgeAttr.getSource()) && channel.equals(edgeAttr.getDestination())) { - edgeCell.setValue(dataFlow.getAttribute()); - break; - } - } - } - } - } - } - } finally { - graph.getModel().endUpdate(); - } - graph.refresh(); - } - - public void setTreeLayout() { - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - try { - mxCompactTreeLayout ctl = new mxCompactTreeLayout(graph); - ctl.setLevelDistance(100); - // ctl.setHorizontal(false); - ctl.setEdgeRouting(false); - ctl.execute(parent); - } finally { - graph.getModel().endUpdate(); - } - } - - public void setCircleLayout() { - Object parent = graph.getDefaultParent(); - graph.getModel().beginUpdate(); - try { - mxCircleLayout ctl = new mxCircleLayout(graph); - ctl.execute(parent); - } finally { - graph.getModel().endUpdate(); - } - } - - public ResourcePath addResourcePath(ResourcePath parentPath, String resName) { - ResourcePath resourcePath = null; - if (parentPath == null) { - resourcePath = new ResourcePath(resName); - getModel().addResourcePath(resourcePath); - } else { - if (resName.startsWith(Parser.LEFT_CURLY_BRACKET) && resName.endsWith(Parser.RIGHT_CURLY_BRACKET)) { - TokenStream stream = new Parser.TokenStream(); - Parser parser = new Parser(stream); - stream.addLine(resName.substring(1, resName.length() - 1)); - try { - Expression exp = parser.parseTerm(stream, getModel()); - resourcePath = new ResourcePath(parentPath, exp); - getModel().addResourcePath(resourcePath); - } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon e) { - e.printStackTrace(); - return null; - } - } else { - resourcePath = new ResourcePath(parentPath, resName); - getModel().addResourcePath(resourcePath); - } - } - resetDataFlowGraph(); - graph.getModel().beginUpdate(); - Object parent = graph.getDefaultParent(); - try { - graph.insertVertex(parent, null, resName, 20, 20, 80, 30, - "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex - } finally { - graph.getModel().endUpdate(); - } - return resourcePath; - } - - public void addChannel(DataTransferChannel channelGen) { - getModel().addChannel(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(); - } - } - - public void addIOChannel(DataTransferChannel ioChannelGen) { - getModel().addInputChannel(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(); - } - } - - public void addFormulaChannel(FormulaChannel formulaChannelGen) { - getModel().addChannel(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(); - } - } - - public boolean connectEdge(mxCell edge, mxCell src, mxCell dst) { - if (bReflectingArchitectureModel) return false; - DataTransferModel model = getModel(); - Channel srcCh = model.getChannel((String) src.getValue()); - if (srcCh == null) { - srcCh = model.getInputChannel((String) src.getValue()); - if (srcCh == null) { - ResourcePath srcRes = model.getResourcePath((String) src.getValue()); - Channel dstCh = model.getChannel((String) dst.getValue()); - if (srcRes == null || dstCh == null) return false; - // resource to channel edge - ChannelMember srcCm = new ChannelMember(srcRes); - ((DataTransferChannel ) dstCh).addChannelMemberAsInput(srcCm); - edge.setValue(new SrcDstAttribute(srcRes, dstCh)); - resetDataFlowGraph(); - return true; - } - } - ResourcePath dstRes = model.getResourcePath((String) dst.getValue()); - if (dstRes == null) return false; - // channel to resource edge - ChannelMember dstCm = new ChannelMember(dstRes); - ((DataTransferChannel) srcCh).addChannelMemberAsOutput(dstCm); - edge.setValue(new SrcDstAttribute(srcCh, dstRes)); - resetDataFlowGraph(); - 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.getResourcePath(srcName) != null) { - // resource to channel edge - Channel ch = model.getChannel(dstName); - ch.removeChannelMember(model.getResourcePath(srcName)); - } else if (model.getResourcePath(dstName) != null) { - // channel to resource edge - Channel ch = model.getChannel(srcName); - if (ch == null) { - ch = model.getInputChannel(srcName); - } - ch.removeChannelMember(model.getResourcePath(dstName)); - } - } else if (cell.isVertex()) { - String name = (String) cell.getValue(); - if (model.getChannel(name) != null) { - model.removeChannel(name); - } else if (model.getInputChannel(name) != null) { - model.removeInputChannel(name); - } else if (model.getResourcePath(name) != null) { - model.removeResourcePath(name); - } - } - } - graph.removeCells(graph.getSelectionCells()); - resetDataFlowGraph(); - } - - public void setChannelCode(DataTransferChannel ch, String code) { - ch.setSourceText(code); - TokenStream stream = new Parser.TokenStream(); - Parser parser = new Parser(stream); - - for (String line: code.split("\n")) { - stream.addLine(line); - } - try { - DataTransferChannel ch2 = parser.parseChannel(getModel()); - for (ChannelMember chm2: ch2.getInputChannelMembers()) { - for (ChannelMember chm: ch.getInputChannelMembers()) { - if (chm2.getResource() == chm.getResource()) { - chm.setStateTransition(chm2.getStateTransition()); - break; - } - } - } - for (ChannelMember chm2: ch2.getOutputChannelMembers()) { - for (ChannelMember chm: ch.getOutputChannelMembers()) { - if (chm2.getResource() == chm.getResource()) { - chm.setStateTransition(chm2.getStateTransition()); - break; - } - } - } - for (ChannelMember chm2: ch2.getReferenceChannelMembers()) { - for (ChannelMember chm: ch.getReferenceChannelMembers()) { - if (chm2.getResource() == chm.getResource()) { - chm.setStateTransition(chm2.getStateTransition()); - break; - } - } - } - resetDataFlowGraph(); - } catch (ExpectedRightBracket | ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket - | ExpectedInOrOutOrRefOrSubKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression - | WrongLHSExpression | WrongRHSExpression | ExpectedAssignment | ExpectedRightCurlyBracket | WrongPathExpression | WrongJsonExpression | ExpectedColon e) { - e.printStackTrace(); - } - } + public void addFormulaChannel(FormulaChannel formulaChannelGen) { + // Force to change to data-flow modeling stage + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (stageChanged) { + return; + } + ((DataFlowModelingStage) curStage).addFormulaChannel(formulaChannelGen); + model = curStage.getModel(); + } - public Set> getResourceDependencyForChannel(DataTransferChannel ch, DataTransferModel model, DataFlowGraph dataFlowGraph) { - Set> resourceDpendency = new HashSet<>(); - 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)); - } - } - } - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage - | UnificationFailed | ValueUndefined e) { - e.printStackTrace(); - } - } - return resourceDpendency; - } + public boolean connectEdge(mxCell edge, mxCell src, mxCell dst) { + boolean stageChanged = changeStage(STAGE_DATA_FLOW_MODELING); + if (!stageChanged) { + return false; + } + return ((DataFlowModelingStage) curStage).connectEdge(edge, src, dst); + } - private class SrcDstAttribute extends EdgeAttribute { - private Object src; - private Object dst; + public static class SrcDstAttribute extends EdgeAttribute { + private final Object src; + private final Object dst; - public SrcDstAttribute(Object src, Object dst) { - this.src = src; - this.dst = dst; - } + public SrcDstAttribute(Object src, Object dst) { + this.src = src; + this.dst = dst; + } - public Object getSource() { - return src; - } + public Object getSource() { + return src; + } - public Object getDestination() { - return dst; - } + public Object getDestination() { + return dst; + } - public String toString() { - return ""; - } - } + public String toString() { + return ""; + } + } } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java index be708bc..33114bd 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/Stage.java @@ -10,6 +10,9 @@ public abstract class Stage { + public static final int PORT_DIAMETER = 8; + public static final int PORT_RADIUS = PORT_DIAMETER / 2; + protected DataTransferModel model = null; protected mxGraphComponent graphComponent; diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java index e0aa2da..fabe3fb 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowCellEditor.java @@ -1,8 +1,22 @@ package application.editor.stages; import application.editor.FlowCellEditor; +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxIGraphModel; import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.util.mxConstants; +import com.mxgraph.util.mxUtils; +import models.algebra.Expression; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import models.visualModel.FormulaChannel; +import parser.Parser; +import parser.exceptions.ExpectedColon; +import parser.exceptions.ExpectedRightBracket; +import parser.exceptions.WrongJsonExpression; +import javax.swing.*; +import java.awt.*; import java.util.EventObject; public class DataFlowCellEditor extends FlowCellEditor { @@ -13,7 +27,77 @@ @Override public void startEditing(Object cellObj, EventObject eventObj) { - // TODO Implement + if (editingCell != null) { + stopEditing(true); + } + if (graphComponent.getGraph().getModel().isEdge(cellObj)) { + return; + } + DataTransferModel model = stage.getModel(); + DataTransferChannel ch = (DataTransferChannel) model.getChannel((String) ((mxCell) cellObj).getValue()); + if (ch == null) { + ch = (DataTransferChannel) model.getInputChannel((String) ((mxCell) cellObj).getValue()); + if (ch == null) { + // selected cell is a resource + return; + } + } + JPanel panel = new JPanel(); + if (ch instanceof FormulaChannel) { + JLabel label1 = new JLabel("Formula: "); + JLabel label2 = new JLabel("Source: "); + GridBagLayout layout = new GridBagLayout(); + panel.setLayout(layout); + GridBagConstraints gbc = new GridBagConstraints(); + + gbc.gridx = 0; + gbc.gridy = 0; + layout.setConstraints(label1, gbc); + panel.add(label1); + + gbc.gridx = 1; + gbc.gridy = 0; + JTextField formulaText = new JTextField(((FormulaChannel) ch).getFormula(), 15); + layout.setConstraints(formulaText, gbc); + panel.add(formulaText); + + gbc.gridx = 0; + gbc.gridy = 1; + layout.setConstraints(label2, gbc); + panel.add(label2); + + gbc.gridx = 1; + gbc.gridy = 1; + JTextArea textArea = new JTextArea(ch.getSourceText(), 7, 15); + textArea.setEditable(false); + layout.setConstraints(textArea, gbc); + panel.add(textArea); + + int option = JOptionPane.showConfirmDialog(null, panel, "Edit Formula Channel", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (option == JOptionPane.OK_OPTION) { + Parser.TokenStream stream = new Parser.TokenStream(); + Parser parser = new Parser(stream); + + String formula = formulaText.getText(); + stream.addLine(formula.split(Parser.EQUALS)[1]); + + try { + Expression exp = parser.parseTerm(stream, stage.getModel()); + ((FormulaChannel) ch).setFormula(formula); + ((FormulaChannel) ch).setFormulaTerm(exp); + } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon e) { + e.printStackTrace(); + } + } + } else { + JTextArea textArea = new JTextArea(ch.getSourceText(), 10, 20); + panel.add(textArea); + + int option = JOptionPane.showConfirmDialog(null, panel, "Channel Code", JOptionPane.OK_CANCEL_OPTION); + if (option == JOptionPane.OK_OPTION) { + ((DataFlowModelingStage) stage).setChannelCode(ch, textArea.getText()); + } + } } @Override diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java index f2a07d2..cccd863 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/DataFlowModelingStage.java @@ -1,33 +1,39 @@ package application.editor.stages; +import algorithms.Validation; import application.editor.Editor; import application.editor.FlowCellEditor; import application.editor.Stage; import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGeometry; +import com.mxgraph.model.mxGraphModel; +import com.mxgraph.model.mxGraphModel.mxTerminalChange; import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.util.mxEventSource.mxIEventListener; -import com.mxgraph.view.mxGraph; +import com.mxgraph.util.mxPoint; +import models.algebra.Expression; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; import models.dataConstraintModel.ResourcePath; import models.dataFlowModel.DataTransferChannel; import models.dataFlowModel.DataTransferModel; import models.visualModel.FormulaChannel; +import parser.Parser; +import parser.exceptions.*; import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; public class DataFlowModelingStage extends Stage { - public int PORT_DIAMETER = 8; - public int PORT_RADIUS = PORT_DIAMETER / 2; - - private boolean bReflectingArchitectureModel = false; - public DataFlowModelingStage(mxGraphComponent graphComponent) { super(graphComponent); } @Override public void init(Stage prevStage) { - // TODO Implement + // showOnlyLayers(DATA_FLOW_LAYER); } @Override @@ -37,8 +43,24 @@ @Override public mxIEventListener createChangeEventListener(Editor editor) { - // TODO Implement - return null; + return (sender, event) -> { + List terminals = new ArrayList<>(); + mxCell cell = null; + for (Object change : ((List) event.getProperties().get("changes"))) { + if (change instanceof mxTerminalChange) { + mxTerminalChange terminalChange = (mxTerminalChange) change; + cell = (mxCell) terminalChange.getCell(); + mxCell terminal = (mxCell) terminalChange.getTerminal(); + terminals.add(terminal); + } + } + if (terminals.size() == 2) { + if (!editor.connectEdge(cell, terminals.get(0), terminals.get(1))) { + graph.removeCells(new mxCell[]{cell}); + graph.clearSelection(); + } + } + }; } @Override @@ -51,65 +73,245 @@ return true; } - /** - * mxGraphのレイヤーを全てクリアする. - */ public void clear() { - // TODO Implement + ((mxGraphModel) graph.getModel()).clear(); + model = null; } public DataTransferModel getModel() { - // TODO Implement - return null; + if (model == null) { + model = new DataTransferModel(); + } + return model; } public void setModel(DataTransferModel model) { - // TODO Implement + // Clear the mxGraph + clear(); + + this.model = model; + + if (!isValid()) { + System.err.println("Model is not valid!"); + clear(); + return; + } + + // Update the mxGraph +// this.graph = constructGraph(this.graph, model); } public boolean isValid() { - // TODO Implement - return true; + if (model == null) { + return false; + } + return Validation.checkUpdateConflict(model); } - /** - * Construct a mxGraph from DataFlowModel - * - * @param graph mxGraph - * @param model DataTransferModel - * @return constructed mxGraph - */ - public mxGraph constructGraph(mxGraph graph, DataTransferModel model) { - // TODO Implement - return null; - } - - public void addResourcePath(ResourcePath res) { - // TODO Implement + public void addResourcePath(ResourcePath parentPath, String resName) { + ResourcePath resourcePath; + if (parentPath == null) { + resourcePath = new ResourcePath(resName); + getModel().addResourcePath(resourcePath); + } else { + if (resName.startsWith(Parser.LEFT_CURLY_BRACKET) && resName.endsWith(Parser.RIGHT_CURLY_BRACKET)) { + Parser.TokenStream stream = new Parser.TokenStream(); + Parser parser = new Parser(stream); + stream.addLine(resName.substring(1, resName.length() - 1)); + try { + Expression exp = parser.parseTerm(stream, getModel()); + resourcePath = new ResourcePath(parentPath, exp); + getModel().addResourcePath(resourcePath); + } catch (ExpectedRightBracket | WrongJsonExpression | ExpectedColon e) { + e.printStackTrace(); + } + } else { + resourcePath = new ResourcePath(parentPath, resName); + getModel().addResourcePath(resourcePath); + } + } +// resetDataFlowGraph(); + graph.getModel().beginUpdate(); + Object parent = graph.getDefaultParent(); + try { + graph.insertVertex(parent, null, resName, 20, 20, 80, 30, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex + } finally { + graph.getModel().endUpdate(); + } } public void addChannel(DataTransferChannel channelGen) { - // TODO Implement + getModel().addChannel(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(); + } } public void addIOChannel(DataTransferChannel ioChannelGen) { - // TODO Implement + getModel().addInputChannel(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(); + } } public void addFormulaChannel(FormulaChannel formulaChannelGen) { - // TODO Implement + getModel().addChannel(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(); + } } public boolean connectEdge(mxCell edge, mxCell src, mxCell dst) { - // TODO Implement +// if (bReflectingArchitectureModel) return false; + DataTransferModel model = getModel(); + Channel srcCh = model.getChannel((String) src.getValue()); + if (srcCh == null) { + srcCh = model.getInputChannel((String) src.getValue()); + if (srcCh == null) { + ResourcePath srcRes = model.getResourcePath((String) src.getValue()); + Channel dstCh = model.getChannel((String) dst.getValue()); + if (srcRes == null || dstCh == null) return false; + // resource to channel edge + ChannelMember srcCm = new ChannelMember(srcRes); + ((DataTransferChannel) dstCh).addChannelMemberAsInput(srcCm); + edge.setValue(new Editor.SrcDstAttribute(srcRes, dstCh)); +// resetDataFlowGraph(); + return true; + } + } + ResourcePath dstRes = model.getResourcePath((String) dst.getValue()); + if (dstRes == null) return false; + // channel to resource edge + ChannelMember dstCm = new ChannelMember(dstRes); + ((DataTransferChannel) srcCh).addChannelMemberAsOutput(dstCm); + edge.setValue(new Editor.SrcDstAttribute(srcCh, dstRes)); +// resetDataFlowGraph(); return true; } public void delete() { - // TODO Implement + 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.getResourcePath(srcName) != null) { + // resource to channel edge + Channel ch = model.getChannel(dstName); + ch.removeChannelMember(model.getResourcePath(srcName)); + } else if (model.getResourcePath(dstName) != null) { + // channel to resource edge + Channel ch = model.getChannel(srcName); + if (ch == null) { + ch = model.getInputChannel(srcName); + } + ch.removeChannelMember(model.getResourcePath(dstName)); + } + } else if (cell.isVertex()) { + String name = (String) cell.getValue(); + if (model.getChannel(name) != null) { + model.removeChannel(name); + } else if (model.getInputChannel(name) != null) { + model.removeInputChannel(name); + } else if (model.getResourcePath(name) != null) { + model.removeResourcePath(name); + } + } + } + graph.removeCells(graph.getSelectionCells()); +// resetDataFlowGraph(); } public void setChannelCode(DataTransferChannel ch, String code) { - // TODO Implement + ch.setSourceText(code); + Parser.TokenStream stream = new Parser.TokenStream(); + Parser parser = new Parser(stream); + + for (String line : code.split("\n")) { + stream.addLine(line); + } + try { + DataTransferChannel ch2 = parser.parseChannel(getModel()); + for (ChannelMember chm2 : ch2.getInputChannelMembers()) { + for (ChannelMember chm : ch.getInputChannelMembers()) { + if (chm2.getResource() == chm.getResource()) { + chm.setStateTransition(chm2.getStateTransition()); + break; + } + } + } + for (ChannelMember chm2 : ch2.getOutputChannelMembers()) { + for (ChannelMember chm : ch.getOutputChannelMembers()) { + if (chm2.getResource() == chm.getResource()) { + chm.setStateTransition(chm2.getStateTransition()); + break; + } + } + } + for (ChannelMember chm2 : ch2.getReferenceChannelMembers()) { + for (ChannelMember chm : ch.getReferenceChannelMembers()) { + if (chm2.getResource() == chm.getResource()) { + chm.setStateTransition(chm2.getStateTransition()); + break; + } + } + } +// resetDataFlowGraph(); + } catch (ExpectedRightBracket | ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | + ExpectedInOrOutOrRefOrSubKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | + WrongLHSExpression | WrongRHSExpression | ExpectedAssignment | ExpectedRightCurlyBracket | + WrongPathExpression | WrongJsonExpression | ExpectedColon e) { + e.printStackTrace(); + } } } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java index dbf2c92..7d6d99b 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionCellEditor.java @@ -1,12 +1,18 @@ package application.editor.stages; import application.editor.FlowCellEditor; +import com.mxgraph.model.mxIGraphModel; import com.mxgraph.swing.mxGraphComponent; +import com.mxgraph.util.mxConstants; +import com.mxgraph.util.mxUtils; import com.mxgraph.view.mxCellState; +import models.dataFlowModel.PushPullAttribute; +import models.dataFlowModel.PushPullValue; import javax.swing.*; import java.awt.*; import java.util.EventObject; +import java.util.List; public class PushPullSelectionCellEditor extends FlowCellEditor { @@ -27,12 +33,71 @@ @Override public void startEditing(Object cellObj, EventObject eventObj) { - // TODO Implement + if (editingCell != null) { + stopEditing(true); + } + if (!graphComponent.getGraph().getModel().isEdge(cellObj)) { + return; + } + mxCellState state = graphComponent.getGraph().getView().getState(cellObj); + if (state != null && state.getLabel() != null && !state.getLabel().isEmpty()) { + editingCell = cellObj; + trigger = eventObj; + + double scale = Math.max(minimumEditorScale, graphComponent.getGraph().getView().getScale()); + Object value = graphComponent.getGraph().getModel().getValue(cellObj); + if (value instanceof PushPullAttribute) { + PushPullAttribute attr = (PushPullAttribute) value; + comboBox = new JComboBox<>(attr.getOptionStrings()); + comboBox.setBorder(BorderFactory.createEmptyBorder()); + comboBox.setOpaque(false); + comboBox.setBounds(getEditorBounds(state, scale)); + comboBox.setVisible(true); + graphComponent.getGraphControl().add(comboBox, 0); + comboBox.updateUI(); + } + } } @Override public void stopEditing(boolean cancel) { - // TODO Implement + if (editingCell == null) { + return; + } + comboBox.transferFocusUpCycle(); + Object cell = editingCell; + editingCell = null; + if (!cancel) { + EventObject trig = trigger; + trigger = null; + Object value = graphComponent.getGraph().getModel().getValue(cell); + if (value instanceof PushPullAttribute) { + PushPullAttribute attr = (PushPullAttribute) value; + List options = attr.getOptions(); + PushPullValue selected = null; + for (PushPullValue option : options) { + if (option.toString().equals(getCurrentValue())) { + selected = option; + break; + } + } + if (selected != null) { + options.remove(selected); + options.add(0, selected); + } + graphComponent.labelChanged(cell, attr, trig); + } + } else { + mxCellState state = graphComponent.getGraph().getView().getState(cell); + graphComponent.redraw(state); + } + + if (comboBox.getParent() != null) { + comboBox.setVisible(false); + comboBox.getParent().remove(comboBox); + } + + graphComponent.requestFocusInWindow(); } public String getCurrentValue() { @@ -43,7 +108,26 @@ * Returns the bounds to be used for the editor. */ public Rectangle getEditorBounds(mxCellState state, double scale) { - // TODO Implement - return null; + mxIGraphModel model = state.getView().getGraph().getModel(); + Rectangle bounds = state.getLabelBounds().getRectangle(); + bounds.height += 10; + + // Applies the horizontal and vertical label positions + if (model.isVertex(state.getCell())) { + String horizontal = mxUtils.getString(state.getStyle(), mxConstants.STYLE_LABEL_POSITION, mxConstants.ALIGN_CENTER); + if (horizontal.equals(mxConstants.ALIGN_LEFT)) { + bounds.x -= (int) state.getWidth(); + } else if (horizontal.equals(mxConstants.ALIGN_RIGHT)) { + bounds.x += (int) state.getWidth(); + } + String vertical = mxUtils.getString(state.getStyle(), mxConstants.STYLE_VERTICAL_LABEL_POSITION, mxConstants.ALIGN_MIDDLE); + if (vertical.equals(mxConstants.ALIGN_TOP)) { + bounds.y -= (int) state.getHeight(); + } else if (vertical.equals(mxConstants.ALIGN_BOTTOM)) { + bounds.y += (int) state.getHeight(); + } + } + bounds.setSize((int) Math.max(bounds.getWidth(), Math.round(minimumWidth * scale)), (int) Math.max(bounds.getHeight(), Math.round(minimumHeight * scale))); + return bounds; } } diff --git a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java index 40464c7..c88c642 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java +++ b/AlgebraicDataflowArchitectureModel/src/application/editor/stages/PushPullSelectionStage.java @@ -1,19 +1,31 @@ package application.editor.stages; +import algorithms.DataTransferModelAnalyzer; import application.editor.Editor; import application.editor.FlowCellEditor; import application.editor.Stage; +import com.mxgraph.model.mxCell; +import com.mxgraph.model.mxGeometry; +import com.mxgraph.model.mxGraphModel; import com.mxgraph.swing.mxGraphComponent; import com.mxgraph.util.mxEventSource.mxIEventListener; +import com.mxgraph.util.mxPoint; import com.mxgraph.view.mxGraph; -import models.dataFlowModel.DataFlowGraph; -import models.dataFlowModel.DataTransferModel; +import generators.JavaCodeGenerator; +import models.Edge; +import models.algebra.*; +import models.dataConstraintModel.Channel; +import models.dataConstraintModel.ChannelMember; +import models.dataConstraintModel.ResourcePath; +import models.dataConstraintModel.Selector; +import models.dataFlowModel.*; import java.awt.event.MouseListener; +import java.util.*; public class PushPullSelectionStage extends Stage { - protected DataFlowGraph dataFlowGraph = null; + private DataFlowGraph dataFlowGraph = null; public PushPullSelectionStage(mxGraphComponent graphComponent) { super(graphComponent); @@ -21,7 +33,12 @@ @Override public void init(Stage prevStage) { - // TODO Implement + if (prevStage instanceof DataFlowModelingStage) { + model = prevStage.getModel(); + dataFlowGraph = analyzeDataTransferModel(model); + graph = constructGraph(model, dataFlowGraph); + updateEdgeAttributes(graph, dataFlowGraph); + } } @Override @@ -31,8 +48,23 @@ @Override public mxIEventListener createChangeEventListener(Editor editor) { - // TODO Implement - return null; + return (sender, eventObject) -> { + List terminals = new ArrayList<>(); + mxCell cell = null; + for (Object change : ((List) eventObject.getProperties().get("changes"))) { + if (change instanceof mxGraphModel.mxTerminalChange) { + mxGraphModel.mxTerminalChange terminalChange = (mxGraphModel.mxTerminalChange) change; + cell = (mxCell) terminalChange.getCell(); + mxCell terminal = (mxCell) terminalChange.getTerminal(); + terminals.add(terminal); + } + } + if (terminals.size() == 2) { + // cancel connect + graph.removeCells(new mxCell[]{cell}); + graph.clearSelection(); + } + }; } @Override @@ -42,17 +74,220 @@ @Override public boolean canChangeFrom(Stage prevStage) { - // TODO Implement + if (prevStage instanceof DataFlowModelingStage) { + return ((DataFlowModelingStage) prevStage).isValid(); + } return false; } - public DataFlowGraph analyzeDataTransferModel(mxGraph graph, DataTransferModel model) { - // TODO Implement - return null; + public DataFlowGraph analyzeDataTransferModel(DataTransferModel model) { + DataFlowGraph flowGraph = DataTransferModelAnalyzer.createDataFlowGraphWithStateStoringAttribute(model); + return DataTransferModelAnalyzer.annotateWithSelectableDataTransferAttiribute(flowGraph); } private void updateEdgeAttributes(mxGraph graph, DataFlowGraph dataFlowGraph) { - // TODO Implement + 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; + if (!dataFlow.isChannelToResource()) { + ResourceNode srcRes = (ResourceNode) dataFlow.getSource(); + DataTransferChannel channel = ((ChannelNode) dataFlow.getDestination()).getChannel(); + // input edge + for (Object edge : graph.getChildEdges(parent)) { + mxCell edgeCell = (mxCell) edge; + if (edgeCell.getValue() instanceof Editor.SrcDstAttribute) { + Editor.SrcDstAttribute edgeAttr = (Editor.SrcDstAttribute) edgeCell.getValue(); + if (srcRes.getPrimaryResourcePath().equals(edgeAttr.getSource()) && channel.equals(edgeAttr.getDestination())) { + edgeCell.setValue(dataFlow.getAttribute()); + break; + } + } + } + } + } + } + } finally { + graph.getModel().endUpdate(); + } + graph.refresh(); + } + + /** + * Construct a mxGraph from DataFlowModel and DataFlowModel + * + * @param model DataTransferModel + * @param dataFlowGraph DataFlowGraph + * @return constructed mxGraph + */ + private mxGraph constructGraph(DataTransferModel model, DataFlowGraph dataFlowGraph) { +// bReflectingArchitectureModel = true; + ((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 resource vertices + for (ResourceNode resNode : dataFlowGraph.getRootResourceNodes()) { + int w = 80; + int h = 30; + ResourcePath res = resNode.getPrimaryResourcePath(); + Object resource = graph.insertVertex(parent, null, res.getLeafResourceName(), 20, 20, w, h, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex + resources.put(resNode, resource); + createChildResourceVertices(resource, resNode, resources, w, h); + } + + // create channel vertices + for (ChannelNode c : dataFlowGraph.getRootChannelNodes()) { + DataTransferChannel channel = (DataTransferChannel) c.getChannel(); + if (channel.getInputResources().size() > 0) { + // Normal channel + if (channelsIn.get(channel) == null || channelsOut.get(channel) == null) { + if (channel.getSelectors().toString() == "[]") { + Object chCell = graph.insertVertex(parent, null, channel.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, chCell); // 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, chCell); // insert the output port of a channel + channelsIn.put(channel, port_in); + channelsOut.put(channel, port_out); + } else { + for (Selector s : channel.getSelectors()) { + Expression exp = s.getExpression(); + String selName = exp.toString(); + String cName = channel.getChannelName(); + String channelName = cName + " (" + selName + ")"; + Object chCell = graph.insertVertex(parent, null, channelName, 150, 20, 60, 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, chCell); // 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, chCell); // insert the output port of a channel + channelsIn.put(channel, port_in); + channelsOut.put(channel, port_out); + } + } + } + } else { + // I/O channel + if (channelsOut.get(channel) == null) { + if (channel.getSelectors().toString() == "[]") { + Object chCell = graph.insertVertex(parent, null, channel.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, chCell); // 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, chCell); // insert the output port of a channel + channelsIn.put(channel, port_in); + channelsOut.put(channel, port_out); + } else { + for (Selector s : channel.getSelectors()) { + Expression exp = s.getExpression(); + String selName = exp.toString(); + String cName = channel.getChannelName(); + String channelName = cName + " (" + selName + ")"; + Object chCell = graph.insertVertex(parent, null, channelName, 150, 20, 60, 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, chCell); // 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, chCell); // insert the output port of a channel + channelsIn.put(channel, port_in); + channelsOut.put(channel, port_out); + } + } + } + } + } + + // add input, output and reference edges + for (Edge edge : dataFlowGraph.getEdges()) { + DataFlowEdge dfEdge = (DataFlowEdge) edge; + if (dfEdge.isChannelToResource()) { + // output edge + DataTransferChannel channel = ((ChannelNode) dfEdge.getSource()).getChannel(); + ResourcePath dstRes = ((ResourceNode) dfEdge.getDestination()).getInSideResource(channel); + graph.insertEdge(parent, null, new Editor.SrcDstAttribute(channel, dstRes), channelsOut.get(channel), resources.get((ResourceNode) dfEdge.getDestination()), "movable=false"); + } else { + // input edge + DataTransferChannel channel = ((ChannelNode) dfEdge.getDestination()).getChannel(); + ResourcePath srcRes = ((ResourceNode) dfEdge.getSource()).getOutSideResource(channel); + Set> toRes = getResourceDependencyForChannel(channel, model, dataFlowGraph); + for (Map.Entry RtoR : toRes) { + graph.insertEdge(parent, null, null, resources.get(RtoR.getValue()), resources.get(RtoR.getKey()), "dashed=true;movable=false"); + } + + graph.insertEdge(parent, null, new Editor.SrcDstAttribute(srcRes, channel), resources.get((ResourceNode) dfEdge.getSource()), channelsIn.get(channel), "movable=false"); + } + } + + for (Channel ch : model.getChannels()) { + // reference edges + DataTransferChannel channel = (DataTransferChannel) ch; + for (ResourcePath refRes : channel.getReferenceResources()) { + graph.insertEdge(parent, null, null, resources.get(dataFlowGraph.getResourceNode(refRes)), channelsIn.get(channel), "dashed=true;movable=false"); + } + } + } finally { + graph.getModel().endUpdate(); + } +// setDAGLayout(); + +// bReflectingArchitectureModel = false; + return graph; + } + + private Set> getResourceDependencyForChannel(DataTransferChannel ch, DataTransferModel model, DataFlowGraph dataFlowGraph) { + Set> resourceDependency = new HashSet<>(); + if (!ch.getOutputChannelMembers().isEmpty()) { + 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(); + } + resourceDependency.add(new AbstractMap.SimpleEntry<>(srcNode, dstNode)); + } + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | + UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + } + return resourceDependency; + } + + private void createChildResourceVertices(Object resource, ResourceNode resNode, Map resources, int w, int h) { + for (ResourceNode childNode : resNode.getChildren()) { + ResourcePath childRes = childNode.getPrimaryResourcePath(); + Object childResource = graph.insertVertex(resource, null, childRes.getName(), 0, 0, w, h, "shape=ellipse;perimeter=ellipsePerimeter"); // insert a resource as a vertex + resources.put(childNode, childResource); + createChildResourceVertices(childResource, childNode, resources, w, h); + } } public DataFlowGraph getDataFlowGraph() {