Source Code Cross Referenced for SimplePathInterpreter.java in  » Library » Apache-commons-jxpath-1.2-src » org » apache » commons » jxpath » ri » axes » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache commons jxpath 1.2 src » org.apache.commons.jxpath.ri.axes 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 1999-2004 The Apache Software Foundation
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *     http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:        package org.apache.commons.jxpath.ri.axes;
017:
018:        import java.util.ArrayList;
019:        import java.util.Collections;
020:        import java.util.List;
021:
022:        import org.apache.commons.jxpath.JXPathException;
023:        import org.apache.commons.jxpath.ri.Compiler;
024:        import org.apache.commons.jxpath.ri.EvalContext;
025:        import org.apache.commons.jxpath.ri.InfoSetUtil;
026:        import org.apache.commons.jxpath.ri.QName;
027:        import org.apache.commons.jxpath.ri.compiler.Expression;
028:        import org.apache.commons.jxpath.ri.compiler.NameAttributeTest;
029:        import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
030:        import org.apache.commons.jxpath.ri.compiler.NodeTest;
031:        import org.apache.commons.jxpath.ri.compiler.Step;
032:        import org.apache.commons.jxpath.ri.model.NodeIterator;
033:        import org.apache.commons.jxpath.ri.model.NodePointer;
034:        import org.apache.commons.jxpath.ri.model.beans.LangAttributePointer;
035:        import org.apache.commons.jxpath.ri.model.beans.NullElementPointer;
036:        import org.apache.commons.jxpath.ri.model.beans.NullPropertyPointer;
037:        import org.apache.commons.jxpath.ri.model.beans.PropertyOwnerPointer;
038:        import org.apache.commons.jxpath.ri.model.beans.PropertyPointer;
039:
040:        /**
041:         * An evaluation mechanism for simple XPaths, which
042:         * is much faster than the usual process. It is only used for
043:         * xpaths which have no context-dependent parts, consist entirely of
044:         * <code>child::name</code> and <code>self::node()</code> steps with
045:         * predicates that either integer or have the form <code>[@name = ...]</code>.
046:         *
047:         * @author Dmitri Plotnikov
048:         * @version $Revision: 1.10 $ $Date: 2002/04/24 04:05:40 $
049:         */
050:        public class SimplePathInterpreter {
051:
052:            // Because of the complexity caused by the variety of situations
053:            // that need to be addressed by this class, we attempt to break up
054:            // the class into individual methods addressing those situations
055:            // individually.  The names of the methods are supposed to
056:            // give brief descriptions of those situations.
057:
058:            private static final QName QNAME_NAME = new QName(null, "name");
059:            private static final int PERFECT_MATCH = 1000;
060:
061:            // Uncomment this variable and the PATH = ... lines in
062:            // the two following methods in order to be able to print the
063:            // currently evaluated path for debugging of this class
064:            //    private static String PATH;       // Debugging
065:
066:            /**
067:             * Interpret a simple path that starts with the given root and
068:             * follows the given steps. All steps must have the axis "child::"
069:             * and a name test.  They can also optionally have predicates
070:             * of type [@name=expression] or simply [expression] interpreted
071:             * as an index.
072:             */
073:            public static NodePointer interpretSimpleLocationPath(
074:                    EvalContext context, NodePointer root, Step steps[]) {
075:                //        PATH = createNullPointer(context, root, steps, 0).toString();  // Dbg
076:                NodePointer pointer = doStep(context, root, steps, 0);
077:                //        return valuePointer(pointer);
078:                return pointer;
079:            }
080:
081:            /**
082:             * Interpret the steps of a simple expression path that
083:             * starts with the given root, which is the result of evaluation
084:             * of the root expression of the expression path, applies the
085:             * given predicates to it and then follows the given steps.
086:             * All steps must have the axis "child::" or "attribute::"
087:             * and a name test.  They can also optionally have predicates
088:             * of type [@name=...] or simply [...] interpreted as an index.
089:             */
090:            public static NodePointer interpretSimpleExpressionPath(
091:                    EvalContext context, NodePointer root,
092:                    Expression predicates[], Step[] steps) {
093:                //        PATH = createNullPointerForPredicates(context, root,
094:                //                    steps, -1, predicates, 0).toString();  // Debugging
095:                NodePointer pointer = doPredicate(context, root, steps, -1,
096:                        predicates, 0);
097:                //        return valuePointer(pointer);
098:                return pointer;
099:            }
100:
101:            /**
102:             * Recursive evaluation of a path. The general plan is:
103:             * Look at the current step,
104:             * find nodes that match it,
105:             * iterate over those nodes and
106:             * for each of them call doStep again for subsequent steps.
107:             */
108:            private static NodePointer doStep(EvalContext context,
109:                    NodePointer parent, Step steps[], int currentStep) {
110:                if (parent == null) {
111:                    return null;
112:                }
113:
114:                if (currentStep == steps.length) {
115:                    // We have reached the end of the list of steps
116:                    return parent;
117:                }
118:
119:                // Open all containers
120:                parent = valuePointer(parent);
121:
122:                Step step = steps[currentStep];
123:                Expression predicates[] = step.getPredicates();
124:
125:                // Divide and conquer: the process is broken out into
126:                // four major use cases.
127:                // 1. Current step has no predicates and
128:                //    the root is a property owner (e.g. bean or map)
129:                // 2. Current step has predicates and
130:                //    the root is a property owner (e.g. bean or map)
131:                // 3. Current step has no predicates and
132:                //    the root is an InfoSet standard node (e.g. DOM Node)
133:                // 4. Current step has predicates and
134:                //    the root is an InfoSet standard node (e.g. DOM Node)
135:
136:                if (parent instanceof  PropertyOwnerPointer) {
137:                    if (predicates == null || predicates.length == 0) {
138:                        return doStepNoPredicatesPropertyOwner(context,
139:                                (PropertyOwnerPointer) parent, steps,
140:                                currentStep);
141:                    } else {
142:                        return doStepPredicatesPropertyOwner(context,
143:                                (PropertyOwnerPointer) parent, steps,
144:                                currentStep);
145:                    }
146:                } else {
147:                    if (predicates == null || predicates.length == 0) {
148:                        return doStepNoPredicatesStandard(context, parent,
149:                                steps, currentStep);
150:                    } else {
151:                        return doStepPredicatesStandard(context, parent, steps,
152:                                currentStep);
153:                    }
154:                }
155:            }
156:
157:            /**
158:             * We have a step that starts with a property owner (bean, map, etc) and has
159:             * no predicates.  The name test of the step may map to a scalar property
160:             * or to a collection.  If it is a collection, we should apply the tail of
161:             * the path to each element until we find a match. If we don't find
162:             * a perfect match, we should return the "best quality" pointer, which
163:             * has the longest chain of steps mapping to existing nodes and the shortes
164:             * tail of Null* pointers.
165:             */
166:            private static NodePointer doStepNoPredicatesPropertyOwner(
167:                    EvalContext context, PropertyOwnerPointer parentPointer,
168:                    Step[] steps, int currentStep) {
169:                Step step = steps[currentStep];
170:                NodePointer childPointer = createChildPointerForStep(
171:                        parentPointer, step);
172:
173:                if (!childPointer.isActual()) {
174:                    // The property does not exist - create a null pointer.
175:                    return createNullPointer(context, parentPointer, steps,
176:                            currentStep);
177:                } else if (currentStep == steps.length - 1) {
178:                    // If this is the last step - we are done, we found it
179:                    return childPointer;
180:                } else if (childPointer.isCollection()) {
181:                    // Iterate over all values and
182:                    // execute remaining steps for each node,
183:                    // looking for the best quality match
184:                    int bestQuality = 0;
185:                    childPointer = (NodePointer) childPointer.clone();
186:                    NodePointer bestMatch = null;
187:                    int count = childPointer.getLength();
188:                    for (int i = 0; i < count; i++) {
189:                        childPointer.setIndex(i);
190:                        NodePointer pointer = doStep(context, childPointer,
191:                                steps, currentStep + 1);
192:                        int quality = computeQuality(pointer);
193:                        if (quality == PERFECT_MATCH) {
194:                            return pointer;
195:                        } else if (quality > bestQuality) {
196:                            bestQuality = quality;
197:                            bestMatch = (NodePointer) pointer.clone();
198:                        }
199:                    }
200:                    if (bestMatch != null) {
201:                        return bestMatch;
202:                    }
203:                    // This step did not find anything - return a null pointer
204:                    return createNullPointer(context, childPointer, steps,
205:                            currentStep);
206:                } else {
207:                    // Evaluate subsequent steps
208:                    return doStep(context, childPointer, steps, currentStep + 1);
209:                }
210:            }
211:
212:            /**
213:             * A path that starts with a standard InfoSet node (e.g. DOM Node) and
214:             * has no predicates.  Get a child iterator and apply the tail of
215:             * the path to each element until we find a match. If we don't find
216:             * a perfect match, we should return the "best quality" pointer, which
217:             * has the longest chain of steps mapping to existing nodes and the shortes
218:             * tail of Null* pointers.
219:             */
220:            private static NodePointer doStepNoPredicatesStandard(
221:                    EvalContext context, NodePointer parentPointer,
222:                    Step[] steps, int currentStep) {
223:                Step step = steps[currentStep];
224:
225:                if (step.getAxis() == Compiler.AXIS_SELF) {
226:                    return doStep(context, parentPointer, steps,
227:                            currentStep + 1);
228:                }
229:
230:                int bestQuality = 0;
231:                NodePointer bestMatch = null;
232:                NodeIterator it = getNodeIterator(context, parentPointer, step);
233:                if (it != null) {
234:                    for (int i = 1; it.setPosition(i); i++) {
235:                        NodePointer childPointer = it.getNodePointer();
236:                        if (steps.length == currentStep + 1) {
237:                            // If this is the last step - we are done, we found it
238:                            return childPointer;
239:                        }
240:                        NodePointer pointer = doStep(context, childPointer,
241:                                steps, currentStep + 1);
242:                        int quality = computeQuality(pointer);
243:                        if (quality == PERFECT_MATCH) {
244:                            return pointer;
245:                        } else if (quality > bestQuality) {
246:                            bestQuality = quality;
247:                            bestMatch = (NodePointer) pointer.clone();
248:                        }
249:                    }
250:                }
251:
252:                if (bestMatch != null) {
253:                    return bestMatch;
254:                }
255:
256:                return createNullPointer(context, parentPointer, steps,
257:                        currentStep);
258:            }
259:
260:            /**
261:             * A path that starts with a property owner. The method evaluates
262:             * the first predicate in a special way and then forwards to
263:             * a general predicate processing method.
264:             */
265:            private static NodePointer doStepPredicatesPropertyOwner(
266:                    EvalContext context, PropertyOwnerPointer parentPointer,
267:                    Step[] steps, int currentStep) {
268:                Step step = steps[currentStep];
269:                Expression predicates[] = step.getPredicates();
270:
271:                NodePointer childPointer = createChildPointerForStep(
272:                        parentPointer, step);
273:                if (!childPointer.isActual()) {
274:                    // Property does not exist - return a null pointer
275:                    return createNullPointer(context, parentPointer, steps,
276:                            currentStep);
277:                }
278:
279:                // Evaluate predicates
280:                return doPredicate(context, childPointer, steps, currentStep,
281:                        predicates, 0);
282:            }
283:
284:            private static NodePointer createChildPointerForStep(
285:                    PropertyOwnerPointer parentPointer, Step step) {
286:                int axis = step.getAxis();
287:                if (axis == Compiler.AXIS_CHILD
288:                        || axis == Compiler.AXIS_ATTRIBUTE) {
289:                    NodePointer childPointer;
290:                    QName name = ((NodeNameTest) step.getNodeTest())
291:                            .getNodeName();
292:                    if (axis == Compiler.AXIS_ATTRIBUTE
293:                            && isLangAttribute(name)) {
294:                        childPointer = new LangAttributePointer(parentPointer);
295:                    } else {
296:                        childPointer = parentPointer.getPropertyPointer();
297:                        ((PropertyPointer) childPointer).setPropertyName(name
298:                                .toString());
299:                        childPointer
300:                                .setAttribute(axis == Compiler.AXIS_ATTRIBUTE);
301:                    }
302:                    return childPointer;
303:                } else {
304:                    return parentPointer;
305:                }
306:            }
307:
308:            /**
309:             * A path that starts with a standard InfoSet node, e.g. a DOM Node.
310:             * The method evaluates the first predicate in a special way and
311:             * then forwards to a general predicate processing method.
312:             */
313:            private static NodePointer doStepPredicatesStandard(
314:                    EvalContext context, NodePointer parent, Step[] steps,
315:                    int currentStep) {
316:                Step step = steps[currentStep];
317:                Expression predicates[] = step.getPredicates();
318:
319:                int axis = step.getAxis();
320:                if (axis == Compiler.AXIS_SELF) {
321:                    return doPredicate(context, parent, steps, currentStep,
322:                            predicates, 0);
323:                }
324:
325:                Expression predicate = predicates[0];
326:
327:                // Optimize for a single predicate to avoid building a list
328:                // and to allow the direct access to the index'th element
329:                // in the case of a simple subscript predecate
330:                // It is a very common use case, so it deserves individual
331:                // attention
332:                if (predicates.length == 1) {
333:                    NodeIterator it = getNodeIterator(context, parent, step);
334:                    NodePointer pointer = null;
335:                    if (it != null) {
336:                        if (predicate instanceof  NameAttributeTest) { // [@name = key]
337:                            String key = keyFromPredicate(context, predicate);
338:                            for (int i = 1; it.setPosition(i); i++) {
339:                                NodePointer ptr = it.getNodePointer();
340:                                if (isNameAttributeEqual(ptr, key)) {
341:                                    pointer = ptr;
342:                                    break;
343:                                }
344:                            }
345:                        } else {
346:                            int index = indexFromPredicate(context, predicate);
347:                            if (it.setPosition(index + 1)) {
348:                                pointer = it.getNodePointer();
349:                            }
350:                        }
351:                    }
352:                    if (pointer != null) {
353:                        return doStep(context, pointer, steps, currentStep + 1);
354:                    }
355:                } else {
356:                    NodeIterator it = getNodeIterator(context, parent, step);
357:                    if (it != null) {
358:                        List list = new ArrayList();
359:                        for (int i = 1; it.setPosition(i); i++) {
360:                            list.add(it.getNodePointer());
361:                        }
362:                        NodePointer pointer = doPredicatesStandard(context,
363:                                list, steps, currentStep, predicates, 0);
364:                        if (pointer != null) {
365:                            return pointer;
366:                        }
367:                    }
368:                }
369:                return createNullPointer(context, parent, steps, currentStep);
370:            }
371:
372:            /**
373:             * Evaluates predicates and proceeds with the subsequent steps
374:             * of the path.
375:             */
376:            private static NodePointer doPredicate(EvalContext context,
377:                    NodePointer parent, Step[] steps, int currentStep,
378:                    Expression predicates[], int currentPredicate) {
379:                if (currentPredicate == predicates.length) {
380:                    return doStep(context, parent, steps, currentStep + 1);
381:                }
382:
383:                Expression predicate = predicates[currentPredicate];
384:                if (predicate instanceof  NameAttributeTest) { // [@name = key1]
385:                    return doPredicateName(context, parent, steps, currentStep,
386:                            predicates, currentPredicate);
387:                } else { // [index]
388:                    return doPredicateIndex(context, parent, steps,
389:                            currentStep, predicates, currentPredicate);
390:                }
391:            }
392:
393:            private static NodePointer doPredicateName(EvalContext context,
394:                    NodePointer parent, Step[] steps, int currentStep,
395:                    Expression[] predicates, int currentPredicate) {
396:                Expression predicate = predicates[currentPredicate];
397:                String key = keyFromPredicate(context, predicate);
398:                NodePointer child = valuePointer(parent);
399:                if (child instanceof  PropertyOwnerPointer) {
400:                    PropertyPointer pointer = ((PropertyOwnerPointer) child)
401:                            .getPropertyPointer();
402:                    pointer.setPropertyName(key);
403:                    if (pointer.isActual()) {
404:                        return doPredicate(context, pointer, steps,
405:                                currentStep, predicates, currentPredicate + 1);
406:                    }
407:                } else if (child.isCollection()) {
408:                    // For each node in the collection, perform the following:
409:                    // if the node is a property owner, apply this predicate to it;
410:                    // if the node is a collection, apply this predicate to each elem.;
411:                    // if the node is not a prop owner or a collection,
412:                    //  see if it has the attribute "name" with the right value,
413:                    //  if so - proceed to the next predicate
414:                    NodePointer bestMatch = null;
415:                    int bestQuality = 0;
416:                    child = (NodePointer) child.clone();
417:                    int count = child.getLength();
418:                    for (int i = 0; i < count; i++) {
419:                        child.setIndex(i);
420:                        NodePointer valuePointer = valuePointer(child);
421:                        NodePointer pointer;
422:                        if ((valuePointer instanceof  PropertyOwnerPointer)
423:                                || valuePointer.isCollection()) {
424:                            pointer = doPredicateName(context, valuePointer,
425:                                    steps, currentStep, predicates,
426:                                    currentPredicate);
427:                        } else if (isNameAttributeEqual(valuePointer, key)) {
428:                            pointer = doPredicate(context, valuePointer, steps,
429:                                    currentStep, predicates,
430:                                    currentPredicate + 1);
431:                        } else {
432:                            pointer = null;
433:                        }
434:                        if (pointer != null) {
435:                            int quality = computeQuality(pointer);
436:                            if (quality == PERFECT_MATCH) {
437:                                return pointer;
438:                            }
439:                            if (quality > bestQuality) {
440:                                bestMatch = (NodePointer) pointer.clone();
441:                                bestQuality = quality;
442:                            }
443:                        }
444:                    }
445:                    if (bestMatch != null) {
446:                        return bestMatch;
447:                    }
448:                } else {
449:                    // If the node is a standard InfoSet node (e.g. DOM Node),
450:                    // employ doPredicates_standard, which will iterate through
451:                    // the node's children and apply all predicates
452:                    NodePointer found = doPredicatesStandard(context,
453:                            Collections.singletonList(child), steps,
454:                            currentStep, predicates, currentPredicate);
455:                    if (found != null) {
456:                        return found;
457:                    }
458:                }
459:                // If nothing worked - return a null pointer
460:                return createNullPointerForPredicates(context, child, steps,
461:                        currentStep, predicates, currentPredicate);
462:            }
463:
464:            /**
465:             * Called exclusively for standard InfoSet nodes, e.g. DOM nodes
466:             * to evaluate predicate sequences like [@name=...][@name=...][index].
467:             */
468:            private static NodePointer doPredicatesStandard(
469:                    EvalContext context, List parents, Step[] steps,
470:                    int currentStep, Expression predicates[],
471:                    int currentPredicate) {
472:                if (parents.size() == 0) {
473:                    return null;
474:                }
475:
476:                // If all predicates have been processed, take the first
477:                // element from the list of results and proceed to the
478:                // remaining steps with that element.
479:                if (currentPredicate == predicates.length) {
480:                    NodePointer pointer = (NodePointer) parents.get(0);
481:                    return doStep(context, pointer, steps, currentStep + 1);
482:                }
483:
484:                Expression predicate = predicates[currentPredicate];
485:                if (predicate instanceof  NameAttributeTest) {
486:                    String key = keyFromPredicate(context, predicate);
487:                    List newList = new ArrayList();
488:                    for (int i = 0; i < parents.size(); i++) {
489:                        NodePointer pointer = (NodePointer) parents.get(i);
490:                        if (isNameAttributeEqual(pointer, key)) {
491:                            newList.add(pointer);
492:                        }
493:                    }
494:                    if (newList.size() == 0) {
495:                        return null;
496:                    }
497:                    return doPredicatesStandard(context, newList, steps,
498:                            currentStep, predicates, currentPredicate + 1);
499:                } else {
500:                    // For a subscript, simply take the corresponding
501:                    // element from the list of results and
502:                    // proceed to the remaining predicates with that element
503:                    int index = indexFromPredicate(context, predicate);
504:                    if (index < 0 || index >= parents.size()) {
505:                        return null;
506:                    }
507:                    NodePointer ptr = (NodePointer) parents.get(index);
508:                    return doPredicate(context, ptr, steps, currentStep,
509:                            predicates, currentPredicate + 1);
510:                }
511:            }
512:
513:            /**
514:             * Evaluate a subscript predicate: see if the node is a collection and
515:             * if the index is inside the collection
516:             */
517:            private static NodePointer doPredicateIndex(EvalContext context,
518:                    NodePointer parent, Step[] steps, int currentStep,
519:                    Expression[] predicates, int currentPredicate) {
520:                Expression predicate = predicates[currentPredicate];
521:                int index = indexFromPredicate(context, predicate);
522:                NodePointer pointer = parent;
523:                if (isCollectionElement(pointer, index)) {
524:                    pointer = (NodePointer) pointer.clone();
525:                    pointer.setIndex(index);
526:                    return doPredicate(context, pointer, steps, currentStep,
527:                            predicates, currentPredicate + 1);
528:                }
529:                return createNullPointerForPredicates(context, parent, steps,
530:                        currentStep, predicates, currentPredicate);
531:            }
532:
533:            /**
534:             * Extract an integer from a subscript predicate. The returned index
535:             * starts with 0, even though the subscript starts with 1.
536:             */
537:            private static int indexFromPredicate(EvalContext context,
538:                    Expression predicate) {
539:                Object value = predicate.computeValue(context);
540:                if (value instanceof  EvalContext) {
541:                    value = ((EvalContext) value).getSingleNodePointer();
542:                }
543:                if (value instanceof  NodePointer) {
544:                    value = ((NodePointer) value).getValue();
545:                }
546:                if (value == null) {
547:                    throw new JXPathException("Predicate value is null");
548:                }
549:
550:                if (value instanceof  Number) {
551:                    return (int) (InfoSetUtil.doubleValue(value) + 0.5) - 1;
552:                } else if (InfoSetUtil.booleanValue(value)) {
553:                    return 0;
554:                }
555:
556:                return -1;
557:            }
558:
559:            /**
560:             * Extracts the string value of the expression from a predicate like
561:             * [@name=expression].
562:             */
563:            private static String keyFromPredicate(EvalContext context,
564:                    Expression predicate) {
565:                Expression expr = ((NameAttributeTest) predicate)
566:                        .getNameTestExpression();
567:                return InfoSetUtil.stringValue(expr.computeValue(context));
568:            }
569:
570:            /**
571:             * For a pointer that matches an actual node, returns 0.
572:             * For a pointer that does not match an actual node, but whose
573:             * parent pointer does returns -1, etc.
574:             */
575:            private static int computeQuality(NodePointer pointer) {
576:                int quality = PERFECT_MATCH;
577:                while (pointer != null && !pointer.isActual()) {
578:                    quality--;
579:                    pointer = pointer.getImmediateParentPointer();
580:                }
581:                return quality;
582:            }
583:
584:            /**
585:             * Returns true if the pointer has an attribute called "name" and
586:             * its value is equal to the supplied string.
587:             */
588:            private static boolean isNameAttributeEqual(NodePointer pointer,
589:                    String name) {
590:                NodeIterator it = pointer.attributeIterator(QNAME_NAME);
591:                return it != null && it.setPosition(1)
592:                        && name.equals(it.getNodePointer().getValue());
593:            }
594:
595:            /**
596:             * Returns true if the pointer is a collection and the index is
597:             * withing the bounds of the collection.
598:             */
599:            private static boolean isCollectionElement(NodePointer pointer,
600:                    int index) {
601:                return pointer.isActual()
602:                        && (index == 0 || (pointer.isCollection() && index >= 0 && index < pointer
603:                                .getLength()));
604:            }
605:
606:            /**
607:             * For an intermediate pointer (e.g. PropertyPointer, ContainerPointer)
608:             * returns a pointer for the contained value.
609:             */
610:            private static NodePointer valuePointer(NodePointer pointer) {
611:                return pointer == null ? null : pointer.getValuePointer();
612:            }
613:
614:            /**
615:             * Creates a "null pointer" that
616:             * a) represents the requested path and
617:             * b) can be used for creation of missing nodes in the path.
618:             */
619:            public static NodePointer createNullPointer(EvalContext context,
620:                    NodePointer parent, Step[] steps, int currentStep) {
621:                if (currentStep == steps.length) {
622:                    return parent;
623:                }
624:
625:                parent = valuePointer(parent);
626:
627:                Step step = steps[currentStep];
628:
629:                int axis = step.getAxis();
630:                if (axis == Compiler.AXIS_CHILD
631:                        || axis == Compiler.AXIS_ATTRIBUTE) {
632:                    NullPropertyPointer pointer = new NullPropertyPointer(
633:                            parent);
634:                    QName name = ((NodeNameTest) step.getNodeTest())
635:                            .getNodeName();
636:                    pointer.setPropertyName(name.toString());
637:                    pointer.setAttribute(axis == Compiler.AXIS_ATTRIBUTE);
638:                    parent = pointer;
639:                }
640:                // else { it is self::node() }
641:
642:                Expression predicates[] = step.getPredicates();
643:                return createNullPointerForPredicates(context, parent, steps,
644:                        currentStep, predicates, 0);
645:            }
646:
647:            /**
648:             * Creates a "null pointer" that starts with predicates.
649:             */
650:            private static NodePointer createNullPointerForPredicates(
651:                    EvalContext context, NodePointer parent, Step[] steps,
652:                    int currentStep, Expression predicates[],
653:                    int currentPredicate) {
654:                for (int i = currentPredicate; i < predicates.length; i++) {
655:                    Expression predicate = predicates[i];
656:                    if (predicate instanceof  NameAttributeTest) {
657:                        String key = keyFromPredicate(context, predicate);
658:                        parent = valuePointer(parent);
659:                        NullPropertyPointer pointer = new NullPropertyPointer(
660:                                parent);
661:                        pointer.setNameAttributeValue(key);
662:                        parent = pointer;
663:                    } else {
664:                        int index = indexFromPredicate(context, predicate);
665:                        if (parent instanceof  NullPropertyPointer) {
666:                            parent.setIndex(index);
667:                        } else {
668:                            parent = new NullElementPointer(parent, index);
669:                        }
670:                    }
671:                }
672:                // Proceed with the remaining steps
673:                return createNullPointer(context, parent, steps,
674:                        currentStep + 1);
675:            }
676:
677:            private static NodeIterator getNodeIterator(EvalContext context,
678:                    NodePointer pointer, Step step) {
679:                if (step.getAxis() == Compiler.AXIS_CHILD) {
680:                    NodeTest nodeTest = step.getNodeTest();
681:                    QName qname = ((NodeNameTest) nodeTest).getNodeName();
682:                    String prefix = qname.getPrefix();
683:                    if (prefix != null) {
684:                        String namespaceURI = context.getJXPathContext()
685:                                .getNamespaceURI(prefix);
686:                        nodeTest = new NodeNameTest(qname, namespaceURI);
687:
688:                    }
689:                    return pointer.childIterator(nodeTest, false, null);
690:                } else { // Compiler.AXIS_ATTRIBUTE
691:                    if (!(step.getNodeTest() instanceof  NodeNameTest)) {
692:                        throw new UnsupportedOperationException(
693:                                "Not supported node test for attributes: "
694:                                        + step.getNodeTest());
695:                    }
696:                    return pointer.attributeIterator(((NodeNameTest) step
697:                            .getNodeTest()).getNodeName());
698:                }
699:            }
700:
701:            private static boolean isLangAttribute(QName name) {
702:                return name.getPrefix() != null
703:                        && name.getPrefix().equals("xml")
704:                        && name.getName().equals("lang");
705:            }
706:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.