1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 1999-2002,2004 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xerces.internal.dom;
  22 
  23 import org.w3c.dom.DOMException;
  24 import org.w3c.dom.Node;
  25 import org.w3c.dom.traversal.NodeFilter;
  26 import org.w3c.dom.traversal.TreeWalker;
  27 
  28 /** This class implements the TreeWalker interface.
  29  *
  30  * @xerces.internal
  31  *
  32  */
  33 
  34 public class TreeWalkerImpl implements TreeWalker {
  35 
  36     //
  37     // Data
  38     //
  39 
  40     /** When TRUE, the children of entites references are returned in the iterator. */
  41     private boolean fEntityReferenceExpansion = false;
  42     /** The whatToShow mask. */
  43     int fWhatToShow = NodeFilter.SHOW_ALL;
  44     /** The NodeFilter reference. */
  45     NodeFilter fNodeFilter;
  46     /** The current Node. */
  47     Node fCurrentNode;
  48     /** The root Node. */
  49     Node fRoot;
  50 
  51     //
  52     // Implementation Note: No state is kept except the data above
  53     // (fWhatToShow, fNodeFilter, fCurrentNode, fRoot) such that
  54     // setters could be created for these data values and the
  55     // implementation will still work.
  56 
  57 
  58     //
  59     // Constructor
  60     //
  61 
  62     /** Public constructor */
  63     public TreeWalkerImpl(Node root,
  64                           int whatToShow,
  65                           NodeFilter nodeFilter,
  66                           boolean entityReferenceExpansion) {
  67         fCurrentNode = root;
  68         fRoot = root;
  69         fWhatToShow = whatToShow;
  70         fNodeFilter = nodeFilter;
  71         fEntityReferenceExpansion = entityReferenceExpansion;
  72     }
  73 
  74     public Node getRoot() {
  75         return fRoot;
  76     }
  77 
  78     /** Return the whatToShow value */
  79     public int                getWhatToShow() {
  80         return fWhatToShow;
  81     }
  82 
  83     public void setWhatShow(int whatToShow){
  84         fWhatToShow = whatToShow;
  85     }
  86     /** Return the NodeFilter */
  87     public NodeFilter         getFilter() {
  88         return fNodeFilter;
  89     }
  90 
  91     /** Return whether children entity references are included in the iterator. */
  92     public boolean            getExpandEntityReferences() {
  93         return fEntityReferenceExpansion;
  94     }
  95 
  96     /** Return the current Node. */
  97     public Node               getCurrentNode() {
  98         return fCurrentNode;
  99     }
 100     /** Return the current Node. */
 101     public void               setCurrentNode(Node node) {
 102         if (node == null) {
 103             String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
 104               throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 105         }
 106 
 107         fCurrentNode = node;
 108     }
 109 
 110     /** Return the parent Node from the current node,
 111      *  after applying filter, whatToshow.
 112      *  If result is not null, set the current Node.
 113      */
 114     public Node               parentNode() {
 115 
 116         if (fCurrentNode == null) return null;
 117 
 118         Node node = getParentNode(fCurrentNode);
 119         if (node !=null) {
 120             fCurrentNode = node;
 121         }
 122         return node;
 123 
 124     }
 125 
 126     /** Return the first child Node from the current node,
 127      *  after applying filter, whatToshow.
 128      *  If result is not null, set the current Node.
 129      */
 130     public Node               firstChild() {
 131 
 132         if (fCurrentNode == null) return null;
 133 
 134         Node node = getFirstChild(fCurrentNode);
 135         if (node !=null) {
 136             fCurrentNode = node;
 137         }
 138         return node;
 139     }
 140     /** Return the last child Node from the current node,
 141      *  after applying filter, whatToshow.
 142      *  If result is not null, set the current Node.
 143      */
 144     public Node               lastChild() {
 145 
 146         if (fCurrentNode == null) return null;
 147 
 148         Node node = getLastChild(fCurrentNode);
 149         if (node !=null) {
 150             fCurrentNode = node;
 151         }
 152         return node;
 153     }
 154 
 155     /** Return the previous sibling Node from the current node,
 156      *  after applying filter, whatToshow.
 157      *  If result is not null, set the current Node.
 158      */
 159     public Node               previousSibling() {
 160 
 161         if (fCurrentNode == null) return null;
 162 
 163         Node node = getPreviousSibling(fCurrentNode);
 164         if (node !=null) {
 165             fCurrentNode = node;
 166         }
 167         return node;
 168     }
 169 
 170     /** Return the next sibling Node from the current node,
 171      *  after applying filter, whatToshow.
 172      *  If result is not null, set the current Node.
 173      */
 174     public Node               nextSibling(){
 175         if (fCurrentNode == null) return null;
 176 
 177         Node node = getNextSibling(fCurrentNode);
 178         if (node !=null) {
 179             fCurrentNode = node;
 180         }
 181         return node;
 182     }
 183 
 184     /** Return the previous Node from the current node,
 185      *  after applying filter, whatToshow.
 186      *  If result is not null, set the current Node.
 187      */
 188     public Node               previousNode() {
 189         Node result;
 190 
 191         if (fCurrentNode == null) return null;
 192 
 193         // get sibling
 194         result = getPreviousSibling(fCurrentNode);
 195         if (result == null) {
 196             result = getParentNode(fCurrentNode);
 197             if (result != null) {
 198                 fCurrentNode = result;
 199                 return fCurrentNode;
 200             }
 201             return null;
 202         }
 203 
 204         // get the lastChild of result.
 205         Node lastChild  = getLastChild(result);
 206 
 207         Node prev = lastChild ;
 208         while (lastChild != null) {
 209           prev = lastChild ;
 210           lastChild = getLastChild(prev) ;
 211         }
 212 
 213         lastChild = prev ;
 214 
 215         // if there is a lastChild which passes filters return it.
 216         if (lastChild != null) {
 217             fCurrentNode = lastChild;
 218             return fCurrentNode;
 219         }
 220 
 221         // otherwise return the previous sibling.
 222         if (result != null) {
 223             fCurrentNode = result;
 224             return fCurrentNode;
 225         }
 226 
 227         // otherwise return null.
 228         return null;
 229     }
 230 
 231     /** Return the next Node from the current node,
 232      *  after applying filter, whatToshow.
 233      *  If result is not null, set the current Node.
 234      */
 235     public Node               nextNode() {
 236 
 237         if (fCurrentNode == null) return null;
 238 
 239         Node result = getFirstChild(fCurrentNode);
 240 
 241         if (result != null) {
 242             fCurrentNode = result;
 243             return result;
 244         }
 245 
 246         result = getNextSibling(fCurrentNode);
 247 
 248         if (result != null) {
 249             fCurrentNode = result;
 250             return result;
 251         }
 252 
 253         // return parent's 1st sibling.
 254         Node parent = getParentNode(fCurrentNode);
 255         while (parent != null) {
 256             result = getNextSibling(parent);
 257             if (result != null) {
 258                 fCurrentNode = result;
 259                 return result;
 260             } else {
 261                 parent = getParentNode(parent);
 262             }
 263         }
 264 
 265         // end , return null
 266         return null;
 267     }
 268 
 269     /** Internal function.
 270      *  Return the parent Node, from the input node
 271      *  after applying filter, whatToshow.
 272      *  The current node is not consulted or set.
 273      */
 274     Node getParentNode(Node node) {
 275 
 276         if (node == null || node == fRoot) return null;
 277 
 278         Node newNode = node.getParentNode();
 279         if (newNode == null)  return null;
 280 
 281         int accept = acceptNode(newNode);
 282 
 283         if (accept == NodeFilter.FILTER_ACCEPT)
 284             return newNode;
 285         else
 286         //if (accept == NodeFilter.SKIP_NODE) // and REJECT too.
 287         {
 288             return getParentNode(newNode);
 289         }
 290 
 291 
 292     }
 293 
 294     /** Internal function.
 295      *  Return the nextSibling Node, from the input node
 296      *  after applying filter, whatToshow.
 297      *  The current node is not consulted or set.
 298      */
 299     Node getNextSibling(Node node) {
 300                 return getNextSibling(node, fRoot);
 301         }
 302 
 303     /** Internal function.
 304      *  Return the nextSibling Node, from the input node
 305      *  after applying filter, whatToshow.
 306      *  NEVER TRAVERSES ABOVE THE SPECIFIED ROOT NODE.
 307      *  The current node is not consulted or set.
 308      */
 309     Node getNextSibling(Node node, Node root) {
 310 
 311         if (node == null || node == root) return null;
 312 
 313         Node newNode = node.getNextSibling();
 314         if (newNode == null) {
 315 
 316             newNode = node.getParentNode();
 317 
 318             if (newNode == null || newNode == root)  return null;
 319 
 320             int parentAccept = acceptNode(newNode);
 321 
 322             if (parentAccept==NodeFilter.FILTER_SKIP) {
 323                 return getNextSibling(newNode, root);
 324             }
 325 
 326             return null;
 327         }
 328 
 329         int accept = acceptNode(newNode);
 330 
 331         if (accept == NodeFilter.FILTER_ACCEPT)
 332             return newNode;
 333         else
 334         if (accept == NodeFilter.FILTER_SKIP) {
 335             Node fChild = getFirstChild(newNode);
 336             if (fChild == null) {
 337                 return getNextSibling(newNode, root);
 338             }
 339             return fChild;
 340         }
 341         else
 342         //if (accept == NodeFilter.REJECT_NODE)
 343         {
 344             return getNextSibling(newNode, root);
 345         }
 346 
 347     } // getNextSibling(Node node) {
 348 
 349     /** Internal function.
 350      *  Return the previous sibling Node, from the input node
 351      *  after applying filter, whatToshow.
 352      *  The current node is not consulted or set.
 353      */
 354     Node getPreviousSibling(Node node) {
 355                 return getPreviousSibling(node, fRoot);
 356         }
 357 
 358     /** Internal function.
 359      *  Return the previousSibling Node, from the input node
 360      *  after applying filter, whatToshow.
 361          *  NEVER TRAVERSES ABOVE THE SPECIFIED ROOT NODE.
 362      *  The current node is not consulted or set.
 363      */
 364     Node getPreviousSibling(Node node, Node root) {
 365 
 366         if (node == null || node == root) return null;
 367 
 368         Node newNode = node.getPreviousSibling();
 369         if (newNode == null) {
 370 
 371             newNode = node.getParentNode();
 372             if (newNode == null || newNode == root)  return null;
 373 
 374             int parentAccept = acceptNode(newNode);
 375 
 376             if (parentAccept==NodeFilter.FILTER_SKIP) {
 377                 return getPreviousSibling(newNode, root);
 378             }
 379 
 380             return null;
 381         }
 382 
 383         int accept = acceptNode(newNode);
 384 
 385         if (accept == NodeFilter.FILTER_ACCEPT)
 386             return newNode;
 387         else
 388         if (accept == NodeFilter.FILTER_SKIP) {
 389             Node fChild =  getLastChild(newNode);
 390             if (fChild == null) {
 391                 return getPreviousSibling(newNode, root);
 392             }
 393             return fChild;
 394         }
 395         else
 396         //if (accept == NodeFilter.REJECT_NODE)
 397         {
 398             return getPreviousSibling(newNode, root);
 399         }
 400 
 401     } // getPreviousSibling(Node node) {
 402 
 403     /** Internal function.
 404      *  Return the first child Node, from the input node
 405      *  after applying filter, whatToshow.
 406      *  The current node is not consulted or set.
 407      */
 408     Node getFirstChild(Node node) {
 409         if (node == null) return null;
 410 
 411         if ( !fEntityReferenceExpansion
 412              && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
 413             return null;
 414         Node newNode = node.getFirstChild();
 415         if (newNode == null)  return null;
 416         int accept = acceptNode(newNode);
 417 
 418         if (accept == NodeFilter.FILTER_ACCEPT)
 419             return newNode;
 420         else
 421         if (accept == NodeFilter.FILTER_SKIP
 422             && newNode.hasChildNodes())
 423         {
 424             Node fChild = getFirstChild(newNode);
 425 
 426             if (fChild == null) {
 427                 return getNextSibling(newNode, node);
 428             }
 429             return fChild;
 430         }
 431         else
 432         //if (accept == NodeFilter.REJECT_NODE)
 433         {
 434             return getNextSibling(newNode, node);
 435         }
 436 
 437 
 438     }
 439 
 440     /** Internal function.
 441      *  Return the last child Node, from the input node
 442      *  after applying filter, whatToshow.
 443      *  The current node is not consulted or set.
 444      */
 445     Node getLastChild(Node node) {
 446 
 447         if (node == null) return null;
 448 
 449         if ( !fEntityReferenceExpansion
 450              && node.getNodeType() == Node.ENTITY_REFERENCE_NODE)
 451             return null;
 452 
 453         Node newNode = node.getLastChild();
 454         if (newNode == null)  return null;
 455 
 456         int accept = acceptNode(newNode);
 457 
 458         if (accept == NodeFilter.FILTER_ACCEPT)
 459             return newNode;
 460         else
 461         if (accept == NodeFilter.FILTER_SKIP
 462             && newNode.hasChildNodes())
 463         {
 464             Node lChild = getLastChild(newNode);
 465             if (lChild == null) {
 466                 return getPreviousSibling(newNode, node);
 467             }
 468             return lChild;
 469         }
 470         else
 471         //if (accept == NodeFilter.REJECT_NODE)
 472         {
 473             return getPreviousSibling(newNode, node);
 474         }
 475 
 476 
 477     }
 478 
 479     /** Internal function.
 480      *  The node whatToShow and the filter are combined into one result. */
 481     short acceptNode(Node node) {
 482         /***
 483          7.1.2.4. Filters and whatToShow flags
 484 
 485          Iterator and TreeWalker apply whatToShow flags before applying Filters. If a node is rejected by the
 486          active whatToShow flags, a Filter will not be called to evaluate that node. When a node is rejected by
 487          the active whatToShow flags, children of that node will still be considered, and Filters may be called to
 488          evaluate them.
 489          ***/
 490 
 491         if (fNodeFilter == null) {
 492             if ( ( fWhatToShow & (1 << node.getNodeType()-1)) != 0) {
 493                 return NodeFilter.FILTER_ACCEPT;
 494             } else {
 495                 return NodeFilter.FILTER_SKIP;
 496             }
 497         } else {
 498             if ((fWhatToShow & (1 << node.getNodeType()-1)) != 0 ) {
 499                 return fNodeFilter.acceptNode(node);
 500             } else {
 501                 // What to show has failed. See above excerpt from spec.
 502                 // Equivalent to FILTER_SKIP.
 503                 return NodeFilter.FILTER_SKIP;
 504             }
 505         }
 506     }
 507 }