/** * 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]; }