1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.commons.jxpath.ri.axes;
19
20 import org.apache.commons.jxpath.ri.EvalContext;
21 import org.apache.commons.jxpath.ri.compiler.NodeTest;
22 import org.apache.commons.jxpath.ri.model.NodePointer;
23
24 /**
25 * EvalContext that walks the "ancestor::" and "ancestor-or-self::" axes.
26 */
27 public class AncestorContext extends EvalContext {
28
29 private final NodeTest nodeTest;
30 private boolean setStarted;
31 private NodePointer currentNodePointer;
32 private final boolean includeSelf;
33
34 /**
35 * Constructs a new AncestorContext.
36 *
37 * @param parentContext represents the previous step on the path
38 * @param includeSelf differentiates between "ancestor::" and "ancestor-or-self::" axes
39 * @param nodeTest is the name of the element(s) we are looking for
40 */
41 public AncestorContext(final EvalContext parentContext, final boolean includeSelf, final NodeTest nodeTest) {
42 super(parentContext);
43 this.includeSelf = includeSelf;
44 this.nodeTest = nodeTest;
45 }
46
47 @Override
48 public NodePointer getCurrentNodePointer() {
49 return currentNodePointer;
50 }
51
52 @Override
53 public int getDocumentOrder() {
54 return -1;
55 }
56
57 @Override
58 public boolean nextNode() {
59 if (!setStarted) {
60 setStarted = true;
61 currentNodePointer = parentContext.getCurrentNodePointer();
62 if (includeSelf && currentNodePointer.testNode(nodeTest)) {
63 position++;
64 return true;
65 }
66 }
67 while (true) {
68 currentNodePointer = currentNodePointer.getImmediateParentPointer();
69 if (currentNodePointer == null) {
70 return false;
71 }
72 if (currentNodePointer.testNode(nodeTest)) {
73 position++;
74 return true;
75 }
76 }
77 }
78
79 @Override
80 public void reset() {
81 super.reset();
82 setStarted = false;
83 }
84
85 @Override
86 public boolean setPosition(final int position) {
87 if (position < getCurrentPosition()) {
88 reset();
89 }
90 while (getCurrentPosition() < position) {
91 if (!nextNode()) {
92 return false;
93 }
94 }
95 return true;
96 }
97 }