BasicTestIterator.java revision 9f8118474e9513f7a5b7d2a05e4a0fb15d1a6569
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the  "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18/*
19 * $Id: BasicTestIterator.java 469314 2006-10-30 23:31:59Z minchau $
20 */
21package org.apache.xpath.axes;
22
23import org.apache.xml.dtm.DTM;
24import org.apache.xml.dtm.DTMFilter;
25import org.apache.xml.dtm.DTMIterator;
26import org.apache.xml.utils.PrefixResolver;
27import org.apache.xpath.compiler.Compiler;
28import org.apache.xpath.compiler.OpMap;
29
30/**
31 * Base for iterators that handle predicates.  Does the basic next
32 * node logic, so all the derived iterator has to do is get the
33 * next node.
34 */
35public abstract class BasicTestIterator extends LocPathIterator
36{
37    static final long serialVersionUID = 3505378079378096623L;
38  /**
39   * Create a LocPathIterator object.
40   *
41   * @param nscontext The namespace context for this iterator,
42   * should be OK if null.
43   */
44  protected BasicTestIterator()
45  {
46  }
47
48
49  /**
50   * Create a LocPathIterator object.
51   *
52   * @param nscontext The namespace context for this iterator,
53   * should be OK if null.
54   */
55  protected BasicTestIterator(PrefixResolver nscontext)
56  {
57
58    super(nscontext);
59  }
60
61  /**
62   * Create a LocPathIterator object, including creation
63   * of step walkers from the opcode list, and call back
64   * into the Compiler to create predicate expressions.
65   *
66   * @param compiler The Compiler which is creating
67   * this expression.
68   * @param opPos The position of this iterator in the
69   * opcode list from the compiler.
70   *
71   * @throws javax.xml.transform.TransformerException
72   */
73  protected BasicTestIterator(Compiler compiler, int opPos, int analysis)
74          throws javax.xml.transform.TransformerException
75  {
76    super(compiler, opPos, analysis, false);
77
78    int firstStepPos = OpMap.getFirstChildPos(opPos);
79    int whatToShow = compiler.getWhatToShow(firstStepPos);
80
81    if ((0 == (whatToShow
82               & (DTMFilter.SHOW_ATTRIBUTE
83               | DTMFilter.SHOW_NAMESPACE
84               | DTMFilter.SHOW_ELEMENT
85               | DTMFilter.SHOW_PROCESSING_INSTRUCTION)))
86               || (whatToShow == DTMFilter.SHOW_ALL))
87      initNodeTest(whatToShow);
88    else
89    {
90      initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
91                              compiler.getStepLocalName(firstStepPos));
92    }
93    initPredicateInfo(compiler, firstStepPos);
94  }
95
96  /**
97   * Create a LocPathIterator object, including creation
98   * of step walkers from the opcode list, and call back
99   * into the Compiler to create predicate expressions.
100   *
101   * @param compiler The Compiler which is creating
102   * this expression.
103   * @param opPos The position of this iterator in the
104   * opcode list from the compiler.
105   * @param shouldLoadWalkers True if walkers should be
106   * loaded, or false if this is a derived iterator and
107   * it doesn't wish to load child walkers.
108   *
109   * @throws javax.xml.transform.TransformerException
110   */
111  protected BasicTestIterator(
112          Compiler compiler, int opPos, int analysis, boolean shouldLoadWalkers)
113            throws javax.xml.transform.TransformerException
114  {
115    super(compiler, opPos, analysis, shouldLoadWalkers);
116  }
117
118
119  /**
120   * Get the next node via getNextXXX.  Bottlenecked for derived class override.
121   * @return The next node on the axis, or DTM.NULL.
122   */
123  protected abstract int getNextNode();
124
125  /**
126   *  Returns the next node in the set and advances the position of the
127   * iterator in the set. After a NodeIterator is created, the first call
128   * to nextNode() returns the first node in the set.
129   *
130   * @return  The next <code>Node</code> in the set being iterated over, or
131   *   <code>null</code> if there are no more members in that set.
132   */
133  public int nextNode()
134  {
135  	if(m_foundLast)
136  	{
137  		m_lastFetched = DTM.NULL;
138  		return DTM.NULL;
139  	}
140
141    if(DTM.NULL == m_lastFetched)
142    {
143      resetProximityPositions();
144    }
145
146    int next;
147
148    org.apache.xpath.VariableStack vars;
149    int savedStart;
150    if (-1 != m_stackFrame)
151    {
152      vars = m_execContext.getVarStack();
153
154      // These three statements need to be combined into one operation.
155      savedStart = vars.getStackFrame();
156
157      vars.setStackFrame(m_stackFrame);
158    }
159    else
160    {
161      // Yuck.  Just to shut up the compiler!
162      vars = null;
163      savedStart = 0;
164    }
165
166    try
167    {
168      do
169      {
170        next = getNextNode();
171
172        if (DTM.NULL != next)
173        {
174          if(DTMIterator.FILTER_ACCEPT == acceptNode(next))
175            break;
176          else
177            continue;
178        }
179        else
180          break;
181      }
182      while (next != DTM.NULL);
183
184      if (DTM.NULL != next)
185      {
186      	m_pos++;
187        return next;
188      }
189      else
190      {
191        m_foundLast = true;
192
193        return DTM.NULL;
194      }
195    }
196    finally
197    {
198      if (-1 != m_stackFrame)
199      {
200        // These two statements need to be combined into one operation.
201        vars.setStackFrame(savedStart);
202      }
203    }
204  }
205
206  /**
207   *  Get a cloned Iterator that is reset to the beginning
208   *  of the query.
209   *
210   *  @return A cloned NodeIterator set of the start of the query.
211   *
212   *  @throws CloneNotSupportedException
213   */
214  public DTMIterator cloneWithReset() throws CloneNotSupportedException
215  {
216
217    ChildTestIterator clone = (ChildTestIterator) super.cloneWithReset();
218
219    clone.resetProximityPositions();
220
221    return clone;
222  }
223
224
225}
226
227