KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xml > internal > serialize > IndentPrinter


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58
59 package com.sun.org.apache.xml.internal.serialize;
60
61
62 import java.io.Writer JavaDoc;
63 import java.io.StringWriter JavaDoc;
64 import java.io.IOException JavaDoc;
65
66
67 /**
68  * Extends {@link Printer} and adds support for indentation and line
69  * wrapping.
70  *
71  * @version $Revision: 1.8 $ $Date: 2003/01/13 15:59:09 $
72  * @author <a HREF="mailto:arkin@intalio.com">Assaf Arkin</a>
73  */

74 public class IndentPrinter
75     extends Printer
76 {
77
78
79     /**
80      * Holds the currently accumulating text line. This buffer will constantly
81      * be reused by deleting its contents instead of reallocating it.
82      */

83     private StringBuffer JavaDoc _line;
84
85
86     /**
87      * Holds the currently accumulating text that follows {@link #_line}.
88      * When the end of the part is identified by a call to {@link #printSpace}
89      * or {@link #breakLine}, this part is added to the accumulated line.
90      */

91     private StringBuffer JavaDoc _text;
92
93
94     /**
95      * Counts how many white spaces come between the accumulated line and the
96      * current accumulated text. Multiple spaces at the end of the a line
97      * will not be printed.
98      */

99     private int _spaces;
100
101
102     /**
103      * Holds the indentation for the current line that is now accumulating in
104      * memory and will be sent for printing shortly.
105      */

106     private int _thisIndent;
107     
108     
109     /**
110      * Holds the indentation for the next line to be printed. After this line is
111      * printed, {@link #_nextIndent} is assigned to {@link #_thisIndent}.
112      */

113     private int _nextIndent;
114
115
116     public IndentPrinter( Writer JavaDoc writer, OutputFormat format)
117     {
118         super( writer, format );
119         // Initialize everything for a first/second run.
120
_line = new StringBuffer JavaDoc( 80 );
121         _text = new StringBuffer JavaDoc( 20 );
122         _spaces = 0;
123         _thisIndent = _nextIndent = 0;
124     }
125
126
127     /**
128      * Called by any of the DTD handlers to enter DTD mode.
129      * Once entered, all output will be accumulated in a string
130      * that can be printed as part of the document's DTD.
131      * This method may be called any number of time but will only
132      * have affect the first time it's called. To exist DTD state
133      * and get the accumulated DTD, call {@link #leaveDTD}.
134      */

135     public void enterDTD()
136     {
137         // Can only enter DTD state once. Once we're out of DTD
138
// state, can no longer re-enter it.
139
if ( _dtdWriter == null ) {
140             _line.append( _text );
141             _text = new StringBuffer JavaDoc( 20 );
142             flushLine( false );
143             _dtdWriter = new StringWriter JavaDoc();
144             _docWriter = _writer;
145             _writer = _dtdWriter;
146         }
147     }
148     
149     
150     /**
151      * Called by the root element to leave DTD mode and if any
152      * DTD parts were printer, will return a string with their
153      * textual content.
154      */

155     public String JavaDoc leaveDTD()
156     {
157         // Only works if we're going out of DTD mode.
158
if ( _writer == _dtdWriter ) {
159             _line.append( _text );
160             _text = new StringBuffer JavaDoc( 20 );
161             flushLine( false );
162             _writer = _docWriter;
163             return _dtdWriter.toString();
164         } else
165             return null;
166     }
167     
168     
169     /**
170      * Called to print additional text. Each time this method is called
171      * it accumulates more text. When a space is printed ({@link
172      * #printSpace}) all the accumulated text becomes one part and is
173      * added to the accumulate line. When a line is long enough, it can
174      * be broken at its text boundary.
175      *
176      * @param text The text to print
177      */

178     public void printText( String JavaDoc text )
179     {
180         _text.append( text );
181     }
182     
183     
184     public void printText( StringBuffer JavaDoc text )
185     {
186         _text.append( text.toString() );
187     }
188
189
190     public void printText( char ch )
191     {
192         _text.append( ch );
193     }
194
195
196     public void printText( char[] chars, int start, int length )
197     {
198         _text.append( chars, start, length );
199     }
200     
201
202     /**
203      * Called to print a single space between text parts that may be
204      * broken into separate lines. Must not be called to print a space
205      * when preserving spaces. The text accumulated so far with {@link
206      * #printText} will be added to the accumulated line, and a space
207      * separator will be counted. If the line accumulated so far is
208      * long enough, it will be printed.
209      */

210     public void printSpace()
211     {
212         // The line consists of the text accumulated in _line,
213
// followed by one or more spaces as counted by _spaces,
214
// followed by more space accumulated in _text:
215
// - Text is printed and accumulated into _text.
216
// - A space is printed, so _text is added to _line and
217
// a space is counted.
218
// - More text is printed and accumulated into _text.
219
// - A space is printed, the previous spaces are added
220
// to _line, the _text is added to _line, and a new
221
// space is counted.
222

223         // If text was accumulated with printText(), then the space
224
// means we have to move that text into the line and
225
// start accumulating new text with printText().
226
if ( _text.length() > 0 ) {
227             // If the text breaks a line bounary, wrap to the next line.
228
// The printed line size consists of the indentation we're going
229
// to use next, the accumulated line so far, some spaces and the
230
// accumulated text so far.
231
if ( _format.getLineWidth() > 0 &&
232                  _thisIndent + _line.length() + _spaces + _text.length() > _format.getLineWidth() ) {
233                 flushLine( false );
234                 try {
235                     // Print line and new line, then zero the line contents.
236
_writer.write( _format.getLineSeparator() );
237                 } catch ( IOException JavaDoc except ) {
238                     // We don't throw an exception, but hold it
239
// until the end of the document.
240
if ( _exception == null )
241                         _exception = except;
242                 }
243             }
244             
245             // Add as many spaces as we accumulaed before.
246
// At the end of this loop, _spaces is zero.
247
while ( _spaces > 0 ) {
248                 _line.append( ' ' );
249                 --_spaces;
250             }
251             _line.append( _text );
252             _text = new StringBuffer JavaDoc( 20 );
253         }
254         // Starting a new word: accumulate the text between the line
255
// and this new word; not a new word: just add another space.
256
++_spaces;
257     }
258
259
260     /**
261      * Called to print a line consisting of the text accumulated so
262      * far. This is equivalent to calling {@link #printSpace} but
263      * forcing the line to print and starting a new line ({@link
264      * #printSpace} will only start a new line if the current line
265      * is long enough).
266      */

267     public void breakLine()
268     {
269         breakLine( false );
270     }
271
272
273     public void breakLine( boolean preserveSpace )
274     {
275         // Equivalent to calling printSpace and forcing a flushLine.
276
if ( _text.length() > 0 ) {
277             while ( _spaces > 0 ) {
278                 _line.append( ' ' );
279                 --_spaces;
280             }
281             _line.append( _text );
282             _text = new StringBuffer JavaDoc( 20 );
283         }
284         flushLine( preserveSpace );
285         try {
286             // Print line and new line, then zero the line contents.
287
_writer.write( _format.getLineSeparator() );
288         } catch ( IOException JavaDoc except ) {
289             // We don't throw an exception, but hold it
290
// until the end of the document.
291
if ( _exception == null )
292                 _exception = except;
293         }
294     }
295     
296
297     /**
298      * Flushes the line accumulated so far to the writer and get ready
299      * to accumulate the next line. This method is called by {@link
300      * #printText} and {@link #printSpace} when the accumulated line plus
301      * accumulated text are two long to fit on a given line. At the end of
302      * this method _line is empty and _spaces is zero.
303      */

304     public void flushLine( boolean preserveSpace )
305     {
306         int indent;
307         
308         if ( _line.length() > 0 ) {
309             try {
310                 
311                 if ( _format.getIndenting() && ! preserveSpace ) {
312                     // Make sure the indentation does not blow us away.
313
indent = _thisIndent;
314                     if ( ( 2 * indent ) > _format.getLineWidth() && _format.getLineWidth() > 0 )
315                         indent = _format.getLineWidth() / 2;
316                     // Print the indentation as spaces and set the current
317
// indentation to the next expected indentation.
318
while ( indent > 0 ) {
319                         _writer.write( ' ' );
320                         --indent;
321                     }
322                 }
323                 _thisIndent = _nextIndent;
324                 
325                 // There is no need to print the spaces at the end of the line,
326
// they are simply stripped and replaced with a single line
327
// separator.
328
_spaces = 0;
329                 _writer.write( _line.toString() );
330                 
331                 _line = new StringBuffer JavaDoc( 40 );
332             } catch ( IOException JavaDoc except ) {
333                 // We don't throw an exception, but hold it
334
// until the end of the document.
335
if ( _exception == null )
336                     _exception = except;
337             }
338         }
339     }
340     
341     
342     /**
343      * Flush the output stream. Must be called when done printing
344      * the document, otherwise some text might be buffered.
345      */

346     public void flush()
347     {
348         if ( _line.length() > 0 || _text.length() > 0 )
349             breakLine();
350         try {
351             _writer.flush();
352         } catch ( IOException JavaDoc except ) {
353             // We don't throw an exception, but hold it
354
// until the end of the document.
355
if ( _exception == null )
356                 _exception = except;
357         }
358     }
359
360
361     /**
362      * Increment the indentation for the next line.
363      */

364     public void indent()
365     {
366         _nextIndent += _format.getIndent();
367     }
368
369
370     /**
371      * Decrement the indentation for the next line.
372      */

373     public void unindent()
374     {
375         _nextIndent -= _format.getIndent();
376         if ( _nextIndent < 0 )
377             _nextIndent = 0;
378         // If there is no current line and we're de-identing then
379
// this indentation level is actually the next level.
380
if ( ( _line.length() + _spaces + _text.length() ) == 0 )
381             _thisIndent = _nextIndent;
382     }
383
384
385     public int getNextIndent()
386     {
387         return _nextIndent;
388     }
389
390
391     public void setNextIndent( int indent )
392     {
393         _nextIndent = indent;
394     }
395
396
397     public void setThisIndent( int indent )
398     {
399         _thisIndent = indent;
400     }
401
402
403 }
404
Popular Tags