package goalModelSlicer; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.FileDialog; import java.awt.FlowLayout; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Rectangle2D; import java.io.File; import java.io.IOException; import java.util.Set; import javax.swing.BorderFactory; import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import org.jgraph.JGraph; import org.jgraph.graph.AttributeMap; import org.jgraph.graph.DefaultGraphCell; import org.jgraph.graph.GraphConstants; import org.jgrapht.ext.JGraphModelAdapter; import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.ListenableUndirectedGraph; public class Main extends JApplet { // Setting for JGraphT private static final long serialVersionUID = 3256444702936019250L; private static final Color DEFAULT_BG_COLOR = Color.decode("#FAFBFF"); private static final Dimension DEFAULT_SIZE = new Dimension(530, 320); private static JGraphModelAdapter<String, DefaultEdge> jgAdapter; // create a JGraphT graph private static ListenableUndirectedGraph<String, DefaultEdge> g = new ListenableUndirectedGraph<>( DefaultEdge.class); static Set<Goal> criterion = null; static Set<Goal> goals = null; public static void main(String[] args) { //Setting for GoalModelSlicer GUI Main applet = new Main(); applet.init(); JFrame frame = new JFrame(); Container content = frame.getContentPane(); content.setLayout(new BorderLayout()); JPanel consolePanel = new JPanel(); JTextArea console = new JTextArea(10, 97); console.setFont(new Font("Courier New", Font.PLAIN, 13)); JScrollPane consoleJsp = new JScrollPane(console); consolePanel.add(consoleJsp); JTextField csvFile = new JTextField(9); JButton openCSV = new JButton("Open"); // when button (@param: openCSV) clicked, // goal model file is parsed and shown up at the applet. openCSV.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { goals = openWindow(1, frame, console, csvFile); drawGoalModel(goals); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }); JTextField sliceCriterion = new JTextField(7); JButton openCriterion = new JButton("Open"); // when button (@param: openCriterion) clicked, // slice criterion file is parsed openCriterion.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { criterion = openWindow(2, frame, console, sliceCriterion); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }); JButton detectChange = new JButton("Detect Change-related goals"); // when button (@param: detectChange) clicked, // goal model is sliced, the old model is removed, and new sliced goal model is shown up. detectChange.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { GoalModelSlicer gms = new GoalModelSlicer(); gms.sliceGoalModel(goals, criterion); goals = gms.getSlicedGoals(); removeGoalModel(goals); drawGoalModel(goals); } }); // menu, console and applet is constructed. JPanel menuPanel = new JPanel(); menuPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); menuPanel.setPreferredSize(new Dimension(260, 600)); menuPanel.add(new JLabel(" ===== Setting Analyzer ===== ")); menuPanel.add(new JLabel("Goal model: ")); menuPanel.add(csvFile); menuPanel.add(openCSV); menuPanel.add(new JLabel("Slicing criterion:")); menuPanel.add(sliceCriterion); menuPanel.add(openCriterion); JPanel startPanel = new JPanel(); startPanel.setLayout(new FlowLayout(FlowLayout.CENTER)); startPanel.add(detectChange); menuPanel.add(startPanel); content.add("South", consolePanel); content.add("West", menuPanel); content.add("East", applet); frame.setTitle("SoS Goal Model Slicer"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } // find root goal among goal set (@param: goals) // @return root Goal public static Goal findRootGoal(Set<Goal> goals) { for (Goal goal : goals) { for (String higherGoal : goal.higherGoals) { if (higherGoal.equals("-")) return goal; } } return null; } // @return Goal which has name (@param: goalName) public static Goal findGoalByName(String goalName) { for (Goal goal : goals) { if (goal.name.equals(goalName)) return goal; } return null; } // draw goal model according to goal set (@param: goals) public static void drawGoalModel(Set<Goal> goals) { // add vertices for (Goal goal : goals) { g.addVertex(goal.name); } // add edges for (Goal goal : goals) { for (String subgoal : goal.subGoals) { if (!subgoal.equals("-")) g.addEdge(goal.name, subgoal); } } // locate vertices Goal root = findRootGoal(goals); recursiveLocate(root, 60, 20, 1); } // recursively locate rectangle with @param: goal, posX, posY, depth public static void recursiveLocate(Goal goal, int posX, int posY, int depth) { positionVertexAt(goal.name, posX, posY); int i = 0; for (String subGoalName : goal.subGoals) { if (subGoalName.equals("-")) return; recursiveLocate(findGoalByName(subGoalName), posX + (450 / ((depth + 1) * 2) * i), posY + 150, depth + 1); i++; } } // remove old goal model (@param: goals) before slicing is done. public static void removeGoalModel(Set<Goal> goals) { for (Goal goal : goals) { g.removeVertex(goal.name); for (String subGoal : goal.subGoals) { if (subGoal.equals("-")) continue; g.removeEdge(goal.name, subGoal); } } } // open file // type 1: open CSV file - goal model // type 2: open txt file - slicing criterion public static Set<Goal> openWindow(int type, JFrame frame, JTextArea console, JTextField textField) throws IOException { FileDialog fileDialog = null; if (type == 1) { fileDialog = new FileDialog(frame, "Open Goal Model", FileDialog.LOAD); fileDialog.setFile("*.csv"); fileDialog.setVisible(true); File goalModel[] = fileDialog.getFiles(); if (goalModel.length != 0) { GoalModelParser gmp = new GoalModelParser(); gmp.parseGoalModel(goalModel[0]); consolePrint(console, gmp.getGoalLog()); textField.setText(goalModel[0].getAbsolutePath()); return gmp.getGoals(); } } else if (type == 2) { fileDialog = new FileDialog(frame, "Open Slicing Criterion", FileDialog.LOAD); fileDialog.setFile("*.txt"); fileDialog.setVisible(true); File criterion[] = fileDialog.getFiles(); if (criterion.length != 0) { CriterionParser cp = new CriterionParser(); textField.setText(criterion[0].getAbsolutePath()); return cp.parseCriterion(criterion[0]); } } return null; } /** * {@inheritDoc} */ @Override public void init() { // create a visualization using JGraph, via an adapter jgAdapter = new JGraphModelAdapter<>(g); JGraph jgraph = new JGraph(jgAdapter); adjustDisplaySettings(jgraph); getContentPane().add(jgraph); resize(DEFAULT_SIZE); } private void adjustDisplaySettings(JGraph jg) { jg.setPreferredSize(DEFAULT_SIZE); Color c = DEFAULT_BG_COLOR; String colorStr = null; try { colorStr = getParameter("bgcolor"); } catch (Exception e) { } if (colorStr != null) { c = Color.decode(colorStr); } jg.setBackground(c); } @SuppressWarnings("unchecked") private static void positionVertexAt(Object vertex, int x, int y) { DefaultGraphCell cell = jgAdapter.getVertexCell(vertex); AttributeMap attr = cell.getAttributes(); AttributeMap map = new AttributeMap(); GraphConstants.setBounds(map, new Rectangle2D.Double(50, 50, 90, 30)); GraphConstants.setBorder(map, BorderFactory.createRaisedBevelBorder()); GraphConstants.setBackground(map, Color.BLUE); GraphConstants.setForeground(map, Color.white); GraphConstants.setFont(map, GraphConstants.DEFAULTFONT.deriveFont(Font.BOLD, 12)); GraphConstants.setOpaque(map, true); Rectangle2D bounds = GraphConstants.getBounds(map); Rectangle2D newBounds = new Rectangle2D.Double(x, y, bounds.getWidth(), bounds.getHeight()); GraphConstants.setBounds(map, newBounds); GraphConstants.setBounds(attr, newBounds); AttributeMap cellAttr = new AttributeMap(); if (findGoalByName((String) vertex).isSliced) cellAttr.put(cell, map); else cellAttr.put(cell, attr); jgAdapter.edit(cellAttr, null, null, null); } // print text (@param: text) at console (@param: console) public static void consolePrint(JTextArea console, String text) { console.append(text); console.setCaretPosition(console.getDocument().getLength()); console.requestFocus(); } }