Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new JSON format for exporting servers #127

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 120 additions & 62 deletions src/main/studio/kdb/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,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 @@ -469,24 +479,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 @@ -496,7 +511,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 @@ -510,7 +525,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 @@ -528,59 +543,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 @@ -882,7 +941,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 @@ -556,13 +556,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