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. package org.apache.commons.jxpath.ri.axes;
  17. import java.util.Stack;
  18. import org.apache.commons.jxpath.ri.EvalContext;
  19. import org.apache.commons.jxpath.ri.compiler.NodeTest;
  20. import org.apache.commons.jxpath.ri.model.NodeIterator;
  21. import org.apache.commons.jxpath.ri.model.NodePointer;
  22. import org.apache.commons.jxpath.ri.model.beans.PropertyIterator;
  23. /**
  24. * EvalContext that walks the "preceding::" and "following::" axes.
  25. *
  26. * @author Dmitri Plotnikov
  27. * @version $Revision: 1.15 $ $Date: 2004/03/25 03:49:50 $
  28. */
  29. public class PrecedingOrFollowingContext extends EvalContext {
  30. private NodeTest nodeTest;
  31. private boolean setStarted = false;
  32. private boolean started = false;
  33. private Stack stack;
  34. private Stack nameStack;
  35. private NodePointer currentNodePointer;
  36. private NodePointer currentRootLocation;
  37. private boolean reverse;
  38. public PrecedingOrFollowingContext(
  39. EvalContext parentContext,
  40. NodeTest nodeTest,
  41. boolean reverse)
  42. {
  43. super(parentContext);
  44. this.nodeTest = nodeTest;
  45. this.reverse = reverse;
  46. }
  47. public NodePointer getCurrentNodePointer() {
  48. return currentNodePointer;
  49. }
  50. public int getDocumentOrder() {
  51. return reverse ? -1 : 1;
  52. }
  53. public void reset() {
  54. super.reset();
  55. stack = new Stack();
  56. setStarted = false;
  57. }
  58. public boolean setPosition(int position) {
  59. if (position < this.position) {
  60. reset();
  61. }
  62. while (this.position < position) {
  63. if (!nextNode()) {
  64. return false;
  65. }
  66. }
  67. return true;
  68. }
  69. public boolean nextNode() {
  70. if (!setStarted) {
  71. setStarted = true;
  72. currentRootLocation = parentContext.getCurrentNodePointer();
  73. NodePointer parent = currentRootLocation.getParent();
  74. if (parent != null) {
  75. // TBD: check type
  76. stack.push(
  77. parent.childIterator(null, reverse, currentRootLocation));
  78. }
  79. }
  80. while (true) {
  81. if (stack.isEmpty()) {
  82. currentRootLocation = currentRootLocation.getParent();
  83. if (currentRootLocation == null
  84. || currentRootLocation.isRoot()) {
  85. break;
  86. }
  87. NodePointer parent = currentRootLocation.getParent();
  88. if (parent != null) {
  89. stack.push(
  90. parent.childIterator(
  91. null,
  92. reverse,
  93. currentRootLocation));
  94. }
  95. }
  96. while (!stack.isEmpty()) {
  97. if (!reverse) {
  98. NodeIterator it = (NodeIterator) stack.peek();
  99. if (it.setPosition(it.getPosition() + 1)) {
  100. currentNodePointer = it.getNodePointer();
  101. if (!currentNodePointer.isLeaf()) {
  102. stack.push(
  103. currentNodePointer.childIterator(
  104. null,
  105. reverse,
  106. null));
  107. }
  108. if (currentNodePointer.testNode(nodeTest)) {
  109. super.setPosition(getCurrentPosition() + 1);
  110. return true;
  111. }
  112. }
  113. else {
  114. // We get here only if the name test failed
  115. // and the iterator ended
  116. stack.pop();
  117. }
  118. }
  119. else {
  120. NodeIterator it = (NodeIterator) stack.peek();
  121. if (it.setPosition(it.getPosition() + 1)) {
  122. currentNodePointer = it.getNodePointer();
  123. if (!currentNodePointer.isLeaf()) {
  124. stack.push(
  125. currentNodePointer.childIterator(
  126. null,
  127. reverse,
  128. null));
  129. }
  130. else if (currentNodePointer.testNode(nodeTest)) {
  131. super.setPosition(getCurrentPosition() + 1);
  132. return true;
  133. }
  134. }
  135. else {
  136. stack.pop();
  137. if (!stack.isEmpty()) {
  138. it = (PropertyIterator) stack.peek();
  139. currentNodePointer = it.getNodePointer();
  140. if (currentNodePointer.testNode(nodeTest)) {
  141. super.setPosition(getCurrentPosition() + 1);
  142. return true;
  143. }
  144. }
  145. }
  146. }
  147. }
  148. }
  149. return false;
  150. }
  151. }