1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jxpath.ri.compiler;
18
19 import org.apache.commons.jxpath.Pointer;
20 import org.apache.commons.jxpath.ri.Compiler;
21 import org.apache.commons.jxpath.ri.EvalContext;
22 import org.apache.commons.jxpath.ri.QName;
23 import org.apache.commons.jxpath.ri.axes.AncestorContext;
24 import org.apache.commons.jxpath.ri.axes.AttributeContext;
25 import org.apache.commons.jxpath.ri.axes.ChildContext;
26 import org.apache.commons.jxpath.ri.axes.DescendantContext;
27 import org.apache.commons.jxpath.ri.axes.InitialContext;
28 import org.apache.commons.jxpath.ri.axes.NamespaceContext;
29 import org.apache.commons.jxpath.ri.axes.ParentContext;
30 import org.apache.commons.jxpath.ri.axes.PrecedingOrFollowingContext;
31 import org.apache.commons.jxpath.ri.axes.PredicateContext;
32 import org.apache.commons.jxpath.ri.axes.SelfContext;
33 import org.apache.commons.jxpath.ri.axes.SimplePathInterpreter;
34 import org.apache.commons.jxpath.ri.axes.UnionContext;
35 import org.apache.commons.jxpath.ri.model.NodePointer;
36
37
38
39
40
41 public abstract class Path extends Expression {
42
43 private Step[] steps;
44 private boolean basicKnown = false;
45 private boolean basic;
46
47
48
49
50
51 public Path(Step[] steps) {
52 this.steps = steps;
53 }
54
55
56
57
58
59 public Step[] getSteps() {
60 return steps;
61 }
62
63 public boolean computeContextDependent() {
64 if (steps != null) {
65 for (int i = 0; i < steps.length; i++) {
66 if (steps[i].isContextDependent()) {
67 return true;
68 }
69 }
70 }
71 return false;
72 }
73
74
75
76
77
78
79
80 public synchronized boolean isSimplePath() {
81 if (!basicKnown) {
82 basicKnown = true;
83 basic = true;
84 Step[] steps = getSteps();
85 for (int i = 0; i < steps.length; i++) {
86 if (!isSimpleStep(steps[i])) {
87 basic = false;
88 break;
89 }
90 }
91 }
92 return basic;
93 }
94
95
96
97
98
99
100
101
102 protected boolean isSimpleStep(Step step) {
103 if (step.getAxis() == Compiler.AXIS_SELF) {
104 NodeTest nodeTest = step.getNodeTest();
105 if (!(nodeTest instanceof NodeTypeTest)) {
106 return false;
107 }
108 int nodeType = ((NodeTypeTest) nodeTest).getNodeType();
109 if (nodeType != Compiler.NODE_TYPE_NODE) {
110 return false;
111 }
112 return areBasicPredicates(step.getPredicates());
113 }
114 if (step.getAxis() == Compiler.AXIS_CHILD
115 || step.getAxis() == Compiler.AXIS_ATTRIBUTE) {
116 NodeTest nodeTest = step.getNodeTest();
117 if (!(nodeTest instanceof NodeNameTest)) {
118 return false;
119 }
120 if (((NodeNameTest) nodeTest).isWildcard()) {
121 return false;
122 }
123 return areBasicPredicates(step.getPredicates());
124 }
125 return false;
126 }
127
128
129
130
131
132
133 protected boolean areBasicPredicates(Expression[] predicates) {
134 if (predicates != null && predicates.length != 0) {
135 boolean firstIndex = true;
136 for (int i = 0; i < predicates.length; i++) {
137 if (predicates[i] instanceof NameAttributeTest) {
138 if (((NameAttributeTest) predicates[i])
139 .getNameTestExpression()
140 .isContextDependent()) {
141 return false;
142 }
143 }
144 else if (predicates[i].isContextDependent()) {
145 return false;
146 }
147 else {
148 if (!firstIndex) {
149 return false;
150 }
151 firstIndex = false;
152 }
153 }
154 }
155 return true;
156 }
157
158
159
160
161
162
163
164 protected Pointer getSingleNodePointerForSteps(EvalContext context) {
165 if (steps.length == 0) {
166 return context.getSingleNodePointer();
167 }
168
169 if (isSimplePath()) {
170 NodePointer ptr = (NodePointer) context.getSingleNodePointer();
171 return SimplePathInterpreter.interpretSimpleLocationPath(
172 context,
173 ptr,
174 steps);
175 }
176 return searchForPath(context);
177 }
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199 protected Pointer searchForPath(EvalContext context) {
200 EvalContext ctx = buildContextChain(context, steps.length, true);
201 Pointer pointer = ctx.getSingleNodePointer();
202
203 if (pointer != null) {
204 return pointer;
205 }
206
207 for (int i = steps.length; --i > 0;) {
208 if (!isSimpleStep(steps[i])) {
209 return null;
210 }
211 ctx = buildContextChain(context, i, true);
212 if (ctx.hasNext()) {
213 Pointer partial = (Pointer) ctx.next();
214 if (ctx.hasNext()) {
215
216
217 return null;
218 }
219 if (partial instanceof NodePointer) {
220 return SimplePathInterpreter.createNullPointer(
221 context,
222 (NodePointer) partial,
223 steps,
224 i);
225 }
226 }
227 }
228 return null;
229 }
230
231
232
233
234
235
236
237 protected EvalContext evalSteps(EvalContext context) {
238 return buildContextChain(context, steps.length, false);
239 }
240
241
242
243
244
245
246
247
248 protected EvalContext buildContextChain(
249 EvalContext context,
250 int stepCount,
251 boolean createInitialContext) {
252 if (createInitialContext) {
253 context = new InitialContext(context);
254 }
255 if (steps.length == 0) {
256 return context;
257 }
258 for (int i = 0; i < stepCount; i++) {
259 context =
260 createContextForStep(
261 context,
262 steps[i].getAxis(),
263 steps[i].getNodeTest());
264 Expression[] predicates = steps[i].getPredicates();
265 if (predicates != null) {
266 for (int j = 0; j < predicates.length; j++) {
267 if (j != 0) {
268 context = new UnionContext(context, new EvalContext[]{context});
269 }
270 context = new PredicateContext(context, predicates[j]);
271 }
272 }
273 }
274 return context;
275 }
276
277
278
279
280
281
282
283
284
285 protected EvalContext createContextForStep(
286 EvalContext context,
287 int axis,
288 NodeTest nodeTest) {
289 if (nodeTest instanceof NodeNameTest) {
290 QName qname = ((NodeNameTest) nodeTest).getNodeName();
291 String prefix = qname.getPrefix();
292 if (prefix != null) {
293 String namespaceURI = context.getJXPathContext()
294 .getNamespaceURI(prefix);
295 nodeTest = new NodeNameTest(qname, namespaceURI);
296 }
297 }
298
299 switch (axis) {
300 case Compiler.AXIS_ANCESTOR :
301 return new AncestorContext(context, false, nodeTest);
302 case Compiler.AXIS_ANCESTOR_OR_SELF :
303 return new AncestorContext(context, true, nodeTest);
304 case Compiler.AXIS_ATTRIBUTE :
305 return new AttributeContext(context, nodeTest);
306 case Compiler.AXIS_CHILD :
307 return new ChildContext(context, nodeTest, false, false);
308 case Compiler.AXIS_DESCENDANT :
309 return new DescendantContext(context, false, nodeTest);
310 case Compiler.AXIS_DESCENDANT_OR_SELF :
311 return new DescendantContext(context, true, nodeTest);
312 case Compiler.AXIS_FOLLOWING :
313 return new PrecedingOrFollowingContext(context, nodeTest, false);
314 case Compiler.AXIS_FOLLOWING_SIBLING :
315 return new ChildContext(context, nodeTest, true, false);
316 case Compiler.AXIS_NAMESPACE :
317 return new NamespaceContext(context, nodeTest);
318 case Compiler.AXIS_PARENT :
319 return new ParentContext(context, nodeTest);
320 case Compiler.AXIS_PRECEDING :
321 return new PrecedingOrFollowingContext(context, nodeTest, true);
322 case Compiler.AXIS_PRECEDING_SIBLING :
323 return new ChildContext(context, nodeTest, true, true);
324 case Compiler.AXIS_SELF :
325 return new SelfContext(context, nodeTest);
326 default:
327 return null;
328 }
329 }
330 }