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 }