JDOM2 Feature Outputter Updates

rolfl edited this page Apr 8, 2012 · 3 revisions

The internals of XMLOutputter have been completely reworked. The public API itself is unchanged, but the implementation has been modified to meet the following goals:

  1. Consistency of output - Make XMLOutputter, DOMOutputter, SAXOutputter, and the new StAXOutputters produce the same results with the same inputs (Only the XMLOutputter supported the 'Format' concept in JDOM 1.x).
  2. Support output to StAX Streams
  3. Implement basic functionality - changing the way that Namespaces are output (the order of presentation) was hard to do without deep changes.
  4. Consistency of subclass-interface - people wanting to subclass the XMLOutputter had a real challenge finding the right hooks. The hooks for the XMLOutputter were different to the hooks for the other Outputters.
  5. Simplify the implementations - XMLOutputter (DOM and SAX Outputters were very rudimentary in comparison) contained three distinct concepts all mixed together: handling the actual output; formatting the output; and managing the input state.
  6. Improve the performance of the Outputters

The end result of the changes to the Outputters are that:

  1. All the outputters support the Format concept.
  2. All the outputters have similar hooks for customizing functionality.
  3. The managing of the intput data, the data formatting, and the output target are independant code items

Th change has a significant impact on people who sub-class the XMLOutputter, but the benefit on the subclassing-API is significant.

In Detail

All the Outputers now share a common model. There is the client side API for the Outputter, and this API is given an implementation of an specific Outputter which does the actual work. The JDOM code supplies a default implementation that can be overriden to customize your output, if necessary. The output implementation is responsible for interfacing to the output destination, but it delegates the management of the input data, formatting, and other administration to existing JDOM classes.

An example is useful. The XMLOutputter is the client-side API for outputting JDOM content to an OutputStream or Writer (or String). The XMLOutputter does some simple client-side validation and handling (converts output String and OutputStream targets to simple Writer targets), and delegates the real work to the XMLOutputProcessor implementation. There is a default implementation called AbstractXMLOutputProcessor that does the real interface to the output Writer. The AbstractXMLOutputProcessor contains the actual output code, but it delegates the management of the formatting of the XML, and the handling of the Namespace stack to classes like the FormatStack, NamespaceStack, Walkers, and EscapeStrategy.

All the Outputters (XMLOutputter, DOMOutputter, SAXOutputter, StAXEventOutputter, and StAXStreamOutputter) use the same model for outputting data to their respective targets. Customizing the Outputters is thus a whole lot easier than JDOM 1.x.

JDOM 2.x now effectively differentiates between 5 areas of code required for output of JDOM content to some target destination. The following list identifies the 5 areas, and the code that performs the appropriate function:

  1. Managing Namespaces - NamespaceStack
  2. Managing format configuration (indenting, etc.) - Format and FormatStack.
  3. Applying formatting to the output - Walker.
  4. Escaping the output appropriately - EscapeStrategy
  5. Managing the output process, and delivering the output to the target destination - *OutputProcessor.

This process allows the default system to implement high-performance and reusable classes for output, while at the same time making it easier to subclass and customize the output if you need to.

It is now possible to create a new formatter, and apply the same formatter (Walker) to any of the 5 output targets. Additionally, it is possible to create a new type of output target without having to worry about the actual formatting of the XML.