package com.joe.utilities.core.data;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a Tree of Objects of generic type T. The Tree is represented as a
* single rootElement which points to a List<Node<T>> of children. There is no
* restriction on the number of children that a particular node may have. This
* Tree provides a method to serialize the Tree into a List by doing a pre-order
* traversal. It has several methods to allow easy updating of Nodes in the
* Tree.
*/
public class Tree<T>
{
/** The root element. */
private Node<T> rootElement;
/**
* Instantiates a new tree.
*
* @param rootElement the root element
*/
public Tree(T data)
{
this(new Node<T>(data));
}
/**
* Instantiates a new tree.
*
* @param rootElement the root element
*/
public Tree(Node<T> rootElement)
{
super();
this.rootElement = rootElement;
}
/**
* Instantiates a new tree.
*/
public Tree()
{
this((Node<T>)null);
}
/**
* Return the root Node of the tree.
*
* @return the root element.
*/
public Node<T> getRootElement()
{
return this.rootElement;
}
/**
* Set the root Element for the tree.
*
* @param rootElement the root element to set.
*/
public Node<T> setRootElement(T data)
{
return setRootElement(new Node<T>(data));
}
/**
* Set the root Element for the tree.
*
* @param rootElement the root element to set.
*/
public Node<T> setRootElement(Node<T> rootElement)
{
// Clear references if changing an existing root element
if (this.rootElement != null && this.rootElement != rootElement)
this.rootElement.clear();
// Assign new root element
this.rootElement = rootElement;
return this.rootElement;
}
/**
* Clear.
*/
public void clear()
{
if (rootElement != null)
rootElement.clear();
}
/**
* Size.
*
* @return the int
*/
public int size()
{
if (rootElement != null)
return 1 + rootElement.subTreeSize();
else
return 0;
}
/**
* Returns the Tree<T> as a List of Node<T> objects. The elements of the
* List are generated from a pre-order traversal of the tree.
*
* @return a List<Node<T>>.
*/
public List<Node<T>> toList()
{
List<Node<T>> list = new ArrayList<Node<T>>(16);
traverse(rootElement, list);
return list;
}
/**
* Returns a String representation of the Tree. The elements are generated
* from a pre-order traversal of the Tree.
*
* @return the String representation of the Tree.
*/
public String toString()
{
if (rootElement != null)
{
if (rootElement.getData() != null)
return "Tree of class " + rootElement.getData().getClass().getName() + ":\n"+ rootElement.toString();
else
return "Tree:\n"+ rootElement.toString();
}
else
{
return "Tree has no root element";
}
}
/**
* Walks the Tree in pre-order style. This is a recursive method, and is
* called from the toList() method with the root element as the first
* argument. It appends to the second argument, which is passed by reference *
* as it recurses down the tree.
*
* @param element the starting element.
* @param list the output of the walk.
*/
private void traverse(Node<T> element, List<Node<T>> list)
{
if (element == null)
throw new IllegalStateException("Tree node (root or child) is not yet defined. Cannot traverse tree.");
list.add(element);
for (Node<T> data : element.getChildren())
{
traverse(data, list);
}
}
}