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         */
078        void comment(String text);
079    
080    
081        /**
082         * Adds parsed character content. This will be enclosed in a CDATA block if supported.  When not supported, this is
083         * the same as {@link #write(String)}.
084         *
085         * @param content pre-parsed content
086         */
087        void cdata(String content);
088    
089        /**
090         * Adds a series of attributes and values. Null values are quietly skipped. If a name already has a value, then the
091         * new value is <em>ignored</em>.
092         */
093        void attributes(Object... namesAndValues);
094    
095        /**
096         * Converts the collected markup into an markup stream (according to rules provided by the {@link Document}'s {@link
097         * MarkupModel}). The markup stream is sent to the writer.
098         */
099        void toMarkup(PrintWriter writer);
100    
101        /**
102         * Returns the Document into which this writer creates elements or other nodes.
103         */
104        Document getDocument();
105    
106        /**
107         * Returns the currently active element.
108         */
109        Element getElement();
110    
111        /**
112         * Defines a namespace for the currently active element. The namespace URI will be mapped to the provided namespace
113         * prefix within the Element.
114         *
115         * @param namespace       the namespace URI
116         * @param namespacePrefix the prefix for elements and attributes associated with the namespace    (may be the empty
117         *                        string for the default namespace)
118         * @return the currently active element
119         */
120        Element defineNamespace(String namespace, String namespacePrefix);
121    
122        /**
123         * Starts an element within the given namespace. The correct namespace prefix will be identified and used. Must be
124         * balanced by a call to {@link #end()}.
125         *
126         * @param namespace   URI containing the element
127         * @param elementName name of the element within the namespace
128         * @return the new Element
129         */
130        Element elementNS(String namespace, String elementName);
131    
132        /**
133         * Creates an attribute within the namespace for the current element.
134         *
135         * @param namespace      URI containing the element
136         * @param attributeName  name of the attribute within the namespace
137         * @param attributeValue the value for the attribute
138         * @return the currently active element
139         */
140        Element attributeNS(String namespace, String attributeName, String attributeValue);
141    
142        /**
143         * Adds a markup writer listener that will be notified as elements are started and ended.
144         */
145        void addListener(MarkupWriterListener listener);
146    
147        /**
148         * Removes a previously added listener.
149         */
150        void removeListener(MarkupWriterListener listener);
151    }