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 org.apache.commons.jxpath.Pointer;
  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. /**
  23. * EvalContext that can walk the "child::", "following-sibling::" and
  24. * "preceding-sibling::" axes.
  25. *
  26. * @author Dmitri Plotnikov
  27. * @version $Revision: 1.16 $ $Date: 2004/03/25 03:49:50 $
  28. */
  29. public class ChildContext extends EvalContext {
  30. private NodeTest nodeTest;
  31. private boolean startFromParentLocation;
  32. private boolean reverse;
  33. private NodeIterator iterator;
  34. public ChildContext(
  35. EvalContext parentContext,
  36. NodeTest nodeTest,
  37. boolean startFromParentLocation,
  38. boolean reverse)
  39. {
  40. super(parentContext);
  41. this.nodeTest = nodeTest;
  42. this.startFromParentLocation = startFromParentLocation;
  43. this.reverse = reverse;
  44. }
  45. public NodePointer getCurrentNodePointer() {
  46. if (position == 0) {
  47. if (!setPosition(1)) {
  48. return null;
  49. }
  50. }
  51. if (iterator != null) {
  52. return iterator.getNodePointer();
  53. }
  54. else {
  55. return null;
  56. }
  57. }
  58. /**
  59. * This method is called on the last context on the path when only
  60. * one value is needed. Note that this will return the whole property,
  61. * even if it is a collection. It will not extract the first element
  62. * of the collection. For example, "books" will return the collection
  63. * of books rather than the first book from that collection.
  64. */
  65. public Pointer getSingleNodePointer() {
  66. if (position == 0) {
  67. while (nextSet()) {
  68. prepare();
  69. if (iterator == null) {
  70. return null;
  71. }
  72. // See if there is a property there, singular or collection
  73. NodePointer pointer = iterator.getNodePointer();
  74. if (pointer != null) {
  75. return pointer;
  76. }
  77. }
  78. return null;
  79. }
  80. return getCurrentNodePointer();
  81. }
  82. public boolean nextNode() {
  83. return setPosition(getCurrentPosition() + 1);
  84. }
  85. public void reset() {
  86. super.reset();
  87. iterator = null;
  88. }
  89. public boolean setPosition(int position) {
  90. int oldPosition = getCurrentPosition();
  91. super.setPosition(position);
  92. if (oldPosition == 0) {
  93. prepare();
  94. }
  95. if (iterator == null) {
  96. return false;
  97. }
  98. return iterator.setPosition(position);
  99. }
  100. /**
  101. * Allocates a PropertyIterator.
  102. */
  103. private void prepare() {
  104. NodePointer parent = parentContext.getCurrentNodePointer();
  105. if (parent == null) {
  106. return;
  107. }
  108. if (startFromParentLocation) {
  109. NodePointer pointer = parent.getParent();
  110. iterator = pointer.childIterator(nodeTest, reverse, parent);
  111. }
  112. else {
  113. iterator = parent.childIterator(nodeTest, reverse, null);
  114. }
  115. }
  116. }