Browse Source

Improves ConnectionCreationPanel and Controller.changeRoleOfDevice()

Fixes a spelling mistake in MQTT Roles Array.
ComboBoxes now show the right selected Indices on startUp of the
ConnectionCreationPanel and try to keep role on protocol change.
Disallow changes to invalid roles or protocols.
Adds some comments to the ConnectionCreationPanel.
Andreas T. Meyer-Berg 5 years ago
parent
commit
c6f54e9736

+ 15 - 5
src/main/java/de/tu_darmstadt/tk/SmartHomeNetworkSim/control/Controller.java

@@ -348,14 +348,24 @@ public class Controller {
 		smartDevice.removeLink(newLink);
 	}
 	
-	public void changeRoleOfDevice(Protocol protocol, Port device, int newRole){
-		if(newRole < 0 || newRole >= protocol.getNumberOfRoles())
+	/**
+	 * Changes Roles of the device to the newRole, returns true, if the role was successfully changed, false if not.
+	 * If false is returned, the device will no longer be part of this connection.
+	 * 
+	 * @param protocol protocol which should be edited
+	 * @param device device which should be added
+	 * @param newRole new role of the device
+	 * @return true if new role was set, false if not
+	 */
+	public boolean changeRoleOfDevice(Protocol protocol, Port device, int newRole){
+		if(newRole < 0 || newRole >= protocol.getNumberOfRoles()){
 			protocol.removeDevice(device);
-		else if(protocol.getDevicesWithRole(newRole).contains(device))
-			return;
+			return false;
+		} else if(protocol.getDevicesWithRole(newRole).contains(device))
+			return true;
 		else{
 			protocol.removeDevice(device);
-			protocol.addDeviceOfRole(device, newRole);
+			return protocol.addDeviceOfRole(device, newRole);
 		}
 	}
 }

+ 1 - 1
src/main/java/de/tu_darmstadt/tk/SmartHomeNetworkSim/core/protocols/MQTT_protocol.java

@@ -195,7 +195,7 @@ public class MQTT_protocol implements Protocol {
 	@Override
 	public String[] getRoles() {
 		// PublisherSubscriber is Publisher as well as Subscriber
-		return new String[] { "Broker", "PublisherSubsriber", "Publisher", "Subscriber" };
+		return new String[] { "Broker", "PublisherSubscriber", "Publisher", "Subscriber" };
 	}
 
 	@Override

+ 247 - 150
src/main/java/de/tu_darmstadt/tk/SmartHomeNetworkSim/view/ConnectionCreationPanel.java

@@ -4,11 +4,9 @@ import java.awt.Dimension;
 import java.awt.Window;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.lang.reflect.InvocationTargetException;
 import java.util.Collection;
 import java.util.LinkedList;
-
-import javax.swing.JFrame;
+import java.util.concurrent.ThreadLocalRandom;
 
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.control.Controller;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Connection;
@@ -22,6 +20,7 @@ import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.protocols.MQTT_protocol;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleLink;
 import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.simpleImplementation.SimpleProtocol;
 
+import javax.swing.JFrame;
 import javax.swing.JPanel;
 import javax.swing.JLabel;
 import javax.swing.JScrollPane;
@@ -32,22 +31,72 @@ import javax.swing.JComboBox;
 import javax.swing.JButton;
 
 @SuppressWarnings("serial")
-public class ConnectionCreationPanel extends JScrollPane{
-	
+public class ConnectionCreationPanel extends JScrollPane {
+
+	/**
+	 * 
+	 */
 	JPanel content;
+
+	/**
+	 * Textfield which stores the Name of the connection
+	 */
 	private JTextField tfName;
-	
+
+	/**
+	 * Parent window which contains this frame - for the close operation
+	 */
 	private Window frame;
-	
+
+	/**
+	 * Connection which is edited
+	 */
 	private Connection connection;
+	
+	/**
+	 * Index of the disconnected option in the boxes Array 
+	 */
+	private int disconnectedIndex;
+
+	/**
+	 * Ports which could participate in the connection
+	 */
 	private Port[] ports;
+
+	/**
+	 * ComboBoxes to allow role changes of the different Ports
+	 */
 	private JComboBox<String>[] boxes;
+
+	/**
+	 * True if an existing connection is being edited, or false if a new one is
+	 * being created
+	 */
 	private boolean edit;
-	
-	private LinkedList<Class<? extends Protocol>> availableProtocols;
+
+	/**
+	 * Last index which was selected in the linkType ComboBox, to allow restore
+	 * the selected Index in case of invalid protocols
+	 */
 	private int lastIndex = 0;
+
+	/**
+	 * Mutex for the protocol change, so the different Devices don't change
+	 * their role, while their comboBoxes are updated. True if the protocol
+	 * change is in progress and the boxes should not update their role.
+	 */
+	private boolean protocolChange = false;
+	/**
+	 * Controller to
+	 */
 	private Controller controller;
-	
+
+	/**
+	 * List of available protocols -> should be moved to the Model and accessed
+	 * via controller
+	 */
+	private LinkedList<Class<? extends Protocol>> availableProtocols;
+
 	/**
 	 * @wbp.parser.constructor
 	 */
@@ -58,248 +107,295 @@ public class ConnectionCreationPanel extends JScrollPane{
 		edit = true;
 		initializePanel();
 	}
-	
-	public ConnectionCreationPanel(Collection<Port> ports,Link l, Controller controller) {
+
+	public ConnectionCreationPanel(Collection<Port> ports, Link l,
+			Controller controller) {
 		this.controller = controller;
-		connection = new ConnectionImplementation(l, new SimpleProtocol(null, null));
+		connection = new ConnectionImplementation(l, new SimpleProtocol(null,
+				null));
 		this.ports = new Port[ports.size()];
-		int i=0;
-		for(Port d: ports){
-			//controller.addLinkToDevice(connection, d);
+		int i = 0;
+		for (Port d : ports) {
+			// controller.addLinkToDevice(connection, d);
 			this.ports[i++] = d;
 		}
 		edit = false;
 		initializePanel();
 	}
-	
+
+	@SuppressWarnings("unchecked")
 	private void initializePanel() {
+		disconnectedIndex = connection.getProtocol().getNumberOfRoles();
+		
 		availableProtocols = new LinkedList<Class<? extends Protocol>>();
 		availableProtocols.add(MQTT_protocol.class);
 		availableProtocols.add(SimpleProtocol.class);
-		
-		
+
 		setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
-		this.setPreferredSize(new Dimension(600, 170 + ports.length*20));
+		this.setPreferredSize(new Dimension(600, 170 + ports.length * 20));
 		content = new JPanel();
-		content.setPreferredSize(new Dimension(600, 150 + ports.length*20));
+		content.setPreferredSize(new Dimension(600, 150 + ports.length * 20));
 		this.setViewportView(content);
 		content.setLayout(null);
-		
+
 		JLabel lblDescription = new JLabel("Connection Creation");
 		lblDescription.setBounds(12, 13, 476, 16);
 		content.add(lblDescription);
-		
+
 		JLabel lblName = new JLabel("Name:");
 		lblName.setHorizontalAlignment(SwingConstants.RIGHT);
 		lblName.setBounds(12, 42, 138, 16);
 		content.add(lblName);
-		
+
 		tfName = new JTextField();
 		tfName.setText(connection.getName());
 		tfName.setBounds(162, 39, 300, 22);
 		content.add(tfName);
 		tfName.setColumns(10);
 		tfName.addActionListener(new ActionListener() {
-			
+
 			@Override
 			public void actionPerformed(ActionEvent e) {
 				connection.setName(tfName.getText());
 			}
 		});
-		
+
 		JLabel lblLinkType = new JLabel("Type:");
 		lblLinkType.setHorizontalAlignment(SwingConstants.RIGHT);
 		lblLinkType.setBounds(12, 71, 138, 16);
 		content.add(lblLinkType);
-		
+
 		JComboBox<String> cmbLinkType = new JComboBox<String>();
-		for(int i = 0; i<availableProtocols.size();i++)
+		for (int i = 0; i < availableProtocols.size(); i++)
 			try {
-				cmbLinkType.addItem(availableProtocols.get(i).newInstance().getName());
+				cmbLinkType.addItem(availableProtocols.get(i).newInstance()
+						.getName());
 			} catch (InstantiationException | IllegalAccessException e1) {
-				e1.printStackTrace();
+				System.out.println("Protocol " + i + " is invalid");
 				cmbLinkType.addItem("unknown");
 			}
 		cmbLinkType.setBounds(162, 68, 116, 22);
 		content.add(cmbLinkType);
+		// Set Index to selected Protocol
+		for (int i = 0; i < availableProtocols.size(); i++)
+			if (connection.getProtocol().getClass()
+					.equals(availableProtocols.get(i)))
+				cmbLinkType.setSelectedIndex(i);
+
+		// Add Functionality for changing protocol
 		cmbLinkType.addActionListener(new ActionListener() {
-			
 			@Override
 			public void actionPerformed(ActionEvent e) {
+				/**
+				 * Old Protocol
+				 */
 				Protocol oldProtocol = connection.getProtocol();
+				//Set Mutex to true, to disallow changes of roles during the editing
+				protocolChange = true;
+				/**
+				 * New Protocol which should be created and configured
+				 */
 				Protocol newProtocol = null;
 				try {
-					newProtocol = availableProtocols.get(cmbLinkType.getSelectedIndex()).newInstance();
-				} catch (InstantiationException e1) {
-					// TODO Auto-generated catch block
-					e1.printStackTrace();
-				} catch (IllegalAccessException e1) {
-					// TODO Auto-generated catch block
-					e1.printStackTrace();
+					//Create new Instance of the protocol
+					newProtocol = availableProtocols.get(
+							cmbLinkType.getSelectedIndex()).newInstance();
+				} catch (InstantiationException | IllegalAccessException e1) {
+					System.out
+							.println("WARNING: Protocol could not be initialized");
 				}
-				if( newProtocol == null){
+				if (newProtocol == null) {
 					cmbLinkType.setSelectedIndex(lastIndex);
-					System.out.println("WARNING: Invalid Protocol Selected");
-				}else{
-					System.out.println("WARNING: No  further Link Types in progress");
+					System.out
+							.println("WARNING: Invalid Protocol Selected - restore last index");
+				} else {
+					/**
+					 * New Roles as Strings
+					 */
 					String[] newRoles = newProtocol.getRoles();
+					/**
+					 * The old disconnected status
+					 */
 					int oldDisconnected = oldProtocol.getNumberOfRoles();
-					for(int i = 0; i<boxes.length; i++){
+					//Update to new disconnected Index
+					disconnectedIndex = newProtocol.getNumberOfRoles();
+					//Update Boxes
+					for (int i = 0; i < boxes.length; i++) {
+						/**
+						 * The previous selected Index
+						 */
 						int oldSelected = boxes[i].getSelectedIndex();
+						//Update Labels of the current Box
 						boxes[i].removeAllItems();
-						for(int j = 0; j < newRoles.length; j++)
+						for (int j = 0; j < newRoles.length; j++)
 							boxes[i].addItem(newRoles[j]);
 						boxes[i].addItem("Disconnected");
-						if(oldSelected<0||oldSelected>=newRoles.length)
-							boxes[i].setSelectedIndex(newRoles.length);
-						else
-							if(newProtocol.addDeviceOfRole(ports[i], oldSelected))
-								boxes[i].setSelectedItem(oldSelected);
-							else
-								boxes[i].setSelectedItem(newRoles.length);
+						//Try to update the Roles
+						if (oldSelected < 0 || oldSelected >= disconnectedIndex
+								|| oldSelected == oldDisconnected) {
+							//Invalid Index -> Disconnected
+							boxes[i].setSelectedIndex(disconnectedIndex);
+						} else {
+							if (newProtocol.addDeviceOfRole(ports[i],
+									oldSelected)) {
+								//Set to Box to display role
+								boxes[i].setSelectedIndex(oldSelected);
+							} else {
+								//Could not be added -> Disconnected
+								boxes[i].setSelectedIndex(disconnectedIndex);
+							}
+						}
 					}
-					//Update all Boxes, Roles etc.
+					// Update all Boxes, Roles etc.
+					connection.setProtocol(newProtocol);
+					// Update lastIndex to new Index
+					lastIndex = cmbLinkType.getSelectedIndex();
 				}
-				//Link changing possibility, port all comboboxes - change combobox options
+				//Set Mutex back to false - allow changes
+				protocolChange = false;
 			}
 		});
-		
+
 		JButton btnImportLink = new JButton("Import Link Type");
 		btnImportLink.setBounds(290, 67, 144, 25);
 		content.add(btnImportLink);
-		btnImportLink.addActionListener(a->System.out.println("WARNING: No import yet"));
-		
+		btnImportLink.addActionListener(a -> System.out
+				.println("WARNING: No import yet"));
+
 		JButton btnCreate = new JButton("Verify and Create");
 		btnCreate.setBounds(121, 103, 206, 25);
 		content.add(btnCreate);
 		btnCreate.addActionListener(new ActionListener() {
-			
+
 			@Override
 			public void actionPerformed(ActionEvent e) {
-				/* 
-				if(!edit){
-					controller.addLink(connection);
-				}*/
+				/*
+				 * if(!edit){ controller.addLink(connection); }
+				 */
 				connection.setName(tfName.getText());
 				content.setVisible(false);
 				setVisible(false);
-				if(frame != null){
+				if (frame != null) {
 					frame.setVisible(false);
 					frame.dispose();
 				}
 			}
 		});
 		
+		/**
+		 * Height of the current Box which is being created
+		 */
 		int currentHeight = 150;
+
 		boxes = new JComboBox[ports.length];
-		for(int i = 0; i < ports.length;i++){
+		for (int i = 0; i < ports.length; i++) {
+			//Effectively final variables for the action listener
 			int pos = i;
 			Port currentPort = ports[i];
 			SmartDevice currentDevice = currentPort.getOwner();
-			JLabel lblDevice = new JLabel(currentDevice.getName()+":"+currentPort.getPortNumber()+":");
+			
+			JLabel lblDevice = new JLabel(currentDevice.getName() + ":"
+					+ currentPort.getPortNumber() + ":");
 			lblDevice.setHorizontalAlignment(SwingConstants.RIGHT);
 			lblDevice.setBounds(10, currentHeight, 230, 18);
 			content.add(lblDevice);
-			
+
 			boxes[pos] = new JComboBox<String>();
-			for(String role:connection.getProtocol().getRoles())
+			for (String role : connection.getProtocol().getRoles())
 				boxes[pos].addItem(role);
 			boxes[pos].addItem("Disconnected");
 			boxes[pos].setBounds(250, currentHeight, 240, 18);
 			content.add(boxes[pos]);
+			if(edit){
+				int roleOfDevice = connection.getProtocol().getRoleOfDevice(currentPort);
+				if(roleOfDevice != -1)
+					boxes[pos].setSelectedIndex(roleOfDevice);
+				else
+					boxes[pos].setSelectedIndex(disconnectedIndex);
+			} else {
+				/**
+				 * Number of tries to add the Port
+				 */
+				int n = 5;
+				for(int j = 0; j <= n; j++){
+					if(j == 0){//Try to add Router first
+						if(connection.getProtocol().addDeviceOfRole(currentPort, 0)){
+							boxes[pos].setSelectedIndex(0);
+							break;
+						}										
+					}else if(j == n){//If it could not be added
+						boxes[pos].setSelectedIndex(disconnectedIndex);
+						break;
+					}else{
+						int randomRole = ThreadLocalRandom.current().nextInt(0, disconnectedIndex);
+						if(connection.getProtocol().addDeviceOfRole(currentPort, randomRole)){
+							boxes[pos].setSelectedIndex(randomRole);
+							break;
+						}
+					}
+				}
+			}
 			boxes[pos].addActionListener(new ActionListener() {
-				
+
 				@Override
 				public void actionPerformed(ActionEvent e) {
+					if (protocolChange) {
+						return;
+					}
+					/**
+					 * Selected Index of the ComboBox, which represents the new role (or disconnected)
+					 */
 					int selected = boxes[pos].getSelectedIndex();
-					if(selected==-1)
-						System.out.println("Changed "+lblDevice.getText()+" to -1");
-					else if(selected<connection.getProtocol().getNumberOfRoles())
-						System.out.println("Changed "+lblDevice.getText()+" to "+connection.getProtocol().getRoles()[selected]);
-					else
-						System.out.println("Changed "+lblDevice.getText()+" to Disconnected");
-					
-					controller.changeRoleOfDevice(connection.getProtocol(), ports[pos], selected);
+					/**
+					 * True if role was successfully changed
+					 */
+					boolean successfullChange = controller.changeRoleOfDevice(connection.getProtocol(),
+							ports[pos], selected);
+					/**
+					 * Set to Disconnected, if role could not be changed
+					 */
+					if(!successfullChange){
+						boxes[pos].setSelectedIndex(connection.getProtocol().getNumberOfRoles());
+					}	
 				}
 			});
 			currentHeight += 20;
 		}
-		/*
-		JLabel lblDeviceA = new JLabel("DeviceA:");
-		lblDeviceA.setHorizontalAlignment(SwingConstants.RIGHT);
-		lblDeviceA.setBounds(12, 141, 138, 16);
-		content.add(lblDeviceA);
-		
-		JLabel lblDeviceb = new JLabel("DeviceB:");
-		lblDeviceb.setHorizontalAlignment(SwingConstants.RIGHT);
-		lblDeviceb.setBounds(12, 170, 138, 16);
-		content.add(lblDeviceb);
-		
-		JLabel lblDeviceC = new JLabel("DeviceC:");
-		lblDeviceC.setHorizontalAlignment(SwingConstants.RIGHT);
-		lblDeviceC.setBounds(12, 199, 138, 16);
-		content.add(lblDeviceC);
-		
-		JComboBox<String> cmbDev1 = new JComboBox<String>();
-		cmbDev1.addItem("Connected");
-		cmbDev1.addItem("Disconnected");
-		cmbDev1.setBounds(162, 138, 165, 22);
-		content.add(cmbDev1);
-		
-		JComboBox<String> cmbDev2 = new JComboBox<String>();
-		cmbDev1.addItem("Connected");
-		cmbDev1.addItem("Disconnected");
-		cmbDev2.setBounds(162, 167, 165, 22);
-		content.add(cmbDev2);
-		
-		JComboBox<String> cmbDev3 = new JComboBox<String>();
-		cmbDev1.addItem("Connected");
-		cmbDev1.addItem("Disconnected");
-		cmbDev3.setBounds(162, 196, 165, 22);
-		content.add(cmbDev3);*/
 	}
 
-	
-	 /**
-     * Test the Panel
-     */
-    private static void testGUI() {
-        JFrame frame = new JFrame("LinkCreation Panel");
-        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- 
-        ConnectionCreationPanel panel;
-        Link testNet = new SimpleLink("Test Network");
-        LinkedList<SmartDevice> devicesOfLink = new LinkedList<SmartDevice>();
-        LinkedList<Port> ports = new LinkedList<Port>();
-        for(int i = 0; i<5; i++){
-        	SmartDevice d = new SmartDevice("Device" + i);
-        	Port p = new Port(d, (short) i);
-        	d.addPort(p);
-        	devicesOfLink.add(d);
-        	ports.add(p);
-        }
-        panel = new ConnectionCreationPanel(ports,testNet, new Controller(new Model()));
-        /*
-        Link testNet = new SimpleLink("Test Network");
-        for(int i = 0; i<5; i++)
-        	testNet.addDevice(new SmartDevice("Device" + i));
-        panel = new LinkCreationPanel(testNet);
-        */
-        panel.setFrame(frame);
-        frame.setContentPane(panel);
-        frame.pack();
-        frame.setVisible(true);
-    }
-    
-
- 
-    public static void main(String[] args) {
-        javax.swing.SwingUtilities.invokeLater(new Runnable() {
-            public void run() {
-                testGUI();
-            }
-        });
-    }
+	/**
+	 * Test the Panel
+	 */
+	private static void testGUI() {
+		JFrame frame = new JFrame("LinkCreation Panel");
+		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+		ConnectionCreationPanel panel;
+		Link testNet = new SimpleLink("Test Network");
+		LinkedList<SmartDevice> devicesOfLink = new LinkedList<SmartDevice>();
+		LinkedList<Port> ports = new LinkedList<Port>();
+		for (int i = 0; i < 5; i++) {
+			SmartDevice d = new SmartDevice("Device" + i);
+			Port p = new Port(d, (short) i);
+			d.addPort(p);
+			devicesOfLink.add(d);
+			ports.add(p);
+		}
+		panel = new ConnectionCreationPanel(ports, testNet, new Controller(
+				new Model()));
+		panel.setFrame(frame);
+		frame.setContentPane(panel);
+		frame.pack();
+		frame.setVisible(true);
+	}
+
+	public static void main(String[] args) {
+		javax.swing.SwingUtilities.invokeLater(new Runnable() {
+			public void run() {
+				testGUI();
+			}
+		});
+	}
 
 	/**
 	 * @return the frame
@@ -309,7 +405,8 @@ public class ConnectionCreationPanel extends JScrollPane{
 	}
 
 	/**
-	 * @param frame the frame to set
+	 * @param frame
+	 *            the frame to set
 	 */
 	public void setFrame(Window frame) {
 		this.frame = frame;