Source Code Cross Referenced for XPath.java in  » XML » xerces-2_9_1 » org » apache » xerces » impl » xpath » 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 » XML » xerces 2_9_1 » org.apache.xerces.impl.xpath 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        package org.apache.xerces.impl.xpath;
0019:
0020:        import java.util.ArrayList;
0021:        import java.util.Vector;
0022:
0023:        import org.apache.xerces.util.SymbolTable;
0024:        import org.apache.xerces.util.XMLChar;
0025:        import org.apache.xerces.util.XMLSymbols;
0026:        import org.apache.xerces.xni.NamespaceContext;
0027:        import org.apache.xerces.xni.QName;
0028:
0029:        /**
0030:         * Bare minimum XPath parser.
0031:         * 
0032:         * @xerces.internal
0033:         *
0034:         * @author Andy Clark, IBM
0035:         * @version $Id: XPath.java 572107 2007-09-02 18:40:40Z mrglavas $
0036:         */
0037:        public class XPath {
0038:
0039:            //
0040:            // Constants
0041:            //
0042:
0043:            private static final boolean DEBUG_ALL = false;
0044:
0045:            private static final boolean DEBUG_XPATH_PARSE = DEBUG_ALL || false;
0046:
0047:            private static final boolean DEBUG_ANY = DEBUG_XPATH_PARSE;
0048:
0049:            //
0050:            // Data
0051:            //
0052:
0053:            /** Expression. */
0054:            protected final String fExpression;
0055:
0056:            /** Symbol table. */
0057:            protected final SymbolTable fSymbolTable;
0058:
0059:            /** Location paths. */
0060:            protected final LocationPath[] fLocationPaths;
0061:
0062:            //
0063:            // Constructors
0064:            //
0065:
0066:            /** Constructs an XPath object from the specified expression. */
0067:            public XPath(String xpath, SymbolTable symbolTable,
0068:                    NamespaceContext context) throws XPathException {
0069:                fExpression = xpath;
0070:                fSymbolTable = symbolTable;
0071:                fLocationPaths = parseExpression(context);
0072:                if (DEBUG_XPATH_PARSE) {
0073:                    System.out.println(">>> " + fLocationPaths);
0074:                }
0075:            } // <init>(String,SymbolTable,NamespaceContext)
0076:
0077:            //
0078:            // Public methods
0079:            //
0080:
0081:            /**
0082:             * Returns a representation of all location paths for this XPath.
0083:             * XPath = locationPath ( '|' locationPath)
0084:             */
0085:            public LocationPath[] getLocationPaths() {
0086:                LocationPath[] ret = new LocationPath[fLocationPaths.length];
0087:                for (int i = 0; i < fLocationPaths.length; i++) {
0088:                    ret[i] = (LocationPath) fLocationPaths[i].clone();
0089:                }
0090:                return ret;
0091:            } // getLocationPath(LocationPath)
0092:
0093:            /** Returns a representation of the first location path for this XPath. */
0094:            public LocationPath getLocationPath() {
0095:                return (LocationPath) fLocationPaths[0].clone();
0096:            } // getLocationPath(LocationPath)
0097:
0098:            //
0099:            // Object methods
0100:            //
0101:
0102:            /** Returns a string representation of this object. */
0103:            public String toString() {
0104:                StringBuffer buf = new StringBuffer();
0105:                for (int i = 0; i < fLocationPaths.length; i++) {
0106:                    if (i > 0) {
0107:                        buf.append("|");
0108:                    }
0109:                    buf.append(fLocationPaths[i].toString());
0110:                }
0111:                return buf.toString();
0112:            } // toString():String
0113:
0114:            //
0115:            // Private methods
0116:            //
0117:
0118:            /**
0119:             * Used by the {@link #parseExpression(NamespaceContext)} method
0120:             * to verify the assumption.
0121:             * 
0122:             * If <tt>b</tt> is false, this method throws XPathException
0123:             * to report the error.
0124:             */
0125:            private static void check(boolean b) throws XPathException {
0126:                if (!b)
0127:                    throw new XPathException("c-general-xpath");
0128:            }
0129:
0130:            /**
0131:             * Used by the {@link #parseExpression(NamespaceContext)} method
0132:             * to build a {@link LocationPath} object from the accumulated
0133:             * {@link Step}s.
0134:             */
0135:            private LocationPath buildLocationPath(Vector stepsVector)
0136:                    throws XPathException {
0137:                int size = stepsVector.size();
0138:                check(size != 0);
0139:                Step[] steps = new Step[size];
0140:                stepsVector.copyInto(steps);
0141:                stepsVector.removeAllElements();
0142:
0143:                return new LocationPath(steps);
0144:            }
0145:
0146:            /**
0147:             * This method is implemented by using the XPathExprScanner and
0148:             * examining the list of tokens that it returns.
0149:             */
0150:            private LocationPath[] parseExpression(
0151:                    final NamespaceContext context) throws XPathException {
0152:
0153:                // tokens
0154:                final XPath.Tokens xtokens = new XPath.Tokens(fSymbolTable);
0155:
0156:                // scanner
0157:                XPath.Scanner scanner = new XPath.Scanner(fSymbolTable) {
0158:                    protected void addToken(XPath.Tokens tokens, int token)
0159:                            throws XPathException {
0160:                        if (token == XPath.Tokens.EXPRTOKEN_ATSIGN
0161:                                || token == XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME
0162:                                || token == XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH
0163:                                || token == XPath.Tokens.EXPRTOKEN_PERIOD
0164:                                || token == XPath.Tokens.EXPRTOKEN_NAMETEST_ANY
0165:                                || token == XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE
0166:                                || token == XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH
0167:                                || token == XPath.Tokens.EXPRTOKEN_OPERATOR_UNION
0168:                                || token == XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD
0169:                                || token == XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE
0170:                                || token == XPath.Tokens.EXPRTOKEN_DOUBLE_COLON
0171:                        //
0172:                        ) {
0173:                            super .addToken(tokens, token);
0174:                            return;
0175:                        }
0176:                        throw new XPathException("c-general-xpath");
0177:                    }
0178:                };
0179:
0180:                int length = fExpression.length();
0181:
0182:                boolean success = scanner.scanExpr(fSymbolTable, xtokens,
0183:                        fExpression, 0, length);
0184:                if (!success)
0185:                    throw new XPathException("c-general-xpath");
0186:
0187:                //fTokens.dumpTokens();
0188:                Vector stepsVector = new Vector();
0189:                ArrayList locationPathsVector = new ArrayList();
0190:
0191:                // true when the next token should be 'Step' (as defined in
0192:                // the production rule [3] of XML Schema P1 section 3.11.6
0193:                // if false, we are expecting either '|' or '/'.
0194:                //
0195:                // this is to make sure we can detect a token list like
0196:                // 'abc' '/' '/' 'def' 'ghi'
0197:                boolean expectingStep = true;
0198:
0199:                while (xtokens.hasMore()) {
0200:                    final int token = xtokens.nextToken();
0201:
0202:                    switch (token) {
0203:                    case XPath.Tokens.EXPRTOKEN_OPERATOR_UNION: {
0204:                        check(!expectingStep);
0205:                        locationPathsVector.add(buildLocationPath(stepsVector));
0206:                        expectingStep = true;
0207:                        break;
0208:                    }
0209:                    case XPath.Tokens.EXPRTOKEN_ATSIGN: {
0210:                        check(expectingStep);
0211:                        Step step = new Step(new Axis(Axis.ATTRIBUTE),
0212:                                parseNodeTest(xtokens.nextToken(), xtokens,
0213:                                        context));
0214:                        stepsVector.addElement(step);
0215:                        expectingStep = false;
0216:                        break;
0217:                    }
0218:                    case XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE: {
0219:                        check(expectingStep);
0220:                        // If we got here we're expecting attribute::
0221:                        if (xtokens.nextToken() != XPath.Tokens.EXPRTOKEN_DOUBLE_COLON) {
0222:                            throw new XPathException("c-general-xpath");
0223:                        }
0224:                        Step step = new Step(new Axis(Axis.ATTRIBUTE),
0225:                                parseNodeTest(xtokens.nextToken(), xtokens,
0226:                                        context));
0227:                        stepsVector.addElement(step);
0228:                        expectingStep = false;
0229:                        break;
0230:                    }
0231:                    case XPath.Tokens.EXPRTOKEN_NAMETEST_ANY:
0232:                    case XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE:
0233:                    case XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME: {
0234:                        check(expectingStep);
0235:                        Step step = new Step(new Axis(Axis.CHILD),
0236:                                parseNodeTest(token, xtokens, context));
0237:                        stepsVector.addElement(step);
0238:                        expectingStep = false;
0239:                        break;
0240:                    }
0241:                    case XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD: {
0242:                        check(expectingStep);
0243:                        // If we got here we're expecting child::
0244:                        if (xtokens.nextToken() != XPath.Tokens.EXPRTOKEN_DOUBLE_COLON) {
0245:                            throw new XPathException("c-general-xpath");
0246:                        }
0247:                        Step step = new Step(new Axis(Axis.CHILD),
0248:                                parseNodeTest(xtokens.nextToken(), xtokens,
0249:                                        context));
0250:                        stepsVector.addElement(step);
0251:                        expectingStep = false;
0252:                        break;
0253:                    }
0254:                    case XPath.Tokens.EXPRTOKEN_PERIOD: {
0255:                        check(expectingStep);
0256:                        expectingStep = false;
0257:
0258:                        // unless this is the first step in this location path,
0259:                        // there's really no reason to keep them in LocationPath.
0260:                        // This amounts to shorten "a/././b/./c" to "a/b/c".
0261:                        // Also, the matcher fails to work correctly if XPath
0262:                        // has those redundant dots. 
0263:                        if (stepsVector.size() == 0) {
0264:                            // build step
0265:                            Axis axis = new Axis(Axis.SELF);
0266:                            NodeTest nodeTest = new NodeTest(NodeTest.NODE);
0267:                            Step step = new Step(axis, nodeTest);
0268:                            stepsVector.addElement(step);
0269:
0270:                            if (xtokens.hasMore()
0271:                                    && xtokens.peekToken() == XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH) {
0272:                                // consume '//'
0273:                                xtokens.nextToken();
0274:
0275:                                // build step
0276:                                axis = new Axis(Axis.DESCENDANT);
0277:                                nodeTest = new NodeTest(NodeTest.NODE);
0278:                                step = new Step(axis, nodeTest);
0279:                                stepsVector.addElement(step);
0280:                                expectingStep = true;
0281:                            }
0282:                        }
0283:                        break;
0284:                    }
0285:                    case XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH: {
0286:                        // this cannot appear in an arbitrary position.
0287:                        // it is only allowed right after '.' when
0288:                        // '.' is the first token of a location path.
0289:                        throw new XPathException("c-general-xpath");
0290:                    }
0291:                    case XPath.Tokens.EXPRTOKEN_DOUBLE_COLON: {
0292:                        // :: cannot appear in an arbitrary position.
0293:                        // We only expect this token if the xpath
0294:                        // contains child:: or attribute::
0295:                        throw new XPathException("c-general-xpath");
0296:                    }
0297:                    case XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH: {
0298:                        check(!expectingStep);
0299:                        expectingStep = true;
0300:                        break;
0301:                    }
0302:                    default:
0303:                        // we should have covered all the tokens that we can possibly see. 
0304:                        throw new InternalError();
0305:                    }
0306:                }
0307:
0308:                check(!expectingStep);
0309:
0310:                locationPathsVector.add(buildLocationPath(stepsVector));
0311:
0312:                // return location path
0313:                return (LocationPath[]) locationPathsVector
0314:                        .toArray(new LocationPath[locationPathsVector.size()]);
0315:
0316:            } // parseExpression(SymbolTable,NamespaceContext)
0317:
0318:            /**
0319:             * Used by {@link #parseExpression} to parse a node test
0320:             * from the token list.
0321:             */
0322:            private NodeTest parseNodeTest(int typeToken, Tokens xtokens,
0323:                    NamespaceContext context) throws XPathException {
0324:                switch (typeToken) {
0325:                case XPath.Tokens.EXPRTOKEN_NAMETEST_ANY:
0326:                    return new NodeTest(NodeTest.WILDCARD);
0327:
0328:                case XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE:
0329:                case XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME:
0330:                    // consume QName token
0331:                    String prefix = xtokens.nextTokenAsString();
0332:                    String uri = null;
0333:                    if (context != null && prefix != XMLSymbols.EMPTY_STRING) {
0334:                        uri = context.getURI(prefix);
0335:                    }
0336:                    if (prefix != XMLSymbols.EMPTY_STRING && context != null
0337:                            && uri == null) {
0338:                        throw new XPathException("c-general-xpath-ns");
0339:                    }
0340:
0341:                    if (typeToken == XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE)
0342:                        return new NodeTest(prefix, uri);
0343:
0344:                    String localpart = xtokens.nextTokenAsString();
0345:                    String rawname = prefix != XMLSymbols.EMPTY_STRING ? fSymbolTable
0346:                            .addSymbol(prefix + ':' + localpart)
0347:                            : localpart;
0348:
0349:                    return new NodeTest(new QName(prefix, localpart, rawname,
0350:                            uri));
0351:
0352:                default:
0353:                    throw new XPathException("c-general-xpath");
0354:                }
0355:            }
0356:
0357:            //
0358:            // Classes
0359:            //
0360:
0361:            // location path information
0362:
0363:            /**
0364:             * A location path representation for an XPath expression.
0365:             * 
0366:             * @xerces.internal
0367:             *
0368:             * @author Andy Clark, IBM
0369:             */
0370:            public static class LocationPath implements  Cloneable {
0371:
0372:                //
0373:                // Data
0374:                //
0375:
0376:                /** List of steps. */
0377:                public final Step[] steps;
0378:
0379:                //
0380:                // Constructors
0381:                //
0382:
0383:                /** Creates a location path from a series of steps. */
0384:                public LocationPath(Step[] steps) {
0385:                    this .steps = steps;
0386:                } // <init>(Step[])
0387:
0388:                /** Copy constructor. */
0389:                protected LocationPath(LocationPath path) {
0390:                    steps = new Step[path.steps.length];
0391:                    for (int i = 0; i < steps.length; i++) {
0392:                        steps[i] = (Step) path.steps[i].clone();
0393:                    }
0394:                } // <init>(LocationPath)
0395:
0396:                //
0397:                // Object methods
0398:                //
0399:
0400:                /** Returns a string representation of this object. */
0401:                public String toString() {
0402:                    StringBuffer str = new StringBuffer();
0403:                    for (int i = 0; i < steps.length; i++) {
0404:                        if (i > 0
0405:                                && (steps[i - 1].axis.type != Axis.DESCENDANT && steps[i].axis.type != Axis.DESCENDANT)) {
0406:                            str.append('/');
0407:                        }
0408:                        str.append(steps[i].toString());
0409:                    }
0410:                    // DEBUG: This code is just for debugging and should *not*
0411:                    //        be left in because it will mess up hashcodes of
0412:                    //        serialized versions of this object. -Ac
0413:                    if (false) {
0414:                        str.append('[');
0415:                        String s = super .toString();
0416:                        str.append(s.substring(s.indexOf('@')));
0417:                        str.append(']');
0418:                    }
0419:                    return str.toString();
0420:                } // toString():String
0421:
0422:                /** Returns a clone of this object. */
0423:                public Object clone() {
0424:                    return new LocationPath(this );
0425:                } // clone():Object
0426:
0427:            } // class locationPath
0428:
0429:            /**
0430:             * A location path step comprised of an axis and node test.
0431:             * 
0432:             * @xerces.internal
0433:             *
0434:             * @author Andy Clark, IBM
0435:             */
0436:            public static class Step implements  Cloneable {
0437:
0438:                //
0439:                // Data
0440:                //
0441:
0442:                /** Axis. */
0443:                public final Axis axis;
0444:
0445:                /** Node test. */
0446:                public final NodeTest nodeTest;
0447:
0448:                //
0449:                // Constructors
0450:                //
0451:
0452:                /** Constructs a step from an axis and node test. */
0453:                public Step(Axis axis, NodeTest nodeTest) {
0454:                    this .axis = axis;
0455:                    this .nodeTest = nodeTest;
0456:                } // <init>(Axis,NodeTest)
0457:
0458:                /** Copy constructor. */
0459:                protected Step(Step step) {
0460:                    axis = (Axis) step.axis.clone();
0461:                    nodeTest = (NodeTest) step.nodeTest.clone();
0462:                } // <init>(Step)
0463:
0464:                //
0465:                // Object methods
0466:                //
0467:
0468:                /** Returns a string representation of this object. */
0469:                public String toString() {
0470:                    if (axis.type == Axis.SELF) {
0471:                        return ".";
0472:                    }
0473:                    if (axis.type == Axis.ATTRIBUTE) {
0474:                        return "@" + nodeTest.toString();
0475:                    }
0476:                    if (axis.type == Axis.CHILD) {
0477:                        return nodeTest.toString();
0478:                    }
0479:                    if (axis.type == Axis.DESCENDANT) {
0480:                        return "//";
0481:                    }
0482:                    return "??? (" + axis.type + ')';
0483:                } // toString():String
0484:
0485:                /** Returns a clone of this object. */
0486:                public Object clone() {
0487:                    return new Step(this );
0488:                } // clone():Object
0489:
0490:            } // class Step
0491:
0492:            /**
0493:             * Axis.
0494:             * 
0495:             * @xerces.internal
0496:             *
0497:             * @author Andy Clark, IBM
0498:             */
0499:            public static class Axis implements  Cloneable {
0500:
0501:                //
0502:                // Constants
0503:                //
0504:
0505:                /** Type: child. */
0506:                public static final short CHILD = 1;
0507:
0508:                /** Type: attribute. */
0509:                public static final short ATTRIBUTE = 2;
0510:
0511:                /** Type: self. */
0512:                public static final short SELF = 3;
0513:
0514:                /** Type: descendant. */
0515:                public static final short DESCENDANT = 4;
0516:                //
0517:                // Data
0518:                //
0519:
0520:                /** Axis type. */
0521:                public final short type;
0522:
0523:                //
0524:                // Constructors
0525:                //
0526:
0527:                /** Constructs an axis with the specified type. */
0528:                public Axis(short type) {
0529:                    this .type = type;
0530:                } // <init>(short)
0531:
0532:                /** Copy constructor. */
0533:                protected Axis(Axis axis) {
0534:                    type = axis.type;
0535:                } // <init>(Axis)
0536:
0537:                //
0538:                // Object methods
0539:                //
0540:
0541:                /** Returns a string representation of this object. */
0542:                public String toString() {
0543:                    switch (type) {
0544:                    case CHILD:
0545:                        return "child";
0546:                    case ATTRIBUTE:
0547:                        return "attribute";
0548:                    case SELF:
0549:                        return "self";
0550:                    case DESCENDANT:
0551:                        return "descendant";
0552:                    }
0553:                    return "???";
0554:                } // toString():String
0555:
0556:                /** Returns a clone of this object. */
0557:                public Object clone() {
0558:                    return new Axis(this );
0559:                } // clone():Object
0560:
0561:            } // class Axis
0562:
0563:            /**
0564:             * Node test.
0565:             * 
0566:             * @xerces.internal
0567:             *
0568:             * @author Andy Clark, IBM
0569:             */
0570:            public static class NodeTest implements  Cloneable {
0571:
0572:                //
0573:                // Constants
0574:                //
0575:
0576:                /** Type: qualified name. */
0577:                public static final short QNAME = 1;
0578:
0579:                /** Type: wildcard. */
0580:                public static final short WILDCARD = 2;
0581:
0582:                /** Type: node. */
0583:                public static final short NODE = 3;
0584:
0585:                /** Type: namespace */
0586:                public static final short NAMESPACE = 4;
0587:
0588:                //
0589:                // Data
0590:                //
0591:
0592:                /** Node test type. */
0593:                public final short type;
0594:
0595:                /** Node qualified name. */
0596:                public final QName name = new QName();
0597:
0598:                //
0599:                // Constructors
0600:                //
0601:
0602:                /** Constructs a node test of type WILDCARD or NODE. */
0603:                public NodeTest(short type) {
0604:                    this .type = type;
0605:                } // <init>(int)
0606:
0607:                /** Constructs a node test of type QName. */
0608:                public NodeTest(QName name) {
0609:                    this .type = QNAME;
0610:                    this .name.setValues(name);
0611:                } // <init>(QName)
0612:
0613:                /** Constructs a node test of type Namespace. */
0614:                public NodeTest(String prefix, String uri) {
0615:                    this .type = NAMESPACE;
0616:                    this .name.setValues(prefix, null, null, uri);
0617:                } // <init>(String,String)
0618:
0619:                /** Copy constructor. */
0620:                public NodeTest(NodeTest nodeTest) {
0621:                    type = nodeTest.type;
0622:                    name.setValues(nodeTest.name);
0623:                } // <init>(NodeTest)
0624:
0625:                //
0626:                // Object methods
0627:                //
0628:
0629:                /** Returns a string representation of this object. */
0630:                public String toString() {
0631:
0632:                    switch (type) {
0633:                    case QNAME: {
0634:                        if (name.prefix.length() != 0) {
0635:                            if (name.uri != null) {
0636:                                return name.prefix + ':' + name.localpart;
0637:                            }
0638:                            return "{" + name.uri + '}' + name.prefix + ':'
0639:                                    + name.localpart;
0640:                        }
0641:                        return name.localpart;
0642:                    }
0643:                    case NAMESPACE: {
0644:                        if (name.prefix.length() != 0) {
0645:                            if (name.uri != null) {
0646:                                return name.prefix + ":*";
0647:                            }
0648:                            return "{" + name.uri + '}' + name.prefix + ":*";
0649:                        }
0650:                        return "???:*";
0651:                    }
0652:                    case WILDCARD: {
0653:                        return "*";
0654:                    }
0655:                    case NODE: {
0656:                        return "node()";
0657:                    }
0658:                    }
0659:                    return "???";
0660:
0661:                } // toString():String
0662:
0663:                /** Returns a clone of this object. */
0664:                public Object clone() {
0665:                    return new NodeTest(this );
0666:                } // clone():Object
0667:
0668:            } // class NodeTest
0669:
0670:            // xpath implementation
0671:
0672:            // NOTE: The XPath implementation classes are kept internal because
0673:            //       this implementation is just a temporary hack until a better
0674:            //       and/or more appropriate implementation can be written.
0675:            //       keeping the code in separate source files would "muddy" the
0676:            //       CVS directory when it's not needed. -Ac
0677:
0678:            /**
0679:             * List of tokens.
0680:             * 
0681:             * @xerces.internal
0682:             * 
0683:             * @author Glenn Marcy, IBM
0684:             * @author Andy Clark, IBM
0685:             *
0686:             * @version $Id: XPath.java 572107 2007-09-02 18:40:40Z mrglavas $
0687:             */
0688:            private static final class Tokens {
0689:
0690:                static final boolean DUMP_TOKENS = false;
0691:
0692:                /**
0693:                 * [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::'
0694:                 *                  | NameTest | NodeType | Operator | FunctionName
0695:                 *                  | AxisName | Literal | Number | VariableReference
0696:                 */
0697:                public static final int EXPRTOKEN_OPEN_PAREN = 0,
0698:                        EXPRTOKEN_CLOSE_PAREN = 1,
0699:                        EXPRTOKEN_OPEN_BRACKET = 2,
0700:                        EXPRTOKEN_CLOSE_BRACKET = 3,
0701:                        EXPRTOKEN_PERIOD = 4,
0702:                        EXPRTOKEN_DOUBLE_PERIOD = 5,
0703:                        EXPRTOKEN_ATSIGN = 6,
0704:                        EXPRTOKEN_COMMA = 7,
0705:                        EXPRTOKEN_DOUBLE_COLON = 8,
0706:                        //
0707:                        // [37] NameTest ::= '*' | NCName ':' '*' | QName
0708:                        //
0709:                        // followed by symbol handle of NCName or QName
0710:                        //
0711:                        EXPRTOKEN_NAMETEST_ANY = 9,
0712:                        EXPRTOKEN_NAMETEST_NAMESPACE = 10,
0713:                        EXPRTOKEN_NAMETEST_QNAME = 11,
0714:                        //
0715:                        // [38] NodeType ::= 'comment' | 'text' | 'processing-instruction' | 'node'
0716:                        //
0717:                        EXPRTOKEN_NODETYPE_COMMENT = 12,
0718:                        EXPRTOKEN_NODETYPE_TEXT = 13,
0719:                        EXPRTOKEN_NODETYPE_PI = 14,
0720:                        EXPRTOKEN_NODETYPE_NODE = 15,
0721:                        //
0722:                        // [32] Operator ::= OperatorName
0723:                        //                 | MultiplyOperator
0724:                        //                 | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>='
0725:                        // [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div'
0726:                        // [34] MultiplyOperator ::= '*'
0727:                        //
0728:                        EXPRTOKEN_OPERATOR_AND = 16,
0729:                        EXPRTOKEN_OPERATOR_OR = 17,
0730:                        EXPRTOKEN_OPERATOR_MOD = 18,
0731:                        EXPRTOKEN_OPERATOR_DIV = 19,
0732:                        EXPRTOKEN_OPERATOR_MULT = 20,
0733:                        EXPRTOKEN_OPERATOR_SLASH = 21,
0734:                        EXPRTOKEN_OPERATOR_DOUBLE_SLASH = 22,
0735:                        EXPRTOKEN_OPERATOR_UNION = 23,
0736:                        EXPRTOKEN_OPERATOR_PLUS = 24,
0737:                        EXPRTOKEN_OPERATOR_MINUS = 25,
0738:                        EXPRTOKEN_OPERATOR_EQUAL = 26,
0739:                        EXPRTOKEN_OPERATOR_NOT_EQUAL = 27,
0740:                        EXPRTOKEN_OPERATOR_LESS = 28,
0741:                        EXPRTOKEN_OPERATOR_LESS_EQUAL = 29,
0742:                        EXPRTOKEN_OPERATOR_GREATER = 30,
0743:                        EXPRTOKEN_OPERATOR_GREATER_EQUAL = 31,
0744:
0745:                        //EXPRTOKEN_FIRST_OPERATOR                = EXPRTOKEN_OPERATOR_AND,
0746:                        //EXPRTOKEN_LAST_OPERATOR                 = EXPRTOKEN_OPERATOR_GREATER_EQUAL,
0747:
0748:                        //
0749:                        // [35] FunctionName ::= QName - NodeType
0750:                        //
0751:                        // followed by symbol handle
0752:                        //
0753:                        EXPRTOKEN_FUNCTION_NAME = 32,
0754:                        //
0755:                        // [6] AxisName ::= 'ancestor' | 'ancestor-or-self'
0756:                        //                | 'attribute'
0757:                        //                | 'child'
0758:                        //                | 'descendant' | 'descendant-or-self'
0759:                        //                | 'following' | 'following-sibling'
0760:                        //                | 'namespace'
0761:                        //                | 'parent'
0762:                        //                | 'preceding' | 'preceding-sibling'
0763:                        //                | 'self'
0764:                        //
0765:                        EXPRTOKEN_AXISNAME_ANCESTOR = 33,
0766:                        EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF = 34,
0767:                        EXPRTOKEN_AXISNAME_ATTRIBUTE = 35,
0768:                        EXPRTOKEN_AXISNAME_CHILD = 36,
0769:                        EXPRTOKEN_AXISNAME_DESCENDANT = 37,
0770:                        EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF = 38,
0771:                        EXPRTOKEN_AXISNAME_FOLLOWING = 39,
0772:                        EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING = 40,
0773:                        EXPRTOKEN_AXISNAME_NAMESPACE = 41,
0774:                        EXPRTOKEN_AXISNAME_PARENT = 42,
0775:                        EXPRTOKEN_AXISNAME_PRECEDING = 43,
0776:                        EXPRTOKEN_AXISNAME_PRECEDING_SIBLING = 44,
0777:                        EXPRTOKEN_AXISNAME_SELF = 45,
0778:                        //
0779:                        // [29] Literal ::= '"' [^"]* '"' | "'" [^']* "'"
0780:                        //
0781:                        // followed by symbol handle for literal
0782:                        //
0783:                        EXPRTOKEN_LITERAL = 46,
0784:                        //
0785:                        // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
0786:                        // [31] Digits ::= [0-9]+
0787:                        //
0788:                        // followed by number handle
0789:                        //
0790:                        EXPRTOKEN_NUMBER = 47,
0791:                        //
0792:                        // [36] VariableReference ::= '$' QName
0793:                        //
0794:                        // followed by symbol handle for QName
0795:                        //
0796:                        EXPRTOKEN_VARIABLE_REFERENCE = 48;
0797:
0798:                private static final String[] fgTokenNames = {
0799:                        "EXPRTOKEN_OPEN_PAREN", "EXPRTOKEN_CLOSE_PAREN",
0800:                        "EXPRTOKEN_OPEN_BRACKET", "EXPRTOKEN_CLOSE_BRACKET",
0801:                        "EXPRTOKEN_PERIOD", "EXPRTOKEN_DOUBLE_PERIOD",
0802:                        "EXPRTOKEN_ATSIGN", "EXPRTOKEN_COMMA",
0803:                        "EXPRTOKEN_DOUBLE_COLON", "EXPRTOKEN_NAMETEST_ANY",
0804:                        "EXPRTOKEN_NAMETEST_NAMESPACE",
0805:                        "EXPRTOKEN_NAMETEST_QNAME",
0806:                        "EXPRTOKEN_NODETYPE_COMMENT",
0807:                        "EXPRTOKEN_NODETYPE_TEXT", "EXPRTOKEN_NODETYPE_PI",
0808:                        "EXPRTOKEN_NODETYPE_NODE", "EXPRTOKEN_OPERATOR_AND",
0809:                        "EXPRTOKEN_OPERATOR_OR", "EXPRTOKEN_OPERATOR_MOD",
0810:                        "EXPRTOKEN_OPERATOR_DIV", "EXPRTOKEN_OPERATOR_MULT",
0811:                        "EXPRTOKEN_OPERATOR_SLASH",
0812:                        "EXPRTOKEN_OPERATOR_DOUBLE_SLASH",
0813:                        "EXPRTOKEN_OPERATOR_UNION", "EXPRTOKEN_OPERATOR_PLUS",
0814:                        "EXPRTOKEN_OPERATOR_MINUS", "EXPRTOKEN_OPERATOR_EQUAL",
0815:                        "EXPRTOKEN_OPERATOR_NOT_EQUAL",
0816:                        "EXPRTOKEN_OPERATOR_LESS",
0817:                        "EXPRTOKEN_OPERATOR_LESS_EQUAL",
0818:                        "EXPRTOKEN_OPERATOR_GREATER",
0819:                        "EXPRTOKEN_OPERATOR_GREATER_EQUAL",
0820:                        "EXPRTOKEN_FUNCTION_NAME",
0821:                        "EXPRTOKEN_AXISNAME_ANCESTOR",
0822:                        "EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF",
0823:                        "EXPRTOKEN_AXISNAME_ATTRIBUTE",
0824:                        "EXPRTOKEN_AXISNAME_CHILD",
0825:                        "EXPRTOKEN_AXISNAME_DESCENDANT",
0826:                        "EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF",
0827:                        "EXPRTOKEN_AXISNAME_FOLLOWING",
0828:                        "EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING",
0829:                        "EXPRTOKEN_AXISNAME_NAMESPACE",
0830:                        "EXPRTOKEN_AXISNAME_PARENT",
0831:                        "EXPRTOKEN_AXISNAME_PRECEDING",
0832:                        "EXPRTOKEN_AXISNAME_PRECEDING_SIBLING",
0833:                        "EXPRTOKEN_AXISNAME_SELF", "EXPRTOKEN_LITERAL",
0834:                        "EXPRTOKEN_NUMBER", "EXPRTOKEN_VARIABLE_REFERENCE" };
0835:
0836:                /**
0837:                 *
0838:                 */
0839:                private static final int INITIAL_TOKEN_COUNT = 1 << 8;
0840:                private int[] fTokens = new int[INITIAL_TOKEN_COUNT];
0841:                private int fTokenCount = 0; // for writing
0842:
0843:                private SymbolTable fSymbolTable;
0844:
0845:                // REVISIT: Code something better here. -Ac
0846:                private java.util.Hashtable fSymbolMapping = new java.util.Hashtable();
0847:
0848:                // REVISIT: Code something better here. -Ac
0849:                private java.util.Hashtable fTokenNames = new java.util.Hashtable();
0850:
0851:                /**
0852:                 * Current position in the token list. 
0853:                 */
0854:                private int fCurrentTokenIndex;
0855:
0856:                //
0857:                // Constructors
0858:                //
0859:
0860:                public Tokens(SymbolTable symbolTable) {
0861:                    fSymbolTable = symbolTable;
0862:                    final String[] symbols = { "ancestor", "ancestor-or-self",
0863:                            "attribute", "child", "descendant",
0864:                            "descendant-or-self", "following",
0865:                            "following-sibling", "namespace", "parent",
0866:                            "preceding", "preceding-sibling", "self", };
0867:                    for (int i = 0; i < symbols.length; i++) {
0868:                        fSymbolMapping.put(fSymbolTable.addSymbol(symbols[i]),
0869:                                new Integer(i));
0870:                    }
0871:                    fTokenNames.put(new Integer(EXPRTOKEN_OPEN_PAREN),
0872:                            "EXPRTOKEN_OPEN_PAREN");
0873:                    fTokenNames.put(new Integer(EXPRTOKEN_CLOSE_PAREN),
0874:                            "EXPRTOKEN_CLOSE_PAREN");
0875:                    fTokenNames.put(new Integer(EXPRTOKEN_OPEN_BRACKET),
0876:                            "EXPRTOKEN_OPEN_BRACKET");
0877:                    fTokenNames.put(new Integer(EXPRTOKEN_CLOSE_BRACKET),
0878:                            "EXPRTOKEN_CLOSE_BRACKET");
0879:                    fTokenNames.put(new Integer(EXPRTOKEN_PERIOD),
0880:                            "EXPRTOKEN_PERIOD");
0881:                    fTokenNames.put(new Integer(EXPRTOKEN_DOUBLE_PERIOD),
0882:                            "EXPRTOKEN_DOUBLE_PERIOD");
0883:                    fTokenNames.put(new Integer(EXPRTOKEN_ATSIGN),
0884:                            "EXPRTOKEN_ATSIGN");
0885:                    fTokenNames.put(new Integer(EXPRTOKEN_COMMA),
0886:                            "EXPRTOKEN_COMMA");
0887:                    fTokenNames.put(new Integer(EXPRTOKEN_DOUBLE_COLON),
0888:                            "EXPRTOKEN_DOUBLE_COLON");
0889:                    fTokenNames.put(new Integer(EXPRTOKEN_NAMETEST_ANY),
0890:                            "EXPRTOKEN_NAMETEST_ANY");
0891:                    fTokenNames.put(new Integer(EXPRTOKEN_NAMETEST_NAMESPACE),
0892:                            "EXPRTOKEN_NAMETEST_NAMESPACE");
0893:                    fTokenNames.put(new Integer(EXPRTOKEN_NAMETEST_QNAME),
0894:                            "EXPRTOKEN_NAMETEST_QNAME");
0895:                    fTokenNames.put(new Integer(EXPRTOKEN_NODETYPE_COMMENT),
0896:                            "EXPRTOKEN_NODETYPE_COMMENT");
0897:                    fTokenNames.put(new Integer(EXPRTOKEN_NODETYPE_TEXT),
0898:                            "EXPRTOKEN_NODETYPE_TEXT");
0899:                    fTokenNames.put(new Integer(EXPRTOKEN_NODETYPE_PI),
0900:                            "EXPRTOKEN_NODETYPE_PI");
0901:                    fTokenNames.put(new Integer(EXPRTOKEN_NODETYPE_NODE),
0902:                            "EXPRTOKEN_NODETYPE_NODE");
0903:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_AND),
0904:                            "EXPRTOKEN_OPERATOR_AND");
0905:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_OR),
0906:                            "EXPRTOKEN_OPERATOR_OR");
0907:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_MOD),
0908:                            "EXPRTOKEN_OPERATOR_MOD");
0909:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_DIV),
0910:                            "EXPRTOKEN_OPERATOR_DIV");
0911:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_MULT),
0912:                            "EXPRTOKEN_OPERATOR_MULT");
0913:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_SLASH),
0914:                            "EXPRTOKEN_OPERATOR_SLASH");
0915:                    fTokenNames.put(
0916:                            new Integer(EXPRTOKEN_OPERATOR_DOUBLE_SLASH),
0917:                            "EXPRTOKEN_OPERATOR_DOUBLE_SLASH");
0918:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_UNION),
0919:                            "EXPRTOKEN_OPERATOR_UNION");
0920:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_PLUS),
0921:                            "EXPRTOKEN_OPERATOR_PLUS");
0922:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_MINUS),
0923:                            "EXPRTOKEN_OPERATOR_MINUS");
0924:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_EQUAL),
0925:                            "EXPRTOKEN_OPERATOR_EQUAL");
0926:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_NOT_EQUAL),
0927:                            "EXPRTOKEN_OPERATOR_NOT_EQUAL");
0928:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_LESS),
0929:                            "EXPRTOKEN_OPERATOR_LESS");
0930:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_LESS_EQUAL),
0931:                            "EXPRTOKEN_OPERATOR_LESS_EQUAL");
0932:                    fTokenNames.put(new Integer(EXPRTOKEN_OPERATOR_GREATER),
0933:                            "EXPRTOKEN_OPERATOR_GREATER");
0934:                    fTokenNames.put(new Integer(
0935:                            EXPRTOKEN_OPERATOR_GREATER_EQUAL),
0936:                            "EXPRTOKEN_OPERATOR_GREATER_EQUAL");
0937:                    fTokenNames.put(new Integer(EXPRTOKEN_FUNCTION_NAME),
0938:                            "EXPRTOKEN_FUNCTION_NAME");
0939:                    fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_ANCESTOR),
0940:                            "EXPRTOKEN_AXISNAME_ANCESTOR");
0941:                    fTokenNames.put(new Integer(
0942:                            EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF),
0943:                            "EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF");
0944:                    fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_ATTRIBUTE),
0945:                            "EXPRTOKEN_AXISNAME_ATTRIBUTE");
0946:                    fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_CHILD),
0947:                            "EXPRTOKEN_AXISNAME_CHILD");
0948:                    fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_DESCENDANT),
0949:                            "EXPRTOKEN_AXISNAME_DESCENDANT");
0950:                    fTokenNames.put(new Integer(
0951:                            EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF),
0952:                            "EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF");
0953:                    fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_FOLLOWING),
0954:                            "EXPRTOKEN_AXISNAME_FOLLOWING");
0955:                    fTokenNames.put(new Integer(
0956:                            EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING),
0957:                            "EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING");
0958:                    fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_NAMESPACE),
0959:                            "EXPRTOKEN_AXISNAME_NAMESPACE");
0960:                    fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_PARENT),
0961:                            "EXPRTOKEN_AXISNAME_PARENT");
0962:                    fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_PRECEDING),
0963:                            "EXPRTOKEN_AXISNAME_PRECEDING");
0964:                    fTokenNames.put(new Integer(
0965:                            EXPRTOKEN_AXISNAME_PRECEDING_SIBLING),
0966:                            "EXPRTOKEN_AXISNAME_PRECEDING_SIBLING");
0967:                    fTokenNames.put(new Integer(EXPRTOKEN_AXISNAME_SELF),
0968:                            "EXPRTOKEN_AXISNAME_SELF");
0969:                    fTokenNames.put(new Integer(EXPRTOKEN_LITERAL),
0970:                            "EXPRTOKEN_LITERAL");
0971:                    fTokenNames.put(new Integer(EXPRTOKEN_NUMBER),
0972:                            "EXPRTOKEN_NUMBER");
0973:                    fTokenNames.put(new Integer(EXPRTOKEN_VARIABLE_REFERENCE),
0974:                            "EXPRTOKEN_VARIABLE_REFERENCE");
0975:                }
0976:
0977:                //
0978:                // Public methods
0979:                //
0980:
0981:                //        public String getTokenName(int token) {
0982:                //            if (token < 0 || token >= fgTokenNames.length)
0983:                //                return null;
0984:                //            return fgTokenNames[token];
0985:                //        }
0986:                //
0987:                public String getTokenString(int token) {
0988:                    return (String) fTokenNames.get(new Integer(token));
0989:                }
0990:
0991:                public void addToken(String tokenStr) {
0992:                    Integer tokenInt = (Integer) fTokenNames.get(tokenStr);
0993:                    if (tokenInt == null) {
0994:                        tokenInt = new Integer(fTokenNames.size());
0995:                        fTokenNames.put(tokenInt, tokenStr);
0996:                    }
0997:                    addToken(tokenInt.intValue());
0998:                }
0999:
1000:                public void addToken(int token) {
1001:                    try {
1002:                        fTokens[fTokenCount] = token;
1003:                    } catch (ArrayIndexOutOfBoundsException ex) {
1004:                        int[] oldList = fTokens;
1005:                        fTokens = new int[fTokenCount << 1];
1006:                        System.arraycopy(oldList, 0, fTokens, 0, fTokenCount);
1007:                        fTokens[fTokenCount] = token;
1008:                    }
1009:                    fTokenCount++;
1010:                }
1011:
1012:                //        public int getTokenCount() {
1013:                //            return fTokenCount;
1014:                //        }
1015:                //        public int getToken(int tokenIndex) {
1016:                //            return fTokens[tokenIndex];
1017:                //        }
1018:
1019:                /**
1020:                 * Resets the current position to the head of the token list.
1021:                 */
1022:                public void rewind() {
1023:                    fCurrentTokenIndex = 0;
1024:                }
1025:
1026:                /**
1027:                 * Returns true if the {@link #getNextToken()} method
1028:                 * returns a valid token.
1029:                 */
1030:                public boolean hasMore() {
1031:                    return fCurrentTokenIndex < fTokenCount;
1032:                }
1033:
1034:                /**
1035:                 * Obtains the token at the current position, then advance
1036:                 * the current position by one.
1037:                 * 
1038:                 * If there's no such next token, this method throws
1039:                 * <tt>new XPathException("c-general-xpath");</tt>.
1040:                 */
1041:                public int nextToken() throws XPathException {
1042:                    if (fCurrentTokenIndex == fTokenCount)
1043:                        throw new XPathException("c-general-xpath");
1044:                    return fTokens[fCurrentTokenIndex++];
1045:                }
1046:
1047:                /**
1048:                 * Obtains the token at the current position, without advancing
1049:                 * the current position.
1050:                 * 
1051:                 * If there's no such next token, this method throws
1052:                 * <tt>new XPathException("c-general-xpath");</tt>.
1053:                 */
1054:                public int peekToken() throws XPathException {
1055:                    if (fCurrentTokenIndex == fTokenCount)
1056:                        throw new XPathException("c-general-xpath");
1057:                    return fTokens[fCurrentTokenIndex];
1058:                }
1059:
1060:                /**
1061:                 * Obtains the token at the current position as a String.
1062:                 * 
1063:                 * If there's no current token or if the current token
1064:                 * is not a string token, this method throws 
1065:                 * <tt>new XPathException("c-general-xpath");</tt>.
1066:                 */
1067:                public String nextTokenAsString() throws XPathException {
1068:                    String s = getTokenString(nextToken());
1069:                    if (s == null)
1070:                        throw new XPathException("c-general-xpath");
1071:                    return s;
1072:                }
1073:
1074:                public void dumpTokens() {
1075:                    //if (DUMP_TOKENS) {
1076:                    for (int i = 0; i < fTokenCount; i++) {
1077:                        switch (fTokens[i]) {
1078:                        case EXPRTOKEN_OPEN_PAREN:
1079:                            System.out.print("<OPEN_PAREN/>");
1080:                            break;
1081:                        case EXPRTOKEN_CLOSE_PAREN:
1082:                            System.out.print("<CLOSE_PAREN/>");
1083:                            break;
1084:                        case EXPRTOKEN_OPEN_BRACKET:
1085:                            System.out.print("<OPEN_BRACKET/>");
1086:                            break;
1087:                        case EXPRTOKEN_CLOSE_BRACKET:
1088:                            System.out.print("<CLOSE_BRACKET/>");
1089:                            break;
1090:                        case EXPRTOKEN_PERIOD:
1091:                            System.out.print("<PERIOD/>");
1092:                            break;
1093:                        case EXPRTOKEN_DOUBLE_PERIOD:
1094:                            System.out.print("<DOUBLE_PERIOD/>");
1095:                            break;
1096:                        case EXPRTOKEN_ATSIGN:
1097:                            System.out.print("<ATSIGN/>");
1098:                            break;
1099:                        case EXPRTOKEN_COMMA:
1100:                            System.out.print("<COMMA/>");
1101:                            break;
1102:                        case EXPRTOKEN_DOUBLE_COLON:
1103:                            System.out.print("<DOUBLE_COLON/>");
1104:                            break;
1105:                        case EXPRTOKEN_NAMETEST_ANY:
1106:                            System.out.print("<NAMETEST_ANY/>");
1107:                            break;
1108:                        case EXPRTOKEN_NAMETEST_NAMESPACE:
1109:                            System.out.print("<NAMETEST_NAMESPACE");
1110:                            System.out.print(" prefix=\""
1111:                                    + getTokenString(fTokens[++i]) + "\"");
1112:                            System.out.print("/>");
1113:                            break;
1114:                        case EXPRTOKEN_NAMETEST_QNAME:
1115:                            System.out.print("<NAMETEST_QNAME");
1116:                            if (fTokens[++i] != -1)
1117:                                System.out.print(" prefix=\""
1118:                                        + getTokenString(fTokens[i]) + "\"");
1119:                            System.out.print(" localpart=\""
1120:                                    + getTokenString(fTokens[++i]) + "\"");
1121:                            System.out.print("/>");
1122:                            break;
1123:                        case EXPRTOKEN_NODETYPE_COMMENT:
1124:                            System.out.print("<NODETYPE_COMMENT/>");
1125:                            break;
1126:                        case EXPRTOKEN_NODETYPE_TEXT:
1127:                            System.out.print("<NODETYPE_TEXT/>");
1128:                            break;
1129:                        case EXPRTOKEN_NODETYPE_PI:
1130:                            System.out.print("<NODETYPE_PI/>");
1131:                            break;
1132:                        case EXPRTOKEN_NODETYPE_NODE:
1133:                            System.out.print("<NODETYPE_NODE/>");
1134:                            break;
1135:                        case EXPRTOKEN_OPERATOR_AND:
1136:                            System.out.print("<OPERATOR_AND/>");
1137:                            break;
1138:                        case EXPRTOKEN_OPERATOR_OR:
1139:                            System.out.print("<OPERATOR_OR/>");
1140:                            break;
1141:                        case EXPRTOKEN_OPERATOR_MOD:
1142:                            System.out.print("<OPERATOR_MOD/>");
1143:                            break;
1144:                        case EXPRTOKEN_OPERATOR_DIV:
1145:                            System.out.print("<OPERATOR_DIV/>");
1146:                            break;
1147:                        case EXPRTOKEN_OPERATOR_MULT:
1148:                            System.out.print("<OPERATOR_MULT/>");
1149:                            break;
1150:                        case EXPRTOKEN_OPERATOR_SLASH:
1151:                            System.out.print("<OPERATOR_SLASH/>");
1152:                            if (i + 1 < fTokenCount) {
1153:                                System.out.println();
1154:                                System.out.print("  ");
1155:                            }
1156:                            break;
1157:                        case EXPRTOKEN_OPERATOR_DOUBLE_SLASH:
1158:                            System.out.print("<OPERATOR_DOUBLE_SLASH/>");
1159:                            break;
1160:                        case EXPRTOKEN_OPERATOR_UNION:
1161:                            System.out.print("<OPERATOR_UNION/>");
1162:                            break;
1163:                        case EXPRTOKEN_OPERATOR_PLUS:
1164:                            System.out.print("<OPERATOR_PLUS/>");
1165:                            break;
1166:                        case EXPRTOKEN_OPERATOR_MINUS:
1167:                            System.out.print("<OPERATOR_MINUS/>");
1168:                            break;
1169:                        case EXPRTOKEN_OPERATOR_EQUAL:
1170:                            System.out.print("<OPERATOR_EQUAL/>");
1171:                            break;
1172:                        case EXPRTOKEN_OPERATOR_NOT_EQUAL:
1173:                            System.out.print("<OPERATOR_NOT_EQUAL/>");
1174:                            break;
1175:                        case EXPRTOKEN_OPERATOR_LESS:
1176:                            System.out.print("<OPERATOR_LESS/>");
1177:                            break;
1178:                        case EXPRTOKEN_OPERATOR_LESS_EQUAL:
1179:                            System.out.print("<OPERATOR_LESS_EQUAL/>");
1180:                            break;
1181:                        case EXPRTOKEN_OPERATOR_GREATER:
1182:                            System.out.print("<OPERATOR_GREATER/>");
1183:                            break;
1184:                        case EXPRTOKEN_OPERATOR_GREATER_EQUAL:
1185:                            System.out.print("<OPERATOR_GREATER_EQUAL/>");
1186:                            break;
1187:                        case EXPRTOKEN_FUNCTION_NAME:
1188:                            System.out.print("<FUNCTION_NAME");
1189:                            if (fTokens[++i] != -1)
1190:                                System.out.print(" prefix=\""
1191:                                        + getTokenString(fTokens[i]) + "\"");
1192:                            System.out.print(" localpart=\""
1193:                                    + getTokenString(fTokens[++i]) + "\"");
1194:                            System.out.print("/>");
1195:                            break;
1196:                        case EXPRTOKEN_AXISNAME_ANCESTOR:
1197:                            System.out.print("<AXISNAME_ANCESTOR/>");
1198:                            break;
1199:                        case EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF:
1200:                            System.out.print("<AXISNAME_ANCESTOR_OR_SELF/>");
1201:                            break;
1202:                        case EXPRTOKEN_AXISNAME_ATTRIBUTE:
1203:                            System.out.print("<AXISNAME_ATTRIBUTE/>");
1204:                            break;
1205:                        case EXPRTOKEN_AXISNAME_CHILD:
1206:                            System.out.print("<AXISNAME_CHILD/>");
1207:                            break;
1208:                        case EXPRTOKEN_AXISNAME_DESCENDANT:
1209:                            System.out.print("<AXISNAME_DESCENDANT/>");
1210:                            break;
1211:                        case EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF:
1212:                            System.out.print("<AXISNAME_DESCENDANT_OR_SELF/>");
1213:                            break;
1214:                        case EXPRTOKEN_AXISNAME_FOLLOWING:
1215:                            System.out.print("<AXISNAME_FOLLOWING/>");
1216:                            break;
1217:                        case EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING:
1218:                            System.out.print("<AXISNAME_FOLLOWING_SIBLING/>");
1219:                            break;
1220:                        case EXPRTOKEN_AXISNAME_NAMESPACE:
1221:                            System.out.print("<AXISNAME_NAMESPACE/>");
1222:                            break;
1223:                        case EXPRTOKEN_AXISNAME_PARENT:
1224:                            System.out.print("<AXISNAME_PARENT/>");
1225:                            break;
1226:                        case EXPRTOKEN_AXISNAME_PRECEDING:
1227:                            System.out.print("<AXISNAME_PRECEDING/>");
1228:                            break;
1229:                        case EXPRTOKEN_AXISNAME_PRECEDING_SIBLING:
1230:                            System.out.print("<AXISNAME_PRECEDING_SIBLING/>");
1231:                            break;
1232:                        case EXPRTOKEN_AXISNAME_SELF:
1233:                            System.out.print("<AXISNAME_SELF/>");
1234:                            break;
1235:                        case EXPRTOKEN_LITERAL:
1236:                            System.out.print("<LITERAL");
1237:                            System.out.print(" value=\""
1238:                                    + getTokenString(fTokens[++i]) + "\"");
1239:                            System.out.print("/>");
1240:                            break;
1241:                        case EXPRTOKEN_NUMBER:
1242:                            System.out.print("<NUMBER");
1243:                            System.out.print(" whole=\""
1244:                                    + getTokenString(fTokens[++i]) + "\"");
1245:                            System.out.print(" part=\""
1246:                                    + getTokenString(fTokens[++i]) + "\"");
1247:                            System.out.print("/>");
1248:                            break;
1249:                        case EXPRTOKEN_VARIABLE_REFERENCE:
1250:                            System.out.print("<VARIABLE_REFERENCE");
1251:                            if (fTokens[++i] != -1)
1252:                                System.out.print(" prefix=\""
1253:                                        + getTokenString(fTokens[i]) + "\"");
1254:                            System.out.print(" localpart=\""
1255:                                    + getTokenString(fTokens[++i]) + "\"");
1256:                            System.out.print("/>");
1257:                            break;
1258:                        default:
1259:                            System.out.println("<???/>");
1260:                        }
1261:                    }
1262:                    System.out.println();
1263:                    //}
1264:                }
1265:
1266:            } // class Tokens
1267:
1268:            /**
1269:             * @xerces.internal
1270:             * 
1271:             * @author Glenn Marcy, IBM
1272:             * @author Andy Clark, IBM
1273:             *
1274:             * @version $Id: XPath.java 572107 2007-09-02 18:40:40Z mrglavas $
1275:             */
1276:            private static class Scanner {
1277:
1278:                /**
1279:                 * 7-bit ASCII subset
1280:                 *
1281:                 *  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
1282:                 *  0,  0,  0,  0,  0,  0,  0,  0,  0, HT, LF,  0,  0, CR,  0,  0,  // 0
1283:                 *  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 1
1284:                 * SP,  !,  ",  #,  $,  %,  &,  ',  (,  ),  *,  +,  ,,  -,  .,  /,  // 2
1285:                 *  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  :,  ;,  <,  =,  >,  ?,  // 3
1286:                 *  @,  A,  B,  C,  D,  E,  F,  G,  H,  I,  J,  K,  L,  M,  N,  O,  // 4
1287:                 *  P,  Q,  R,  S,  T,  U,  V,  W,  X,  Y,  Z,  [,  \,  ],  ^,  _,  // 5
1288:                 *  `,  a,  b,  c,  d,  e,  f,  g,  h,  i,  j,  k,  l,  m,  n,  o,  // 6
1289:                 *  p,  q,  r,  s,  t,  u,  v,  w,  x,  y,  z,  {,  |,  },  ~, DEL  // 7
1290:                 */
1291:                private static final byte CHARTYPE_INVALID = 0, // invalid XML character
1292:                        CHARTYPE_OTHER = 1, // not special - one of "#%&;?\^`{}~" or DEL
1293:                        CHARTYPE_WHITESPACE = 2, // one of "\t\n\r " (0x09, 0x0A, 0x0D, 0x20)
1294:                        CHARTYPE_EXCLAMATION = 3, // '!' (0x21)
1295:                        CHARTYPE_QUOTE = 4, // '\"' or '\'' (0x22 and 0x27)
1296:                        CHARTYPE_DOLLAR = 5, // '$' (0x24)
1297:                        CHARTYPE_OPEN_PAREN = 6, // '(' (0x28)
1298:                        CHARTYPE_CLOSE_PAREN = 7, // ')' (0x29)
1299:                        CHARTYPE_STAR = 8, // '*' (0x2A)
1300:                        CHARTYPE_PLUS = 9, // '+' (0x2B)
1301:                        CHARTYPE_COMMA = 10, // ',' (0x2C)
1302:                        CHARTYPE_MINUS = 11, // '-' (0x2D)
1303:                        CHARTYPE_PERIOD = 12, // '.' (0x2E)
1304:                        CHARTYPE_SLASH = 13, // '/' (0x2F)
1305:                        CHARTYPE_DIGIT = 14, // '0'-'9' (0x30 to 0x39)
1306:                        CHARTYPE_COLON = 15, // ':' (0x3A)
1307:                        CHARTYPE_LESS = 16, // '<' (0x3C)
1308:                        CHARTYPE_EQUAL = 17, // '=' (0x3D)
1309:                        CHARTYPE_GREATER = 18, // '>' (0x3E)
1310:                        CHARTYPE_ATSIGN = 19, // '@' (0x40)
1311:                        CHARTYPE_LETTER = 20, // 'A'-'Z' or 'a'-'z' (0x41 to 0x5A and 0x61 to 0x7A)
1312:                        CHARTYPE_OPEN_BRACKET = 21, // '[' (0x5B)
1313:                        CHARTYPE_CLOSE_BRACKET = 22, // ']' (0x5D)
1314:                        CHARTYPE_UNDERSCORE = 23, // '_' (0x5F)
1315:                        CHARTYPE_UNION = 24, // '|' (0x7C)
1316:                        CHARTYPE_NONASCII = 25; // Non-ASCII Unicode codepoint (>= 0x80)
1317:
1318:                private static final byte[] fASCIICharMap = { 0, 0, 0, 0, 0, 0,
1319:                        0, 0, 0, 2, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1320:                        0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 1, 5, 1, 1, 4, 6, 7,
1321:                        8, 9, 10, 11, 12, 13, 14, 14, 14, 14, 14, 14, 14, 14,
1322:                        14, 14, 15, 1, 16, 17, 18, 1, 19, 20, 20, 20, 20, 20,
1323:                        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1324:                        20, 20, 20, 20, 20, 20, 20, 21, 1, 22, 1, 23, 1, 20,
1325:                        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
1326:                        20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 1, 24, 1,
1327:                        1, 1 };
1328:
1329:                /**
1330:                 * Symbol literals
1331:                 */
1332:
1333:                //
1334:                // Data
1335:                //
1336:                /** Symbol table. */
1337:                private SymbolTable fSymbolTable;
1338:
1339:                // symbols
1340:
1341:                private static final String fAndSymbol = "and".intern();
1342:                private static final String fOrSymbol = "or".intern();
1343:                private static final String fModSymbol = "mod".intern();
1344:                private static final String fDivSymbol = "div".intern();
1345:
1346:                private static final String fCommentSymbol = "comment".intern();
1347:                private static final String fTextSymbol = "text".intern();
1348:                private static final String fPISymbol = "processing-instruction"
1349:                        .intern();
1350:                private static final String fNodeSymbol = "node".intern();
1351:
1352:                private static final String fAncestorSymbol = "ancestor"
1353:                        .intern();
1354:                private static final String fAncestorOrSelfSymbol = "ancestor-or-self"
1355:                        .intern();
1356:                private static final String fAttributeSymbol = "attribute"
1357:                        .intern();
1358:                private static final String fChildSymbol = "child".intern();
1359:                private static final String fDescendantSymbol = "descendant"
1360:                        .intern();
1361:                private static final String fDescendantOrSelfSymbol = "descendant-or-self"
1362:                        .intern();
1363:                private static final String fFollowingSymbol = "following"
1364:                        .intern();
1365:                private static final String fFollowingSiblingSymbol = "following-sibling"
1366:                        .intern();
1367:                private static final String fNamespaceSymbol = "namespace"
1368:                        .intern();
1369:                private static final String fParentSymbol = "parent".intern();
1370:                private static final String fPrecedingSymbol = "preceding"
1371:                        .intern();
1372:                private static final String fPrecedingSiblingSymbol = "preceding-sibling"
1373:                        .intern();
1374:                private static final String fSelfSymbol = "self".intern();
1375:
1376:                //
1377:                // Constructors
1378:                //
1379:
1380:                /** Constructs an XPath expression scanner. */
1381:                public Scanner(SymbolTable symbolTable) {
1382:
1383:                    // save pool and tokens
1384:                    fSymbolTable = symbolTable;
1385:
1386:                } // <init>(SymbolTable)
1387:
1388:                /**
1389:                 *
1390:                 */
1391:                public boolean scanExpr(SymbolTable symbolTable,
1392:                        XPath.Tokens tokens, String data, int currentOffset,
1393:                        int endOffset) throws XPathException {
1394:
1395:                    int nameOffset;
1396:                    String nameHandle, prefixHandle;
1397:                    boolean starIsMultiplyOperator = false;
1398:                    int ch;
1399:
1400:                    while (true) {
1401:                        if (currentOffset == endOffset) {
1402:                            break;
1403:                        }
1404:                        ch = data.charAt(currentOffset);
1405:                        //
1406:                        // [39] ExprWhitespace ::= S
1407:                        //
1408:                        while (ch == ' ' || ch == 0x0A || ch == 0x09
1409:                                || ch == 0x0D) {
1410:                            if (++currentOffset == endOffset) {
1411:                                break;
1412:                            }
1413:                            ch = data.charAt(currentOffset);
1414:                        }
1415:                        if (currentOffset == endOffset) {
1416:                            break;
1417:                        }
1418:                        //
1419:                        // [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::'
1420:                        //                  | NameTest | NodeType | Operator | FunctionName
1421:                        //                  | AxisName | Literal | Number | VariableReference
1422:                        //
1423:                        byte chartype = (ch >= 0x80) ? CHARTYPE_NONASCII
1424:                                : fASCIICharMap[ch];
1425:                        switch (chartype) {
1426:                        case CHARTYPE_OPEN_PAREN: // '('
1427:                            addToken(tokens, XPath.Tokens.EXPRTOKEN_OPEN_PAREN);
1428:                            starIsMultiplyOperator = false;
1429:                            if (++currentOffset == endOffset) {
1430:                                break;
1431:                            }
1432:                            break;
1433:                        case CHARTYPE_CLOSE_PAREN: // ')'
1434:                            addToken(tokens, XPath.Tokens.EXPRTOKEN_CLOSE_PAREN);
1435:                            starIsMultiplyOperator = true;
1436:                            if (++currentOffset == endOffset) {
1437:                                break;
1438:                            }
1439:                            break;
1440:                        case CHARTYPE_OPEN_BRACKET: // '['
1441:                            addToken(tokens,
1442:                                    XPath.Tokens.EXPRTOKEN_OPEN_BRACKET);
1443:                            starIsMultiplyOperator = false;
1444:                            if (++currentOffset == endOffset) {
1445:                                break;
1446:                            }
1447:                            break;
1448:                        case CHARTYPE_CLOSE_BRACKET: // ']'
1449:                            addToken(tokens,
1450:                                    XPath.Tokens.EXPRTOKEN_CLOSE_BRACKET);
1451:                            starIsMultiplyOperator = true;
1452:                            if (++currentOffset == endOffset) {
1453:                                break;
1454:                            }
1455:                            break;
1456:                        //
1457:                        // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
1458:                        //                                         ^^^^^^^^^^
1459:                        //
1460:                        case CHARTYPE_PERIOD: // '.', '..' or '.' Digits
1461:                            if (currentOffset + 1 == endOffset) {
1462:                                addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD);
1463:                                starIsMultiplyOperator = true;
1464:                                currentOffset++;
1465:                                break;
1466:                            }
1467:                            ch = data.charAt(currentOffset + 1);
1468:                            if (ch == '.') { // '..'
1469:                                addToken(tokens,
1470:                                        XPath.Tokens.EXPRTOKEN_DOUBLE_PERIOD);
1471:                                starIsMultiplyOperator = true;
1472:                                currentOffset += 2;
1473:                            } else if (ch >= '0' && ch <= '9') {
1474:                                addToken(tokens, XPath.Tokens.EXPRTOKEN_NUMBER);
1475:                                starIsMultiplyOperator = true;
1476:                                currentOffset = scanNumber(tokens, data,
1477:                                        endOffset, currentOffset/*, encoding*/);
1478:                            } else if (ch == '/') {
1479:                                addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD);
1480:                                starIsMultiplyOperator = true;
1481:                                currentOffset++;
1482:                            } else if (ch == '|') {
1483:                                addToken(tokens, XPath.Tokens.EXPRTOKEN_PERIOD);
1484:                                starIsMultiplyOperator = true;
1485:                                currentOffset++;
1486:                                break;
1487:                            } else if (ch == ' ' || ch == 0x0A || ch == 0x09
1488:                                    || ch == 0x0D) {
1489:                                // this is legal if the next token is non-existent or |
1490:                                do {
1491:                                    if (++currentOffset == endOffset) {
1492:                                        break;
1493:                                    }
1494:                                    ch = data.charAt(currentOffset);
1495:                                } while (ch == ' ' || ch == 0x0A || ch == 0x09
1496:                                        || ch == 0x0D);
1497:                                if (currentOffset == endOffset || ch == '|') {
1498:                                    addToken(tokens,
1499:                                            XPath.Tokens.EXPRTOKEN_PERIOD);
1500:                                    starIsMultiplyOperator = true;
1501:                                    break;
1502:                                }
1503:                                throw new XPathException("c-general-xpath");
1504:                            } else { // '.'
1505:                                throw new XPathException("c-general-xpath");
1506:                            }
1507:                            if (currentOffset == endOffset) {
1508:                                break;
1509:                            }
1510:                            break;
1511:                        case CHARTYPE_ATSIGN: // '@'
1512:                            addToken(tokens, XPath.Tokens.EXPRTOKEN_ATSIGN);
1513:                            starIsMultiplyOperator = false;
1514:                            if (++currentOffset == endOffset) {
1515:                                break;
1516:                            }
1517:                            break;
1518:                        case CHARTYPE_COMMA: // ','
1519:                            addToken(tokens, XPath.Tokens.EXPRTOKEN_COMMA);
1520:                            starIsMultiplyOperator = false;
1521:                            if (++currentOffset == endOffset) {
1522:                                break;
1523:                            }
1524:                            break;
1525:                        case CHARTYPE_COLON: // '::'
1526:                            if (++currentOffset == endOffset) {
1527:                                // System.out.println("abort 1a");
1528:                                return false; // REVISIT
1529:                            }
1530:                            ch = data.charAt(currentOffset);
1531:                            if (ch != ':') {
1532:                                // System.out.println("abort 1b");
1533:                                return false; // REVISIT
1534:                            }
1535:                            addToken(tokens,
1536:                                    XPath.Tokens.EXPRTOKEN_DOUBLE_COLON);
1537:                            starIsMultiplyOperator = false;
1538:                            if (++currentOffset == endOffset) {
1539:                                break;
1540:                            }
1541:                            break;
1542:                        case CHARTYPE_SLASH: // '/' and '//'
1543:                            if (++currentOffset == endOffset) {
1544:                                addToken(tokens,
1545:                                        XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH);
1546:                                starIsMultiplyOperator = false;
1547:                                break;
1548:                            }
1549:                            ch = data.charAt(currentOffset);
1550:                            if (ch == '/') { // '//'
1551:                                addToken(
1552:                                        tokens,
1553:                                        XPath.Tokens.EXPRTOKEN_OPERATOR_DOUBLE_SLASH);
1554:                                starIsMultiplyOperator = false;
1555:                                if (++currentOffset == endOffset) {
1556:                                    break;
1557:                                }
1558:                            } else {
1559:                                addToken(tokens,
1560:                                        XPath.Tokens.EXPRTOKEN_OPERATOR_SLASH);
1561:                                starIsMultiplyOperator = false;
1562:                            }
1563:                            break;
1564:                        case CHARTYPE_UNION: // '|'
1565:                            addToken(tokens,
1566:                                    XPath.Tokens.EXPRTOKEN_OPERATOR_UNION);
1567:                            starIsMultiplyOperator = false;
1568:                            if (++currentOffset == endOffset) {
1569:                                break;
1570:                            }
1571:                            break;
1572:                        case CHARTYPE_PLUS: // '+'
1573:                            addToken(tokens,
1574:                                    XPath.Tokens.EXPRTOKEN_OPERATOR_PLUS);
1575:                            starIsMultiplyOperator = false;
1576:                            if (++currentOffset == endOffset) {
1577:                                break;
1578:                            }
1579:                            break;
1580:                        case CHARTYPE_MINUS: // '-'
1581:                            addToken(tokens,
1582:                                    XPath.Tokens.EXPRTOKEN_OPERATOR_MINUS);
1583:                            starIsMultiplyOperator = false;
1584:                            if (++currentOffset == endOffset) {
1585:                                break;
1586:                            }
1587:                            break;
1588:                        case CHARTYPE_EQUAL: // '='
1589:                            addToken(tokens,
1590:                                    XPath.Tokens.EXPRTOKEN_OPERATOR_EQUAL);
1591:                            starIsMultiplyOperator = false;
1592:                            if (++currentOffset == endOffset) {
1593:                                break;
1594:                            }
1595:                            break;
1596:                        case CHARTYPE_EXCLAMATION: // '!='
1597:                            if (++currentOffset == endOffset) {
1598:                                // System.out.println("abort 2a");
1599:                                return false; // REVISIT
1600:                            }
1601:                            ch = data.charAt(currentOffset);
1602:                            if (ch != '=') {
1603:                                // System.out.println("abort 2b");
1604:                                return false; // REVISIT
1605:                            }
1606:                            addToken(tokens,
1607:                                    XPath.Tokens.EXPRTOKEN_OPERATOR_NOT_EQUAL);
1608:                            starIsMultiplyOperator = false;
1609:                            if (++currentOffset == endOffset) {
1610:                                break;
1611:                            }
1612:                            break;
1613:                        case CHARTYPE_LESS: // '<' and '<='
1614:                            if (++currentOffset == endOffset) {
1615:                                addToken(tokens,
1616:                                        XPath.Tokens.EXPRTOKEN_OPERATOR_LESS);
1617:                                starIsMultiplyOperator = false;
1618:                                break;
1619:                            }
1620:                            ch = data.charAt(currentOffset);
1621:                            if (ch == '=') { // '<='
1622:                                addToken(
1623:                                        tokens,
1624:                                        XPath.Tokens.EXPRTOKEN_OPERATOR_LESS_EQUAL);
1625:                                starIsMultiplyOperator = false;
1626:                                if (++currentOffset == endOffset) {
1627:                                    break;
1628:                                }
1629:                            } else {
1630:                                addToken(tokens,
1631:                                        XPath.Tokens.EXPRTOKEN_OPERATOR_LESS);
1632:                                starIsMultiplyOperator = false;
1633:                            }
1634:                            break;
1635:                        case CHARTYPE_GREATER: // '>' and '>='
1636:                            if (++currentOffset == endOffset) {
1637:                                addToken(tokens,
1638:                                        XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER);
1639:                                starIsMultiplyOperator = false;
1640:                                break;
1641:                            }
1642:                            ch = data.charAt(currentOffset);
1643:                            if (ch == '=') { // '>='
1644:                                addToken(
1645:                                        tokens,
1646:                                        XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER_EQUAL);
1647:                                starIsMultiplyOperator = false;
1648:                                if (++currentOffset == endOffset) {
1649:                                    break;
1650:                                }
1651:                            } else {
1652:                                addToken(tokens,
1653:                                        XPath.Tokens.EXPRTOKEN_OPERATOR_GREATER);
1654:                                starIsMultiplyOperator = false;
1655:                            }
1656:                            break;
1657:                        //
1658:                        // [29] Literal ::= '"' [^"]* '"' | "'" [^']* "'"
1659:                        //
1660:                        case CHARTYPE_QUOTE: // '\"' or '\''
1661:                            int qchar = ch;
1662:                            if (++currentOffset == endOffset) {
1663:                                // System.out.println("abort 2c");
1664:                                return false; // REVISIT
1665:                            }
1666:                            ch = data.charAt(currentOffset);
1667:                            int litOffset = currentOffset;
1668:                            while (ch != qchar) {
1669:                                if (++currentOffset == endOffset) {
1670:                                    // System.out.println("abort 2d");
1671:                                    return false; // REVISIT
1672:                                }
1673:                                ch = data.charAt(currentOffset);
1674:                            }
1675:                            int litLength = currentOffset - litOffset;
1676:                            addToken(tokens, XPath.Tokens.EXPRTOKEN_LITERAL);
1677:                            starIsMultiplyOperator = true;
1678:                            tokens.addToken(symbolTable
1679:                                    .addSymbol(data.substring(litOffset,
1680:                                            litOffset + litLength)));
1681:                            if (++currentOffset == endOffset) {
1682:                                break;
1683:                            }
1684:                            break;
1685:                        //
1686:                        // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
1687:                        // [31] Digits ::= [0-9]+
1688:                        //
1689:                        case CHARTYPE_DIGIT:
1690:                            addToken(tokens, XPath.Tokens.EXPRTOKEN_NUMBER);
1691:                            starIsMultiplyOperator = true;
1692:                            currentOffset = scanNumber(tokens, data, endOffset,
1693:                                    currentOffset/*, encoding*/);
1694:                            break;
1695:                        //
1696:                        // [36] VariableReference ::= '$' QName
1697:                        //
1698:                        case CHARTYPE_DOLLAR:
1699:                            if (++currentOffset == endOffset) {
1700:                                // System.out.println("abort 3a");
1701:                                return false; // REVISIT
1702:                            }
1703:                            nameOffset = currentOffset;
1704:                            currentOffset = scanNCName(data, endOffset,
1705:                                    currentOffset);
1706:                            if (currentOffset == nameOffset) {
1707:                                // System.out.println("abort 3b");
1708:                                return false; // REVISIT
1709:                            }
1710:                            if (currentOffset < endOffset) {
1711:                                ch = data.charAt(currentOffset);
1712:                            } else {
1713:                                ch = -1;
1714:                            }
1715:                            nameHandle = symbolTable.addSymbol(data.substring(
1716:                                    nameOffset, currentOffset));
1717:                            if (ch != ':') {
1718:                                prefixHandle = XMLSymbols.EMPTY_STRING;
1719:                            } else {
1720:                                prefixHandle = nameHandle;
1721:                                if (++currentOffset == endOffset) {
1722:                                    // System.out.println("abort 4a");
1723:                                    return false; // REVISIT
1724:                                }
1725:                                nameOffset = currentOffset;
1726:                                currentOffset = scanNCName(data, endOffset,
1727:                                        currentOffset);
1728:                                if (currentOffset == nameOffset) {
1729:                                    // System.out.println("abort 4b");
1730:                                    return false; // REVISIT
1731:                                }
1732:                                if (currentOffset < endOffset) {
1733:                                    ch = data.charAt(currentOffset);
1734:                                } else {
1735:                                    ch = -1;
1736:                                }
1737:                                nameHandle = symbolTable.addSymbol(data
1738:                                        .substring(nameOffset, currentOffset));
1739:                            }
1740:                            addToken(tokens,
1741:                                    XPath.Tokens.EXPRTOKEN_VARIABLE_REFERENCE);
1742:                            starIsMultiplyOperator = true;
1743:                            tokens.addToken(prefixHandle);
1744:                            tokens.addToken(nameHandle);
1745:                            break;
1746:                        //
1747:                        // [37] NameTest ::= '*' | NCName ':' '*' | QName
1748:                        // [34] MultiplyOperator ::= '*'
1749:                        //
1750:                        case CHARTYPE_STAR: // '*'
1751:                            //
1752:                            // 3.7 Lexical Structure
1753:                            //
1754:                            //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
1755:                            //  an Operator, then a * must be recognized as a MultiplyOperator.
1756:                            //
1757:                            // Otherwise, the token must not be recognized as a MultiplyOperator.
1758:                            //
1759:                            if (starIsMultiplyOperator) {
1760:                                addToken(tokens,
1761:                                        XPath.Tokens.EXPRTOKEN_OPERATOR_MULT);
1762:                                starIsMultiplyOperator = false;
1763:                            } else {
1764:                                addToken(tokens,
1765:                                        XPath.Tokens.EXPRTOKEN_NAMETEST_ANY);
1766:                                starIsMultiplyOperator = true;
1767:                            }
1768:                            if (++currentOffset == endOffset) {
1769:                                break;
1770:                            }
1771:                            break;
1772:                        //
1773:                        // NCName, QName and non-terminals
1774:                        //
1775:                        case CHARTYPE_NONASCII: // possibly a valid non-ascii 'Letter' (BaseChar | Ideographic)
1776:                        case CHARTYPE_LETTER:
1777:                        case CHARTYPE_UNDERSCORE:
1778:                            //
1779:                            // 3.7 Lexical Structure
1780:                            //
1781:                            //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
1782:                            //  an Operator, then an NCName must be recognized as an OperatorName.
1783:                            //
1784:                            //  If the character following an NCName (possibly after intervening ExprWhitespace) is (,
1785:                            //  then the token must be recognized as a NodeType or a FunctionName.
1786:                            //
1787:                            //  If the two characters following an NCName (possibly after intervening ExprWhitespace)
1788:                            //  are ::, then the token must be recognized as an AxisName.
1789:                            //
1790:                            //  Otherwise, the token must not be recognized as an OperatorName, a NodeType, a
1791:                            //  FunctionName, or an AxisName.
1792:                            //
1793:                            // [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div'
1794:                            // [38] NodeType ::= 'comment' | 'text' | 'processing-instruction' | 'node'
1795:                            // [35] FunctionName ::= QName - NodeType
1796:                            // [6] AxisName ::= (see above)
1797:                            //
1798:                            // [37] NameTest ::= '*' | NCName ':' '*' | QName
1799:                            // [5] NCName ::= (Letter | '_') (NCNameChar)*
1800:                            // [?] NCNameChar ::= Letter | Digit | '.' | '-' | '_'  (ascii subset of 'NCNameChar')
1801:                            // [?] QName ::= (NCName ':')? NCName
1802:                            // [?] Letter ::= [A-Za-z]                              (ascii subset of 'Letter')
1803:                            // [?] Digit ::= [0-9]                                  (ascii subset of 'Digit')
1804:                            //
1805:                            nameOffset = currentOffset;
1806:                            currentOffset = scanNCName(data, endOffset,
1807:                                    currentOffset);
1808:                            if (currentOffset == nameOffset) {
1809:                                // System.out.println("abort 4c");
1810:                                return false; // REVISIT
1811:                            }
1812:                            if (currentOffset < endOffset) {
1813:                                ch = data.charAt(currentOffset);
1814:                            } else {
1815:                                ch = -1;
1816:                            }
1817:                            nameHandle = symbolTable.addSymbol(data.substring(
1818:                                    nameOffset, currentOffset));
1819:                            boolean isNameTestNCName = false;
1820:                            boolean isAxisName = false;
1821:                            prefixHandle = XMLSymbols.EMPTY_STRING;
1822:                            if (ch == ':') {
1823:                                if (++currentOffset == endOffset) {
1824:                                    // System.out.println("abort 5");
1825:                                    return false; // REVISIT
1826:                                }
1827:                                ch = data.charAt(currentOffset);
1828:                                if (ch == '*') {
1829:                                    if (++currentOffset < endOffset) {
1830:                                        ch = data.charAt(currentOffset);
1831:                                    }
1832:                                    isNameTestNCName = true;
1833:                                } else if (ch == ':') {
1834:                                    if (++currentOffset < endOffset) {
1835:                                        ch = data.charAt(currentOffset);
1836:                                    }
1837:                                    isAxisName = true;
1838:                                } else {
1839:                                    prefixHandle = nameHandle;
1840:                                    nameOffset = currentOffset;
1841:                                    currentOffset = scanNCName(data, endOffset,
1842:                                            currentOffset);
1843:                                    if (currentOffset == nameOffset) {
1844:                                        // System.out.println("abort 5b");
1845:                                        return false; // REVISIT
1846:                                    }
1847:                                    if (currentOffset < endOffset) {
1848:                                        ch = data.charAt(currentOffset);
1849:                                    } else {
1850:                                        ch = -1;
1851:                                    }
1852:                                    nameHandle = symbolTable.addSymbol(data
1853:                                            .substring(nameOffset,
1854:                                                    currentOffset));
1855:                                }
1856:                            }
1857:                            //
1858:                            // [39] ExprWhitespace ::= S
1859:                            //
1860:                            while (ch == ' ' || ch == 0x0A || ch == 0x09
1861:                                    || ch == 0x0D) {
1862:                                if (++currentOffset == endOffset) {
1863:                                    break;
1864:                                }
1865:                                ch = data.charAt(currentOffset);
1866:                            }
1867:                            //
1868:                            //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
1869:                            //  an Operator, then an NCName must be recognized as an OperatorName.
1870:                            //
1871:                            if (starIsMultiplyOperator) {
1872:                                if (nameHandle == fAndSymbol) {
1873:                                    addToken(tokens,
1874:                                            XPath.Tokens.EXPRTOKEN_OPERATOR_AND);
1875:                                    starIsMultiplyOperator = false;
1876:                                } else if (nameHandle == fOrSymbol) {
1877:                                    addToken(tokens,
1878:                                            XPath.Tokens.EXPRTOKEN_OPERATOR_OR);
1879:                                    starIsMultiplyOperator = false;
1880:                                } else if (nameHandle == fModSymbol) {
1881:                                    addToken(tokens,
1882:                                            XPath.Tokens.EXPRTOKEN_OPERATOR_MOD);
1883:                                    starIsMultiplyOperator = false;
1884:                                } else if (nameHandle == fDivSymbol) {
1885:                                    addToken(tokens,
1886:                                            XPath.Tokens.EXPRTOKEN_OPERATOR_DIV);
1887:                                    starIsMultiplyOperator = false;
1888:                                } else {
1889:                                    // System.out.println("abort 6");
1890:                                    return false; // REVISIT
1891:                                }
1892:                                if (isNameTestNCName) {
1893:                                    // System.out.println("abort 7");
1894:                                    return false; // REVISIT - NCName:* where an OperatorName is required
1895:                                } else if (isAxisName) {
1896:                                    // System.out.println("abort 8");
1897:                                    return false; // REVISIT - AxisName:: where an OperatorName is required
1898:                                }
1899:                                break;
1900:                            }
1901:                            //
1902:                            //  If the character following an NCName (possibly after intervening ExprWhitespace) is (,
1903:                            //  then the token must be recognized as a NodeType or a FunctionName.
1904:                            //
1905:                            if (ch == '(' && !isNameTestNCName && !isAxisName) {
1906:                                if (nameHandle == fCommentSymbol) {
1907:                                    addToken(
1908:                                            tokens,
1909:                                            XPath.Tokens.EXPRTOKEN_NODETYPE_COMMENT);
1910:                                } else if (nameHandle == fTextSymbol) {
1911:                                    addToken(
1912:                                            tokens,
1913:                                            XPath.Tokens.EXPRTOKEN_NODETYPE_TEXT);
1914:                                } else if (nameHandle == fPISymbol) {
1915:                                    addToken(tokens,
1916:                                            XPath.Tokens.EXPRTOKEN_NODETYPE_PI);
1917:                                } else if (nameHandle == fNodeSymbol) {
1918:                                    addToken(
1919:                                            tokens,
1920:                                            XPath.Tokens.EXPRTOKEN_NODETYPE_NODE);
1921:                                } else {
1922:                                    addToken(
1923:                                            tokens,
1924:                                            XPath.Tokens.EXPRTOKEN_FUNCTION_NAME);
1925:                                    tokens.addToken(prefixHandle);
1926:                                    tokens.addToken(nameHandle);
1927:                                }
1928:                                addToken(tokens,
1929:                                        XPath.Tokens.EXPRTOKEN_OPEN_PAREN);
1930:                                starIsMultiplyOperator = false;
1931:                                if (++currentOffset == endOffset) {
1932:                                    break;
1933:                                }
1934:                                break;
1935:                            }
1936:                            //
1937:                            //  If the two characters following an NCName (possibly after intervening ExprWhitespace)
1938:                            //  are ::, then the token must be recognized as an AxisName.
1939:                            //
1940:                            if (isAxisName
1941:                                    || (ch == ':'
1942:                                            && currentOffset + 1 < endOffset && data
1943:                                            .charAt(currentOffset + 1) == ':')) {
1944:                                if (nameHandle == fAncestorSymbol) {
1945:                                    addToken(
1946:                                            tokens,
1947:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_ANCESTOR);
1948:                                } else if (nameHandle == fAncestorOrSelfSymbol) {
1949:                                    addToken(
1950:                                            tokens,
1951:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF);
1952:                                } else if (nameHandle == fAttributeSymbol) {
1953:                                    addToken(
1954:                                            tokens,
1955:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_ATTRIBUTE);
1956:                                } else if (nameHandle == fChildSymbol) {
1957:                                    addToken(
1958:                                            tokens,
1959:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_CHILD);
1960:                                } else if (nameHandle == fDescendantSymbol) {
1961:                                    addToken(
1962:                                            tokens,
1963:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_DESCENDANT);
1964:                                } else if (nameHandle == fDescendantOrSelfSymbol) {
1965:                                    addToken(
1966:                                            tokens,
1967:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF);
1968:                                } else if (nameHandle == fFollowingSymbol) {
1969:                                    addToken(
1970:                                            tokens,
1971:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_FOLLOWING);
1972:                                } else if (nameHandle == fFollowingSiblingSymbol) {
1973:                                    addToken(
1974:                                            tokens,
1975:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING);
1976:                                } else if (nameHandle == fNamespaceSymbol) {
1977:                                    addToken(
1978:                                            tokens,
1979:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_NAMESPACE);
1980:                                } else if (nameHandle == fParentSymbol) {
1981:                                    addToken(
1982:                                            tokens,
1983:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_PARENT);
1984:                                } else if (nameHandle == fPrecedingSymbol) {
1985:                                    addToken(
1986:                                            tokens,
1987:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_PRECEDING);
1988:                                } else if (nameHandle == fPrecedingSiblingSymbol) {
1989:                                    addToken(
1990:                                            tokens,
1991:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_PRECEDING_SIBLING);
1992:                                } else if (nameHandle == fSelfSymbol) {
1993:                                    addToken(
1994:                                            tokens,
1995:                                            XPath.Tokens.EXPRTOKEN_AXISNAME_SELF);
1996:                                } else {
1997:                                    // System.out.println("abort 9");
1998:                                    return false; // REVISIT
1999:                                }
2000:                                if (isNameTestNCName) {
2001:                                    // System.out.println("abort 10");
2002:                                    return false; // REVISIT - "NCName:* ::" where "AxisName ::" is required
2003:                                }
2004:                                addToken(tokens,
2005:                                        XPath.Tokens.EXPRTOKEN_DOUBLE_COLON);
2006:                                starIsMultiplyOperator = false;
2007:                                if (!isAxisName) {
2008:                                    currentOffset++;
2009:                                    if (++currentOffset == endOffset) {
2010:                                        break;
2011:                                    }
2012:                                }
2013:                                break;
2014:                            }
2015:                            //
2016:                            //  Otherwise, the token must not be recognized as an OperatorName, a NodeType, a
2017:                            //  FunctionName, or an AxisName.
2018:                            //
2019:                            if (isNameTestNCName) {
2020:                                addToken(
2021:                                        tokens,
2022:                                        XPath.Tokens.EXPRTOKEN_NAMETEST_NAMESPACE);
2023:                                starIsMultiplyOperator = true;
2024:                                tokens.addToken(nameHandle);
2025:                            } else {
2026:                                addToken(tokens,
2027:                                        XPath.Tokens.EXPRTOKEN_NAMETEST_QNAME);
2028:                                starIsMultiplyOperator = true;
2029:                                tokens.addToken(prefixHandle);
2030:                                tokens.addToken(nameHandle);
2031:                            }
2032:                            break;
2033:                        }
2034:                    }
2035:                    if (XPath.Tokens.DUMP_TOKENS) {
2036:                        tokens.dumpTokens();
2037:                    }
2038:                    return true;
2039:                }
2040:
2041:                //
2042:                // [5] NCName ::= (Letter | '_') (NCNameChar)*
2043:                // [6] NCNameChar ::= Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender
2044:                //
2045:                int scanNCName(String data, int endOffset, int currentOffset) {
2046:                    int ch = data.charAt(currentOffset);
2047:                    if (ch >= 0x80) {
2048:                        if (!XMLChar.isNameStart(ch))
2049:                        /*** // REVISIT: Make sure this is a negation. ***
2050:                        if ((XMLCharacterProperties.fgCharFlags[ch] &
2051:                             XMLCharacterProperties.E_InitialNameCharFlag) == 0)
2052:                        /***/
2053:                        {
2054:                            return currentOffset;
2055:                        }
2056:                    } else {
2057:                        byte chartype = fASCIICharMap[ch];
2058:                        if (chartype != CHARTYPE_LETTER
2059:                                && chartype != CHARTYPE_UNDERSCORE) {
2060:                            return currentOffset;
2061:                        }
2062:                    }
2063:                    while (++currentOffset < endOffset) {
2064:                        ch = data.charAt(currentOffset);
2065:                        if (ch >= 0x80) {
2066:                            if (!XMLChar.isName(ch))
2067:                            /*** // REVISIT: Make sure this is a negation. ***
2068:                            if ((XMLCharacterProperties.fgCharFlags[ch] &
2069:                                 XMLCharacterProperties.E_NameCharFlag) == 0)
2070:                            /***/
2071:                            {
2072:                                break;
2073:                            }
2074:                        } else {
2075:                            byte chartype = fASCIICharMap[ch];
2076:                            if (chartype != CHARTYPE_LETTER
2077:                                    && chartype != CHARTYPE_DIGIT
2078:                                    && chartype != CHARTYPE_PERIOD
2079:                                    && chartype != CHARTYPE_MINUS
2080:                                    && chartype != CHARTYPE_UNDERSCORE) {
2081:                                break;
2082:                            }
2083:                        }
2084:                    }
2085:                    return currentOffset;
2086:                }
2087:
2088:                //
2089:                // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
2090:                // [31] Digits ::= [0-9]+
2091:                //
2092:                private int scanNumber(XPath.Tokens tokens,
2093:                        String/*byte[]*/data, int endOffset, int currentOffset/*, EncodingSupport encoding*/) {
2094:                    int ch = data.charAt(currentOffset);
2095:                    int whole = 0;
2096:                    int part = 0;
2097:                    while (ch >= '0' && ch <= '9') {
2098:                        whole = (whole * 10) + (ch - '0');
2099:                        if (++currentOffset == endOffset) {
2100:                            break;
2101:                        }
2102:                        ch = data.charAt(currentOffset);
2103:                    }
2104:                    if (ch == '.') {
2105:                        if (++currentOffset < endOffset) {
2106:                            /** int start = currentOffset; **/
2107:                            ch = data.charAt(currentOffset);
2108:                            while (ch >= '0' && ch <= '9') {
2109:                                part = (part * 10) + (ch - '0');
2110:                                if (++currentOffset == endOffset) {
2111:                                    break;
2112:                                }
2113:                                ch = data.charAt(currentOffset);
2114:                            }
2115:                            if (part != 0) {
2116:                                /***
2117:                                part = tokens.addSymbol(data, start, currentOffset - start, encoding);
2118:                                /***/
2119:                                throw new RuntimeException("find a solution!");
2120:                                //part = fStringPool.addSymbol(data.substring(start, currentOffset));
2121:                                /***/
2122:                            }
2123:                        }
2124:                    }
2125:                    tokens.addToken(whole);
2126:                    tokens.addToken(part);
2127:                    return currentOffset;
2128:                }
2129:
2130:                //
2131:                // Protected methods
2132:                //
2133:
2134:                /**
2135:                 * This method adds the specified token to the token list. By
2136:                 * default, this method allows all tokens. However, subclasses
2137:                 * of the XPathExprScanner can override this method in order
2138:                 * to disallow certain tokens from being used in the scanned
2139:                 * XPath expression. This is a convenient way of allowing only
2140:                 * a subset of XPath.
2141:                 */
2142:                protected void addToken(XPath.Tokens tokens, int token)
2143:                        throws XPathException {
2144:                    tokens.addToken(token);
2145:                } // addToken(int)
2146:
2147:            } // class Scanner
2148:
2149:            //
2150:            // MAIN
2151:            //
2152:
2153:            /** Main program entry. */
2154:            public static void main(String[] argv) throws Exception {
2155:
2156:                for (int i = 0; i < argv.length; i++) {
2157:                    final String expression = argv[i];
2158:                    System.out.println("# XPath expression: \"" + expression
2159:                            + '"');
2160:                    try {
2161:                        SymbolTable symbolTable = new SymbolTable();
2162:                        XPath xpath = new XPath(expression, symbolTable, null);
2163:                        System.out.println("expanded xpath: \""
2164:                                + xpath.toString() + '"');
2165:                    } catch (XPathException e) {
2166:                        System.out.println("error: " + e.getMessage());
2167:                    }
2168:                }
2169:
2170:            } // main(String[])
2171:
2172:        } // class XPath
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.