1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jxpath.ri.axes;
19
20 import java.util.Iterator;
21
22 import org.apache.commons.jxpath.ri.EvalContext;
23 import org.apache.commons.jxpath.ri.InfoSetUtil;
24 import org.apache.commons.jxpath.ri.compiler.Expression;
25 import org.apache.commons.jxpath.ri.compiler.NameAttributeTest;
26 import org.apache.commons.jxpath.ri.model.NodePointer;
27 import org.apache.commons.jxpath.ri.model.beans.PropertyOwnerPointer;
28 import org.apache.commons.jxpath.ri.model.beans.PropertyPointer;
29
30
31
32
33 public class PredicateContext extends EvalContext {
34
35 private final Expression expression;
36 private boolean done;
37 private Expression nameTestExpression;
38 private PropertyPointer dynamicPropertyPointer;
39
40
41
42
43
44
45
46 public PredicateContext(final EvalContext parentContext, final Expression expression) {
47 super(parentContext);
48 this.expression = expression;
49 if (expression instanceof NameAttributeTest) {
50 nameTestExpression = ((NameAttributeTest) expression).getNameTestExpression();
51 }
52 }
53
54 @Override
55 public NodePointer getCurrentNodePointer() {
56 if (position == 0 && !setPosition(1)) {
57 return null;
58 }
59 if (dynamicPropertyPointer != null) {
60 return dynamicPropertyPointer.getValuePointer();
61 }
62 return parentContext.getCurrentNodePointer();
63 }
64
65 @Override
66 public boolean nextNode() {
67 if (done) {
68 return false;
69 }
70 while (parentContext.nextNode()) {
71 if (setupDynamicPropertyPointer()) {
72 final Object pred = nameTestExpression.computeValue(parentContext);
73 final String propertyName = InfoSetUtil.stringValue(pred);
74
75
76
77
78
79
80
81
82 boolean ok = false;
83 final String[] names = dynamicPropertyPointer.getPropertyNames();
84 for (final String name : names) {
85 if (name.equals(propertyName)) {
86 ok = true;
87 break;
88 }
89 }
90 if (ok) {
91 dynamicPropertyPointer.setPropertyName(propertyName);
92 position++;
93 return true;
94 }
95 } else {
96 Object pred = expression.computeValue(parentContext);
97 if (pred instanceof Iterator) {
98 if (!((Iterator) pred).hasNext()) {
99 return false;
100 }
101 pred = ((Iterator) pred).next();
102 }
103 if (pred instanceof NodePointer) {
104 pred = ((NodePointer) pred).getNode();
105 }
106 if (pred instanceof Number) {
107 final int pos = (int) InfoSetUtil.doubleValue(pred);
108 position++;
109 done = true;
110 return parentContext.setPosition(pos);
111 }
112 if (InfoSetUtil.booleanValue(pred)) {
113 position++;
114 return true;
115 }
116 }
117 }
118 return false;
119 }
120
121 @Override
122 public boolean nextSet() {
123 reset();
124 return parentContext.nextSet();
125 }
126
127 @Override
128 public void reset() {
129 super.reset();
130 parentContext.reset();
131 done = false;
132 }
133
134 @Override
135 public boolean setPosition(final int position) {
136 if (nameTestExpression == null) {
137 return setPositionStandard(position);
138 }
139 if (dynamicPropertyPointer == null && !setupDynamicPropertyPointer()) {
140 return setPositionStandard(position);
141 }
142 if (position < 1 || position > dynamicPropertyPointer.getLength()) {
143 return false;
144 }
145 dynamicPropertyPointer.setIndex(position - 1);
146 return true;
147 }
148
149
150
151
152
153
154
155 private boolean setPositionStandard(final int position) {
156 if (this.position > position) {
157 reset();
158 }
159 while (this.position < position) {
160 if (!nextNode()) {
161 return false;
162 }
163 }
164 return true;
165 }
166
167
168
169
170
171
172 private boolean setupDynamicPropertyPointer() {
173 if (nameTestExpression == null) {
174 return false;
175 }
176 NodePointer parent = parentContext.getCurrentNodePointer();
177 if (parent == null) {
178 return false;
179 }
180 parent = parent.getValuePointer();
181 if (!(parent instanceof PropertyOwnerPointer)) {
182 return false;
183 }
184 dynamicPropertyPointer = (PropertyPointer) ((PropertyOwnerPointer) parent).getPropertyPointer().clone();
185 return true;
186 }
187 }