KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > Context


1 package com.icl.saxon;
2 import com.icl.saxon.om.*;
3 import com.icl.saxon.expr.*;
4 import com.icl.saxon.output.Outputter;
5 import com.icl.saxon.style.XSLTemplate;
6 import com.icl.saxon.functions.SystemProperty;
7 import javax.xml.transform.TransformerException JavaDoc;
8
9 import java.util.Stack JavaDoc;
10 import java.net.URL JavaDoc;
11 import java.io.Writer JavaDoc;
12 import org.w3c.dom.Node JavaDoc;
13 import org.w3c.dom.Document JavaDoc;
14
15 import org.w3c.xsl.XSLTContext;
16
17
18 /**
19 * This class represents a context in which an expression is evaluated or a template is executed
20 * (as defined in the XSLT specification). It also provides a range of services to node handlers,
21 * for example access to the outputter and bindery, and the applyTemplates() function.
22 */

23
24 public final class Context implements XSLTContext, LastPositionFinder {
25
26     // Define the different kinds of context-dependency in an expression
27

28     public static final int VARIABLES = 1; // Expression depends on values of variables
29
public static final int CURRENT_NODE = 4; // Expression depends on current() node
30
public static final int CONTEXT_NODE = 8; // Expression depends on context node
31
public static final int POSITION = 16; // Expression depends on position()
32
public static final int LAST = 32; // Expression depends on last()
33
public static final int CONTROLLER = 64; // Expression evaluation needs the Controller
34
public static final int CONTEXT_DOCUMENT = 128; // Expression depends on the document
35
// containing the context node
36
public static final int NO_DEPENDENCIES = 0;
37     public static final int ALL_DEPENDENCIES = 255;
38     public static final int XSLT_CONTEXT = CONTROLLER | VARIABLES | CURRENT_NODE;
39
40     private NodeInfo contextNode;
41     private NodeInfo currentNode;
42     private int position = -1;
43     private int last = -1;
44     private LastPositionFinder lastPositionFinder;
45     private Controller controller;
46     //private Bindery bindery;
47
private Mode currentMode;
48     private XSLTemplate currentTemplate;
49     private Stack JavaDoc groupActivationStack; // holds stack of active saxon:group activations
50
private StaticContext staticContext;
51     private ParameterSet tailRecursion; // set when a tail-recursive call is requested
52
private NodeInfo lastRememberedNode = null;
53     private int lastRememberedNumber = -1;
54     private Value returnValue = null;
55     private XPathException exception = null;
56     
57     private static Controller defaultController = null;
58     
59     /**
60     * The default constructor is not used within Saxon itself, but is available to
61     * applications (and is used in some samples). Because some expressions (for example
62     * union expressions) cannot execute without a Controller, a system default Controller
63     * is created. This is a quick fix, but is not entirely satisfactory, because it's
64     * not thread-safe. Applications are encouraged to create a Controller explicitly and
65     * use it only within a single thread.
66     */

67     
68     public Context() {
69         if (defaultController==null) {
70             defaultController = new Controller();
71         }
72         controller = defaultController;
73         lastPositionFinder = this;
74     }
75         
76
77     /**
78     * Constructor should only be called by the Controller, which acts as a Context factory.
79     */

80
81     public Context(Controller c) {
82         controller = c;
83         lastPositionFinder = this;
84     }
85
86     /**
87     * Construct a new context as a copy of another
88     */

89
90     public Context newContext() {
91         Context c = new Context(controller);
92         c.staticContext = staticContext;
93         c.currentNode = currentNode;
94         c.contextNode = contextNode;
95         c.position = position;
96         c.last = last;
97         c.lastPositionFinder = lastPositionFinder;
98         c.currentMode = currentMode;
99         c.currentTemplate = currentTemplate;
100         //c.bindery = bindery;
101
c.groupActivationStack = groupActivationStack;
102         c.lastRememberedNode = lastRememberedNode;
103         c.lastRememberedNumber = lastRememberedNumber;
104         c.returnValue = null;
105         return c;
106     }
107
108     /**
109     * Set the controller for this Context
110     */

111
112     public void setController(Controller c) {
113         controller = c;
114     }
115
116     /**
117     * Get the controller for this Context
118     */

119
120     public Controller getController() {
121         return controller;
122     }
123
124     /**
125     * Get the Bindery used by this Context
126     */

127
128     public Bindery getBindery() {
129         return controller.getBindery();
130     }
131
132     /**
133     * Get the current Outputter. This gives access to the writeStartTag, writeAttribute,
134     * and writeEndTag methods
135     * @return the current Outputter
136     */

137
138     public Outputter getOutputter() {
139         return controller.getOutputter();
140     }
141     
142     /**
143     * Set the mode (for use by the built-in handlers)
144     */

145
146     public void setMode(Mode mode) {
147         currentMode = mode;
148     }
149
150     /**
151     * Get the current mode (for use by the built-in handlers)
152     */

153
154     public Mode getMode() {
155         return currentMode;
156     }
157
158     /**
159     * Set the context node. <br>
160     * Note that this has no effect on position() or last(), which must be set separately.
161     * @param node the node that is to be the context node.
162     */

163
164     public void setContextNode(NodeInfo node) {
165         this.contextNode = node;
166     }
167
168     /**
169     * Get the context node
170     * @return the context node
171     */

172
173     public NodeInfo getContextNodeInfo() {
174         return contextNode;
175     }
176
177     /**
178     * Get the context node, provided it is a DOM Node
179     * @return the context node if it is a DOM Node, otherwise null
180     */

181
182     public Node JavaDoc getContextNode() {
183         if (contextNode instanceof Node JavaDoc) {
184             return (Node JavaDoc)contextNode;
185         } else {
186             return null;
187         }
188     }
189
190     /**
191     * Set the context position
192     */

193
194     public void setPosition(int pos) {
195         position = pos;
196     }
197
198     /**
199     * Get the context position (the position of the context node in the context node list)
200     * @return the context position (starting at one)
201     */

202
203     public int getContextPosition() {
204         return position;
205     }
206
207     /**
208     * Set the context size; this also makes the Context object responisble for returning the last()
209     * position.
210     */

211
212     public void setLast(int last) {
213         this.last = last;
214         lastPositionFinder = this;
215     }
216
217     /**
218     * Set the LastPositionFinder, another object that will do the work of returning the last()
219     * position
220     */

221
222     public void setLastPositionFinder(LastPositionFinder finder) {
223         lastPositionFinder = finder;
224     }
225
226     /**
227     * Get the context size (the position of the last item in the current node list)
228     * @return the context size
229     */

230
231     public int getLast() throws XPathException {
232         if (lastPositionFinder==null) return 1; // fallback, shouldn't happen
233
return lastPositionFinder.getLastPosition();
234     }
235
236     /**
237     * Determine whether the context position is the same as the context size
238     * that is, whether position()=last()
239     */

240     
241     public boolean isAtLast() throws XPathException {
242         // The code is designed to answer the question without searching to the end
243
// of the node-set to determine the last position, wherever possible
244
if (lastPositionFinder!=null && lastPositionFinder instanceof NodeEnumeration) {
245             return !((NodeEnumeration)lastPositionFinder).hasMoreElements();
246         } else {
247             return getContextPosition() == getLast();
248         }
249     }
250
251     /**
252     * Get the context size (the position of the last item in the current node list).
253     * This is the XSLTContext method: it differs from getLast() in that it cannot throw
254     * an exception.
255     * This method should be called only from within extension functions. If any error occurs,
256     * it will be accessible via Context#getException().
257     * @return the context size
258     */

259
260     public int getContextSize() {
261         try {
262             return getLast();
263         } catch (XPathException err) {
264             // The XSLTContext interfaces doesn't allow us to throw any exceptions.
265
// We'll pick it up on return from the extension function.
266
setException(err);
267             return getContextPosition(); // for want of anything better
268
}
269     }
270
271     /**
272     * Get the last position, to be used only
273     * when the context object is being used as the last position finder
274     */

275
276     public int getLastPosition() {
277         return last;
278     }
279
280     /**
281     * Set the current node. This is the node in the source document currently being processed
282     * (e.g. by apply-templates).
283     */

284
285     public void setCurrentNode(NodeInfo node) {
286         currentNode = node;
287     }
288
289     /**
290     * Get the current node. This is the node in the source document currently being processed
291     * (e.g. by apply-templates). It is not necessarily the same as the context node: the context
292     * node can change in a sub-expression, the current node cannot.
293     */

294
295     public NodeInfo getCurrentNodeInfo() {
296         return currentNode;
297     }
298
299     /**
300     * Get the current node,provided it is a DOM Node.
301     * This is the node in the source document currently being processed
302     * (e.g. by apply-templates). It is not necessarily the same as the context node: the context
303     * node can change in a sub-expression, the current node cannot.
304     * @return the current node if it is a DOM Node; otherwise null.
305     */

306
307     public Node JavaDoc getCurrentNode() {
308         if (currentNode instanceof Node JavaDoc) {
309             return (Node JavaDoc)currentNode;
310         } else {
311             return null;
312         }
313     }
314
315     /**
316     * Set the current template. This is used to support xsl:apply-imports
317     */

318
319     public void setCurrentTemplate(XSLTemplate template) {
320         currentTemplate = template;
321     }
322
323     /**
324     * Get the current template. This is used to support xsl:apply-imports
325     */

326
327     public XSLTemplate getCurrentTemplate() {
328         return currentTemplate;
329     }
330
331     /**
332     * Get owner Document (enabling extension functions to create new Nodes)
333     */

334     
335     public Document JavaDoc getOwnerDocument() {
336         return (Document JavaDoc)(Node JavaDoc)contextNode.getDocumentRoot();
337     }
338     
339     /**
340     * Get the value of a system property
341     */

342     
343     public Object JavaDoc systemProperty(String JavaDoc namespaceURI, String JavaDoc localName) {
344         try {
345             Value prop = SystemProperty.getProperty(namespaceURI, localName);
346             if (prop==null) {
347                 return null;
348             } else if (prop instanceof StringValue) {
349                 return prop.asString();
350             } else if (prop instanceof NumericValue) {
351                 return new Double JavaDoc(prop.asNumber());
352             } else if (prop instanceof BooleanValue) {
353                 return new Boolean JavaDoc(prop.asBoolean());
354             } else {
355                 return prop;
356             }
357         } catch (Exception JavaDoc err) {
358             return null;
359         }
360     }
361         
362     /**
363     * Return the String value of a node
364     * @throws IllegalArgumentException if it is not a Saxon node
365     */

366     
367     public String JavaDoc stringValue(Node JavaDoc n) {
368         if (n instanceof NodeInfo) {
369             return ((NodeInfo)n).getStringValue();
370         } else {
371             throw new IllegalArgumentException JavaDoc("Node is not a Saxon node");
372         }
373     }
374
375     /**
376     * Set the static context
377     */

378
379     public void setStaticContext(StaticContext sc) {
380         staticContext = sc;
381     }
382
383     /**
384     * Get the static context. This is currently available only while processing an
385     * extension function
386     */

387
388     public StaticContext getStaticContext() {
389         return staticContext;
390     }
391
392     /**
393     * Set an exception value. This is useful when an extension function makes a call
394     * such as getContextSize() that causes an error. The error is saved as part of the
395     * context, and reported on return from the extension function
396     */

397     
398     public void setException(XPathException err) {
399         exception = err;
400     }
401     
402     /**
403     * Get the saved exception value.
404     */

405     
406     public XPathException getException() {
407         return exception;
408     }
409
410     /**
411     * Get the saxon:group activation stack
412     */

413
414     public Stack JavaDoc getGroupActivationStack() {
415         if (groupActivationStack==null) {
416             groupActivationStack = new Stack JavaDoc();
417         }
418         return groupActivationStack;
419     }
420
421     /**
422     * Set the last remembered node, for node numbering purposes
423     */

424
425     public void setRememberedNumber(NodeInfo node, int number) {
426         lastRememberedNode = node;
427         lastRememberedNumber = number;
428     }
429
430     /**
431     * Get the number of a node if it is the last remembered one.
432     * @return the number of this node if known, else -1.
433     */

434
435     public int getRememberedNumber(NodeInfo node) {
436         if (lastRememberedNode == node) return lastRememberedNumber;
437         return -1;
438     }
439
440     /**
441     * Set tail recursion parameters
442     */

443
444     public void setTailRecursion(ParameterSet p) {
445         tailRecursion = p;
446     }
447
448     /**
449     * Get tail recursion parameters
450     */

451
452     public ParameterSet getTailRecursion() {
453         return tailRecursion;
454     }
455
456     /**
457     * Set return value from function
458     */

459
460     public void setReturnValue(Value value) throws TransformerException JavaDoc {
461         if (value != null && returnValue != null) {
462             throw new TransformerException JavaDoc("A function can only return one result");
463         }
464         returnValue = value;
465     }
466
467     /**
468     * Get the return value from function
469     */

470
471     public Value getReturnValue() {
472         return returnValue;
473     }
474 }
475
476 //
477
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
478
// you may not use this file except in compliance with the License. You may obtain a copy of the
479
// License at http://www.mozilla.org/MPL/
480
//
481
// Software distributed under the License is distributed on an "AS IS" basis,
482
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
483
// See the License for the specific language governing rights and limitations under the License.
484
//
485
// The Original Code is: all this file.
486
//
487
// The Initial Developer of the Original Code is
488
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
489
//
490
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
491
//
492
// Contributor(s): none.
493
//
494
Popular Tags