package com.joe.utilities.core.data;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
/**
* Represents a node of the Tree<T> class. The Node<T> is also a container,
* and can be thought of as instrumentation to determine the location of the
* type T in the Tree<T>.
*/
public class Node<T>
{
/** The parent node. */
private Node<T> parentNode = null;
/** The data. */
public T data;
/** The children. */
public List<Node<T>> children = new ArrayList<Node<T>>(4);
/**
* Instantiates a new node.
*
* @param data the data
*/
public Node(T data)
{
this(null, data);
}
/**
* Instantiates a new node.
*
* @param parentNode the parent node
* @param data the data
*/
public Node(Node<T> parentNode, T data)
{
super();
this.parentNode = parentNode;
this.data = data;
}
/**
* Return the children of Node<T>. The Tree<T> is represented by a single
* root Node<T> whose children are represented by a List<Node<T>>. Each
* of these Node<T> elements in the List can have children. The
* getChildren() method will return the children of a Node<T>.
*
* @return the children of Node<T>
*/
public List<Node<T>> getChildren()
{
return new ArrayList<Node<T>>(this.children);
}
/**
* Returns the number of immediate children of this Node<T>.
*
* @return the number of immediate children.
*/
public int size()
{
return children.size();
}
/**
* Sub tree size.
*
* @return the int
*/
public int subTreeSize()
{
int count = children.size();
for (Node<T> child : children)
{
count += child.subTreeSize();
}
return count;
}
/**
* Adds a child to the list of children for this Node<T>. The addition of
* the first child will create a new List<Node<T>>.
*
* @param child a Node<T> object to set.
*/
public Node<T> addChildNode(Node<T> child)
{
if (child == null)
throw new IllegalArgumentException("Cannot add null child node.");
// Already added
if (child.parentNode == this)
return child;
// Detach from existing parent. Establish this node as new parent
setParentNode(child);
// Add as child
children.add(child);
return child;
}
/**
* Adds the child. Convenience method to construct the Node with the given data
*
* @param data the data
*/
public Node<T> addChild(T data)
{
return addChildNode(new Node<T>(data));
}
/**
* Sets the parent node.
*
* @param child the new parent node
*/
private void setParentNode(Node<T> child)
{
// Already parent.
if (child.parentNode == this)
return;
// Detach from existing parent. Establish this node as new parent
if (child.parentNode != null)
child.parentNode.removeChildNode(child);
child.parentNode = this;
}
/**
* Clear.
*/
public void clear()
{
// Recursively clear the subnodes
for (Node<T> e : this.children)
{
if (e != null)
e.clear();
}
// Release references to child nodes
this.children.clear();
}
/**
* Remove the Node<T> element at index index of the List<Node<T>>.
*
* @param index the index of the element to delete.
*
* @throws IndexOutOfBoundsException if thrown.
*/
public Node<T> removeChildNode(Node<T> child)
{
// Detach
if (child != null)
{
child.parentNode = null;
children.remove(child);
}
return child;
}
/**
* Gets the node depth.
*
* @return the node depth
*/
public int getNodeDepth()
{
if (parentNode != null)
return 1+parentNode.getNodeDepth();
else
return 0;
}
/**
* Gets the data.
*
* @return the data
*/
public T getData()
{
return this.data;
}
/**
* Gets the data.
*
* @return the data
*/
public void setData(T data)
{
this.data = data;
}
/**
* To string.
*
* @return the string
*
* @see java.lang.Object#toString()
*/
public String toString()
{
StringBuilder sb = new StringBuilder(64);
int depth = getNodeDepth();
if (depth > 0)
{
sb.append(StringUtils.repeat(" ", depth));
sb.append("|->");
}
sb.append(data);
for (Node<T> node : this.children)
{
sb.append((char)10);
sb.append(node.toString());
}
return sb.toString();
}
}