From 5cd0d283407f7df80dafa21a191243a4ac5de5e5 Mon Sep 17 00:00:00 2001 From: Ali Smesseim Date: Mon, 9 May 2016 19:06:05 +0200 Subject: [PATCH 1/2] Add JSON serializer for treenode --- .../pl1_2016/parser/BaseTreeNode.java | 47 ++++++++++++------- .../pl1_2016/parser/JsonSerializable.java | 15 +----- .../pl1_2016/parser/NodeList.java | 9 ++++ .../pl1_2016/parser/NodeMap.java | 9 ++++ .../parser/PhyloGeneticTreeParser.java | 22 ++++----- .../pl1_2016/parser/TreeNode.java | 14 ++++-- .../pl1_2016/parser/TreeNodeCollection.java | 8 ++++ .../parser/TreeNodeCollectionSerializer.java | 36 ++++++++++++++ .../pl1_2016/parser/TreeNodeList.java | 26 ++++++++++ .../parser/PhyloGeneticTreeParserTest.java | 8 ++-- 10 files changed, 143 insertions(+), 51 deletions(-) create mode 100644 src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeCollection.java create mode 100644 src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeCollectionSerializer.java create mode 100644 src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeList.java diff --git a/src/main/java/io/github/programminglife2016/pl1_2016/parser/BaseTreeNode.java b/src/main/java/io/github/programminglife2016/pl1_2016/parser/BaseTreeNode.java index 105b4b9..12da050 100644 --- a/src/main/java/io/github/programminglife2016/pl1_2016/parser/BaseTreeNode.java +++ b/src/main/java/io/github/programminglife2016/pl1_2016/parser/BaseTreeNode.java @@ -7,8 +7,10 @@ /** * Class for representing a node in the phylogenetic tree. */ -public class BaseTreeNode implements JsonSerializable, TreeNode { - private String id; +public class BaseTreeNode implements TreeNode { + private static int STATIC_ID = 1; + private int id; + private String name; private double weight; private List children; private TreeNode parent; @@ -22,22 +24,23 @@ public BaseTreeNode() { /** * Create a Tree Node Object. - * @param id id of the tree node. + * @param name name of the tree node. * @param weight weight of the tree node. */ - public BaseTreeNode(String id, double weight) { - this(id, weight, new ArrayList<>(), null); + public BaseTreeNode(String name, double weight) { + this(name, weight, new ArrayList<>(), null); } /** * Create a BaseTreeNode object. - * @param id id of the treenode. + * @param name name of the treenode. * @param weight weight of the tree node. * @param children list of children tree nodes. * @param parent parent tree node of this tree node. */ - public BaseTreeNode(String id, double weight, List children, TreeNode parent) { - this.id = id; + public BaseTreeNode(String name, double weight, List children, TreeNode parent) { + this.id = STATIC_ID++; + this.name = name; this.weight = weight; this.children = children; this.parent = parent; @@ -60,11 +63,21 @@ public void setChildren(List children) { } /** - * Set the id of the tree node. - * @param id value of the id. + * Get the id of the tree node. + * + * @return id of the tree node */ - public void setId(String id) { - this.id = id; + @Override + public int getId() { + return id; + } + + /** + * Set the name of the tree node. + * @param name value of the name. + */ + public void setName(String name) { + this.name = name; } /** @@ -76,11 +89,11 @@ public void setWeight(double weight) { } /** - * Get id of tree node. - * @return id of tree. + * Get name of tree node. + * @return name of tree. */ - public String getId() { - return id; + public String getName() { + return name; } /** @@ -113,7 +126,7 @@ public void setParent(TreeNode parent) { */ @Override public String toString() { - return "[" + this.getId() + " " + this.getWeight() + return "[" + this.getName() + " " + this.getWeight() + " {" + children.stream() .map(Object::toString) .collect(joining(", ")) + "}]"; diff --git a/src/main/java/io/github/programminglife2016/pl1_2016/parser/JsonSerializable.java b/src/main/java/io/github/programminglife2016/pl1_2016/parser/JsonSerializable.java index 2d7e273..d851533 100644 --- a/src/main/java/io/github/programminglife2016/pl1_2016/parser/JsonSerializable.java +++ b/src/main/java/io/github/programminglife2016/pl1_2016/parser/JsonSerializable.java @@ -1,22 +1,9 @@ package io.github.programminglife2016.pl1_2016.parser; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - /** * Data is sent by the server in JSON format. Classes extending this method can convert their * representation to JSON. */ public interface JsonSerializable { - /** - * Convert the representation to JSON. - * - * @return JSON representation of this object. - */ - default String toJson() { - Gson gson = new GsonBuilder() - .registerTypeAdapter(NodeList.class, new NodeCollectionSerializer()) - .registerTypeAdapter(NodeMap.class, new NodeCollectionSerializer()).create(); - return gson.toJson(this); - } + String toJson(); } diff --git a/src/main/java/io/github/programminglife2016/pl1_2016/parser/NodeList.java b/src/main/java/io/github/programminglife2016/pl1_2016/parser/NodeList.java index d696dea..2fa3389 100644 --- a/src/main/java/io/github/programminglife2016/pl1_2016/parser/NodeList.java +++ b/src/main/java/io/github/programminglife2016/pl1_2016/parser/NodeList.java @@ -1,5 +1,8 @@ package io.github.programminglife2016.pl1_2016.parser; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + import java.util.Arrays; import java.util.Collection; import java.util.stream.Collectors; @@ -62,4 +65,10 @@ public boolean containsKey(Object id) { public Collection getNodes() { return Arrays.asList(array).stream().filter(x -> x != null).collect(Collectors.toList()); } + + @Override + public String toJson() { + Gson gson = new GsonBuilder().registerTypeAdapter(NodeList.class, new NodeCollectionSerializer()).create(); + return gson.toJson(this); + } } diff --git a/src/main/java/io/github/programminglife2016/pl1_2016/parser/NodeMap.java b/src/main/java/io/github/programminglife2016/pl1_2016/parser/NodeMap.java index c5a23f7..d95e0c3 100644 --- a/src/main/java/io/github/programminglife2016/pl1_2016/parser/NodeMap.java +++ b/src/main/java/io/github/programminglife2016/pl1_2016/parser/NodeMap.java @@ -1,5 +1,8 @@ package io.github.programminglife2016.pl1_2016.parser; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + import java.util.Collection; import java.util.HashMap; @@ -24,4 +27,10 @@ public NodeMap(int initialCapacity) { public Collection getNodes() { return values(); } + + @Override + public String toJson() { + Gson gson = new GsonBuilder().registerTypeAdapter(NodeMap.class, new NodeCollectionSerializer()).create(); + return gson.toJson(this); + } } diff --git a/src/main/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParser.java b/src/main/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParser.java index adb1860..6303cbc 100644 --- a/src/main/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParser.java +++ b/src/main/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParser.java @@ -1,7 +1,5 @@ package io.github.programminglife2016.pl1_2016.parser; -import io.github.programminglife2016.pl1_2016.Launcher; - import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; @@ -16,8 +14,7 @@ public class PhyloGeneticTreeParser implements Parser { @Override public JsonSerializable parse(InputStream inputStream) { String s = inputStreamToString(inputStream); - Collection nodes = parseTokensFromString(s); - return null; + return parseTokensFromString(s); } private String inputStreamToString(InputStream inputStream) { @@ -32,9 +29,9 @@ private String inputStreamToString(InputStream inputStream) { * @param s string representin the tree. * @return root of tree */ - public Collection parseTokensFromString(String s) { + public TreeNodeCollection parseTokensFromString(String s) { StringIterator tokenizer = new TokenIterator(s, "(:,);", true); - Collection nodes = construct(tokenizer); + TreeNodeCollection nodes = construct(tokenizer); return nodes; } @@ -43,10 +40,11 @@ public Collection parseTokensFromString(String s) { * @param tokenizer tokenizer with the contents of the .nwk file. * @return parsed Tree Node object. */ - public Collection construct(StringIterator tokenizer) { - Collection nodes = new ArrayList(); + public TreeNodeCollection construct(StringIterator tokenizer) { + TreeNodeCollection nodes = new TreeNodeList(); TreeNode root = new BaseTreeNode(); nodes.add(root); + nodes.setRoot(root); TreeNode current = root; while (tokenizer.hasNext()) { String currentToken = tokenizer.next(); @@ -76,7 +74,7 @@ public Collection construct(StringIterator tokenizer) { case ";": break; default: - current.setId(currentToken); + current.setName(currentToken); break; } } @@ -112,7 +110,7 @@ public TreeNode constructTree(TreeNode parent, StringIterator tokenizer) { current = new BaseTreeNode(); break; case ")": - if (!current.getId().equals("-") && current.getWeight() != 0.0) { + if (!current.getName().equals("-") && current.getWeight() != 0.0) { nodes.add(current); } weight = 0; @@ -124,7 +122,7 @@ public TreeNode constructTree(TreeNode parent, StringIterator tokenizer) { current.setChildren(nodes); return current; default: - current.setId(next); + current.setName(next); break; } } @@ -143,7 +141,7 @@ public static void main(String[] args) { String s = "(A: 0.1,B: 0.2,(C:0.3,(Z:1,Y:2):0.4):0.5);"; s = "(A:0.1,(B:0.2,(C:0.3,(D:0.4,E:0.5):0.6):0.4):0.5);"; // parser.parse(Launcher.class.getResourceAsStream("/genomes/340tree.rooted.TKK.nwk")); - parser.parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8))); + System.out.println(parser.parse(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8))).toJson()); System.out.println("Done"); } } diff --git a/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNode.java b/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNode.java index 0c39836..ad4762a 100644 --- a/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNode.java +++ b/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNode.java @@ -7,12 +7,18 @@ * Created by ravishivam on 6-5-16. */ public interface TreeNode { + /** + * Get the id of the tree node. + * + * @return id of the tree node + */ + int getId(); /** - * Set the id of the tree node. - * @param id value of the id. + * Set the name of the tree node. + * @param name value of the name. */ - void setId(String id); + void setName(String name); /** * Set the list of children tree nodes. @@ -24,7 +30,7 @@ public interface TreeNode { * Get id of tree node. * @return id of tree. */ - String getId(); + String getName(); /** * Return weight of this node. diff --git a/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeCollection.java b/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeCollection.java new file mode 100644 index 0000000..1799e9d --- /dev/null +++ b/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeCollection.java @@ -0,0 +1,8 @@ +package io.github.programminglife2016.pl1_2016.parser; + +import java.util.Collection; + +public interface TreeNodeCollection extends Collection, JsonSerializable { + TreeNode getRoot(); + void setRoot(TreeNode root); +} diff --git a/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeCollectionSerializer.java b/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeCollectionSerializer.java new file mode 100644 index 0000000..8e94c96 --- /dev/null +++ b/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeCollectionSerializer.java @@ -0,0 +1,36 @@ +package io.github.programminglife2016.pl1_2016.parser; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +import java.lang.reflect.Type; + +public class TreeNodeCollectionSerializer implements JsonSerializer { + @Override + public JsonElement serialize(TreeNodeCollection treeNodeCollection, Type type, JsonSerializationContext jsonSerializationContext) { + JsonObject jsonObject = new JsonObject(); + JsonArray treeNodes = new JsonArray(); + for (TreeNode treeNode : treeNodeCollection) { + JsonObject treeNodeObject = new JsonObject(); + treeNodeObject.add("id", new JsonPrimitive(treeNode.getId())); + treeNodeObject.add("name", new JsonPrimitive(treeNode.getName())); + JsonArray children = new JsonArray(); + treeNode.getChildren().stream().map(TreeNode::getName).forEach(children::add); + treeNodeObject.add("children", children); + if (treeNode.getParent() != null) { + treeNodeObject.add("parent", new JsonPrimitive(treeNode.getParent().getId())); + } else { + treeNodeObject.add("parent", new JsonPrimitive("null")); + } + treeNodeObject.add("weight", new JsonPrimitive(treeNode.getWeight())); + treeNodes.add(treeNodeObject); + } + jsonObject.add("treeNodes", treeNodes); + jsonObject.add("root", new JsonPrimitive(treeNodeCollection.getRoot().getName())); + return jsonObject; + } +} diff --git a/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeList.java b/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeList.java new file mode 100644 index 0000000..ca7e1a8 --- /dev/null +++ b/src/main/java/io/github/programminglife2016/pl1_2016/parser/TreeNodeList.java @@ -0,0 +1,26 @@ +package io.github.programminglife2016.pl1_2016.parser; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.util.ArrayList; + +public class TreeNodeList extends ArrayList implements TreeNodeCollection { + private TreeNode root; + + @Override + public String toJson() { + Gson gson = new GsonBuilder().registerTypeAdapter(TreeNodeList.class, new TreeNodeCollectionSerializer()).create(); + return gson.toJson(this); + } + + @Override + public TreeNode getRoot() { + return root; + } + + @Override + public void setRoot(TreeNode root) { + this.root = root; + } +} diff --git a/src/test/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParserTest.java b/src/test/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParserTest.java index d101125..2051362 100644 --- a/src/test/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParserTest.java +++ b/src/test/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParserTest.java @@ -26,8 +26,8 @@ public void setUp() { public void testTreeWithSingleNode() { PhyloGeneticTreeParser parser = new PhyloGeneticTreeParser(); String s = "(B:6.0,A:5.0);"; - TreeNode node = parser.parseTokensFromString(s); - assertEquals("B", node.getId()); + TreeNodeCollection node = parser.parseTokensFromString(s); + assertEquals("B", node.getRoot().getName()); } /** @@ -37,8 +37,8 @@ public void testTreeWithSingleNode() { public void testTreeWithOneNestedLevel() { PhyloGeneticTreeParser parser = new PhyloGeneticTreeParser(); String s = "(B:6.0,(A:5.0,(Z:9.0,T:10):3.0,E:4.0):5.0,D:11.0);"; - TreeNode node = parser.parseTokensFromString(s); - assertEquals("B", node.getId()); + TreeNodeCollection node = parser.parseTokensFromString(s); + assertEquals("B", node.getRoot().getName()); } /** From 614a298a5d4a97ee7c9c733cbf992041faf5efad Mon Sep 17 00:00:00 2001 From: Ali Smesseim Date: Mon, 9 May 2016 19:23:08 +0200 Subject: [PATCH 2/2] fix test failures --- .../pl1_2016/parser/PhyloGeneticTreeParserTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParserTest.java b/src/test/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParserTest.java index 2051362..fc7835f 100644 --- a/src/test/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParserTest.java +++ b/src/test/java/io/github/programminglife2016/pl1_2016/parser/PhyloGeneticTreeParserTest.java @@ -27,7 +27,7 @@ public void testTreeWithSingleNode() { PhyloGeneticTreeParser parser = new PhyloGeneticTreeParser(); String s = "(B:6.0,A:5.0);"; TreeNodeCollection node = parser.parseTokensFromString(s); - assertEquals("B", node.getRoot().getName()); + assertEquals("B", node.getRoot().getChildren().get(0).getName()); } /** @@ -38,7 +38,7 @@ public void testTreeWithOneNestedLevel() { PhyloGeneticTreeParser parser = new PhyloGeneticTreeParser(); String s = "(B:6.0,(A:5.0,(Z:9.0,T:10):3.0,E:4.0):5.0,D:11.0);"; TreeNodeCollection node = parser.parseTokensFromString(s); - assertEquals("B", node.getRoot().getName()); + assertEquals("B", node.getRoot().getChildren().get(0).getName()); } /**