001    // Copyright 2006, 2007, 2008 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.tapestry5;
016    
017    import org.apache.tapestry5.dom.Document;
018    import org.apache.tapestry5.dom.Element;
019    import org.apache.tapestry5.dom.MarkupModel;
020    import org.apache.tapestry5.dom.Raw;
021    
022    import java.io.PrintWriter;
023    
024    /**
025     * An interface used by objects, such as Tapestry components, that need to render themselves as some form of XML markup.
026     * A markup writer maintains the idea of a current element. Attributes are added to the current element, and new text
027     * and elements are placed inside the current element. In this way, the markup writer maintains a facade that XML markup
028     * is generated as a stream, even though the implementation builds a kind of DOM tree. The DOM tree can be also be
029     * manipulated. This solves a number of problems from Tapestry 4 (and earlier) where random access to the DOM was
030     * desired and had to be simulated through complex buffering.
031     */
032    public interface MarkupWriter
033    {
034        /**
035         * Begins a new element as a child of the current element. The new element becomes the current element. The new
036         * Element is returned and can be directly manipulated (possibly at a later date). Optionally, attributes for the
037         * new element can be specified directly.
038         * <p/>
039         *
040         * @param name       the name of the element to create
041         * @param attributes an even number of values, alternating names and values
042         * @return the new DOM Element node
043         * @see #attributes(Object[])
044         */
045        Element element(String name, Object... attributes);
046    
047        /**
048         * Ends the current element. The new current element will be the parent element. Returns the new current element
049         * (which may be null when ending the root element for the document).
050         */
051    
052        Element end();
053    
054        /**
055         * Writes the text as a child of the current element.
056         */
057    
058        void write(String text);
059    
060        /**
061         * Writes a formatted string.
062         */
063        void writef(String format, Object... args);
064    
065        /**
066         * Writes <em>raw</em> text, text with existing markup that should be passed through the client without change. This
067         * can be useful when the markup is read from an external source (a file or a database) and is simply to be
068         * included.
069         *
070         * @param text
071         * @see Raw
072         */
073        void writeRaw(String text);
074    
075        /**
076         * Adds an XML comment. The text should be just the comment content, the comment delimiters will be provided.
077         * Note that, as of Tapestry 5.2., no extra whitespace is added (previous releases added a space around the text).
078         */
079        void comment(String text);
080    
081    
082        /**
083         * Adds parsed character content. This will be enclosed in a CDATA block if supported.  When not supported, this is
084         * the same as {@link #write(String)}.
085         *
086         * @param content pre-parsed content
087         */
088        void cdata(String content);
089    
090        /**
091         * Adds a series of attributes and values. Null values are quietly skipped. If a name already has a value, then the
092         * new value is <em>ignored</em>.
093         */
094        void attributes(Object... namesAndValues);
095    
096        /**
097         * Converts the collected markup into an markup stream (according to rules provided by the {@link Document}'s {@link
098         * MarkupModel}). The markup stream is sent to the writer.
099         */
100        void toMarkup(PrintWriter writer);
101    
102        /**
103         * Returns the Document into which this writer creates elements or other nodes.
104         */
105        Document getDocument();
106    
107        /**
108         * Returns the currently active element.
109         */
110        Element getElement();
111    
112        /**
113         * Defines a namespace for the currently active element. The namespace URI will be mapped to the provided namespace
114         * prefix within the Element.
115         *
116         * @param namespace       the namespace URI
117         * @param namespacePrefix the prefix for elements and attributes associated with the namespace    (may be the empty
118         *                        string for the default namespace)
119         * @return the currently active element
120         */
121        Element defineNamespace(String namespace, String namespacePrefix);
122    
123        /**
124         * Starts an element within the given namespace. The correct namespace prefix will be identified and used. Must be
125         * balanced by a call to {@link #end()}.
126         *
127         * @param namespace   URI containing the element
128         * @param elementName name of the element within the namespace
129         * @return the new Element
130         */
131        Element elementNS(String namespace, String elementName);
132    
133        /**
134         * Creates an attribute within the namespace for the current element.
135         *
136         * @param namespace      URI containing the element
137         * @param attributeName  name of the attribute within the namespace
138         * @param attributeValue the value for the attribute
139         * @return the currently active element
140         */
141        Element attributeNS(String namespace, String attributeName, String attributeValue);
142    
143        /**
144         * Adds a markup writer listener that will be notified as elements are started and ended.
145         */
146        void addListener(MarkupWriterListener listener);
147    
148        /**
149         * Removes a previously added listener.
150         */
151        void removeListener(MarkupWriterListener listener);
152    }