KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > xml > writer > XMLWriterSupport


1 /* ========================================================================
2  * JCommon : a free general purpose class library for the Java(tm) platform
3  * ========================================================================
4  *
5  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jcommon/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * ---------------------
28  * XMLWriterSupport.java
29  * ---------------------
30  * (C)opyright 2003-2005, by Thomas Morgner and Contributors.
31  *
32  * Original Author: Thomas Morgner;
33  * Contributor(s): David Gilbert (for Object Refinery Limited);
34  *
35  * $Id: XMLWriterSupport.java,v 1.6 2005/11/08 14:35:52 mungady Exp $
36  *
37  * Changes
38  * -------
39  * 21-Jun-2003 : Initial version (TM);
40  * 26-Nov-2003 : Updated Javadocs (DG);
41  *
42  */

43
44 package org.jfree.xml.writer;
45
46 import java.io.IOException JavaDoc;
47 import java.io.Writer JavaDoc;
48 import java.util.Enumeration JavaDoc;
49 import java.util.Iterator JavaDoc;
50 import java.util.Properties JavaDoc;
51
52 /**
53  * A support class for writing XML files.
54  *
55  * @author Thomas Morgner
56  */

57 public class XMLWriterSupport {
58
59     /** A constant for controlling the indent function. */
60     public static final int OPEN_TAG_INCREASE = 1;
61
62     /** A constant for controlling the indent function. */
63     public static final int CLOSE_TAG_DECREASE = 2;
64
65     /** A constant for controlling the indent function. */
66     public static final int INDENT_ONLY = 3;
67
68     /** A constant for close. */
69     public static final boolean CLOSE = true;
70
71     /** A constant for open. */
72     public static final boolean OPEN = false;
73
74     /** The line separator. */
75     private static String JavaDoc lineSeparator;
76
77     /** A list of safe tags. */
78     private SafeTagList safeTags;
79
80     /** The indent level for that writer. */
81     private int indentLevel;
82
83     /** The indent string. */
84     private String JavaDoc indentString;
85
86     /**
87      * A flag indicating whether to force a linebreak before printing the next
88      * tag.
89      */

90     private boolean newLineOk;
91
92     /**
93      * Default Constructor. The created XMLWriterSupport will not have no safe
94      * tags and starts with an indention level of 0.
95      */

96     public XMLWriterSupport() {
97         this(new SafeTagList(), 0);
98     }
99
100     /**
101      * Creates a new support instance.
102      *
103      * @param safeTags tags that are safe for line breaks.
104      * @param indentLevel the index level.
105      */

106     public XMLWriterSupport(final SafeTagList safeTags, final int indentLevel) {
107         this(safeTags, indentLevel, " ");
108     }
109
110     /**
111      * Creates a new support instance.
112      *
113      * @param safeTags the tags that are safe for line breaks.
114      * @param indentLevel the indent level.
115      * @param indentString the indent string.
116      */

117     public XMLWriterSupport(final SafeTagList safeTags, final int indentLevel,
118             final String JavaDoc indentString) {
119         if (indentString == null) {
120             throw new NullPointerException JavaDoc("IndentString must not be null");
121         }
122
123         this.safeTags = safeTags;
124         this.indentLevel = indentLevel;
125         this.indentString = indentString;
126     }
127
128     /**
129      * Starts a new block by increasing the indent level.
130      *
131      * @throws IOException if an IO error occurs.
132      */

133     public void startBlock() throws IOException JavaDoc {
134         this.indentLevel++;
135         allowLineBreak();
136     }
137
138     /**
139      * Ends the current block by decreasing the indent level.
140      *
141      * @throws IOException if an IO error occurs.
142      */

143     public void endBlock() throws IOException JavaDoc {
144         this.indentLevel--;
145         allowLineBreak();
146     }
147
148     /**
149      * Forces a linebreak on the next call to writeTag or writeCloseTag.
150      *
151      * @throws IOException if an IO error occurs.
152      */

153     public void allowLineBreak() throws IOException JavaDoc {
154         this.newLineOk = true;
155     }
156
157     /**
158      * Returns the line separator.
159      *
160      * @return the line separator.
161      */

162     public static String JavaDoc getLineSeparator() {
163         if (lineSeparator == null) {
164             try {
165                 lineSeparator = System.getProperty("line.separator", "\n");
166             }
167             catch (SecurityException JavaDoc se) {
168                 lineSeparator = "\n";
169             }
170         }
171         return lineSeparator;
172     }
173
174     /**
175      * Writes an opening XML tag that has no attributes.
176      *
177      * @param w the writer.
178      * @param name the tag name.
179      *
180      * @throws java.io.IOException if there is an I/O problem.
181      */

182     public void writeTag(final Writer JavaDoc w, final String JavaDoc name) throws IOException JavaDoc {
183         if (this.newLineOk) {
184             w.write(getLineSeparator());
185         }
186         indent(w, OPEN_TAG_INCREASE);
187
188         w.write("<");
189         w.write(name);
190         w.write(">");
191         if (getSafeTags().isSafeForOpen(name)) {
192             w.write(getLineSeparator());
193         }
194     }
195
196     /**
197      * Writes a closing XML tag.
198      *
199      * @param w the writer.
200      * @param tag the tag name.
201      *
202      * @throws java.io.IOException if there is an I/O problem.
203      */

204     public void writeCloseTag(final Writer JavaDoc w, final String JavaDoc tag)
205             throws IOException JavaDoc {
206         // check whether the tag contains CData - we ma not indent such tags
207
if (this.newLineOk || getSafeTags().isSafeForOpen(tag)) {
208             if (this.newLineOk) {
209                 w.write(getLineSeparator());
210             }
211             indent(w, CLOSE_TAG_DECREASE);
212         }
213         else {
214             decreaseIndent();
215         }
216         w.write("</");
217         w.write(tag);
218         w.write(">");
219         if (getSafeTags().isSafeForClose(tag)) {
220             w.write(getLineSeparator());
221         }
222         this.newLineOk = false;
223     }
224
225     /**
226      * Writes an opening XML tag with an attribute/value pair.
227      *
228      * @param w the writer.
229      * @param name the tag name.
230      * @param attributeName the attribute name.
231      * @param attributeValue the attribute value.
232      * @param close controls whether the tag is closed.
233      *
234      * @throws java.io.IOException if there is an I/O problem.
235      */

236     public void writeTag(final Writer JavaDoc w, final String JavaDoc name,
237             final String JavaDoc attributeName, final String JavaDoc attributeValue,
238             final boolean close) throws IOException JavaDoc {
239         final AttributeList attr = new AttributeList();
240         if (attributeName != null) {
241             attr.setAttribute(attributeName, attributeValue);
242         }
243         writeTag(w, name, attr, close);
244     }
245
246     /**
247      * Writes an opening XML tag along with a list of attribute/value pairs.
248      *
249      * @param w the writer.
250      * @param name the tag name.
251      * @param attributes the attributes.
252      * @param close controls whether the tag is closed.
253      *
254      * @throws java.io.IOException if there is an I/O problem.
255      * @deprecated use the attribute list instead of the properties.
256      */

257     public void writeTag(final Writer JavaDoc w, final String JavaDoc name,
258             final Properties JavaDoc attributes, final boolean close)
259             throws IOException JavaDoc {
260         final AttributeList attList = new AttributeList();
261         final Enumeration JavaDoc keys = attributes.keys();
262         while (keys.hasMoreElements()) {
263             final String JavaDoc key = (String JavaDoc) keys.nextElement();
264             attList.setAttribute(key, attributes.getProperty(key));
265         }
266         writeTag(w, name, attList, close);
267     }
268
269     /**
270      * Writes an opening XML tag along with a list of attribute/value pairs.
271      *
272      * @param w the writer.
273      * @param name the tag name.
274      * @param attributes the attributes.
275      * @param close controls whether the tag is closed.
276      *
277      * @throws java.io.IOException if there is an I/O problem.
278      */

279     public void writeTag(final Writer JavaDoc w, final String JavaDoc name,
280             final AttributeList attributes, final boolean close)
281             throws IOException JavaDoc {
282
283         if (this.newLineOk) {
284             w.write(getLineSeparator());
285             this.newLineOk = false;
286         }
287         indent(w, OPEN_TAG_INCREASE);
288
289         w.write("<");
290         w.write(name);
291         final Iterator JavaDoc keys = attributes.keys();
292         while (keys.hasNext()) {
293             final String JavaDoc key = (String JavaDoc) keys.next();
294             final String JavaDoc value = attributes.getAttribute(key);
295             w.write(" ");
296             w.write(key);
297             w.write("=\"");
298             w.write(normalize(value));
299             w.write("\"");
300         }
301         if (close) {
302             w.write("/>");
303             if (getSafeTags().isSafeForClose(name)) {
304                 w.write(getLineSeparator());
305             }
306             decreaseIndent();
307         }
308         else {
309             w.write(">");
310             if (getSafeTags().isSafeForOpen(name)) {
311                 w.write(getLineSeparator());
312             }
313         }
314     }
315
316     /**
317      * Normalises a string, replacing certain characters with their escape
318      * sequences so that the XML text is not corrupted.
319      *
320      * @param s the string.
321      *
322      * @return the normalised string.
323      */

324     public static String JavaDoc normalize(final String JavaDoc s) {
325         if (s == null) {
326             return "";
327         }
328         final StringBuffer JavaDoc str = new StringBuffer JavaDoc();
329         final int len = s.length();
330
331         for (int i = 0; i < len; i++) {
332             final char ch = s.charAt(i);
333
334             switch (ch) {
335                 case '<':
336                     {
337                         str.append("&lt;");
338                         break;
339                     }
340                 case '>':
341                     {
342                         str.append("&gt;");
343                         break;
344                     }
345                 case '&':
346                     {
347                         str.append("&amp;");
348                         break;
349                     }
350                 case '"':
351                     {
352                         str.append("&quot;");
353                         break;
354                     }
355                 case '\n':
356                     {
357                         if (i > 0) {
358                             final char lastChar = str.charAt(str.length() - 1);
359
360                             if (lastChar != '\r') {
361                                 str.append(getLineSeparator());
362                             }
363                             else {
364                                 str.append('\n');
365                             }
366                         }
367                         else {
368                             str.append(getLineSeparator());
369                         }
370                         break;
371                     }
372                 default :
373                     {
374                         str.append(ch);
375                     }
376             }
377         }
378
379         return (str.toString());
380     }
381
382     /**
383      * Indent the line. Called for proper indenting in various places.
384      *
385      * @param writer the writer which should receive the indentention.
386      * @param increase the current indent level.
387      * @throws java.io.IOException if writing the stream failed.
388      */

389     public void indent(final Writer JavaDoc writer, final int increase)
390             throws IOException JavaDoc {
391         if (increase == CLOSE_TAG_DECREASE) {
392             decreaseIndent();
393         }
394         for (int i = 0; i < this.indentLevel; i++) {
395             writer.write(this.indentString); // 4 spaces, we could also try tab,
396
// but I do not know whether this works
397
// with our XML edit pane
398
}
399         if (increase == OPEN_TAG_INCREASE) {
400             increaseIndent();
401         }
402     }
403
404     /**
405      * Returns the current indent level.
406      *
407      * @return the current indent level.
408      */

409     public int getIndentLevel() {
410         return this.indentLevel;
411     }
412
413     /**
414      * Increases the indention by one level.
415      */

416     protected void increaseIndent() {
417         this.indentLevel++;
418     }
419
420     /**
421      * Decreates the indention by one level.
422      */

423     protected void decreaseIndent() {
424         this.indentLevel--;
425     }
426
427     /**
428      * Returns the list of safe tags.
429      *
430      * @return The list.
431      */

432     public SafeTagList getSafeTags() {
433         return this.safeTags;
434     }
435 }
436
Popular Tags