KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > riotfamily > common > markup > TagWriter


1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1
3  * The contents of this file are subject to the Mozilla Public License Version
4  * 1.1 (the "License"); you may not use this file except in compliance with
5  * the License. You may obtain a copy of the License at
6  * http://www.mozilla.org/MPL/
7  *
8  * Software distributed under the License is distributed on an "AS IS" basis,
9  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10  * for the specific language governing rights and limitations under the
11  * License.
12  *
13  * The Original Code is Riot.
14  *
15  * The Initial Developer of the Original Code is
16  * Neteye GmbH.
17  * Portions created by the Initial Developer are Copyright (C) 2006
18  * the Initial Developer. All Rights Reserved.
19  *
20  * Contributor(s):
21  * Felix Gnass [fgnass at neteye dot de]
22  *
23  * ***** END LICENSE BLOCK ***** */

24 package org.riotfamily.common.markup;
25
26 import java.io.PrintWriter JavaDoc;
27
28 import org.riotfamily.common.util.FormatUtils;
29
30 /**
31  * Utility class to generate markup code. This example ...
32  * <pre>
33  *TagWriter tag = new TagWriter(writer);
34  *tag.start("div").attribute("id", "foo")
35  * .body("Hello ")
36  * .start("strong").body("World")
37  * .closeAll();
38  * </pre>
39  * ... will produce the following code:
40  * <pre>
41  * &lt;div id="foo"&gt;Hello &lt;strong&gt;World&lt;/strong&gt;&lt;/div&gt;
42  * </pre>
43  * <p>
44  * Note that calling <code>start()</code> on an already opened tag will return
45  * a new TagWriter. To create complex nested structures you should better use
46  * a {@link org.riotfamily.common.markup.DocumentWriter DocumentWriter} instead.
47  * </p>
48  */

49 public class TagWriter {
50
51     private static final int STATE_CLOSED = 0;
52
53     private static final int STATE_START = 1;
54
55     private static final int STATE_BODY = 2;
56
57     private static final int STATE_CDATA = 3;
58
59     private boolean empty = false;
60
61     private String JavaDoc tagName;
62
63     private PrintWriter JavaDoc writer;
64
65     private boolean xhtml = true;
66
67     private int state = STATE_CLOSED;
68
69     private TagWriter parent;
70
71     public TagWriter(PrintWriter JavaDoc writer) {
72         this.writer = writer;
73     }
74
75     private TagWriter(TagWriter parent) {
76         this.parent = parent;
77         this.writer = parent.writer;
78         this.xhtml = parent.xhtml;
79     }
80
81     public void setXhtml(boolean xhtml) {
82         this.xhtml = xhtml;
83     }
84
85     public TagWriter start(String JavaDoc tagName) {
86         return start(tagName, false);
87     }
88
89     public TagWriter startEmpty(String JavaDoc tagName) {
90         return start(tagName, true);
91     }
92
93     public TagWriter start(String JavaDoc tagName, boolean empty) {
94         if (state != STATE_CLOSED) {
95             if (state == STATE_START) {
96                 body();
97             }
98             return new TagWriter(this).start(tagName, empty);
99         }
100         else {
101             this.tagName = tagName;
102             this.empty = empty;
103             writer.write('<');
104             writer.write(tagName);
105             state = STATE_START;
106             return this;
107         }
108     }
109
110     public TagWriter attribute(String JavaDoc name) {
111         String JavaDoc value = null;
112         if (xhtml) {
113             value = name;
114         }
115         return attribute(name, value, true);
116     }
117
118     public TagWriter attribute(String JavaDoc name, int value) {
119         if (state != STATE_START) {
120             throw new IllegalStateException JavaDoc("start() must be called first");
121         }
122         writer.write(' ');
123         writer.write(name);
124         writer.write('=');
125         writer.write('"');
126         writer.write(String.valueOf(value));
127         writer.write('"');
128         return this;
129     }
130
131     public TagWriter attribute(String JavaDoc name, boolean present) {
132         String JavaDoc value = present ? name : null;
133         return attribute(name, value, false);
134     }
135
136     public TagWriter attribute(String JavaDoc name, String JavaDoc value) {
137         return attribute(name, value, false);
138     }
139
140     public TagWriter attribute(String JavaDoc name, String JavaDoc value, boolean renderEmpty) {
141         if (state != STATE_START) {
142             throw new IllegalStateException JavaDoc("start() must be called first");
143         }
144         if (value == null && !renderEmpty) {
145             return this;
146         }
147         writer.write(' ');
148         writer.write(name);
149         if (value != null) {
150             writer.write('=');
151             writer.write('"');
152                writer.write(FormatUtils.xmlEscape(value));
153             writer.write('"');
154         }
155         return this;
156     }
157
158     public TagWriter body() {
159         if (state != STATE_START) {
160             throw new IllegalStateException JavaDoc("start() must be called first");
161         }
162         if (empty) {
163             throw new IllegalStateException JavaDoc("Body not allowed for empty tags");
164         }
165         writer.write('>');
166         state = STATE_BODY;
167         return this;
168     }
169
170     public TagWriter body(String JavaDoc body) {
171         return body(body, true);
172     }
173
174     public TagWriter body(String JavaDoc body, boolean escapeHtml) {
175         body();
176         if (body != null) {
177             if (escapeHtml) {
178                 writer.write(FormatUtils.xmlEscape(body));
179             }
180             else {
181                 writer.write(body);
182             }
183         }
184         return this;
185     }
186
187     public TagWriter cData() {
188         if (state != STATE_BODY) {
189             throw new IllegalStateException JavaDoc("body() must be called first");
190         }
191         if (state == STATE_CDATA) {
192             throw new IllegalStateException JavaDoc(
193                     "cData() must not be called within a CDATA section");
194         }
195         writer.write("<![CDATA[\n");
196         state = STATE_CDATA;
197         return this;
198     }
199
200     public TagWriter closeCData() {
201         if (state != STATE_CDATA) {
202             throw new IllegalStateException JavaDoc("cData() must be called first");
203         }
204         writer.write("]]>");
205         state = STATE_BODY;
206         return this;
207     }
208
209     public TagWriter print(String JavaDoc s) {
210         if (state < STATE_BODY) {
211             throw new IllegalStateException JavaDoc("body() must be called first");
212         }
213         writer.print(state == STATE_CDATA ? s : FormatUtils.xmlEscape(s));
214         return this;
215     }
216
217     public TagWriter println(String JavaDoc s) {
218         print(s);
219         writer.println();
220         return this;
221     }
222
223     public TagWriter println() {
224         writer.println();
225         return this;
226     }
227
228     public TagWriter end() {
229         if (state == STATE_CLOSED) {
230             throw new IllegalStateException JavaDoc("Tag already closed");
231         }
232         if (empty) {
233             if (xhtml) {
234                 writer.write('/');
235             }
236             writer.write('>');
237         }
238         else {
239             if (state == STATE_CDATA) {
240                 closeCData();
241             }
242             if (state < STATE_BODY) {
243                 body();
244             }
245             writer.write('<');
246             writer.write('/');
247             writer.write(tagName);
248             writer.write('>');
249         }
250         state = STATE_CLOSED;
251         return parent != null ? parent : this;
252     }
253
254     public void closeAll() {
255         TagWriter writer = this;
256         while (writer != null) {
257             writer.end();
258             writer = writer.parent;
259         }
260     }
261
262 }
Popular Tags