001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry;
016    
017    import org.apache.tapestry.markup.Attribute;
018    
019    /**
020     * Defines an object that can write markup (XML, HTML, XHTML) style output. A
021     * <code>IMarkupWriter</code> handles translation from unicode to the markup language (escaping
022     * characters such as '&lt;' and '&gt;' to their entity equivalents, '&amp;lt;' and '&amp;gt;') as
023     * well as assisting with nested elements, closing tags, etc.
024     * 
025     * @author Howard Ship, David Solis
026     */
027    
028    public interface IMarkupWriter
029    {
030        /**
031         * Writes an integer attribute into the currently open tag.
032         * 
033         * @throws IllegalStateException
034         *             if there is no open tag.
035         */
036    
037        void attribute(String name, int value);
038    
039        /**
040         * Writes a boolean attribute into the currently open tag.
041         * 
042         * @throws IllegalStateException
043         *             if there is no open tag.
044         * @since 3.0
045         */
046    
047        void attribute(String name, boolean value);
048    
049        /**
050         * Writes an attribute into the most recently opened tag. This must be called after
051         * {@link #begin(String)}and before any other kind of writing (which closes the tag).
052         * <p>
053         * The value may be null.
054         * 
055         * @throws IllegalStateException
056         *             if there is no open tag.
057         */
058    
059        void attribute(String name, String value);
060    
061        /**
062         * Similar to {@link #attribute(String, String)}but no escaping of invalid elements is done for
063         * the value.
064         * 
065         * @throws IllegalStateException
066         *             if there is no open tag.
067         * @since 3.0
068         */
069    
070        void attributeRaw(String name, String value);
071        
072        /**
073         * Appends an integer attribute to the current attribute with a matching 
074         * <code>name</code> key, if one exists. 
075         * 
076         * @throws IllegalStateException
077         *             if there is no open tag.
078         */
079    
080        void appendAttribute(String name, int value);
081    
082        /**
083         * Appends a boolean attribute into the currently open tag.
084         * 
085         * @throws IllegalStateException
086         *             if there is no open tag.
087         * @since 3.0
088         */
089    
090        void appendAttribute(String name, boolean value);
091    
092        /**
093         * Appends an attribute into the most recently opened tag. This must be called after
094         * {@link #begin(String)} and before any other kind of writing (which closes the tag).
095         * <p>
096         * The value may be null.
097         * 
098         * @throws IllegalStateException
099         *             if there is no open tag.
100         */
101    
102        void appendAttribute(String name, String value);
103    
104        /**
105         * Similar to {@link #attribute(String, String)} but no escaping of invalid elements is done for
106         * the value.
107         * 
108         * @throws IllegalStateException
109         *             if there is no open tag.
110         * @since 3.0
111         */
112    
113        void appendAttributeRaw(String name, String value);
114        
115        /**
116         * Checks if the current tag has an attribute keyed off of <code>name</code>.
117         * 
118         * @param name
119         *          The name of the attribute to check for existance of.
120         * @return 
121         *          True if the attribute exists, false otherwise.
122         * @throws IllegalStateException
123         *             If there is no open tag.
124         */
125        boolean hasAttribute(String name);
126        
127        /**
128         * Gets the attribute matching <code>name</code> from the current open
129         * tag, if it exists.
130         * 
131         * @param name
132         *          The attribute to get the value of by name.
133         * @return 
134         *          The attribute value, or null if it doesn't exist.
135         * @throws IllegalStateException
136         *             If there is no open tag.
137         */
138        Attribute getAttribute(String name);
139        
140        /**
141         * Removes the attribute specified with a matching <code>name</code> if 
142         * one exists.
143         * 
144         * @param name
145         *          The attribute to remove.
146         * @return
147         *          The removed attribute, null if one didn't exist.
148         * @throws IllegalStateException
149         *             If there is no open tag.
150         */
151        Attribute removeAttribute(String name);
152        
153        /**
154         * Removes all current attributes on the open tag, if any.
155         * 
156         * @throws IllegalStateException
157         *             If there is no open tag.
158         */
159        void clearAttributes();
160        
161        /**
162         * Closes any existing tag then starts a new element. The new element is pushed onto the active
163         * element stack.
164         */
165    
166        void begin(String name);
167    
168        /**
169         * Starts an element that will not later be matched with an <code>end()</code> call. This is
170         * useful for elements that do not need closing tags.
171         */
172    
173        void beginEmpty(String name);
174    
175        /**
176         * Invokes checkError() on the <code>PrintWriter</code> used to format output.
177         */
178    
179        boolean checkError();
180    
181        /**
182         * Closes this <code>IMarkupWriter</code>. Close tags are written for any active elements.
183         * The <code>PrintWriter</code> is then sent <code>close()</code>. A nested writer will
184         * commit its buffer to its containing writer.
185         */
186    
187        void close();
188    
189        /**
190         * Closes the most recently opened element by writing the '&gt;' that ends it. Once this is
191         * invoked, the <code>attribute()</code> methods may not be used until a new element is opened
192         * with {@link #begin(String)}or or {@link #beginEmpty(String)}.
193         */
194    
195        void closeTag();
196    
197        /**
198         * Writes an XML/HTML comment. Any open tag is first closed. The method takes care of providing
199         * the <code>&lt;!--</code> and <code>--&gt;</code>, and provides a blank line after the
200         * close of the comment.
201         * <p>
202         * <em>Most</em> characters are valid inside a comment, so no check of the contents is made
203         * (much like {@link #printRaw(String)}.
204         */
205    
206        void comment(String value);
207    
208        /**
209         * Ends the element most recently started by {@link #begin(String)}. The name of the tag is
210         * popped off of the active element stack and used to form an HTML close tag.
211         */
212    
213        void end();
214    
215        /**
216         * Ends the most recently started element with the given name. This will also end any other
217         * intermediate elements. This is very useful for easily ending a table or even an entire page.
218         */
219    
220        void end(String name);
221    
222        /**
223         * Forwards <code>flush()</code> to this <code>IMarkupWriter</code>'s
224         * <code>PrintWriter</code>.
225         */
226    
227        void flush();
228    
229        /**
230         * Returns a nested writer, one that accumulates its changes in a buffer. When the nested writer
231         * is closed, it writes its buffer of markup into its containing <code>IMarkupWriter</code>
232         * using {@link #printRaw(String)}.
233         */
234    
235        NestedMarkupWriter getNestedWriter();
236    
237        /**
238         * Version of {@link #print(char[], int, int, boolean)}&nbsp;that assumes filter is
239         * <em>enabled</em>.
240         */
241    
242        void print(char[] data, int offset, int length);
243    
244        /**
245         * The primary <code>print()</code> method, used by most other methods.
246         * <p>
247         * Prints the character array, first closing any open tag. Problematic characters ('&lt;',
248         * '&gt;' and '&amp;') are converted to appropriate entities.
249         * <p>
250         * Does <em>nothing</em> if <code>data</code> is null.
251         * <p>
252         * Closes any open tag.
253         * 
254         * @param data
255         *            contains the characters to print, or null to not print anything
256         * @param offset
257         *            offset into the array to start printing from
258         * @param length
259         *            number of characters to print
260         * @param raw
261         *            if true, filtering is disabled
262         * @since 4.0
263         */
264    
265        void print(char[] data, int offset, int length, boolean raw);
266    
267        /**
268         * Prints a single character, or its equivalent entity.
269         * <p>
270         * Closes any open tag.
271         */
272    
273        void print(char value);
274    
275        /**
276         * Prints an integer.
277         * <p>
278         * Closes any open tag.
279         */
280    
281        void print(int value);
282    
283        /**
284         * As with {@link #print(char[], int, int, boolean)}, but the data to print is defined by the
285         * String. Assumes filtering is <em>enabled</em>.
286         */
287    
288        void print(String value);
289    
290        /**
291         * As with {@link #print(char[], int, int, boolean)}, but the data to print is defined by the
292         * String.
293         */
294    
295        void print(String value, boolean raw);
296    
297        /**
298         * Closes the open tag (if any), then prints a line seperator to the output stream.
299         */
300    
301        void println();
302    
303        /**
304         * Version of {@link #print(char[], int, int, boolean)}that assumes filter is <em>enabled</em>.
305         */
306    
307        void printRaw(char[] buffer, int offset, int length);
308    
309        /**
310         * As with {@link #print(char[], int, int, boolean)}, but the data to print is defined by the
311         * String. Assumes filtering is <em>disabled</em>.
312         */
313    
314        void printRaw(String value);
315    
316        /**
317         * Returns the type of content generated by this response writer, as a MIME type.
318         */
319    
320        String getContentType();
321    }