001package org.jsoup.select;
002
003import org.jsoup.nodes.Node;
004
005/**
006 A controllable Node visitor interface. Execute via {@link #traverse(Node)}.
007 <p>
008 This interface provides two methods, {@code head} and {@code tail}. The head method is called when a node is first seen,
009 and the tail method when all that node's children have been visited.
010 </p>
011 <p>
012 For each visited node, the resulting action may be:
013 <ul>
014 <li>continue ({@link FilterResult#CONTINUE}),</li>
015 <li>skip all children ({@link FilterResult#SKIP_CHILDREN}),</li>
016 <li>skip node entirely ({@link FilterResult#SKIP_ENTIRELY}),</li>
017 <li>remove the subtree ({@link FilterResult#REMOVE}),</li>
018 <li>interrupt the iteration and return ({@link FilterResult#STOP}).</li>
019 </ul>
020 The difference between {@link FilterResult#SKIP_CHILDREN} and {@link FilterResult#SKIP_ENTIRELY} is that the first
021 will invoke {@link NodeFilter#tail(Node, int)} on the node, while the latter will not.
022 Within {@link NodeFilter#tail(Node, int)}, both are equivalent to {@link FilterResult#CONTINUE}.
023 </p>
024 */
025public interface NodeFilter {
026    /**
027     Traversal action.
028     */
029    enum FilterResult {
030        /** Continue processing the tree */
031        CONTINUE,
032        /** Skip the child nodes, but do call {@link NodeFilter#tail(Node, int)} next. */
033        SKIP_CHILDREN,
034        /** Skip the subtree, and do not call {@link NodeFilter#tail(Node, int)}. */
035        SKIP_ENTIRELY,
036        /** Remove the node and its children */
037        REMOVE,
038        /** Stop processing */
039        STOP
040    }
041
042    /**
043     * Callback for when a node is first visited.
044     * @param node the node being visited.
045     * @param depth the depth of the node, relative to the root node. E.g., the root node has depth 0, and a child node of that will have depth 1.
046     * @return Traversal action
047     */
048    FilterResult head(Node node, int depth);
049
050    /**
051     * Callback for when a node is last visited, after all of its descendants have been visited.
052     * <p>This method has a default implementation to return {@link FilterResult#CONTINUE}.</p>
053     * @param node the node being visited.
054     * @param depth the depth of the node, relative to the root node. E.g., the root node has depth 0, and a child node of that will have depth 1.
055     * @return Traversal action
056     */
057    default FilterResult tail(Node node, int depth) {
058        return FilterResult.CONTINUE;
059    }
060
061    /**
062     Run a depth-first controlled traverse of the root and all of its descendants.
063     @param root the initial node point to traverse.
064     @since 1.21.1
065     */
066    default void traverse(Node root) {
067        NodeTraversor.filter(this, root);
068    }
069}