1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xerces" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, International
  53. * Business Machines, Inc., http://www.apache.org. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package com.sun.org.apache.xerces.internal.dom;
  58. import org.w3c.dom.DOMException;
  59. import org.w3c.dom.Node;
  60. import org.w3c.dom.traversal.NodeFilter;
  61. import org.w3c.dom.traversal.TreeWalker;
  62. /** This class implements the TreeWalker interface. */
  63. /**
  64. * @version $Id: TreeWalkerImpl.java,v 1.8 2003/07/29 18:29:40 elena Exp $
  65. */
  66. public class TreeWalkerImpl implements TreeWalker {
  67. //
  68. // Data
  69. //
  70. /** When TRUE, the children of entites references are returned in the iterator. */
  71. private boolean fEntityReferenceExpansion = false;
  72. /** The whatToShow mask. */
  73. int fWhatToShow = NodeFilter.SHOW_ALL;
  74. /** The NodeFilter reference. */
  75. NodeFilter fNodeFilter;
  76. /** The current Node. */
  77. Node fCurrentNode;
  78. /** The root Node. */
  79. Node fRoot;
  80. //
  81. // Implementation Note: No state is kept except the data above
  82. // (fWhatToShow, fNodeFilter, fCurrentNode, fRoot) such that
  83. // setters could be created for these data values and the
  84. // implementation will still work.
  85. //
  86. // Constructor
  87. //
  88. /** Public constructor */
  89. public TreeWalkerImpl(Node root,
  90. int whatToShow,
  91. NodeFilter nodeFilter,
  92. boolean entityReferenceExpansion) {
  93. fCurrentNode = root;
  94. fRoot = root;
  95. fWhatToShow = whatToShow;
  96. fNodeFilter = nodeFilter;
  97. fEntityReferenceExpansion = entityReferenceExpansion;
  98. }
  99. public Node getRoot() {
  100. return fRoot;
  101. }
  102. /** Return the whatToShow value */
  103. public int getWhatToShow() {
  104. return fWhatToShow;
  105. }
  106. public void setWhatShow(int whatToShow){
  107. fWhatToShow = whatToShow;
  108. }
  109. /** Return the NodeFilter */
  110. public NodeFilter getFilter() {
  111. return fNodeFilter;
  112. }
  113. /** Return whether children entity references are included in the iterator. */
  114. public boolean getExpandEntityReferences() {
  115. return fEntityReferenceExpansion;
  116. }
  117. /** Return the current Node. */
  118. public Node getCurrentNode() {
  119. return fCurrentNode;
  120. }
  121. /** Return the current Node. */
  122. public void setCurrentNode(Node node) {
  123. if (node == null) {
  124. String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
  125. throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
  126. }
  127. fCurrentNode = node;
  128. }
  129. /** Return the parent Node from the current node,
  130. * after applying filter, whatToshow.
  131. * If result is not null, set the current Node.
  132. */
  133. public Node parentNode() {
  134. if (fCurrentNode == null) return null;
  135. Node node = getParentNode(fCurrentNode);
  136. if (node !=null) {
  137. fCurrentNode = node;
  138. }
  139. return node;
  140. }
  141. /** Return the first child Node from the current node,
  142. * after applying filter, whatToshow.
  143. * If result is not null, set the current Node.
  144. */
  145. public Node firstChild() {
  146. if (fCurrentNode == null) return null;
  147. Node node = getFirstChild(fCurrentNode);
  148. if (node !=null) {
  149. fCurrentNode = node;
  150. }
  151. return node;
  152. }
  153. /** Return the last child Node from the current node,
  154. * after applying filter, whatToshow.
  155. * If result is not null, set the current Node.
  156. */
  157. public Node lastChild() {
  158. if (fCurrentNode == null) return null;
  159. Node node = getLastChild(fCurrentNode);
  160. if (node !=null) {
  161. fCurrentNode = node;
  162. }
  163. return node;
  164. }
  165. /** Return the previous sibling Node from the current node,
  166. * after applying filter, whatToshow.
  167. * If result is not null, set the current Node.
  168. */
  169. public Node previousSibling() {
  170. if (fCurrentNode == null) return null;
  171. Node node = getPreviousSibling(fCurrentNode);
  172. if (node !=null) {
  173. fCurrentNode = node;
  174. }
  175. return node;
  176. }
  177. /** Return the next sibling Node from the current node,
  178. * after applying filter, whatToshow.
  179. * If result is not null, set the current Node.
  180. */
  181. public Node nextSibling(){
  182. if (fCurrentNode == null) return null;
  183. Node node = getNextSibling(fCurrentNode);
  184. if (node !=null) {
  185. fCurrentNode = node;
  186. }
  187. return node;
  188. }
  189. /** Return the previous Node from the current node,
  190. * after applying filter, whatToshow.
  191. * If result is not null, set the current Node.
  192. */
  193. public Node previousNode() {
  194. Node result;
  195. if (fCurrentNode == null) return null;
  196. // get sibling
  197. result = getPreviousSibling(fCurrentNode);
  198. if (result == null) {
  199. result = getParentNode(fCurrentNode);
  200. if (result != null) {
  201. fCurrentNode = result;
  202. return fCurrentNode;
  203. }
  204. return null;
  205. }
  206. // get the lastChild of result.
  207. Node lastChild = getLastChild(result);
  208. Node prev = lastChild ;
  209. while (lastChild != null) {
  210. prev = lastChild ;
  211. lastChild = getLastChild(prev) ;
  212. }
  213. lastChild = prev ;
  214. // if there is a lastChild which passes filters return it.
  215. if (lastChild != null) {
  216. fCurrentNode = lastChild;
  217. return fCurrentNode;
  218. }
  219. // otherwise return the previous sibling.
  220. if (result != null) {
  221. fCurrentNode = result;
  222. return fCurrentNode;
  223. }
  224. // otherwise return null.
  225. return null;
  226. }
  227. /** Return the next Node from the current node,
  228. * after applying filter, whatToshow.
  229. * If result is not null, set the current Node.
  230. */
  231. public Node nextNode() {
  232. if (fCurrentNode == null) return null;
  233. Node result = getFirstChild(fCurrentNode);
  234. if (result != null) {
  235. fCurrentNode = result;
  236. return result;
  237. }
  238. result = getNextSibling(fCurrentNode);
  239. if (result != null) {
  240. fCurrentNode = result;
  241. return result;
  242. }
  243. // return parent's 1st sibling.
  244. Node parent = getParentNode(fCurrentNode);
  245. while (parent != null) {
  246. result = getNextSibling(parent);
  247. if (result != null) {
  248. fCurrentNode = result;
  249. return result;
  250. } else {
  251. parent = getParentNode(parent);
  252. }
  253. }
  254. // end , return null
  255. return null;
  256. }
  257. /** Internal function.
  258. * Return the parent Node, from the input node
  259. * after applying filter, whatToshow.
  260. * The current node is not consulted or set.
  261. */
  262. Node getParentNode(Node node) {
  263. if (node == null || node == fRoot) return null;
  264. Node newNode = node.getParentNode();
  265. if (newNode == null) return null;
  266. int accept = acceptNode(newNode);
  267. if (accept == NodeFilter.FILTER_ACCEPT)
  268. return newNode;
  269. else
  270. //if (accept == NodeFilter.SKIP_NODE) // and REJECT too.
  271. {
  272. return getParentNode(newNode);
  273. }
  274. }
  275. /** Internal function.
  276. * Return the nextSibling Node, from the input node
  277. * after applying filter, whatToshow.
  278. * The current node is not consulted or set.
  279. */
  280. Node getNextSibling(Node node) {
  281. return getNextSibling(node, fRoot);
  282. }
  283. /** Internal function.
  284. * Return the nextSibling Node, from the input node
  285. * after applying filter, whatToshow.
  286. * NEVER TRAVERSES ABOVE THE SPECIFIED ROOT NODE.
  287. * The current node is not consulted or set.
  288. */
  289. Node getNextSibling(Node node, Node root) {
  290. if (node == null || node == root) return null;
  291. Node newNode = node.getNextSibling();
  292. if (newNode == null) {
  293. newNode = node.getParentNode();
  294. if (newNode == null || newNode == root) return null;
  295. int parentAccept = acceptNode(newNode);
  296. if (parentAccept==NodeFilter.FILTER_SKIP) {
  297. return getNextSibling(newNode, root);
  298. }
  299. return null;
  300. }
  301. int accept = acceptNode(newNode);
  302. if (accept == NodeFilter.FILTER_ACCEPT)
  303. return newNode;
  304. else
  305. if (accept == NodeFilter.FILTER_SKIP) {
  306. Node fChild = getFirstChild(newNode);
  307. if (fChild == null) {
  308. return getNextSibling(newNode, root);
  309. }
  310. return fChild;
  311. }
  312. else
  313. //if (accept == NodeFilter.REJECT_NODE)
  314. {
  315. return getNextSibling(newNode, root);
  316. }
  317. } // getNextSibling(Node node) {
  318. /** Internal function.
  319. * Return the previous sibling Node, from the input node
  320. * after applying filter, whatToshow.
  321. * The current node is not consulted or set.
  322. */
  323. Node getPreviousSibling(Node node) {
  324. return getPreviousSibling(node, fRoot);
  325. }
  326. /** Internal function.
  327. * Return the previousSibling Node, from the input node
  328. * after applying filter, whatToshow.
  329. * NEVER TRAVERSES ABOVE THE SPECIFIED ROOT NODE.
  330. * The current node is not consulted or set.
  331. */
  332. Node getPreviousSibling(Node node, Node root) {
  333. if (node == null || node == root) return null;
  334. Node newNode = node.getPreviousSibling();
  335. if (newNode == null) {
  336. newNode = node.getParentNode();
  337. if (newNode == null || newNode == root) return null;
  338. int parentAccept = acceptNode(newNode);
  339. if (parentAccept==NodeFilter.FILTER_SKIP) {
  340. return getPreviousSibling(newNode, root);
  341. }
  342. return null;
  343. }
  344. int accept = acceptNode(newNode);
  345. if (accept == NodeFilter.FILTER_ACCEPT)
  346. return newNode;
  347. else
  348. if (accept == NodeFilter.FILTER_SKIP) {
  349. Node fChild = getLastChild(newNode);
  350. if (fChild == null) {
  351. return getPreviousSibling(newNode, root);
  352. }
  353. return fChild;
  354. }
  355. else
  356. //if (accept == NodeFilter.REJECT_NODE)
  357. {
  358. return getPreviousSibling(newNode, root);
  359. }
  360. } // getPreviousSibling(Node node) {
  361. /** Internal function.
  362. * Return the first child Node, from the input node
  363. * after applying filter, whatToshow.
  364. * The current node is not consulted or set.
  365. */
  366. Node getFirstChild(Node node) {
  367. if (node == null) return null;
  368. if ( !fEntityReferenceExpansion
  369. && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
  370. return null;
  371. Node newNode = node.getFirstChild();
  372. if (newNode == null) return null;
  373. int accept = acceptNode(newNode);
  374. if (accept == NodeFilter.FILTER_ACCEPT)
  375. return newNode;
  376. else
  377. if (accept == NodeFilter.FILTER_SKIP
  378. && newNode.hasChildNodes())
  379. {
  380. Node fChild = getFirstChild(newNode);
  381. if (fChild == null) {
  382. return getNextSibling(newNode, node);
  383. }
  384. return fChild;
  385. }
  386. else
  387. //if (accept == NodeFilter.REJECT_NODE)
  388. {
  389. return getNextSibling(newNode, node);
  390. }
  391. }
  392. /** Internal function.
  393. * Return the last child Node, from the input node
  394. * after applying filter, whatToshow.
  395. * The current node is not consulted or set.
  396. */
  397. Node getLastChild(Node node) {
  398. if (node == null) return null;
  399. if ( !fEntityReferenceExpansion
  400. && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
  401. return null;
  402. Node newNode = node.getLastChild();
  403. if (newNode == null) return null;
  404. int accept = acceptNode(newNode);
  405. if (accept == NodeFilter.FILTER_ACCEPT)
  406. return newNode;
  407. else
  408. if (accept == NodeFilter.FILTER_SKIP
  409. && newNode.hasChildNodes())
  410. {
  411. Node lChild = getLastChild(newNode);
  412. if (lChild == null) {
  413. return getPreviousSibling(newNode, node);
  414. }
  415. return lChild;
  416. }
  417. else
  418. //if (accept == NodeFilter.REJECT_NODE)
  419. {
  420. return getPreviousSibling(newNode, node);
  421. }
  422. }
  423. /** Internal function.
  424. * The node whatToShow and the filter are combined into one result. */
  425. short acceptNode(Node node) {
  426. /***
  427. 7.1.2.4. Filters and whatToShow flags
  428. Iterator and TreeWalker apply whatToShow flags before applying Filters. If a node is rejected by the
  429. active whatToShow flags, a Filter will not be called to evaluate that node. When a node is rejected by
  430. the active whatToShow flags, children of that node will still be considered, and Filters may be called to
  431. evaluate them.
  432. ***/
  433. if (fNodeFilter == null) {
  434. if ( ( fWhatToShow & (1 << node.getNodeType()-1)) != 0) {
  435. return NodeFilter.FILTER_ACCEPT;
  436. } else {
  437. return NodeFilter.FILTER_SKIP;
  438. }
  439. } else {
  440. if ((fWhatToShow & (1 << node.getNodeType()-1)) != 0 ) {
  441. return fNodeFilter.acceptNode(node);
  442. } else {
  443. // What to show has failed. See above excerpt from spec.
  444. // Equivalent to FILTER_SKIP.
  445. return NodeFilter.FILTER_SKIP;
  446. }
  447. }
  448. }
  449. }