1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.html;
16
17 import java.io.Serializable;
18
19 import org.w3c.dom.Node;
20 import org.w3c.dom.traversal.NodeFilter;
21 import org.w3c.dom.traversal.NodeIterator;
22
23
24
25
26
27
28
29 public class DomNodeIterator implements NodeIterator, Serializable {
30
31 private final DomNode root_;
32 private final int whatToShow_;
33 private final NodeFilter filter_;
34 private DomNode referenceNode_;
35 private final boolean expandEntityReferences_;
36 private boolean pointerBeforeReferenceNode_;
37
38
39
40
41
42
43
44
45
46
47
48 public DomNodeIterator(final DomNode root, final int whatToShow, final NodeFilter filter,
49 final boolean expandEntityReferences) {
50 root_ = root;
51 referenceNode_ = root;
52 whatToShow_ = whatToShow;
53 filter_ = filter;
54 expandEntityReferences_ = expandEntityReferences;
55 pointerBeforeReferenceNode_ = true;
56 }
57
58
59
60
61 @Override
62 public DomNode getRoot() {
63 return root_;
64 }
65
66
67
68
69 @Override
70 public int getWhatToShow() {
71 return whatToShow_;
72 }
73
74
75
76
77 @Override
78 public boolean getExpandEntityReferences() {
79 return expandEntityReferences_;
80 }
81
82
83
84
85 @Override
86 public NodeFilter getFilter() {
87 return filter_;
88 }
89
90
91
92
93
94 public boolean isPointerBeforeReferenceNode() {
95 return pointerBeforeReferenceNode_;
96 }
97
98
99
100
101 @Override
102 public void detach() {
103
104 }
105
106
107
108
109 @Override
110 public DomNode nextNode() {
111 return traverse(true);
112 }
113
114
115
116
117 @Override
118 public DomNode previousNode() {
119 return traverse(false);
120 }
121
122 private DomNode traverse(final boolean next) {
123 DomNode node = referenceNode_;
124 boolean beforeNode = pointerBeforeReferenceNode_;
125
126 do {
127 if (next) {
128 if (beforeNode) {
129 beforeNode = false;
130 }
131 else if (node != null) {
132 final DomNode firstChild = node.getFirstChild();
133 if (firstChild != null) {
134 node = firstChild;
135 }
136 else {
137 final DomNode nextSibling = node.getNextSibling();
138 node = nextSibling == null ? getFirstUncleNode(node) : nextSibling;
139 }
140 }
141 }
142 else {
143 if (beforeNode) {
144 DomNode follow = node == null ? null : node.getPreviousSibling();
145 while (follow != null && follow.hasChildNodes()) {
146 follow = follow.getLastChild();
147 }
148 node = follow;
149 }
150 else {
151 beforeNode = true;
152 }
153 }
154 }
155 while (node != null && (!isNodeVisible(node) || !isAccepted(node)));
156
157 referenceNode_ = node;
158 pointerBeforeReferenceNode_ = beforeNode;
159 return node;
160 }
161
162 private boolean isNodeVisible(final Node node) {
163 return (whatToShow_ & HtmlDomTreeWalker.getFlagForNode(node)) != 0;
164 }
165
166 private boolean isAccepted(final Node node) {
167 if (filter_ == null) {
168 return true;
169 }
170 return filter_.acceptNode(node) == NodeFilter.FILTER_ACCEPT;
171 }
172
173
174
175
176
177 private DomNode getFirstUncleNode(final DomNode startNode) {
178 DomNode curr = startNode;
179 while (curr != null && curr != root_) {
180 final DomNode parent = curr.getParentNode();
181 if (parent == null || parent == root_) {
182 return null;
183 }
184 final DomNode uncle = parent.getNextSibling();
185 if (uncle != null) {
186 return uncle;
187 }
188 curr = parent;
189 }
190 return null;
191 }
192 }