package de.tu_darmstadt.tk.SmartHomeNetworkSim.control; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Connection; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Link; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Model; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.PacketCollector; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Port; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Protocol; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.SmartDevice; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.configuration.NetworkTreeNodeStatus; import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.configuration.SelectionModel; /** * Controller for manipulation of the network model with methods like * * * @author Andreas T. Meyer-Berg */ public class NetworkController { /** * Model which will be manipulated */ private Model model; /** * Controller which can be use */ private Controller controller; /** * NetworkTreeSettings Controller */ private NetworkTreeSettingsController networkTreeSettings; /** * Packet Capture Controller */ private PacketCaptureController captureController; /** * ExampleAnomalyController */ private ExampleAnomalyController anomalyController; /** * Creates a new NetworkController, which may manipulate the given model and use the controller * @param model Model which can be manipulated * @param controller main controller for updates etc */ public NetworkController(Model model, Controller controller) { this.model = model; this.controller = controller; networkTreeSettings = controller.getSettingsController().getNetworkTreeSettingsController(); captureController = controller.getSimulationController().getPacketCaptureController(); anomalyController = new ExampleAnomalyController(controller); } /** * Validate all device positions, move all devices into the bounds, if they are outside the visualization */ public void validateDevicePosition() { // Update all device positions for (SmartDevice d : model.getDevices()) { d.setX(controller.getSettingsController().scalePos(d.getX(), 1.0, controller.getSettingsController().getWidth())); d.setY(controller.getSettingsController().scalePos(d.getY(), 1.0, controller.getSettingsController().getHeight())); d.setZ(controller.getSettingsController().scalePos(d.getZ(), 1.0, controller.getSettingsController().getDepth())); } } /** * Adds SmartDevice to the Model and verifies that it is inside the model * bounds * * @param sd * SmartDevice which should be added to the model */ public void addSmartDevice(SmartDevice sd) { if (model.getDevices().contains(sd)) return; model.addDevices(sd); // validate Position sd.setX(controller.getSettingsController().scalePos(sd.getX(), 1.0, controller.getSettingsController().getWidth())); sd.setY(controller.getSettingsController().scalePos(sd.getY(), 1.0, controller.getSettingsController().getHeight())); sd.setZ(controller.getSettingsController().scalePos(sd.getZ(), 1.0, controller.getSettingsController().getDepth())); } /** * Creates a new SmartDevice at the given Position. The Device is moved * into the model bounds, if the position is outside the bounds * * @param name * name of the smartDevice * @param x_pos * position on the x-Axis * @param y_pos * position on the y-Axis * @param z_pos * position on the z-Axis */ public SmartDevice createSmartDevice(String name, int x_pos, int y_pos, int z_pos) { SmartDevice sd = new SmartDevice(name); sd.setX(controller.getSettingsController().scalePos(x_pos, 1.0, controller.getSettingsController().getWidth())); sd.setY(controller.getSettingsController().scalePos(y_pos, 1.0, controller.getSettingsController().getHeight())); sd.setZ(controller.getSettingsController().scalePos(z_pos, 1.0, controller.getSettingsController().getDepth())); model.addDevices(sd); return sd; } /** * Deletes the given SmartDevice toDelete, removes it from its links and * connections. * * @param toDelete * the SmartDevice to delete */ public void deleteSmartDevice(SmartDevice toDelete) { if (toDelete == null) return; // Remove from Collectors PacketCaptureController captureController = controller.getSimulationController().getPacketCaptureController(); for(PacketCollector collector:captureController.getPacketCollectors()){ if(collector.getDevices().contains(toDelete)){ captureController.removeDeviceFromCollector(collector, toDelete); } } // Delete Connections for (Port p : toDelete.getPorts()) { //Skip ports that are not connected if(p.getConnection()==null) continue; removeDeviceFromConnectionAndProtocol(p, p.getConnection()); } // Remove from Links LinkedList links = new LinkedList(toDelete.getLinks()); for (Link link : links) removeSmartDeviceFromLink(toDelete, link); links.clear(); // Remove Links from Device toDelete.getLinks().clear(); //Remove all ports from the device toDelete.getPorts().clear(); //Remove from network Tree networkTreeSettings.removeStatusOfObject(toDelete); model.getDevices().remove(toDelete); } /** * Returns smartDevices of the model, which are not hidden * @return all SmartDevices which are not hidden */ public Collection getVisibleSmartDevices(){ LinkedList devices = new LinkedList(model.getDevices()); devices.removeIf(c->!controller.getSettingsController().getNetworkTreeSettingsController().isVisible(c)); return devices; } /** * Returns smartDevices of the model * @return all SmartDevices of the model */ public Collection getSmartDevices(){ return model.getDevices(); } /** * Removes the SmartDevice from the given Link * * @param toRemove the Device that should be removed from the link * @param link the Link, which contains the SmartDevice */ public void removeSmartDeviceFromLink(SmartDevice toRemove, Link link) { if(link != null){ link.removeDevice(toRemove); if(link.getDevices().size()==0) deleteLink(link); } if(toRemove!=null) toRemove.removeLink(link); } /** * Moves the SmartDevice device to the specified location, if it exists * * @param device * the device to move * @param x * new x position * @param y * new y position * @param z * new z position */ public void moveSmartDevice(SmartDevice device, int x, int y, int z) { device.setX(x); device.setY(y); device.setZ(z); } /** * Adds Link to the model * @param link link to add */ public void addLink(Link link){ if(link!=null && !model.getConnectionNetworks().contains(link)) model.addConnectionNetwork(link); } /** * Removes Link from the Model * @param link link to remove */ public void removeLink(Link link){ model.getConnectionNetworks().remove(link); } /** * Return visible links of the model * @return visible link */ public Collection getVisibleLinks(){ LinkedList links = new LinkedList(model.getConnectionNetworks()); links.removeIf(c->!controller.getSettingsController().getNetworkTreeSettingsController().isVisible(c)); return links; } /** * Return links of the model * @return link */ public Collection getLinks(){ return model.getConnectionNetworks(); } /** * Add Connection to the model * @param connection connection to be added */ public void addConnection(Connection connection){ if(connection!=null && !getConnections().contains(connection)) model.addConnection(connection); } /** * Remove the connection from the model * @param connection connection to be removed */ public void removeConnection(Connection connection){ model.getConnections().remove(connection); } /** * Returns visible connections of the model * @return visible connections */ public Collection getVisibleConnections(){ LinkedList links = new LinkedList(model.getConnections()); links.removeIf(c->!controller.getSettingsController().getNetworkTreeSettingsController().isVisible(c)); return links; } /** * Returns connections of the model * @return connections */ public Collection getConnections(){ return model.getConnections(); } /** * Adds the smartDevice to the link * @param link link to be added to the device * @param smartDevice device to be added to the link */ public void addLinkToDevice(Link link, SmartDevice smartDevice) { if(link == null || smartDevice == null)return; if(!link.getDevices().contains(smartDevice)){ link.addDevice(smartDevice); } if(!smartDevice.getLinks().contains(link)){ smartDevice.addLink(link); } } /** * Remove the smartDevice from the link * @param link link, the device should be removed from * @param smartDevice device which should be removed */ public void removeLinkFromDevice(Link link, SmartDevice smartDevice) { if(smartDevice!=null) smartDevice.removeLink(link); if(link!=null){ link.removeDevice(smartDevice); if(link.getDevices().size()==0) deleteLink(link); } } /** * 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 con Connection, which contains the protocol * @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, Connection con, Port device, int newRole){ if(newRole < 0 || newRole >= protocol.getNumberOfRoles()){ protocol.removeDevice(device); removeDeviceFromConnectionAndProtocol(device, con); return false; } else if(protocol.getDevicesWithRole(newRole).contains(device)){ if(!con.getParticipants().contains(device)) con.addSmartDevice(device); if(device.getConnection()!=con) device.setConnection(con); return true; } else{ protocol.removeDevice(device); boolean added = protocol.addDeviceOfRole(device, newRole); if(added){ if(!con.getParticipants().contains(device)) con.addSmartDevice(device); if(device.getConnection()!=con) device.setConnection(con); return true; }else{ if(con.getParticipants().contains(device)) con.removeSmartDevice(device); if(device.getConnection()!=null) device.setConnection(null); return false; } } } /** * Removes Device p from the Connection and Protocol * @param p Port/Device to remove * @param connection connection, which should remove the device */ public void removeDeviceFromConnectionAndProtocol(Port p, Connection connection){ if(connection != null){ connection.removeSmartDevice(p); //TODO: Protocol ? if(connection.getProtocol()!=null){ connection.getProtocol().removeDevice(p); if(connection.getParticipants().size() == 0) deleteConnection(connection); } } if(p!=null && p.getConnection() == connection) p.setConnection(null); } /** * Removes Device p from the Connection and Protocol * @param p Port/Device to remove * @param connection connection, which should remove the device */ public void removeDeviceFromConnection(Port p, Connection connection){ if(connection != null){ connection.removeSmartDevice(p); p.setConnection(null); if(connection.getParticipants().isEmpty()) deleteConnection(connection); } if(p != connection) p.setConnection(null); } /** * Adds Device p to the connection with the specified role * @param p Port/Device to be added * @param connection Connection * @param role new role of the device (See {@link Protocol} Roles) * @return true, if the device was added */ public boolean addDeviceToConnectionAndProtocol(Port p, Connection connection, int role){ if(connection.getProtocol().getDevicesWithRole(role).contains(p) || connection.getProtocol().addDeviceOfRole(p, role)){ //If port already has the role, or it could be assigned - just check the fields if(!connection.getParticipants().contains(p)) connection.addSmartDevice(p); if(p.getConnection()!=connection) p.setConnection(connection); if(!p.getOwner().getPorts().contains(p)) p.getOwner().addPort(p); return true; }else { //Device could not be added -> Remove if(p.getConnection()==connection) p.setConnection(null); if(connection.getParticipants().contains(p)) connection.removeSmartDevice(p); if(connection.getProtocol().getDevices().contains(p)) connection.getProtocol().removeDevice(p); return false; } } /** * Adds Device p to the connection * @param p Port/Device to be added * @param connection Connection */ public void addDeviceToConnection(Port p, Connection connection){ if(p==null || connection == null) return; if(!connection.getParticipants().contains(p)) connection.addSmartDevice(p); p.setConnection(connection); } /** * Changes the link of the given connection to the new link. Returns true if it was successfully changed, false if it could not be changed. * @param connection connection which should be edited * @param link new link * @return true on successful change, false on failure and restore */ public boolean changeLinkOfConnection(Connection connection, Link link) { if(connection !=null && link != null){ addConnectionToLink(connection, link); return true; }else{ return false; } } /** * Adds the given connection to the link * @param connection connection to be added * @param link link the connection should be added to */ public void addConnectionToLink(Connection connection, Link link) { if(connection == null || link == null)return; /** * Remove connection from Old Link */ if(connection.getLink()!=null) removeConnectionFromLink(connection, connection.getLink()); /** * Add Connection to new Link */ connection.setLink(link); if(!link.getConnections().contains(connection)) link.addConnection(connection); /** * */ for(Port p:connection.getParticipants()){ if(p!=null && !link.getDevices().contains(p.getOwner())){ addLinkToDevice(link, p.getOwner()); } } } /** * Changes the type of the connection to the new Type and updates all references * @param connection connection to be updated * @param newConnectionClass class of new type * @return newly created connection */ public Connection changeConnectionType(Connection connection, Class newConnectionClass) { Connection newCon = null; try{ newCon = newConnectionClass.newInstance(); copyNetworkTreeStatus(connection, newCon); newCon.setProtocol(connection.getProtocol()); newCon.setStatus(connection.getStatus()); newCon.setPacketLossProbability(connection.getPacketLossProbability()); newCon.setName(connection.getName()); if(getConnections().contains(connection)){ removeConnection(connection); addConnection(newCon); } addConnectionToLink(newCon, connection.getLink()); connection.setProtocol(null); for (Iterator p = connection.getParticipants().iterator(); p.hasNext();) { Port type = (Port) p.next(); removeDeviceFromConnection(type, connection); addDeviceToConnection(type, newCon); } }catch(Exception e){ System.out.println("Error while changing protocol: "+e.toString()); /** * Restore old connection on Failure */ if(newCon != null){ if(getConnections().contains(newCon)){ removeConnection(newCon); addConnection(connection); } if(newCon.getProtocol()!=null){ connection.setProtocol(newCon.getProtocol()); newCon.setProtocol(null); } if(newCon.getLink()!=null) newCon.getLink().removeConnection(newCon); newCon.setLink(null); for (Iterator p = connection.getParticipants().iterator(); p.hasNext();) { Port type = (Port) p.next(); if(type.getConnection()!=connection) type.setConnection(connection); newCon.removeSmartDevice(type); } } return null; } controller.getSettingsController().getConfigurationManager().getSelectionModel().clickedConnection.clear(); connection.setProtocol(null); deleteConnection(connection); controller.notifyObservers(); return newCon; } /** * Deletes the network model, removes all Devices, Connections and Links */ public void deleteNetworkModel(){ /** * Devices which should be deleted */ LinkedList devicesToDelete = new LinkedList(model.getDevices()); for(SmartDevice d: devicesToDelete) deleteSmartDevice(d); devicesToDelete.clear(); /** * Connections which should be deleted */ LinkedList connectionsToDelete = new LinkedList(model.getConnections()); for(Connection c: connectionsToDelete) deleteConnection(c); connectionsToDelete.clear(); /** * Links which should be deleted */ LinkedList linksToDelete = new LinkedList(model.getConnectionNetworks()); for(Link l: model.getConnectionNetworks()) deleteLink(l); linksToDelete.clear(); /** * Delete Collectors */ LinkedList collectors = new LinkedList(captureController.getPacketCollectors()); for(PacketCollector p:collectors){ captureController.removePacketCollector(p); } /** * Clear event queue */ /** * Update the GUI */ controller.notifyObservers(); } /** * Deletes the Connection c and all references * @param c Connection to be deleted */ public void deleteConnection(Connection c) { if(c == null) return; c.setName("Deleted"); LinkedList ports = new LinkedList(c.getParticipants()); for(Port p:ports) removeDeviceFromConnectionAndProtocol(p, c); ports.clear(); removeConnectionFromLink(c, c.getLink()); c.setStatus(Connection.TERMINATED); networkTreeSettings.removeStatusOfObject(c); removeConnection(c); } /** * Deletes Link 'toDelete' and all references * @param toDelete Link to be deleted */ public void deleteLink(Link toDelete) { if(toDelete==null)return; LinkedList devices = new LinkedList(toDelete.getDevices()); for(SmartDevice d : devices) removeLinkFromDevice(toDelete, d); devices.clear(); LinkedList connections = new LinkedList(toDelete.getConnections()); for(Connection c:connections) removeConnectionFromLink(c,toDelete); connections.clear(); toDelete.getPackets().clear(); /** * Remove Link Color */ controller.getSettingsController().getLinkColors().removeLink(toDelete); networkTreeSettings.removeStatusOfObject(toDelete); /** * Remove from Collectors */ PacketCaptureController captureController = controller.getSimulationController().getPacketCaptureController(); for(PacketCollector collector:captureController.getPacketCollectors()){ if(collector.getLinks().contains(toDelete)){ captureController.removeLinkFromCollector(collector, toDelete); } } /** * Remove Link from model */ removeLink(toDelete); } /** * Removes Connection from Link * @param c Connection to be removed * @param l Link to be removed */ public void removeConnectionFromLink(Connection c, Link l) { if(c!=null && c.getLink()==l){ c.setLink(null); } if(l!=null){ l.removeConnection(c); } } /** * Changes the type of the link to new type, specified by the given Link-class * @param oldLink oldLink, whose attributes will b copied to the new Link * @param newType Type/Class of the new Link * @return newly created Link, null on failure/error */ public Link changeLinkType(Link oldLink, Class newType) { if(newType == null) return null; /** * New Link which was created */ Link newLink = null; try{ newLink = newType.newInstance(); }catch(Exception e){ return null; } if (newLink == null || !(newLink instanceof Link)) { return null; }else { //Update Link Color LinkColorController linkColor = controller.getSettingsController().getLinkColors(); linkColor.setColorOfLink(newLink, linkColor.getColorOfLink(oldLink).getRight()); copyNetworkTreeStatus(oldLink, newLink); //Update Collectors PacketCaptureController captureController = controller.getSimulationController().getPacketCaptureController(); for(PacketCollector collector:captureController.getPacketCollectors()){ if(collector.getLinks().contains(oldLink)){ captureController.removeLinkFromCollector(collector, oldLink); captureController.addLinkToCollector(collector, newLink); } } // Set old Name newLink.setName(oldLink.getName()); // Add to Model if(getLinks().contains(oldLink)){ removeLink(oldLink); addLink(newLink); } //Connection to the new Link for(Connection c: new LinkedList(oldLink.getConnections())){ addConnectionToLink(c, newLink); } // Add devices to the new Link LinkedList devices= new LinkedList<>(oldLink.getDevices()); for(SmartDevice device:devices){ removeLinkFromDevice(oldLink, device); addLinkToDevice(newLink, device); } return newLink; } } /** * Adds status of the old Object to the new Object * @param oldObject old object, whose status should be copied * @param newObject new object, which should get the new status */ private void copyNetworkTreeStatus(Object oldObject, Object newObject){ NetworkTreeNodeStatus oldStatus = networkTreeSettings.getStatusOfObject(oldObject); NetworkTreeNodeStatus newStatus = new NetworkTreeNodeStatus(newObject); newStatus.setExpanded(oldStatus.isExpanded()); newStatus.setVisible(oldStatus.isVisible()); networkTreeSettings.addStatusOfObject(newObject, newStatus); } /** * Changes the Type of the SmartDevice * @param old old Device which should be * @param newClass new Class of the SmartDevice * @return new SmartDevice, null on failure */ public SmartDevice changeDeviceType(SmartDevice old, Class newClass){ //Compile new SmartDevice if(newClass == null) return null; /** * New Link which was created */ SmartDevice newDevice = null; try{ newDevice = newClass.newInstance(); }catch(Exception e){ return null; } if (newDevice == null || !(newDevice instanceof SmartDevice)) { return null; }else { // Update base informations newDevice.setName(old.getName()); old.setName("Deleted"); newDevice.setX(old.getX()); newDevice.setY(old.getY()); newDevice.setZ(old.getZ()); //Update Packet Collectors PacketCaptureController captureController = controller.getSimulationController().getPacketCaptureController(); for(PacketCollector collector:captureController.getPacketCollectors()){ if(collector.getDevices().contains(old)){ captureController.removeDeviceFromCollector(collector, newDevice); captureController.addDeviceToCollector(collector, newDevice); } } //Update all references LinkedList links = new LinkedList(old.getLinks()); for(Link l: links){ addLinkToDevice(l, newDevice); removeLinkFromDevice(l, old); } LinkedList ports = new LinkedList(old.getPorts()); for(Port p:ports){ p.setOwner(newDevice); newDevice.addPort(p); old.removePort(p); } SelectionModel selectionModel = controller.getSettingsController().getConfigurationManager().getSelectionModel(); if(selectionModel.selectedDevices.contains(old)){ selectionModel.selectedDevices.add(newDevice); selectionModel.selectedDevices.remove(old); } if(selectionModel.selectedDevicesDrag.contains(old)){ selectionModel.selectedDevicesDrag.add(newDevice); selectionModel.selectedDevicesDrag.remove(old); } //Update Colors tree status ? copyNetworkTreeStatus(old, newDevice); //Remove and add Device deleteSmartDevice(old); addSmartDevice(newDevice); return newDevice; } } /** * Returns the AnomalyController, which can be used to insert anomalies into the network model * @return Anomaly Controller */ public ExampleAnomalyController getAnomalyController() { return anomalyController; } }