KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > functions > Available


1 package net.sf.saxon.functions;
2 import net.sf.saxon.expr.Expression;
3 import net.sf.saxon.expr.StaticContext;
4 import net.sf.saxon.expr.XPathContext;
5 import net.sf.saxon.om.*;
6 import net.sf.saxon.style.StyleNodeFactory;
7 import net.sf.saxon.style.XSLTStaticContext;
8 import net.sf.saxon.trans.StaticError;
9 import net.sf.saxon.trans.XPathException;
10 import net.sf.saxon.value.*;
11 import net.sf.saxon.Configuration;
12
13 /**
14 * This class supports the XSLT element-available and function-available functions.
15 */

16
17 public class Available extends SystemFunction implements XSLTFunction {
18
19     public static final int ELEMENT_AVAILABLE = 0;
20     public static final int FUNCTION_AVAILABLE = 1;
21
22     private transient NamespaceResolver nsContext;
23     private transient StyleNodeFactory styleNodeFactory;
24     private transient boolean checked = false;
25         // the second time checkArguments is called, it's a global check so the static context is inaccurate
26

27     public void checkArguments(StaticContext env) throws XPathException {
28         if (checked) return;
29         checked = true;
30         super.checkArguments(env);
31         if (!(argument[0] instanceof Value &&
32                 (argument.length==1 || argument[1] instanceof Value))) {
33             // we need to save the namespace context
34
nsContext = env.getNamespaceResolver();
35         }
36     }
37
38     /**
39     * preEvaluate: this method uses the static context to do early evaluation of the function
40     * if the argument is known
41     */

42
43     public Expression preEvaluate(StaticContext env) throws XPathException {
44         String JavaDoc qname = ((StringValue)argument[0]).getStringValue();
45
46         boolean b = false;
47         switch(operation) {
48             case ELEMENT_AVAILABLE:
49                 b = ((XSLTStaticContext)env).isElementAvailable(qname);
50                 break;
51             case FUNCTION_AVAILABLE:
52                 long arity = -1;
53                 if (argument.length == 2) {
54                     arity = ((NumericValue)argument[1].evaluateItem(null)).longValue();
55                 }
56                 //b = ((ExpressionContext)env).isFunctionAvailable(qname, arity);
57
try {
58                     String JavaDoc[] parts = Name.getQNameParts(qname);
59                     String JavaDoc prefix = parts[0];
60                     String JavaDoc uri;
61                     if (prefix.equals("")) {
62                         uri = env.getDefaultFunctionNamespace();
63                     } else {
64                         uri = env.getURIForPrefix(prefix);
65                     }
66                     int fingerprint = env.getNamePool().allocate(prefix, uri, parts[1]) & 0xfffff;
67                     b = env.getFunctionLibrary().isAvailable(fingerprint, uri, parts[1], (int)arity);
68                 } catch (QNameException e) {
69                     throw new StaticError(e.getMessage());
70                 }
71                 break;
72         }
73         return BooleanValue.get(b);
74     }
75
76     /**
77     * Run-time evaluation. This is the only thing in the spec that requires information
78      * about in-scope functions to be available at run-time. However, we keep it because
79      * it's handy for some other things such as saxon:evaluate().
80     */

81
82     public Item evaluateItem(XPathContext context) throws XPathException {
83         AtomicValue av1 = (AtomicValue)argument[0].evaluateItem(context);
84         long arity = -1;
85         if (argument.length == 2) {
86             arity = ((NumericValue)argument[1].evaluateItem(context)).longValue();
87         }
88         StringValue nameValue = (StringValue)av1.getPrimitiveValue();
89         String JavaDoc name = nameValue.getStringValue();
90         String JavaDoc[] parts = null;
91         try {
92             parts = Name.getQNameParts(name);
93         } catch (QNameException e) {
94             String JavaDoc code = (operation == FUNCTION_AVAILABLE ? "XTDE1400" : "XTDE1440");
95             dynamicError(e.getMessage(), code, context);
96         }
97         String JavaDoc prefix = parts[0];
98         String JavaDoc lname = parts[1];
99         String JavaDoc uri;
100         if (prefix.equals("")) {
101             if (operation==ELEMENT_AVAILABLE) {
102                 // Use the default namespace for ELEMENT_AVAILABLE only
103
uri = nsContext.getURIForPrefix(prefix, true);
104             } else {
105                 uri = NamespaceConstant.FN;
106             }
107         } else {
108             uri = nsContext.getURIForPrefix(prefix, false);
109         }
110         if (uri==null) {
111             dynamicError("Namespace prefix '" + prefix + "' has not been declared", context);
112         }
113
114         boolean b = false;
115         switch(operation) {
116             case ELEMENT_AVAILABLE:
117                 b = isElementAvailable(uri, lname, context);
118                 break;
119             case FUNCTION_AVAILABLE:
120                 final int fingerprint = context.getController().getNamePool().allocate(prefix, uri, lname) & 0xfffff;
121                 final FunctionLibrary lib = context.getController().getExecutable().getFunctionLibrary();
122                 b = lib.isAvailable(fingerprint, uri, lname, (int)arity);
123                 break;
124         }
125         return BooleanValue.get(b);
126
127     }
128
129     /**
130     * Determine at run-time whether a function is available. Returns true only in the case
131     * of standard functions, EXSLT and Saxon functions, and Java extension functions found
132     * in a class that's implicit from the URI. Currently returns false in the case of
133     * stylesheet functions (xsl:function) and Java classes identified using saxon:script
134     */

135
136 // private static boolean isFunctionAvailable(String uri, String localname, int arity, XPathContext context) {
137
// try {
138
// if (uri.equals("") || uri.equals(NamespaceConstant.FN)) {
139
// StandardFunction.Entry entry =
140
// StandardFunction.getFunction(localname);
141
// if (entry == null) {
142
// return false;
143
// }
144
// return (arity == -1 ||
145
// (arity >= entry.minArguments && arity <= entry.maxArguments));
146
// } else {
147
// FunctionLibrary proxy = context.getController().getConfiguration().getExtensionBinder();
148
// return proxy.isAvailable(uri, localname, arity);
149
// }
150
// } catch (Exception err) {
151
// return false;
152
// }
153
// }
154

155     /**
156     * Determine at run-time whether a particular instruction is available. Returns true
157     * only in the case of XSLT instructions and Saxon extension instructions; returns false
158     * for user-defined extension instructions
159     */

160
161     private boolean isElementAvailable(String JavaDoc uri, String JavaDoc localname, XPathContext context) {
162
163         // This is horribly inefficient. But hopefully it's hardly ever executed, because there
164
// is very little point calling element-available() with a dynamically-constructed argument.
165
// And the inefficiency is only incurred once, on the first call.
166

167         // Note: this requires the compile-time classes to be available at run-time; it will need
168
// changing if we ever want to build a run-time JAR file.
169

170         try {
171             if (styleNodeFactory==null) {
172                 Configuration config = context.getController().getConfiguration();
173                 //NamePool instructionNamePool = new NamePool();
174
styleNodeFactory =
175                     new StyleNodeFactory (
176                             config);
177             }
178             return styleNodeFactory.isElementAvailable(uri, localname);
179         } catch (Exception JavaDoc err) {
180             //err.printStackTrace();
181
return false;
182         }
183     }
184
185 }
186
187
188
189 //
190
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
191
// you may not use this file except in compliance with the License. You may obtain a copy of the
192
// License at http://www.mozilla.org/MPL/
193
//
194
// Software distributed under the License is distributed on an "AS IS" basis,
195
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
196
// See the License for the specific language governing rights and limitations under the License.
197
//
198
// The Original Code is: all this file.
199
//
200
// The Initial Developer of the Original Code is Michael H. Kay.
201
//
202
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
203
//
204
// Contributor(s): none.
205
//
206
Popular Tags