javafx - moved node interface management out of nodes, rely on graph to obtain interfaces from links
This commit is contained in:
parent
c5f62a106f
commit
0d63630c99
5 changed files with 99 additions and 67 deletions
|
@ -61,7 +61,7 @@ public class Controller implements Initializable {
|
||||||
// ui elements
|
// ui elements
|
||||||
private NetworkGraph networkGraph = new NetworkGraph(this);
|
private NetworkGraph networkGraph = new NetworkGraph(this);
|
||||||
private AnnotationToolbar annotationToolbar = new AnnotationToolbar(networkGraph);
|
private AnnotationToolbar annotationToolbar = new AnnotationToolbar(networkGraph);
|
||||||
private NodeDetails nodeDetails = new NodeDetails();
|
private NodeDetails nodeDetails = new NodeDetails(this);
|
||||||
private LinkDetails linkDetails = new LinkDetails(networkGraph);
|
private LinkDetails linkDetails = new LinkDetails(networkGraph);
|
||||||
private GraphToolbar graphToolbar = new GraphToolbar(this);
|
private GraphToolbar graphToolbar = new GraphToolbar(this);
|
||||||
private MobilityPlayer mobilityPlayer = new MobilityPlayer(this);
|
private MobilityPlayer mobilityPlayer = new MobilityPlayer(this);
|
||||||
|
|
|
@ -7,7 +7,8 @@ import lombok.NoArgsConstructor;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
|
@ -26,8 +27,6 @@ public class CoreNode {
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private String icon;
|
private String icon;
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private Map<Integer, CoreInterface> interfaces = new HashMap<>();
|
|
||||||
@JsonIgnore
|
|
||||||
private boolean loaded = true;
|
private boolean loaded = true;
|
||||||
|
|
||||||
public CoreNode(Integer id) {
|
public CoreNode(Integer id) {
|
||||||
|
@ -36,10 +35,6 @@ public class CoreNode {
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CoreInterface getInterface(Integer id) {
|
|
||||||
return interfaces.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public String getNodeTypeKey() {
|
public String getNodeTypeKey() {
|
||||||
if (model == null) {
|
if (model == null) {
|
||||||
|
@ -48,18 +43,4 @@ public class CoreNode {
|
||||||
return String.format("%s-%s", type, model);
|
return String.format("%s-%s", type, model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addInterface(CoreInterface coreInterface) {
|
|
||||||
logger.info("adding interface node({}) {}", id, coreInterface);
|
|
||||||
interfaces.put(coreInterface.getId(), coreInterface);
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
public int getNextInterfaceId() {
|
|
||||||
if (interfaces.isEmpty()) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return Collections.max(interfaces.keySet()) + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,10 @@ import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@ -119,7 +121,7 @@ public class NetworkGraph {
|
||||||
Toast.error("Node terminal command failed");
|
Toast.error("Node terminal command failed");
|
||||||
}
|
}
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
logger.error("error waiting for terminal to start");
|
logger.error("error waiting for terminal to start", ex);
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.error("error launching terminal", ex);
|
logger.error("error launching terminal", ex);
|
||||||
|
@ -204,20 +206,20 @@ public class NetworkGraph {
|
||||||
|
|
||||||
// create interfaces for nodes
|
// create interfaces for nodes
|
||||||
int sub = coreAddresses.getSubnet(
|
int sub = coreAddresses.getSubnet(
|
||||||
nodeOne.getInterfaces().values(),
|
getInterfaces(nodeOne),
|
||||||
nodeTwo.getInterfaces().values()
|
getInterfaces(nodeTwo)
|
||||||
);
|
);
|
||||||
|
|
||||||
link.setNodeOne(nodeOne.getId());
|
link.setNodeOne(nodeOne.getId());
|
||||||
int interfaceOneId = nodeOne.getNextInterfaceId();
|
|
||||||
if (isNode(nodeOne)) {
|
if (isNode(nodeOne)) {
|
||||||
|
int interfaceOneId = nextInterfaceId(nodeOne);
|
||||||
CoreInterface interfaceOne = createInterface(nodeOne, sub, interfaceOneId);
|
CoreInterface interfaceOne = createInterface(nodeOne, sub, interfaceOneId);
|
||||||
link.setInterfaceOne(interfaceOne);
|
link.setInterfaceOne(interfaceOne);
|
||||||
}
|
}
|
||||||
|
|
||||||
link.setNodeTwo(nodeTwo.getId());
|
link.setNodeTwo(nodeTwo.getId());
|
||||||
if (isNode(nodeTwo)) {
|
if (isNode(nodeTwo)) {
|
||||||
int interfaceTwoId = nodeTwo.getNextInterfaceId();
|
int interfaceTwoId = nextInterfaceId(nodeTwo);
|
||||||
CoreInterface interfaceTwo = createInterface(nodeTwo, sub, interfaceTwoId);
|
CoreInterface interfaceTwo = createInterface(nodeTwo, sub, interfaceTwoId);
|
||||||
link.setInterfaceTwo(interfaceTwo);
|
link.setInterfaceTwo(interfaceTwo);
|
||||||
}
|
}
|
||||||
|
@ -229,18 +231,53 @@ public class NetworkGraph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<CoreInterface> getInterfaces(CoreNode node) {
|
||||||
|
return graph.getIncidentEdges(node).stream()
|
||||||
|
.map(link -> {
|
||||||
|
if (node.getId().equals(link.getNodeOne())) {
|
||||||
|
return link.getInterfaceOne();
|
||||||
|
} else {
|
||||||
|
return link.getInterfaceTwo();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private int nextInterfaceId(CoreNode node) {
|
||||||
|
Set<Integer> interfaceIds = graph.getIncidentEdges(node).stream()
|
||||||
|
.map(link -> {
|
||||||
|
if (node.getId().equals(link.getNodeOne())) {
|
||||||
|
return link.getInterfaceOne();
|
||||||
|
} else {
|
||||||
|
return link.getInterfaceTwo();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(CoreInterface::getId)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (true) {
|
||||||
|
if (!interfaceIds.contains(i)) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isNode(CoreNode node) {
|
private boolean isNode(CoreNode node) {
|
||||||
return node.getType() == NodeType.DEFAULT;
|
return node.getType() == NodeType.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CoreInterface createInterface(CoreNode node, int sub, int interfaceId) {
|
private CoreInterface createInterface(CoreNode node, int sub, int interfaceId) {
|
||||||
String nodeOneIp4 = coreAddresses.getIp4Address(sub, node.getId());
|
|
||||||
CoreInterface coreInterface = new CoreInterface();
|
CoreInterface coreInterface = new CoreInterface();
|
||||||
coreInterface.setId(interfaceId);
|
coreInterface.setId(interfaceId);
|
||||||
coreInterface.setName(String.format("eth%s", interfaceId));
|
coreInterface.setName(String.format("eth%s", interfaceId));
|
||||||
|
String nodeOneIp4 = coreAddresses.getIp4Address(sub, node.getId());
|
||||||
coreInterface.setIp4(nodeOneIp4);
|
coreInterface.setIp4(nodeOneIp4);
|
||||||
coreInterface.setIp4Mask(CoreAddresses.IP4_MASK);
|
coreInterface.setIp4Mask(CoreAddresses.IP4_MASK);
|
||||||
node.addInterface(coreInterface);
|
|
||||||
return coreInterface;
|
return coreInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,18 +359,8 @@ public class NetworkGraph {
|
||||||
|
|
||||||
public void addLink(CoreLink link) {
|
public void addLink(CoreLink link) {
|
||||||
link.setId(linkId++);
|
link.setId(linkId++);
|
||||||
|
|
||||||
CoreNode nodeOne = nodeMap.get(link.getNodeOne());
|
CoreNode nodeOne = nodeMap.get(link.getNodeOne());
|
||||||
CoreInterface interfaceOne = link.getInterfaceOne();
|
|
||||||
if (interfaceOne != null) {
|
|
||||||
nodeOne.addInterface(interfaceOne);
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreNode nodeTwo = nodeMap.get(link.getNodeTwo());
|
CoreNode nodeTwo = nodeMap.get(link.getNodeTwo());
|
||||||
CoreInterface interfaceTwo = link.getInterfaceTwo();
|
|
||||||
if (interfaceTwo != null) {
|
|
||||||
nodeTwo.addInterface(interfaceTwo);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isVisible = !isWirelessLink(nodeOne, nodeTwo);
|
boolean isVisible = !isWirelessLink(nodeOne, nodeTwo);
|
||||||
link.setVisible(isVisible);
|
link.setVisible(isVisible);
|
||||||
|
@ -362,26 +389,4 @@ public class NetworkGraph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void linkNodes(CoreNode nodeOne, CoreNode nodeTwo, CoreLink link) {
|
|
||||||
// create interfaces for nodes
|
|
||||||
int sub = coreAddresses.getSubnet(
|
|
||||||
nodeOne.getInterfaces().values(),
|
|
||||||
nodeTwo.getInterfaces().values()
|
|
||||||
);
|
|
||||||
|
|
||||||
link.setNodeOne(nodeOne.getId());
|
|
||||||
int interfaceOneId = nodeOne.getNextInterfaceId();
|
|
||||||
if (isNode(nodeOne)) {
|
|
||||||
CoreInterface interfaceOne = createInterface(nodeOne, sub, interfaceOneId);
|
|
||||||
link.setInterfaceOne(interfaceOne);
|
|
||||||
}
|
|
||||||
|
|
||||||
link.setNodeTwo(nodeTwo.getId());
|
|
||||||
if (isNode(nodeTwo)) {
|
|
||||||
int interfaceTwoId = nodeTwo.getNextInterfaceId();
|
|
||||||
CoreInterface interfaceTwo = createInterface(nodeTwo, sub, interfaceTwoId);
|
|
||||||
link.setInterfaceTwo(interfaceTwo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
package com.core.ui;
|
package com.core.ui;
|
||||||
|
|
||||||
|
import com.core.Controller;
|
||||||
import com.core.data.CoreInterface;
|
import com.core.data.CoreInterface;
|
||||||
|
import com.core.data.CoreLink;
|
||||||
import com.core.data.CoreNode;
|
import com.core.data.CoreNode;
|
||||||
import com.core.data.NodeType;
|
import com.core.data.NodeType;
|
||||||
|
import com.jfoenix.controls.JFXButton;
|
||||||
|
import com.jfoenix.controls.JFXListView;
|
||||||
|
import com.jfoenix.controls.JFXScrollPane;
|
||||||
import com.jfoenix.controls.JFXTextField;
|
import com.jfoenix.controls.JFXTextField;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
|
@ -12,8 +19,6 @@ import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.control.ScrollPane;
|
||||||
import javafx.scene.control.Separator;
|
import javafx.scene.control.Separator;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.scene.text.Font;
|
|
||||||
import javafx.scene.text.FontWeight;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
@ -22,13 +27,18 @@ import java.io.IOException;
|
||||||
public class NodeDetails extends ScrollPane {
|
public class NodeDetails extends ScrollPane {
|
||||||
private static final Logger logger = LogManager.getLogger();
|
private static final Logger logger = LogManager.getLogger();
|
||||||
private static final int START_INDEX = 1;
|
private static final int START_INDEX = 1;
|
||||||
|
private final Controller controller;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private ScrollPane scrollPane;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private GridPane gridPane;
|
private GridPane gridPane;
|
||||||
|
|
||||||
private int index = START_INDEX;
|
private int index = START_INDEX;
|
||||||
|
|
||||||
public NodeDetails() {
|
public NodeDetails(Controller controller) {
|
||||||
|
this.controller = controller;
|
||||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/node_details.fxml"));
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/node_details.fxml"));
|
||||||
loader.setRoot(this);
|
loader.setRoot(this);
|
||||||
loader.setController(this);
|
loader.setController(this);
|
||||||
|
@ -60,18 +70,54 @@ public class NodeDetails extends ScrollPane {
|
||||||
addRow("X", node.getPosition().getX().toString());
|
addRow("X", node.getPosition().getX().toString());
|
||||||
addRow("Y", node.getPosition().getY().toString());
|
addRow("Y", node.getPosition().getY().toString());
|
||||||
|
|
||||||
for (CoreInterface coreInterface : node.getInterfaces().values()) {
|
for (CoreLink link : controller.getNetworkGraph().getGraph().getIncidentEdges(node)) {
|
||||||
|
CoreNode linkedNode;
|
||||||
|
CoreInterface coreInterface;
|
||||||
|
if (node.getId().equals(link.getNodeOne())) {
|
||||||
|
coreInterface = link.getInterfaceOne();
|
||||||
|
linkedNode = controller.getNetworkGraph().getNodeMap().get(link.getNodeTwo());
|
||||||
|
} else {
|
||||||
|
coreInterface = link.getInterfaceTwo();
|
||||||
|
linkedNode = controller.getNetworkGraph().getNodeMap().get(link.getNodeOne());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coreInterface == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
addSeparator();
|
addSeparator();
|
||||||
|
if (linkedNode.getType() == NodeType.EMANE) {
|
||||||
|
addButton(linkedNode.getName(), event -> controller.getNodeEmaneDialog().showDialog(linkedNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linkedNode.getType() == NodeType.WLAN) {
|
||||||
|
addButton(linkedNode.getName(), event -> controller.getNodeWlanDialog().showDialog(linkedNode));
|
||||||
|
}
|
||||||
addInterface(coreInterface);
|
addInterface(coreInterface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!node.getServices().isEmpty()) {
|
if (!node.getServices().isEmpty()) {
|
||||||
addSeparator();
|
addSeparator();
|
||||||
addLabel("Services");
|
addLabel("Services");
|
||||||
|
JFXListView<String> listView = new JFXListView<>();
|
||||||
|
listView.setMouseTransparent(true);
|
||||||
|
listView.setFocusTraversable(false);
|
||||||
for (String service : node.getServices()) {
|
for (String service : node.getServices()) {
|
||||||
gridPane.add(new Label(service), 0, index++, 2, 1);
|
listView.getItems().add(service);
|
||||||
}
|
}
|
||||||
|
gridPane.add(listView, 0, index++, 2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JFXScrollPane.smoothScrolling(scrollPane);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addButton(String text, EventHandler<ActionEvent> handler) {
|
||||||
|
JFXButton emaneButton = new JFXButton(text);
|
||||||
|
emaneButton.getStyleClass().add("core-button");
|
||||||
|
emaneButton.setMaxWidth(Double.MAX_VALUE);
|
||||||
|
emaneButton.setOnAction(handler);
|
||||||
|
gridPane.add(emaneButton, 0, index++, 2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addLabel(String text) {
|
private void addLabel(String text) {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<?import javafx.scene.layout.RowConstraints?>
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<fx:root fitToWidth="true" prefHeight="418.0" prefWidth="300.0" type="ScrollPane" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
|
<fx:root fx:id="scrollPane" fitToWidth="true" prefHeight="418.0" prefWidth="300.0" type="ScrollPane" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<content>
|
<content>
|
||||||
<GridPane fx:id="gridPane" hgap="5.0" prefWidth="298.0" vgap="5.0">
|
<GridPane fx:id="gridPane" hgap="5.0" prefWidth="298.0" vgap="5.0">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
|
|
Loading…
Add table
Reference in a new issue