Skip to content

Commit

Permalink
new JSON format for exporting servers
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Gyorok authored and Peter Gyorok committed Jun 23, 2022
1 parent 28935cb commit e02416e
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 71 deletions.
182 changes: 120 additions & 62 deletions src/main/studio/kdb/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,16 @@ public Object serverTreeToObj(ServerTreeNode root) {
for (Enumeration<TreeNode> e = root.children(); e.hasMoreElements();) {
children.add(serverTreeToObj((ServerTreeNode) e.nextElement()));
}
} else {
Server s = root.getServer();
result.put("name", s.getName());
result.put("host", s.getHost());
result.put("port", s.getPort());
result.put("username", s.getUsername());
result.put("password", s.getPassword());
result.put("useTls", s.getUseTLS());
result.put("authMethod", s.getAuthenticationMechanism());
result.put("color", colorToJSON(s.getBackgroundColor()));
}
return result;
}
Expand All @@ -467,24 +477,29 @@ public static Object colorToJSON(Color color) {
return acolor;
}

public Server serverFromJson(JsonNode serverNode) {
Server s = new Server();
if (serverNode.has("name")) s.setName(serverNode.get("name").asText(""));
if (serverNode.has("host")) s.setHost(serverNode.get("host").asText(""));
if (serverNode.has("port")) s.setPort(serverNode.get("port").asInt(0));
if (serverNode.has("username")) s.setUsername(serverNode.get("username").asText(""));
if (serverNode.has("password")) s.setPassword(serverNode.get("password").asText(""));
if (serverNode.has("useTls")) s.setUseTLS(serverNode.get("useTls").asBoolean(false));
if (serverNode.has("authMethod")) s.setAuthenticationMechanism(serverNode.get("authMethod").asText(""));
if (serverNode.has("color")) {
JsonNode color = serverNode.get("color");
if (color.isArray() && color.size() >= 3) {
s.setBackgroundColor(new Color(color.get(0).asInt(255),color.get(1).asInt(255),color.get(2).asInt(255)));
}
}
return s;
}

public void exportServerListToJSON(File f) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
Map<String,Object> cfg = new LinkedHashMap<>();
ArrayList<Map<String,Object>> svs = new ArrayList<>();
for (Server s : servers.values()) {
LinkedHashMap<String,Object> ps = new LinkedHashMap<>();
svs.add(ps);
ps.put("name", s.getName());
ps.put("host", s.getHost());
ps.put("port", s.getPort());
ps.put("username", s.getUsername());
ps.put("password", s.getPassword());
ps.put("useTls", s.getUseTLS());
ps.put("authMethod", s.getAuthenticationMechanism());
ps.put("color", colorToJSON(s.getBackgroundColor()));
}
cfg.put("servers",svs);
cfg.put("version",2);
cfg.put("serverTree", serverTreeToObj(serverTree));
try {
FileWriter sw = new FileWriter(f);
Expand All @@ -494,7 +509,7 @@ public void exportServerListToJSON(File f) {
}
}

private void importServerTreeFromJSON(HashMap<String, Server> serverMap, boolean isRoot, JsonNode jn, ServerTreeNode tn) {
private void importServerTreeFromJSONv1(HashMap<String, Server> serverMap, boolean isRoot, JsonNode jn, ServerTreeNode tn) {
if (jn.has("children")) { //is a folder
ServerTreeNode ntn = tn;
if (!isRoot) {
Expand All @@ -508,7 +523,7 @@ private void importServerTreeFromJSON(HashMap<String, Server> serverMap, boolean
JsonNode children = jn.get("children");
if (children.isArray()) {
for (JsonNode child : (Iterable<JsonNode>) ()->children.elements()) {
importServerTreeFromJSON(serverMap, false, child, ntn);
importServerTreeFromJSONv1(serverMap, false, child, ntn);
}
}
} else {
Expand All @@ -526,59 +541,103 @@ private void importServerTreeFromJSON(HashMap<String, Server> serverMap, boolean
}
}

private void importServerListFromJSONv1(JsonNode root, StringBuilder sb) {
ArrayList<String> alreadyExist = new ArrayList<>();
ArrayList<Integer> noName = new ArrayList<>();
if (!root.has("servers")) { sb.append("JSON root node doesn't have a \"servers\" property"); return; }
if (!root.has("serverTree")) { sb.append("JSON root node doesn't have a \"serverTree\" property"); return; }
JsonNode serversNode = root.get("servers");
JsonNode serverTreeNode = root.get("serverTree");
if (!serversNode.isArray()) { sb.append("\"servers\" node is not an array"); return; }
HashSet<String> existingServers = new HashSet<>();
for (Server s : servers.values()) existingServers.add(s.getName());
HashMap<String, Server> serverMap = new HashMap<>();
int i=0;
for (JsonNode serverNode : (Iterable<JsonNode>) ()->serversNode.elements()) {
if (!serverNode.isObject()) {
sb.append("Non-object found inside \"servers\" array at index "+i+"\n");
} else if (!serverNode.has("name")) {
sb.append("Server at index "+i+" has no name\n");
} else {
String sname = serverNode.get("name").asText();
if (sname.length() == 0) {
noName.add(i);
} else if (existingServers.contains(sname)) {
alreadyExist.add(sname);
} else {
Server s = serverFromJson(serverNode);
serverMap.put(sname, s);
}
}
++i;
}
if (serverTreeNode.isObject()) {
importServerTreeFromJSONv1(serverMap, true, serverTreeNode, serverTree);
}
if (0<noName.size()) sb.append("The servers at the following indices have no names: "+noName+"\n");
if (0<alreadyExist.size()) sb.append("The following servers already exist and were not imported: "+alreadyExist+"\n");
}

private void importServerTreeFromJSONv2(boolean isRoot, JsonNode jn, ServerTreeNode tn) {
if (jn.has("children")) { //is a folder
ServerTreeNode ntn = tn;
if (!isRoot) {
String folderName = jn.get("name").asText("");
ntn = tn.getChild(folderName);
if (ntn == null) {
ntn = new ServerTreeNode(folderName);
tn.add(ntn);
}
};
JsonNode children = jn.get("children");
if (children.isArray()) {
for (JsonNode child : (Iterable<JsonNode>) ()->children.elements()) {
importServerTreeFromJSONv2(false, child, ntn);
}
}
} else {
if (jn.has("name")) {
String name = jn.get("name").asText("");
if (name.length() > 0) {
Server s = serverFromJson(jn);
s.setFolder(tn);
addServer(s);
}
}
}
}

private void importServerListFromJSONv2(JsonNode root, StringBuilder sb) {
if (!root.has("serverTree")) { sb.append("JSON root node doesn't have a \"serverTree\" property"); return; }
JsonNode serverTreeNode = root.get("serverTree");
if (!serverTreeNode.isObject()) {
sb.append("serverTree is not an object");
}
importServerTreeFromJSONv2(true, serverTreeNode, serverTree);
}

public String importServerListFromJSON(File f) {
int version = 1;
ObjectMapper objectMapper = new ObjectMapper();
StringBuilder sb = new StringBuilder();
ArrayList<String> alreadyExist = new ArrayList<>();
ArrayList<Integer> noName = new ArrayList<>();
try {
JsonNode root = objectMapper.readTree(f);
if (!root.isObject()) return "JSON root node is not an object";
if (!root.has("servers")) return "JSON root node doesn't have a \"servers\" property";
if (!root.has("serverTree")) return "JSON root node doesn't have a \"serverTree\" property";
JsonNode serversNode = root.get("servers");
JsonNode serverTreeNode = root.get("serverTree");
if (!serversNode.isArray()) return "\"servers\" node is not an array";
HashSet<String> existingServers = new HashSet<>();
for (Server s : servers.values()) existingServers.add(s.getName());
HashMap<String, Server> serverMap = new HashMap<>();
int i=0;
for (JsonNode serverNode : (Iterable<JsonNode>) ()->serversNode.elements()) {
if (!serverNode.isObject()) {
sb.append("Non-object found inside \"servers\" array at index "+i+"\n");
} else if (!serverNode.has("name")) {
sb.append("Server at index "+i+" has no name\n");
} else {
String sname = serverNode.get("name").asText();
if (sname.length() == 0) {
noName.add(i);
} else if (existingServers.contains(sname)) {
alreadyExist.add(sname);
} else {
Server s = new Server();
s.setName(sname);
if (serverNode.has("host")) s.setHost(serverNode.get("host").asText(""));
if (serverNode.has("port")) s.setPort(serverNode.get("port").asInt(0));
if (serverNode.has("username")) s.setUsername(serverNode.get("username").asText(""));
if (serverNode.has("password")) s.setPassword(serverNode.get("password").asText(""));
if (serverNode.has("useTls")) s.setUseTLS(serverNode.get("useTls").asBoolean(false));
if (serverNode.has("authMethod")) s.setAuthenticationMechanism(serverNode.get("authMethod").asText(""));
if (serverNode.has("color")) {
JsonNode color = serverNode.get("color");
if (color.isArray() && color.size() >= 3) {
s.setBackgroundColor(new Color(color.get(0).asInt(255),color.get(1).asInt(255),color.get(2).asInt(255)));
}
}
serverMap.put(sname, s);
}
}
++i;
if (root.has("version")) {
JsonNode versionNode = root.get("version");
if (!versionNode.isInt()) return "version is not an integer";
version = versionNode.intValue();
}
if (serverTreeNode.isObject()) {
importServerTreeFromJSON(serverMap, true, serverTreeNode, serverTree);
switch(version) {
case 1:
importServerListFromJSONv1(root, sb);
break;
case 2:
importServerListFromJSONv2(root, sb);
break;
default:
return "unsupported version: "+version;
}
if (0<noName.size()) sb.append("The servers at the following indices have no names: "+noName);
if (0<alreadyExist.size()) sb.append("The following servers already exist and were not imported: "+alreadyExist);
} catch(IOException e) {
return e.toString();
}
Expand Down Expand Up @@ -880,7 +939,6 @@ private void addServerInternal(Server server) {
serverNames.add(fullName);
}


public void addServer(Server server) {
addServers(false, server);
}
Expand Down
10 changes: 7 additions & 3 deletions src/main/studio/ui/EditorTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,14 @@ public Server getServer() {

public void setServer(Server server) {
this.server = server;
getTextArea().setBackground(server.getBackgroundColor());
if (server.equals(getServer())) return;
if (server != null) {
getTextArea().setBackground(server.getBackgroundColor());
if (server.equals(getServer())) return;

setStatus("Changed server: " + server.getDescription(true));
setStatus("Changed server: " + server.getDescription(true));
} else {
setStatus("No server selected");
}
}

public LineEnding getLineEnding() {
Expand Down
30 changes: 28 additions & 2 deletions src/main/studio/ui/ServerList.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class ServerList extends EscapeDialog implements TreeExpansionListener {
addServerBeforeAction, addServerAfterAction,
addFolderBeforeAction, addFolderAfterAction,
pickUpAction, dropIntoAction, dropAboveAction, dropBelowAction,
importFromJSONAction, exportToJSONAction;
importFromJSONAction, exportToJSONAction, removeAllAction;

public static final int DEFAULT_WIDTH = 300;
public static final int DEFAULT_HEIGHT = 410;
Expand Down Expand Up @@ -362,6 +362,7 @@ public void mouseClicked(MouseEvent e) {
menu.setMnemonic(KeyEvent.VK_F);
menu.add(new JMenuItem(importFromJSONAction));
menu.add(new JMenuItem(exportToJSONAction));
menu.add(new JMenuItem(removeAllAction));
menubar.add(menu);
setJMenuBar(menubar);
}
Expand Down Expand Up @@ -394,9 +395,11 @@ private void initActions() {
KeyEvent.VK_L, e -> dropNode(AddNodeLocation.AFTER));

importFromJSONAction = UserAction.create("Import from JSON...", "Import server list from JSON",
KeyEvent.VK_I, e -> JSONServerList.importFromJSON(this, studioPanel));
KeyEvent.VK_I, e -> importFromJSON());
exportToJSONAction = UserAction.create("Export to JSON...", "Export server list to JSON",
KeyEvent.VK_E, e -> JSONServerList.exportToJSON(this));
removeAllAction = UserAction.create("Remove All", "Remove all servers",
KeyEvent.VK_R, e -> removeAllServersWithConfirm());

UserAction toggleAction = UserAction.create("toggle", e-> toggleTreeListView());
UserAction focusTreeAction = UserAction.create("focus tree", e-> tree.requestFocusInWindow());
Expand Down Expand Up @@ -592,4 +595,27 @@ private void dropNode(AddNodeLocation location) {
studioPanel.updateServerComboBox();
}

private void importFromJSON() {
JSONServerList.importFromJSON(this, studioPanel);
refreshServers();
}

private void removeAllServersWithConfirm() {
int choice = JOptionPane.showOptionDialog(studioPanel,
"Are you sure you want to remove ALL servers?",
"Remove all servers",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE,
Util.WARNING_ICON,
null, // use standard button titles
null); // no default selection

if (choice == 0) {
Config.getInstance().removeAllServers();
//setRoot(null);
updateServerTree(null, null);
studioPanel.setServer(null);
}
}

}
9 changes: 5 additions & 4 deletions src/main/studio/ui/StudioPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -548,13 +548,14 @@ else if ((row == 1) && ((noWins % 3) > 1))
}
}

private void setServer(Server server) {
if (server == null) return;
public void setServer(Server server) {
editor.setServer(server);

if (!loading) {
CONFIG.addServerToHistory(server);
serverHistory.add(server);
if (server != null) {
CONFIG.addServerToHistory(server);
serverHistory.add(server);
}

refreshTitle();
rebuildAll();
Expand Down

0 comments on commit e02416e

Please sign in to comment.