/**
   * Get a cloned Iterator that is reset to the beginning of the query.
   *
   * @return A cloned NodeIterator set of the start of the query.
   * @throws CloneNotSupportedException
   */
  public DTMIterator cloneWithReset() throws CloneNotSupportedException {

    OneStepIterator clone = (OneStepIterator) super.cloneWithReset();
    clone.m_iterator = m_iterator;

    return clone;
  }
  /**
   * Get a cloned iterator.
   *
   * @return A new iterator that can be used without mutating this one.
   * @throws CloneNotSupportedException
   */
  public Object clone() throws CloneNotSupportedException {
    // Do not access the location path itterator during this operation!

    OneStepIterator clone = (OneStepIterator) super.clone();

    if (m_iterator != null) {
      clone.m_iterator = m_iterator.cloneIterator();
    }
    return clone;
  }
  /**
   * The number of nodes in the list. The range of valid child node indices is 0 to <code>length-1
   * </code> inclusive.
   *
   * @return The number of nodes in the list, always greater or equal to zero.
   */
  public int getLength() {
    if (!isReverseAxes()) return super.getLength();

    // Tell if this is being called from within a predicate.
    boolean isPredicateTest = (this == m_execContext.getSubContextList());

    // And get how many total predicates are part of this step.
    int predCount = getPredicateCount();

    // If we have already calculated the length, and the current predicate
    // is the first predicate, then return the length.  We don't cache
    // the anything but the length of the list to the first predicate.
    if (-1 != m_length && isPredicateTest && m_predicateIndex < 1) return m_length;

    int count = 0;

    XPathContext xctxt = getXPathContext();
    try {
      OneStepIterator clone = (OneStepIterator) this.cloneWithReset();

      int root = getRoot();
      xctxt.pushCurrentNode(root);
      clone.setRoot(root, xctxt);

      clone.m_predCount = m_predicateIndex;

      int next;

      while (DTM.NULL != (next = clone.nextNode())) {
        count++;
      }
    } catch (CloneNotSupportedException cnse) {
      // can't happen
    } finally {
      xctxt.popCurrentNode();
    }
    if (isPredicateTest && m_predicateIndex < 1) m_length = count;

    return count;
  }
  /**
   * Get the current sub-context position. In order to do the reverse axes count, for the moment
   * this re-searches the axes up to the predicate. An optimization on this is to cache the nodes
   * searched, but, for the moment, this case is probably rare enough that the added complexity
   * isn't worth it.
   *
   * @param predicateIndex The predicate index of the proximity position.
   * @return The pridicate index, or -1.
   */
  protected int getProximityPosition(int predicateIndex) {
    if (!isReverseAxes()) return super.getProximityPosition(predicateIndex);

    // A negative predicate index seems to occur with
    // (preceding-sibling::*|following-sibling::*)/ancestor::*[position()]/*[position()]
    // -sb
    if (predicateIndex < 0) return -1;

    if (m_proximityPositions[predicateIndex] <= 0) {
      XPathContext xctxt = getXPathContext();
      try {
        OneStepIterator clone = (OneStepIterator) this.clone();

        int root = getRoot();
        xctxt.pushCurrentNode(root);
        clone.setRoot(root, xctxt);

        // clone.setPredicateCount(predicateIndex);
        clone.m_predCount = predicateIndex;

        // Count 'em all
        int count = 1;
        int next;

        while (DTM.NULL != (next = clone.nextNode())) {
          count++;
        }

        m_proximityPositions[predicateIndex] += count;
      } catch (CloneNotSupportedException cnse) {

        // can't happen
      } finally {
        xctxt.popCurrentNode();
      }
    }

    return m_proximityPositions[predicateIndex];
  }