KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > event > SequenceWriter


1 package net.sf.saxon.event;
2
3 import net.sf.saxon.trans.XPathException;
4 import net.sf.saxon.tinytree.TinyBuilder;
5 import net.sf.saxon.om.*;
6 import net.sf.saxon.type.Type;
7 import net.sf.saxon.value.AtomicValue;
8
9 /**
10  * This outputter is used when writing a sequence of atomic values and nodes, for
11  * example, when xsl:variable is used with content and an "as" attribute. The outputter
12  * builds the sequence; the concrete subclass is responsible for deciding what to do with the
13  * resulting items.
14  *
15  * <p>This class is not used to build temporary trees. For that, the ComplexContentOutputter
16  * is used.</p>
17  *
18  *
19  * @author Michael H. Kay
20  */

21
22 public abstract class SequenceWriter extends SequenceReceiver {
23     private String JavaDoc systemId;
24     private Receiver tree = null;
25     private TinyBuilder builder = null;
26     private int level = 0;
27     private boolean inStartTag = false;
28     private static final int[] treeSizeParameters = {50, 10, 5, 200};
29
30
31
32     /**
33      * Abstract method to be supplied by subclasses: output one item in the sequence.
34      */

35
36     public abstract void write(Item item) throws XPathException;
37
38     /**
39     * Set the system ID
40     * @param systemId the URI used to identify the tree being passed across this interface
41     */

42
43     public void setSystemId(String JavaDoc systemId) {
44         this.systemId = systemId;
45     }
46
47     /**
48     * Get the system ID
49     * @return the system ID that was supplied using the setSystemId() method
50     */

51
52     public String JavaDoc getSystemId() {
53         return systemId;
54     }
55
56     /**
57      * Determine whether there are any open document or element nodes in the output
58      */

59
60     public boolean hasOpenNodes() {
61         return level != 0;
62     }
63
64     /**
65      * Start of a document node.
66     */

67
68     public void startDocument(int properties) throws XPathException {
69         if (tree==null) {
70             createTree();
71         }
72         if (level++ == 0) {
73             tree.startDocument(properties);
74         }
75     }
76
77     /**
78      * Create a TinyTree to hold a document or element node.
79      * @throws net.sf.saxon.trans.XPathException
80      */

81
82     private void createTree() throws XPathException {
83         builder = new TinyBuilder();
84         builder.setPipelineConfiguration(getPipelineConfiguration());
85         builder.setSizeParameters(treeSizeParameters);
86
87         NamespaceReducer reducer = new NamespaceReducer();
88         reducer.setUnderlyingReceiver(builder);
89         reducer.setPipelineConfiguration(getPipelineConfiguration());
90
91         ComplexContentOutputter complex = new ComplexContentOutputter();
92         complex.setPipelineConfiguration(getPipelineConfiguration());
93         complex.setReceiver(reducer);
94         tree = complex;
95
96         tree.setSystemId(systemId);
97         tree.setPipelineConfiguration(getPipelineConfiguration());
98         tree.open();
99     }
100
101     /**
102      * Notify the end of a document node
103      */

104
105     public void endDocument() throws XPathException {
106         if (--level == 0) {
107             tree.endDocument();
108             DocumentInfo doc = (DocumentInfo)builder.getCurrentRoot();
109             // add the constructed document to the result sequence
110
append(doc, 0, NodeInfo.ALL_NAMESPACES);
111         }
112         previousAtomic = false;
113     }
114
115     /**
116     * Output an element start tag.
117     * @param nameCode The element name code - a code held in the Name Pool
118     * @param typeCode Integer code identifying the type of this element. Zero identifies the default
119     * type, that is xs:anyType
120     * @param properties bit-significant flags indicating any special information
121     */

122
123     public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException {
124
125         if (inStartTag) {
126             startContent();
127         }
128
129         if (tree==null) {
130             createTree();
131         }
132
133         tree.startElement(nameCode, typeCode, locationId, properties);
134         level++;
135         inStartTag = true;
136         previousAtomic = false;
137     }
138
139     /**
140     * Output an element end tag.
141     */

142
143     public void endElement() throws XPathException {
144         if (inStartTag) {
145             startContent();
146         }
147         tree.endElement();
148         if (--level == 0) {
149             NodeInfo element = builder.getCurrentRoot();
150             append(element, 0, NodeInfo.ALL_NAMESPACES);
151         }
152         previousAtomic = false;
153     }
154
155     /**
156     * Output a namespace declaration. <br>
157     * This is added to a list of pending namespaces for the current start tag.
158     * If there is already another declaration of the same prefix, this one is
159     * ignored.
160     * Note that unlike SAX2 startPrefixMapping(), this call is made AFTER writing the start tag.
161     * @param nscode The namespace code
162     * @param properties Allows special properties to be passed if required
163     * @throws net.sf.saxon.trans.XPathException if there is no start tag to write to (created using writeStartTag),
164     * or if character content has been written since the start tag was written.
165     */

166
167     public void namespace(int nscode, int properties)
168     throws XPathException {
169         if (level == 0) {
170             NamePool namePool = getNamePool();
171             Orphan o = new Orphan(getConfiguration());
172             o.setNodeKind(Type.NAMESPACE);
173             o.setNameCode(namePool.allocate("", "", namePool.getPrefixFromNamespaceCode(nscode)));
174             o.setStringValue(namePool.getURIFromNamespaceCode(nscode));
175             append(o, 0, NodeInfo.ALL_NAMESPACES);
176         } else {
177             tree.namespace(nscode, properties);
178         }
179         previousAtomic = false;
180     }
181
182     /**
183     * Output an attribute value. <br>
184     * @param nameCode An integer code representing the name of the attribute, as held in the Name Pool
185     * @param typeCode Integer code identifying the type annotation of the attribute; zero represents
186     * the default type (xs:untypedAtomic)
187     * @param value The value of the attribute
188     * @param properties Bit significant flags for passing extra information to the serializer, e.g.
189     * to disable escaping
190     * @throws net.sf.saxon.trans.XPathException if there is no start tag to write to (created using writeStartTag),
191     * or if character content has been written since the start tag was written.
192     */

193
194     public void attribute(int nameCode, int typeCode, CharSequence JavaDoc value, int locationId, int properties)
195     throws XPathException {
196         if (level == 0) {
197             Orphan o = new Orphan(getConfiguration());
198             o.setNodeKind(Type.ATTRIBUTE);
199             o.setNameCode(nameCode);
200             o.setStringValue(value);
201             o.setTypeAnnotation(typeCode);
202             append(o, locationId, NodeInfo.ALL_NAMESPACES);
203         } else {
204             tree.attribute(nameCode, typeCode, value, locationId, properties);
205         }
206         previousAtomic = false;
207     }
208
209     /**
210     * The startContent() event is notified after all namespaces and attributes of an element
211     * have been notified, and before any child nodes are notified.
212     * @throws net.sf.saxon.trans.XPathException for any failure
213     */

214
215     public void startContent() throws XPathException {
216         inStartTag = false;
217         tree.startContent();
218         previousAtomic = false;
219     }
220
221     /**
222     * Produce text content output. <BR>
223     * @param s The String to be output
224     * @param properties bit-significant flags for extra information, e.g. disable-output-escaping
225     * @throws net.sf.saxon.trans.XPathException for any failure
226     */

227
228     public void characters(CharSequence JavaDoc s, int locationId, int properties) throws XPathException {
229         if (level == 0) {
230             Orphan o = new Orphan(getConfiguration());
231             o.setNodeKind(Type.TEXT);
232             o.setStringValue(s);
233             append(o, locationId, NodeInfo.ALL_NAMESPACES);
234         } else {
235             if (s.length() > 0) {
236                 if (inStartTag) {
237                     startContent();
238                 }
239                 tree.characters(s, locationId, properties);
240             }
241         }
242         previousAtomic = false;
243     }
244
245     /**
246     * Write a comment.
247     */

248
249     public void comment(CharSequence JavaDoc comment, int locationId, int properties) throws XPathException {
250         if (inStartTag) {
251             startContent();
252         }
253         if (level == 0) {
254             Orphan o = new Orphan(getConfiguration());
255             o.setNodeKind(Type.COMMENT);
256             o.setStringValue(comment);
257             append(o, locationId, NodeInfo.ALL_NAMESPACES);
258         } else {
259             tree.comment(comment, locationId, properties);
260         }
261         previousAtomic = false;
262     }
263
264     /**
265     * Write a processing instruction
266     * No-op in this implementation
267     */

268
269     public void processingInstruction(String JavaDoc target, CharSequence JavaDoc data, int locationId, int properties) throws XPathException {
270         if (inStartTag) {
271             startContent();
272         }
273         if (level == 0) {
274             Orphan o = new Orphan(getConfiguration());
275             o.setNameCode(getNamePool().allocate("", "", target));
276             o.setNodeKind(Type.PROCESSING_INSTRUCTION);
277             o.setStringValue(data);
278             append(o, locationId, NodeInfo.ALL_NAMESPACES);
279         } else {
280             tree.processingInstruction(target, data, locationId, properties);
281         }
282         previousAtomic = false;
283     }
284
285     /**
286     * Close the output
287     */

288
289     public void close() throws XPathException {
290         previousAtomic = false;
291         if (tree != null) {
292             tree.close();
293         }
294     }
295
296     /**
297     * Append an item to the sequence, performing any necessary type-checking and conversion
298     */

299
300     public void append(Item item, int locationId, int copyNamespaces) throws XPathException {
301
302         if (item==null) {
303             return;
304         }
305
306         if (level==0) {
307             write(item);
308             previousAtomic = false;
309         } else {
310             if (item instanceof AtomicValue) {
311                 // If an atomic value is written to a tree, and the previous item was also
312
// an atomic value, then add a single space to separate them
313
if (previousAtomic) {
314                     tree.characters(" ", 0, 0);
315                 }
316                 tree.characters(item.getStringValueCS(), 0, 0);
317                 previousAtomic = true;
318             } else {
319                 ((NodeInfo)item).copy(tree, NodeInfo.ALL_NAMESPACES, true, locationId);
320                 previousAtomic = false;
321             }
322         }
323     }
324 }
325
326 //
327
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
328
// you may not use this file except in compliance with the License. You may obtain a copy of the
329
// License at http://www.mozilla.org/MPL/
330
//
331
// Software distributed under the License is distributed on an "AS IS" basis,
332
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
333
// See the License for the specific language governing rights and limitations under the License.
334
//
335
// The Original Code is: all this file.
336
//
337
// The Initial Developer of the Original Code is Michael H. Kay
338
//
339
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
340
//
341
// Contributor(s): none.
342
//
Popular Tags