001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 /*
019 * $Id: BasicTestIterator.java 469314 2006-10-30 23:31:59Z minchau $
020 */
021 package org.apache.xpath.axes;
022
023 import org.apache.xml.dtm.DTM;
024 import org.apache.xml.dtm.DTMFilter;
025 import org.apache.xml.dtm.DTMIterator;
026 import org.apache.xml.utils.PrefixResolver;
027 import org.apache.xpath.compiler.Compiler;
028 import org.apache.xpath.compiler.OpMap;
029
030 /**
031 * Base for iterators that handle predicates. Does the basic next
032 * node logic, so all the derived iterator has to do is get the
033 * next node.
034 */
035 public abstract class BasicTestIterator extends LocPathIterator
036 {
037 static final long serialVersionUID = 3505378079378096623L;
038 /**
039 * Create a LocPathIterator object.
040 *
041 * @param nscontext The namespace context for this iterator,
042 * should be OK if null.
043 */
044 protected BasicTestIterator()
045 {
046 }
047
048
049 /**
050 * Create a LocPathIterator object.
051 *
052 * @param nscontext The namespace context for this iterator,
053 * should be OK if null.
054 */
055 protected BasicTestIterator(PrefixResolver nscontext)
056 {
057
058 super(nscontext);
059 }
060
061 /**
062 * Create a LocPathIterator object, including creation
063 * of step walkers from the opcode list, and call back
064 * into the Compiler to create predicate expressions.
065 *
066 * @param compiler The Compiler which is creating
067 * this expression.
068 * @param opPos The position of this iterator in the
069 * opcode list from the compiler.
070 *
071 * @throws javax.xml.transform.TransformerException
072 */
073 protected BasicTestIterator(Compiler compiler, int opPos, int analysis)
074 throws javax.xml.transform.TransformerException
075 {
076 super(compiler, opPos, analysis, false);
077
078 int firstStepPos = OpMap.getFirstChildPos(opPos);
079 int whatToShow = compiler.getWhatToShow(firstStepPos);
080
081 if ((0 == (whatToShow
082 & (DTMFilter.SHOW_ATTRIBUTE
083 | DTMFilter.SHOW_NAMESPACE
084 | DTMFilter.SHOW_ELEMENT
085 | DTMFilter.SHOW_PROCESSING_INSTRUCTION)))
086 || (whatToShow == DTMFilter.SHOW_ALL))
087 initNodeTest(whatToShow);
088 else
089 {
090 initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
091 compiler.getStepLocalName(firstStepPos));
092 }
093 initPredicateInfo(compiler, firstStepPos);
094 }
095
096 /**
097 * Create a LocPathIterator object, including creation
098 * of step walkers from the opcode list, and call back
099 * 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