KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tapestry > markup > MarkupWriterImpl


1 // Copyright 2005 The Apache Software Foundation
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15 package org.apache.tapestry.markup;
16
17 import java.io.PrintWriter JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.List JavaDoc;
20
21 import org.apache.hivemind.ApplicationRuntimeException;
22 import org.apache.hivemind.util.Defense;
23 import org.apache.tapestry.IMarkupWriter;
24 import org.apache.tapestry.NestedMarkupWriter;
25
26 /**
27  * Completely revised (for 4.0) implementation of {@link org.apache.tapestry.IMarkupWriter}. No
28  * longer does internal buffering (since the servlet/portlet APIs support that natively) and wraps
29  * around a {@link java.io.PrintWriter} (rather than an {@link java.io.OutputStream}).
30  *
31  * @author Howard M. Lewis Ship
32  * @since 4.0
33  */

34 public class MarkupWriterImpl implements IMarkupWriter
35 {
36     /**
37      * The underlying {@link PrintWriter}that output is sent to.
38      */

39
40     private PrintWriter JavaDoc _writer;
41
42     /**
43      * Filter used to "escape" characters that need any kind of special encoding for the output
44      * content type.
45      */

46
47     private MarkupFilter _filter;
48
49     /**
50      * Indicates whether a tag is open or not. A tag is opened by {@link #begin(String)}or
51      * {@link #beginEmpty(String)}. It stays open while calls to the <code>attribute()</code>
52      * methods are made. It is closed (the '&gt;' is written) when any other method is invoked.
53      */

54
55     private boolean _openTag = false;
56
57     /**
58      * Indicates that the tag was opened with {@link #beginEmpty(String)}, which affects how the
59      * tag is closed (a slash is added to indicate the lack of a body). This is compatible with
60      * HTML, but reflects an XML/XHTML leaning.
61      */

62
63     private boolean _emptyTag = false;
64
65     private String JavaDoc _contentType;
66
67     /**
68      * A Stack of Strings used to track the active tag elements. Elements are active until the
69      * corresponding close tag is written. The {@link #push(String)}method adds elements to the
70      * stack, {@link #pop()}removes them.
71      */

72
73     private List JavaDoc _activeElementStack;
74
75     public MarkupWriterImpl(String JavaDoc contentType, PrintWriter JavaDoc writer, MarkupFilter filter)
76     {
77         Defense.notNull(contentType, "contentType");
78         Defense.notNull(writer, "writer");
79         Defense.notNull(filter, "filter");
80
81         _contentType = contentType;
82         _writer = writer;
83         _filter = filter;
84     }
85
86     public void attribute(String JavaDoc name, int value)
87     {
88         checkTagOpen();
89
90         _writer.print(' ');
91         _writer.print(name);
92         _writer.print("=\"");
93         _writer.print(value);
94         _writer.print('"');
95     }
96
97     public void attribute(String JavaDoc name, boolean value)
98     {
99         checkTagOpen();
100
101         _writer.print(' ');
102         _writer.print(name);
103         _writer.print("=\"");
104         _writer.print(value);
105         _writer.print('"');
106     }
107
108     public void attribute(String JavaDoc name, String JavaDoc value)
109     {
110         attribute(name, value, false);
111     }
112
113     public void attribute(String JavaDoc name, String JavaDoc value, boolean raw)
114     {
115         checkTagOpen();
116
117         _writer.print(' ');
118
119         // Could use a check here that name contains only valid characters
120

121         _writer.print(name);
122         _writer.print("=\"");
123
124         if (value != null)
125         {
126             char[] data = value.toCharArray();
127             maybePrintFiltered(data, 0, data.length, raw, true);
128         }
129
130         _writer.print('"');
131     }
132
133     /**
134      * Prints the value, if non-null. May pass it through the filter, unless raw is true.
135      */

136
137     private void maybePrintFiltered(char[] data, int offset, int length, boolean raw,
138             boolean isAttribute)
139     {
140         if (data == null || length <= 0)
141             return;
142
143         if (raw)
144         {
145             _writer.write(data, offset, length);
146             return;
147         }
148
149         _filter.print(_writer, data, offset, length, isAttribute);
150     }
151
152     public void attributeRaw(String JavaDoc name, String JavaDoc value)
153     {
154         attribute(name, value, true);
155     }
156
157     public void begin(String JavaDoc name)
158     {
159         if (_openTag)
160             closeTag();
161
162         push(name);
163
164         _writer.print('<');
165         _writer.print(name);
166
167         _openTag = true;
168         _emptyTag = false;
169     }
170
171     public void beginEmpty(String JavaDoc name)
172     {
173         if (_openTag)
174             closeTag();
175
176         _writer.print('<');
177         _writer.print(name);
178
179         _openTag = true;
180         _emptyTag = true;
181     }
182
183     public boolean checkError()
184     {
185         return _writer.checkError();
186     }
187
188     public void close()
189     {
190         if (_openTag)
191             closeTag();
192
193         // Close any active elements.
194

195         while (!stackEmpty())
196         {
197             _writer.print("</");
198             _writer.print(pop());
199             _writer.print('>');
200         }
201
202         _writer.close();
203
204         _writer = null;
205         _filter = null;
206         _activeElementStack = null;
207     }
208
209     public void closeTag()
210     {
211         if (_emptyTag)
212             _writer.print('/');
213
214         _writer.print('>');
215
216         _openTag = false;
217         _emptyTag = false;
218     }
219
220     public void comment(String JavaDoc value)
221     {
222         if (_openTag)
223             closeTag();
224
225         _writer.print("<!-- ");
226         _writer.print(value);
227         _writer.println(" -->");
228     }
229
230     public void end()
231     {
232         if (_openTag)
233             closeTag();
234
235         if (stackEmpty())
236             throw new ApplicationRuntimeException(MarkupMessages.endWithEmptyStack());
237
238         _writer.print("</");
239         _writer.print(pop());
240         _writer.print('>');
241     }
242
243     public void end(String JavaDoc name)
244     {
245         if (_openTag)
246             closeTag();
247
248         if (_activeElementStack == null || !_activeElementStack.contains(name))
249             throw new ApplicationRuntimeException(MarkupMessages.elementNotOnStack(
250                     name,
251                     _activeElementStack));
252
253         while (true)
254         {
255             String JavaDoc tagName = pop();
256
257             _writer.print("</");
258             _writer.print(tagName);
259             _writer.print('>');
260
261             if (tagName.equals(name))
262                 break;
263         }
264     }
265
266     public void flush()
267     {
268         _writer.flush();
269     }
270
271     public NestedMarkupWriter getNestedWriter()
272     {
273         return new NestedMarkupWriterImpl(this, _filter);
274     }
275
276     public void print(char[] data, int offset, int length)
277     {
278         print(data, offset, length, false);
279     }
280
281     public void printRaw(char[] buffer, int offset, int length)
282     {
283         print(buffer, offset, length, true);
284     }
285
286     public void print(char[] buffer, int offset, int length, boolean raw)
287     {
288         if (_openTag)
289             closeTag();
290
291         maybePrintFiltered(buffer, offset, length, raw, false);
292     }
293
294     public void print(String JavaDoc value)
295     {
296         print(value, false);
297     }
298
299     public void printRaw(String JavaDoc value)
300     {
301         print(value, true);
302     }
303
304     public void print(String JavaDoc value, boolean raw)
305     {
306         if (value == null || value.length() == 0)
307         {
308             print(null, 0, 0, raw);
309             return;
310         }
311
312         char[] buffer = value.toCharArray();
313
314         print(buffer, 0, buffer.length, raw);
315     }
316
317     public void print(char value)
318     {
319         char[] data = new char[]
320         { value };
321
322         print(data, 0, 1);
323     }
324
325     public void print(int value)
326     {
327         if (_openTag)
328             closeTag();
329
330         _writer.print(value);
331     }
332
333     public void println()
334     {
335         if (_openTag)
336             closeTag();
337
338         _writer.println();
339     }
340
341     public String JavaDoc getContentType()
342     {
343         return _contentType;
344     }
345
346     private void checkTagOpen()
347     {
348         if (!_openTag)
349             throw new IllegalStateException JavaDoc(MarkupMessages.tagNotOpen());
350     }
351
352     private void push(String JavaDoc name)
353     {
354         if (_activeElementStack == null)
355             _activeElementStack = new ArrayList JavaDoc();
356
357         _activeElementStack.add(name);
358     }
359
360     private String JavaDoc pop()
361     {
362         int lastIndex = _activeElementStack.size() - 1;
363
364         return (String JavaDoc) _activeElementStack.remove(lastIndex);
365     }
366
367     private boolean stackEmpty()
368     {
369         return _activeElementStack == null || _activeElementStack.isEmpty();
370     }
371 }
Popular Tags