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: package org.apache.commons.jxpath.ri.axes;
017:
018: import java.util.Stack;
019:
020: import org.apache.commons.jxpath.ri.EvalContext;
021: import org.apache.commons.jxpath.ri.compiler.NodeTest;
022: import org.apache.commons.jxpath.ri.model.NodeIterator;
023: import org.apache.commons.jxpath.ri.model.NodePointer;
024: import org.apache.commons.jxpath.ri.model.beans.PropertyIterator;
025:
026: /**
027: * EvalContext that walks the "preceding::" and "following::" axes.
028: *
029: * @author Dmitri Plotnikov
030: * @version $Revision: 1.15 $ $Date: 2004/03/25 03:49:50 $
031: */
032: public class PrecedingOrFollowingContext extends EvalContext {
033: private NodeTest nodeTest;
034: private boolean setStarted = false;
035: private boolean started = false;
036: private Stack stack;
037: private Stack nameStack;
038: private NodePointer currentNodePointer;
039: private NodePointer currentRootLocation;
040: private boolean reverse;
041:
042: public PrecedingOrFollowingContext(EvalContext parentContext,
043: NodeTest nodeTest, boolean reverse) {
044: super (parentContext);
045: this .nodeTest = nodeTest;
046: this .reverse = reverse;
047: }
048:
049: public NodePointer getCurrentNodePointer() {
050: return currentNodePointer;
051: }
052:
053: public int getDocumentOrder() {
054: return reverse ? -1 : 1;
055: }
056:
057: public void reset() {
058: super .reset();
059: stack = new Stack();
060: setStarted = false;
061: }
062:
063: public boolean setPosition(int position) {
064: if (position < this .position) {
065: reset();
066: }
067:
068: while (this .position < position) {
069: if (!nextNode()) {
070: return false;
071: }
072: }
073: return true;
074: }
075:
076: public boolean nextNode() {
077: if (!setStarted) {
078: setStarted = true;
079: currentRootLocation = parentContext.getCurrentNodePointer();
080: NodePointer parent = currentRootLocation.getParent();
081: if (parent != null) {
082: // TBD: check type
083: stack.push(parent.childIterator(null, reverse,
084: currentRootLocation));
085: }
086: }
087:
088: while (true) {
089: if (stack.isEmpty()) {
090: currentRootLocation = currentRootLocation.getParent();
091:
092: if (currentRootLocation == null
093: || currentRootLocation.isRoot()) {
094: break;
095: }
096:
097: NodePointer parent = currentRootLocation.getParent();
098: if (parent != null) {
099: stack.push(parent.childIterator(null, reverse,
100: currentRootLocation));
101: }
102: }
103:
104: while (!stack.isEmpty()) {
105: if (!reverse) {
106: NodeIterator it = (NodeIterator) stack.peek();
107: if (it.setPosition(it.getPosition() + 1)) {
108: currentNodePointer = it.getNodePointer();
109: if (!currentNodePointer.isLeaf()) {
110: stack
111: .push(currentNodePointer
112: .childIterator(null,
113: reverse, null));
114: }
115: if (currentNodePointer.testNode(nodeTest)) {
116: super .setPosition(getCurrentPosition() + 1);
117: return true;
118: }
119: } else {
120: // We get here only if the name test failed
121: // and the iterator ended
122: stack.pop();
123: }
124: } else {
125: NodeIterator it = (NodeIterator) stack.peek();
126: if (it.setPosition(it.getPosition() + 1)) {
127: currentNodePointer = it.getNodePointer();
128: if (!currentNodePointer.isLeaf()) {
129: stack
130: .push(currentNodePointer
131: .childIterator(null,
132: reverse, null));
133: } else if (currentNodePointer
134: .testNode(nodeTest)) {
135: super .setPosition(getCurrentPosition() + 1);
136: return true;
137: }
138: } else {
139: stack.pop();
140: if (!stack.isEmpty()) {
141: it = (PropertyIterator) stack.peek();
142: currentNodePointer = it.getNodePointer();
143: if (currentNodePointer.testNode(nodeTest)) {
144: super
145: .setPosition(getCurrentPosition() + 1);
146: return true;
147: }
148: }
149: }
150: }
151: }
152: }
153: return false;
154: }
155: }
|