mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			273 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			273 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* ElementIterator.java --
 | |
|    Copyright (C) 2005 Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| package javax.swing.text;
 | |
| 
 | |
| import java.util.Stack;
 | |
| 
 | |
| /**
 | |
|  * This class can be used to iterate over the {@link Element} tree of
 | |
|  * a {@link Document} or an {@link Element}.  This iterator performs
 | |
|  * an "in-order" traversal -- first it visits a node, then each of the
 | |
|  * node's children in order.  No locking is performed during the
 | |
|  * iteration; that is up to the caller.
 | |
|  */
 | |
| public class ElementIterator implements Cloneable
 | |
| {
 | |
|   /**
 | |
|    * Uses to track the iteration on the stack.
 | |
|    */
 | |
|   private class ElementRef
 | |
|   {
 | |
|     /**
 | |
|      * The element.
 | |
|      */
 | |
|     Element element;
 | |
| 
 | |
|     /**
 | |
|      * The child index. -1 means the element itself. >= 0 values mean the
 | |
|      * n-th child of the element.
 | |
|      */
 | |
|     int index;
 | |
| 
 | |
|     /**
 | |
|      * Creates a new ElementRef.
 | |
|      *
 | |
|      * @param el the element
 | |
|      */
 | |
|     ElementRef(Element el)
 | |
|     {
 | |
|       element = el;
 | |
|       index = -1;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // The root element.
 | |
|   private Element root;
 | |
| 
 | |
|   /**
 | |
|    * Holds ElementRefs.
 | |
|    */
 | |
|   private Stack stack;
 | |
| 
 | |
|   /**
 | |
|    * Create a new ElementIterator to iterate over the given document.
 | |
|    * @param document the Document over which we iterate
 | |
|    */
 | |
|   public ElementIterator(Document document)
 | |
|   {
 | |
|     root = document.getDefaultRootElement();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Create a new ElementIterator to iterate over the given document.
 | |
|    * @param root the Document over which we iterate
 | |
|    */
 | |
|   public ElementIterator(Element root)
 | |
|   {
 | |
|     this.root = root;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns a new ElementIterator which is a clone of this
 | |
|    * ElementIterator.
 | |
|    */
 | |
|   public Object clone()
 | |
|   {
 | |
|     try
 | |
|       {
 | |
|         return super.clone();
 | |
|       }
 | |
|     catch (CloneNotSupportedException _)
 | |
|       {
 | |
|         // Can't happen.
 | |
|         return null;
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the current element.
 | |
|    */
 | |
|   public Element current()
 | |
|   {
 | |
|     Element current;
 | |
|     if (stack == null)
 | |
|       current = first();
 | |
|     else
 | |
|       {
 | |
|         current = null;
 | |
|         if (! stack.isEmpty())
 | |
|           {
 | |
|             ElementRef ref = (ElementRef) stack.peek();
 | |
|             Element el = ref.element;
 | |
|             int index = ref.index;
 | |
|             if (index == -1)
 | |
|               current = el;
 | |
|             else
 | |
|               current = el.getElement(index);
 | |
|           }
 | |
|       }
 | |
|     return current;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the depth to which we have descended in the tree.
 | |
|    */
 | |
|   public int depth()
 | |
|   {
 | |
|     int depth = 0;
 | |
|     if (stack != null)
 | |
|       depth = stack.size();
 | |
|     return depth;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the first element in the tree.
 | |
|    */
 | |
|   public Element first()
 | |
|   {
 | |
|     Element first = null;
 | |
|     if (root != null)
 | |
|       {
 | |
|         stack = new Stack();
 | |
|         if (root.getElementCount() > 0)
 | |
|           stack.push(new ElementRef(root));
 | |
|         first = root;
 | |
|       }
 | |
|     return first;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Advance the iterator and return the next element of the tree,
 | |
|    * performing an "in-order" traversal.
 | |
|    */
 | |
|   public Element next()
 | |
|   {
 | |
|     Element next;
 | |
|     if (stack == null)
 | |
|       next = first();
 | |
|     else
 | |
|       {
 | |
|         next = null;
 | |
|         if (! stack.isEmpty())
 | |
|           {
 | |
|             ElementRef ref = (ElementRef) stack.peek();
 | |
|             Element el = ref.element;
 | |
|             int index = ref.index;
 | |
|             if (el.getElementCount() > index + 1)
 | |
|               {
 | |
|                 Element child = el.getElement(index + 1);
 | |
|                 if (child.isLeaf())
 | |
|                   ref.index++;
 | |
|                 else
 | |
|                   stack.push(new ElementRef(child));
 | |
|                 next = child;
 | |
|                 next = child;
 | |
|               }
 | |
|             else
 | |
|               {
 | |
|                 stack.pop();
 | |
|                 if (! stack.isEmpty())
 | |
|                   {
 | |
|                     ElementRef top = (ElementRef) stack.peek();
 | |
|                     top.index++;
 | |
|                     next = next();
 | |
|                   }
 | |
|               }
 | |
|           }
 | |
|         // else return null.
 | |
|       }
 | |
|     return next;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the previous item.  Does not modify the iterator state.
 | |
|    */
 | |
|   public Element previous()
 | |
|   {
 | |
|     Element previous = null;
 | |
|     int stackSize;
 | |
|     if (stack != null && (stackSize = stack.size()) > 0)
 | |
|       {
 | |
|         ElementRef ref = (ElementRef) stack.peek();
 | |
|         Element el = ref.element;
 | |
|         int index = ref.index;
 | |
|         if (index > 0)
 | |
|           {
 | |
|             previous = deepestLeaf(el.getElement(--index));
 | |
|           }
 | |
|         else if (index == 0)
 | |
|           {
 | |
|             previous = el;
 | |
|           }
 | |
|         else if (index == -1)
 | |
|           {
 | |
|             ElementRef top = (ElementRef) stack.pop();
 | |
|             ElementRef item = (ElementRef) stack.peek();
 | |
|             stack.push(top);
 | |
|             index = item.index;
 | |
|             el = item.element;
 | |
|             previous = index == -1 ? el : deepestLeaf(el.getElement(index));
 | |
|           }
 | |
|       }
 | |
|     return previous;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Determines and returns the deepest leaf of the element <code>el</code>.
 | |
|    *
 | |
|    * @param el the base element
 | |
|    *
 | |
|    * @returnthe deepest leaf of the element <code>el</code>
 | |
|    */
 | |
|   private Element deepestLeaf(Element el)
 | |
|   {
 | |
|     Element leaf;
 | |
|     if (el.isLeaf())
 | |
|       leaf = el;
 | |
|     else
 | |
|       {
 | |
|         int count = el.getElementCount();
 | |
|         if (count == 0)
 | |
|           leaf = el;
 | |
|         else
 | |
|           leaf = deepestLeaf(el.getElement(count - 1));
 | |
|       }
 | |
|     return leaf;
 | |
|   }
 | |
| }
 |