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 extends Connection> 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 extends Link> 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 extends SmartDevice> 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;
}
}