Source Code Cross Referenced for StaticQueryContext.java in  » XML » XPath-Saxon » net » sf » saxon » query » 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 » XPath Saxon » net.sf.saxon.query 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package net.sf.saxon.query;
0002:
0003:        import net.sf.saxon.Configuration;
0004:        import net.sf.saxon.event.Builder;
0005:        import net.sf.saxon.event.Stripper;
0006:        import net.sf.saxon.expr.*;
0007:        import net.sf.saxon.functions.ConstructorFunctionLibrary;
0008:        import net.sf.saxon.functions.FunctionLibrary;
0009:        import net.sf.saxon.functions.FunctionLibraryList;
0010:        import net.sf.saxon.functions.SystemFunctionLibrary;
0011:        import net.sf.saxon.instruct.*;
0012:        import net.sf.saxon.om.*;
0013:        import net.sf.saxon.sort.CodepointCollator;
0014:        import net.sf.saxon.sort.IntHashMap;
0015:        import net.sf.saxon.trans.StaticError;
0016:        import net.sf.saxon.trans.XPathException;
0017:        import net.sf.saxon.type.AtomicType;
0018:        import net.sf.saxon.type.SchemaType;
0019:        import org.xml.sax.SAXParseException;
0020:
0021:        import javax.xml.transform.Source;
0022:        import javax.xml.transform.SourceLocator;
0023:        import javax.xml.transform.TransformerException;
0024:        import java.io.IOException;
0025:        import java.io.InputStream;
0026:        import java.io.Reader;
0027:        import java.util.*;
0028:
0029:        /**
0030:         * StaticQueryContext is the implementation of StaticContext used when processing XQuery
0031:         * expressions.
0032:         * <p/>
0033:         * The StaticQueryContext object has two different usages. The application constructs a StaticQueryContext
0034:         * and initializes it with information about the context, for example, default namespaces, base URI, and so on.
0035:         * When a query is compiled using this StaticQueryContext, the query parser makes a copy of the StaticQueryContext
0036:         * and uses this internally, modifying it with information obtained from the query prolog, as well as information
0037:         * such as namespace and variable declarations that can occur at any point in the query. The query parser does
0038:         * not modify the original StaticQueryContext supplied by the calling application, which may therefore be used
0039:         * for compiling multiple queries, serially or even in multiple threads.
0040:         * <p/>
0041:         * This class forms part of Saxon's published XQuery API.
0042:         * Note that some of the methods are intended for use internally by the
0043:         * query processor itself: these are labelled as such. Methods that
0044:         * are considered stable are labelled with the JavaDoc "since" tag.
0045:         * The value 8.4 indicates a method introduced at or before Saxon 8.4; other
0046:         * values indicate the version at which the method was introduced.
0047:         * <p/>
0048:         * In the longer term, this entire API may at some stage be superseded by a proposed
0049:         * standard Java API for XQuery.
0050:         *
0051:         * @since 8.4
0052:         */
0053:
0054:        public class StaticQueryContext implements  StaticContext {
0055:
0056:            private boolean isMainModule;
0057:            private Configuration config;
0058:            private NamePool namePool;
0059:            private String locationURI;
0060:            private String moduleNamespace;
0061:            private String baseURI;
0062:            private HashMap passiveNamespaces;
0063:            private HashSet explicitPrologNamespaces;
0064:            private Stack activeNamespaces;
0065:            private boolean inheritNamespaces = true;
0066:            private boolean preserveNamespaces = true;
0067:            private NamespaceResolver externalNamespaceResolver = null;
0068:            private HashMap collations;
0069:            private IntHashMap variables; // global variables declared in this module
0070:            private IntHashMap libraryVariables; // all variables defined in library modules
0071:            // defined only on the top-level module
0072:            private IntHashMap undeclaredVariables;
0073:            private HashSet importedSchemata;
0074:            private String defaultCollationName;
0075:            private String defaultFunctionNamespace;
0076:            private short defaultElementNamespace;
0077:            private SlotManager stackFrameMap; // map of the outermost local stackframe
0078:            private short moduleNamespaceURICode;
0079:            private int constructionMode;
0080:            private Executable executable;
0081:            private List importers; // A list of StaticQueryContext objects representing the modules that import this one,
0082:            // Null for the main module
0083:            private FunctionLibraryList functionLibraryList;
0084:            private XQueryFunctionLibrary globalFunctionLibrary; // used only on a top-level module
0085:            //private XQueryFunctionLibrary localFunctionLibrary;       // contains functions declared in this module
0086:            //private ImportedFunctionLibrary importedFunctionLibrary;  // contains imported functions
0087:            //private UnboundFunctionLibrary unboundFunctionLibrary;
0088:            private int localFunctionLibraryNr;
0089:            private int importedFunctionLibraryNr;
0090:            private int unboundFunctionLibraryNr;
0091:            private Set importedModuleNamespaces;
0092:
0093:            /**
0094:             * Private constructor used when copying a context
0095:             */
0096:
0097:            private StaticQueryContext() {
0098:            }
0099:
0100:            /**
0101:             * Create a StaticQueryContext using a given Configuration. This creates a StaticQueryContext for a main module
0102:             * (that is, a module that is not a library module).
0103:             *
0104:             * @since 8.4
0105:             */
0106:
0107:            public StaticQueryContext(Configuration config) {
0108:                this .config = config;
0109:                this .namePool = config.getNamePool();
0110:                isMainModule = true;
0111:                reset();
0112:            }
0113:
0114:            /**
0115:             * Create a StaticQueryContext for a library module.
0116:             * @param importer the module that imported this module. This may be null, in which case the
0117:             * library module is treated as a "top-level" library module.
0118:             */
0119:
0120:            public StaticQueryContext(Configuration config,
0121:                    StaticQueryContext importer) {
0122:                this .config = config;
0123:                this .namePool = config.getNamePool();
0124:                isMainModule = false;
0125:                if (importers == null && importer != null) {
0126:                    importers = new ArrayList(2);
0127:                    importers.add(importer);
0128:                }
0129:                reset();
0130:            }
0131:
0132:            /**
0133:             * Reset the state of this StaticQueryContext to an uninitialized state
0134:             *
0135:             * @since 8.4
0136:             */
0137:
0138:            public void reset() {
0139:                passiveNamespaces = new HashMap(10);
0140:                explicitPrologNamespaces = new HashSet(10);
0141:                activeNamespaces = new Stack();
0142:                externalNamespaceResolver = null;
0143:                collations = new HashMap(5);
0144:                variables = new IntHashMap(10);
0145:                undeclaredVariables = new IntHashMap(5);
0146:                if (isTopLevelModule()) {
0147:                    globalFunctionLibrary = new XQueryFunctionLibrary(config);
0148:                    libraryVariables = new IntHashMap(10);
0149:                }
0150:                importedSchemata = new HashSet(5);
0151:                importedModuleNamespaces = new HashSet(5);
0152:                defaultFunctionNamespace = NamespaceConstant.FN;
0153:                defaultElementNamespace = NamespaceConstant.NULL_CODE;
0154:                moduleNamespace = null;
0155:                moduleNamespaceURICode = 0;
0156:                constructionMode = Validation.PRESERVE;
0157:                defaultCollationName = NamespaceConstant.CODEPOINT_COLLATION_URI;
0158:                declareCollation(defaultCollationName, CodepointCollator
0159:                        .getInstance());
0160:                functionLibraryList = new FunctionLibraryList();
0161:                functionLibraryList
0162:                        .addFunctionLibrary(new SystemFunctionLibrary(
0163:                                SystemFunctionLibrary.XPATH_ONLY));
0164:                functionLibraryList.addFunctionLibrary(config
0165:                        .getVendorFunctionLibrary());
0166:                functionLibraryList
0167:                        .addFunctionLibrary(new ConstructorFunctionLibrary(
0168:                                config));
0169:                if (config.isAllowExternalFunctions()) {
0170:                    functionLibraryList.addFunctionLibrary(config
0171:                            .getExtensionBinder());
0172:                }
0173:                localFunctionLibraryNr = functionLibraryList
0174:                        .addFunctionLibrary(new XQueryFunctionLibrary(config));
0175:
0176:                importedFunctionLibraryNr = functionLibraryList
0177:                        .addFunctionLibrary(new ImportedFunctionLibrary(
0178:                                getTopLevelModule(this )
0179:                                        .getGlobalFunctionLibrary()));
0180:
0181:                unboundFunctionLibraryNr = functionLibraryList
0182:                        .addFunctionLibrary(new UnboundFunctionLibrary());
0183:
0184:                clearPassiveNamespaces();
0185:            }
0186:
0187:            /**
0188:             * Test whether this is a "top-level" module. This is true for a main module and also for a
0189:             * module directly imported into an XSLT stylesheet. It may also be true in future for independently-compiled
0190:             * modules
0191:             */
0192:
0193:            public boolean isTopLevelModule() {
0194:                return importers == null;
0195:            }
0196:
0197:            /**
0198:             * Test whether this is a "main" module, in the sense of the XQuery language specification
0199:             */
0200:
0201:            public boolean isMainModule() {
0202:                return isMainModule;
0203:            }
0204:
0205:            /**
0206:             * Check whether this module is allowed to import a module with namespace N. Note that before
0207:             * calling this we have already handled the exception case where a module imports another in the same
0208:             * namespace (the only case where cycles are allowed)
0209:             */
0210:
0211:            public boolean mayImport(String namespace) {
0212:                if (namespace.equals(moduleNamespace)) {
0213:                    return false;
0214:                }
0215:                if (importers == null) {
0216:                    return true;
0217:                }
0218:                for (int i = 0; i < importers.size(); i++) {
0219:                    if (!((StaticQueryContext) importers.get(i))
0220:                            .mayImport(namespace)) {
0221:                        return false;
0222:                    }
0223:                }
0224:                return true;
0225:            }
0226:
0227:            public XQueryFunctionLibrary getGlobalFunctionLibrary() {
0228:                return globalFunctionLibrary;
0229:            }
0230:
0231:            public ImportedFunctionLibrary getImportedFunctionLibrary() {
0232:                return (ImportedFunctionLibrary) functionLibraryList
0233:                        .get(importedFunctionLibraryNr);
0234:            }
0235:
0236:            /**
0237:             * Register that this module imports a particular module namespace
0238:             */
0239:
0240:            public void addImportedNamespace(String uri) {
0241:                if (importedModuleNamespaces == null) {
0242:                    importedModuleNamespaces = new HashSet(5);
0243:                }
0244:                importedModuleNamespaces.add(uri);
0245:                getImportedFunctionLibrary().addImportedNamespace(uri);
0246:            }
0247:
0248:            /**
0249:             * Test whether this module directly imports a particular namespace
0250:             */
0251:
0252:            public boolean importsNamespace(String uri) {
0253:                return importedModuleNamespaces != null
0254:                        && importedModuleNamespaces.contains(uri);
0255:            }
0256:
0257:            /**
0258:             * Test whether this module imports a particular namespace directly or indirectly
0259:             */
0260:
0261:            public boolean importsNamespaceIndirectly(String uri) {
0262:                if (importsNamespace(uri)) {
0263:                    return true;
0264:                }
0265:                for (Iterator it = iterateImportedNamespaces(); it.hasNext();) {
0266:                    String moduleURI = (String) it.next();
0267:                    List list = executable.getQueryLibraryModules(moduleURI);
0268:                    for (Iterator i2 = list.iterator(); i2.hasNext();) {
0269:                        StaticQueryContext sqc = (StaticQueryContext) i2.next();
0270:                        if (sqc.importsNamespaceIndirectly(uri)) {
0271:                            return true;
0272:                        }
0273:                    }
0274:                }
0275:                return false;
0276:            }
0277:
0278:            /**
0279:             * Get an iterator over all the module namespaces that this module imports
0280:             */
0281:
0282:            public Iterator iterateImportedNamespaces() {
0283:                if (importedModuleNamespaces == null) {
0284:                    return Collections.EMPTY_LIST.iterator();
0285:                }
0286:                return importedModuleNamespaces.iterator();
0287:            }
0288:
0289:            /**
0290:             * Get the Static Query Context for the top-level module. This will normally be a main module,
0291:             * but in the case of saxon:import-query it will be the library module that is imported into
0292:             * the stylesheet
0293:             */
0294:
0295:            public StaticQueryContext getTopLevelModule(StaticQueryContext start) {
0296:                if (importers == null) {
0297:                    return this ;
0298:                }
0299:                // There may be import cycles of modules using the same namespace. So first we
0300:                // try to find an importer in a different namespace; if this fails we try the first
0301:                // importer. Somewhere in the cycle there must be a module that was imported from a different
0302:                // namespace (we hope!)
0303:                for (int i = 0; i < importers.size(); i++) {
0304:                    StaticQueryContext importer = (StaticQueryContext) importers
0305:                            .get(i);
0306:                    if (!start.importsNamespace(importer.getModuleNamespace())) {
0307:                        return importer.getTopLevelModule(start);
0308:                    }
0309:                }
0310:                return ((StaticQueryContext) importers.get(0))
0311:                        .getTopLevelModule(start);
0312:            }
0313:
0314:            /**
0315:             * Make a copy of this StaticQueryContext. The StaticQueryContext that is constructed by a user
0316:             * application and passed to Saxon when a query is compiled should not be modified by the query
0317:             * compiler. Saxon therefore makes a copy of the StaticQueryContext and uses this copy internally,
0318:             * to capture any changes to the StaticQueryContext defined in the query prolog.
0319:             *
0320:             * @return a copy of this StaticQueryContext
0321:             */
0322:
0323:            public StaticQueryContext copy() {
0324:                StaticQueryContext n = new StaticQueryContext();
0325:                n.config = config;
0326:                n.namePool = namePool;
0327:                n.isMainModule = isMainModule;
0328:                n.passiveNamespaces = new HashMap(passiveNamespaces);
0329:                n.explicitPrologNamespaces = new HashSet(
0330:                        explicitPrologNamespaces);
0331:                n.activeNamespaces = new Stack();
0332:                n.externalNamespaceResolver = externalNamespaceResolver;
0333:                n.inheritNamespaces = inheritNamespaces;
0334:                n.preserveNamespaces = preserveNamespaces;
0335:                n.collations = new HashMap(collations);
0336:                n.variables = variables.copy();
0337:                n.undeclaredVariables = undeclaredVariables.copy();
0338:                if (libraryVariables != null) {
0339:                    n.libraryVariables = libraryVariables.copy();
0340:                }
0341:                //n.variableList = new ArrayList(variableList);
0342:                n.importedSchemata = new HashSet(importedSchemata);
0343:                n.defaultCollationName = defaultCollationName;
0344:                n.defaultFunctionNamespace = defaultFunctionNamespace;
0345:                n.defaultElementNamespace = defaultElementNamespace;
0346:                n.locationURI = locationURI;
0347:                n.baseURI = baseURI;
0348:                n.stackFrameMap = stackFrameMap;
0349:                n.moduleNamespace = moduleNamespace;
0350:                n.moduleNamespaceURICode = moduleNamespaceURICode;
0351:                n.constructionMode = constructionMode;
0352:                n.executable = executable;
0353:                n.importers = importers;
0354:                n.functionLibraryList = (FunctionLibraryList) functionLibraryList
0355:                        .copy();
0356:                n.localFunctionLibraryNr = localFunctionLibraryNr;
0357:                n.importedFunctionLibraryNr = importedFunctionLibraryNr;
0358:                n.unboundFunctionLibraryNr = unboundFunctionLibraryNr;
0359:                n.globalFunctionLibrary = (XQueryFunctionLibrary) globalFunctionLibrary;
0360:                n.importedModuleNamespaces = new HashSet(
0361:                        importedModuleNamespaces);
0362:                return n;
0363:            }
0364:
0365:            /**
0366:             * Set the Configuration options
0367:             *
0368:             * @throws IllegalArgumentException if the configuration supplied is different from the existing
0369:             *                                  configuration
0370:             * @since 8.4
0371:             * @deprecated This method serves no purpose, since it is not possible to change the configuration
0372:             *             once the StaticQueryContext has been initialized.
0373:             */
0374:
0375:            public void setConfiguration(Configuration config) {
0376:                if (this .config != config) {
0377:                    throw new IllegalArgumentException(
0378:                            "Configuration cannot be changed dynamically");
0379:                }
0380:                this .config = config;
0381:            }
0382:
0383:            /**
0384:             * Get the Configuration options
0385:             *
0386:             * @since 8.4
0387:             */
0388:
0389:            public Configuration getConfiguration() {
0390:                return config;
0391:            }
0392:
0393:            /**
0394:             * Construct a dynamic context for early evaluation of constant subexpressions
0395:             */
0396:
0397:            public XPathContext makeEarlyEvaluationContext() {
0398:                return new EarlyEvaluationContext(this );
0399:            }
0400:
0401:            /**
0402:             * Convenience method for building Saxon's internal representation of a source XML
0403:             * document. The document will be built using the default NamePool, which means that
0404:             * any process that uses it must also use the default NamePool.
0405:             *
0406:             * @param source Any javax.xml.transform.Source object representing the document against
0407:             *               which queries will be executed. Note that a Saxon {@link net.sf.saxon.om.DocumentInfo DocumentInfo}
0408:             *               (indeed any {@link net.sf.saxon.om.NodeInfo NodeInfo})
0409:             *               can be used as a Source. To use a third-party DOM Document as a source, create an instance of
0410:             *               {@link javax.xml.transform.dom.DOMSource DOMSource} to wrap it.
0411:             *               <p>For additional control over the way in which the source document is processed,
0412:             *               supply an {@link net.sf.saxon.AugmentedSource AugmentedSource} object and set appropriate
0413:             *               options on the object.</p>
0414:             * @return the DocumentInfo representing the root node of the resulting document object.
0415:             * @since 8.4
0416:             */
0417:
0418:            public DocumentInfo buildDocument(Source source)
0419:                    throws XPathException {
0420:                Source s2 = config.getSourceResolver().resolveSource(source,
0421:                        config);
0422:                if (s2 != null) {
0423:                    source = s2;
0424:                }
0425:                Stripper stripper = null;
0426:                if (config.isStripsAllWhiteSpace()) {
0427:                    stripper = AllElementStripper.getInstance();
0428:                    stripper.setStripAll();
0429:                }
0430:                try {
0431:                    NodeInfo contextNode = Builder.build(source, stripper,
0432:                            config);
0433:                    return contextNode.getDocumentRoot();
0434:                } catch (XPathException err) {
0435:                    Throwable cause = err.getException();
0436:                    if (cause != null && cause instanceof  SAXParseException) {
0437:                        // This generally means the error was already reported.
0438:                        // But if a RuntimeException occurs in Saxon during a callback from
0439:                        // the Crimson parser, Crimson wraps this in a SAXParseException without
0440:                        // reporting it further.
0441:                        SAXParseException spe = (SAXParseException) cause;
0442:                        cause = spe.getException();
0443:                        if (cause instanceof  RuntimeException) {
0444:                            config.reportFatalError(err);
0445:                        }
0446:                    } else {
0447:                        while (err.getException() instanceof  XPathException) {
0448:                            err = (XPathException) err.getException();
0449:                        }
0450:                        config.reportFatalError(err);
0451:                    }
0452:                    throw err;
0453:                }
0454:            }
0455:
0456:            /**
0457:             * Prepare an XQuery query for subsequent evaluation. The source text of the query
0458:             * is supplied as a String. The base URI of the query is taken from the static context,
0459:             * and defaults to the current working directory.
0460:             *
0461:             * @param query The XQuery query to be evaluated, supplied as a string.
0462:             * @return an XQueryExpression object representing the prepared expression
0463:             * @throws net.sf.saxon.trans.XPathException
0464:             *          if the syntax of the expression is wrong,
0465:             *          or if it references namespaces, variables, or functions that have not been declared,
0466:             *          or contains other static errors.
0467:             * @since 8.4
0468:             */
0469:
0470:            public XQueryExpression compileQuery(String query)
0471:                    throws XPathException {
0472:                QueryParser qp = new QueryParser();
0473:                XQueryExpression queryExp = qp.makeXQueryExpression(query,
0474:                        copy(), config);
0475:                return queryExp;
0476:            }
0477:
0478:            /**
0479:             * Prepare an XQuery query for subsequent evaluation. The Query is supplied
0480:             * in the form of a Reader. The base URI of the query is taken from the static context,
0481:             * and defaults to the current working directory.
0482:             *
0483:             * @param source A Reader giving access to the text of the XQuery query to be compiled.
0484:             * @return an XPathExpression object representing the prepared expression.
0485:             * @throws net.sf.saxon.trans.XPathException
0486:             *                             if the syntax of the expression is wrong, or if it references namespaces,
0487:             *                             variables, or functions that have not been declared, or any other static error is reported.
0488:             * @throws java.io.IOException if a failure occurs reading the supplied input.
0489:             * @since 8.4
0490:             */
0491:
0492:            public XQueryExpression compileQuery(Reader source)
0493:                    throws XPathException, IOException {
0494:                char[] buffer = new char[4096];
0495:                StringBuffer sb = new StringBuffer(4096);
0496:                while (true) {
0497:                    int n = source.read(buffer);
0498:                    if (n > 0) {
0499:                        sb.append(buffer, 0, n);
0500:                    } else {
0501:                        break;
0502:                    }
0503:                }
0504:                return compileQuery(sb.toString());
0505:            }
0506:
0507:            /**
0508:             * Prepare an XQuery query for subsequent evaluation. The Query is supplied
0509:             * in the form of a InputStream, with an optional encoding. If the encoding is not specified,
0510:             * the query parser attempts to obtain the encoding by inspecting the input stream: it looks specifically
0511:             * for a byte order mark, and for the encoding option in the version declaration of an XQuery prolog.
0512:             * The encoding defaults to UTF-8.
0513:             * The base URI of the query is taken from the static context,
0514:             * and defaults to the current working directory.
0515:             *
0516:             * @param source   An InputStream giving access to the text of the XQuery query to be compiled, as a stream
0517:             *                 of octets
0518:             * @param encoding The encoding used to translate characters to octets in the query source. The parameter
0519:             *                 may be null: in this case the query parser attempts to infer the encoding by inspecting the source,
0520:             *                 and if that fails, it assumes UTF-8 encoding
0521:             * @return an XPathExpression object representing the prepared expression.
0522:             * @throws net.sf.saxon.trans.XPathException
0523:             *                             if the syntax of the expression is wrong, or if it references namespaces,
0524:             *                             variables, or functions that have not been declared, or any other static error is reported.
0525:             * @throws java.io.IOException if a failure occurs reading the supplied input.
0526:             * @since 8.5
0527:             */
0528:
0529:            public XQueryExpression compileQuery(InputStream source,
0530:                    String encoding) throws XPathException, IOException {
0531:                String query = QueryReader.readInputStream(source, encoding,
0532:                        config.getNameChecker());
0533:                return compileQuery(query);
0534:            }
0535:
0536:            /**
0537:             * Get the Executable, an object representing the compiled query and its environment.
0538:             * <p/>
0539:             * This method is intended for internal use only.
0540:             *
0541:             * @return the Executable
0542:             */
0543:
0544:            public Executable getExecutable() {
0545:                return executable;
0546:            }
0547:
0548:            /**
0549:             * Set the executable.
0550:             * <p/>
0551:             * This method is intended for internal use only.
0552:             *
0553:             * @param executable the Executable
0554:             */
0555:
0556:            public void setExecutable(Executable executable) {
0557:                this .executable = executable;
0558:            }
0559:
0560:            /**
0561:             * Get the LocationMap, an data structure used to identify the location of compiled expressions within
0562:             * the query source text.
0563:             * <p/>
0564:             * This method is intended for internal use only.
0565:             *
0566:             * @return the LocationMap
0567:             */
0568:
0569:            public LocationMap getLocationMap() {
0570:                return executable.getLocationMap();
0571:            }
0572:
0573:            /**
0574:             * Declare a namespace whose prefix can be used in expressions. This is
0575:             * a passive namespace, it won't be copied into the result tree. Passive
0576:             * namespaces are never undeclared, and active namespaces override them.
0577:             *
0578:             * @param prefix   The namespace prefix. Must not be null.
0579:             * @param uri      The namespace URI. Must not be null. The value "" (zero-length string) is used
0580:             *                 to undeclare a namespace; it is not an error if there is no existing binding for
0581:             *                 the namespace prefix.
0582:             * @param explicit This parameter is set to true when Saxon calls the method internally to
0583:             *                 define a namespace declared within the query prolog. It should normally be set to false
0584:             *                 in the case of a call from a user application.
0585:             * @since 8.4
0586:             */
0587:
0588:            public void declarePassiveNamespace(String prefix, String uri,
0589:                    boolean explicit) throws StaticError {
0590:                if (prefix == null) {
0591:                    throw new NullPointerException(
0592:                            "Null prefix supplied to declarePassiveNamespace()");
0593:                }
0594:                if (uri == null) {
0595:                    throw new NullPointerException(
0596:                            "Null namespace URI supplied to declarePassiveNamespace()");
0597:                }
0598:                if (explicit) {
0599:                    if (uri.equals("") && !prefix.equals("")) {
0600:                        explicitPrologNamespaces.remove(prefix);
0601:                    } else {
0602:                        if (explicitPrologNamespaces.contains(prefix)) {
0603:                            StaticError err = new StaticError(
0604:                                    "Duplicate declaration of namespace prefix \""
0605:                                            + prefix + '"');
0606:                            err.setErrorCode("XQST0033");
0607:                            throw err;
0608:                        } else {
0609:                            explicitPrologNamespaces.add(prefix);
0610:                        }
0611:                    }
0612:                }
0613:                if (uri.equals("") && !prefix.equals("")) {
0614:                    passiveNamespaces.remove(prefix);
0615:                } else {
0616:                    passiveNamespaces.put(prefix, uri);
0617:                    namePool.allocateNamespaceCode(prefix, uri);
0618:                }
0619:            }
0620:
0621:            /**
0622:             * Declare an active namespace, that is, a namespace which as well as affecting the static
0623:             * context of the query, will also be copied to the result tree when element constructors
0624:             * are evaluated. When searching for a prefix-URI binding, active namespaces are searched
0625:             * first, then passive namespaces. Active namespaces may be undeclared (in reverse sequence)
0626:             * using {@link #undeclareNamespace()}.
0627:             * <p/>
0628:             * This method is intended for internal use only.
0629:             */
0630:
0631:            public void declareActiveNamespace(String prefix, String uri) {
0632:                if (prefix == null) {
0633:                    throw new NullPointerException(
0634:                            "Null prefix supplied to declareActiveNamespace()");
0635:                }
0636:                if (uri == null) {
0637:                    throw new NullPointerException(
0638:                            "Null namespace URI supplied to declareActiveNamespace()");
0639:                }
0640:
0641:                int nscode = namePool.allocateNamespaceCode(prefix, uri);
0642:                ActiveNamespace entry = new ActiveNamespace();
0643:                entry.prefix = prefix;
0644:                entry.uri = uri;
0645:                entry.code = nscode;
0646:                activeNamespaces.push(entry);
0647:
0648:                if (prefix.equals("")) {
0649:                    defaultElementNamespace = (short) (nscode & 0xffff);
0650:                }
0651:
0652:            }
0653:
0654:            /**
0655:             * Undeclare the most recently-declared active namespace. This method is called
0656:             * when a namespace declaration goes out of scope (while processing an element end tag).
0657:             * It is NOT called when an XML 1.1-style namespace undeclaration is encountered.
0658:             * <p/>
0659:             * This method is intended for internal use only.
0660:             *
0661:             * @see #declareActiveNamespace(String, String)
0662:             */
0663:
0664:            public void undeclareNamespace() {
0665:                ActiveNamespace entry = (ActiveNamespace) activeNamespaces
0666:                        .pop();
0667:                if (entry.prefix.equals("")) {
0668:                    for (int i = activeNamespaces.size() - 1; i >= 0; i--) {
0669:                        if (((ActiveNamespace) activeNamespaces.get(i)).prefix
0670:                                .equals("")) {
0671:                            defaultElementNamespace = (short) (((ActiveNamespace) activeNamespaces
0672:                                    .get(i)).code & 0xffff);
0673:                            return;
0674:                        }
0675:                    }
0676:                    String defaultNS = (String) passiveNamespaces.get("");
0677:                    if ("".equals(defaultNS)) {
0678:                        defaultElementNamespace = NamespaceConstant.NULL_CODE;
0679:                    } else {
0680:                        defaultElementNamespace = getNamePool().getCodeForURI(
0681:                                defaultNS);
0682:                    }
0683:                }
0684:            }
0685:
0686:            /**
0687:             * Clear all the declared passive namespaces, except for the standard ones (xml, saxon, etc)
0688:             *
0689:             * @since 8.4
0690:             */
0691:
0692:            public void clearPassiveNamespaces() {
0693:                try {
0694:                    if (passiveNamespaces != null) {
0695:                        passiveNamespaces.clear();
0696:                        declarePassiveNamespace("xml", NamespaceConstant.XML,
0697:                                false);
0698:                        declarePassiveNamespace("saxon",
0699:                                NamespaceConstant.SAXON, false);
0700:                        declarePassiveNamespace("xs", NamespaceConstant.SCHEMA,
0701:                                false);
0702:                        declarePassiveNamespace("fn", NamespaceConstant.FN,
0703:                                false);
0704:                        declarePassiveNamespace("xdt", NamespaceConstant.XDT,
0705:                                false);
0706:                        declarePassiveNamespace("xsi",
0707:                                NamespaceConstant.SCHEMA_INSTANCE, false);
0708:                        declarePassiveNamespace("local",
0709:                                NamespaceConstant.LOCAL, false);
0710:                        declarePassiveNamespace("", "", false);
0711:                    }
0712:                } catch (StaticError staticError) {
0713:                    // can't happen when third argument is "false"
0714:                    throw new IllegalStateException(
0715:                            "Internal Failure initializing namespace declarations");
0716:                }
0717:            }
0718:
0719:            /**
0720:             * Set an external namespace resolver. If a namespace prefix cannot be resolved using any
0721:             * other mechanism, then as a last resort the external namespace resolver is called to
0722:             * obtain a URI for the given prefix.
0723:             * <p>
0724:             * Note that the external namespace resolver is used only for namespace prefixes that are
0725:             * resolved at compile time. Where namespace prefixes are resolved at run-time (which happens
0726:             * very rarely with XQuery: the only case is to resolve the computed name used in a computed
0727:             * element or attribute constructor), the external namespace resolver is not invoked.
0728:             * <p>
0729:             * Although the supplied object must implement the NamespaceResolver interface, the only method
0730:             * actually used is the method {@link NamespaceResolver#getURIForPrefix(String, boolean)}. Other
0731:             * methods may throw an UnsupportedOperationException.
0732:             */
0733:
0734:            public void setExternalNamespaceResolver(NamespaceResolver resolver) {
0735:                externalNamespaceResolver = resolver;
0736:            }
0737:
0738:            /**
0739:             * Get the external namespace resolver that has been registered using
0740:             * setExternalNamespaceResolver(), if any.
0741:             */
0742:
0743:            public NamespaceResolver getExternalNamespaceResolver() {
0744:                return externalNamespaceResolver;
0745:            }
0746:
0747:            /**
0748:             * Get the URI for a prefix.
0749:             * This method is used by the XQuery parser to resolve namespace prefixes.
0750:             * <p/>
0751:             * This method is intended primarily for internal use.
0752:             *
0753:             * @param prefix The prefix
0754:             * @return the corresponding namespace URI
0755:             * @throws net.sf.saxon.trans.XPathException
0756:             *          if the prefix has not been declared
0757:             */
0758:
0759:            public String getURIForPrefix(String prefix) throws XPathException {
0760:                String uri = checkURIForPrefix(prefix);
0761:                if (uri == null) {
0762:                    StaticError err = new StaticError("Prefix " + prefix
0763:                            + " has not been declared");
0764:                    err.setErrorCode("XPST0008");
0765:                    throw err;
0766:                }
0767:                return uri;
0768:            }
0769:
0770:            /**
0771:             * Get the URI for a prefix if there is one, return null if not.
0772:             * This method is used by the XQuery parser to resolve namespace prefixes.
0773:             * <p/>
0774:             * This method is intended primarily for internal use.
0775:             *
0776:             * @param prefix The prefix. Supply "" to obtain the default namespace.
0777:             * @return the corresponding namespace URI, or null if the prefix has not
0778:             *         been declared. If the prefix is "" and the default namespace is the non-namespace,
0779:             *         return "".
0780:             */
0781:
0782:            public String checkURIForPrefix(String prefix) {
0783:                // Search the active namespaces first, then the passive ones.
0784:                for (int i = activeNamespaces.size() - 1; i >= 0; i--) {
0785:                    if (((ActiveNamespace) activeNamespaces.get(i)).prefix
0786:                            .equals(prefix)) {
0787:                        return ((ActiveNamespace) activeNamespaces.get(i)).uri;
0788:                    }
0789:                }
0790:                String uri = (String) passiveNamespaces.get(prefix);
0791:                if (uri != null) {
0792:                    return uri;
0793:                }
0794:                if (externalNamespaceResolver != null) {
0795:                    return externalNamespaceResolver.getURIForPrefix(prefix,
0796:                            true);
0797:                }
0798:                return null;
0799:            }
0800:
0801:            /**
0802:             * Get an array containing the namespace codes of all active
0803:             * namespaces.
0804:             * <p/>
0805:             * This method is for internal use only.
0806:             */
0807:
0808:            public int[] getActiveNamespaceCodes() {
0809:                int[] nscodes = new int[activeNamespaces.size()];
0810:                int used = 0;
0811:                HashSet prefixes = new HashSet(10);
0812:                for (int n = activeNamespaces.size() - 1; n >= 0; n--) {
0813:                    ActiveNamespace an = (ActiveNamespace) activeNamespaces
0814:                            .get(n);
0815:                    if (!prefixes.contains(an.prefix)) {
0816:                        prefixes.add(an.prefix);
0817:                        nscodes[used++] = an.code;
0818:                    }
0819:                }
0820:                if (used < nscodes.length) {
0821:                    int[] nscodes2 = new int[used];
0822:                    System.arraycopy(nscodes, 0, nscodes2, 0, used);
0823:                    nscodes = nscodes2;
0824:                }
0825:                return nscodes;
0826:            }
0827:
0828:            /**
0829:             * Get a copy of the Namespace Context. This method is used internally
0830:             * by the query parser when a construct is encountered that needs
0831:             * to save the namespace context for use at run-time.
0832:             * <p/>
0833:             * This method is for internal use only.
0834:             */
0835:
0836:            public NamespaceResolver getNamespaceResolver() {
0837:                int[] active = getActiveNamespaceCodes();
0838:                int[] nscodes = new int[passiveNamespaces.size()
0839:                        + active.length];
0840:
0841:                int used = 0;
0842:                for (Iterator iter = passiveNamespaces.keySet().iterator(); iter
0843:                        .hasNext();) {
0844:                    String prefix = (String) iter.next();
0845:                    String uri = (String) passiveNamespaces.get(prefix);
0846:                    nscodes[used++] = namePool.getNamespaceCode(prefix, uri);
0847:                    ;
0848:                }
0849:                for (int a = 0; a < active.length; a++) {
0850:                    nscodes[used++] = active[a];
0851:                }
0852:
0853:                return new SavedNamespaceContext(nscodes, namePool);
0854:            }
0855:
0856:            /**
0857:             * Get the default function namespace
0858:             *
0859:             * @return the default function namespace (defaults to the fn: namespace)
0860:             * @since 8.4
0861:             */
0862:
0863:            public String getDefaultFunctionNamespace() {
0864:                return defaultFunctionNamespace;
0865:            }
0866:
0867:            /**
0868:             * Set the default function namespace
0869:             *
0870:             * @param defaultFunctionNamespace The namespace to be used for unprefixed function calls
0871:             * @since 8.4
0872:             */
0873:
0874:            public void setDefaultFunctionNamespace(
0875:                    String defaultFunctionNamespace) {
0876:                this .defaultFunctionNamespace = defaultFunctionNamespace;
0877:            }
0878:
0879:            /**
0880:             * Set the default element namespace
0881:             *
0882:             * @since 8.4
0883:             */
0884:
0885:            public void setDefaultElementNamespace(String uri)
0886:                    throws StaticError {
0887:                int nscode = namePool.allocateNamespaceCode("", uri);
0888:                defaultElementNamespace = (short) (nscode & 0xffff);
0889:                declarePassiveNamespace("", uri, true);
0890:            }
0891:
0892:            /**
0893:             * Get the default XPath namespace, as a namespace URI code that can be looked up in the NamePool
0894:             *
0895:             * @since 8.4
0896:             */
0897:
0898:            public short getDefaultElementNamespace() {
0899:                return defaultElementNamespace;
0900:            }
0901:
0902:            /**
0903:             * Set the namespace for a library module.
0904:             * <p/>
0905:             * This method is for internal use only.
0906:             */
0907:
0908:            public void setModuleNamespace(String uri) {
0909:                moduleNamespace = uri;
0910:                moduleNamespaceURICode = namePool.getCodeForURI(uri);
0911:            }
0912:
0913:            /**
0914:             * Get the namespace of the current library module.
0915:             * <p/>
0916:             * This method is intended primarily for internal use.
0917:             *
0918:             * @return the module namespace, or null if this is a main module
0919:             */
0920:
0921:            public String getModuleNamespace() {
0922:                return moduleNamespace;
0923:            }
0924:
0925:            /**
0926:             * Get the namesapce code of the current library module.
0927:             * <p/>
0928:             * This method is intended primarily for internal use.
0929:             *
0930:             * @return the module namespace, or null if this is a main module
0931:             */
0932:
0933:            public short getModuleNamespaceCode() {
0934:                return moduleNamespaceURICode;
0935:            }
0936:
0937:            /**
0938:             * Set the location URI for a module
0939:             */
0940:
0941:            public void setLocationURI(String uri) {
0942:                locationURI = uri;
0943:            }
0944:
0945:            /**
0946:             * Get the location URI for a module
0947:             */
0948:
0949:            public String getLocationURI() {
0950:                return locationURI;
0951:            }
0952:
0953:            /**
0954:             * Set the namespace inheritance mode
0955:             *
0956:             * @param inherit true if namespaces are inherited, false if not
0957:             * @since 8.4
0958:             */
0959:
0960:            public void setInheritNamespaces(boolean inherit) {
0961:                inheritNamespaces = inherit;
0962:            }
0963:
0964:            /**
0965:             * Get the namespace inheritance mode
0966:             *
0967:             * @return true if namespaces are inherited, false if not
0968:             * @since 8.4
0969:             */
0970:
0971:            public boolean isInheritNamespaces() {
0972:                return inheritNamespaces;
0973:            }
0974:
0975:            /**
0976:             * Set the namespace copy mode
0977:             *
0978:             * @param inherit true if namespaces are preserved, false if not
0979:             * @since 8.4
0980:             */
0981:
0982:            public void setPreserveNamespaces(boolean inherit) {
0983:                preserveNamespaces = inherit;
0984:            }
0985:
0986:            /**
0987:             * Get the namespace copy mode
0988:             *
0989:             * @return true if namespaces are preserved, false if not
0990:             * @since 8.4
0991:             */
0992:
0993:            public boolean isPreserveNamespaces() {
0994:                return preserveNamespaces;
0995:            }
0996:
0997:            /**
0998:             * Declare a named collation. Collations are only available in a query if this method
0999:             * has been called externally to declare the collation and associate it with an
1000:             * implementation, in the form of a Java Comparator. The default collation is the
1001:             * Unicode codepoint collation, unless otherwise specified.
1002:             *
1003:             * @param name       The name of the collation (technically, a URI)
1004:             * @param comparator The Java Comparator used to implement the collating sequence
1005:             * @since 8.4
1006:             */
1007:
1008:            public void declareCollation(String name, Comparator comparator) {
1009:                collations.put(name, comparator);
1010:            }
1011:
1012:            /**
1013:             * Set the default collation.
1014:             * @param name The collation name, as specified in the query prolog. The name
1015:             * is not validated until it is used.
1016:             * @since 8.4. Changed in 8.6 so it no longer validates the collation name: this is
1017:             * because the base URI is not necessarily known at the point where the default
1018:             * collation is declared.
1019:             */
1020:
1021:            public void declareDefaultCollation(String name) {
1022:                defaultCollationName = name;
1023:            }
1024:
1025:            /**
1026:             * Get a named collation.
1027:             * @param name the name of the collation, as an absolute URI
1028:             * @return the collation identified by the given name, as set previously using declareCollation.
1029:             *         If no collation with this name has been declared, the method calls the CollationURIResolver
1030:             *         to locate a collation with this name.
1031:             *         Return null if no collation with this name is found.
1032:             * @since 8.4
1033:             */
1034:
1035:            public Comparator getCollation(String name) {
1036:                Comparator c = (Comparator) collations.get(name);
1037:                if (c != null) {
1038:                    return c;
1039:                }
1040:                return config.getCollationURIResolver().resolve(name,
1041:                        getBaseURI(), config);
1042:            }
1043:
1044:            /**
1045:             * Get the name of the default collation.
1046:             *
1047:             * @return the name of the default collation; or the name of the codepoint collation
1048:             *         if no default collation has been defined. The name is returned in the form
1049:             *         it was specified; that is, it is not yet resolved against the base URI. (This
1050:             *         is because the base URI declaration can follow the default collation declaration
1051:             *         in the query prolog.) If no default collation has been specified, the "default default"
1052:             *         (that is, the Unicode codepoint collation) is returned.
1053:             * @since 8.4
1054:             */
1055:
1056:            public String getDefaultCollationName() {
1057:                if (defaultCollationName != null) {
1058:                    return defaultCollationName;
1059:                } else {
1060:                    return NamespaceConstant.CODEPOINT_COLLATION_URI;
1061:                }
1062:            }
1063:
1064:            /**
1065:             * Get a HashMap that maps all registered collations to Comparators.
1066:             * Note that this returns a snapshot copy of the data held by the static context.
1067:             * This method is provided for internal use by the query processor.
1068:             * <p/>
1069:             * This method is intended for internal use.
1070:             */
1071:
1072:            public HashMap getAllCollations() {
1073:                return new HashMap(collations);
1074:            }
1075:
1076:            /**
1077:             * Get the stack frame map for global variables.
1078:             * <p/>
1079:             * This method is intended for internal use.
1080:             */
1081:
1082:            public SlotManager getGlobalStackFrameMap() {
1083:                return executable.getGlobalVariableMap();
1084:            }
1085:
1086:            /**
1087:             * Declare a global variable. A variable must normally be declared before an expression referring
1088:             * to it is compiled, but there are exceptions where a set of modules in the same namespace
1089:             * import each other cyclically. Global variables are normally declared in the Query Prolog, but
1090:             * they can also be predeclared using this API. All global variables are held in the StaticQueryContext
1091:             * for the main module. The fact that a global variable is present therefore does not mean that it
1092:             * is visible: there are two additional conditions (a) the namespace must be imported into the
1093:             * module where the reference appears, and (b) the declaration must not be in the same module and textually
1094:             * after the reference.
1095:             *
1096:             * @since 8.4
1097:             */
1098:
1099:            public void declareVariable(VariableDeclaration var)
1100:                    throws StaticError {
1101:                int key = var.getNameCode() & NamePool.FP_MASK;
1102:                if (variables.get(key) != null) {
1103:                    GlobalVariableDefinition old = (GlobalVariableDefinition) variables
1104:                            .get(key);
1105:                    if (old == var) {
1106:                        // do nothing
1107:                    } else {
1108:                        StaticError err = new StaticError(
1109:                                "Duplicate definition of global variable "
1110:                                        + var.getVariableName() + " (see line "
1111:                                        + old.getLineNumber() /*+ " in module " + old.getSystemId()*/
1112:                                        + ')');
1113:                        err.setErrorCode("XQST0049");
1114:                        if (var instanceof  GlobalVariableDefinition) {
1115:                            ExpressionLocation loc = new ExpressionLocation();
1116:                            loc.setLineNumber(((GlobalVariableDefinition) var)
1117:                                    .getLineNumber());
1118:                            loc.setSystemId(((GlobalVariableDefinition) var)
1119:                                    .getSystemId());
1120:                            err.setLocator(loc);
1121:                        }
1122:                        throw err;
1123:                    }
1124:                }
1125:                variables.put(key, var);
1126:                if (!isTopLevelModule()) {
1127:                    final IntHashMap libVars = getTopLevelModule(this ).libraryVariables;
1128:                    GlobalVariableDefinition old = (GlobalVariableDefinition) libVars
1129:                            .get(key);
1130:                    if (old == null || old == var) {
1131:                        // do nothing
1132:                    } else {
1133:                        StaticError err = new StaticError(
1134:                                "Duplicate definition of global variable "
1135:                                        + var.getVariableName() + " (see line "
1136:                                        + old.getLineNumber() + " in module "
1137:                                        + old.getSystemId() + ')');
1138:                        err.setErrorCode("XQST0049");
1139:                        if (var instanceof  GlobalVariableDefinition) {
1140:                            ExpressionLocation loc = new ExpressionLocation();
1141:                            loc.setLineNumber(((GlobalVariableDefinition) var)
1142:                                    .getLineNumber());
1143:                            loc.setSystemId(((GlobalVariableDefinition) var)
1144:                                    .getSystemId());
1145:                            err.setLocator(loc);
1146:                        }
1147:                        throw err;
1148:                    }
1149:
1150:                    libVars.put(key, var);
1151:                }
1152:            }
1153:
1154:            /**
1155:             * Fixup all references to global variables.
1156:             * <p/>
1157:             * This method is for internal use by the Query Parser only.
1158:             */
1159:
1160:            public List fixupGlobalVariables(SlotManager globalVariableMap)
1161:                    throws StaticError {
1162:                List compiledVars = new ArrayList(20);
1163:                Iterator[] iters = { variables.valueIterator(),
1164:                        libraryVariables.valueIterator() };
1165:                for (int i = 0; i < 2; i++) {
1166:                    while (iters[i].hasNext()) {
1167:                        GlobalVariableDefinition var = (GlobalVariableDefinition) iters[i]
1168:                                .next();
1169:                        try {
1170:                            int slot = globalVariableMap.allocateSlotNumber(var
1171:                                    .getNameCode()
1172:                                    & NamePool.FP_MASK);
1173:                            GlobalVariable gv = var.getCompiledVariable();
1174:                            if (gv == null) {
1175:                                gv = var.compile(this , slot);
1176:                            }
1177:                            if (!compiledVars.contains(gv)) {
1178:                                compiledVars.add(gv);
1179:                            }
1180:                        } catch (XPathException err) {
1181:                            throw StaticError.makeStaticError(err);
1182:                        }
1183:                    }
1184:                }
1185:                return compiledVars;
1186:            }
1187:
1188:            /**
1189:             * Get global variables declared in this module
1190:             * @return an Iterator whose items are GlobalVariableDefinition objects
1191:             */
1192:
1193:            public Iterator getModuleVariables() {
1194:                return variables.valueIterator();
1195:            }
1196:
1197:            /**
1198:             * Get references to undeclared variables.
1199:             * @return a list of XPathException objects, one for each undeclared variable
1200:             */
1201:
1202:            public List getUndeclaredVariables(SlotManager globalVariableMap)
1203:                    throws StaticError {
1204:                List undeclaredVars = new ArrayList(20);
1205:                Iterator iter = variables.valueIterator();
1206:                while (iter.hasNext()) {
1207:                    GlobalVariableDefinition var = (GlobalVariableDefinition) iter
1208:                            .next();
1209:                    if (var instanceof  UndeclaredVariable) {
1210:                        Iterator refs = var.iterateReferences();
1211:                        while (refs.hasNext()) {
1212:                            VariableReference ref = (VariableReference) refs
1213:                                    .next();
1214:                            StaticError err = new StaticError(
1215:                                    "Unresolved reference to variable $"
1216:                                            + var.getVariableName());
1217:                            err.setLocator(ref);
1218:                            err.setErrorCode("XPST0008");
1219:                            undeclaredVars.add(err);
1220:                        }
1221:                        // Note: not an error if there are no references
1222:                    } else {
1223:                        // A GlobalVariableDeclaration that was introduced by importing may still need to have its
1224:                        // references bound
1225:                        Iterator refs = var.iterateReferences();
1226:                        while (refs.hasNext()) {
1227:                            VariableReference ref = (VariableReference) refs
1228:                                    .next();
1229:                            if (ref.getBinding() == null) {
1230:                                ref.fixup(var.getCompiledVariable());
1231:                            }
1232:                        }
1233:                    }
1234:                }
1235:                return undeclaredVars;
1236:            }
1237:
1238:            public void typeCheckGlobalVariables(List compiledVars)
1239:                    throws StaticError {
1240:                try {
1241:                    Iterator iter = compiledVars.iterator();
1242:                    Stack stack = new Stack();
1243:                    while (iter.hasNext()) {
1244:                        GlobalVariable gv = (GlobalVariable) iter.next();
1245:                        gv.lookForCycles(stack);
1246:                        GlobalVariableDefinition.typeCheck(this , gv);
1247:                    }
1248:                } catch (XPathException e) {
1249:                    throw StaticError.makeStaticError(e);
1250:                }
1251:            }
1252:
1253:            /**
1254:             * Produce "explain" output for all global variables.
1255:             * <p/>
1256:             * This method is intended primarily for internal use.
1257:             */
1258:
1259:            public void explainGlobalVariables() {
1260:                Iterator iter = variables.valueIterator();
1261:                while (iter.hasNext()) {
1262:                    GlobalVariableDefinition var = (GlobalVariableDefinition) iter
1263:                            .next();
1264:                    var.explain(getNamePool());
1265:                }
1266:            }
1267:
1268:            /**
1269:             * Get an iterator over the variables defined in this module.
1270:             * <p/>
1271:             * This method is intended primarily for internal use.
1272:             *
1273:             * @return an Iterator, whose items are VariableDeclaration objects.  It returns
1274:             *         all variables known to this module including those imported from elsewhere; they
1275:             *         can be distinguished by their namespace. The variables are returned in order of
1276:             *         declaration.
1277:             */
1278:
1279:            //    public Iterator getVariableDeclarations() {
1280:            //        return variableList.iterator();
1281:            //    }
1282:            /**
1283:             * Get the stack frame map for local variables in the "main" query expression.
1284:             * <p/>
1285:             * This method is intended for internal use only.
1286:             */
1287:
1288:            public SlotManager getStackFrameMap() {
1289:                if (stackFrameMap == null) {
1290:                    stackFrameMap = getConfiguration().makeSlotManager();
1291:                }
1292:                return stackFrameMap;
1293:            }
1294:
1295:            /**
1296:             * Get the NamePool used for compiling expressions
1297:             *
1298:             * @since 8.4
1299:             */
1300:
1301:            public NamePool getNamePool() {
1302:                return namePool;
1303:            }
1304:
1305:            /**
1306:             * Issue a compile-time warning. This method is used during XQuery expression compilation to
1307:             * output warning conditions.
1308:             * <p/>
1309:             * This method is intended for internal use only.
1310:             */
1311:
1312:            public void issueWarning(String s, SourceLocator locator) {
1313:                StaticError err = new StaticError(s);
1314:                err.setLocator(locator);
1315:                try {
1316:                    config.getErrorListener().warning(err);
1317:                } catch (TransformerException e) {
1318:                    // ignore any error thrown
1319:                }
1320:            }
1321:
1322:            /**
1323:             * Set the Base URI of the query
1324:             *
1325:             * @since 8.4
1326:             */
1327:
1328:            public void setBaseURI(String baseURI) {
1329:                this .baseURI = baseURI;
1330:            }
1331:
1332:            /**
1333:             * Get the system ID of the container of the expression. Used to construct error messages.
1334:             * Note that the systemID and the Base URI are currently identical, but they might be distinguished
1335:             * in the future.
1336:             *
1337:             * @return the Base URI
1338:             * @since 8.4
1339:             */
1340:
1341:            public String getSystemId() {
1342:                return baseURI;
1343:            }
1344:
1345:            /**
1346:             * Get the Base URI of the query, for resolving any relative URI's used
1347:             * in the expression.
1348:             * Note that the systemID and the Base URI are currently identical, but they might be distinguished
1349:             * in the future.
1350:             * Used by the document() function.
1351:             *
1352:             * @return the base URI of the query
1353:             * @since 8.4
1354:             */
1355:
1356:            public String getBaseURI() {
1357:                return baseURI;
1358:            }
1359:
1360:            /**
1361:             * Get the line number of the expression within that container.
1362:             * Used to construct error messages. This method is provided to satisfy the StaticContext interface,
1363:             * but the value is meaningful only for XPath expressions within a document such as a stylesheet.
1364:             *
1365:             * @return -1 always
1366:             */
1367:
1368:            public int getLineNumber() {
1369:                return -1;
1370:            }
1371:
1372:            /**
1373:             * Bind a variable used in a query to the expression in which it is declared.
1374:             * <p/>
1375:             * This method is provided for use by the XQuery parser, and it should not be called by the user of
1376:             * the API, or overridden, unless variables are to be declared using a mechanism other than the
1377:             * declareVariable method of this class.
1378:             */
1379:
1380:            public VariableReference bindVariable(int fingerprint)
1381:                    throws StaticError {
1382:                VariableDeclaration var = (VariableDeclaration) variables
1383:                        .get(fingerprint);
1384:                if (var == null) {
1385:                    String uri = getNamePool().getURI(fingerprint);
1386:                    //String local = getNamePool().getLocalName(fingerprint);
1387:                    if (importedModuleNamespaces.contains(uri)) {
1388:                        StaticQueryContext main = getTopLevelModule(this );
1389:                        var = (VariableDeclaration) main.libraryVariables
1390:                                .get(fingerprint);
1391:                        if (var == null) {
1392:                            // If the namespace has been imported there's the possibility that
1393:                            // the variable declaration hasn't yet been read, because of the limited provision
1394:                            // for cyclic imports
1395:                            UndeclaredVariable uvar = new UndeclaredVariable();
1396:                            uvar.setNameCode(fingerprint);
1397:                            uvar.setVariableName(getNamePool().getDisplayName(
1398:                                    fingerprint));
1399:                            VariableReference ref = new VariableReference(uvar);
1400:                            undeclaredVariables.put(fingerprint, uvar);
1401:                            return ref;
1402:                        }
1403:                    } else {
1404:                        // If the namespace hasn't been imported then we might as well throw the error right away
1405:                        StaticError err = new StaticError(
1406:                                "Unresolved reference to variable");
1407:                        // the message isn't used...
1408:                        throw err;
1409:                    }
1410:                }
1411:                return new VariableReference(var);
1412:            }
1413:
1414:            /**
1415:             * Set the function library used for binding any function call appearing within the query module.
1416:             * <p/>
1417:             * This method is available for use by advanced applications. The details of the FunctionLibrary
1418:             * interface are subject to change. Applications using this interface take responsibility for
1419:             * ensuring that the results conform to the constraints imposed by the XQuery language specification,
1420:             * for example that one function within a query module can call other functions defined in the same
1421:             * query module.
1422:             *
1423:             * @param functionLibrary the FunctionLibrary to be used. This will typically be a
1424:             *                        FunctionLibraryList; in most cases it will be a slightly modified copy of a FunctionLibraryList
1425:             *                        constructed by the system and obtained using the {@link #getFunctionLibrary} method.
1426:             * @see FunctionLibraryList
1427:             */
1428:
1429:            public void setFunctionLibraryList(
1430:                    FunctionLibraryList functionLibrary) {
1431:                this .functionLibraryList = functionLibrary;
1432:            }
1433:
1434:            /**
1435:             * Get the function library containing all the in-scope functions available in this static
1436:             * context (that is, the functions available in this query module).
1437:             * <p/>
1438:             * This method is provided for use by advanced applications.
1439:             * The details of the interface are subject to change.
1440:             *
1441:             * @return the FunctionLibrary used. For XQuery, this will always be a FunctionLibraryList.
1442:             * @see FunctionLibraryList
1443:             */
1444:
1445:            public FunctionLibrary getFunctionLibrary() {
1446:                return functionLibraryList;
1447:            }
1448:
1449:            /**
1450:             * Get the functions declared locally within this module
1451:             */
1452:
1453:            public XQueryFunctionLibrary getLocalFunctionLibrary() {
1454:                return (XQueryFunctionLibrary) functionLibraryList
1455:                        .get(localFunctionLibraryNr);
1456:            }
1457:
1458:            /**
1459:             * Register a user-defined XQuery function.
1460:             * <p/>
1461:             * This method is intended for internal use only.
1462:             */
1463:
1464:            public void declareFunction(XQueryFunction function)
1465:                    throws StaticError {
1466:                if (function.getNumberOfArguments() == 1) {
1467:                    SchemaType t = config.getSchemaType(function.getNameCode()
1468:                            & NamePool.FP_MASK);
1469:                    if (t != null && t instanceof  AtomicType) {
1470:                        StaticError err = new StaticError(
1471:                                "Function name "
1472:                                        + function
1473:                                                .getFunctionDisplayName(getNamePool())
1474:                                        + " clashes with the name of the constructor function for an atomic type");
1475:                        err.setErrorCode("XQST0034");
1476:                        throw err;
1477:                    }
1478:                }
1479:                XQueryFunctionLibrary local = getLocalFunctionLibrary();
1480:                local.declareFunction(function);
1481:                StaticQueryContext main = getTopLevelModule(this );
1482:                main.globalFunctionLibrary.declareFunction(function);
1483:            }
1484:
1485:            /**
1486:             * Bind function calls that could not be bound when first encountered. These
1487:             * will either be forwards references to functions declared later in the same query module,
1488:             * or in modules that are being imported recursively, or errors.
1489:             * <p/>
1490:             * This method is for internal use only.
1491:             *
1492:             * @throws net.sf.saxon.trans.StaticError if a function call refers to a function that has
1493:             *                                        not been declared
1494:             */
1495:
1496:            public void bindUnboundFunctionCalls() throws XPathException {
1497:                UnboundFunctionLibrary lib = (UnboundFunctionLibrary) functionLibraryList
1498:                        .get(unboundFunctionLibraryNr);
1499:                lib.bindUnboundFunctionCalls(functionLibraryList, config);
1500:            }
1501:
1502:            /**
1503:             * Fixup all references to global functions. This method is called
1504:             * on completion of query parsing. Each XQueryFunction is required to
1505:             * bind all references to that function to the object representing the run-time
1506:             * executable code of the function.
1507:             * <p/>
1508:             * This method is for internal use only.
1509:             */
1510:
1511:            public void fixupGlobalFunctions() throws XPathException {
1512:                globalFunctionLibrary.fixupGlobalFunctions(this );
1513:            }
1514:
1515:            /**
1516:             * Output "explain" information about each declared function.
1517:             * <p/>
1518:             * This method is intended primarily for internal use.
1519:             */
1520:
1521:            public void explainGlobalFunctions() throws XPathException {
1522:                globalFunctionLibrary.explainGlobalFunctions();
1523:            }
1524:
1525:            /**
1526:             * Get the function with a given name and arity. This method is provided so that XQuery functions
1527:             * can be called directly from a Java application. Note that there is no type checking or conversion
1528:             * of arguments when this is done: the arguments must be provided in exactly the form that the function
1529:             * signature declares them.
1530:             *
1531:             * @param uri       the uri of the function name
1532:             * @param localName the local part of the function name
1533:             * @param arity     the number of arguments.
1534:             * @since 8.4
1535:             */
1536:
1537:            public UserFunction getUserDefinedFunction(String uri,
1538:                    String localName, int arity) {
1539:                return globalFunctionLibrary.getUserDefinedFunction(uri,
1540:                        localName, arity);
1541:            }
1542:
1543:            /**
1544:             * Bind unbound variables (these are typically variables that reference another module
1545:             * participating in a same-namespace cycle, since local forwards references are not allowed
1546:             */
1547:
1548:            public void bindUnboundVariables() throws XPathException {
1549:                for (Iterator iter = undeclaredVariables.valueIterator(); iter
1550:                        .hasNext();) {
1551:                    UndeclaredVariable uv = (UndeclaredVariable) iter.next();
1552:                    int fingerprint = uv.getNameCode() & NamePool.FP_MASK;
1553:                    VariableDeclaration var = (VariableDeclaration) variables
1554:                            .get(fingerprint);
1555:                    if (var == null) {
1556:                        String uri = getNamePool().getURI(fingerprint);
1557:                        if (importedModuleNamespaces.contains(uri)) {
1558:                            StaticQueryContext main = getTopLevelModule(this );
1559:                            var = (VariableDeclaration) main.libraryVariables
1560:                                    .get(fingerprint);
1561:                        }
1562:                    }
1563:                    if (var == null) {
1564:                        StaticError err = new StaticError(
1565:                                "Unresolved reference to variable $"
1566:                                        + uv.getVariableName());
1567:                        err.setErrorCode("XPST0008");
1568:                        throw err;
1569:                    } else {
1570:                        uv.transferReferences(var);
1571:                    }
1572:                }
1573:            }
1574:
1575:            /**
1576:             * Determine whether Backwards Compatible Mode is used
1577:             *
1578:             * @return false; XPath 1.0 compatibility mode is not supported in XQuery
1579:             * @since 8.4
1580:             */
1581:
1582:            public boolean isInBackwardsCompatibleMode() {
1583:                return false;
1584:            }
1585:
1586:            /**
1587:             * Add an imported schema to this static context. A query module can reference
1588:             * types in a schema provided two conditions are satisfied: the schema containing those
1589:             * types has been loaded into the Configuration, and the target namespace has been imported
1590:             * by this query module. This method achieves the second of these conditions. It does not
1591:             * cause the schema to be loaded.
1592:             * <p/>
1593:             *
1594:             * @param targetNamespace The target namespace of the schema to be added
1595:             * @since 8.4
1596:             */
1597:
1598:            public void addImportedSchema(String targetNamespace) {
1599:                if (importedSchemata == null) {
1600:                    importedSchemata = new HashSet(5);
1601:                }
1602:                importedSchemata.add(targetNamespace);
1603:            }
1604:
1605:            /**
1606:             * Get the schema for a given namespace, if it has been imported
1607:             *
1608:             * @param namespace The namespace of the required schema. Supply "" for
1609:             *                  a no-namespace schema.
1610:             * @return The schema if found, or null if not found.
1611:             * @since 8.4
1612:             */
1613:
1614:            public boolean isImportedSchema(String namespace) {
1615:                if (importedSchemata == null) {
1616:                    return false;
1617:                }
1618:                return importedSchemata.contains(namespace);
1619:            }
1620:
1621:            /**
1622:             * Get the set of imported schemas
1623:             *
1624:             * @return a Set, the set of URIs representing the names of imported schemas
1625:             */
1626:
1627:            public Set getImportedSchemaNamespaces() {
1628:                return importedSchemata;
1629:            }
1630:
1631:            /**
1632:             * Determine whether a built-in type is available in this context. This method caters for differences
1633:             * between host languages as to which set of types are built in.
1634:             *
1635:             * @param type the supposedly built-in type. This will always be a type in the
1636:             *             XS or XDT namespace.
1637:             * @return true if this type can be used in this static context
1638:             */
1639:
1640:            public boolean isAllowedBuiltInType(AtomicType type) {
1641:                return true;
1642:            }
1643:
1644:            /**
1645:             * Set the construction mode for this module
1646:             *
1647:             * @param mode one of {@link Validation#STRIP}, {@link Validation#PRESERVE}
1648:             * @since 8.4
1649:             */
1650:
1651:            public void setConstructionMode(int mode) {
1652:                constructionMode = mode;
1653:            }
1654:
1655:            /**
1656:             * Get the current validation mode
1657:             *
1658:             * @return one of {@link Validation#STRIP}, {@link Validation#PRESERVE}
1659:             * @since 8.4
1660:             */
1661:
1662:            public int getConstructionMode() {
1663:                return constructionMode;
1664:            }
1665:
1666:            /**
1667:             * Supporting method to load a query module. Used also by saxon:import-query in XSLT.
1668:             * <p/>
1669:             * This method is intended for internal use only.
1670:             *
1671:             * @param baseURI      The base URI and location URI of the module
1672:             * @param executable   The Executable
1673:             * @param importer     The importing query module (used to check for cycles). This is null
1674:             *                     when loading a query module from XSLT.
1675:             * @param query        The text of the query, after decoding and normalizing line endings
1676:             * @param namespaceURI namespace of the query module to be loaded
1677:             * @return The StaticQueryContext representing the loaded query module
1678:             * @throws net.sf.saxon.trans.StaticError
1679:             */
1680:
1681:            public static StaticQueryContext makeStaticQueryContext(
1682:                    String baseURI, Executable executable,
1683:                    StaticQueryContext importer, String query,
1684:                    String namespaceURI) throws StaticError {
1685:                Configuration config = executable.getConfiguration();
1686:                StaticQueryContext module = new StaticQueryContext(config,
1687:                        importer);
1688:                module.setLocationURI(baseURI);
1689:                module.setBaseURI(baseURI);
1690:                module.setModuleNamespace(namespaceURI);
1691:                module.setExecutable(executable);
1692:
1693:                executable.addQueryLibraryModule(module);
1694:                QueryParser qp = new QueryParser();
1695:                qp.parseLibraryModule(query, module);
1696:                if (module.getModuleNamespace() == null) {
1697:                    throw new StaticError(
1698:                            "Imported module must be a library module");
1699:                }
1700:                if (!module.getModuleNamespace().equals(namespaceURI)) {
1701:                    throw new StaticError(
1702:                            "Imported module's namespace does not match requested namespace");
1703:                }
1704:
1705:                return module;
1706:            }
1707:
1708:            /**
1709:             * Inner class containing information about an active namespace entry
1710:             */
1711:
1712:            private static class ActiveNamespace {
1713:                public String prefix;
1714:                public String uri;
1715:                public int code;
1716:            }
1717:
1718:        }
1719:
1720:        //
1721:        // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
1722:        // you may not use this file except in compliance with the License. You may obtain a copy of the
1723:        // License at http://www.mozilla.org/MPL/
1724:        //
1725:        // Software distributed under the License is distributed on an "AS IS" basis,
1726:        // WITHOUT WARRANTY OF ANY KIND, either express or implied.
1727:        // See the License for the specific language governing rights and limitations under the License.
1728:        //
1729:        // The Original Code is: all this file.
1730:        //
1731:        // The Initial Developer of the Original Code is Michael H. Kay.
1732:        //
1733:        // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
1734:        //
1735:        // Contributor(s): none.
1736:        //
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.