Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
BeanWriter |
|
| 1.7027027027027026;1.703 |
1 | /* |
|
2 | * Copyright 2001-2004 The Apache Software Foundation. |
|
3 | * |
|
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
|
5 | * you may not use this file except in compliance with the License. |
|
6 | * You may obtain a copy of the License at |
|
7 | * |
|
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
9 | * |
|
10 | * Unless required by applicable law or agreed to in writing, software |
|
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
13 | * See the License for the specific language governing permissions and |
|
14 | * limitations under the License. |
|
15 | */ |
|
16 | package org.apache.commons.betwixt.io; |
|
17 | ||
18 | import java.beans.IntrospectionException; |
|
19 | import java.io.BufferedWriter; |
|
20 | import java.io.IOException; |
|
21 | import java.io.OutputStream; |
|
22 | import java.io.OutputStreamWriter; |
|
23 | import java.io.UnsupportedEncodingException; |
|
24 | import java.io.Writer; |
|
25 | ||
26 | import org.apache.commons.betwixt.XMLUtils; |
|
27 | import org.apache.commons.betwixt.strategy.MixedContentEncodingStrategy; |
|
28 | import org.apache.commons.logging.Log; |
|
29 | import org.apache.commons.logging.LogFactory; |
|
30 | import org.xml.sax.Attributes; |
|
31 | import org.xml.sax.SAXException; |
|
32 | ||
33 | /** <p><code>BeanWriter</code> outputs beans as XML to an io stream.</p> |
|
34 | * |
|
35 | * <p>The output for each bean is an xml fragment |
|
36 | * (rather than a well-formed xml-document). |
|
37 | * This allows bean representations to be appended to a document |
|
38 | * by writing each in turn to the stream. |
|
39 | * So to create a well formed xml document, |
|
40 | * you'll need to write the prolog to the stream first. |
|
41 | * If you append more than one bean to the stream, |
|
42 | * then you'll need to add a wrapping root element as well. |
|
43 | * |
|
44 | * <p> The line ending to be used is set by {@link #setEndOfLine}. |
|
45 | * |
|
46 | * <p> The output can be formatted (with whitespace) for easy reading |
|
47 | * by calling {@link #enablePrettyPrint}. |
|
48 | * The output will be indented. |
|
49 | * The indent string used is set by {@link #setIndent}. |
|
50 | * |
|
51 | * <p> Bean graphs can sometimes contain cycles. |
|
52 | * Care must be taken when serializing cyclic bean graphs |
|
53 | * since this can lead to infinite recursion. |
|
54 | * The approach taken by <code>BeanWriter</code> is to automatically |
|
55 | * assign an <code>ID</code> attribute value to beans. |
|
56 | * When a cycle is encountered, |
|
57 | * an element is written that has the <code>IDREF</code> attribute set to the |
|
58 | * id assigned earlier. |
|
59 | * |
|
60 | * <p> The names of the <code>ID</code> and <code>IDREF</code> attributes used |
|
61 | * can be customized by the <code>XMLBeanInfo</code>. |
|
62 | * The id's used can also be customized by the user |
|
63 | * via <code>IDGenerator</code> subclasses. |
|
64 | * The implementation used can be set by the <code>IdGenerator</code> property. |
|
65 | * BeanWriter defaults to using <code>SequentialIDGenerator</code> |
|
66 | * which supplies id values in numeric sequence. |
|
67 | * |
|
68 | * <p>If generated <code>ID</code> attribute values are not acceptable in the output, |
|
69 | * then this can be disabled by setting the <code>WriteIDs</code> property to false. |
|
70 | * If a cyclic reference is encountered in this case then a |
|
71 | * <code>CyclicReferenceException</code> will be thrown. |
|
72 | * When the <code>WriteIDs</code> property is set to false, |
|
73 | * it is recommended that this exception is caught by the caller. |
|
74 | * |
|
75 | * |
|
76 | * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> |
|
77 | * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a> |
|
78 | */ |
|
79 | 695 | public class BeanWriter extends AbstractBeanWriter { |
80 | ||
81 | /** |
|
82 | * Gets the default EOL string. |
|
83 | * @return EOL string, not null |
|
84 | */ |
|
85 | private static final String getEOL() { |
|
86 | // just wraps call in an exception check for access restricted environments |
|
87 | 695 | String result = "\n"; |
88 | try { |
|
89 | 695 | result = System.getProperty( "line.separator", "\n" ); |
90 | 0 | } catch (SecurityException se) { |
91 | 0 | Log log = LogFactory.getLog( BeanWriter.class ); |
92 | 0 | log.warn("Cannot load line separator property: " + se.getMessage()); |
93 | 0 | log.trace("Caused by: ", se); |
94 | } |
|
95 | 695 | return result; |
96 | } |
|
97 | ||
98 | ||
99 | /** Where the output goes */ |
|
100 | private Writer writer; |
|
101 | /** text used for end of lines. Defaults to <code>\n</code>*/ |
|
102 | 695 | private static final String EOL = getEOL(); |
103 | /** text used for end of lines. Defaults to <code>\n</code>*/ |
|
104 | 1943 | private String endOfLine = EOL; |
105 | /** Initial level of indentation (starts at 1 with the first element by default) */ |
|
106 | 1943 | private int initialIndentLevel = 1; |
107 | /** indentation text */ |
|
108 | private String indent; |
|
109 | ||
110 | /** should we flush after writing bean */ |
|
111 | private boolean autoFlush; |
|
112 | /** Log used for logging (Doh!) */ |
|
113 | 1943 | private Log log = LogFactory.getLog( BeanWriter.class ); |
114 | /** Has any content (excluding attributes) been written to the current element */ |
|
115 | 1943 | private boolean currentElementIsEmpty = false; |
116 | /** Has the current element written any body text */ |
|
117 | 1943 | private boolean currentElementHasBodyText = false; |
118 | /** Has the last start tag been closed */ |
|
119 | 1943 | private boolean closedStartTag = true; |
120 | /** Should an end tag be added for empty elements? */ |
|
121 | 1943 | private boolean addEndTagForEmptyElement = false; |
122 | /** Current level of indentation */ |
|
123 | private int indentLevel; |
|
124 | /** USed to determine how body content should be encoded before being output*/ |
|
125 | 1943 | private MixedContentEncodingStrategy mixedContentEncodingStrategy |
126 | 1943 | = MixedContentEncodingStrategy.DEFAULT; |
127 | ||
128 | /** |
|
129 | * <p> Constructor uses <code>System.out</code> for output.</p> |
|
130 | */ |
|
131 | public BeanWriter() { |
|
132 | 39 | this( System.out ); |
133 | 39 | } |
134 | ||
135 | /** |
|
136 | * <p> Constuctor uses given <code>OutputStream</code> for output.</p> |
|
137 | * |
|
138 | * @param out write out representations to this stream |
|
139 | */ |
|
140 | 52 | public BeanWriter(OutputStream out) { |
141 | 52 | this.writer = new BufferedWriter( new OutputStreamWriter( out ) ); |
142 | 52 | this.autoFlush = true; |
143 | 52 | } |
144 | ||
145 | /** |
|
146 | * <p>Constuctor uses given <code>OutputStream</code> for output |
|
147 | * and allows encoding to be set.</p> |
|
148 | * |
|
149 | * @param out write out representations to this stream |
|
150 | * @param enc the name of the encoding to be used. This should be compatible |
|
151 | * with the encoding types described in <code>java.io</code> |
|
152 | * @throws UnsupportedEncodingException if the given encoding is not supported |
|
153 | */ |
|
154 | 0 | public BeanWriter(OutputStream out, String enc) throws UnsupportedEncodingException { |
155 | 0 | this.writer = new BufferedWriter( new OutputStreamWriter( out, enc ) ); |
156 | 0 | this.autoFlush = true; |
157 | 0 | } |
158 | ||
159 | /** |
|
160 | * <p> Constructor sets writer used for output.</p> |
|
161 | * |
|
162 | * @param writer write out representations to this writer |
|
163 | */ |
|
164 | 1891 | public BeanWriter(Writer writer) { |
165 | 1891 | this.writer = writer; |
166 | 1891 | } |
167 | ||
168 | /** |
|
169 | * A helper method that allows you to write the XML Declaration. |
|
170 | * This should only be called once before you output any beans. |
|
171 | * |
|
172 | * @param xmlDeclaration is the XML declaration string typically of |
|
173 | * the form "<xml version='1.0' encoding='UTF-8' ?> |
|
174 | * |
|
175 | * @throws IOException when declaration cannot be written |
|
176 | */ |
|
177 | public void writeXmlDeclaration(String xmlDeclaration) throws IOException { |
|
178 | 52 | writer.write( xmlDeclaration ); |
179 | 52 | printLine(); |
180 | 52 | } |
181 | ||
182 | /** |
|
183 | * Allows output to be flushed on the underlying output stream |
|
184 | * |
|
185 | * @throws IOException when the flush cannot be completed |
|
186 | */ |
|
187 | public void flush() throws IOException { |
|
188 | 130 | writer.flush(); |
189 | 130 | } |
190 | ||
191 | /** |
|
192 | * Closes the underlying output stream |
|
193 | * |
|
194 | * @throws IOException when writer cannot be closed |
|
195 | */ |
|
196 | public void close() throws IOException { |
|
197 | 0 | writer.close(); |
198 | 0 | } |
199 | ||
200 | /** |
|
201 | * Write the given object to the stream (and then flush). |
|
202 | * |
|
203 | * @param bean write this <code>Object</code> to the stream |
|
204 | * @throws IOException if an IO problem causes failure |
|
205 | * @throws SAXException if a SAX problem causes failure |
|
206 | * @throws IntrospectionException if bean cannot be introspected |
|
207 | */ |
|
208 | public void write(Object bean) throws IOException, SAXException, IntrospectionException { |
|
209 | ||
210 | 1722 | super.write(bean); |
211 | ||
212 | 1696 | if ( autoFlush ) { |
213 | 104 | writer.flush(); |
214 | } |
|
215 | 1696 | } |
216 | ||
217 | ||
218 | /** |
|
219 | * <p> Switch on formatted output. |
|
220 | * This sets the end of line and the indent. |
|
221 | * The default is adding 2 spaces and a newline |
|
222 | */ |
|
223 | public void enablePrettyPrint() { |
|
224 | 507 | endOfLine = EOL; |
225 | 507 | indent = " "; |
226 | 507 | } |
227 | ||
228 | /** |
|
229 | * Gets the string used to mark end of lines. |
|
230 | * |
|
231 | * @return the string used for end of lines |
|
232 | */ |
|
233 | public String getEndOfLine() { |
|
234 | 26 | return endOfLine; |
235 | } |
|
236 | ||
237 | /** |
|
238 | * Sets the string used for end of lines |
|
239 | * Produces a warning the specified value contains an invalid whitespace character |
|
240 | * |
|
241 | * @param endOfLine the <code>String</code to use |
|
242 | */ |
|
243 | public void setEndOfLine(String endOfLine) { |
|
244 | 702 | this.endOfLine = endOfLine; |
245 | 1391 | for (int i = 0; i < endOfLine.length(); i++) { |
246 | 715 | if (!Character.isWhitespace(endOfLine.charAt(i))) { |
247 | 26 | log.warn("Invalid EndOfLine character(s)"); |
248 | 26 | break; |
249 | } |
|
250 | } |
|
251 | ||
252 | 702 | } |
253 | ||
254 | /** |
|
255 | * Gets the initial indent level |
|
256 | * |
|
257 | * @return the initial level for indentation |
|
258 | */ |
|
259 | public int getInitialIndentLevel() { |
|
260 | 0 | return initialIndentLevel; |
261 | } |
|
262 | ||
263 | /** |
|
264 | * Sets the initial indent level used for pretty print indents |
|
265 | * @param initialIndentLevel use this <code>int</code> to start with |
|
266 | */ |
|
267 | public void setInitialIndentLevel(int initialIndentLevel) { |
|
268 | 0 | this.initialIndentLevel = initialIndentLevel; |
269 | 0 | } |
270 | ||
271 | ||
272 | /** |
|
273 | * Gets the indent string |
|
274 | * |
|
275 | * @return the string used for indentation |
|
276 | */ |
|
277 | public String getIndent() { |
|
278 | 27820 | return indent; |
279 | } |
|
280 | ||
281 | /** |
|
282 | * Sets the string used for pretty print indents |
|
283 | * @param indent use this <code>string</code> for indents |
|
284 | */ |
|
285 | public void setIndent(String indent) { |
|
286 | 65 | this.indent = indent; |
287 | 65 | } |
288 | ||
289 | /** |
|
290 | * <p> Set the log implementation used. </p> |
|
291 | * |
|
292 | * @return a <code>org.apache.commons.logging.Log</code> level constant |
|
293 | */ |
|
294 | public Log getLog() { |
|
295 | 0 | return log; |
296 | } |
|
297 | ||
298 | /** |
|
299 | * <p> Set the log implementation used. </p> |
|
300 | * |
|
301 | * @param log <code>Log</code> implementation to use |
|
302 | */ |
|
303 | public void setLog( Log log ) { |
|
304 | 13 | this.log = log; |
305 | 13 | } |
306 | ||
307 | /** |
|
308 | * Gets the encoding strategy for mixed content. |
|
309 | * This is used to process body content |
|
310 | * before it is written to the textual output. |
|
311 | * @return the <code>MixedContentEncodingStrategy</code>, not null |
|
312 | * @since 0.5 |
|
313 | */ |
|
314 | public MixedContentEncodingStrategy getMixedContentEncodingStrategy() { |
|
315 | 0 | return mixedContentEncodingStrategy; |
316 | } |
|
317 | ||
318 | /** |
|
319 | * Sets the encoding strategy for mixed content. |
|
320 | * This is used to process body content |
|
321 | * before it is written to the textual output. |
|
322 | * @param strategy the <code>MixedContentEncodingStrategy</code> |
|
323 | * used to process body content, not null |
|
324 | * @since 0.5 |
|
325 | */ |
|
326 | public void setMixedContentEncodingStrategy(MixedContentEncodingStrategy strategy) { |
|
327 | 26 | mixedContentEncodingStrategy = strategy; |
328 | 26 | } |
329 | ||
330 | /** |
|
331 | * <p>Should an end tag be added for each empty element? |
|
332 | * </p><p> |
|
333 | * When this property is false then empty elements will |
|
334 | * be written as <code><<em>element-name</em>/gt;</code>. |
|
335 | * When this property is true then empty elements will |
|
336 | * be written as <code><<em>element-name</em>gt; |
|
337 | * </<em>element-name</em>gt;</code>. |
|
338 | * </p> |
|
339 | * @return true if an end tag should be added |
|
340 | */ |
|
341 | public boolean isEndTagForEmptyElement() { |
|
342 | 0 | return addEndTagForEmptyElement; |
343 | } |
|
344 | ||
345 | /** |
|
346 | * Sets when an an end tag be added for each empty element. |
|
347 | * When this property is false then empty elements will |
|
348 | * be written as <code><<em>element-name</em>/gt;</code>. |
|
349 | * When this property is true then empty elements will |
|
350 | * be written as <code><<em>element-name</em>gt; |
|
351 | * </<em>element-name</em>gt;</code>. |
|
352 | * @param addEndTagForEmptyElement true if an end tag should be |
|
353 | * written for each empty element, false otherwise |
|
354 | */ |
|
355 | public void setEndTagForEmptyElement(boolean addEndTagForEmptyElement) { |
|
356 | 39 | this.addEndTagForEmptyElement = addEndTagForEmptyElement; |
357 | 39 | } |
358 | ||
359 | ||
360 | ||
361 | // New API |
|
362 | //------------------------------------------------------------------------------ |
|
363 | ||
364 | ||
365 | /** |
|
366 | * Writes the start tag for an element. |
|
367 | * |
|
368 | * @param uri the element's namespace uri |
|
369 | * @param localName the element's local name |
|
370 | * @param qualifiedName the element's qualified name |
|
371 | * @param attr the element's attributes |
|
372 | * @throws IOException if an IO problem occurs during writing |
|
373 | * @throws SAXException if an SAX problem occurs during writing |
|
374 | * @since 0.5 |
|
375 | */ |
|
376 | protected void startElement( |
|
377 | WriteContext context, |
|
378 | String uri, |
|
379 | String localName, |
|
380 | String qualifiedName, |
|
381 | Attributes attr) |
|
382 | throws |
|
383 | IOException, |
|
384 | SAXException { |
|
385 | 17217 | if ( !closedStartTag ) { |
386 | 6350 | writer.write( '>' ); |
387 | 6350 | printLine(); |
388 | } |
|
389 | ||
390 | 17217 | indentLevel++; |
391 | ||
392 | 17217 | indent(); |
393 | 17217 | writer.write( '<' ); |
394 | 17217 | writer.write( qualifiedName ); |
395 | ||
396 | 25368 | for ( int i=0; i< attr.getLength(); i++ ) { |
397 | 8151 | writer.write( ' ' ); |
398 | 8151 | writer.write( attr.getQName(i) ); |
399 | 8151 | writer.write( "=\"" ); |
400 | 8151 | writer.write( XMLUtils.escapeAttributeValue( attr.getValue(i) ) ); |
401 | 8151 | writer.write( '\"' ); |
402 | } |
|
403 | 17217 | closedStartTag = false; |
404 | 17217 | currentElementIsEmpty = true; |
405 | 17217 | currentElementHasBodyText = false; |
406 | 17217 | } |
407 | ||
408 | /** |
|
409 | * Writes the end tag for an element |
|
410 | * |
|
411 | * @param uri the element's namespace uri |
|
412 | * @param localName the element's local name |
|
413 | * @param qualifiedName the element's qualified name |
|
414 | * |
|
415 | * @throws IOException if an IO problem occurs during writing |
|
416 | * @throws SAXException if an SAX problem occurs during writing |
|
417 | * @since 0.5 |
|
418 | */ |
|
419 | protected void endElement( |
|
420 | WriteContext context, |
|
421 | String uri, |
|
422 | String localName, |
|
423 | String qualifiedName) |
|
424 | throws |
|
425 | IOException, |
|
426 | SAXException { |
|
427 | if ( |
|
428 | 17035 | !addEndTagForEmptyElement |
429 | 17009 | && !closedStartTag |
430 | 3886 | && currentElementIsEmpty ) { |
431 | ||
432 | 3886 | writer.write( "/>" ); |
433 | 3886 | closedStartTag = true; |
434 | ||
435 | } else { |
|
436 | ||
437 | if ( |
|
438 | 13149 | addEndTagForEmptyElement |
439 | 26 | && !closedStartTag ) { |
440 | 26 | writer.write( ">" ); |
441 | 26 | closedStartTag = true; |
442 | } |
|
443 | 13123 | else if (!currentElementHasBodyText) { |
444 | 6194 | indent(); |
445 | } |
|
446 | 13149 | writer.write( "</" ); |
447 | 13149 | writer.write( qualifiedName ); |
448 | 13149 | writer.write( '>' ); |
449 | ||
450 | } |
|
451 | ||
452 | 17035 | indentLevel--; |
453 | 17035 | printLine(); |
454 | ||
455 | 17035 | currentElementHasBodyText = false; |
456 | 17035 | } |
457 | ||
458 | /** |
|
459 | * Write element body text |
|
460 | * |
|
461 | * @param text write out this body text |
|
462 | * @throws IOException when the stream write fails |
|
463 | * @since 0.5 |
|
464 | */ |
|
465 | protected void bodyText(WriteContext context, String text) throws IOException { |
|
466 | 6942 | if ( text == null ) { |
467 | // XXX This is probably a programming error |
|
468 | 0 | log.error( "[expressBodyText]Body text is null" ); |
469 | ||
470 | } else { |
|
471 | 6942 | if ( !closedStartTag ) { |
472 | 6929 | writer.write( '>' ); |
473 | 6929 | closedStartTag = true; |
474 | } |
|
475 | 13884 | writer.write( |
476 | 13884 | mixedContentEncodingStrategy.encode( |
477 | 6942 | text, |
478 | 6942 | context.getCurrentDescriptor()) ); |
479 | 6942 | currentElementIsEmpty = false; |
480 | 6942 | currentElementHasBodyText = true; |
481 | } |
|
482 | 6942 | } |
483 | ||
484 | /** Writes out an empty line. |
|
485 | * Uses current <code>endOfLine</code>. |
|
486 | * |
|
487 | * @throws IOException when stream write fails |
|
488 | */ |
|
489 | private void printLine() throws IOException { |
|
490 | 23437 | if ( endOfLine != null ) { |
491 | 23437 | writer.write( endOfLine ); |
492 | } |
|
493 | 23437 | } |
494 | ||
495 | /** |
|
496 | * Writes out <code>indent</code>'s to the current <code>indentLevel</code> |
|
497 | * |
|
498 | * @throws IOException when stream write fails |
|
499 | */ |
|
500 | private void indent() throws IOException { |
|
501 | 23411 | if ( indent != null ) { |
502 | 37076 | for ( int i = 1 - initialIndentLevel; i < indentLevel; i++ ) { |
503 | 27820 | writer.write( getIndent() ); |
504 | } |
|
505 | } |
|
506 | 23411 | } |
507 | ||
508 | // OLD API (DEPRECATED) |
|
509 | //---------------------------------------------------------------------------- |
|
510 | ||
511 | ||
512 | /** Writes out an empty line. |
|
513 | * Uses current <code>endOfLine</code>. |
|
514 | * |
|
515 | * @throws IOException when stream write fails |
|
516 | * @deprecated 0.5 replaced by new SAX inspired API |
|
517 | */ |
|
518 | protected void writePrintln() throws IOException { |
|
519 | 0 | if ( endOfLine != null ) { |
520 | 0 | writer.write( endOfLine ); |
521 | } |
|
522 | 0 | } |
523 | ||
524 | /** |
|
525 | * Writes out <code>indent</code>'s to the current <code>indentLevel</code> |
|
526 | * |
|
527 | * @throws IOException when stream write fails |
|
528 | * @deprecated 0.5 replaced by new SAX inspired API |
|
529 | */ |
|
530 | protected void writeIndent() throws IOException { |
|
531 | 0 | if ( indent != null ) { |
532 | 0 | for ( int i = 0; i < indentLevel; i++ ) { |
533 | 0 | writer.write( getIndent() ); |
534 | } |
|
535 | } |
|
536 | 0 | } |
537 | ||
538 | /** |
|
539 | * <p>Escape the <code>toString</code> of the given object. |
|
540 | * For use as body text.</p> |
|
541 | * |
|
542 | * @param value escape <code>value.toString()</code> |
|
543 | * @return text with escaped delimiters |
|
544 | * @deprecated 0.5 moved into utility class {@link XMLUtils#escapeBodyValue} |
|
545 | */ |
|
546 | protected String escapeBodyValue(Object value) { |
|
547 | 0 | return XMLUtils.escapeBodyValue(value); |
548 | } |
|
549 | ||
550 | /** |
|
551 | * <p>Escape the <code>toString</code> of the given object. |
|
552 | * For use in an attribute value.</p> |
|
553 | * |
|
554 | * @param value escape <code>value.toString()</code> |
|
555 | * @return text with characters restricted (for use in attributes) escaped |
|
556 | * |
|
557 | * @deprecated 0.5 moved into utility class {@link XMLUtils#escapeAttributeValue} |
|
558 | */ |
|
559 | protected String escapeAttributeValue(Object value) { |
|
560 | 0 | return XMLUtils.escapeAttributeValue(value); |
561 | } |
|
562 | ||
563 | /** |
|
564 | * Express an element tag start using given qualified name |
|
565 | * |
|
566 | * @param qualifiedName the fully qualified name of the element to write |
|
567 | * @throws IOException when stream write fails |
|
568 | * @deprecated 0.5 replaced by new SAX inspired API |
|
569 | */ |
|
570 | protected void expressElementStart(String qualifiedName) throws IOException { |
|
571 | 0 | if ( qualifiedName == null ) { |
572 | // XXX this indicates a programming error |
|
573 | 0 | log.fatal( "[expressElementStart]Qualified name is null." ); |
574 | 0 | throw new RuntimeException( "Qualified name is null." ); |
575 | } |
|
576 | ||
577 | 0 | writePrintln(); |
578 | 0 | writeIndent(); |
579 | 0 | writer.write( '<' ); |
580 | 0 | writer.write( qualifiedName ); |
581 | 0 | } |
582 | ||
583 | /** |
|
584 | * Write a tag close to the stream |
|
585 | * |
|
586 | * @throws IOException when stream write fails |
|
587 | * @deprecated 0.5 replaced by new SAX inspired API |
|
588 | */ |
|
589 | protected void expressTagClose() throws IOException { |
|
590 | 0 | writer.write( '>' ); |
591 | 0 | } |
592 | ||
593 | /** |
|
594 | * Write an element end tag to the stream |
|
595 | * |
|
596 | * @param qualifiedName the name of the element |
|
597 | * @throws IOException when stream write fails |
|
598 | * @deprecated 0.5 replaced by new SAX inspired API |
|
599 | */ |
|
600 | protected void expressElementEnd(String qualifiedName) throws IOException { |
|
601 | 0 | if (qualifiedName == null) { |
602 | // XXX this indicates a programming error |
|
603 | 0 | log.fatal( "[expressElementEnd]Qualified name is null." ); |
604 | 0 | throw new RuntimeException( "Qualified name is null." ); |
605 | } |
|
606 | ||
607 | 0 | writer.write( "</" ); |
608 | 0 | writer.write( qualifiedName ); |
609 | 0 | writer.write( '>' ); |
610 | 0 | } |
611 | ||
612 | /** |
|
613 | * Write an empty element end to the stream |
|
614 | * |
|
615 | * @throws IOException when stream write fails |
|
616 | * @deprecated 0.5 replaced by new SAX inspired API |
|
617 | */ |
|
618 | protected void expressElementEnd() throws IOException { |
|
619 | 0 | writer.write( "/>" ); |
620 | 0 | } |
621 | ||
622 | /** |
|
623 | * Write element body text |
|
624 | * |
|
625 | * @param text write out this body text |
|
626 | * @throws IOException when the stream write fails |
|
627 | * @deprecated 0.5 replaced by new SAX inspired API |
|
628 | */ |
|
629 | protected void expressBodyText(String text) throws IOException { |
|
630 | 0 | if ( text == null ) { |
631 | // XXX This is probably a programming error |
|
632 | 0 | log.error( "[expressBodyText]Body text is null" ); |
633 | ||
634 | } else { |
|
635 | 0 | writer.write( XMLUtils.escapeBodyValue(text) ); |
636 | } |
|
637 | 0 | } |
638 | ||
639 | /** |
|
640 | * Writes an attribute to the stream. |
|
641 | * |
|
642 | * @param qualifiedName fully qualified attribute name |
|
643 | * @param value attribute value |
|
644 | * @throws IOException when the stream write fails |
|
645 | * @deprecated 0.5 replaced by new SAX inspired API |
|
646 | */ |
|
647 | protected void expressAttribute( |
|
648 | String qualifiedName, |
|
649 | String value) |
|
650 | throws |
|
651 | IOException{ |
|
652 | 0 | if ( value == null ) { |
653 | // XXX probably a programming error |
|
654 | 0 | log.error( "Null attribute value." ); |
655 | 0 | return; |
656 | } |
|
657 | ||
658 | 0 | if ( qualifiedName == null ) { |
659 | // XXX probably a programming error |
|
660 | 0 | log.error( "Null attribute value." ); |
661 | 0 | return; |
662 | } |
|
663 | ||
664 | 0 | writer.write( ' ' ); |
665 | 0 | writer.write( qualifiedName ); |
666 | 0 | writer.write( "=\"" ); |
667 | 0 | writer.write( XMLUtils.escapeAttributeValue(value) ); |
668 | 0 | writer.write( '\"' ); |
669 | 0 | } |
670 | ||
671 | ||
672 | } |