Using a JDOM document as a Swing Document
This small article aims at providing an approach to extend a JDOM
Document in such a way that it behaves as a Swing
Document . It does not require to have an understanding of the Swing document model, but requires on the other hand should be familiar with the W3C DOM API or the JDOM API.
As some readers may not be very familiar with the Swing text package, it is a good idea to briefly present it.
The Swing text package has been created in order to ease the development of text-based application, such as text editors, word processer or even web browsers. It contains numerous classes, including some to view RTF files or HTML files, from which a few are from real interest.
All those classes conform to the Model-View-Controller design pattern that resides at Swing core.
Here follows a list of the text package main classes with a small description on their role:
The Document interface:
The document interface represents the data, the model . This data can be a simple plain text file, but can also be structured, ie. can contain sections, paragraphs, etc.
The Element interface:
This interface is closely related to the
Document interface, and is in charge for representing the structural elements of the text, which can be as said before, paragraphs, sections, etc. Each element has an attached
The AttributeSet interface:
AttributeSet represent a collection of attributes attached to a specific
Element . The
AttributeSet is a map between names and objects, is not ordered, and supports attribute resolution in the parent hierarchy. This means that attributes sets can support attribute inheritance, though this is not required.
The View class:
The view class is of course repsonsible for displaying the model on screen, thus playing the role of view in the pattern. Each view is bound to an Element by a
The ViewFactory interface:
ViewFactory is in charge for producing
View objects from a given element. This means that a
ViewFactory associates to each element, sometimes depending on its attributes, a given
The KeyMap interface:
KeyMap plays the role of controller in the Swing text package pattern. It simply binds keys (and event combination of keys) to action commands that modify the document.
The Caret and Highlighter interfaces:
Those two interfaces are of least interest compared to the others, they repsectively display the small caret that tells where text will be inserted and allow to graphically show what portion of the document has been selected.
The EditoKit class:
EditorKit is the class that embodies all the aspects that we have seen so far. It is in fact a combination of
Highlighter that make up a text-based application.
The interest of using a JDOM document as a Swing document may not be obvious, nevertheless there are many applications that could have benefit of such a possibility.
The first interesting point is that you can manipulate a Swing document using the JDOM API, and use interesting features such as XPath or XSLT to manipulate or make queries in your document. Moreover, as we will see later, the JDOM API is better for manipulating structured content than the Swing text package API.
The second interesting point is that you are always able to save and load your document to the XML format, which relieves you from the pain of writing your custom text format.
The third interest is that it makes your application very versatile and will allow you to reuse most of your code for any application that has its data stored as XML.
As said, it is very interesting to use a JDOM document as a Swing document. However, before trying to think about possible solutions, the Swing document model should be understood, in order to have a good overview of the differences between the model it offers and the model offered by JDOM.
The MVC pattern mentioned earlier is the core of the Swing text package, and the classes or interfaces that have important roles in this pattern have been presented.
Document interface endorses the role of model . Its primary concern is to be able to store textual informations, and provide the following facilities:
- Insert, change and remove text.
- Keep track of specific positions in the text, that follow changes made to the document.
- Offer a way for third-party classes to be notified of any change
These are the three main aspects of a Swing document, but they don't allow to manipulate nor store any strucutre. For this purpose the Swing document stores a hierarchy of
Elements organized in a tree structure.
Each Swing document has one or more root nodes, the latter being very rare we will assume that there will always be a single root element . Each
Element offers also a set of facilities:
- Acces to attributes.
- Acces to the parent element.
- Wether children are allowed or not.
- Acces to the element childrens and children count.
- Acces to the start and end offsets of the element in the document. This facility plays an inderect role in the logical view of the element.
The attributes are expressed as an
AttributeSet , and the
Elements have also a name.
There is a clear conceptual separation between the facilities offered by the document, and those offered by the elements. Moreover the document model does not offer any facility for creating and adding elements, thus reinforcing this separation. So a text document can be considered from two different points of view:
The logical view:
The logical view is the representation of the document as a long sequence of characters. In this sequence are inserted some stickers that follow text changes, which define either the presence (starting or ending) of an element, or a specific position that has to be remember (like a bookmark).
The structural view:
The structural view is the representation of the document as a hierrachy of elements that originate from a single root element. This is the vision of the document offered by XML.
The conceptual separation does not imply that there is a physical separation in the underlying implementation, in fact both views are tighly bound together, as the choosen implementation will show.
The JDOM document being an XML document does not offer all the functionnalities needed by a Swing document. The functionnalities related to the logical view , for instance, are completely absent from the JDOM document.
A good example of this fact would be the
getText method of the JDOM
Element class which only returns the concatenated text contained in the current
Element , ignoring the text contained by child elements. The design of this method break in a way the concept of the logical view.
Basically the functionnalities of the logical view have to be implemented from scratch. The other problem comes from functionnalities of the
Element that are also related to the logical view: the access to the start and end offsets of the element in the document.
As mentioned, all the functionnalities of the logical view have to be part of the new hybrid document, hybrid because it conforms to the JDOM document model and also to the Swing document model.
Two functionnalities are of real interest
- How an element can return its start and end offset in the logical view.
- How positions in the logical view can follow text changes.
There is a redundance in the localisation of an element position between the
Element classes of the Swing text package, as
Elements are part of a
Document , this functionnalities should be delegated to the
This means that the new implementation will have to redefine an
Element class that is able to retrieve its current start and end offset in the document logical view.
Another important set of functionnalities is text change, insertion and removal. As expressed in the Swing document model, these functionnalities are offered by the document, but it is more conveniant to delegate this functionnalities to the elements. In this case any developer will be able to insert, remove or change an Element text content with a single Element reference, even if it doesn't belong (yet) to a document.
The *tracking of positions* in the text poses a small problem
stickers* or positions are stored in the document. Having them stored in an
Element poses a problem when the element is deleted
Well actually both implementations (in the document or in the element) are feasible but the Swing document model conceptually stores the positions in the document.
. When positions are kept inside the document, the updates of these positions can be made when the document is notified of a change in its content. This implies that the elements automatically notify their document (if it exists) of any undergoing change in their content.
The model is now clear: the elements offer facilities for the structural view that are already present in the JDOM document model, plus facilities for the logical view which are:
- Text insertion, change and removal
- Start and end offset in the logical view
- Automatic notification of the document when changes occur
We could also add a facility to get the whole text contained in a specific elements and its descendants.
From an implementation point of view, extending the JDOM
Document class to make it implement the Swing
Document interface poses no difficulties. Many of the functionnalities that have to be implemented are delegated to the new hybrid
Element implementation. The only things the new hybrid document has to take care of are event propagation, position tracking and wrapping up the root node functionnalities.
Element implementation is a little bit trickier as the JDOM
Element and the Swing
Element share a common method prototype with a different return type. This forces to create a wrapper for a JDOM element that presents it as a Swing
Element . Both elements have to be able to reference each other, and a modification to one shall modify the other. This presents no difficulty as the wrapper does not contain any information by only provides acces to the JDOM
Another last problem comes from the JDOM: a JDOM
Element can contain strings that are not mutable objects. This poses a problem as those strings should be elements in the Swing document model. The choosen solution is to replace every String by a custom JDOM
Text subclass that also has a wrapper that presents this element as a valid Swing
Element . As JDOM Text nodes are mutable the wrapper will be able to repercute changes made to the text element it wraps.
The JDOM and Swing document model are not incompatible, though a little bit different. The JDOM model offer a lot of different elements, which the Swing document does not. Supporting all those elements, like comments, processing instructions, and entity references implies subclassing and creating a wrapper, and also making changes to the hybrid
The main differences resides in the fact that the Swing document model offer two conceptual views of the document. The Swing document model being not only focused on structure, but also on content, which is something that the JDOM API misses.
An interesting addition to the implementation is to add TreeModel compliance for the hybrid document and TreeNode compliance for the various hybrid Elements, thus allowing to display everything both in a
TextPane and in a
The definitive advantage of this hybrid model is that you have with a single data structure an XML document, a tree-representable data, and a framework on which you can efficiently build a data editor.