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