1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package org.jaxen.expr;
35
36 import java.util.ArrayList;
37 import java.util.Collections;
38 import java.util.Iterator;
39 import java.util.List;
40
41 import org.jaxen.Context;
42 import org.jaxen.ContextSupport;
43 import org.jaxen.JaxenException;
44 import org.jaxen.UnresolvableException;
45 import org.jaxen.Navigator;
46 import org.jaxen.expr.iter.IterableAxis;
47 import org.jaxen.saxpath.Axis;
48
49
50
51
52
53
54
55
56
57
58
59
60
61 public class DefaultNameStep extends DefaultStep implements NameStep {
62
63 private static final long serialVersionUID = 428414912247718390L;
64
65
66
67
68
69
70
71 private String prefix;
72
73
74
75
76
77 private String localName;
78
79
80 private boolean matchesAnyName;
81
82
83 private boolean hasPrefix;
84
85
86
87
88
89
90
91
92
93 public DefaultNameStep(IterableAxis axis,
94 String prefix,
95 String localName,
96 PredicateSet predicateSet) {
97 super(axis, predicateSet);
98
99 this.prefix = prefix;
100 this.localName = localName;
101 this.matchesAnyName = "*".equals(localName);
102 this.hasPrefix = (this.prefix != null && this.prefix.length() > 0);
103 }
104
105
106
107
108
109
110 public String getPrefix() {
111 return this.prefix;
112 }
113
114
115
116
117
118
119 public String getLocalName() {
120 return this.localName;
121 }
122
123
124
125
126
127
128 public boolean isMatchesAnyName() {
129 return matchesAnyName;
130 }
131
132
133
134
135
136
137 public String getText() {
138 StringBuffer buf = new StringBuffer(64);
139 buf.append(getAxisName()).append("::");
140 if (getPrefix() != null && getPrefix().length() > 0) {
141 buf.append(getPrefix()).append(':');
142 }
143 return buf.append(getLocalName()).append(super.getText()).toString();
144 }
145
146
147
148
149
150
151 public List evaluate(Context context) throws JaxenException {
152
153 List contextNodeSet = context.getNodeSet();
154 int contextSize = contextNodeSet.size();
155
156 if (contextSize == 0) {
157 return Collections.EMPTY_LIST;
158 }
159 ContextSupport support = context.getContextSupport();
160 IterableAxis iterableAxis = getIterableAxis();
161 boolean namedAccess = (!matchesAnyName && iterableAxis.supportsNamedAccess(support));
162
163
164 if (contextSize == 1) {
165 Object contextNode = contextNodeSet.get(0);
166 if (namedAccess) {
167
168 String uri = null;
169 if (hasPrefix) {
170 uri = support.translateNamespacePrefixToUri(prefix);
171 if (uri == null) {
172 throw new UnresolvableException("XPath expression uses unbound namespace prefix " + prefix);
173 }
174 }
175 Iterator axisNodeIter = iterableAxis.namedAccessIterator(
176 contextNode, support, localName, prefix, uri);
177 if (axisNodeIter == null || !axisNodeIter.hasNext()) {
178 return Collections.EMPTY_LIST;
179 }
180
181
182
183 List newNodeSet = new ArrayList();
184 while (axisNodeIter.hasNext()) {
185 newNodeSet.add(axisNodeIter.next());
186 }
187
188
189 return getPredicateSet().evaluatePredicates(newNodeSet, support);
190
191 }
192 else {
193
194 Iterator axisNodeIter = iterableAxis.iterator(contextNode, support);
195 if (axisNodeIter == null || !axisNodeIter.hasNext()) {
196 return Collections.EMPTY_LIST;
197 }
198
199
200
201 List newNodeSet = new ArrayList(contextSize);
202 while (axisNodeIter.hasNext()) {
203 Object eachAxisNode = axisNodeIter.next();
204 if (matches(eachAxisNode, support)) {
205 newNodeSet.add(eachAxisNode);
206 }
207 }
208
209
210 return getPredicateSet().evaluatePredicates(newNodeSet, support);
211 }
212 }
213
214
215 IdentitySet unique = new IdentitySet();
216 List<Object> interimSet = new ArrayList<Object>(contextSize);
217 List<Object> newNodeSet = new ArrayList<Object>(contextSize);
218
219 if (namedAccess) {
220 String uri = null;
221 if (hasPrefix) {
222 uri = support.translateNamespacePrefixToUri(prefix);
223 if (uri == null) {
224 throw new UnresolvableException("XPath expression uses unbound namespace prefix " + prefix);
225 }
226 }
227 for (int i = 0; i < contextSize; ++i) {
228 Object eachContextNode = contextNodeSet.get(i);
229
230 Iterator axisNodeIter = iterableAxis.namedAccessIterator(
231 eachContextNode, support, localName, prefix, uri);
232 if (axisNodeIter == null || !axisNodeIter.hasNext()) {
233 continue;
234 }
235
236 while (axisNodeIter.hasNext())
237 {
238 Object eachAxisNode = axisNodeIter.next();
239 interimSet.add(eachAxisNode);
240 }
241
242
243 List predicateNodes = getPredicateSet().evaluatePredicates(interimSet, support);
244
245
246 Iterator predicateNodeIter = predicateNodes.iterator();
247 while (predicateNodeIter.hasNext())
248 {
249 Object eachPredicateNode = predicateNodeIter.next();
250 if (! unique.contains(eachPredicateNode))
251 {
252 unique.add(eachPredicateNode);
253 newNodeSet.add(eachPredicateNode);
254 }
255 }
256 interimSet.clear();
257 }
258
259 } else {
260 for (int i = 0; i < contextSize; ++i) {
261 Object eachContextNode = contextNodeSet.get(i);
262
263 Iterator axisNodeIter = axisIterator(eachContextNode, support);
264 if (axisNodeIter == null || !axisNodeIter.hasNext()) {
265 continue;
266 }
267
268
269
270
271
272
273
274
275
276
277 while (axisNodeIter.hasNext()) {
278 Object eachAxisNode = axisNodeIter.next();
279
280 if (matches(eachAxisNode, support)) {
281 interimSet.add(eachAxisNode);
282 }
283 }
284
285
286 List predicateNodes = getPredicateSet().evaluatePredicates(interimSet, support);
287
288
289 Iterator predicateNodeIter = predicateNodes.iterator();
290 while (predicateNodeIter.hasNext())
291 {
292 Object eachPredicateNode = predicateNodeIter.next();
293 if (! unique.contains(eachPredicateNode))
294 {
295 unique.add(eachPredicateNode);
296 newNodeSet.add(eachPredicateNode);
297 }
298 }
299 interimSet.clear();
300 }
301 }
302
303 return newNodeSet;
304 }
305
306
307
308
309
310
311
312
313
314 public boolean matches(Object node, ContextSupport contextSupport) throws JaxenException {
315
316 Navigator nav = contextSupport.getNavigator();
317 String myUri = null;
318 String nodeName = null;
319 String nodeUri = null;
320
321 if (nav.isElement(node)) {
322 nodeName = nav.getElementName(node);
323 nodeUri = nav.getElementNamespaceUri(node);
324 }
325 else if (nav.isText(node)) {
326 return false;
327 }
328 else if (nav.isAttribute(node)) {
329 if (getAxis() != Axis.ATTRIBUTE) {
330 return false;
331 }
332 nodeName = nav.getAttributeName(node);
333 nodeUri = nav.getAttributeNamespaceUri(node);
334
335 }
336 else if (nav.isDocument(node)) {
337 return false;
338 }
339 else if (nav.isNamespace(node)) {
340 if (getAxis() != Axis.NAMESPACE) {
341
342 return false;
343 }
344 nodeName = nav.getNamespacePrefix(node);
345 }
346 else {
347 return false;
348 }
349
350 if (hasPrefix) {
351 myUri = contextSupport.translateNamespacePrefixToUri(this.prefix);
352 if (myUri == null) {
353 throw new UnresolvableException("Cannot resolve namespace prefix '"+this.prefix+"'");
354 }
355 }
356 else if (matchesAnyName) {
357 return true;
358 }
359
360
361
362 if (hasNamespace(myUri) != hasNamespace(nodeUri)) {
363 return false;
364 }
365
366
367
368
369 if (matchesAnyName || nodeName.equals(getLocalName())) {
370 return matchesNamespaceURIs(myUri, nodeUri);
371 }
372
373 return false;
374 }
375
376
377
378
379
380
381
382 private boolean hasNamespace(String uri) {
383 return (uri != null && uri.length() > 0);
384 }
385
386
387
388
389
390
391
392
393 boolean matchesNamespaceURIs(String uri1, String uri2) {
394 if (uri1 == uri2) {
395 return true;
396 }
397 if (uri1 == null) {
398 return (uri2.length() == 0);
399 }
400 if (uri2 == null) {
401 return (uri1.length() == 0);
402 }
403 return uri1.equals(uri2);
404 }
405
406
407
408
409
410
411 @Override
412 public String toString() {
413 String prefix = getPrefix();
414 String qName = "".equals(prefix) ? getLocalName() : getPrefix() + ":" + getLocalName();
415 return "[(DefaultNameStep): " + qName + "]";
416 }
417
418 }