/*
* SimpleNode.java
*
* Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
*
* This file is part of BEAST.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership and licensing.
*
* BEAST is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* BEAST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BEAST; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package dr.evolution.tree;
import dr.evolution.util.Taxon;
import dr.util.Attributable;
import java.util.Iterator;
/**
* A simple implementation of the Node interface.
*
* @version $Id: SimpleNode.java,v 1.40 2005/08/16 16:03:17 rambaut Exp $
*
* @author Andrew Rambaut
* @author Alexei Drummond
*/
public class SimpleNode implements NodeRef, Attributable {
/** parent node */
private SimpleNode parent;
/** number of node */
private int nodeNumber;
/** height of this node */
private double height;
/** instantaneous rate at this node */
private double rate;
/** the taxon if node is external */
private Taxon taxon = null;
//
// Private stuff
//
private SimpleNode[] child;
/** constructor default node */
public SimpleNode()
{
parent = null;
child =null;
height = 0.0;
rate = 1.0;
nodeNumber = 0;
}
public SimpleNode(SimpleNode node) {
parent = null;
setHeight(node.getHeight());
setRate(node.getRate());
setId(node.getId());
setNumber(node.getNumber());
setTaxon(node.getTaxon());
child = null;
for (int i = 0; i < node.getChildCount(); i++) {
addChild(new SimpleNode(node.getChild(i)));
}
}
/** constructor used to clone a node and all children */
public SimpleNode(Tree tree, NodeRef node)
{
parent = null;
setHeight(tree.getNodeHeight(node));
setRate(tree.getNodeRate(node));
final int nodeNumber = node.getNumber();
setId(tree.getTaxonId(nodeNumber));
setNumber(nodeNumber);
setTaxon(tree.getNodeTaxon(node));
child = null;
for (int i = 0; i < tree.getChildCount(node); i++) {
addChild(new SimpleNode(tree, tree.getChild(node, i)));
}
}
public SimpleNode getDeepCopy() {
return new SimpleNode(this);
}
/**
* Returns the parent node of this node.
*/
public final SimpleNode getParent() {
return parent;
}
/** Set the parent node of this node. */
public void setParent(SimpleNode node) { parent = node; }
/**
* Get the height of this node.
*/
public final double getHeight() {
return height;
}
/**
* Set the height of this node.
*/
public final void setHeight(double value) {
height = value;
}
/**
* Get the rate at this node.
*/
public final double getRate() {
return rate;
}
/**
* Set the rate at this node.
*/
public final void setRate(double value) {
rate = value;
}
public void setNumber(int n) {
nodeNumber = n;
}
public int getNumber() {
return nodeNumber;
}
public void setTaxon(Taxon taxon) {
this.taxon = taxon;
}
public Taxon getTaxon() {
return taxon;
}
/**
* get child node
*
* @param n number of child
*
* @return child node
*/
public SimpleNode getChild(int n)
{
assert 0 <= n && n < child.length;
return child[n];
}
public boolean hasChild(SimpleNode node) {
for (int i = 0, n = getChildCount(); i < n; i++) {
if (node == child[i]) return true;
}
return false;
}
/**
* add new child node
*
* @param n new child node
*/
public void addChild(SimpleNode n)
{
insertChild(n, getChildCount());
}
/**
* add new child node (insertion at a specific position)
*
* @param n new child node
+ @param pos position
*/
public void insertChild(SimpleNode n, int pos)
{
int numChildren = getChildCount();
SimpleNode[] newChild = new SimpleNode[numChildren + 1];
for (int i = 0; i < pos; i++)
{
newChild[i] = child[i];
}
newChild[pos] = n;
for (int i = pos; i < numChildren; i++)
{
newChild[i+1] = child[i];
}
child = newChild;
n.setParent(this);
}
/**
* remove child
*
* @param n child to be removed
*/
public SimpleNode removeChild(SimpleNode n)
{
int numChildren = getChildCount();
SimpleNode[] newChild = new SimpleNode[numChildren-1];
int j = 0;
boolean found = false;
for (int i = 0; i < numChildren; i++) {
if (child[i] != n) {
newChild[j] = child[i];
j++;
} else
found = true;
}
if (!found)
throw new IllegalArgumentException("Nonexistent child");
//remove parent link from removed child!
n.setParent(null);
child = newChild;
return n;
}
/**
* remove child
*
* @param n number of child to be removed
*/
public SimpleNode removeChild(int n)
{
int numChildren = getChildCount();
if (n >= numChildren)
{
throw new IllegalArgumentException("Nonexistent child");
}
return removeChild(child[n]);
}
public void replaceChild(SimpleNode childNode, SimpleNode replacment) {
for(int nc = 0; nc < child.length; ++nc) {
if( child[nc] == childNode ) {
replacment.setParent(this);
child[nc] = replacment;
break;
}
}
}
/**
* check whether this node has any children
*
* @return result (true or false)
*/
public boolean hasChildren()
{
return (getChildCount() != 0);
}
/**
* check whether this node is an external node
*
* @return result (true or false)
*/
public boolean isExternal() {
return !hasChildren();
}
/**
* check whether this node is a root node
*
* @return result (true or false)
*/
public boolean isRoot()
{
return (getParent() == null);
}
/**
* Returns the number of children this node has.
*/
public final int getChildCount() {
if (child == null) return 0;
return child.length;
}
// **************************************************************
// Identifiable IMPLEMENTATION
// **************************************************************
private String id = null;
/**
* @return the id as a string.
*/
public String getId() {
return id;
}
/**
* set the id as a string.
*/
public void setId(String id) {
this.id = id;
}
// **************************************************************
// Attributable IMPLEMENTATION
// **************************************************************
private Attributable.AttributeHelper attributes = null;
/**
* Sets an named attribute for this object.
* @param name the name of the attribute.
* @param value the new value of the attribute.
*/
public void setAttribute(String name, Object value) {
if (attributes == null)
attributes = new Attributable.AttributeHelper();
attributes.setAttribute(name, value);
}
/**
* @return an object representing the named attributed for this object.
* @param name the name of the attribute of interest.
*/
public Object getAttribute(String name) {
if (attributes == null)
return null;
else
return attributes.getAttribute(name);
}
/**
* @return an iterator of the attributes that this object has.
*/
public Iterator<String> getAttributeNames() {
if (attributes == null)
return null;
else
return attributes.getAttributeNames();
}
}