package org.codehaus.mojo.pomtools.helpers;
/*
* Copyright 2001-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;
/** Used for representing and printing a hierarchy of objects.
*
* @author <a href="mailto:dhawkins@codehaus.org">David Hawkins</a>
* @version $Id$
*/
public class TreeNode
{
protected static final String NEWLINE = "\n";
protected static final int MAX_DEPTH = 1024;
public static final Stringifier DEFAULT_STRINGIFIER = new Stringifier() {
public String getNodeLabel( TreeNode tree )
{
return String.valueOf( tree.getId() );
}
};
private final Comparator comparator;
private final Object oid;
private final TreeNode parent;
private final TreeMap children;
public TreeNode( Object id )
{
this( id, null, null );
}
public TreeNode( Object id, Comparator comparator )
{
this( id, comparator, null );
}
public TreeNode( Object id, Comparator comparator, TreeNode parent )
{
this.oid = id;
this.comparator = comparator;
this.parent = parent;
this.children = new TreeMap( comparator );
}
protected Comparator getComparator()
{
return comparator;
}
public boolean containsChild( Object id )
{
return children.containsKey( id );
}
public TreeNode addChild( Object id )
{
if ( !children.containsKey( id ) )
{
children.put( id, new TreeNode( id, comparator, this ) );
}
return (TreeNode) children.get( id );
}
public TreeNode getParent()
{
return this.parent;
}
public TreeNode getSingleChild()
{
if ( this.children.isEmpty() || this.children.size() > 1 )
{
throw new IllegalArgumentException( "This node does not contain a single child" );
}
return (TreeNode) children.values().toArray()[0];
}
public List getChildren()
{
return Collections.unmodifiableList( new ArrayList( children.values() ) );
}
public Object getId()
{
return this.oid;
}
public boolean hasChildren()
{
return !children.isEmpty();
}
public String toString()
{
return toString( DEFAULT_STRINGIFIER );
}
public String toString( Stringifier stringifier )
{
StringBuffer sb = new StringBuffer();
boolean[] hasMore = new boolean[MAX_DEPTH];
printNode( stringifier, this, sb, 0, hasMore );
return sb.toString();
}
protected void printNode( Stringifier stringifier, TreeNode tree, StringBuffer sb, int depth, boolean[] hasMore )
{
for ( int i = 1; i < depth; i++ )
{
sb.append( hasMore[i] ? "| " : " " );
}
if ( depth > 0 )
{
sb.append( hasMore[depth] ? "|-- " : "`-- " );
}
int childDepth = depth + 1;
if ( this.oid == null && this.parent == null )
{
// don't print anything for a null parent and null label
childDepth = depth;
}
else
{
sb.append( stringifier.getNodeLabel( tree ) );
sb.append( NEWLINE );
}
if ( tree.hasChildren() )
{
for ( Iterator iter = tree.getChildren().iterator(); iter.hasNext(); )
{
TreeNode childTree = (TreeNode) iter.next();
hasMore[depth + 1] = iter.hasNext();
printNode( stringifier, childTree, sb, childDepth, hasMore );
}
}
}
public interface Stringifier
{
String getNodeLabel( TreeNode treeNode );
}
}