ee.telekom.workflow.api.Tree Maven / Gradle / Ivy
package ee.telekom.workflow.api;
import java.util.LinkedList;
import java.util.List;
/**
* A tree implementation where a tree node may carry content. Every node is aware of its parent, its previous and next sibling, and its child node.
* The implementation provides a method to find the tree node which is next in pre-order iteration.
*/
public class Tree {
private T content;
private Tree parent;
private Tree previous;
private Tree next;
private LinkedList> children = new LinkedList<>();
public static Tree root( Class clazz ){
return new Tree( null );
}
public static Tree of( T content ){
return new Tree( content );
}
private Tree( T content ){
this.content = content;
}
public T getContent(){
return content;
}
public Tree getParent(){
return parent;
}
public boolean hasPrevious(){
return previous != null;
}
public Tree getPrevious(){
return previous;
}
public boolean hasNext(){
return next != null;
}
public Tree getNext(){
return next;
}
public boolean hasChildren(){
return !children.isEmpty();
}
public Tree getFirstChild(){
return children.getFirst();
}
public Tree getLastChild(){
return children.getLast();
}
public List> getChildren(){
return children;
}
public Tree addChild( Tree child ){
if( !children.isEmpty() ){
children.getLast().next = child;
child.previous = children.getLast();
}
child.parent = this;
children.add( child );
return child;
}
public Tree addSibling( Tree sibling ){
return parent.addChild( sibling );
}
/**
* Iterates tree in pre-order (http://en.wikipedia.org/wiki/Tree_traversal)
*/
public Tree findPreOrderNext(){
if( hasChildren() ){
return getFirstChild();
}
if( hasNext() ){
return getNext();
}
Tree parent = getParent();
while( parent != null ){
if( parent.hasNext() ){
return parent.getNext();
}
parent = parent.getParent();
}
return null;
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder();
appendAsText( sb, "" );
return sb.toString();
}
private void appendAsText( StringBuilder sb, String identation ){
if( parent == null ){
sb.append( "\n" );
}
else{
sb.append( identation + content + "\n" );
}
identation = " " + identation;
for( Tree child : children ){
child.appendAsText( sb, identation );
}
}
}