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