286N/A/*
286N/A * reserved comment block
286N/A * DO NOT REMOVE OR ALTER!
286N/A */
286N/A/*
286N/A * Copyright 1999-2004 The Apache Software Foundation.
286N/A *
286N/A * Licensed under the Apache License, Version 2.0 (the "License");
286N/A * you may not use this file except in compliance with the License.
286N/A * You may obtain a copy of the License at
286N/A *
286N/A * http://www.apache.org/licenses/LICENSE-2.0
286N/A *
286N/A * Unless required by applicable law or agreed to in writing, software
286N/A * distributed under the License is distributed on an "AS IS" BASIS,
286N/A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
286N/A * See the License for the specific language governing permissions and
286N/A * limitations under the License.
286N/A */
286N/A/*
286N/A * $Id: ReverseAxesWalker.java,v 1.2.4.1 2005/09/14 19:45:21 jeffsuttor Exp $
286N/A */
286N/Apackage com.sun.org.apache.xpath.internal.axes;
286N/A
286N/Aimport com.sun.org.apache.xml.internal.dtm.DTM;
286N/Aimport com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
286N/Aimport com.sun.org.apache.xpath.internal.XPathContext;
286N/A
286N/A/**
286N/A * Walker for a reverse axes.
286N/A * @see <a href="http://www.w3.org/TR/xpath#predicates">XPath 2.4 Predicates</a>
286N/A */
286N/Apublic class ReverseAxesWalker extends AxesWalker
286N/A{
286N/A static final long serialVersionUID = 2847007647832768941L;
286N/A
286N/A /**
286N/A * Construct an AxesWalker using a LocPathIterator.
286N/A *
286N/A * @param locPathIterator The location path iterator that 'owns' this walker.
286N/A */
286N/A ReverseAxesWalker(LocPathIterator locPathIterator, int axis)
286N/A {
286N/A super(locPathIterator, axis);
286N/A }
286N/A
286N/A /**
286N/A * Set the root node of the TreeWalker.
286N/A * (Not part of the DOM2 TreeWalker interface).
286N/A *
286N/A * @param root The context node of this step.
286N/A */
286N/A public void setRoot(int root)
286N/A {
286N/A super.setRoot(root);
286N/A m_iterator = getDTM(root).getAxisIterator(m_axis);
286N/A m_iterator.setStartNode(root);
286N/A }
286N/A
286N/A /**
286N/A * Detaches the walker from the set which it iterated over, releasing
286N/A * any computational resources and placing the iterator in the INVALID
286N/A * state.
286N/A */
286N/A public void detach()
286N/A {
286N/A m_iterator = null;
286N/A super.detach();
286N/A }
286N/A
286N/A /**
286N/A * Get the next node in document order on the axes.
286N/A *
286N/A * @return the next node in document order on the axes, or null.
286N/A */
286N/A protected int getNextNode()
286N/A {
286N/A if (m_foundLast)
286N/A return DTM.NULL;
286N/A
286N/A int next = m_iterator.next();
286N/A
286N/A if (m_isFresh)
286N/A m_isFresh = false;
286N/A
286N/A if (DTM.NULL == next)
286N/A this.m_foundLast = true;
286N/A
286N/A return next;
286N/A }
286N/A
286N/A
286N/A /**
286N/A * Tells if this is a reverse axes. Overrides AxesWalker#isReverseAxes.
286N/A *
286N/A * @return true for this class.
286N/A */
286N/A public boolean isReverseAxes()
286N/A {
286N/A return true;
286N/A }
286N/A
286N/A// /**
286N/A// * Set the root node of the TreeWalker.
286N/A// *
286N/A// * @param root The context node of this step.
286N/A// */
286N/A// public void setRoot(int root)
286N/A// {
286N/A// super.setRoot(root);
286N/A// }
286N/A
286N/A /**
286N/A * Get the current sub-context position. In order to do the
286N/A * reverse axes count, for the moment this re-searches the axes
286N/A * up to the predicate. An optimization on this is to cache
286N/A * the nodes searched, but, for the moment, this case is probably
286N/A * rare enough that the added complexity isn't worth it.
286N/A *
286N/A * @param predicateIndex The predicate index of the proximity position.
286N/A *
286N/A * @return The pridicate index, or -1.
286N/A */
286N/A protected int getProximityPosition(int predicateIndex)
286N/A {
286N/A // A negative predicate index seems to occur with
286N/A // (preceding-sibling::*|following-sibling::*)/ancestor::*[position()]/*[position()]
286N/A // -sb
286N/A if(predicateIndex < 0)
286N/A return -1;
286N/A
286N/A int count = m_proximityPositions[predicateIndex];
286N/A
286N/A if (count <= 0)
286N/A {
286N/A AxesWalker savedWalker = wi().getLastUsedWalker();
286N/A
286N/A try
286N/A {
286N/A ReverseAxesWalker clone = (ReverseAxesWalker) this.clone();
286N/A
286N/A clone.setRoot(this.getRoot());
286N/A
286N/A clone.setPredicateCount(predicateIndex);
286N/A
286N/A clone.setPrevWalker(null);
286N/A clone.setNextWalker(null);
286N/A wi().setLastUsedWalker(clone);
286N/A
286N/A // Count 'em all
286N/A count++;
286N/A int next;
286N/A
286N/A while (DTM.NULL != (next = clone.nextNode()))
286N/A {
286N/A count++;
286N/A }
286N/A
286N/A m_proximityPositions[predicateIndex] = count;
286N/A }
286N/A catch (CloneNotSupportedException cnse)
286N/A {
286N/A
286N/A // can't happen
286N/A }
286N/A finally
286N/A {
286N/A wi().setLastUsedWalker(savedWalker);
286N/A }
286N/A }
286N/A
286N/A return count;
286N/A }
286N/A
286N/A /**
286N/A * Count backwards one proximity position.
286N/A *
286N/A * @param i The predicate index.
286N/A */
286N/A protected void countProximityPosition(int i)
286N/A {
286N/A if (i < m_proximityPositions.length)
286N/A m_proximityPositions[i]--;
286N/A }
286N/A
286N/A /**
286N/A * Get the number of nodes in this node list. The function is probably ill
286N/A * named?
286N/A *
286N/A *
286N/A * @param xctxt The XPath runtime context.
286N/A *
286N/A * @return the number of nodes in this node list.
286N/A */
286N/A public int getLastPos(XPathContext xctxt)
286N/A {
286N/A
286N/A int count = 0;
286N/A AxesWalker savedWalker = wi().getLastUsedWalker();
286N/A
286N/A try
286N/A {
286N/A ReverseAxesWalker clone = (ReverseAxesWalker) this.clone();
286N/A
286N/A clone.setRoot(this.getRoot());
286N/A
286N/A clone.setPredicateCount(this.getPredicateCount() - 1);
286N/A
286N/A clone.setPrevWalker(null);
286N/A clone.setNextWalker(null);
286N/A wi().setLastUsedWalker(clone);
286N/A
286N/A // Count 'em all
286N/A // count = 1;
286N/A int next;
286N/A
286N/A while (DTM.NULL != (next = clone.nextNode()))
286N/A {
286N/A count++;
286N/A }
286N/A }
286N/A catch (CloneNotSupportedException cnse)
286N/A {
286N/A
286N/A // can't happen
286N/A }
286N/A finally
286N/A {
286N/A wi().setLastUsedWalker(savedWalker);
286N/A }
286N/A
286N/A return count;
286N/A }
286N/A
286N/A /**
286N/A * Returns true if all the nodes in the iteration well be returned in document
286N/A * order.
286N/A * Warning: This can only be called after setRoot has been called!
286N/A *
286N/A * @return false.
286N/A */
286N/A public boolean isDocOrdered()
286N/A {
286N/A return false; // I think.
286N/A }
286N/A
286N/A /** The DTM inner traversal class, that corresponds to the super axis. */
286N/A protected DTMAxisIterator m_iterator;
286N/A}