KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > pull > PullFromIterator


1 package net.sf.saxon.pull;
2
3 import net.sf.saxon.event.PipelineConfiguration;
4 import net.sf.saxon.om.*;
5 import net.sf.saxon.trans.XPathException;
6 import net.sf.saxon.type.AtomicType;
7 import net.sf.saxon.type.Type;
8 import net.sf.saxon.value.AtomicValue;
9
10 import javax.xml.transform.SourceLocator JavaDoc;
11
12 /**
13  * This class delivers any XPath sequence through the pull interface. Atomic values
14  * in the sequence are supplied unchanged, as are top-level text, comment, attribute,
15  * namespace, and processing-instruction nodes. Elements and documents appearing in
16  * the input sequence are supplied as a sequence of events that walks recursively
17  * down the subtree rooted at that node. The input is supplied in the form of a
18  * SequenceIterator.
19  */

20
21 public class PullFromIterator implements PullProvider {
22
23     private SequenceIterator base;
24     private PullProvider treeWalker = null;
25     private PipelineConfiguration pipe;
26     private int currentEvent = START_OF_INPUT;
27
28     public PullFromIterator(SequenceIterator base) {
29         this.base = base;
30     }
31
32     /**
33      * Set configuration information. This must only be called before any events
34      * have been read.
35      */

36
37     public void setPipelineConfiguration(PipelineConfiguration pipe) {
38         this.pipe = pipe;
39     }
40
41     /**
42      * Get configuration information.
43      */

44
45     public PipelineConfiguration getPipelineConfiguration() {
46         return pipe;
47     }
48
49     /**
50      * Get the next event
51      *
52      * @return an integer code indicating the type of event. The code
53      * {@link #END_OF_INPUT} is returned at the end of the sequence.
54      */

55
56     public int next() throws XPathException {
57         if (treeWalker == null) {
58             Item item = base.next();
59             if (item == null) {
60                 currentEvent = END_OF_INPUT;
61                 return currentEvent;
62             } else if (item instanceof UnconstructedParent) {
63                 // this represents a lazily-evaluated element or document node constructor
64
treeWalker = ((UnconstructedParent)item).getPuller();
65                 treeWalker.setPipelineConfiguration(pipe);
66                 currentEvent = treeWalker.next();
67                 return currentEvent;
68             } else if (item instanceof AtomicValue) {
69                 currentEvent = ATOMIC_VALUE;
70                 return currentEvent;
71             } else {
72                 switch (((NodeInfo)item).getNodeKind()) {
73                     case Type.TEXT:
74                         currentEvent = TEXT;
75                         return currentEvent;
76
77                     case Type.COMMENT:
78                         currentEvent = COMMENT;
79                         return currentEvent;
80
81                     case Type.PROCESSING_INSTRUCTION:
82                         currentEvent = PROCESSING_INSTRUCTION;
83                         return currentEvent;
84
85                     case Type.ATTRIBUTE:
86                         currentEvent = ATTRIBUTE;
87                         return currentEvent;
88
89                     case Type.NAMESPACE:
90                         currentEvent = NAMESPACE;
91                         return currentEvent;
92
93                     case Type.ELEMENT:
94                     case Type.DOCUMENT:
95                         treeWalker = TreeWalker.makeTreeWalker((NodeInfo)item);
96                         treeWalker.setPipelineConfiguration(pipe);
97                         currentEvent = treeWalker.next();
98                         return currentEvent;
99
100                     default:
101                         throw new IllegalStateException JavaDoc();
102
103                 }
104             }
105
106         } else {
107             // there is an active TreeWalker: just return its next event
108
int event = treeWalker.next();
109             if (event == END_OF_INPUT) {
110                 treeWalker = null;
111                 currentEvent = next();
112             } else {
113                 currentEvent = event;
114             }
115             return currentEvent;
116
117         }
118     }
119
120     /**
121      * Get the event most recently returned by next(), or by other calls that change
122      * the position, for example getStringValue() and skipToMatchingEnd(). This
123      * method does not change the position of the PullProvider.
124      *
125      * @return the current event
126      */

127
128     public int current() {
129         return currentEvent;
130     }
131
132     /**
133      * Get the attributes associated with the current element. This method must
134      * be called only after a START_ELEMENT event has been notified. The contents
135      * of the returned AttributeCollection are guaranteed to remain unchanged
136      * until the next START_ELEMENT event, but may be modified thereafter. The object
137      * should not be modified by the client.
138      * <p/>
139      * <p>Attributes may be read before or after reading the namespaces of an element,
140      * but must not be read after the first child node has been read, or after calling
141      * one of the methods skipToEnd(), getStringValue(), or getTypedValue().</p>
142      *
143      * @return an AttributeCollection representing the attributes of the element
144      * that has just been notified.
145      */

146
147     public AttributeCollection getAttributes() throws XPathException {
148         if (treeWalker != null) {
149             return treeWalker.getAttributes();
150         } else {
151             throw new IllegalStateException JavaDoc();
152         }
153     }
154
155     /**
156      * Get the namespace declarations associated with the current element. This method must
157      * be called only after a START_ELEMENT event has been notified. In the case of a top-level
158      * START_ELEMENT event (that is, an element that either has no parent node, or whose parent
159      * is not included in the sequence being read), the NamespaceDeclarations object returned
160      * will contain a namespace declaration for each namespace that is in-scope for this element
161      * node. In the case of a non-top-level element, the NamespaceDeclarations will contain
162      * a set of namespace declarations and undeclarations, representing the differences between
163      * this element and its parent.
164      * <p/>
165      * <p>It is permissible for this method to return namespace declarations that are redundant.</p>
166      * <p/>
167      * <p>The NamespaceDeclarations object is guaranteed to remain unchanged until the next START_ELEMENT
168      * event, but may then be overwritten. The object should not be modified by the client.</p>
169      * <p/>
170      * <p>Namespaces may be read before or after reading the attributes of an element,
171      * but must not be read after the first child node has been read, or after calling
172      * one of the methods skipToEnd(), getStringValue(), or getTypedValue().</p>*
173      */

174
175     public NamespaceDeclarations getNamespaceDeclarations() throws XPathException {
176         if (treeWalker != null) {
177             return treeWalker.getNamespaceDeclarations();
178         } else {
179             throw new IllegalStateException JavaDoc();
180         }
181     }
182
183     /**
184      * Skip the current subtree. This method may be called only immediately after
185      * a START_DOCUMENT or START_ELEMENT event. This call returns the matching
186      * END_DOCUMENT or END_ELEMENT event; the next call on next() will return
187      * the event following the END_DOCUMENT or END_ELEMENT.
188      */

189
190     public int skipToMatchingEnd() throws XPathException {
191         if (treeWalker != null) {
192             return treeWalker.skipToMatchingEnd();
193         } else {
194             throw new IllegalStateException JavaDoc();
195         }
196     }
197
198     /**
199      * Close the event reader. This indicates that no further events are required.
200      * It is not necessary to close an event reader after {@link #END_OF_INPUT} has
201      * been reported, but it is recommended to close it if reading terminates
202      * prematurely. Once an event reader has been closed, the effect of further
203      * calls on next() is undefined.
204      */

205
206     public void close() {
207         if (treeWalker != null) {
208             treeWalker.close();
209         }
210     }
211
212     /**
213      * Get the nameCode identifying the name of the current node. This method
214      * can be used after the {@link #START_ELEMENT}, {@link #PROCESSING_INSTRUCTION},
215      * {@link #ATTRIBUTE}, or {@link #NAMESPACE} events. With some PullProvider implementations,
216      * including this one, it can also be used after {@link #END_ELEMENT}.
217      * If called at other times, the result is undefined and may result in an IllegalStateException.
218      * If called when the current node is an unnamed namespace node (a node representing the default namespace)
219      * the returned value is -1.
220      *
221      * @return the nameCode. The nameCode can be used to obtain the prefix, local name,
222      * and namespace URI from the name pool.
223      */

224
225     public int getNameCode() {
226         if (treeWalker != null) {
227             return treeWalker.getNameCode();
228         } else {
229             Item item = base.current();
230             if (item instanceof NodeInfo) {
231                 return ((NodeInfo)item).getNameCode();
232             } else {
233                 throw new IllegalStateException JavaDoc();
234             }
235         }
236     }
237
238     /**
239      * Get the fingerprint of the name of the element. This is similar to the nameCode, except that
240      * it does not contain any information about the prefix: so two elements with the same fingerprint
241      * have the same name, excluding prefix. This method
242      * can be used after the {@link #START_ELEMENT}, {@link #END_ELEMENT}, {@link #PROCESSING_INSTRUCTION},
243      * {@link #ATTRIBUTE}, or {@link #NAMESPACE} events.
244      * If called at other times, the result is undefined and may result in an IllegalStateException.
245      * If called when the current node is an unnamed namespace node (a node representing the default namespace)
246      * the returned value is -1.
247      *
248      * @return the fingerprint. The fingerprint can be used to obtain the local name
249      * and namespace URI from the name pool.
250      */

251
252     public int getFingerprint() {
253         int nc = getNameCode();
254         if (nc == -1) {
255             return -1;
256         } else {
257             return nc & NamePool.FP_MASK;
258         }
259     }
260
261     /**
262      * Get the string value of the current element, text node, processing-instruction,
263      * or top-level attribute or namespace node, or atomic value.
264      * <p/>
265      * <p>In other situations the result is undefined and may result in an IllegalStateException.</p>
266      * <p/>
267      * <p>If the most recent event was a {@link #START_ELEMENT}, this method causes the content
268      * of the element to be read. The current event on completion of this method will be the
269      * corresponding {@link #END_ELEMENT}. The next call of next() will return the event following
270      * the END_ELEMENT event.</p>
271      *
272      * @return the String Value of the node in question, defined according to the rules in the
273      * XPath data model.
274      */

275
276     public CharSequence JavaDoc getStringValue() throws XPathException {
277         if (treeWalker != null) {
278             return treeWalker.getStringValue();
279         } else {
280             Item item = base.current();
281             return item.getStringValueCS();
282         }
283     }
284
285     /**
286      * Get an atomic value. This call may be used only when the last event reported was
287      * ATOMIC_VALUE. This indicates that the PullProvider is reading a sequence that contains
288      * a free-standing atomic value; it is never used when reading the content of a node.
289      */

290
291     public AtomicValue getAtomicValue() {
292         if (currentEvent == ATOMIC_VALUE) {
293             return (AtomicValue)base.current();
294         } else {
295             throw new IllegalStateException JavaDoc();
296         }
297     }
298
299     /**
300      * Get the type annotation of the current attribute or element node, or atomic value.
301      * The result of this method is undefined unless the most recent event was START_ELEMENT,
302      * ATTRIBUTE, or ATOMIC_VALUE.
303      *
304      * @return the type annotation. This code is the fingerprint of a type name, which may be
305      * resolved to a {@link net.sf.saxon.type.SchemaType} by access to the Configuration.
306      */

307
308     public int getTypeAnnotation() {
309         if (treeWalker != null) {
310             return treeWalker.getTypeAnnotation();
311         } else {
312             Item item = base.current();
313             if (item instanceof NodeInfo) {
314                 return ((NodeInfo)item).getTypeAnnotation();
315             } else {
316                 return ((AtomicType)((AtomicValue)item).getItemType()).getFingerprint();
317             }
318         }
319     }
320
321     /**
322      * Get the location of the current event.
323      * For an event stream representing a real document, the location information
324      * should identify the location in the lexical XML source. For a constructed document, it should
325      * identify the location in the query or stylesheet that caused the node to be created.
326      * A value of null can be returned if no location information is available.
327      */

328
329     public SourceLocator JavaDoc getSourceLocator() {
330         if (treeWalker != null) {
331             return treeWalker.getSourceLocator();
332         } else {
333             return null;
334         }
335     }
336 }
337
338
339 //
340
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
341
// you may not use this file except in compliance with the License. You may obtain a copy of the
342
// License at http://www.mozilla.org/MPL/
343
//
344
// Software distributed under the License is distributed on an "AS IS" basis,
345
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
346
// See the License for the specific language governing rights and limitations under the License.
347
//
348
// The Original Code is: all this file.
349
//
350
// The Initial Developer of the Original Code is Michael H. Kay.
351
//
352
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
353
//
354
// Contributor(s): none.
355
//
Popular Tags