KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > style > ExpressionContext


1 package com.icl.saxon.style;
2 import com.icl.saxon.Loader;
3 import com.icl.saxon.FeatureKeys;
4 import com.icl.saxon.expr.StaticContext;
5 import com.icl.saxon.expr.Function;
6 import com.icl.saxon.expr.ExpressionParser;
7 import com.icl.saxon.expr.FunctionProxy;
8 import com.icl.saxon.expr.XPathException;
9 import com.icl.saxon.Binding;
10 import com.icl.saxon.om.Name;
11 import com.icl.saxon.om.Namespace;
12 import com.icl.saxon.om.NamePool;
13 import com.icl.saxon.om.NamespaceException;
14 import com.icl.saxon.pattern.NameTest;
15 import com.icl.saxon.pattern.NamespaceTest;
16 import javax.xml.transform.TransformerException JavaDoc;
17
18
19 /**
20 * An ExpressionContext represents the context for an XPath expression written
21 * in the stylesheet.
22 */

23
24 public class ExpressionContext implements StaticContext {
25     
26     private StyleElement element;
27     private NamePool namePool;
28
29     public ExpressionContext(StyleElement styleElement) {
30         element = styleElement;
31         namePool = styleElement.getNamePool(); // the stylesheet namepool
32
}
33
34     /**
35     * Create a context for parsing XPath expressions at runtime, using this styelsheet
36     * element for namespace declarations, variables, etc, but using the runtime NamePool
37     */

38     
39     public StaticContext makeRuntimeContext(NamePool pool) {
40         ExpressionContext ec = new ExpressionContext(element);
41         ec.namePool = pool;
42         return ec;
43     }
44
45     /**
46     * Get the System ID of the entity containing the expression (used for diagnostics)
47     */

48
49     public String JavaDoc getSystemId() {
50         return element.getSystemId();
51     }
52
53     /**
54     * Get the line number of the expression within its containing entity
55     * Returns -1 if no line number is available
56     */

57
58     public int getLineNumber() {
59         return element.getLineNumber();
60     }
61
62     /**
63     * Get the Base URI of the element containing the expression, for resolving any
64     * relative URI's used in the expression.
65     * Used by the document() function.
66     */

67     
68     public String JavaDoc getBaseURI() {
69         return element.getBaseURI();
70     }
71
72     /**
73     * Get the URI for a prefix, using this Element as the context for namespace resolution
74     * @param prefix The prefix
75     * @throw XPathxception if the prefix is not declared
76     */

77
78     public String JavaDoc getURIForPrefix(String JavaDoc prefix) throws XPathException {
79         try {
80             short uriCode = element.getURICodeForPrefix(prefix);
81             return namePool.getURIFromURICode(uriCode);
82         } catch (NamespaceException err) {
83             throw new XPathException(err.getMessage());
84         }
85     }
86
87     /**
88     * Make a NameCode, using this Element as the context for namespace resolution
89     * @param qname The name as written, in the form "[prefix:]localname"
90     * @boolean useDefault Defines the action when there is no prefix. If true, use
91     * the default namespace URI (as for element names). If false, use no namespace URI
92     * (as for attribute names).
93     */

94
95     public final int makeNameCode(String JavaDoc qname, boolean useDefault) throws XPathException {
96
97         String JavaDoc prefix = Name.getPrefix(qname);
98         try {
99             if (prefix.equals("")) {
100                 short uriCode = 0;
101                 
102                 if (!Name.isNCName(qname)) {
103                     throw new XPathException("Name " + qname + " contains invalid characters");
104                 }
105                 
106                 if (useDefault) {
107                     uriCode = element.getURICodeForPrefix(prefix);
108                 }
109                 
110                 return namePool.allocate(prefix, uriCode, qname);
111                 
112             } else {
113                 String JavaDoc localName = Name.getLocalName(qname);
114                 short uriCode = element.getURICodeForPrefix(prefix);
115                 return namePool.allocate(prefix, uriCode, localName);
116             }
117         } catch (NamespaceException err) {
118             throw new XPathException("Namespace prefix " + prefix + " has not been declared");
119         }
120
121     }
122
123     /**
124     * Get a fingerprint for a name, using this as the context for namespace resolution
125     * @param qname The name as written, in the form "[prefix:]localname"
126     * @boolean useDefault Defines the action when there is no prefix. If true, use
127     * the default namespace URI (as for element names). If false, use no namespace URI
128     * (as for attribute names).
129     * @return -1 if the name is not already present in the name pool
130     */

131
132     public int getFingerprint(String JavaDoc qname, boolean useDefault) throws XPathException {
133
134         String JavaDoc prefix = Name.getPrefix(qname);
135         if (prefix.equals("")) {
136             String JavaDoc uri = "";
137             
138             if (useDefault) {
139                 uri = getURIForPrefix(prefix);
140             }
141             
142             return namePool.getFingerprint(uri, qname);
143             
144         } else {
145             String JavaDoc localName = Name.getLocalName(qname);
146             String JavaDoc uri = getURIForPrefix(prefix);
147             return namePool.getFingerprint(uri, localName);
148         }
149     }
150
151     /**
152     * Make a NameTest, using this element as the context for namespace resolution
153     */

154     
155     public NameTest makeNameTest(short nodeType, String JavaDoc qname, boolean useDefault)
156             throws XPathException {
157         int nameCode = makeNameCode(qname, useDefault);
158         NameTest nt = new NameTest(nodeType, nameCode);
159         nt.setOriginalText(qname);
160         return nt;
161     }
162
163     /**
164     * Make a NamespaceTest, using this element as the context for namespace resolution
165     */

166     
167     public NamespaceTest makeNamespaceTest(short nodeType, String JavaDoc prefix)
168             throws XPathException {
169         try {
170             short uriCode = element.getURICodeForPrefix(prefix);
171             NamespaceTest nt = new NamespaceTest(namePool, nodeType, uriCode);
172             nt.setOriginalText(prefix + ":*");
173             return nt;
174         } catch (NamespaceException err) {
175             throw new XPathException(err.getMessage());
176         }
177     }
178
179     /**
180     * Bind a variable to an object that can be used to refer to it
181     * @param fingerprint The fingerprint of the variable name
182     * @return a Binding object that can be used to identify it in the Bindery
183     * @throws XPathException if the variable has not been declared
184     */

185
186     public Binding bindVariable(int fingerprint) throws XPathException {
187         return element.bindVariable(fingerprint);
188     }
189
190     /**
191     * Determine whether a given URI code identifies an extension element namespace
192     */

193
194     public boolean isExtensionNamespace(short uriCode) throws XPathException {
195         return element.isExtensionNamespace(uriCode);
196     }
197
198     /**
199     * Determine whether forwards-compatible mode is enabled
200     */

201
202     public boolean forwardsCompatibleModeIsEnabled() throws XPathException {
203         return element.forwardsCompatibleModeIsEnabled();
204     }
205
206     /*
207     * Get a Function declared using a saxon:function element in the stylesheet
208     * @param fingerprint the fingerprint of the name of the function
209     * @return the Function object represented by this saxon:function; or null if not found
210     */

211
212     public Function getStyleSheetFunction(int fingerprint) throws XPathException {
213         return element.getStyleSheetFunction(fingerprint);
214     }
215
216     /**
217     * Get an external Java class corresponding to a given namespace prefix, if there is
218     * one.
219     * @param uri The namespace URI corresponding to the prefix used in the function call.
220     * @return the Java class name if a suitable class exists, otherwise return null.
221     */

222     
223     public Class JavaDoc getExternalJavaClass(String JavaDoc uri) throws TransformerException JavaDoc {
224         
225         // First try to use an xsl:script element if there is one
226

227         XSLStyleSheet sse = element.getPrincipalStyleSheet();
228         Class JavaDoc c = sse.getExternalJavaClass(uri);
229         if (c != null) {
230             return c;
231         }
232
233         // Try well-known namespaces (Saxon and EXSLT extensions)
234

235         if (uri.equals(Namespace.SAXON)) {
236             return com.icl.saxon.functions.Extensions.class;
237
238         } else if (uri.equals(Namespace.EXSLT_COMMON)) {
239             return com.icl.saxon.exslt.Common.class;
240         } else if (uri.equals(Namespace.EXSLT_SETS)) {
241             return com.icl.saxon.exslt.Sets.class;
242         } else if (uri.equals(Namespace.EXSLT_MATH)) {
243             return com.icl.saxon.exslt.Math.class;
244         } else if (uri.equals(Namespace.EXSLT_DATES_AND_TIMES)) {
245             return com.icl.saxon.exslt.Date.class;
246             
247         // Failing that, try the old proprietary mechanisms from XSLT 1.0 days
248

249         } else {
250             if (!((Boolean JavaDoc)sse.getPreparedStyleSheet().getTransformerFactory().
251                     getAttribute(FeatureKeys.ALLOW_EXTERNAL_FUNCTIONS)).booleanValue()) {
252                 throw new TransformerException JavaDoc("Calls to external functions have been disabled");
253             }
254             try {
255
256                 // support the URN format java:full.class.Name
257

258                 if (uri.startsWith("java:")) {
259                     return Loader.getClass(uri.substring(5));
260                 }
261     
262                 // extract the class name as anything in the URI after the last "/"
263
// if there is one, or the whole class name otherwise
264

265                 int slash = uri.lastIndexOf('/');
266                 if (slash<0) {
267                     return Loader.getClass(uri);
268                 } else if (slash==uri.length()-1) {
269                     return null;
270                 } else {
271                     return Loader.getClass(uri.substring(slash+1));
272                 }
273             } catch (TransformerException JavaDoc err) {
274                 return null;
275             }
276         }
277     }
278
279     /**
280     * Determine if an extension element is available
281     * @throws XPathException if the name is invalid or the prefix is not declared
282     */

283     
284     public boolean isElementAvailable(String JavaDoc qname) throws XPathException {
285         if (!Name.isQName(qname)) {
286             throw new XPathException("Invalid QName: " + qname);
287         }
288
289         String JavaDoc prefix = Name.getPrefix(qname);
290         String JavaDoc localName = Name.getLocalName(qname);
291         String JavaDoc uri = getURIForPrefix(prefix);
292
293         return element.getPreparedStyleSheet().
294                             getStyleNodeFactory().isElementAvailable(uri, localName);
295     }
296
297     /**
298     * Determine if a function is available
299     */

300     
301     public boolean isFunctionAvailable(String JavaDoc qname) throws XPathException {
302         if (!Name.isQName(qname)) {
303             throw new XPathException("Invalid QName: " + qname);
304         }
305         String JavaDoc prefix = Name.getPrefix(qname);
306         String JavaDoc uri = getURIForPrefix(prefix);
307         try {
308             if (prefix.equals("")) {
309                 return ExpressionParser.makeSystemFunction(qname)!=null;
310             }
311     
312             int fingerprint = getFingerprint(qname, false);
313             if (fingerprint>=0) {
314                 Function f = getStyleSheetFunction(fingerprint);
315                 if (f!=null) return true;
316             }
317
318             Class JavaDoc theClass = getExternalJavaClass(uri);
319             if (theClass==null) {
320                 return false;
321             }
322                         
323             String JavaDoc localName = Name.getLocalName(qname);
324                         
325             FunctionProxy fp = new FunctionProxy();
326             return fp.setFunctionName(theClass, localName);
327         } catch (Exception JavaDoc err) {
328             return false;
329         }
330     }
331
332     /**
333     * Determine whether the key() function is permmitted in this context
334     */

335     
336     public boolean allowsKeyFunction() {
337         return !(element instanceof XSLKey);
338     }
339
340     /**
341     * Get the effective XSLT version in this region of the stylesheet
342     */

343     
344     public String JavaDoc getVersion() {
345         return element.getVersion();
346     }
347     
348     /**
349     * String representation for diagnostics
350     */

351     
352     public String JavaDoc toString() {
353         return "Expression Context at " + element.toString();
354     }
355
356 }
357
358 //
359
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
360
// you may not use this file except in compliance with the License. You may obtain a copy of the
361
// License at http://www.mozilla.org/MPL/
362
//
363
// Software distributed under the License is distributed on an "AS IS" basis,
364
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
365
// See the License for the specific language governing rights and limitations under the License.
366
//
367
// The Original Code is: all this file.
368
//
369
// The Initial Developer of the Original Code is
370
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
371
//
372
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
373
//
374
// Contributor(s): none.
375
//
376
Popular Tags