KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xpath > axes > ReverseAxesWalker


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 /*
17  * $Id: ReverseAxesWalker.java,v 1.14 2004/02/17 04:32:08 minchau Exp $
18  */

19 package org.apache.xpath.axes;
20
21 import org.apache.xml.dtm.DTM;
22 import org.apache.xml.dtm.DTMAxisIterator;
23 import org.apache.xpath.XPathContext;
24
25 /**
26  * Walker for a reverse axes.
27  * @see <a HREF="http://www.w3.org/TR/xpath#predicates">XPath 2.4 Predicates</a>
28  */

29 public class ReverseAxesWalker extends AxesWalker
30 {
31
32   /**
33    * Construct an AxesWalker using a LocPathIterator.
34    *
35    * @param locPathIterator The location path iterator that 'owns' this walker.
36    */

37   ReverseAxesWalker(LocPathIterator locPathIterator, int axis)
38   {
39     super(locPathIterator, axis);
40   }
41   
42   /**
43    * Set the root node of the TreeWalker.
44    * (Not part of the DOM2 TreeWalker interface).
45    *
46    * @param root The context node of this step.
47    */

48   public void setRoot(int root)
49   {
50     super.setRoot(root);
51     m_iterator = getDTM(root).getAxisIterator(m_axis);
52     m_iterator.setStartNode(root);
53   }
54
55   /**
56    * Detaches the walker from the set which it iterated over, releasing
57    * any computational resources and placing the iterator in the INVALID
58    * state.
59    */

60   public void detach()
61   {
62     m_iterator = null;
63     super.detach();
64   }
65   
66   /**
67    * Get the next node in document order on the axes.
68    *
69    * @return the next node in document order on the axes, or null.
70    */

71   protected int getNextNode()
72   {
73     if (m_foundLast)
74       return DTM.NULL;
75
76     int next = m_iterator.next();
77     
78     if (m_isFresh)
79       m_isFresh = false;
80
81     if (DTM.NULL == next)
82       this.m_foundLast = true;
83
84     return next;
85   }
86
87
88   /**
89    * Tells if this is a reverse axes. Overrides AxesWalker#isReverseAxes.
90    *
91    * @return true for this class.
92    */

93   public boolean isReverseAxes()
94   {
95     return true;
96   }
97
98 // /**
99
// * Set the root node of the TreeWalker.
100
// *
101
// * @param root The context node of this step.
102
// */
103
// public void setRoot(int root)
104
// {
105
// super.setRoot(root);
106
// }
107

108   /**
109    * Get the current sub-context position. In order to do the
110    * reverse axes count, for the moment this re-searches the axes
111    * up to the predicate. An optimization on this is to cache
112    * the nodes searched, but, for the moment, this case is probably
113    * rare enough that the added complexity isn't worth it.
114    *
115    * @param predicateIndex The predicate index of the proximity position.
116    *
117    * @return The pridicate index, or -1.
118    */

119   protected int getProximityPosition(int predicateIndex)
120   {
121     // A negative predicate index seems to occur with
122
// (preceding-sibling::*|following-sibling::*)/ancestor::*[position()]/*[position()]
123
// -sb
124
if(predicateIndex < 0)
125       return -1;
126       
127     int count = m_proximityPositions[predicateIndex];
128       
129     if (count <= 0)
130     {
131       AxesWalker savedWalker = wi().getLastUsedWalker();
132
133       try
134       {
135         ReverseAxesWalker clone = (ReverseAxesWalker) this.clone();
136
137         clone.setRoot(this.getRoot());
138
139         clone.setPredicateCount(predicateIndex);
140
141         clone.setPrevWalker(null);
142         clone.setNextWalker(null);
143         wi().setLastUsedWalker(clone);
144
145         // Count 'em all
146
count++;
147         int next;
148
149         while (DTM.NULL != (next = clone.nextNode()))
150         {
151           count++;
152         }
153
154         m_proximityPositions[predicateIndex] = count;
155       }
156       catch (CloneNotSupportedException JavaDoc cnse)
157       {
158
159         // can't happen
160
}
161       finally
162       {
163         wi().setLastUsedWalker(savedWalker);
164       }
165     }
166     
167     return count;
168   }
169
170   /**
171    * Count backwards one proximity position.
172    *
173    * @param i The predicate index.
174    */

175   protected void countProximityPosition(int i)
176   {
177     if (i < m_proximityPositions.length)
178       m_proximityPositions[i]--;
179   }
180
181   /**
182    * Get the number of nodes in this node list. The function is probably ill
183    * named?
184    *
185    *
186    * @param xctxt The XPath runtime context.
187    *
188    * @return the number of nodes in this node list.
189    */

190   public int getLastPos(XPathContext xctxt)
191   {
192
193     int count = 0;
194     AxesWalker savedWalker = wi().getLastUsedWalker();
195
196     try
197     {
198       ReverseAxesWalker clone = (ReverseAxesWalker) this.clone();
199
200       clone.setRoot(this.getRoot());
201
202       clone.setPredicateCount(this.getPredicateCount() - 1);
203
204       clone.setPrevWalker(null);
205       clone.setNextWalker(null);
206       wi().setLastUsedWalker(clone);
207
208       // Count 'em all
209
// count = 1;
210
int next;
211
212       while (DTM.NULL != (next = clone.nextNode()))
213       {
214         count++;
215       }
216     }
217     catch (CloneNotSupportedException JavaDoc cnse)
218     {
219
220       // can't happen
221
}
222     finally
223     {
224       wi().setLastUsedWalker(savedWalker);
225     }
226
227     return count;
228   }
229   
230   /**
231    * Returns true if all the nodes in the iteration well be returned in document
232    * order.
233    * Warning: This can only be called after setRoot has been called!
234    *
235    * @return false.
236    */

237   public boolean isDocOrdered()
238   {
239     return false; // I think.
240
}
241   
242   /** The DTM inner traversal class, that corresponds to the super axis. */
243   protected DTMAxisIterator m_iterator;
244 }
245
Popular Tags