1 package com.fasterxml.jackson.dataformat.xml.util;
2
3 import java.io.IOException;
4 import java.math.BigDecimal;
5 import java.math.BigInteger;
6 import java.util.Arrays;
7
8 import javax.xml.stream.XMLStreamException;
9
10 import org.codehaus.stax2.XMLStreamWriter2;
11
12 import com.fasterxml.jackson.core.*;
13 import com.fasterxml.jackson.core.util.Instantiatable;
14
15 import com.fasterxml.jackson.dataformat.xml.XmlPrettyPrinter;
16 import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
17
18
26 public class DefaultXmlPrettyPrinter
27 implements XmlPrettyPrinter, Instantiatable<DefaultXmlPrettyPrinter>,
28 java.io.Serializable
29 {
30 private static final long serialVersionUID = 1L;
31
32
38 public interface Indenter
39 {
40 public void writeIndentation(JsonGenerator g, int level) throws IOException;
41
42 public void writeIndentation(XMLStreamWriter2 sw, int level) throws XMLStreamException;
43
44
48 public boolean isInline();
49 }
50
51
56
57
60 protected Indenter _arrayIndenter = new FixedSpaceIndenter();
61
62
68 protected Indenter _objectIndenter = new Lf2SpacesIndenter();
69
70
71
72
77 protected boolean _spacesInObjectEntries = true;
78
79
84
85
89 protected transient int _nesting = 0;
90
91
98 protected transient boolean _justHadStartElement;
99
100
105
106 public DefaultXmlPrettyPrinter() { }
107
108 protected DefaultXmlPrettyPrinter(DefaultXmlPrettyPrinter base)
109 {
110 _arrayIndenter = base._arrayIndenter;
111 _objectIndenter = base._objectIndenter;
112 _spacesInObjectEntries = base._spacesInObjectEntries;
113 _nesting = base._nesting;
114 }
115
116 public void indentArraysWith(Indenter i)
117 {
118 _arrayIndenter = (i == null) ? new NopIndenter() : i;
119 }
120
121 public void indentObjectsWith(Indenter i)
122 {
123 _objectIndenter = (i == null) ? new NopIndenter() : i;
124 }
125
126 public void spacesInObjectEntries(boolean b) { _spacesInObjectEntries = b; }
127
128
133
134 @Override
135 public DefaultXmlPrettyPrinter createInstance() {
136 return new DefaultXmlPrettyPrinter(this);
137 }
138
139
144
145 @Override
146 public void writeRootValueSeparator(JsonGenerator gen) throws IOException {
147
148 gen.writeRaw('\n');
149 }
150
151
156
157 @Override
158 public void beforeArrayValues(JsonGenerator gen) throws IOException {
159
160 }
161
162 @Override
163 public void writeStartArray(JsonGenerator gen) throws IOException {
164
165 }
166
167 @Override
168 public void writeArrayValueSeparator(JsonGenerator gen) throws IOException {
169
170 }
171
172 @Override
173 public void writeEndArray(JsonGenerator gen, int nrOfValues) throws IOException {
174
175 }
176
177
182
183 @Override
184 public void beforeObjectEntries(JsonGenerator gen)
185 throws IOException, JsonGenerationException
186 {
187
188 }
189
190 @Override
191 public void writeStartObject(JsonGenerator gen) throws IOException
192 {
193 if (!_objectIndenter.isInline()) {
194 if (_nesting > 0) {
195 _objectIndenter.writeIndentation(gen, _nesting);
196 }
197 ++_nesting;
198 }
199 _justHadStartElement = true;
200 ((ToXmlGenerator) gen)._handleStartObject();
201 }
202
203 @Override
204 public void writeObjectEntrySeparator(JsonGenerator gen) throws IOException {
205
206 }
207
208 @Override
209 public void writeObjectFieldValueSeparator(JsonGenerator gen) throws IOException {
210
211 }
212
213 @Override
214 public void writeEndObject(JsonGenerator gen, int nrOfEntries) throws IOException
215 {
216 if (!_objectIndenter.isInline()) {
217 --_nesting;
218 }
219
220 if (_justHadStartElement) {
221 _justHadStartElement = false;
222 } else {
223 _objectIndenter.writeIndentation(gen, _nesting);
224 }
225 ((ToXmlGenerator) gen)._handleEndObject();
226 }
227
228
233
234 @Override
235 public void writeStartElement(XMLStreamWriter2 sw,
236 String nsURI, String localName) throws XMLStreamException
237 {
238 if (!_objectIndenter.isInline()) {
239 if (_justHadStartElement) {
240 _justHadStartElement = false;
241 }
242 _objectIndenter.writeIndentation(sw, _nesting);
243 ++_nesting;
244 }
245 sw.writeStartElement(nsURI, localName);
246 _justHadStartElement = true;
247 }
248
249 @Override
250 public void writeEndElement(XMLStreamWriter2 sw, int nrOfEntries) throws XMLStreamException
251 {
252 if (!_objectIndenter.isInline()) {
253 --_nesting;
254 }
255
256 if (_justHadStartElement) {
257 _justHadStartElement = false;
258 } else {
259 _objectIndenter.writeIndentation(sw, _nesting);
260 }
261 sw.writeEndElement();
262 }
263
264 @Override
265 public void writeLeafElement(XMLStreamWriter2 sw,
266 String nsURI, String localName, String text, boolean isCData)
267 throws XMLStreamException
268 {
269 if (!_objectIndenter.isInline()) {
270 _objectIndenter.writeIndentation(sw, _nesting);
271 }
272 sw.writeStartElement(nsURI, localName);
273 if(isCData) {
274 sw.writeCData(text);
275 } else {
276 sw.writeCharacters(text);
277 }
278 sw.writeEndElement();
279 _justHadStartElement = false;
280 }
281
282 @Override
283 public void writeLeafElement(XMLStreamWriter2 sw,
284 String nsURI, String localName,
285 char[] buffer, int offset, int len, boolean isCData)
286 throws XMLStreamException
287 {
288 if (!_objectIndenter.isInline()) {
289 _objectIndenter.writeIndentation(sw, _nesting);
290 }
291 sw.writeStartElement(nsURI, localName);
292 if(isCData) {
293 sw.writeCData(buffer, offset, len);
294 } else {
295 sw.writeCharacters(buffer, offset, len);
296 }
297 sw.writeEndElement();
298 _justHadStartElement = false;
299 }
300
301 @Override
302 public void writeLeafElement(XMLStreamWriter2 sw,
303 String nsURI, String localName, boolean value)
304 throws XMLStreamException
305 {
306 if (!_objectIndenter.isInline()) {
307 _objectIndenter.writeIndentation(sw, _nesting);
308 }
309 sw.writeStartElement(nsURI, localName);
310 sw.writeBoolean(value);
311 sw.writeEndElement();
312 _justHadStartElement = false;
313 }
314
315 @Override
316 public void writeLeafElement(XMLStreamWriter2 sw,
317 String nsURI, String localName, int value)
318 throws XMLStreamException
319 {
320 if (!_objectIndenter.isInline()) {
321 _objectIndenter.writeIndentation(sw, _nesting);
322 }
323 sw.writeStartElement(nsURI, localName);
324 sw.writeInt(value);
325 sw.writeEndElement();
326 _justHadStartElement = false;
327 }
328
329 @Override
330 public void writeLeafElement(XMLStreamWriter2 sw,
331 String nsURI, String localName, long value)
332 throws XMLStreamException
333 {
334 if (!_objectIndenter.isInline()) {
335 _objectIndenter.writeIndentation(sw, _nesting);
336 }
337 sw.writeStartElement(nsURI, localName);
338 sw.writeLong(value);
339 sw.writeEndElement();
340 _justHadStartElement = false;
341 }
342
343 @Override
344 public void writeLeafElement(XMLStreamWriter2 sw,
345 String nsURI, String localName, double value)
346 throws XMLStreamException
347 {
348 if (!_objectIndenter.isInline()) {
349 _objectIndenter.writeIndentation(sw, _nesting);
350 }
351 sw.writeStartElement(nsURI, localName);
352 sw.writeDouble(value);
353 sw.writeEndElement();
354 _justHadStartElement = false;
355 }
356
357 @Override
358 public void writeLeafElement(XMLStreamWriter2 sw,
359 String nsURI, String localName, float value)
360 throws XMLStreamException
361 {
362 if (!_objectIndenter.isInline()) {
363 _objectIndenter.writeIndentation(sw, _nesting);
364 }
365 sw.writeStartElement(nsURI, localName);
366 sw.writeFloat(value);
367 sw.writeEndElement();
368 _justHadStartElement = false;
369 }
370
371 @Override
372 public void writeLeafElement(XMLStreamWriter2 sw,
373 String nsURI, String localName, BigInteger value)
374 throws XMLStreamException
375 {
376 if (!_objectIndenter.isInline()) {
377 _objectIndenter.writeIndentation(sw, _nesting);
378 }
379 sw.writeStartElement(nsURI, localName);
380 sw.writeInteger(value);
381 sw.writeEndElement();
382 _justHadStartElement = false;
383 }
384
385 @Override
386 public void writeLeafElement(XMLStreamWriter2 sw,
387 String nsURI, String localName, BigDecimal value)
388 throws XMLStreamException
389 {
390 if (!_objectIndenter.isInline()) {
391 _objectIndenter.writeIndentation(sw, _nesting);
392 }
393 sw.writeStartElement(nsURI, localName);
394 sw.writeDecimal(value);
395 sw.writeEndElement();
396 _justHadStartElement = false;
397 }
398
399 @Override
400 public void writeLeafElement(XMLStreamWriter2 sw,
401 String nsURI, String localName,
402 byte[] data, int offset, int len)
403 throws XMLStreamException
404 {
405 if (!_objectIndenter.isInline()) {
406 _objectIndenter.writeIndentation(sw, _nesting);
407 }
408 sw.writeStartElement(nsURI, localName);
409 sw.writeBinary(data, offset, len);
410 sw.writeEndElement();
411 _justHadStartElement = false;
412 }
413
414 @Override
415 public void writeLeafNullElement(XMLStreamWriter2 sw,
416 String nsURI, String localName)
417 throws XMLStreamException
418 {
419 if (!_objectIndenter.isInline()) {
420 _objectIndenter.writeIndentation(sw, _nesting);
421 }
422 sw.writeEmptyElement(nsURI, localName);
423 _justHadStartElement = false;
424 }
425
426 @Override
427 public void writePrologLinefeed(XMLStreamWriter2 sw) throws XMLStreamException
428 {
429
430 sw.writeRaw(Lf2SpacesIndenter.SYSTEM_LINE_SEPARATOR);
431 }
432
433
440
441
444 protected static class NopIndenter
445 implements Indenter, java.io.Serializable
446 {
447 private static final long serialVersionUID = 1L;
448
449 public NopIndenter() { }
450 @Override public void writeIndentation(JsonGenerator jg, int level) { }
451 @Override public boolean isInline() { return true; }
452 @Override public void writeIndentation(XMLStreamWriter2 sw, int level) { }
453 }
454
455
460 protected static class FixedSpaceIndenter
461 implements Indenter, java.io.Serializable
462 {
463 private static final long serialVersionUID = 1L;
464
465 public FixedSpaceIndenter() { }
466
467 @Override
468 public void writeIndentation(XMLStreamWriter2 sw, int level)
469 throws XMLStreamException
470 {
471 sw.writeRaw(" ");
472 }
473
474 @Override
475 public void writeIndentation(JsonGenerator g, int level) throws IOException
476 {
477 g.writeRaw(' ');
478 }
479
480 @Override
481 public boolean isInline() { return true; }
482 }
483
484
488 protected static class Lf2SpacesIndenter
489 implements Indenter, java.io.Serializable
490 {
491 private static final long serialVersionUID = 1L;
492
493 final static String SYSTEM_LINE_SEPARATOR;
494 static {
495 String lf = null;
496 try {
497 lf = System.getProperty("line.separator");
498 } catch (Throwable t) { }
499 SYSTEM_LINE_SEPARATOR = (lf == null) ? "\n" : lf;
500 }
501
502 final static int SPACE_COUNT = 64;
503 final static char[] SPACES = new char[SPACE_COUNT];
504 static {
505 Arrays.fill(SPACES, ' ');
506 }
507
508 public Lf2SpacesIndenter() { }
509
510 @Override
511 public boolean isInline() { return false; }
512
513 @Override
514 public void writeIndentation(XMLStreamWriter2 sw, int level) throws XMLStreamException
515 {
516 sw.writeRaw(SYSTEM_LINE_SEPARATOR);
517 level += level;
518 while (level > SPACE_COUNT) {
519 sw.writeRaw(SPACES, 0, SPACE_COUNT);
520 level -= SPACES.length;
521 }
522 sw.writeRaw(SPACES, 0, level);
523 }
524
525 @Override
526 public void writeIndentation(JsonGenerator jg, int level) throws IOException
527 {
528 jg.writeRaw(SYSTEM_LINE_SEPARATOR);
529 level += level;
530 while (level > SPACE_COUNT) {
531 jg.writeRaw(SPACES, 0, SPACE_COUNT);
532 level -= SPACES.length;
533 }
534 jg.writeRaw(SPACES, 0, level);
535 }
536 }
537 }
538