KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > trans > IndependentContext


1 package net.sf.saxon.trans;
2 import net.sf.saxon.Configuration;
3 import net.sf.saxon.value.QNameValue;
4 import net.sf.saxon.expr.StaticContext;
5 import net.sf.saxon.expr.VariableDeclaration;
6 import net.sf.saxon.functions.ConstructorFunctionLibrary;
7 import net.sf.saxon.functions.FunctionLibrary;
8 import net.sf.saxon.functions.FunctionLibraryList;
9 import net.sf.saxon.functions.SystemFunctionLibrary;
10 import net.sf.saxon.instruct.LocationMap;
11 import net.sf.saxon.instruct.SlotManager;
12 import net.sf.saxon.om.*;
13 import net.sf.saxon.type.AtomicType;
14 import net.sf.saxon.type.Type;
15
16 import javax.xml.transform.SourceLocator JavaDoc;
17 import java.io.Serializable JavaDoc;
18 import java.util.Comparator JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21
22 /**
23 * An IndependentContext provides a context for parsing an expression or pattern appearing
24 * in a context other than a stylesheet.
25  *
26  * This class was formerly named StandaloneContext. It has forked from that class, so that
27  * StandaloneContext could be changed to meet the demands of the JAXP 1.3 XPath API.
28 */

29
30 public class IndependentContext implements StaticContext, NamespaceResolver, Serializable JavaDoc {
31
32     private NamePool namePool;
33     private HashMap JavaDoc namespaces = new HashMap JavaDoc(10);
34     private HashMap JavaDoc collations = new HashMap JavaDoc(10);
35     private HashMap JavaDoc variables = new HashMap JavaDoc(20);
36     private SlotManager stackFrameMap;
37     private String JavaDoc defaultCollationName = null;
38     private String JavaDoc baseURI = null;
39     private Configuration config;
40     private LocationMap locationMap = new LocationMap();
41     private FunctionLibrary functionLibrary;
42     private String JavaDoc defaultFunctionNamespace = NamespaceConstant.FN;
43     private StaticContext schemaImporter = null;
44     private NamespaceResolver externalResolver = null;
45
46     /**
47     * Create an IndependentContext using a specific Configuration
48     */

49
50     public IndependentContext(Configuration config) {
51         this.config = config;
52         namePool = config.getNamePool();
53         stackFrameMap = config.makeSlotManager();
54         clearNamespaces();
55
56         // Set up a default function library. This can be overridden using setFunctionLibrary()
57

58         FunctionLibraryList lib = new FunctionLibraryList();
59         lib.addFunctionLibrary(new SystemFunctionLibrary(SystemFunctionLibrary.XPATH_ONLY));
60         lib.addFunctionLibrary(getConfiguration().getVendorFunctionLibrary());
61         lib.addFunctionLibrary(new ConstructorFunctionLibrary(getConfiguration()));
62         if (config.isAllowExternalFunctions()) {
63             lib.addFunctionLibrary(config.getExtensionBinder());
64         }
65         functionLibrary = lib;
66     }
67
68     /**
69      * Create a copy of this IndependentContext. All aspects of the context are copied
70      * except for declared variables.
71      */

72
73     public IndependentContext copy() {
74         IndependentContext ic = new IndependentContext(config);
75         ic.namespaces = new HashMap JavaDoc(namespaces);
76         ic.collations = new HashMap JavaDoc(collations);
77         ic.variables = new HashMap JavaDoc();
78         ic.defaultCollationName = defaultCollationName;
79         ic.baseURI = baseURI;
80         ic.locationMap = locationMap;
81         ic.functionLibrary = functionLibrary;
82         ic.defaultFunctionNamespace = defaultFunctionNamespace;
83         ic.schemaImporter = schemaImporter;
84         ic.externalResolver = externalResolver;
85         return ic;
86     }
87
88     /**
89      * Get the system configuration
90      */

91
92     public Configuration getConfiguration() {
93         return config;
94     }
95
96     public LocationMap getLocationMap() {
97         return locationMap;
98     }
99
100     public void setLocationMap(LocationMap locationMap) {
101         this.locationMap = locationMap;
102     }
103
104     /**
105     * Declare a namespace whose prefix can be used in expressions
106     * @param prefix The namespace prefix. Must not be null. Must not be the empty string
107     * ("") - unqualified names in an XPath expression always refer to the null namespace.
108     * @param uri The namespace URI. Must not be null.
109     */

110
111     public void declareNamespace(String JavaDoc prefix, String JavaDoc uri) {
112         if (prefix==null) {
113             throw new NullPointerException JavaDoc("Null prefix supplied to declareNamespace()");
114         }
115         if (uri==null) {
116             throw new NullPointerException JavaDoc("Null namespace URI supplied to declareNamespace()");
117         }
118         namespaces.put(prefix, uri);
119         namePool.allocateNamespaceCode(prefix, uri);
120     }
121
122     /**
123     * Clear all the declared namespaces, except for the standard ones (xml, xslt, saxon, xdt)
124     */

125
126     public void clearNamespaces() {
127         namespaces.clear();
128         declareNamespace("xml", NamespaceConstant.XML);
129         declareNamespace("xsl", NamespaceConstant.XSLT);
130         declareNamespace("saxon", NamespaceConstant.SAXON);
131         declareNamespace("xs", NamespaceConstant.SCHEMA);
132         declareNamespace("xdt", NamespaceConstant.XDT);
133         declareNamespace("", "");
134     }
135
136     /**
137     * Clear all the declared namespaces, including the standard ones (xml, xslt, saxon).
138      * Leave only the XML namespace and the default namespace (xmlns="")
139     */

140
141     public void clearAllNamespaces() {
142         namespaces.clear();
143         declareNamespace("xml", NamespaceConstant.XML);
144         declareNamespace("", "");
145     }
146
147     /**
148     * Set all the declared namespaces to be the namespaces that are in-scope for a given node.
149     * In addition, the standard namespaces (xml, xslt, saxon) are declared.
150     * @param node The node whose in-scope namespaces are to be used as the context namespaces.
151     * If the node is an attribute, text node, etc, then the namespaces of its parent element are used.
152     */

153
154     public void setNamespaces(NodeInfo node) {
155         namespaces.clear();
156         int kind = node.getNodeKind();
157         if (kind == Type.ATTRIBUTE || kind == Type.TEXT ||
158                 kind == Type.COMMENT || kind == Type.PROCESSING_INSTRUCTION ||
159                 kind == Type.NAMESPACE) {
160             node = node.getParent();
161         }
162         if (node == null) {
163             return;
164         }
165
166         AxisIterator iter = node.iterateAxis(Axis.NAMESPACE);
167         while (true) {
168             NodeInfo ns = (NodeInfo)iter.next();
169             if (ns == null) {
170                 return;
171             }
172             declareNamespace(ns.getLocalPart(), ns.getStringValue());
173         }
174     }
175
176     /**
177      * Set an external namespace resolver. If this is set, then all resolution of namespace
178      * prefixes is delegated to the external namespace resolver, and namespaces declared
179      * individually on this IndependentContext object are ignored.
180      */

181
182     public void setNamespaceResolver(NamespaceResolver resolver) {
183         this.externalResolver = resolver;
184     }
185
186     /**
187      * Set the base URI in the static context
188      */

189
190     public void setBaseURI(String JavaDoc baseURI) {
191         this.baseURI = baseURI;
192     }
193
194     /**
195     * Declare a named collation
196     * @param name The name of the collation (technically, a URI)
197     * @param comparator The Java Comparator used to implement the collating sequence
198     * @param isDefault True if this is to be used as the default collation
199     */

200
201     public void declareCollation(String JavaDoc name, Comparator JavaDoc comparator, boolean isDefault) {
202         collations.put(name, comparator);
203         if (isDefault) {
204             defaultCollationName = name;
205         }
206     }
207
208     /**
209      * Get the stack frame map containing the slot number allocations for the variables declared
210      * in this static context
211      */

212
213     public SlotManager getStackFrameMap() {
214         return stackFrameMap;
215     }
216
217     /**
218     * Declare a variable. A variable must be declared before an expression referring
219     * to it is compiled. The initial value of the variable will be the empty sequence
220      * @param qname The name of the variable
221     */

222
223     public Variable declareVariable(QNameValue qname) {
224         Variable var = Variable.make(qname, getConfiguration());
225         var.setXPathValue(null);
226         int fingerprint = qname.allocateNameCode(getNamePool()) & 0xfffff;
227         variables.put(new Integer JavaDoc(fingerprint), var);
228         stackFrameMap.allocateSlotNumber(fingerprint);
229         return var;
230     }
231
232     /**
233     * Declare a variable. A variable may be declared before an expression referring
234     * to it is compiled. Alternatively, a JAXP XPathVariableResolver may be supplied
235      * to perform the resolution. A variable that has been explicitly declared is
236      * used in preference.
237      * @param qname Lexical QName identifying the variable. The namespace prefix, if
238      * any, must have been declared before this method is called, or must be resolvable
239      * using the namespace context.
240     */

241
242     public Variable declareVariable(String JavaDoc qname) throws XPathException {
243         String JavaDoc prefix;
244         String JavaDoc localName;
245         try {
246             String JavaDoc[] parts = Name.getQNameParts(qname);
247             prefix = parts[0];
248             localName = parts[1];
249         } catch (QNameException err) {
250             throw new StaticError("Invalid QName for variable: " + qname);
251         }
252         String JavaDoc uri = "";
253         if (!("".equals(prefix))) {
254             uri = getURIForPrefix(prefix);
255         }
256         QNameValue q = new QNameValue(prefix, uri, localName);
257         Variable var = Variable.make(q, getConfiguration());
258         int fingerprint = namePool.allocate(prefix, uri, localName) & 0xfffff;
259         variables.put(new Integer JavaDoc(fingerprint), var);
260         stackFrameMap.allocateSlotNumber(fingerprint);
261         return var;
262     }
263
264
265     /**
266     * Get the NamePool used for compiling expressions
267     */

268
269     public NamePool getNamePool() {
270         return namePool;
271     }
272
273     /**
274     * Issue a compile-time warning. This method is used during XPath expression compilation to
275     * output warning conditions. The default implementation writes the message to System.err. To
276     * change the destination of messages, create a subclass of StandaloneContext that overrides
277     * this method.
278     */

279
280     public void issueWarning(String JavaDoc s, SourceLocator JavaDoc locator) {
281         System.err.println(s);
282     }
283
284     /**
285     * Get the system ID of the container of the expression. Used to construct error messages.
286     * @return "" always
287     */

288
289     public String JavaDoc getSystemId() {
290         return "";
291     }
292
293     /**
294     * Get the Base URI of the stylesheet element, for resolving any relative URI's used
295     * in the expression.
296     * Used by the document() function, resolve-uri(), etc.
297     * @return "" if no base URI has been set
298     */

299
300     public String JavaDoc getBaseURI() {
301         return baseURI==null ? "" : baseURI;
302     }
303
304     /**
305     * Get the line number of the expression within that container.
306     * Used to construct error messages.
307     * @return -1 always
308     */

309
310     public int getLineNumber() {
311         return -1;
312     }
313
314     /**
315      * Get the URI for a prefix, using the declared namespaces as
316      * the context for namespace resolution. The default namespace is NOT used
317      * when the prefix is empty.
318      * This method is provided for use by the XPath parser.
319      * @param prefix The prefix
320      * @throws net.sf.saxon.trans.XPathException if the prefix is not declared
321     */

322
323     public String JavaDoc getURIForPrefix(String JavaDoc prefix) throws XPathException {
324         String JavaDoc uri = getURIForPrefix(prefix, false);
325         if (uri==null) {
326             throw new StaticError("Prefix " + prefix + " has not been declared");
327         }
328         return uri;
329     }
330
331     public NamespaceResolver getNamespaceResolver() {
332         if (externalResolver != null) {
333             return externalResolver;
334         } else {
335             return this;
336         }
337     }
338
339     /**
340      * Get the namespace URI corresponding to a given prefix. Return null
341      * if the prefix is not in scope.
342      * @param prefix the namespace prefix
343      * @param useDefault true if the default namespace is to be used when the
344      * prefix is ""
345      * @return the uri for the namespace, or null if the prefix is not in scope.
346      * Return "" if the prefix maps to the null namespace.
347      */

348
349     public String JavaDoc getURIForPrefix(String JavaDoc prefix, boolean useDefault) {
350         if (externalResolver != null) {
351             return externalResolver.getURIForPrefix(prefix, useDefault);
352         }
353         if (prefix.equals("") && !useDefault) {
354             return "";
355         } else {
356             return (String JavaDoc)namespaces.get(prefix);
357         }
358     }
359
360     /**
361      * Get an iterator over all the prefixes declared in this namespace context. This will include
362      * the default namespace (prefix="") and the XML namespace where appropriate
363      */

364
365     public Iterator JavaDoc iteratePrefixes() {
366         if (externalResolver != null) {
367             return externalResolver.iteratePrefixes();
368         } else {
369             return namespaces.keySet().iterator();
370         }
371     }
372
373     /**
374     * Bind a variable used in an XPath Expression to the XSLVariable element in which it is declared.
375     * This method is provided for use by the XPath parser, and it should not be called by the user of
376     * the API, or overridden, unless variables are to be declared using a mechanism other than the
377     * declareVariable method of this class.
378     */

379
380     public VariableDeclaration bindVariable(int fingerprint) throws StaticError {
381         Variable var = (Variable)variables.get(new Integer JavaDoc(fingerprint));
382         if (var==null) {
383             throw new StaticError("Undeclared variable in a standalone expression");
384         } else {
385             return var;
386         }
387     }
388
389     /**
390      * Get the function library containing all the in-scope functions available in this static
391      * context
392      */

393
394     public FunctionLibrary getFunctionLibrary() {
395         return functionLibrary;
396     }
397
398     /**
399      * Set the function library to be used
400      */

401
402     public void setFunctionLibrary(FunctionLibrary lib) {
403         functionLibrary = lib;
404     }
405
406     /**
407     * Get a named collation.
408     * @return the collation identified by the given name, as set previously using declareCollation.
409     * Return null if no collation with this name is found.
410     */

411
412     public Comparator JavaDoc getCollation(String JavaDoc name) {
413         Configuration config = getConfiguration();
414         return config.getCollationURIResolver().resolve(name, getBaseURI(), config);
415     }
416
417     /**
418     * Get the name of the default collation.
419     * @return the name of the default collation; or the name of the codepoint collation
420     * if no default collation has been defined
421     */

422
423     public String JavaDoc getDefaultCollationName() {
424         if (defaultCollationName != null) {
425             return defaultCollationName;
426         } else {
427             return NamespaceConstant.CODEPOINT_COLLATION_URI;
428         }
429     }
430
431     /**
432     * Get the default XPath namespace, as a namespace code that can be looked up in the NamePool
433     */

434
435     public short getDefaultElementNamespace() {
436         return NamespaceConstant.NULL_CODE;
437     }
438
439     /**
440      * Set the default function namespace
441      */

442
443     public void setDefaultFunctionNamespace(String JavaDoc uri) {
444         defaultFunctionNamespace = uri;
445     }
446
447     /**
448      * Get the default function namespace
449      */

450
451     public String JavaDoc getDefaultFunctionNamespace() {
452         return defaultFunctionNamespace;
453     }
454
455     /**
456      * Determine whether Backwards Compatible Mode is used
457      * @return false; XPath 1.0 compatibility mode is not supported in the standalone
458      * XPath API
459      */

460
461     public boolean isInBackwardsCompatibleMode() {
462         return false;
463     }
464
465     public boolean isImportedSchema(String JavaDoc namespace) {
466         if (schemaImporter == null) {
467             return false;
468         }
469         return schemaImporter.isImportedSchema(namespace);
470     }
471
472     /**
473      * Determine whether a built-in type is available in this context. This method caters for differences
474      * between host languages as to which set of types are built in.
475      *
476      * @param type the supposedly built-in type. This will always be a type in the
477      * XS or XDT namespace.
478      * @return true if this type can be used in this static context
479      */

480
481     public boolean isAllowedBuiltInType(AtomicType type) {
482         if (schemaImporter == null) {
483             return true;
484         }
485         return schemaImporter.isAllowedBuiltInType(type);
486
487     }
488
489     public void setSchemaImporter(StaticContext importer) {
490         schemaImporter = importer;
491     }
492
493 }
494
495 //
496
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
497
// you may not use this file except in compliance with the License. You may obtain a copy of the
498
// License at http://www.mozilla.org/MPL/
499
//
500
// Software distributed under the License is distributed on an "AS IS" basis,
501
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
502
// See the License for the specific language governing rights and limitations under the License.
503
//
504
// The Original Code is: all this file.
505
//
506
// The Initial Developer of the Original Code is Michael H. Kay
507
//
508
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
509
//
510
// Contributor(s): none.
511
//
512
Popular Tags