/*
 * Copyright (c) 2000 World Wide Web Consortium,
 * (Massachusetts Institute of Technology, Institut National de
 * Recherche en Informatique et en Automatique, Keio University). All
 * Rights Reserved. This program is distributed under the W3C's Software
 * Intellectual Property License. This program 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 W3C License http://www.w3.org/Consortium/Legal/ for more details.
 */

package org.w3c.dom.traversal;

import org.w3c.dom.Node;
import org.w3c.dom.DOMException;

/**
 * <code>DocumentTraversal</code> contains methods that create iterators and
 * tree-walkers to traverse a node and its children in document order (depth
 * first, pre-order traversal, which is equivalent to the order in which the
 * start tags occur in the text representation of the document). In DOMs which
 * support the Traversal feature, <code>DocumentTraversal</code> will be
 * implemented by the same objects that implement the Document interface.
 * <p>
 * See also the <a
 * href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Traversal-Range-20001113'>Document
 * Object Model (DOM) Level 2 Traversal and Range Specification</a>.
 * 
 * @since DOM Level 2
 */
public interface DocumentTraversal {
	/**
	 * Create a new <code>NodeIterator</code> over the subtree rooted at the
	 * specified node.
	 * 
	 * @param rootThe
	 *            node which will be iterated together with its children. The
	 *            iterator is initially positioned just before this node. The
	 *            <code>whatToShow</code> flags and the filter, if any, are
	 *            not considered when setting this position. The root must not
	 *            be <code>null</code>.
	 * @param whatToShowThis
	 *            flag specifies which node types may appear in the logical
	 *            view of the tree presented by the iterator. See the
	 *            description of <code>NodeFilter</code> for the set of
	 *            possible <code>SHOW_</code> values.These flags can be
	 *            combined using <code>OR</code>.
	 * @param filterThe
	 *            <code>NodeFilter</code> to be used with this
	 *            <code>TreeWalker</code>, or <code>null</code> to
	 *            indicate no filter.
	 * @param entityReferenceExpansionThe
	 *            value of this flag determines whether entity reference nodes
	 *            are expanded.
	 * @return The newly created <code>NodeIterator</code>.
	 * @exception DOMException
	 *                NOT_SUPPORTED_ERR: Raised if the specified
	 *                <code>root</code> is <code>null</code>.
	 */
	public NodeIterator createNodeIterator(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException;

	/**
	 * Create a new <code>TreeWalker</code> over the subtree rooted at the
	 * specified node.
	 * 
	 * @param rootThe
	 *            node which will serve as the <code>root</code> for the
	 *            <code>TreeWalker</code>. The <code>whatToShow</code>
	 *            flags and the <code>NodeFilter</code> are not considered
	 *            when setting this value; any node type will be accepted as
	 *            the <code>root</code>. The <code>currentNode</code> of
	 *            the <code>TreeWalker</code> is initialized to this node,
	 *            whether or not it is visible. The <code>root</code>
	 *            functions as a stopping point for traversal methods that
	 *            look upward in the document structure, such as
	 *            <code>parentNode</code> and nextNode. The
	 *            <code>root</code> must not be <code>null</code>.
	 * @param whatToShowThis
	 *            flag specifies which node types may appear in the logical
	 *            view of the tree presented by the tree-walker. See the
	 *            description of <code>NodeFilter</code> for the set of
	 *            possible SHOW_ values.These flags can be combined using
	 *            <code>OR</code>.
	 * @param filterThe
	 *            <code>NodeFilter</code> to be used with this
	 *            <code>TreeWalker</code>, or <code>null</code> to
	 *            indicate no filter.
	 * @param entityReferenceExpansionIf
	 *            this flag is false, the contents of
	 *            <code>EntityReference</code> nodes are not presented in
	 *            the logical view.
	 * @return The newly created <code>TreeWalker</code>.
	 * @exception DOMException
	 *                NOT_SUPPORTED_ERR: Raised if the specified
	 *                <code>root</code> is <code>null</code>.
	 */
	public TreeWalker createTreeWalker(Node root, int whatToShow, NodeFilter filter, boolean entityReferenceExpansion) throws DOMException;

}
