001package org.jsoup.select;
002
003import org.jsoup.nodes.Element;
004import org.jsoup.nodes.Node;
005
006/**
007 Node visitor interface, used to walk the DOM, and visit each Node. Execute via {@link #traverse(Node)} or
008 {@link Node#traverse(NodeVisitor)}. The traversal is depth-first.
009 <p>
010 This interface provides two methods, {@link #head} and {@link #tail}. The head method is called when a node is first
011 seen, and the tail method when all that node's children have been visited. As an example, {@code head} can be used to
012 emit a start tag for a node, and {@code tail} to create the end tag. The {@code tail} method defaults to a no-op, so
013 the {@code head} method is the {@link FunctionalInterface}.
014 </p>
015 <p><b>Example:</b></p>
016 <pre><code>
017 doc.body().traverse((node, depth) -&gt; {
018     switch (node) {
019         case Element el     -&gt; print(el.tag() + ": " + el.ownText());
020         case DataNode data  -&gt; print("Data: " + data.getWholeData());
021         default             -&gt; print(node.nodeName() + " at depth " + depth);
022     }
023 });
024 </code></pre>
025 */
026@FunctionalInterface
027public interface NodeVisitor {
028    /**
029     Callback for when a node is first visited.
030     <p>The node may be modified (e.g. {@link Node#attr(String)}, replaced {@link Node#replaceWith(Node)}) or removed
031     {@link Node#remove()}. If it's {@code instanceOf Element}, you may cast it to an {@link Element} and access those
032     methods.</p>
033
034     @param node the node being visited.
035     @param depth the depth of the node, relative to the root node. E.g., the root node has depth 0, and a child node
036     of that will have depth 1.
037     */
038    void head(Node node, int depth);
039
040    /**
041     Callback for when a node is last visited, after all of its descendants have been visited.
042     <p>This method has a default no-op implementation.</p>
043     <p>Note that neither replacement with {@link Node#replaceWith(Node)} nor removal with {@link Node#remove()} is
044     supported during {@code tail()}.
045
046     @param node the node being visited.
047     @param depth the depth of the node, relative to the root node. E.g., the root node has depth 0, and a child node
048     of that will have depth 1.
049     */
050    default void tail(Node node, int depth) {
051        // no-op by default, to allow just specifying the head() method
052    }
053
054    /**
055     Run a depth-first traverse of the root and all of its descendants.
056     @param root the initial node point to traverse.
057     @since 1.21.1
058     */
059    default void traverse(Node root) {
060        NodeTraversor.traverse(this, root);
061    }
062}