001: /*
002: * Copyright 1999-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: BasicTestIterator.java,v 1.7 2004/08/17 19:25:34 jycli Exp $
018: */
019: package org.apache.xpath.axes;
020:
021: import org.apache.xml.dtm.DTM;
022: import org.apache.xml.dtm.DTMFilter;
023: import org.apache.xml.dtm.DTMIterator;
024: import org.apache.xml.utils.PrefixResolver;
025: import org.apache.xpath.compiler.Compiler;
026:
027: /**
028: * Base for iterators that handle predicates. Does the basic next
029: * node logic, so all the derived iterator has to do is get the
030: * next node.
031: */
032: public abstract class BasicTestIterator extends LocPathIterator {
033: static final long serialVersionUID = 3505378079378096623L;
034:
035: /**
036: * Create a LocPathIterator object.
037: *
038: * @param nscontext The namespace context for this iterator,
039: * should be OK if null.
040: */
041: protected BasicTestIterator() {
042: }
043:
044: /**
045: * Create a LocPathIterator object.
046: *
047: * @param nscontext The namespace context for this iterator,
048: * should be OK if null.
049: */
050: protected BasicTestIterator(PrefixResolver nscontext) {
051:
052: super (nscontext);
053: }
054:
055: /**
056: * Create a LocPathIterator object, including creation
057: * of step walkers from the opcode list, and call back
058: * into the Compiler to create predicate expressions.
059: *
060: * @param compiler The Compiler which is creating
061: * this expression.
062: * @param opPos The position of this iterator in the
063: * opcode list from the compiler.
064: *
065: * @throws javax.xml.transform.TransformerException
066: */
067: protected BasicTestIterator(Compiler compiler, int opPos,
068: int analysis)
069: throws javax.xml.transform.TransformerException {
070: super (compiler, opPos, analysis, false);
071:
072: int firstStepPos = compiler.getFirstChildPos(opPos);
073: int whatToShow = compiler.getWhatToShow(firstStepPos);
074:
075: if ((0 == (whatToShow & (DTMFilter.SHOW_ATTRIBUTE
076: | DTMFilter.SHOW_NAMESPACE | DTMFilter.SHOW_ELEMENT | DTMFilter.SHOW_PROCESSING_INSTRUCTION)))
077: || (whatToShow == DTMFilter.SHOW_ALL))
078: initNodeTest(whatToShow);
079: else {
080: initNodeTest(whatToShow, compiler.getStepNS(firstStepPos),
081: compiler.getStepLocalName(firstStepPos));
082: }
083: initPredicateInfo(compiler, firstStepPos);
084: }
085:
086: /**
087: * Create a LocPathIterator object, including creation
088: * of step walkers from the opcode list, and call back
089: * into the Compiler to create predicate expressions.
090: *
091: * @param compiler The Compiler which is creating
092: * this expression.
093: * @param opPos The position of this iterator in the
094: * opcode list from the compiler.
095: * @param shouldLoadWalkers True if walkers should be
096: * loaded, or false if this is a derived iterator and
097: * it doesn't wish to load child walkers.
098: *
099: * @throws javax.xml.transform.TransformerException
100: */
101: protected BasicTestIterator(Compiler compiler, int opPos,
102: int analysis, boolean shouldLoadWalkers)
103: throws javax.xml.transform.TransformerException {
104: super (compiler, opPos, analysis, shouldLoadWalkers);
105: }
106:
107: /**
108: * Get the next node via getNextXXX. Bottlenecked for derived class override.
109: * @return The next node on the axis, or DTM.NULL.
110: */
111: protected abstract int getNextNode();
112:
113: /**
114: * Returns the next node in the set and advances the position of the
115: * iterator in the set. After a NodeIterator is created, the first call
116: * to nextNode() returns the first node in the set.
117: *
118: * @return The next <code>Node</code> in the set being iterated over, or
119: * <code>null</code> if there are no more members in that set.
120: */
121: public int nextNode() {
122: if (m_foundLast) {
123: m_lastFetched = DTM.NULL;
124: return DTM.NULL;
125: }
126:
127: if (DTM.NULL == m_lastFetched) {
128: resetProximityPositions();
129: }
130:
131: int next;
132:
133: org.apache.xpath.VariableStack vars;
134: int savedStart;
135: if (-1 != m_stackFrame) {
136: vars = m_execContext.getVarStack();
137:
138: // These three statements need to be combined into one operation.
139: savedStart = vars.getStackFrame();
140:
141: vars.setStackFrame(m_stackFrame);
142: } else {
143: // Yuck. Just to shut up the compiler!
144: vars = null;
145: savedStart = 0;
146: }
147:
148: try {
149: do {
150: next = getNextNode();
151:
152: if (DTM.NULL != next) {
153: if (DTMIterator.FILTER_ACCEPT == acceptNode(next))
154: break;
155: else
156: continue;
157: } else
158: break;
159: } while (next != DTM.NULL);
160:
161: if (DTM.NULL != next) {
162: m_pos++;
163: return next;
164: } else {
165: m_foundLast = true;
166:
167: return DTM.NULL;
168: }
169: } finally {
170: if (-1 != m_stackFrame) {
171: // These two statements need to be combined into one operation.
172: vars.setStackFrame(savedStart);
173: }
174: }
175: }
176:
177: /**
178: * Get a cloned Iterator that is reset to the beginning
179: * of the query.
180: *
181: * @return A cloned NodeIterator set of the start of the query.
182: *
183: * @throws CloneNotSupportedException
184: */
185: public DTMIterator cloneWithReset()
186: throws CloneNotSupportedException {
187:
188: ChildTestIterator clone = (ChildTestIterator) super
189: .cloneWithReset();
190:
191: clone.resetProximityPositions();
192:
193: return clone;
194: }
195:
196: }
|