6
|
1 |
/*
|
|
2 |
* reserved comment block
|
|
3 |
* DO NOT REMOVE OR ALTER!
|
|
4 |
*/
|
|
5 |
/*
|
|
6 |
* Copyright 1999-2002,2004 The Apache Software Foundation.
|
|
7 |
*
|
|
8 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
9 |
* you may not use this file except in compliance with the License.
|
|
10 |
* You may obtain a copy of the License at
|
|
11 |
*
|
|
12 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13 |
*
|
|
14 |
* Unless required by applicable law or agreed to in writing, software
|
|
15 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17 |
* See the License for the specific language governing permissions and
|
|
18 |
* limitations under the License.
|
|
19 |
*/
|
|
20 |
|
|
21 |
|
|
22 |
package com.sun.org.apache.xml.internal.serialize;
|
|
23 |
|
|
24 |
|
|
25 |
import java.io.Writer;
|
|
26 |
import java.io.StringWriter;
|
|
27 |
import java.io.IOException;
|
|
28 |
|
|
29 |
|
|
30 |
/**
|
|
31 |
* Extends {@link Printer} and adds support for indentation and line
|
|
32 |
* wrapping.
|
|
33 |
*
|
|
34 |
* @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
|
|
35 |
*/
|
|
36 |
public class IndentPrinter
|
|
37 |
extends Printer
|
|
38 |
{
|
|
39 |
|
|
40 |
|
|
41 |
/**
|
|
42 |
* Holds the currently accumulating text line. This buffer will constantly
|
|
43 |
* be reused by deleting its contents instead of reallocating it.
|
|
44 |
*/
|
|
45 |
private StringBuffer _line;
|
|
46 |
|
|
47 |
|
|
48 |
/**
|
|
49 |
* Holds the currently accumulating text that follows {@link #_line}.
|
|
50 |
* When the end of the part is identified by a call to {@link #printSpace}
|
|
51 |
* or {@link #breakLine}, this part is added to the accumulated line.
|
|
52 |
*/
|
|
53 |
private StringBuffer _text;
|
|
54 |
|
|
55 |
|
|
56 |
/**
|
|
57 |
* Counts how many white spaces come between the accumulated line and the
|
|
58 |
* current accumulated text. Multiple spaces at the end of the a line
|
|
59 |
* will not be printed.
|
|
60 |
*/
|
|
61 |
private int _spaces;
|
|
62 |
|
|
63 |
|
|
64 |
/**
|
|
65 |
* Holds the indentation for the current line that is now accumulating in
|
|
66 |
* memory and will be sent for printing shortly.
|
|
67 |
*/
|
|
68 |
private int _thisIndent;
|
|
69 |
|
|
70 |
|
|
71 |
/**
|
|
72 |
* Holds the indentation for the next line to be printed. After this line is
|
|
73 |
* printed, {@link #_nextIndent} is assigned to {@link #_thisIndent}.
|
|
74 |
*/
|
|
75 |
private int _nextIndent;
|
|
76 |
|
|
77 |
|
|
78 |
public IndentPrinter( Writer writer, OutputFormat format)
|
|
79 |
{
|
|
80 |
super( writer, format );
|
|
81 |
// Initialize everything for a first/second run.
|
|
82 |
_line = new StringBuffer( 80 );
|
|
83 |
_text = new StringBuffer( 20 );
|
|
84 |
_spaces = 0;
|
|
85 |
_thisIndent = _nextIndent = 0;
|
|
86 |
}
|
|
87 |
|
|
88 |
|
|
89 |
/**
|
|
90 |
* Called by any of the DTD handlers to enter DTD mode.
|
|
91 |
* Once entered, all output will be accumulated in a string
|
|
92 |
* that can be printed as part of the document's DTD.
|
|
93 |
* This method may be called any number of time but will only
|
|
94 |
* have affect the first time it's called. To exist DTD state
|
|
95 |
* and get the accumulated DTD, call {@link #leaveDTD}.
|
|
96 |
*/
|
|
97 |
public void enterDTD()
|
|
98 |
{
|
|
99 |
// Can only enter DTD state once. Once we're out of DTD
|
|
100 |
// state, can no longer re-enter it.
|
|
101 |
if ( _dtdWriter == null ) {
|
|
102 |
_line.append( _text );
|
|
103 |
_text = new StringBuffer( 20 );
|
|
104 |
flushLine( false );
|
|
105 |
_dtdWriter = new StringWriter();
|
|
106 |
_docWriter = _writer;
|
|
107 |
_writer = _dtdWriter;
|
|
108 |
}
|
|
109 |
}
|
|
110 |
|
|
111 |
|
|
112 |
/**
|
|
113 |
* Called by the root element to leave DTD mode and if any
|
|
114 |
* DTD parts were printer, will return a string with their
|
|
115 |
* textual content.
|
|
116 |
*/
|
|
117 |
public String leaveDTD()
|
|
118 |
{
|
|
119 |
// Only works if we're going out of DTD mode.
|
|
120 |
if ( _writer == _dtdWriter ) {
|
|
121 |
_line.append( _text );
|
|
122 |
_text = new StringBuffer( 20 );
|
|
123 |
flushLine( false );
|
|
124 |
_writer = _docWriter;
|
|
125 |
return _dtdWriter.toString();
|
|
126 |
} else
|
|
127 |
return null;
|
|
128 |
}
|
|
129 |
|
|
130 |
|
|
131 |
/**
|
|
132 |
* Called to print additional text. Each time this method is called
|
|
133 |
* it accumulates more text. When a space is printed ({@link
|
|
134 |
* #printSpace}) all the accumulated text becomes one part and is
|
|
135 |
* added to the accumulate line. When a line is long enough, it can
|
|
136 |
* be broken at its text boundary.
|
|
137 |
*
|
|
138 |
* @param text The text to print
|
|
139 |
*/
|
|
140 |
public void printText( String text )
|
|
141 |
{
|
|
142 |
_text.append( text );
|
|
143 |
}
|
|
144 |
|
|
145 |
|
|
146 |
public void printText( StringBuffer text )
|
|
147 |
{
|
|
148 |
_text.append( text.toString() );
|
|
149 |
}
|
|
150 |
|
|
151 |
|
|
152 |
public void printText( char ch )
|
|
153 |
{
|
|
154 |
_text.append( ch );
|
|
155 |
}
|
|
156 |
|
|
157 |
|
|
158 |
public void printText( char[] chars, int start, int length )
|
|
159 |
{
|
|
160 |
_text.append( chars, start, length );
|
|
161 |
}
|
|
162 |
|
|
163 |
|
|
164 |
/**
|
|
165 |
* Called to print a single space between text parts that may be
|
|
166 |
* broken into separate lines. Must not be called to print a space
|
|
167 |
* when preserving spaces. The text accumulated so far with {@link
|
|
168 |
* #printText} will be added to the accumulated line, and a space
|
|
169 |
* separator will be counted. If the line accumulated so far is
|
|
170 |
* long enough, it will be printed.
|
|
171 |
*/
|
|
172 |
public void printSpace()
|
|
173 |
{
|
|
174 |
// The line consists of the text accumulated in _line,
|
|
175 |
// followed by one or more spaces as counted by _spaces,
|
|
176 |
// followed by more space accumulated in _text:
|
|
177 |
// - Text is printed and accumulated into _text.
|
|
178 |
// - A space is printed, so _text is added to _line and
|
|
179 |
// a space is counted.
|
|
180 |
// - More text is printed and accumulated into _text.
|
|
181 |
// - A space is printed, the previous spaces are added
|
|
182 |
// to _line, the _text is added to _line, and a new
|
|
183 |
// space is counted.
|
|
184 |
|
|
185 |
// If text was accumulated with printText(), then the space
|
|
186 |
// means we have to move that text into the line and
|
|
187 |
// start accumulating new text with printText().
|
|
188 |
if ( _text.length() > 0 ) {
|
|
189 |
// If the text breaks a line bounary, wrap to the next line.
|
|
190 |
// The printed line size consists of the indentation we're going
|
|
191 |
// to use next, the accumulated line so far, some spaces and the
|
|
192 |
// accumulated text so far.
|
|
193 |
if ( _format.getLineWidth() > 0 &&
|
|
194 |
_thisIndent + _line.length() + _spaces + _text.length() > _format.getLineWidth() ) {
|
|
195 |
flushLine( false );
|
|
196 |
try {
|
|
197 |
// Print line and new line, then zero the line contents.
|
|
198 |
_writer.write( _format.getLineSeparator() );
|
|
199 |
} catch ( IOException except ) {
|
|
200 |
// We don't throw an exception, but hold it
|
|
201 |
// until the end of the document.
|
|
202 |
if ( _exception == null )
|
|
203 |
_exception = except;
|
|
204 |
}
|
|
205 |
}
|
|
206 |
|
|
207 |
// Add as many spaces as we accumulaed before.
|
|
208 |
// At the end of this loop, _spaces is zero.
|
|
209 |
while ( _spaces > 0 ) {
|
|
210 |
_line.append( ' ' );
|
|
211 |
--_spaces;
|
|
212 |
}
|
|
213 |
_line.append( _text );
|
|
214 |
_text = new StringBuffer( 20 );
|
|
215 |
}
|
|
216 |
// Starting a new word: accumulate the text between the line
|
|
217 |
// and this new word; not a new word: just add another space.
|
|
218 |
++_spaces;
|
|
219 |
}
|
|
220 |
|
|
221 |
|
|
222 |
/**
|
|
223 |
* Called to print a line consisting of the text accumulated so
|
|
224 |
* far. This is equivalent to calling {@link #printSpace} but
|
|
225 |
* forcing the line to print and starting a new line ({@link
|
|
226 |
* #printSpace} will only start a new line if the current line
|
|
227 |
* is long enough).
|
|
228 |
*/
|
|
229 |
public void breakLine()
|
|
230 |
{
|
|
231 |
breakLine( false );
|
|
232 |
}
|
|
233 |
|
|
234 |
|
|
235 |
public void breakLine( boolean preserveSpace )
|
|
236 |
{
|
|
237 |
// Equivalent to calling printSpace and forcing a flushLine.
|
|
238 |
if ( _text.length() > 0 ) {
|
|
239 |
while ( _spaces > 0 ) {
|
|
240 |
_line.append( ' ' );
|
|
241 |
--_spaces;
|
|
242 |
}
|
|
243 |
_line.append( _text );
|
|
244 |
_text = new StringBuffer( 20 );
|
|
245 |
}
|
|
246 |
flushLine( preserveSpace );
|
|
247 |
try {
|
|
248 |
// Print line and new line, then zero the line contents.
|
|
249 |
_writer.write( _format.getLineSeparator() );
|
|
250 |
} catch ( IOException except ) {
|
|
251 |
// We don't throw an exception, but hold it
|
|
252 |
// until the end of the document.
|
|
253 |
if ( _exception == null )
|
|
254 |
_exception = except;
|
|
255 |
}
|
|
256 |
}
|
|
257 |
|
|
258 |
|
|
259 |
/**
|
|
260 |
* Flushes the line accumulated so far to the writer and get ready
|
|
261 |
* to accumulate the next line. This method is called by {@link
|
|
262 |
* #printText} and {@link #printSpace} when the accumulated line plus
|
|
263 |
* accumulated text are two long to fit on a given line. At the end of
|
|
264 |
* this method _line is empty and _spaces is zero.
|
|
265 |
*/
|
|
266 |
public void flushLine( boolean preserveSpace )
|
|
267 |
{
|
|
268 |
int indent;
|
|
269 |
|
|
270 |
if ( _line.length() > 0 ) {
|
|
271 |
try {
|
|
272 |
|
|
273 |
if ( _format.getIndenting() && ! preserveSpace ) {
|
|
274 |
// Make sure the indentation does not blow us away.
|
|
275 |
indent = _thisIndent;
|
|
276 |
if ( ( 2 * indent ) > _format.getLineWidth() && _format.getLineWidth() > 0 )
|
|
277 |
indent = _format.getLineWidth() / 2;
|
|
278 |
// Print the indentation as spaces and set the current
|
|
279 |
// indentation to the next expected indentation.
|
|
280 |
while ( indent > 0 ) {
|
|
281 |
_writer.write( ' ' );
|
|
282 |
--indent;
|
|
283 |
}
|
|
284 |
}
|
|
285 |
_thisIndent = _nextIndent;
|
|
286 |
|
|
287 |
// There is no need to print the spaces at the end of the line,
|
|
288 |
// they are simply stripped and replaced with a single line
|
|
289 |
// separator.
|
|
290 |
_spaces = 0;
|
|
291 |
_writer.write( _line.toString() );
|
|
292 |
|
|
293 |
_line = new StringBuffer( 40 );
|
|
294 |
} catch ( IOException except ) {
|
|
295 |
// We don't throw an exception, but hold it
|
|
296 |
// until the end of the document.
|
|
297 |
if ( _exception == null )
|
|
298 |
_exception = except;
|
|
299 |
}
|
|
300 |
}
|
|
301 |
}
|
|
302 |
|
|
303 |
|
|
304 |
/**
|
|
305 |
* Flush the output stream. Must be called when done printing
|
|
306 |
* the document, otherwise some text might be buffered.
|
|
307 |
*/
|
|
308 |
public void flush()
|
|
309 |
{
|
|
310 |
if ( _line.length() > 0 || _text.length() > 0 )
|
|
311 |
breakLine();
|
|
312 |
try {
|
|
313 |
_writer.flush();
|
|
314 |
} catch ( IOException except ) {
|
|
315 |
// We don't throw an exception, but hold it
|
|
316 |
// until the end of the document.
|
|
317 |
if ( _exception == null )
|
|
318 |
_exception = except;
|
|
319 |
}
|
|
320 |
}
|
|
321 |
|
|
322 |
|
|
323 |
/**
|
|
324 |
* Increment the indentation for the next line.
|
|
325 |
*/
|
|
326 |
public void indent()
|
|
327 |
{
|
|
328 |
_nextIndent += _format.getIndent();
|
|
329 |
}
|
|
330 |
|
|
331 |
|
|
332 |
/**
|
|
333 |
* Decrement the indentation for the next line.
|
|
334 |
*/
|
|
335 |
public void unindent()
|
|
336 |
{
|
|
337 |
_nextIndent -= _format.getIndent();
|
|
338 |
if ( _nextIndent < 0 )
|
|
339 |
_nextIndent = 0;
|
|
340 |
// If there is no current line and we're de-identing then
|
|
341 |
// this indentation level is actually the next level.
|
|
342 |
if ( ( _line.length() + _spaces + _text.length() ) == 0 )
|
|
343 |
_thisIndent = _nextIndent;
|
|
344 |
}
|
|
345 |
|
|
346 |
|
|
347 |
public int getNextIndent()
|
|
348 |
{
|
|
349 |
return _nextIndent;
|
|
350 |
}
|
|
351 |
|
|
352 |
|
|
353 |
public void setNextIndent( int indent )
|
|
354 |
{
|
|
355 |
_nextIndent = indent;
|
|
356 |
}
|
|
357 |
|
|
358 |
|
|
359 |
public void setThisIndent( int indent )
|
|
360 |
{
|
|
361 |
_thisIndent = indent;
|
|
362 |
}
|
|
363 |
|
|
364 |
|
|
365 |
}
|