content: package org.opencyc.cycobject;
  
  import java.util.*;
  import org.opencyc.api.*;
  
  /**
   * Implements an <tt>Enumeration</tt> for <tt>CycList</tt> objects which traverses
   * recursively into embedded CycLists, in a depth-first fashion, returning the
   * objects which are both non-CycList and non-nil.
   *
   * @version $0.1$
   * @author Stephen L. Reed
   *
   * <p>Copyright 2001 Cycorp, Inc., license is open source GNU LGPL.
   * <p><a href="http://www.opencyc.org/license.txt">the license</a>
   * <p><a href="http://www.opencyc.org">www.opencyc.org</a>
   * <p><a href="http://www.sourceforge.net/projects/opencyc">OpenCyc at SourceForge</a>
   * <p>
   * THIS SOFTWARE AND KNOWLEDGE BASE CONTENT ARE PROVIDED ``AS IS'' AND
   * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
   * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OPENCYC
   * ORGANIZATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE AND KNOWLEDGE
   * BASE CONTENT, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  public class CycListVisitor implements Enumeration {
  
      /**
       * Contains the next <tt>Object</tt> in the sequence of non-CycList
       * elements of the <tt>CycList</tt> tree structure.
       */
      protected Object nextElement = null;
  
      /**
       * Stack of <tt>CycList</tt> <tt>Iterators</tt>
       */
      protected Stack iterators = new Stack();
  
  
      /**
       * Constructs a new <tt>CycListEnumeration</tt> object.
       *
       * @param the <tt>CycList</tt> for recursive enumeration.
       */
      public CycListVisitor(CycList cycList) {
          iterators.push(cycList.iterator());
          getNextElement();
      }
  
      /**
       * Tests if this enumeration contains more elements.
       *
       * @return  <tt>true</tt> if and only if this enumeration object
       *           contains at least one more element to provide;
       *          <tt>false</tt> otherwise.
       */
      public boolean hasMoreElements() {
          return nextElement != null;
      }
  
      /**
       * Returns the next element of this enumeration if this enumeration
       * object has at least one more element to provide.
       *
       * @return     the next element of this <tt>Enumeration</tt>.
       * @exception  NoSuchElementException  if no more elements exist.
       */
      public Object nextElement() {
          if (nextElement == null)
              throw new NoSuchElementException();
          Object answer = nextElement;
          // Stay one ahead to facilitate the determination of hasMoreElements.
          getNextElement();
          return answer;
      }
  
      /**
       * Gets the next element in the sequence.  This method uses recursive descent.
       */
      protected void getNextElement() {
          nextElement = null;
          while (true) {
              if (iterators.empty())
                  // Reached the end of the whole CycList.
                  return;
              Iterator iterator = (Iterator) iterators.peek();
              if (! iterator.hasNext()) {
                  iterators.pop();
                  // Reached the end of an embedded CycList.
                  continue;
              }
              Object element = iterator.next();
              if (element.equals(CycObjectFactory.nil))
                  // bypass nils.
                  continue;
              if (! (element instanceof CycList)) {
                  nextElement = element;
                  // Found the next non-nil element.
                  return;
              }
              // Iterate over the embedded CycList.
              iterators.push(((CycList) element).iterator());
          }
      }
  
  }
  