001    /*
002     * This file is part of the Echo Point Project.  This project is a
003     * collection of Components that have extended the Echo Web Application
004     * Framework Version 3.
005     *
006     * Version: MPL 1.1
007     *
008     * The contents of this file are subject to the Mozilla Public License Version
009     * 1.1 (the "License"); you may not use this file except in compliance with
010     * the License. You may obtain a copy of the License at
011     * http://www.mozilla.org/MPL/
012     *
013     * Software distributed under the License is distributed on an "AS IS" basis,
014     * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
015     * for the specific language governing rights and limitations under the
016     * License.
017     */
018    
019    package echopoint.tree;
020    
021    import java.util.Enumeration;
022    import java.util.Stack;
023    import java.util.EmptyStackException;
024    import java.util.NoSuchElementException;
025    import java.io.Serializable;
026    
027    /**
028     * An enumeration that follows the path from {@code ancestor} to the node.
029     * The enumeration's {@code nextElement()} method first returns
030     * {@code ancestor}, then the child of {@code ancestor} that is an ancestor
031     * of the node, and so on, and finally returns this node. Creation of the
032     * enumeration is O(m) where m is the number of nodes between this node and
033     * {@code ancestor}, inclusive. Each {@code nextElement()} message is O(1).
034     *
035     * @author Brad Baker, Rakesh Vidyadharan 2009-05-29
036     * @version $Id: PathBetweenNodesEnumeration.java 213 2009-06-03 16:34:13Z sptrakesh $
037     * @since 3.0.0b3
038     */
039    public final class PathBetweenNodesEnumeration
040        implements Enumeration<TreeNode>, Serializable
041    {
042      private static final long serialVersionUID = 1l;
043    
044      protected Stack<TreeNode> stack = new Stack<TreeNode>();
045    
046      /**
047       * Create a new enumeration from the specified ancestor the destination.
048       *
049       * @param ancestor The start of the enumeration.
050       * @param descendant The destination of the enumeration.
051       */
052      public PathBetweenNodesEnumeration( final TreeNode ancestor,
053          final TreeNode descendant )
054      {
055        if ( ancestor == null || descendant == null )
056        {
057          throw new IllegalArgumentException( "argument is null" );
058        }
059    
060        stack.push( descendant );
061        TreeNode current = descendant;
062    
063        while ( current != ancestor )
064        {
065          current = current.getParent();
066    
067          if ( current == null && ( descendant != ancestor ) )
068          {
069            throw new IllegalArgumentException( "node " + ancestor
070                + " is not an ancestor of " + descendant );
071          }
072    
073          stack.push( current );
074        }
075      }
076    
077      /** {@inheritDoc} */
078      public boolean hasMoreElements()
079      {
080        return stack.size() > 0;
081      }
082    
083      /** {@inheritDoc} */
084      public TreeNode nextElement()
085      {
086        try
087        {
088          return stack.pop();
089        }
090        catch ( final EmptyStackException e )
091        {
092          throw new NoSuchElementException( "No more elements" );
093        }
094      }
095    }