1 /* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
2 // for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
3
4 package org.codehaus.plexus.util.xml.pull;
5
6 import java.io.IOException;
7 import java.io.OutputStream;
8 import java.io.Writer;
9
10 /**
11 * Define an interface to serialization of XML Infoset. This interface abstracts away if serialized XML is XML 1.0
12 * compatible text or other formats of XML 1.0 serializations (such as binary XML for example with WBXML).
13 * <p>
14 * <b>PLEASE NOTE:</b> This interface will be part of XmlPull 1.2 API. It is included as basis for discussion. It may
15 * change in any way.
16 * <p>
17 * Exceptions that may be thrown are: IOException or runtime exception (more runtime exceptions can be thrown but are
18 * not declared and as such have no semantics defined for this interface):
19 * <ul>
20 * <li><em>IllegalArgumentException</em> - for almost all methods to signal that argument is illegal
21 * <li><em>IllegalStateException</em> - to signal that call has good arguments but is not expected here (violation of
22 * contract) and for features/properties when requesting setting unimplemented feature/property
23 * (UnsupportedOperationException would be better but it is not in MIDP)
24 * </ul>
25 * <p>
26 * <b>NOTE:</b> writing CDSECT, ENTITY_REF, IGNORABLE_WHITESPACE, PROCESSING_INSTRUCTION, COMMENT, and DOCDECL in some
27 * implementations may not be supported (for example when serializing to WBXML). In such case IllegalStateException will
28 * be thrown and it is recommended to use an optional feature to signal that implementation is not supporting this kind
29 * of output.
30 */
31 public interface XmlSerializer {
32
33 /**
34 * Set feature identified by name (recommended to be URI for uniqueness). Some well known optional features are
35 * defined in <a href="http://www.xmlpull.org/v1/doc/features.html">
36 * http://www.xmlpull.org/v1/doc/features.html</a>. If feature is not recognized or can not be set then
37 * IllegalStateException MUST be thrown.
38 * @param name feature name
39 * @param state feature state
40 * @exception IllegalStateException If the feature is not supported or can not be set
41 */
42 void setFeature(String name, boolean state) throws IllegalArgumentException, IllegalStateException;
43
44 /**
45 * Return the current value of the feature with given name.
46 * <p>
47 * <strong>NOTE:</strong> unknown properties are <strong>always</strong> returned as null
48 *
49 * @param name The name of feature to be retrieved.
50 * @return The value of named feature.
51 * @exception IllegalArgumentException if feature string is null
52 */
53 boolean getFeature(String name);
54
55 /**
56 * Set the value of a property. (the property name is recommended to be URI for uniqueness). Some well known
57 * optional properties are defined in <a href="http://www.xmlpull.org/v1/doc/properties.html">
58 * http://www.xmlpull.org/v1/doc/properties.html</a>. If property is not recognized or can not be set then
59 * IllegalStateException MUST be thrown.
60 * @param name property name
61 * @param value property value
62 * @exception IllegalStateException if the property is not supported or can not be set
63 */
64 void setProperty(String name, Object value) throws IllegalArgumentException, IllegalStateException;
65
66 /**
67 * Look up the value of a property. The property name is any fully-qualified URI. I
68 * <p>
69 * <strong>NOTE:</strong> unknown properties are <strong>always</strong> returned as null
70 *
71 * @param name The name of property to be retrieved.
72 * @return The value of named property.
73 */
74 Object getProperty(String name);
75
76 /**
77 * Set to use binary output stream with given encoding.
78 * @param os out
79 * @param encoding encoding
80 * @throws IOException io
81 * @throws IllegalArgumentException if null
82 * @throws IllegalStateException illegal use
83 */
84 void setOutput(OutputStream os, String encoding)
85 throws IOException, IllegalArgumentException, IllegalStateException;
86
87 /**
88 * @param writer Set the output to the given writer.
89 * <p>
90 * <b>WARNING</b> no information about encoding is available!
91 * @throws IOException io
92 * @throws IllegalArgumentException if null
93 * @throws IllegalStateException illegal use
94 */
95 void setOutput(Writer writer) throws IOException, IllegalArgumentException, IllegalStateException;
96
97 /**
98 * Write <?xml declaration with encoding (if encoding not null) and standalone flag (if standalone not null)
99 * This method can only be called just after setOutput.
100 * @param encoding document encoding
101 * @param standalone standalone flag value
102 * @throws IOException io
103 * @throws IllegalArgumentException if null
104 * @throws IllegalStateException illegal use
105 */
106 void startDocument(String encoding, Boolean standalone)
107 throws IOException, IllegalArgumentException, IllegalStateException;
108
109 /**
110 * Finish writing. All unclosed start tags will be closed and output will be flushed. After calling this method no
111 * more output can be serialized until next call to setOutput()
112 * @throws IOException io
113 * @throws IllegalArgumentException if null
114 * @throws IllegalStateException illegal use
115 */
116 void endDocument() throws IOException, IllegalArgumentException, IllegalStateException;
117
118 /**
119 * Binds the given prefix to the given namespace. This call is valid for the next element including child elements.
120 * The prefix and namespace MUST be always declared even if prefix is not used in element (startTag() or
121 * attribute()) - for XML 1.0 it must result in declaring <code>xmlns:prefix='namespace'</code> (or
122 * <code>xmlns:prefix="namespace"</code> depending what character is used to quote attribute value).
123 * <p>
124 * <b>NOTE:</b> this method MUST be called directly before startTag() and if anything but startTag() or setPrefix()
125 * is called next there will be exception.
126 * <p>
127 * <b>NOTE:</b> prefixes "xml" and "xmlns" are already bound and can not be redefined see:
128 * <a href="http://www.w3.org/XML/xml-names-19990114-errata#NE05">Namespaces in XML Errata</a>.
129 * <p>
130 * <b>NOTE:</b> to set default namespace use as prefix empty string.
131 *
132 * @param prefix must be not null (or IllegalArgumentException is thrown)
133 * @param namespace must be not null
134 * @throws IOException io
135 * @throws IllegalArgumentException if null
136 * @throws IllegalStateException illegal use
137 */
138 void setPrefix(String prefix, String namespace) throws IOException, IllegalArgumentException, IllegalStateException;
139
140 /**
141 * @return namespace that corresponds to given prefix If there is no prefix bound to this namespace return null but
142 * if generatePrefix is false then return generated prefix.
143 * <p>
144 * <b>NOTE:</b> if the prefix is empty string "" and default namespace is bound to this prefix then empty string
145 * ("") is returned.
146 * <p>
147 * <b>NOTE:</b> prefixes "xml" and "xmlns" are already bound will have values as defined
148 * <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML specification</a>
149 * @param namespace the namespace
150 * @param generatePrefix to generate the missing prefix
151 * @throws IllegalArgumentException if null
152 */
153 String getPrefix(String namespace, boolean generatePrefix) throws IllegalArgumentException;
154
155 /**
156 * @return the current depth of the element. Outside the root element, the depth is 0. The depth is incremented by 1
157 * when startTag() is called. The depth is decremented after the call to endTag() event was observed.
158 *
159 * <pre>
160 * <!-- outside --> 0
161 * <root> 1
162 * sometext 1
163 * <foobar> 2
164 * </foobar> 2
165 * </root> 1
166 * <!-- outside --> 0
167 * </pre>
168 */
169 int getDepth();
170
171 /**
172 * Returns the namespace URI of the current element as set by startTag().
173 * <p>
174 * <b>NOTE:</b> that means in particular that:
175 * <ul>
176 * <li>if there was startTag("", ...) then getNamespace() returns ""
177 * <li>if there was startTag(null, ...) then getNamespace() returns null
178 * </ul>
179 *
180 * @return namespace set by startTag() that is currently in scope
181 */
182 String getNamespace();
183
184 /**
185 * Returns the name of the current element as set by startTag(). It can only be null before first call to startTag()
186 * or when last endTag() is called to close first startTag().
187 *
188 * @return namespace set by startTag() that is currently in scope
189 */
190 String getName();
191
192 /**
193 * Writes a start tag with the given namespace and name. If there is no prefix defined for the given namespace, a
194 * prefix will be defined automatically. The explicit prefixes for namespaces can be established by calling
195 * setPrefix() immediately before this method. If namespace is null no namespace prefix is printed but just name. If
196 * namespace is empty string then serializer will make sure that default empty namespace is declared (in XML 1.0
197 * xmlns='') or throw IllegalStateException if default namespace is already bound to non-empty string.
198 * @param namespace ns
199 * @param name tag name
200 * @return XmlSerializer
201 * @throws IOException io
202 * @throws IllegalArgumentException if null
203 * @throws IllegalStateException illegal use
204 */
205 XmlSerializer startTag(String namespace, String name)
206 throws IOException, IllegalArgumentException, IllegalStateException;
207
208 /**
209 * Write an attribute. Calls to attribute() MUST follow a call to startTag() immediately. If there is no prefix
210 * defined for the given namespace, a prefix will be defined automatically. If namespace is null or empty string no
211 * namespace prefix is printed but just name.
212 * @param name attribute name
213 * @param value attribute value
214 * @param namespace namespace to use
215 * @return XmlSerializer
216 * @throws IOException io
217 * @throws IllegalArgumentException if null
218 * @throws IllegalStateException illegal use
219 */
220 XmlSerializer attribute(String namespace, String name, String value)
221 throws IOException, IllegalArgumentException, IllegalStateException;
222
223 /**
224 * Write end tag. Repetition of namespace and name is just for avoiding errors.
225 * <b>Background:</b> in kXML endTag had no arguments, and non matching tags were very difficult to find... If
226 * namespace is null no namespace prefix is printed but just name. If namespace is empty string then serializer will
227 * make sure that default empty namespace is declared (in XML 1.0 xmlns='').
228 * @param namespace ns
229 * @param name tag name
230 * @return XmlSerializer
231 * @throws IOException io
232 * @throws IllegalArgumentException if null
233 * @throws IllegalStateException illegal use
234 */
235 XmlSerializer endTag(String namespace, String name)
236 throws IOException, IllegalArgumentException, IllegalStateException;
237
238 // /**
239 // * Writes a start tag with the given namespace and name.
240 // * <br />If there is no prefix defined (prefix == null) for the given namespace,
241 // * a prefix will be defined automatically.
242 // * <br />If explicit prefixes is passed (prefix != null) then it will be used
243 // *and namespace declared if not already declared or
244 // * throw IllegalStateException the same prefix was already set on this
245 // * element (setPrefix()) and was bound to different namespace.
246 // * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
247 // * <br />If namespace is null then no namespace prefix is printed but just name.
248 // * <br />If namespace is empty string then serializer will make sure that
249 // * default empty namespace is declared (in XML 1.0 xmlns='')
250 // * or throw IllegalStateException if default namespace is already bound
251 // * to non-empty string.
252 // */
253 // XmlSerializer startTag (String prefix, String namespace, String name)
254 // throws IOException, IllegalArgumentException, IllegalStateException;
255 //
256 // /**
257 // * Write an attribute. Calls to attribute() MUST follow a call to
258 // * startTag() immediately.
259 // * <br />If there is no prefix defined (prefix == null) for the given namespace,
260 // * a prefix will be defined automatically.
261 // * <br />If explicit prefixes is passed (prefix != null) then it will be used
262 // * and namespace declared if not already declared or
263 // * throw IllegalStateException the same prefix was already set on this
264 // * element (setPrefix()) and was bound to different namespace.
265 // * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
266 // * <br />If namespace is null then no namespace prefix is printed but just name.
267 // * <br />If namespace is empty string then serializer will make sure that
268 // * default empty namespace is declared (in XML 1.0 xmlns='')
269 // * or throw IllegalStateException if default namespace is already bound
270 // * to non-empty string.
271 // */
272 // XmlSerializer attribute (String prefix, String namespace, String name, String value)
273 // throws IOException, IllegalArgumentException, IllegalStateException;
274 //
275 // /**
276 // * Write end tag. Repetition of namespace, prefix, and name is just for avoiding errors.
277 // * <br />If namespace or name arguments are different from corresponding startTag call
278 // * then IllegalArgumentException is thrown, if prefix argument is not null and is different
279 // * from corresponding starTag then IllegalArgumentException is thrown.
280 // * <br />If namespace is null then prefix must be null too or IllegalStateException is thrown.
281 // * <br />If namespace is null then no namespace prefix is printed but just name.
282 // * <br />If namespace is empty string then serializer will make sure that
283 // * default empty namespace is declared (in XML 1.0 xmlns='').
284 // * <p><b>Background:</b> in kXML endTag had no arguments, and non matching tags were
285 // * very difficult to find...</p>
286 // */
287 // ALEK: This is really optional as prefix in end tag MUST correspond to start tag but good for error checking
288 // XmlSerializer endTag (String prefix, String namespace, String name)
289 // throws IOException, IllegalArgumentException, IllegalStateException;
290
291 /**
292 * @param text Writes text, where special XML chars are escaped automatically
293 * @return XmlSerializer
294 * @throws IOException io
295 * @throws IllegalArgumentException if null
296 * @throws IllegalStateException illegal use
297 */
298 XmlSerializer text(String text) throws IOException, IllegalArgumentException, IllegalStateException;
299
300 /**
301 * Writes text, where special XML chars are escaped automatically
302 * @param buf characters
303 * @param len lenght
304 * @param start start
305 * @return XmlSerializer
306 * @throws IOException io
307 * @throws IllegalArgumentException if null
308 * @throws IllegalStateException illegal use
309 */
310 XmlSerializer text(char[] buf, int start, int len)
311 throws IOException, IllegalArgumentException, IllegalStateException;
312
313 void cdsect(String text) throws IOException, IllegalArgumentException, IllegalStateException;
314
315 void entityRef(String text) throws IOException, IllegalArgumentException, IllegalStateException;
316
317 void processingInstruction(String text) throws IOException, IllegalArgumentException, IllegalStateException;
318
319 void comment(String text) throws IOException, IllegalArgumentException, IllegalStateException;
320
321 void docdecl(String text) throws IOException, IllegalArgumentException, IllegalStateException;
322
323 void ignorableWhitespace(String text) throws IOException, IllegalArgumentException, IllegalStateException;
324
325 /**
326 * Write all pending output to the stream. If method startTag() or attribute() was called then start tag is closed
327 * (final >) before flush() is called on underlying output stream.
328 * <p>
329 * <b>NOTE:</b> if there is need to close start tag (so no more attribute() calls are allowed) but without flushing
330 * output call method text() with empty string (text("")).
331 * @throws IOException io
332 */
333 void flush() throws IOException;
334 }