KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > expr > XPathContextMinor


1 package net.sf.saxon.expr;
2 import net.sf.saxon.Configuration;
3 import net.sf.saxon.Controller;
4 import net.sf.saxon.event.*;
5 import net.sf.saxon.instruct.LocalParam;
6 import net.sf.saxon.instruct.ParameterSet;
7 import net.sf.saxon.instruct.RegexIterator;
8 import net.sf.saxon.instruct.Template;
9 import net.sf.saxon.om.*;
10 import net.sf.saxon.sort.CodepointCollator;
11 import net.sf.saxon.sort.GroupIterator;
12 import net.sf.saxon.trace.InstructionInfoProvider;
13 import net.sf.saxon.trans.DynamicError;
14 import net.sf.saxon.trans.Mode;
15 import net.sf.saxon.trans.XPathException;
16 import net.sf.saxon.type.SchemaType;
17
18 import javax.xml.transform.Result JavaDoc;
19 import java.util.Comparator JavaDoc;
20 import java.util.Properties JavaDoc;
21
22 /**
23  * This class represents a minor change in the dynamic context in which an XPath expression is evaluated:
24  * a "major context" object allows all aspects of the dynamic context to change, whereas
25  * a "minor context" only allows changes to the focus and the destination for push output.
26 */

27
28 public class XPathContextMinor implements XPathContext {
29
30     Controller controller;
31     SequenceIterator currentIterator;
32     int last = -1;
33     SequenceReceiver currentReceiver;
34     boolean isTemporaryDestination = false;
35     XPathContext caller = null;
36     Object JavaDoc origin = null;
37
38     /**
39     * Private Constructor
40     */

41
42     protected XPathContextMinor() {
43     }
44
45     /**
46     * Construct a new context as a copy of another. The new context is effectively added
47     * to the top of a stack, and contains a pointer to the previous context
48     */

49
50     public XPathContextMajor newContext() {
51         return XPathContextMajor.newContext(this);
52     }
53
54     public XPathContextMinor newMinorContext() {
55         XPathContextMinor c = new XPathContextMinor();
56         c.controller = controller;
57         c.caller = this;
58         c.currentIterator = currentIterator;
59         c.currentReceiver = currentReceiver;
60         c.last = last;
61         c.isTemporaryDestination = isTemporaryDestination;
62         return c;
63     }
64
65     /**
66      * Set the calling XPathContext
67      */

68
69     public void setCaller(XPathContext caller) {
70         this.caller = caller;
71     }
72
73     /**
74     * Construct a new context without copying (used for the context in a function call)
75     */

76
77     public XPathContextMajor newCleanContext() {
78         XPathContextMajor c = new XPathContextMajor(this.getController());
79         c.setCaller(this);
80         return c;
81     }
82
83     /**
84      * Get the XSLT-specific part of the context
85      */

86
87     public XPathContextMajor.XSLTContext getXSLTContext() {
88         return getCaller().getXSLTContext();
89     }
90
91     /**
92      * Get the local parameters for the current template call.
93      * @return the supplied parameters
94      */

95
96     public ParameterSet getLocalParameters() {
97         return getCaller().getLocalParameters();
98     }
99
100     /**
101      * Get the tunnel parameters for the current template call.
102      * @return the supplied tunnel parameters
103      */

104
105     public ParameterSet getTunnelParameters() {
106         return getCaller().getTunnelParameters();
107     }
108
109     /**
110      * Set the creating expression (for use in diagnostics). The origin is generally set to "this" by the
111      * object that creates the new context. It's up to the debugger to determine whether this information
112      * is useful. Where possible, the object will be an {@link InstructionInfoProvider}, allowing information
113      * about the calling instruction to be obtained.
114      */

115
116     public void setOrigin(InstructionInfoProvider expr) {
117         origin = expr;
118     }
119
120     /**
121      * Set the type of creating expression (for use in diagnostics). When a new context is created, either
122      * this method or {@link #setOrigin} should be called.
123      * @param loc The originating location: the argument must be one of the integer constants in class
124      * {@link net.sf.saxon.trace.Location}
125      */

126
127     public void setOriginatingConstructType(int loc) {
128         origin = new Integer JavaDoc(loc);
129     }
130
131     /**
132      * Get the type of location from which this context was created.
133      */

134
135     public int getOriginatingConstructType() {
136         if (origin instanceof InstructionInfoProvider) {
137             return ((InstructionInfoProvider)origin).getInstructionInfo().getConstructType();
138         } else {
139             return ((Integer JavaDoc)origin).intValue();
140         }
141     }
142
143     /**
144      * Get information about the creating expression or other construct.
145      */

146
147     public InstructionInfoProvider getOrigin() {
148         if (origin instanceof InstructionInfoProvider) {
149             return (InstructionInfoProvider)origin;
150         } else {
151             return null;
152         }
153     }
154
155     /**
156     * Get the Controller. May return null when running outside XSLT or XQuery
157     */

158
159     public Controller getController() {
160         return controller;
161     }
162
163     /**
164      * Get the calling XPathContext (the next one down the stack). This will be null if unknown, or
165      * if the bottom of the stack has been reached.
166      */

167
168     public XPathContext getCaller() {
169         return caller;
170     }
171
172     /**
173     * Set a new sequence iterator.
174     */

175
176     public void setCurrentIterator(SequenceIterator iter) {
177         currentIterator = iter;
178         last = 0;
179     }
180
181     /**
182      * Get the current iterator.
183      * This encapsulates the context item, context position, and context size.
184      * @return the current iterator, or null if there is no current iterator
185      * (which means the context item, position, and size are undefined).
186     */

187
188     public SequenceIterator getCurrentIterator() {
189         return currentIterator;
190     }
191
192     /**
193      * Get the context position (the position of the context item)
194      * @return the context position (starting at one)
195      * @throws DynamicError if the context position is undefined
196     */

197
198     public int getContextPosition() throws DynamicError {
199         if (currentIterator==null) {
200             DynamicError e = new DynamicError("The context position is currently undefined");
201             e.setXPathContext(this);
202             e.setErrorCode("XPDY0002");
203             throw e;
204         }
205         return currentIterator.position();
206     }
207
208     /**
209     * Get the context item
210      * @return the context item, or null if the context item is undefined
211     */

212
213     public Item getContextItem() {
214         if (currentIterator==null) {
215             return null;
216         }
217         return currentIterator.current();
218     }
219
220     /**
221      * Get the context size (the position of the last item in the current node list)
222      * @return the context size
223      * @throws XPathException if the context position is undefined
224      */

225
226     public int getLast() throws XPathException {
227         if (last>0) return last;
228         if (currentIterator==null) {
229             DynamicError e = new DynamicError("The context size is currently undefined");
230             e.setXPathContext(this);
231             e.setErrorCode("XPDY0002");
232             throw e;
233         }
234         if ((currentIterator.getProperties() & SequenceIterator.LAST_POSITION_FINDER) != 0) {
235             last = ((LastPositionFinder)currentIterator).getLastPosition();
236             return last;
237         } else {
238             SequenceIterator another = currentIterator.getAnother();
239             last = 0;
240             while (another.next() != null) {
241                 last++;
242             }
243             return last;
244         }
245     }
246
247     /**
248     * Determine whether the context position is the same as the context size
249     * that is, whether position()=last()
250     */

251
252     public boolean isAtLast() throws XPathException {
253         if ((currentIterator.getProperties() & SequenceIterator.LOOKAHEAD) != 0) {
254             return !((LookaheadIterator)currentIterator).hasNext();
255             // TODO: reinstate this optimization for more types of iterator!
256
}
257         return getContextPosition() == getLast();
258     }
259
260     /**
261     * Get a named collation
262     */

263
264     public Comparator JavaDoc getCollation(String JavaDoc name) throws XPathException {
265         if (name.equals(NamespaceConstant.CODEPOINT_COLLATION_URI)) {
266             return CodepointCollator.getInstance();
267         }
268         Comparator JavaDoc collation = null;
269         if (controller != null) {
270             collation = controller.getExecutable().getNamedCollation(name);
271
272             if (collation == null) {
273                 Configuration config = controller.getConfiguration();
274                 collation = config.getCollationURIResolver().resolve(name, null, config);
275                 //collation = CollationFactory.makeCollationFromURI(name, getController().getConfiguration());
276
}
277         }
278         if (collation==null) {
279             DynamicError e = new DynamicError("Unknown collation " + name);
280             e.setXPathContext(this);
281             throw e;
282         }
283         return collation;
284     }
285
286     /**
287     * Get the default collation
288     */

289
290     public Comparator JavaDoc getDefaultCollation() {
291         if (controller != null) {
292             return controller.getExecutable().getDefaultCollation();
293         } else {
294             return CodepointCollator.getInstance();
295         }
296     }
297
298     /**
299      * Get a reference to the local stack frame for variables. Note that it's
300      * the caller's job to make a local copy of this. This is used for creating
301      * a Closure containing a retained copy of the variables for delayed evaluation.
302      * @return array of variables.
303      */

304
305     public StackFrame getStackFrame() {
306         return getCaller().getStackFrame();
307     }
308
309
310     /**
311      * Get the value of a local variable, identified by its slot number
312      */

313
314     public ValueRepresentation evaluateLocalVariable(int slotnumber) {
315         return getCaller().evaluateLocalVariable(slotnumber);
316     }
317
318     /**
319      * Set the value of a local variable, identified by its slot number
320      */

321
322     public void setLocalVariable(int slotnumber, ValueRepresentation value) {
323         getCaller().setLocalVariable(slotnumber, value);
324     }
325
326     /**
327      * Set a new output destination, supplying the output format details. <BR>
328      * This affects all further output until resetOutputDestination() is called. Note that
329      * it is the caller's responsibility to close the Writer after use.
330      *
331      * @exception XPathException if any dynamic error occurs; and
332      * specifically, if an attempt is made to switch to a final output
333      * destination while writing a temporary tree or sequence
334      * @param props properties defining the output format
335      * @param result Details of the new output destination
336      * @param isFinal true if the destination is a final result tree
337      * (either the principal output or a secondary result tree); false if
338      * it is a temporary tree, xsl:attribute, etc.
339      */

340
341     public void changeOutputDestination(Properties JavaDoc props,
342                                         Result JavaDoc result,
343                                         boolean isFinal,
344                                         int validation,
345                                         SchemaType schemaType)
346     throws XPathException {
347         if (isFinal && isTemporaryDestination) {
348             DynamicError err = new DynamicError("Cannot switch to a final result destination while writing a temporary tree");
349             err.setErrorCode("XTDE1480");
350             throw err;
351         }
352         if (isFinal) {
353             validation |= Validation.VALIDATE_OUTPUT;
354         } else {
355             isTemporaryDestination = true;
356         }
357         PipelineConfiguration pipe = controller.makePipelineConfiguration();
358         pipe.setSerializing(isFinal);
359         ComplexContentOutputter out = new ComplexContentOutputter();
360         out.setPipelineConfiguration(pipe);
361
362         if (props == null) {
363             props = new Properties JavaDoc();
364         }
365
366
367         Receiver receiver = ResultWrapper.getReceiver(
368                                             result,
369                                             pipe,
370                                             props);
371
372         // add a validator to the pipeline if required
373

374         receiver = controller.getConfiguration().getDocumentValidator(
375                 receiver, receiver.getSystemId(), controller.getNamePool(), validation,
376                 schemaType);
377
378         // add a filter to remove duplicate namespaces
379

380         NamespaceReducer ne = new NamespaceReducer();
381         ne.setUnderlyingReceiver(receiver);
382         ne.setPipelineConfiguration(pipe);
383         out.setReceiver(ne);
384
385         out.open();
386         currentReceiver = out;
387     }
388
389     /**
390      * Set the output destination to write to a sequence. <BR>
391      * This affects all further output until resetOutputDestination() is called.
392      *
393      * @param out The SequenceReceiver to be used
394      */

395
396     public void setTemporaryReceiver(SequenceReceiver out) {
397         isTemporaryDestination = true;
398         currentReceiver = out;
399     }
400
401     /**
402      * Change the Receiver to which output is written
403      */

404
405     public void setReceiver(SequenceReceiver receiver) {
406         currentReceiver = receiver;
407     }
408
409     /**
410      * Get the Receiver to which output is currently being written.
411      *
412      * @return the current Receiver
413      */

414     public SequenceReceiver getReceiver() {
415         return currentReceiver;
416     }
417
418     /**
419     * Use local parameter. This is called when a local xsl:param element is processed.
420     * If a parameter of the relevant name was supplied, it is bound to the xsl:param element.
421     * Otherwise the method returns false, so the xsl:param default will be evaluated
422     * @param fingerprint The fingerprint of the parameter name
423     * @param binding The XSLParam element to bind its value to
424     * @param isTunnel True if a tunnel parameter is required, else false
425     * @return true if a parameter of this name was supplied, false if not
426     */

427
428     public boolean useLocalParameter(int fingerprint,
429                                      LocalParam binding,
430                                      boolean isTunnel) throws XPathException {
431         return getCaller().useLocalParameter(fingerprint, binding, isTunnel);
432     }
433
434     /**
435      * Get the current mode.
436      * @return the current mode
437      */

438
439     public Mode getCurrentMode() {
440         return getCaller().getCurrentMode();
441     }
442
443     /**
444      * Get the current template. This is used to support xsl:apply-imports
445      *
446      * @return the current template
447      */

448
449     public Template getCurrentTemplate() {
450         return getCaller().getCurrentTemplate();
451     }
452
453     /**
454      * Get the current group iterator. This supports the current-group() and
455      * current-grouping-key() functions in XSLT 2.0
456      * @return the current grouped collection
457      */

458
459     public GroupIterator getCurrentGroupIterator() {
460         return getCaller().getCurrentGroupIterator();
461     }
462
463     /**
464      * Get the current regex iterator. This supports the functionality of the regex-group()
465      * function in XSLT 2.0.
466      * @return the current regular expressions iterator
467      */

468
469     public RegexIterator getCurrentRegexIterator() {
470         return getCaller().getCurrentRegexIterator();
471     }
472
473     /**
474      * Get the implicit timezone, as a positive or negative offset from UTC in minutes.
475      * The range is -14hours to +14hours
476      */

477
478     public int getImplicitTimezone() {
479         return getController().getConfiguration().getImplicitTimezone();
480     }
481 }
482
483 //
484
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
485
// you may not use this file except in compliance with the License. You may obtain a copy of the
486
// License at http://www.mozilla.org/MPL/
487
//
488
// Software distributed under the License is distributed on an "AS IS" basis,
489
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
490
// See the License for the specific language governing rights and limitations under the License.
491
//
492
// The Original Code is: all this file.
493
//
494
// The Initial Developer of the Original Code is Michael H. Kay.
495
//
496
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
497
//
498
// Contributor(s): none.
499
//
500
Popular Tags