X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Fext%2Farchaeopteryx%2FTreeNode.java;fp=src%2Fjalview%2Fext%2Farchaeopteryx%2FTreeNode.java;h=08441713545b27a42fcf0825454374f1868ba4e6;hb=4a3def9f59cefe629c9a33d87483283aee085928;hp=8e06d6c524369a9f654aef04d61de019699aa2d7;hpb=eca4795050a0f7eca3d5dece68eaa54987cebd15;p=jalview.git diff --git a/src/jalview/ext/archaeopteryx/TreeNode.java b/src/jalview/ext/archaeopteryx/TreeNode.java index 8e06d6c..0844171 100644 --- a/src/jalview/ext/archaeopteryx/TreeNode.java +++ b/src/jalview/ext/archaeopteryx/TreeNode.java @@ -1,38 +1,256 @@ package jalview.ext.archaeopteryx; -import jalview.ext.treeviewer.ExternalTreeNodeI; +import jalview.datamodel.SequenceI; +import jalview.ext.forester.DataConversions; +import jalview.ext.treeviewer.TreeNodeI; +import java.awt.Color; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.forester.phylogeny.PhylogenyMethods; import org.forester.phylogeny.PhylogenyNode; -public class TreeNode implements ExternalTreeNodeI +public class TreeNode implements TreeNodeI { private final PhylogenyNode node; - public TreeNode(PhylogenyNode aptxNode) + private SequenceI nodeSeq; + + private static Map originalNodes = new HashMap<>( + 500); // prolly make this size dynamic? + + private static Map wrappedNodes = new HashMap<>( + 500); + + /** + * Please don't use me directly. + * + * @param aptxNode + */ + private TreeNode(PhylogenyNode aptxNode) { node = aptxNode; + if (aptxNode.getNodeData().getSequence() != null) + { + nodeSeq = DataConversions + .createJalviewSequence(aptxNode); + } + originalNodes.put(aptxNode, this); + wrappedNodes.put(this, aptxNode); + } + @Override - public PhylogenyNode getOriginalNode() + public String getNodeName() { - return node; + return node.getName(); } + @Override - public String getNodeName() + public List getAllDescendants() { - return node.getName(); + + List descNodes = PhylogenyMethods + .getAllDescendants(node); + return getUniqueWrappers(descNodes); + + + } + + @Override + public List getExternalDescendants() + { + List extDescNodes = node.getAllExternalDescendants(); + return getUniqueWrappers(extDescNodes); + } + + + @Override + public List getDirectChildren() + { + List childNodes = node.getDescendants(); + return getUniqueWrappers(childNodes); + + + } + + + + @Override + public void setSequence(SequenceI seq) + { + nodeSeq = seq; + org.forester.phylogeny.data.Sequence foresterFormatSeq = DataConversions + .createForesterSequence(seq, true); + node.getNodeData().setSequence(foresterFormatSeq); + + } + + @Override + public SequenceI getSequence() + { + return nodeSeq; + } + + @Override + public void addAsChild(TreeNodeI childNode) + { + PhylogenyNode aptxNode = unwrapNode(childNode); + + node.addAsChild(aptxNode); + + } + + @Override + public long getId() + { + return node.getId(); + } + + @Override + public float getXcoord() + { + return node.getXcoord(); + } + + @Override + public void setBranchColor(Color branchColor) + { + PhylogenyMethods.setBranchColorValue(node, branchColor); + } @Override - public List getChildren() + public boolean isInternal() { - // return node.getDescendants(); - return null; + return node.isInternal(); } + public static List getUniqueWrappers( + List aptxNodes) + { + List wrappedNodes = new ArrayList<>( + aptxNodes.size()); + + for (PhylogenyNode aptxNode : aptxNodes) + { + wrappedNodes.add(getUniqueWrapper(aptxNode)); + } + return wrappedNodes; + } + + /** + * This method should be used to create new wrappers as there is a possibility + * the Archaeopteryx node was already introduced to Jalview previously so this + * avoids giving one node duplicate wrappers + * + * @param aptxNode + * @return + */ + public static TreeNodeI getUniqueWrapper( + PhylogenyNode aptxNode) + { + if (aptxNode == null) + { + return null; + } + TreeNodeI wrappedNode = originalNodes.get(aptxNode); + if (wrappedNode == null) + { + wrappedNode = new TreeNode(aptxNode); + } + return wrappedNode; + } + + /** + * Attempts to unwrap the given node, if the unwrapped node already exists it + * is simply returned as is. If it is not however, the wrapper will be used to + * create a new Archaeopteryx node. This way it becomes possible to construct + * new Archaeopteryx nodes from different tree viewers, as long as they + * implement the interface. + * + * @param wrappedNode + * @return + */ + protected static PhylogenyNode unwrapNode(TreeNodeI wrappedNode) + { + if (wrappedNode == null) + { + return null; + } + PhylogenyNode aptxNode = wrappedNodes.get(wrappedNode); + if (aptxNode == null) + { + // expand this + aptxNode = new PhylogenyNode(wrappedNode.getNodeName()); + + } + return aptxNode; + + } + + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = (int) (prime * result + + ((node == null) ? 0 : (node.hashCode() * getId()))); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + TreeNode other = (TreeNode) obj; + if (node == null) + { + if (other.node != null) + { + return false; + } + } + if (getId() != other.getId()) + { + return false; + } + + if (!node.equals(other.node)) + { + return false; + } + return true; + } + + + @Override + public float getYcoord() + { + return node.getYcoord(); + } + + @Override + public boolean isCollapsed() + { + return node.isCollapse(); + } }