KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xml > serialize > IndentPrinter


1 /*
2  * Copyright 1999-2002,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
17
18 package org.apache.xml.serialize;
19
20
21 import java.io.Writer JavaDoc;
22 import java.io.StringWriter JavaDoc;
23 import java.io.IOException JavaDoc;
24
25
26 /**
27  * Extends {@link Printer} and adds support for indentation and line
28  * wrapping.
29  *
30  * @version $Revision: 1.9 $ $Date: 2004/02/24 23:34:03 $
31  * @author <a HREF="mailto:arkin@intalio.com">Assaf Arkin</a>
32  */

33 public class IndentPrinter
34     extends Printer
35 {
36
37
38     /**
39      * Holds the currently accumulating text line. This buffer will constantly
40      * be reused by deleting its contents instead of reallocating it.
41      */

42     private StringBuffer JavaDoc _line;
43
44
45     /**
46      * Holds the currently accumulating text that follows {@link #_line}.
47      * When the end of the part is identified by a call to {@link #printSpace}
48      * or {@link #breakLine}, this part is added to the accumulated line.
49      */

50     private StringBuffer JavaDoc _text;
51
52
53     /**
54      * Counts how many white spaces come between the accumulated line and the
55      * current accumulated text. Multiple spaces at the end of the a line
56      * will not be printed.
57      */

58     private int _spaces;
59
60
61     /**
62      * Holds the indentation for the current line that is now accumulating in
63      * memory and will be sent for printing shortly.
64      */

65     private int _thisIndent;
66     
67     
68     /**
69      * Holds the indentation for the next line to be printed. After this line is
70      * printed, {@link #_nextIndent} is assigned to {@link #_thisIndent}.
71      */

72     private int _nextIndent;
73
74
75     public IndentPrinter( Writer JavaDoc writer, OutputFormat format)
76     {
77         super( writer, format );
78         // Initialize everything for a first/second run.
79
_line = new StringBuffer JavaDoc( 80 );
80         _text = new StringBuffer JavaDoc( 20 );
81         _spaces = 0;
82         _thisIndent = _nextIndent = 0;
83     }
84
85
86     /**
87      * Called by any of the DTD handlers to enter DTD mode.
88      * Once entered, all output will be accumulated in a string
89      * that can be printed as part of the document's DTD.
90      * This method may be called any number of time but will only
91      * have affect the first time it's called. To exist DTD state
92      * and get the accumulated DTD, call {@link #leaveDTD}.
93      */

94     public void enterDTD()
95     {
96         // Can only enter DTD state once. Once we're out of DTD
97
// state, can no longer re-enter it.
98
if ( _dtdWriter == null ) {
99             _line.append( _text );
100             _text = new StringBuffer JavaDoc( 20 );
101             flushLine( false );
102             _dtdWriter = new StringWriter JavaDoc();
103             _docWriter = _writer;
104             _writer = _dtdWriter;
105         }
106     }
107     
108     
109     /**
110      * Called by the root element to leave DTD mode and if any
111      * DTD parts were printer, will return a string with their
112      * textual content.
113      */

114     public String JavaDoc leaveDTD()
115     {
116         // Only works if we're going out of DTD mode.
117
if ( _writer == _dtdWriter ) {
118             _line.append( _text );
119             _text = new StringBuffer JavaDoc( 20 );
120             flushLine( false );
121             _writer = _docWriter;
122             return _dtdWriter.toString();
123         } else
124             return null;
125     }
126     
127     
128     /**
129      * Called to print additional text. Each time this method is called
130      * it accumulates more text. When a space is printed ({@link
131      * #printSpace}) all the accumulated text becomes one part and is
132      * added to the accumulate line. When a line is long enough, it can
133      * be broken at its text boundary.
134      *
135      * @param text The text to print
136      */

137     public void printText( String JavaDoc text )
138     {
139         _text.append( text );
140     }
141     
142     
143     public void printText( StringBuffer JavaDoc text )
144     {
145         _text.append( text.toString() );
146     }
147
148
149     public void printText( char ch )
150     {
151         _text.append( ch );
152     }
153
154
155     public void printText( char[] chars, int start, int length )
156     {
157         _text.append( chars, start, length );
158     }
159     
160
161     /**
162      * Called to print a single space between text parts that may be
163      * broken into separate lines. Must not be called to print a space
164      * when preserving spaces. The text accumulated so far with {@link
165      * #printText} will be added to the accumulated line, and a space
166      * separator will be counted. If the line accumulated so far is
167      * long enough, it will be printed.
168      */

169     public void printSpace()
170     {
171         // The line consists of the text accumulated in _line,
172
// followed by one or more spaces as counted by _spaces,
173
// followed by more space accumulated in _text:
174
// - Text is printed and accumulated into _text.
175
// - A space is printed, so _text is added to _line and
176
// a space is counted.
177
// - More text is printed and accumulated into _text.
178
// - A space is printed, the previous spaces are added
179
// to _line, the _text is added to _line, and a new
180
// space is counted.
181

182         // If text was accumulated with printText(), then the space
183
// means we have to move that text into the line and
184
// start accumulating new text with printText().
185
if ( _text.length() > 0 ) {
186             // If the text breaks a line bounary, wrap to the next line.
187
// The printed line size consists of the indentation we're going
188
// to use next, the accumulated line so far, some spaces and the
189
// accumulated text so far.
190
if ( _format.getLineWidth() > 0 &&
191                  _thisIndent + _line.length() + _spaces + _text.length() > _format.getLineWidth() ) {
192                 flushLine( false );
193                 try {
194                     // Print line and new line, then zero the line contents.
195
_writer.write( _format.getLineSeparator() );
196                 } catch ( IOException JavaDoc except ) {
197                     // We don't throw an exception, but hold it
198
// until the end of the document.
199
if ( _exception == null )
200                         _exception = except;
201                 }
202             }
203             
204             // Add as many spaces as we accumulaed before.
205
// At the end of this loop, _spaces is zero.
206
while ( _spaces > 0 ) {
207                 _line.append( ' ' );
208                 --_spaces;
209             }
210             _line.append( _text );
211             _text = new StringBuffer JavaDoc( 20 );
212         }
213         // Starting a new word: accumulate the text between the line
214
// and this new word; not a new word: just add another space.
215
++_spaces;
216     }
217
218
219     /**
220      * Called to print a line consisting of the text accumulated so
221      * far. This is equivalent to calling {@link #printSpace} but
222      * forcing the line to print and starting a new line ({@link
223      * #printSpace} will only start a new line if the current line
224      * is long enough).
225      */

226     public void breakLine()
227     {
228         breakLine( false );
229     }
230
231
232     public void breakLine( boolean preserveSpace )
233     {
234         // Equivalent to calling printSpace and forcing a flushLine.
235
if ( _text.length() > 0 ) {
236             while ( _spaces > 0 ) {
237                 _line.append( ' ' );
238                 --_spaces;
239             }
240             _line.append( _text );
241             _text = new StringBuffer JavaDoc( 20 );
242         }
243         flushLine( preserveSpace );
244         try {
245             // Print line and new line, then zero the line contents.
246
_writer.write( _format.getLineSeparator() );
247         } catch ( IOException JavaDoc except ) {
248             // We don't throw an exception, but hold it
249
// until the end of the document.
250
if ( _exception == null )
251                 _exception = except;
252         }
253     }
254     
255
256     /**
257      * Flushes the line accumulated so far to the writer and get ready
258      * to accumulate the next line. This method is called by {@link
259      * #printText} and {@link #printSpace} when the accumulated line plus
260      * accumulated text are two long to fit on a given line. At the end of
261      * this method _line is empty and _spaces is zero.
262      */

263     public void flushLine( boolean preserveSpace )
264     {
265         int indent;
266         
267         if ( _line.length() > 0 ) {
268             try {
269                 
270                 if ( _format.getIndenting() && ! preserveSpace ) {
271                     // Make sure the indentation does not blow us away.
272
indent = _thisIndent;
273                     if ( ( 2 * indent ) > _format.getLineWidth() && _format.getLineWidth() > 0 )
274                         indent = _format.getLineWidth() / 2;
275                     // Print the indentation as spaces and set the current
276
// indentation to the next expected indentation.
277
while ( indent > 0 ) {
278                         _writer.write( ' ' );
279                         --indent;
280                     }
281                 }
282                 _thisIndent = _nextIndent;
283                 
284                 // There is no need to print the spaces at the end of the line,
285
// they are simply stripped and replaced with a single line
286
// separator.
287
_spaces = 0;
288                 _writer.write( _line.toString() );
289                 
290                 _line = new StringBuffer JavaDoc( 40 );
291             } catch ( IOException JavaDoc except ) {
292                 // We don't throw an exception, but hold it
293
// until the end of the document.
294
if ( _exception == null )
295                     _exception = except;
296             }
297         }
298     }
299     
300     
301     /**
302      * Flush the output stream. Must be called when done printing
303      * the document, otherwise some text might be buffered.
304      */

305     public void flush()
306     {
307         if ( _line.length() > 0 || _text.length() > 0 )
308             breakLine();
309         try {
310             _writer.flush();
311         } catch ( IOException JavaDoc except ) {
312             // We don't throw an exception, but hold it
313
// until the end of the document.
314
if ( _exception == null )
315                 _exception = except;
316         }
317     }
318
319
320     /**
321      * Increment the indentation for the next line.
322      */

323     public void indent()
324     {
325         _nextIndent += _format.getIndent();
326     }
327
328
329     /**
330      * Decrement the indentation for the next line.
331      */

332     public void unindent()
333     {
334         _nextIndent -= _format.getIndent();
335         if ( _nextIndent < 0 )
336             _nextIndent = 0;
337         // If there is no current line and we're de-identing then
338
// this indentation level is actually the next level.
339
if ( ( _line.length() + _spaces + _text.length() ) == 0 )
340             _thisIndent = _nextIndent;
341     }
342
343
344     public int getNextIndent()
345     {
346         return _nextIndent;
347     }
348
349
350     public void setNextIndent( int indent )
351     {
352         _nextIndent = indent;
353     }
354
355
356     public void setThisIndent( int indent )
357     {
358         _thisIndent = indent;
359     }
360
361
362 }
363
Popular Tags