KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.functions;
2 import net.sf.saxon.expr.*;
3 import net.sf.saxon.instruct.InstructionDetails;
4 import net.sf.saxon.instruct.SlotManager;
5 import net.sf.saxon.om.*;
6 import net.sf.saxon.trace.Location;
7 import net.sf.saxon.trans.DynamicError;
8 import net.sf.saxon.trans.IndependentContext;
9 import net.sf.saxon.trans.Variable;
10 import net.sf.saxon.trans.XPathException;
11 import net.sf.saxon.type.ItemType;
12 import net.sf.saxon.type.Type;
13 import net.sf.saxon.value.*;
14
15 import java.util.Iterator JavaDoc;
16 import java.io.ObjectOutputStream JavaDoc;
17 import java.io.IOException JavaDoc;
18
19
20 /**
21 * This class implements the saxon:evaluate(), saxon:expression(), and saxon:eval() extension functions,
22 * which are specially-recognized by the system because they need access to parts of the static context
23 */

24
25 public class Evaluate extends SystemFunction {
26
27     // TODO: make saxon:expression into a data type rather than a function. The function then comes "for free"
28
// as a constructor function, but it also becomes possible to write things like
29
// <xsl:variable name="exp" as="saxon:expression">@price * @qty</xsl:variable>
30
// <xsl:value-of select="sum(//item, $exp)"/>
31

32     IndependentContext staticContext;
33         // This staticContext is created at stylesheet compile time. It is therefore shared by all
34
// threads in which this stylesheet executes. Therefore it is immutable at run-time. When
35
// an XPath expression is compiled, a mutable copy of the staticContext is made.
36
InstructionDetails details;
37     public static final int EVALUATE = 0;
38     public static final int EXPRESSION = 1;
39     public static final int EVAL = 2;
40     public static final int EVALUATE_NODE = 3;
41
42     /**
43     * Get the required type of the nth argument
44     */

45
46     protected SequenceType getRequiredType(int arg) {
47         if (arg==0) {
48             return super.getRequiredType(arg);
49         } else {
50             return SequenceType.ANY_SEQUENCE;
51         }
52     }
53
54     /**
55     * Method supplied by each class of function to check arguments during parsing, when all
56     * the argument expressions have been read
57     */

58
59     public void checkArguments(StaticContext env) throws XPathException {
60         if (staticContext == null) {
61             // only do this once
62
super.checkArguments(env);
63             if (operation == EVALUATE || operation == EXPRESSION) {
64                 NamespaceResolver nsContext = env.getNamespaceResolver();
65                 staticContext = new IndependentContext(env.getConfiguration());
66                 staticContext.setBaseURI(env.getBaseURI());
67                 staticContext.setSchemaImporter(env);
68                 staticContext.setDefaultFunctionNamespace(env.getDefaultFunctionNamespace());
69
70                 // TODO: this creates a link to the XSLStylesheet and XSLFunction objects
71
// in the source stylesheet, which means that a stylesheet containing a call on evaluate()
72
// cannot be compiled.
73
getExecutable().setReasonUnableToCompile(
74                         "Cannot compile a stylesheet containing calls on saxon:evaluate() or saxon:expression(), " +
75                         "because they require access to the uncompiled stylesheet");
76                 staticContext.setFunctionLibrary(env.getFunctionLibrary());
77
78                 for (Iterator JavaDoc iter = nsContext.iteratePrefixes(); iter.hasNext();) {
79                     String JavaDoc prefix = (String JavaDoc)iter.next();
80                     String JavaDoc uri = nsContext.getURIForPrefix(prefix, true);
81                     staticContext.declareNamespace(prefix, uri);
82                 }
83                 details = new InstructionDetails();
84                 details.setConstructType(Location.SAXON_EVALUATE);
85                 details.setSystemId(env.getLocationMap().getSystemId(this.locationId));
86                 details.setLineNumber(env.getLocationMap().getLineNumber(this.locationId));
87             } else if (operation == EVALUATE_NODE) {
88                 // for saxon:evaluate-node() the static context of the expression is based
89
// on the node in the source document containing the expression.
90
staticContext = new IndependentContext(env.getConfiguration());
91             }
92         }
93     }
94
95     /**
96      * preEvaluate: for saxon:expression, if the expression is
97      * known at compile time, then it is compiled at compile time.
98      * In other cases this method suppresses compile-time evaluation by doing nothing
99      * (because the value of the expression depends on the runtime context).
100      */

101
102     public Expression preEvaluate(StaticContext env) throws XPathException {
103         if (operation == EXPRESSION) {
104             // compile-time evaluation of saxon:expression is allowed
105
if (argument[0] instanceof StringValue) {
106                 PreparedExpression pexpr = new PreparedExpression();
107                 //staticContext.setFunctionLibrary(env.getFunctionLibrary());
108
String JavaDoc exprText = ((StringValue)argument[0]).getStringValue();
109                 pexpr.variables = new Variable[10];
110                 for (int i=1; i<10; i++) {
111                     QNameValue qname = new QNameValue("", "", "p"+i);
112                     pexpr.variables[i-1] = staticContext.declareVariable(qname);
113                 }
114                 Expression expr = ExpressionTool.make(exprText, staticContext, 0, Token.EOF, 1);
115
116                 ItemType contextItemType = Type.ITEM_TYPE;
117                 expr = expr.typeCheck(staticContext, contextItemType);
118                 pexpr.stackFrameMap = staticContext.getStackFrameMap();
119                 ExpressionTool.allocateSlots(expr, pexpr.stackFrameMap.getNumberOfVariables(), pexpr.stackFrameMap);
120                 pexpr.expression = expr;
121                 return new ObjectValue(pexpr);
122             }
123         }
124         // the other operations don't allow compile time evaluation because they need a run-time context
125
return this;
126     }
127
128     private PreparedExpression prepareExpression(XPathContext context) throws XPathException {
129         if (operation == EVAL) {
130             Item item = argument[0].evaluateItem(context);
131             if (!(item instanceof ObjectValue)) {
132                 dynamicError(
133                     "First argument to saxon:eval must be an expression prepared using saxon:expression", context);
134                 return null;
135             }
136             ObjectValue obj = (ObjectValue)item;
137             Object JavaDoc v = obj.getObject();
138             if (!(v instanceof PreparedExpression)) {
139                 dynamicError(
140                     "First argument to saxon:eval must be an expression prepared using saxon:expression", context);
141                 return null;
142             }
143             return (PreparedExpression)v;
144
145         }
146
147         PreparedExpression pexpr = new PreparedExpression();
148         String JavaDoc exprText;
149         if (operation == EVALUATE_NODE) {
150             NodeInfo node = (NodeInfo)argument[0].evaluateItem(context);
151             IndependentContext env = staticContext.copy();
152             pexpr.expStaticContext = env;
153             env.setBaseURI(node.getBaseURI());
154             env.setFunctionLibrary(getExecutable().getFunctionLibrary());
155             env.setNamespaces(node);
156             exprText = node.getStringValue();
157             AxisIterator single = SingletonIterator.makeIterator(node);
158             single.next();
159             context.setCurrentIterator(single);
160             Expression expr;
161             try {
162                 expr = ExpressionTool.make(exprText, env, 0, Token.EOF, 1);
163             } catch (XPathException e) {
164                 String JavaDoc name = context.getController().getNamePool().getDisplayName(getFunctionNameCode());
165                 DynamicError err = new DynamicError("Static error in XPath expression supplied to " + name + ": " +
166                         e.getMessage().trim());
167                 err.setXPathContext(context);
168                 throw err;
169             }
170             ItemType contextItemType = Type.ITEM_TYPE;
171             expr = expr.typeCheck(env, contextItemType);
172             pexpr.stackFrameMap = env.getStackFrameMap();
173             ExpressionTool.allocateSlots(expr, pexpr.stackFrameMap.getNumberOfVariables(), pexpr.stackFrameMap);
174             pexpr.expression = expr;
175             if (expr instanceof ComputedExpression) {
176                 ((ComputedExpression)expr).setParentExpression(this);
177             }
178             return pexpr;
179
180         }
181
182         AtomicValue exprSource = (AtomicValue)argument[0].evaluateItem(context);
183         exprText = exprSource.getStringValue();
184         IndependentContext env = staticContext.copy();
185         env.setFunctionLibrary(getExecutable().getFunctionLibrary());
186         pexpr.expStaticContext = env;
187         pexpr.variables = new Variable[10];
188         for (int i=1; i<10; i++) {
189             QNameValue qname = new QNameValue("", "", "p"+i);
190             pexpr.variables[i-1] = env.declareVariable(qname);
191         }
192
193         Expression expr;
194         try {
195             expr = ExpressionTool.make(exprText, env, 0, Token.EOF, 1);
196         } catch (XPathException e) {
197             String JavaDoc name = context.getController().getNamePool().getDisplayName(getFunctionNameCode());
198             DynamicError err = new DynamicError("Static error in XPath expression supplied to " + name + ": " +
199                     e.getMessage().trim());
200             err.setXPathContext(context);
201             throw err;
202         }
203         ItemType contextItemType = Type.ITEM_TYPE;
204         expr = expr.typeCheck(env, contextItemType);
205         pexpr.stackFrameMap = env.getStackFrameMap();
206         ExpressionTool.allocateSlots(expr, pexpr.stackFrameMap.getNumberOfVariables(), pexpr.stackFrameMap);
207         pexpr.expression = expr;
208
209         return pexpr;
210     }
211
212     /**
213     * Evaluate in a general context
214     */

215
216     public Item evaluateItem(XPathContext c) throws XPathException {
217         if (operation == EXPRESSION) {
218             PreparedExpression pexpr = prepareExpression(c);
219             return new ObjectValue(pexpr);
220         } else if (operation == EVALUATE_NODE) {
221             XPathContextMajor c2 = c.newCleanContext();
222             PreparedExpression pexpr = prepareExpression(c2);
223             c2.setOrigin(details);
224             c2.openStackFrame(pexpr.stackFrameMap);
225             return pexpr.expression.evaluateItem(c2);
226         } else {
227             PreparedExpression pexpr = prepareExpression(c);
228             for (int i=1; i<argument.length; i++) {
229                 pexpr.variables[i-1].setXPathValue(ExpressionTool.eagerEvaluate(argument[i],c));
230             }
231             XPathContextMajor c2 = c.newCleanContext();
232             c2.setOrigin(details);
233             c2.openStackFrame(pexpr.stackFrameMap);
234             c2.setCurrentIterator(c.getCurrentIterator());
235             return pexpr.expression.evaluateItem(c2);
236         }
237     }
238
239     /**
240     * Iterate over the results of the function
241     */

242
243     public SequenceIterator iterate(XPathContext c) throws XPathException {
244         PreparedExpression pexpr = prepareExpression(c);
245
246         if (operation == EXPRESSION) {
247             return SingletonIterator.makeIterator(new ObjectValue(pexpr));
248         } else {
249             for (int i=1; i<argument.length; i++) {
250                 pexpr.variables[i-1].setXPathValue(ExpressionTool.eagerEvaluate(argument[i],c));
251             }
252             XPathContextMajor c2 = c.newCleanContext();
253             c2.setOrigin(details);
254             c2.openStackFrame(pexpr.stackFrameMap);
255             c2.setCurrentIterator(c.getCurrentIterator());
256             return Value.getIterator(
257                     ExpressionTool.lazyEvaluate(pexpr.expression, c2, 1));
258         }
259     }
260
261     /**
262     * Determine the dependencies
263     */

264
265     public int getIntrinsicDependencies() {
266        return StaticProperty.DEPENDS_ON_FOCUS;
267     }
268
269     /**
270     * Inner class PreparedExpression represents a compiled XPath expression together
271     * with the standard variables $p1 .. $p9 available for use when the expression is
272     * evaluated
273     */

274
275     public static class PreparedExpression {
276         public IndependentContext expStaticContext;
277         public Expression expression;
278         public Variable[] variables;
279         public SlotManager stackFrameMap;
280     }
281
282     /**
283      * Code to handle serialization: or rather, to report that it's not possible
284      */

285
286     private void writeObject(ObjectOutputStream JavaDoc s) throws IOException JavaDoc {
287         if (operation==EXPRESSION || operation==EVALUATE) {
288             throw new IOException JavaDoc("Cannot compile a stylesheet containing calls on saxon:evaluate() or saxon:expression(). " +
289                     "Consider using saxon:evaluate-node() instead.");
290         } else {
291             s.defaultWriteObject();
292         }
293     }
294
295 }
296
297
298
299
300 //
301
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
302
// you may not use this file except in compliance with the License. You may obtain a copy of the
303
// License at http://www.mozilla.org/MPL/
304
//
305
// Software distributed under the License is distributed on an "AS IS" basis,
306
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
307
// See the License for the specific language governing rights and limitations under the License.
308
//
309
// The Original Code is: all this file.
310
//
311
// The Initial Developer of the Original Code is Michael H. Kay.
312
//
313
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
314
//
315
// Contributor(s): none.
316
//
317
Popular Tags