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 }