KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jdon > util > jdom > DataFormatFilter


1 package com.jdon.util.jdom;
2
3 /*--
4
5  Copyright (C) 2000 Brett McLaughlin & Jason Hunter.
6  All rights reserved.
7
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions
10  are met:
11
12  1. Redistributions of source code must retain the above copyright
13     notice, this list of conditions, and the following disclaimer.
14
15  2. Redistributions in binary form must reproduce the above copyright
16     notice, this list of conditions, and the disclaimer that follows
17     these conditions in the documentation and/or other materials
18     provided with the distribution.
19
20  3. The name "JDOM" must not be used to endorse or promote products
21     derived from this software without prior written permission. For
22     written permission, please contact license@jdom.org.
23
24  4. Products derived from this software may not be called "JDOM", nor
25     may "JDOM" appear in their name, without prior written permission
26     from the JDOM Project Management (pm@jdom.org).
27
28  In addition, we request (but do not require) that you include in the
29  end-user documentation provided with the redistribution and/or in the
30  software itself an acknowledgement equivalent to the following:
31      "This product includes software developed by the
32       JDOM Project (http://www.jdom.org/)."
33  Alternatively, the acknowledgment may be graphical using the logos
34  available at http://www.jdom.org/images/logos.
35
36  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
40  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  SUCH DAMAGE.
48
49  This software consists of voluntary contributions made by many
50  individuals on behalf of the JDOM Project and was originally
51  created by Brett McLaughlin <brett@jdom.org> and
52  Jason Hunter <jhunter@jdom.org>. For more information on the
53  JDOM Project, please see <http://www.jdom.org/>.
54
55  */

56
57
58 import java.util.Stack JavaDoc;
59
60 import org.xml.sax.Attributes JavaDoc;
61 import org.xml.sax.SAXException JavaDoc;
62 import org.xml.sax.XMLReader JavaDoc;
63
64
65 /**
66  * Filter for data- or field-oriented XML.
67  *
68  * <i>Code and comments adapted from DataWriter-0.2, written
69  * by David Megginson and released into the public domain,
70  * without warranty.</i>
71  *
72  * <p>This filter adds indentation and newlines to field-oriented
73  * XML without mixed content. All added indentation and newlines
74  * will be passed on down the filter chain.</p>
75  *
76  * <p>In general, all whitespace in an XML document is potentially
77  * significant. There is, however, a large class of XML documents
78  * where information is strictly fielded: each element contains either
79  * character data or other elements, but not both. For this special
80  * case, it is possible for a filter to provide automatic indentation
81  * and newlines. Note that this class will likely not yield appropriate
82  * results for document-oriented XML like XHTML pages, which mix character
83  * data and elements together.</p>
84  *
85  * <p>This filter will automatically place each start tag on a new line,
86  * optionally indented if an indent step is provided (by default, there
87  * is no indentation). If an element contains other elements, the end
88  * tag will also appear on a new line with leading indentation. Consider,
89  * for example, the following code:</p>
90  *
91  * <pre>
92  * DataFormatFilter df = new DataFormatFilter();
93  * df.setContentHandler(new XMLWriter());
94  *
95  * df.setIndentStep(2);
96  * df.startDocument();
97  * df.startElement("Person");
98  * df.dataElement("name", "Jane Smith");
99  * df.dataElement("date-of-birth", "1965-05-23");
100  * df.dataElement("citizenship", "US");
101  * df.endElement("Person");
102  * df.endDocument();
103  * </pre>
104  *
105  * <p>This code will produce the following document:</p>
106  *
107  * <pre>
108  * &lt;?xml version="1.0"?>
109  *
110  * &lt;Person>
111  * &lt;name>Jane Smith&lt;/name>
112  * &lt;date-of-birth>1965-05-23&lt;/date-of-birth>
113  * &lt;citizenship>US&lt;/citizenship>
114  * &lt;/Person>
115  * </pre>
116  *
117  * @see DataUnformatFilter
118  */

119 public class DataFormatFilter extends XMLFilterBase
120 {
121
122
123
124     ////////////////////////////////////////////////////////////////////
125
// Constructors.
126
////////////////////////////////////////////////////////////////////
127

128
129     /**
130      * Create a new filter.
131      */

132     public DataFormatFilter()
133     {
134     }
135
136
137     /**
138      * Create a new filter.
139      *
140      * <p>Use the XMLReader provided as the source of events.</p>
141      *
142      * @param xmlreader The parent in the filter chain.
143      */

144     public DataFormatFilter(XMLReader JavaDoc xmlreader)
145     {
146         super(xmlreader);
147     }
148
149
150     ////////////////////////////////////////////////////////////////////
151
// Accessors and setters.
152
////////////////////////////////////////////////////////////////////
153

154
155     /**
156      * Return the current indent step.
157      *
158      * <p>Return the current indent step: each start tag will be
159      * indented by this number of spaces times the number of
160      * ancestors that the element has.</p>
161      *
162      * @return The number of spaces in each indentation step,
163      * or 0 or less for no indentation.
164      * @see #setIndentStep
165      */

166     public int getIndentStep ()
167     {
168         return indentStep;
169     }
170
171
172     /**
173      * Set the current indent step.
174      *
175      * @param indentStep The new indent step (0 or less for no
176      * indentation).
177      * @see #getIndentStep
178      */

179     public void setIndentStep (int indentStep)
180     {
181         this.indentStep = indentStep;
182     }
183
184
185
186     ////////////////////////////////////////////////////////////////////
187
// Public methods.
188
////////////////////////////////////////////////////////////////////
189

190
191     /**
192      * Reset the filter so that it can be reused.
193      *
194      * <p>This method is especially useful if the filter failed
195      * with an exception the last time through.</p>
196      */

197     public void reset ()
198     {
199         state = SEEN_NOTHING;
200         stateStack = new Stack JavaDoc();
201     }
202
203
204
205     ////////////////////////////////////////////////////////////////////
206
// Methods from org.xml.sax.ContentHandler.
207
////////////////////////////////////////////////////////////////////
208

209
210     /**
211      * Filter a start document event.
212      *
213      * <p>Reset state and pass the event on for further processing.</p>
214      *
215      * @exception org.xml.sax.SAXException If a filter
216      * further down the chain raises an exception.
217      * @see org.xml.sax.ContentHandler#startDocument
218      */

219     public void startDocument ()
220     throws SAXException JavaDoc
221     {
222         reset();
223         super.startDocument();
224     }
225
226
227     /**
228      * Add newline and indentation prior to start tag.
229      *
230      * <p>Each tag will begin on a new line, and will be
231      * indented by the current indent step times the number
232      * of ancestors that the element has.</p>
233      *
234      * <p>The newline and indentation will be passed on down
235      * the filter chain through regular characters events.</p>
236      *
237      * @param uri The element's Namespace URI.
238      * @param localName The element's local name.
239      * @param qName The element's qualified (prefixed) name.
240      * @param atts The element's attribute list.
241      * @exception org.xml.sax.SAXException If a filter
242      * further down the chain raises an exception.
243      * @see org.xml.sax.ContentHandler#startElement
244      */

245     public void startElement (String JavaDoc uri, String JavaDoc localName,
246                               String JavaDoc qName, Attributes JavaDoc atts)
247     throws SAXException JavaDoc
248     {
249         if (!stateStack.empty()) {
250             doNewline();
251             doIndent();
252         }
253         stateStack.push(SEEN_ELEMENT);
254         state = SEEN_NOTHING;
255         super.startElement(uri, localName, qName, atts);
256     }
257
258
259     /**
260      * Add newline and indentation prior to end tag.
261      *
262      * <p>If the element has contained other elements, the tag
263      * will appear indented on a new line; otherwise, it will
264      * appear immediately following whatever came before.</p>
265      *
266      * <p>The newline and indentation will be passed on down
267      * the filter chain through regular characters events.</p>
268      *
269      * @param uri The element's Namespace URI.
270      * @param localName The element's local name.
271      * @param qName The element's qualified (prefixed) name.
272      * @exception org.xml.sax.SAXException If a filter
273      * further down the chain raises an exception.
274      * @see org.xml.sax.ContentHandler#endElement
275      */

276     public void endElement (String JavaDoc uri, String JavaDoc localName, String JavaDoc qName)
277     throws SAXException JavaDoc
278     {
279         boolean seenElement = (state == SEEN_ELEMENT);
280         state = stateStack.pop();
281         if (seenElement) {
282             doNewline();
283             doIndent();
284         }
285         super.endElement(uri, localName, qName);
286     }
287
288
289     /**
290      * Filter a character data event.
291      *
292      * @param ch The characters to write.
293      * @param start The starting position in the array.
294      * @param length The number of characters to use.
295      * @exception org.xml.sax.SAXException If a filter
296      * further down the chain raises an exception.
297      * @see org.xml.sax.ContentHandler#characters
298      */

299     public void characters (char ch[], int start, int length)
300     throws SAXException JavaDoc
301     {
302         state = SEEN_DATA;
303         super.characters(ch, start, length);
304     }
305
306
307
308     ////////////////////////////////////////////////////////////////////
309
// Internal methods.
310
////////////////////////////////////////////////////////////////////
311

312
313     /**
314      * Add newline.
315      *
316      * @exception org.xml.sax.SAXException If a filter
317      * further down the chain raises an exception.
318      */

319     private void doNewline ()
320     throws SAXException JavaDoc
321     {
322         super.characters(NEWLINE, 0, NEWLINE.length);
323     }
324
325
326     /**
327      * Add indentation for the current level.
328      *
329      * @exception org.xml.sax.SAXException If a filter
330      * further down the chain raises an exception.
331      */

332     private void doIndent ()
333     throws SAXException JavaDoc
334     {
335         int n = indentStep * stateStack.size();
336         if (n > 0) {
337             char ch[] = new char[n];
338             for (int i = 0; i < n; i++) {
339                 ch[i] = INDENT_CHAR;
340             }
341             super.characters(ch, 0, n);
342         }
343     }
344
345
346
347
348     ////////////////////////////////////////////////////////////////////
349
// Constants.
350
////////////////////////////////////////////////////////////////////
351

352     private static final Object JavaDoc SEEN_NOTHING = new Object JavaDoc();
353     private static final Object JavaDoc SEEN_ELEMENT = new Object JavaDoc();
354     private static final Object JavaDoc SEEN_DATA = new Object JavaDoc();
355
356     private static final char[] NEWLINE = new char[] {'\n'};
357     private static final char INDENT_CHAR = ' ';
358
359
360     ////////////////////////////////////////////////////////////////////
361
// Internal state.
362
////////////////////////////////////////////////////////////////////
363

364     private Object JavaDoc state = SEEN_NOTHING;
365     private Stack JavaDoc stateStack = new Stack JavaDoc();
366
367     private int indentStep = 0;
368
369 }
370
371 // end of DataFormatFilter.java
372
Popular Tags