    1   /*
    2    * Copyright 1999-2004 The Apache Software Foundation
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.jxpath.ri.axes;
    17
    18  import org.apache.commons.jxpath.ri.EvalContext;
    19  import org.apache.commons.jxpath.ri.compiler.NodeTest;
    20  import org.apache.commons.jxpath.ri.model.NodePointer;
    21
    22  /***
    23   * EvalContext that walks the "ancestor::" and "ancestor-or-self::" axes.
    24   *
    25   * @author Dmitri Plotnikov
    26   * @version $Revision: 1.15 $ $Date: 2004/03/25 03:49:50 $
    27   */
    28  public class AncestorContext extends EvalContext {
    29      private NodeTest nodeTest;
    30      private boolean setStarted = false;
    31      private NodePointer currentNodePointer;
    32      private boolean includeSelf;
    33
    34      /***
    35       * @param parentContext represents the previous step on the path
    36       * @param  includeSelf differentiates between "ancestor::" and "ancestor-
    37       * or-self::" axes
    38       * @param nameTest is the name of the element(s) we are looking for
    39       */
    40      public AncestorContext(
    41          EvalContext parentContext,
    42          boolean includeSelf,
    43          NodeTest nodeTest)
    44      {
    45          super(parentContext);
    46          this.includeSelf = includeSelf;
    47          this.nodeTest = nodeTest;
    48      }
    49
    50      public NodePointer getCurrentNodePointer() {
    51          return currentNodePointer;
    52      }
    53
    54      public int getDocumentOrder() {
    55          return -1;
    56      }
    57
    58      public void reset() {
    59          super.reset();
    60          setStarted = false;
    61      }
    62
    63      public boolean setPosition(int position) {
    64          if (position < getCurrentPosition()) {
    65              reset();
    66          }
    67
    68          while (getCurrentPosition() < position) {
    69              if (!nextNode()) {
    70                  return false;
    71              }
    72          }
    73          return true;
    74      }
    75
    76      public boolean nextNode() {
    77          if (!setStarted) {
    78              setStarted = true;
    79              currentNodePointer = parentContext.getCurrentNodePointer();
    80              if (includeSelf) {
    81                  if (currentNodePointer.testNode(nodeTest)) {
    82                      position++;
    83                      return true;
    84                  }
    85              }
    86          }
    87
    88          while (true) {
    89              currentNodePointer = currentNodePointer.getImmediateParentPointer();
    90
    91              if (currentNodePointer == null) {
    92                  return false;
    93              }
    94
    95              if (currentNodePointer.testNode(nodeTest)) {
    96                  position++;
    97                  return true;
    98              }
    99          }
    100     }
    101 }