Chaining Document Filters
Posted by Rob Camick on October 18, 2009
A previous entry on Text Validation briefly mentions why you should consider using DocumentFilters. A limitation of a DocumentFilter is that you can only add a single filter to the Document. There may be times when you need to filter on multiple conditions. Of course you can always create a new filter and combine the code for multiple filter conditions. However, an easier approach would be to reuse existing filters. That is, it would be nice to be able to chain multiple filters together to act as a single filter.
The basic approach behind chaining would be to invoke the initial filter. Once that filter finishes executing successfully another filter would be invoked. Finally, when the last filter in the chain is invoked, the Document would get updated. Of course, if any filter in the chain fails, the chain would stop and the Document would not be updated.
The ChainedDocumentFilter class allows you to easily do this type of chaining. ChainedDocumentFilter is an abstract class that extends DocumentFilter and overrides each of the three methods to either update the Document or invoke the next filter in the chain. So from your point of view you would simply extend ChainedDocumentFilter instead of DocumentFilter and the filtering logic should work the same. There are a couple of other considerations when extending ChainedDocumentFilter:
- your class should include a constructor for adding the next filter in the chain. Although you can use the setFilter() method this is a nice convenince.
- your code should use the provideErrorFeedback() method to give feedback to the user when the filter fails. The default is to just use Toolkit.beep(), but some LAFs may override this.
The Swing tutorial on Implementing a Document Filter shows how to add the filter to an AbstractDocument. However, I created the installFilter(…) method to allow you to install the filter directly to the specified text component. The filter can be used on any number of text components.
Note, you can reuse an existing filter you may have created, although this filter must be the last filter in the chain.
As a simple example, to get you started, I have included an UpperCaseDocumentFilter. This filter simply converts lower case characters to upper case as the characters are typed or pasted into a text component. To demonstrate the chaining you need to have a second filter. If you don’t have one handy then you can download the DocumentSizeFilter from the Swing tutorial. Assuming you use the DocumentSizeFilter, then the code to chain the filters together would be:
JTextField textField = new JTextField();
DocumentSizeFilter sf = new DocumentSizeFilter(25);
UpperCaseDocumentFilter ucf = new UpperCaseDocumentFilter(sf);
So even though you may be creating a filter for a current stand alone requirement, why not extend ChainedDocumentFilter, instead of DocumentFilter. You never know when you might be required to mix and match filters.