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}